Skip to content

Commit

Permalink
Merged over timidity from SDL_sound
Browse files Browse the repository at this point in the history
This has changes to make it safe to load MIDI files as sound chunks and adds the ability to seek in MIDI files
Also cherry picked some patches from the original SDL_mixer timidity to fix buffer overruns and so forth.
  • Loading branch information
slouken committed Oct 18, 2017
1 parent 769d53b commit c80b2de
Show file tree
Hide file tree
Showing 35 changed files with 3,815 additions and 5,856 deletions.
1 change: 0 additions & 1 deletion mixer.c
Expand Up @@ -568,7 +568,6 @@ static SDL_AudioSpec *Mix_LoadMusic_RW(Mix_MusicType music_type, SDL_RWops *src,
/* These music interfaces are not safe to use while music is playing */
if (interface->api == MIX_MUSIC_CMD ||
interface->api == MIX_MUSIC_MIKMOD ||
interface->api == MIX_MUSIC_TIMIDITY ||
interface->api == MIX_MUSIC_NATIVEMIDI) {
continue;
}
Expand Down
42 changes: 18 additions & 24 deletions music_timidity.c
Expand Up @@ -28,35 +28,29 @@
#include "timidity/timidity.h"


static int samplesize;

static int TIMIDITY_Open(const SDL_AudioSpec *spec)
{
samplesize = spec->size / spec->samples;
if (Timidity_Init(spec->freq, spec->format, spec->channels, spec->samples) != 0) {
Mix_SetError("%s", Timidity_Error());
return -1;
}
return 0;
return Timidity_Init();
}

static void TIMIDITY_Close(void)
{
Timidity_Close();
Timidity_Exit();
}

void *TIMIDITY_CreateFromRW(SDL_RWops *src, int freesrc)
{
MidiSong *music = Timidity_LoadSong_RW(src, freesrc);
if (!music) {
Mix_SetError("%s", Timidity_Error());
MidiSong *music = Timidity_LoadSong(src, &music_spec);
if (music && freesrc) {
SDL_RWclose(src);
}
return music;
}

static void TIMIDITY_SetVolume(void *context, int volume)
{
Timidity_SetVolume(volume);
MidiSong *music = (MidiSong *)context;
Timidity_SetVolume(music, volume);
}

static int TIMIDITY_Play(void *context)
Expand All @@ -66,21 +60,21 @@ static int TIMIDITY_Play(void *context)
return 0;
}

static SDL_bool TIMIDITY_IsPlaying(void *context)
{
return Timidity_Active() ? SDL_TRUE : SDL_FALSE;
}

static int TIMIDITY_GetAudio(void *context, void *data, int bytes)
{
int samples = (bytes / samplesize);
Timidity_PlaySome(data, samples);
MidiSong *music = (MidiSong *)context;
if (!Timidity_PlaySome(music, data, bytes)) {
/* Nothing consumed, everything left */
return bytes;
}
return 0;
}

static void TIMIDITY_Stop(void *context)
static int TIMIDITY_Seek(void *context, double position)
{
Timidity_Stop();
MidiSong *music = (MidiSong *)context;
Timidity_Seek(music, (Uint32)(position * 1000));
return 0;
}

static void TIMIDITY_Delete(void *context)
Expand All @@ -103,9 +97,9 @@ Mix_MusicInterface Mix_MusicInterface_TIMIDITY =
NULL, /* CreateFromFile */
TIMIDITY_SetVolume,
TIMIDITY_Play,
TIMIDITY_IsPlaying,
NULL, /* IsPlaying */
TIMIDITY_GetAudio,
NULL, /* Seek */
TIMIDITY_Seek,
NULL, /* Pause */
NULL, /* Resume */
NULL, /* Stop */
Expand Down
77 changes: 77 additions & 0 deletions timidity/CHANGES
@@ -0,0 +1,77 @@
This version of TiMidity should contain all the fixes from the
September 25 2003 SDL_mixer CVS snapshot. In addition, I've made some
changes of my own, e.g.:

* All file access is done through SDL_RWops. This means the MIDI
stream no longer has to be a file. (The config file and instruments
still have to be though.)

* Replacing of TiMidity's endian-handling with SDL's.

* Removal of much unused or unnecessary code, such as

+ The "hooks" for putting a user interface onto TiMidity.
+ The antialias filter. It wasn't active, and even at 4 kHz I
couldn't hear any difference when activating it.
+ Removed all traces of LOOKUP_HACK and LOOKUP_INTERPOLATION.
According to the code comments they weren't very good anyway.
("degrades sound quality noticeably"). I also removed the
disclaimer about the "8-bit uLaw to 16-bit PCM and the 13-bit-PCM
to 8-bit uLaw tables" disclaimer, since I believe those were the
tables I removed.
+ Removed LOOKUP_SINE since it was already commented out. I think we
can count on our target audience having math co-processors
nowadays.
+ Removed USE_LDEXP since it wasn't being used and "it doesn't make
much of a difference either way".
+ Removed decompress hack from open_file() since it didn't look very
portable.
+ Removed heaps of unnecessary constants.
+ Removed unused functions.
+ Assume that LINEAR_INTERPOLATION is always used, so remove all
code dealing with it not being so. It's not that I think the
difference in audio quality is that great, but since it wouldn't
compile without code changes I assume no one's used it for quite
some time...
+ Assume PRECALC_LOOPS is always defined. Judging by the comments it
may not make much of a difference either way, so why maintain two
versions of the same code?

* Moving several static globals into the MidiSong struct. This
includes sample rate, formate, etc. which are now all per-song.

* Moved some typedefs (e.g. MidiSong) to timidity.h for easy inclusion
into the MIDI decoder.

* Added free_pathlist().

* Replaced TiMidity's own 8, 16 and 32-bit types with SDL's.

* Made TiMidity look for its configuration file in both /etc and
/usr/local/lib/timidity. (Windows version remains unchanged.)

* Timidity_PlaySome() now takes three arguments. A MidiSong, a decode
buffer and decode buffer size in bytes. (MidiSong is a new argument,
and buffer size used to be in samples.)

In addition, it will return the number of bytes decoded.

* Added Timidity_Exit().

* Removed Timidity_Stop() and Timidity_Active(). Stopping playback
should be handled by SDL_sound, and Timidity_PlaySome() will return
0 when the MIDI stream is finished.

* Modified the ToneBank stuff to allow some data to be shared between
MidiSongs.

* The following files have been removed: controls.c, controls.h,
filter.c, filter.h, sdl_a.c, sdl_c.c

* config.h has been renamed as options.h to avoid confusion with the
automatically generated config.h for SDL_sound.

* Added support for loading DLS format instruments:
Timidity_LoadDLS(), Timidity_FreeDLS(), Timidity_LoadDLSSong()

* Added Timidity_Init_NoConfig()
14 changes: 1 addition & 13 deletions timidity/FAQ
Expand Up @@ -92,19 +92,7 @@ A: Here are some things to try:

- Use a smaller number of simultaneous voices.

- Make sure you compiled with FAST_DECAY and PRECALC_LOOPS enabled
in config.h

- If you don't have hardware to compute sines, recompile with
LOOKUP_SINE enabled in config.h

- Recompile with LOOKUP_HACK enabled in config.h.

- Recompile with LINEAR_INTERPOLATION disabled in config.h.

- Recompile with DANGEROUS_RENICE enabled in config.h, and make
TiMidity setuid root. This will help only if you frequently play
music while other processes are running.
- Make sure you compiled with FAST_DECAY enabled in options.h

- Recompile with an Intel-optimized gcc for a 5-15%
performance increase.
Expand Down
3 changes: 2 additions & 1 deletion timidity/README
@@ -1,4 +1,5 @@
[This version of timidity has been stripped for simplicity in porting to SDL]
[This version of timidity has been stripped for simplicity in porting to SDL,
and then even further for SDL_sound]
---------------------------------*-text-*---------------------------------

From http://www.cgs.fi/~tt/discontinued.html :
Expand Down
37 changes: 37 additions & 0 deletions timidity/TODO
@@ -0,0 +1,37 @@
* I don't like the indentation style at all, but for the most part
I've left it alone.

* Much of the code looks ugly to me.

* The return value from SDL_RWread() is checked inconsistenly.

* Group the members of MidiSong into logical units, i.e. structs?

* The debug messages are probably a bit too noisy. I've removed one
particularly annoying one, but...

Some of them should be turned into error messages instead.

* Can the instrument handling be made more efficient? At the moment
different MidiSongs may separately load the same instrument.

Note that the MidiSong's audio format affects how the instrument is
loaded, so it's not as easy as just letting all MidiSongs share tone
and drum banks.

At the moment they do share the data that is simply read from the
config file, but that's just a quick hack to avoid having to read
the config file every time a MIDI song is loaded.

* Check if any of MidiStruct's members can safely be made into static
globals again.

* TiMidity++ adds a number of undocumented (?) extensions to the
configuration syntax. These are not implemented here. In particular,
the "map" keyword used by the "eawpats".

* The other decoders generally only read as much of the file as is
necessary. Could we do that in this decoder as well? (Currently it
seems to convert the entire file into MIDI events first.)

* Can it be optimized?

0 comments on commit c80b2de

Please sign in to comment.