diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 3cdc83d46..0017e00b2 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,13 @@ April 11, 2008 +- Fixed: Timidity::Channel::mono, rpn, and nrpn were not initialized. In + particular, this meant that every channel was almost certainly in mono mode, + which can sound pretty bad if the song isn't meant to be played that way. +- Added bank numbers to the MIDI precaching for Timidity, since I guess I do + need to care about banks, if even the Duke MIDIs use various banks. +- Fixed: snd_midiprecache only exists in Win32 builds, so gameconfigfile.cpp + shouldn't unconditionally link against it. +- Fixed: pre_resample() was still disabled, and it left two samples at the end + of the new wave data uninitialized. - Moved the xmap table from timidity/tables.cpp to playmidi.cpp. Now I can get rid of timidity/tables.cpp, which conflicts in name with the main Doom tables.cpp. (And interestingly, VC++ automatically renamed the object file, diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index e8ad2b914..0a8914d40 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -71,7 +71,6 @@ EXTERN_CVAR (Color, am_wallcolor) EXTERN_CVAR (Color, am_fdwallcolor) EXTERN_CVAR (Color, am_cdwallcolor) EXTERN_CVAR (Float, spc_amp) -EXTERN_CVAR (Bool, snd_midiprecache) FString WeaponSection; @@ -306,7 +305,11 @@ void FGameConfigFile::DoGlobalSetup () } if (last < 207) { // Now that snd_midiprecache works again, you probably don't want it on. - snd_midiprecache = false; + FBaseCVar *precache = FindCVar ("snd_midiprecache", NULL); + if (precache != NULL) + { + precache->ResetToDefault(); + } } } } diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 202f6ddad..ea84c29df 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -112,7 +112,7 @@ public: virtual bool FakeVolume() = 0; virtual bool Pause(bool paused) = 0; virtual bool NeedThreadedCallback() = 0; - virtual void PrecacheInstruments(const BYTE *instruments, int count); + virtual void PrecacheInstruments(const WORD *instruments, int count); }; // WinMM implementation of a MIDI output device ----------------------------- @@ -138,7 +138,7 @@ public: bool FakeVolume(); bool NeedThreadedCallback(); bool Pause(bool paused); - void PrecacheInstruments(const BYTE *instruments, int count); + void PrecacheInstruments(const WORD *instruments, int count); protected: static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD); @@ -230,7 +230,7 @@ public: bool FakeVolume(); bool Pause(bool paused); bool NeedThreadedCallback(); - void PrecacheInstruments(const BYTE *instruments, int count); + void PrecacheInstruments(const WORD *instruments, int count); protected: static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata); diff --git a/src/sound/music_midi_midiout.cpp b/src/sound/music_midi_midiout.cpp index 612da30ba..95a797192 100644 --- a/src/sound/music_midi_midiout.cpp +++ b/src/sound/music_midi_midiout.cpp @@ -766,14 +766,17 @@ void MIDISong2::SetTempo(int new_tempo) void MIDISong2::Precache() { - int i, j; - // This array keeps track of instruments that are used. The first 128 // entries are for melodic instruments. The second 128 are for // percussion. BYTE found_instruments[256] = { 0, }; + BYTE found_banks[256] = { 0, }; + bool multiple_banks = false; + int i, j; DoRestart(); + found_banks[0] = true; // Bank 0 is always used. + found_banks[128] = true; for (i = 0; i < NumTracks; ++i) { TrackInfo *track = &Tracks[i]; @@ -786,20 +789,20 @@ void MIDISong2::Precache() ev = track->TrackBegin[track->TrackP++]; command = ev & 0xF0; - if (command == MIDI_SYSEX || command == MIDI_SYSEXEND) - { - len = track->ReadVarLen(); - track->TrackP += len; - } - else if (command == MIDI_META) + if (ev == MIDI_META) { track->TrackP++; len = track->ReadVarLen(); track->TrackP += len; } - else if ((command & 0xF0) == 0xF0) + else if (ev == MIDI_SYSEX || ev == MIDI_SYSEXEND) { - track->TrackP += CommonLengths[ev & 0xF]; + len = track->ReadVarLen(); + track->TrackP += len; + } + else if (command == 0xF0) + { + track->TrackP += CommonLengths[ev & 0x0F]; } else { @@ -821,27 +824,62 @@ void MIDISong2::Precache() } if (channel != 9 && command == (MIDI_PRGMCHANGE & 0x70)) { - found_instruments[data1 & 127] = 1; + found_instruments[data1 & 127] = true; + } + else if (channel == 9 && command == (MIDI_PRGMCHANGE & 0x70) && data1 != 0) + { // On a percussion channel, program change also serves as bank select. + multiple_banks = true; + found_banks[data1 | 128] = true; } else if (channel == 9 && command == (MIDI_NOTEON & 0x70) && data2 != 0) { - found_instruments[data1 | 128] = 1; + found_instruments[data1 | 128] = true; + } + else if (command == (MIDI_CTRLCHANGE & 0x70) && data1 == 0 && data2 != 0) + { + multiple_banks = true; + if (channel == 9) + { + found_banks[data2 | 128] = true; + } + else + { + found_banks[data2 & 127] = true; + } } - track->ReadVarLen(); // Skip delay. } + track->ReadVarLen(); // Skip delay. } } DoRestart(); // Now pack everything into a contiguous region for the PrecacheInstruments call(). - for (i = j = 0; i < 256; ++i) + TArray packed; + + for (i = 0; i < 256; ++i) { if (found_instruments[i]) { - found_instruments[j++] = i; + WORD packnum = (i & 127) | ((i & 128) << 7); + if (!multiple_banks) + { + packed.Push(packnum); + } + else + { // In order to avoid having to multiplex tracks in a type 1 file, + // precache every used instrument in every used bank, even if not + // all combinations are actually used. + for (j = 0; j < 128; ++j) + { + if (found_banks[j + (i & 128)]) + { + packed.Push(packnum | (j << 7)); + } + } + } } } - MIDI->PrecacheInstruments(found_instruments, j); + MIDI->PrecacheInstruments(&packed[0], packed.Size()); } //========================================================================== diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp index 2f923fd34..8b9bfa864 100644 --- a/src/sound/music_midistream.cpp +++ b/src/sound/music_midistream.cpp @@ -733,12 +733,13 @@ MIDIDevice::~MIDIDevice() // If the device can benefit from preloading the instruments, it can do so // now. // -// For each entry, bit 7 set indicates that the instrument is percussion and -// the lower 7 bits contain the note number to use on MIDI channel 10, -// otherwise it is melodic and the lower 7 bits are the program number. +// Each entry is packed as follows: +// Bits 0- 6: Instrument number +// Bits 7-13: Bank number +// Bit 14: Select drum set if 1, tone bank if 0 // //========================================================================== -void MIDIDevice::PrecacheInstruments(const BYTE *instruments, int count) +void MIDIDevice::PrecacheInstruments(const WORD *instruments, int count) { } diff --git a/src/sound/music_mus_midiout.cpp b/src/sound/music_mus_midiout.cpp index 03b2fa4ce..6d5960580 100644 --- a/src/sound/music_mus_midiout.cpp +++ b/src/sound/music_mus_midiout.cpp @@ -189,19 +189,20 @@ bool MUSSong2::CheckDone() void MUSSong2::Precache() { - BYTE *work = (BYTE *)alloca(MusHeader->NumInstruments); - const WORD *used = (WORD *)MusHeader + sizeof(MUSHeader) / 2; + WORD *work = (WORD *)alloca(MusHeader->NumInstruments * sizeof(WORD)); + const WORD *used = (WORD *)MusHeader + sizeof(MUSHeader) / sizeof(WORD); int i, j; for (i = j = 0; i < MusHeader->NumInstruments; ++i) { - if (used[i] < 128) + WORD instr = LittleShort(used[i]); + if (instr < 128) { - work[j++] = (BYTE)used[i]; + work[j++] = instr; } else if (used[i] >= 135 && used[i] <= 181) { // Percussions are 100-based, not 128-based, eh? - work[j++] = used[i] - 100 + 128; + work[j++] = instr - 100 + (1 << 14); } } MIDI->PrecacheInstruments(&work[0], j); diff --git a/src/sound/music_timidity_mididevice.cpp b/src/sound/music_timidity_mididevice.cpp index f0afe7b13..98b7a0907 100644 --- a/src/sound/music_timidity_mididevice.cpp +++ b/src/sound/music_timidity_mididevice.cpp @@ -345,17 +345,18 @@ bool TimidityMIDIDevice::Pause(bool paused) // // TimidityMIDIDevice :: PrecacheInstruments // -// For each entry, bit 7 set indicates that the instrument is percussion and -// the lower 7 bits contain the note number to use on MIDI channel 10, -// otherwise it is melodic and the lower 7 bits are the program number. +// Each entry is packed as follows: +// Bits 0- 6: Instrument number +// Bits 7-13: Bank number +// Bit 14: Select drum set if 1, tone bank if 0 // //========================================================================== -void TimidityMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count) +void TimidityMIDIDevice::PrecacheInstruments(const WORD *instruments, int count) { for (int i = 0; i < count; ++i) { - Renderer->MarkInstrument(0, instruments[i] >> 7, instruments[i] & 127); + Renderer->MarkInstrument((instruments[i] >> 7) & 127, instruments[i] >> 14, instruments[i] & 127); } Renderer->load_missing_instruments(); } diff --git a/src/sound/music_win_mididevice.cpp b/src/sound/music_win_mididevice.cpp index aa137a264..d8b02ca53 100644 --- a/src/sound/music_win_mididevice.cpp +++ b/src/sound/music_win_mididevice.cpp @@ -209,9 +209,10 @@ void WinMIDIDevice::Stop() // // WinMIDIDevice :: PrecacheInstruments // -// For each entry, bit 7 set indicates that the instrument is percussion and -// the lower 7 bits contain the note number to use on MIDI channel 10, -// otherwise it is melodic and the lower 7 bits are the program number. +// Each entry is packed as follows: +// Bits 0- 6: Instrument number +// Bits 7-13: Bank number +// Bit 14: Select drum set if 1, tone bank if 0 // // My old GUS PnP needed the instruments to be preloaded, or it would miss // some notes the first time through the song. I doubt any modern @@ -221,7 +222,7 @@ void WinMIDIDevice::Stop() // //========================================================================== -void WinMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count) +void WinMIDIDevice::PrecacheInstruments(const WORD *instruments, int count) { // Setting snd_midiprecache to false disables this precaching, since it // does involve sleeping for more than a miniscule amount of time. @@ -229,14 +230,31 @@ void WinMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count) { return; } - for (int i = 0, chan = 0; i < count; ++i) + BYTE bank[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int i, chan; + + for (i = 0, chan = 0; i < count; ++i) { - if (instruments[i] & 0x80) - { // Percussion + int instr = instruments[i] & 127; + int banknum = (instruments[i] >> 7) & 127; + int percussion = instruments[i] >> 14; + + if (percussion) + { + if (bank[9] != banknum) + { + midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (banknum << 16)); + bank[9] = banknum; + } midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | 9 | ((instruments[i] & 0x7f) << 8) | (1 << 16)); } else { // Melodic + if (bank[chan] != banknum) + { + midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (banknum << 16)); + bank[chan] = banknum; + } midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_PRGMCHANGE | chan | (instruments[i] << 8)); midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | chan | (60 << 8) | (1 << 16)); if (++chan == 9) @@ -258,6 +276,14 @@ void WinMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count) // And now chan is back at 0, ready to start the cycle over. } } + // Make sure all channels are set back to bank 0. + for (i = 0; i < 16; ++i) + { + if (bank[i] != 0) + { + midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (0 << 16)); + } + } } //========================================================================== diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp index 0d1fc9ee5..6eedac7a5 100644 --- a/src/timidity/instrum.cpp +++ b/src/timidity/instrum.cpp @@ -106,20 +106,9 @@ static void free_bank(int dr, int b) } -int convert_envelope_rate_attack(Renderer *song, BYTE rate, BYTE fastness) -{ - int r; - - r = 3 - ((rate>>6) & 0x3); - r *= 3; - r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */ - - /* 15.15 fixed point. */ - return int(((r * 44100) / song->rate) * song->control_ratio) << 10; -} - int convert_envelope_rate(Renderer *song, BYTE rate) { +#if 1 int r; r = 3 - ((rate>>6) & 0x3); @@ -127,8 +116,12 @@ int convert_envelope_rate(Renderer *song, BYTE rate) r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */ /* 15.15 fixed point. */ - return int(((r * 44100) / song->rate) * song->control_ratio) - << ((song->fast_decay) ? 10 : 9); + return int(((r * 44100) / song->rate) * song->control_ratio) << ((song->fast_decay) ? 10 : 9); +#else + double frameadd = (double)(rate & 63) / (double)(1 << (3 * (rate >> 6))); + double realadd = (frameadd * 19293 / song->rate) * (1 << 15) * song->control_ratio; + return (int)realadd; +#endif } int convert_envelope_offset(BYTE offset) @@ -238,11 +231,11 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo if (noluck) { - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name); + cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name); return 0; } - /*song->ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/ + /*cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/ /* Read some headers and do cursory sanity checks. There are loads of magic offsets. This could be rewritten... */ @@ -252,7 +245,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the differences are */ { - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name); + cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name); return 0; } @@ -293,13 +286,13 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */ { - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]); + cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]); return 0; } if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */ { - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]); + cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]); return 0; } @@ -364,7 +357,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo ip->right_sample = NULL; } - song->ctl->cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)", + cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)", (percussion)? " ":"", name, (percussion)? note_to_use : gm_num, bank, (right_samples)? "(2) " : "", @@ -432,7 +425,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo if (1 != fread(&fractions, 1, 1, fp)) { fail: - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i); + cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i); if (stereo_layer == 1) { for (j = 0; j < i; j++) @@ -505,14 +498,14 @@ fail: sp->tremolo_sweep_increment = 0; sp->tremolo_phase_increment = 0; sp->tremolo_depth = 0; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo"); + cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo"); } else { sp->tremolo_sweep_increment = convert_tremolo_sweep(song, tmp[12]); sp->tremolo_phase_increment = convert_tremolo_rate(song, tmp[13]); sp->tremolo_depth = tmp[14]; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, + cmsg(CMSG_INFO, VERB_DEBUG, " * tremolo: sweep %d, phase %d, depth %d", sp->tremolo_sweep_increment, sp->tremolo_phase_increment, sp->tremolo_depth); @@ -523,14 +516,14 @@ fail: sp->vibrato_sweep_increment = 0; sp->vibrato_control_ratio = 0; sp->vibrato_depth = 0; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato"); + cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato"); } else { sp->vibrato_control_ratio = convert_vibrato_rate(song, tmp[16]); sp->vibrato_sweep_increment= convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio); sp->vibrato_depth = tmp[17]; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, + cmsg(CMSG_INFO, VERB_DEBUG, " * vibrato: sweep %d, ctl %d, depth %d", sp->vibrato_sweep_increment, sp->vibrato_control_ratio, sp->vibrato_depth); @@ -571,14 +564,14 @@ fail: if ((strip_loop == 1) && (sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE))) { - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain"); + cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain"); sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE); } if (strip_envelope == 1) { if (sp->modes & MODES_ENVELOPE) - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope"); + cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope"); sp->modes &= ~MODES_ENVELOPE; } else if (strip_envelope != 0) @@ -588,7 +581,7 @@ fail: { /* No loop? Then what's there to sustain? No envelope needed either... */ sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE); - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, + cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope"); } else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100) @@ -596,7 +589,7 @@ fail: /* Envelope rates all maxed out? Envelope end at a high "offset"? That's a weird envelope. Take it out. */ sp->modes &= ~MODES_ENVELOPE; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope"); + cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope"); } else if (!(sp->modes & MODES_SUSTAIN)) { @@ -605,7 +598,7 @@ fail: envelope either... at least the Gravis ones. They're mostly drums. I think. */ sp->modes &= ~MODES_ENVELOPE; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope"); + cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope"); } } @@ -613,8 +606,7 @@ fail: for (j = ATTACK; j < DELAY; j++) { - sp->envelope_rate[j] = - (j < 3) ? convert_envelope_rate_attack(song, tmp[j], 11) : convert_envelope_rate(song, tmp[j]); + sp->envelope_rate[j] = convert_envelope_rate(song, tmp[j]); sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]); } if (sf2flag) @@ -663,7 +655,7 @@ fail: /* The GUS apparently plays reverse loops by reversing the whole sample. We do the same because the GUS does not SUCK. */ - song->ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name); + cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name); reverse_data((sample_t *)sp->data, 0, sp->data_length); sp->data[sp->data_length] = sp->data[sp->data_length - 1]; @@ -699,7 +691,7 @@ fail: maxamp = a; } sp->volume = 1 / maxamp; - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume); + cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume); #else sp->volume = 1; #endif @@ -722,7 +714,7 @@ fail: if (strip_tail == 1) { /* Let's not really, just say we did. */ - song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail"); + cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail"); sp->data_length = sp->loop_end; } } /* end of sample loop */ @@ -839,7 +831,7 @@ static int fill_bank(Renderer *song, int dr, int b) ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]); if (bank == NULL) { - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, + cmsg(CMSG_ERROR, VERB_NORMAL, "Huh. Tried to load instruments in non-existent %s %d", (dr) ? "drumset" : "tone bank", b); return 0; @@ -855,7 +847,7 @@ static int fill_bank(Renderer *song, int dr, int b) } if (bank->tone[i].name.IsEmpty()) { - song->ctl->cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL, + cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL, "No instrument mapped to %s %d, program %d%s", (dr)? "drum set" : "tone bank", b, i, (b!=0) ? "" : " - this instrument will not be heard"); @@ -901,7 +893,7 @@ static int fill_bank(Renderer *song, int dr, int b) bank->tone[i].sf_ix ))) { - song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, + cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't load instrument %s (%s %d, program %d)", bank->tone[i].name, (dr)? "drum set" : "tone bank", b, i); diff --git a/src/timidity/mix.cpp b/src/timidity/mix.cpp index 7e155e049..92a23138b 100644 --- a/src/timidity/mix.cpp +++ b/src/timidity/mix.cpp @@ -105,10 +105,8 @@ static int update_envelope(Voice *v) { v->envelope_volume += v->envelope_increment; /* Why is there no ^^ operator?? */ - if (((v->envelope_increment < 0) && - (v->envelope_volume <= v->envelope_target)) || - ((v->envelope_increment > 0) && - (v->envelope_volume >= v->envelope_target))) + if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) || + ((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target))) { v->envelope_volume = v->envelope_target; if (recompute_envelope(v)) diff --git a/src/timidity/playmidi.cpp b/src/timidity/playmidi.cpp index 41d8c78c6..f622019a6 100644 --- a/src/timidity/playmidi.cpp +++ b/src/timidity/playmidi.cpp @@ -247,6 +247,9 @@ void Renderer::reset_controllers(int c) channel[c].sustain = 0; channel[c].pitchbend = 0x2000; channel[c].pitchfactor = 0; /* to be computed */ + channel[c].mono = 0; + channel[c].rpn = RPN_RESET; + channel[c].nrpn = RPN_RESET; channel[c].reverberation = 0; channel[c].chorusdepth = 0; @@ -880,7 +883,7 @@ void Renderer::start_note(int ch, int this_note, int this_velocity, int i) ip = lp->instrument; if (ip->type == INST_GUS && ip->samples != 1) { - ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, + cmsg(CMSG_WARNING, VERB_VERBOSE, "Strange: percussion instrument with %d samples!", ip->samples); } @@ -1257,7 +1260,7 @@ void Renderer::note_off(int chan, int note, int vel) void Renderer::all_notes_off(int c) { int i = voices; - ctl->cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c); + cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c); while (i--) { if (voice[i].status == VOICE_ON && voice[i].channel == c) diff --git a/src/timidity/resample.cpp b/src/timidity/resample.cpp index 9c9b72d6a..13180da93 100644 --- a/src/timidity/resample.cpp +++ b/src/timidity/resample.cpp @@ -553,8 +553,8 @@ void pre_resample(Renderer *song, Sample *sp) { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; -return; - song->ctl->cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)", + + cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)", sp->note_to_use, note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12); @@ -565,9 +565,9 @@ return; if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE) return; - dest = newdata = (sample_t *)safe_malloc(newlen >> (FRACTION_BITS - 2)); + count = newlen >> FRACTION_BITS; + dest = newdata = (sample_t *)safe_malloc(count * sizeof(float)); - count = (newlen >> FRACTION_BITS) - 1; ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count; if (--count) diff --git a/src/timidity/timidity.cpp b/src/timidity/timidity.cpp index 4c744339c..51d6c1ebc 100644 --- a/src/timidity/timidity.cpp +++ b/src/timidity/timidity.cpp @@ -404,7 +404,6 @@ int LoadConfig() Renderer::Renderer(float sample_rate) { - ctl = new ControlMode; rate = sample_rate; patches = NULL; default_instrument = NULL; @@ -420,7 +419,7 @@ Renderer::Renderer(float sample_rate) if (def_instr_name.IsNotEmpty()) set_default_instrument(def_instr_name); - voices = DEFAULT_VOICES; + voices = MAX_VOICES;//DEFAULT_VOICES; memset(voice, 0, sizeof(voice)); memset(drumvolume, 0, sizeof(drumvolume)); memset(drumpanpot, 0, sizeof(drumpanpot)); @@ -502,12 +501,25 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr) } } -ControlMode::~ControlMode() -{ -} +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif -void ControlMode::cmsg(int type, int verbosity_level, const char *fmt, ...) +void cmsg(int type, int verbosity_level, const char *fmt, ...) { +#ifdef _WIN32 + char buf[1024]; + va_list args; + + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + size_t l = strlen(buf); + buf[l] = '\n'; + buf[l+1] = '\0'; + OutputDebugString(buf); +#endif } } diff --git a/src/timidity/timidity.h b/src/timidity/timidity.h index 331d94096..2a18aab66 100644 --- a/src/timidity/timidity.h +++ b/src/timidity/timidity.h @@ -205,11 +205,7 @@ controls.h #define VERB_DEBUG 3 #define VERB_DEBUG_SILLY 4 -struct ControlMode -{ - virtual ~ControlMode(); - void cmsg(int type, int verbosity_level, const char *fmt, ...); -}; +void cmsg(int type, int verbosity_level, const char *fmt, ...); /* @@ -522,7 +518,6 @@ extern ToneBank *drumset[MAXBANK]; struct Renderer { - ControlMode *ctl; float rate; DLS_Data *patches; InstrumentLayer *default_instrument;