From 9450db3cecc6f7991dde6d62a07163fc3b225bce Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 16 Apr 2008 05:41:03 +0000 Subject: [PATCH] parameters. These seem to be used primarily to restrict percussion instruments to specific notes. - Changed note velocity to not use the volume curve in recompute_amp(), since this sounds closer to TiMidity++, although I don't believe it's correct MIDI behavior. Also changed expression so that it scales the channel volume before going through the curve. - Reworked load_instrument to be less opaque. - Went through the TiMidity code and removed pretty much all of the SDL_mixer extensions. The only exception would be kill_others(), which I reworked into a kill_key_group() function, which should be useful for DLS instruments in the future. SVN r918 (trunk) --- docs/rh-log.txt | 14 + src/timidity/instrum.cpp | 917 ++++++++++----------------- src/timidity/instrum_dls.cpp | 66 +- src/timidity/mix.cpp | 36 +- src/timidity/playmidi.cpp | 1145 +++------------------------------- src/timidity/resample.cpp | 41 +- src/timidity/timidity.cpp | 54 +- src/timidity/timidity.h | 475 +++++++------- 8 files changed, 789 insertions(+), 1959 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index d4c0ebe68..0e0e49d5a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,17 @@ +April 15, 2008 +- Added support for the GUS patch format's scale_frequency and scale_factor + parameters. These seem to be used primarily to restrict percussion + instruments to specific notes. +- Changed note velocity to not use the volume curve in recompute_amp(), since + this sounds closer to TiMidity++, although I don't believe it's correct + MIDI behavior. Also changed expression so that it scales the channel volume + before going through the curve. +- Reworked load_instrument to be less opaque. +- Went through the TiMidity code and removed pretty much all of the SDL_mixer + extensions. The only exception would be kill_others(), which I reworked + into a kill_key_group() function, which should be useful for DLS + instruments in the future. + April 15, 2008 (Changes by Graf Zahl) - Added translation support to multipatch textures. Not tested yet! - Added Martin Howe's morph weapon update. diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp index ee5fdf868..247ce646a 100644 --- a/src/timidity/instrum.cpp +++ b/src/timidity/instrum.cpp @@ -35,74 +35,48 @@ namespace Timidity { -extern InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument); +extern Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument); -/* Some functions get aggravated if not even the standard banks are -available. */ -ToneBank standard_tonebank, standard_drumset; - -/* This is only used for tracks that don't specify a program */ -int default_program = DEFAULT_PROGRAM; extern int openmode; +Instrument::Instrument() +: type(INST_GUS), samples(0), sample(NULL) +{ +} -static void free_instrument(Instrument *ip) +Instrument::~Instrument() { Sample *sp; int i; - if (ip == NULL) - { - return; - } - for (i = 0, sp = &(ip->sample[0]); i < ip->samples; i++, sp++) + + for (i = samples, sp = &(sample[0]); i != 0; i--, sp++) { if (sp->data != NULL) { free(sp->data); } } - for (i = 0, sp = &(ip->right_sample[0]); i < ip->right_samples; i++) - { - if (sp->data != NULL) - { - free(sp->data); - } - } - free(ip->sample); - if (ip->right_sample != NULL) - { - free(ip->right_sample); - } - free(ip); + free(sample); } - -static void free_layer(InstrumentLayer *lp) +ToneBank::ToneBank() { - InstrumentLayer *next; - - for (; lp; lp = next) + tone = new ToneBankElement[128];; + for (int i = 0; i < MAXPROG; ++i) { - next = lp->next; - free_instrument(lp->instrument); - free(lp); + instrument[i] = 0; } } -static void free_bank(int dr, int b) +ToneBank::~ToneBank() { - int i; - ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]); - for (i = 0; i < MAXPROG; i++) + delete[] tone; + for (int i = 0; i < MAXPROG; i++) { - if (bank->tone[i].layer != NULL) + if (instrument[i] != NULL && instrument[i] != MAGIC_LOAD_INSTRUMENT) { - /* Not that this could ever happen, of course */ - if (bank->tone[i].layer != MAGIC_LOAD_INSTRUMENT) - { - free_layer(bank->tone[i].layer); - bank->tone[i].layer = NULL; - } + delete instrument[i]; + instrument[i] = NULL; } } } @@ -110,7 +84,6 @@ static void free_bank(int dr, int b) int convert_envelope_rate(Renderer *song, BYTE rate) { -#if 1 int r; r = 3 - ((rate>>6) & 0x3); @@ -118,12 +91,7 @@ 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); -#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 + return int(((r * 44100) / song->rate) * song->control_ratio) << 9; } int convert_envelope_offset(BYTE offset) @@ -137,7 +105,7 @@ int convert_envelope_offset(BYTE offset) int convert_tremolo_sweep(Renderer *song, BYTE sweep) { - if (!sweep) + if (sweep == 0) return 0; return @@ -146,7 +114,7 @@ int convert_tremolo_sweep(Renderer *song, BYTE sweep) int convert_vibrato_sweep(Renderer *song, BYTE sweep, int vib_control_ratio) { - if (!sweep) + if (sweep == 0) return 0; return @@ -186,30 +154,29 @@ static void reverse_data(sample_t *sp, int ls, int le) } /* -If panning or note_to_use != -1, it will be used for all samples, -instead of the sample-specific values in the instrument file. + If panning or note_to_use != -1, it will be used for all samples, + instead of the sample-specific values in the instrument file. -For note_to_use, any value <0 or >127 will be forced to 0. + For note_to_use, any value <0 or >127 will be forced to 0. -For other parameters, 1 means yes, 0 means no, other values are -undefined. + For other parameters, 1 means yes, 0 means no, other values are + undefined. -TODO: do reverse loops right */ -static InstrumentLayer *load_instrument(Renderer *song, const char *name, int font_type, int percussion, - int panning, int amp, int cfg_tuning, int note_to_use, - int strip_loop, int strip_envelope, - int strip_tail, int bank, int gm_num, int sf_ix) + TODO: do reverse loops right */ +static Instrument *load_instrument(Renderer *song, const char *name, int percussion, + int panning, int amp, int note_to_use, + int strip_loop, int strip_envelope, + int strip_tail) { - InstrumentLayer *lp, *lastlp, *headlp; Instrument *ip; + Sample *sp; FileReader *fp; - BYTE tmp[239]; - int i,j; + GF1PatchHeader header; + GF1InstrumentData idata; + GF1LayerData layer_data; + GF1PatchData patch_data; + int i, j; bool noluck = false; - bool sf2flag = false; - int right_samples = 0; - int stereo_channels = 1, stereo_layer; - int vlayer_list[19][4], vlayer, vlayer_count; if (!name) return 0; @@ -233,518 +200,302 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo if (noluck) { - cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name); + cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.\n", name); return 0; } - /*cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/ + cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s\n", name); - /* Read some headers and do cursory sanity checks. There are loads - of magic offsets. This could be rewritten... */ + /* Read some headers and do cursory sanity checks. */ - if ((239 != fp->Read(tmp, 239)) || - (memcmp(tmp, "GF1PATCH110\0ID#000002", 22) && - memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the - differences are */ + if (sizeof(header) != fp->Read(&header, sizeof(header))) { - cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name); +failread: + cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Error reading instrument.\n", name); + delete fp; + return 0; + } + if (strncmp(header.Header, GF1_HEADER_TEXT, HEADER_SIZE - 4) != 0) + { + cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not an instrument.\n", name); + delete fp; + return 0; + } + if (strcmp(header.Header + 8, "110") < 0) + { + cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Is an old and unsupported patch version.\n", name); + delete fp; + return 0; + } + if (sizeof(idata) != fp->Read(&idata, sizeof(idata))) + { + goto failread; + } + + header.WaveForms = LittleShort(header.WaveForms); + header.MasterVolume = LittleShort(header.MasterVolume); + header.DataSize = LittleLong(header.DataSize); + idata.Instrument = LittleShort(idata.Instrument); + + if (header.Instruments != 1 && header.Instruments != 0) /* instruments. To some patch makers, 0 means 1 */ + { + cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments.\n", header.Instruments); delete fp; return 0; } - /* patch layout: - * bytes: info: starts at offset: - * 12 header (see above) 0 - * 10 Gravis ID 12 - * 60 description 22 - * 1 instruments 82 - * 1 voices 83 - * 1 channels 84 - * 2 number of waveforms 85 - * 2 master volume 87 - * 4 datasize 89 - * 36 reserved, but now: 93 - * 7 "SF2EXT\0" id 93 - * 1 right samples 100 - * 28 reserved 101 - * 2 instrument number 129 - * 16 instrument name 131 - * 4 instrument size 147 - * 1 number of layers 151 - * 40 reserved 152 - * 1 layer duplicate 192 - * 1 layer number 193 - * 4 layer size 194 - * 1 number of samples 198 - * 40 reserved 199 - * 239 - * THEN, for each sample, see below - */ - - vlayer_count = 0; // Silence, GCC - - if (!memcmp(tmp + 93, "SF2EXT", 6)) + if (idata.Layers != 1 && idata.Layers != 0) /* layers. What's a layer? */ { - sf2flag = true; - vlayer_count = tmp[152]; - } - - if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */ - { - cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]); + cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers.\n", idata.Layers); delete fp; return 0; } - if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */ + if (sizeof(layer_data) != fp->Read(&layer_data, sizeof(layer_data))) { - cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]); + goto failread; + } + + if (layer_data.Samples == 0) + { + cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument has 0 samples.\n"); delete fp; return 0; } - - if (sf2flag && vlayer_count > 0) + ip = new Instrument; + ip->samples = layer_data.Samples; + ip->sample = (Sample *)safe_malloc(sizeof(Sample) * layer_data.Samples); + memset(ip->sample, 0, sizeof(Sample) * layer_data.Samples); + ip->type = INST_GUS; + for (i = 0; i < layer_data.Samples; ++i) { - for (i = 0; i < 9; i++) - for (j = 0; j < 4; j++) - vlayer_list[i][j] = tmp[153+i*4+j]; - for (i = 9; i < 19; i++) - for (j = 0; j < 4; j++) - vlayer_list[i][j] = tmp[199+(i-9)*4+j]; - } - else - { - for (i = 0; i < 19; i++) - for (j = 0; j < 4; j++) - vlayer_list[i][j] = 0; - vlayer_list[0][0] = 0; - vlayer_list[0][1] = 127; - vlayer_list[0][2] = tmp[198]; - vlayer_list[0][3] = 0; - vlayer_count = 1; - } - - lastlp = NULL; - headlp = NULL; // Silence, GCC - - for (vlayer = 0; vlayer < vlayer_count; vlayer++) - { - lp = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer)); - lp->lo = vlayer_list[vlayer][0]; - lp->hi = vlayer_list[vlayer][1]; - ip = (Instrument *)safe_malloc(sizeof(Instrument)); - lp->instrument = ip; - lp->next = 0; - - if (lastlp != NULL) + if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data))) { - lastlp->next = lp; - } - else - { - headlp = lp; - } - - lastlp = lp; - - ip->type = sf2flag ? INST_SF2 : INST_GUS; - ip->samples = vlayer_list[vlayer][2]; - ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples); - ip->left_samples = ip->samples; - ip->left_sample = ip->sample; - right_samples = vlayer_list[vlayer][3]; - ip->right_samples = right_samples; - if (right_samples) - { - ip->right_sample = (Sample *)safe_malloc(sizeof(Sample) * right_samples); - stereo_channels = 2; - } - else - { - ip->right_sample = NULL; - } - - 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) " : "", - lp->lo, lp->hi, vlayer+1, vlayer_count); - - for (stereo_layer = 0; stereo_layer < stereo_channels; stereo_layer++) - { - int sample_count; - - if (stereo_layer == 0) - { - sample_count = ip->left_samples; - } - else if (stereo_layer == 1) - { - sample_count = ip->right_samples; - } - else - { - sample_count = 0; - } - - for (i = 0; i < sample_count; i++) - { - BYTE fractions; - int tmplong; - WORD tmpshort; - WORD sample_volume; - BYTE tmpchar; - Sample *sp; - BYTE sf2delay; - -#define READ_CHAR(thing) \ - if (1 != fp->Read(&tmpchar,1)) goto fail; \ - thing = tmpchar; -#define READ_SHORT(thing) \ - if (2 != fp->Read(&tmpshort, 2)) goto fail; \ - thing = LittleShort(tmpshort); -#define READ_LONG(thing) \ - if (4 != fp->Read(&tmplong, 4)) goto fail; \ - thing = LittleLong(tmplong); - - /* - * 7 sample name - * 1 fractions - * 4 length - * 4 loop start - * 4 loop end - * 2 sample rate - * 4 low frequency - * 4 high frequency - * 4 root frequency - * 2 finetune - * 1 panning - * 6 envelope rates | - * 6 envelope offsets | 18 bytes - * 3 tremolo sweep, rate, depth | - * 3 vibrato sweep, rate, depth | - * 1 sample mode - * 2 scale frequency - * 2 scale factor | from 0 to 2048 or 0 to 2 - * 2 sample volume (??) - * 34 reserved - * Now: 1 delay - * 33 reserved - */ - fp->Seek(7, SEEK_CUR); - - if (1 != fp->Read(&fractions, 1)) - { fail: - cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i); - if (stereo_layer == 1) - { - for (j = 0; j < i; j++) - { - free(ip->right_sample[j].data); - } - free(ip->right_sample); - i = ip->left_samples; - } - for (j = 0; j < i; j++) - { - free(ip->left_sample[j].data); - } - free(ip->left_sample); - free(ip); - free(lp); - delete fp; - return 0; - } + cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d.\n", i); + delete ip; + delete fp; + return 0; + } - if (stereo_layer == 0) - { - sp = &(ip->left_sample[i]); - } - else if (stereo_layer == 1) - { - sp = &(ip->right_sample[i]); - } - else - { - assert(0); - sp = NULL; - } + sp = &(ip->sample[i]); - READ_LONG(sp->data_length); - READ_LONG(sp->loop_start); - READ_LONG(sp->loop_end); - READ_SHORT(sp->sample_rate); - READ_LONG(sp->low_freq); - READ_LONG(sp->high_freq); - READ_LONG(sp->root_freq); - fp->Seek(2, SEEK_CUR); /* Unused by GUS: Why have a "root frequency" and then "tuning"?? */ - sp->low_vel = 0; - sp->high_vel = 127; + sp->data_length = LittleLong(patch_data.WaveSize); + sp->loop_start = LittleLong(patch_data.StartLoop); + sp->loop_end = LittleLong(patch_data.EndLoop); + sp->sample_rate = LittleShort(patch_data.SampleRate); + sp->low_freq = LittleLong(patch_data.LowFrequency); + sp->high_freq = LittleLong(patch_data.HighFrequency); + sp->root_freq = LittleLong(patch_data.RootFrequency); + sp->high_vel = 127; - READ_CHAR(tmp[0]); + if (panning == -1) + { + sp->panning = patch_data.Balance & 0x0F; + sp->panning = (sp->panning << 3) | (sp->panning >> 1); + } + else + { + sp->panning = panning & 0x7f; + } + sp->panning |= sp->panning << 7; - if (panning == -1) - sp->panning = (tmp[0] * 8 + 4) & 0x7f; - else - sp->panning = (BYTE)(panning & 0x7F); - sp->panning |= sp->panning << 7; + /* tremolo */ + if (patch_data.TremoloRate == 0 || patch_data.TremoloDepth == 0) + { + sp->tremolo_sweep_increment = 0; + sp->tremolo_phase_increment = 0; + sp->tremolo_depth = 0; + cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo\n"); + } + else + { + sp->tremolo_sweep_increment = convert_tremolo_sweep(song, patch_data.TremoloSweep); + sp->tremolo_phase_increment = convert_tremolo_rate(song, patch_data.TremoloRate); + sp->tremolo_depth = patch_data.TremoloDepth; + cmsg(CMSG_INFO, VERB_DEBUG, " * tremolo: sweep %d, phase %d, depth %d\n", + sp->tremolo_sweep_increment, sp->tremolo_phase_increment, sp->tremolo_depth); + } - sp->resonance = 0; - sp->cutoff_freq = 0; - sp->reverberation = 0; - sp->chorusdepth = 0; - sp->exclusiveClass = 0; - sp->keyToModEnvHold = 0; - sp->keyToModEnvDecay = 0; - sp->keyToVolEnvHold = 0; - sp->keyToVolEnvDecay = 0; + /* vibrato */ + if (patch_data.VibratoRate == 0 || patch_data.VibratoDepth == 0) + { + sp->tremolo_sweep_increment = 0; + sp->vibrato_control_ratio = 0; + sp->vibrato_depth = 0; + cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato\n"); + } + else + { + sp->vibrato_control_ratio = convert_vibrato_rate(song, patch_data.VibratoRate); + sp->tremolo_sweep_increment = convert_vibrato_sweep(song, patch_data.VibratoSweep, sp->vibrato_control_ratio); + sp->vibrato_depth = patch_data.VibratoDepth; + cmsg(CMSG_INFO, VERB_DEBUG, " * vibrato: sweep %d, ctl %d, depth %d\n", + sp->vibrato_sweep_increment, sp->vibrato_control_ratio, sp->vibrato_depth); + } - if (cfg_tuning) - { - double tune_factor = (double)(cfg_tuning) / 1200.0; - tune_factor = pow(2.0, tune_factor); - sp->root_freq = (uint32)( tune_factor * (double)sp->root_freq ); - } + sp->modes = patch_data.Modes; - /* envelope, tremolo, and vibrato */ - if (18 != fp->Read(tmp, 18)) goto fail; + /* Mark this as a fixed-pitch instrument if such a deed is desired. */ + if (note_to_use != -1) + { + sp->scale_note = note_to_use; + sp->scale_factor = 0; + } + else + { + sp->scale_note = LittleShort(patch_data.ScaleFrequency); + sp->scale_factor = LittleShort(patch_data.ScaleFactor); + if (sp->scale_factor != 1024) + { + cmsg(CMSG_INFO, VERB_DEBUG, " * Scale: note %d, factor %d\n", + sp->scale_note, sp->scale_factor); + } + } - if (!tmp[13] || !tmp[14]) - { - sp->tremolo_sweep_increment = 0; - sp->tremolo_phase_increment = 0; - sp->tremolo_depth = 0; - 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]; - cmsg(CMSG_INFO, VERB_DEBUG, - " * tremolo: sweep %d, phase %d, depth %d", - sp->tremolo_sweep_increment, sp->tremolo_phase_increment, - sp->tremolo_depth); - } + /* seashore.pat in the Midia patch set has no Sustain. I don't + understand why, and fixing it by adding the Sustain flag to + all looped patches probably breaks something else. We do it + anyway. */ - if (!tmp[16] || !tmp[17]) - { - sp->vibrato_sweep_increment = 0; - sp->vibrato_control_ratio = 0; - sp->vibrato_depth = 0; - 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]; - cmsg(CMSG_INFO, VERB_DEBUG, - " * vibrato: sweep %d, ctl %d, depth %d", - sp->vibrato_sweep_increment, sp->vibrato_control_ratio, - sp->vibrato_depth); + if (sp->modes & PATCH_LOOPEN) + { + sp->modes |= PATCH_SUSTAIN; + } - } + /* Strip any loops and envelopes we're permitted to */ + if ((strip_loop == 1) && + (sp->modes & (PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD))) + { + cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain\n"); + sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD); + } - READ_CHAR(sp->modes); - READ_SHORT(sp->freq_center); - READ_SHORT(sp->freq_scale); + if (strip_envelope == 1) + { + if (sp->modes & PATCH_NO_SRELEASE) + { + cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope\n"); + } + sp->modes &= ~PATCH_NO_SRELEASE; + } + else if (strip_envelope != 0) + { + /* Have to make a guess. */ + if (!(sp->modes & (PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD))) + { + /* No loop? Then what's there to sustain? No envelope needed either... */ + sp->modes &= ~(PATCH_SUSTAIN | PATCH_NO_SRELEASE); + cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope\n"); + } + else if (memcmp(patch_data.EnvelopeRate, "??????", 6) == 0 || patch_data.EnvelopeOffset[RELEASEC] >= 100) + { + /* Envelope rates all maxed out? Envelope end at a high "offset"? + That's a weird envelope. Take it out. */ + sp->modes &= ~PATCH_NO_SRELEASE; + cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope\n"); + } + else if (!(sp->modes & PATCH_SUSTAIN)) + { + /* No sustain? Then no envelope. I don't know if this is + justified, but patches without sustain usually don't need the + envelope either... at least the Gravis ones. They're mostly + drums. I think. */ + sp->modes &= ~PATCH_NO_SRELEASE; + cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n"); + } + } - if (sf2flag) - { - READ_SHORT(sample_volume); - READ_CHAR(sf2delay); - READ_CHAR(sp->exclusiveClass); - fp->Seek(32, SEEK_CUR); - } - else - { - fp->Seek(36, SEEK_CUR); - sample_volume = 0; - sf2delay = 0; + for (j = 0; j < 6; j++) + { + sp->envelope_rate[j] = convert_envelope_rate(song, patch_data.EnvelopeRate[j]); + sp->envelope_offset[j] = convert_envelope_offset(patch_data.EnvelopeOffset[j]); + } - } + /* Then read the sample data */ + if (((sp->modes & PATCH_16) && sp->data_length/2 > MAX_SAMPLE_SIZE) || + (!(sp->modes & PATCH_16) && sp->data_length > MAX_SAMPLE_SIZE)) + { + goto fail; + } + sp->data = (sample_t *)safe_malloc(sp->data_length); - /* Mark this as a fixed-pitch instrument if such a deed is desired. */ - if (note_to_use != -1) - sp->note_to_use = (BYTE)(note_to_use); - else - sp->note_to_use = 0; + if (sp->data_length != fp->Read(sp->data, sp->data_length)) + goto fail; - /* seashore.pat in the Midia patch set has no Sustain. I don't - understand why, and fixing it by adding the Sustain flag to - all looped patches probably breaks something else. We do it - anyway. */ + convert_sample_data(sp, sp->data); - if (sp->modes & MODES_LOOPING) - sp->modes |= MODES_SUSTAIN; + /* Reverse reverse loops and pass them off as normal loops */ + if (sp->modes & PATCH_BACKWARD) + { + int t; + /* The GUS apparently plays reverse loops by reversing the + whole sample. We do the same because the GUS does not SUCK. */ - /* Strip any loops and envelopes we're permitted to */ - if ((strip_loop == 1) && - (sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE))) - { - cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain"); - sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE); - } + cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s\n", name); + reverse_data((sample_t *)sp->data, 0, sp->data_length); + sp->data[sp->data_length] = sp->data[sp->data_length - 1]; - if (strip_envelope == 1) - { - if (sp->modes & MODES_ENVELOPE) - cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope"); - sp->modes &= ~MODES_ENVELOPE; - } - else if (strip_envelope != 0) - { - /* Have to make a guess. */ - if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE))) - { - /* No loop? Then what's there to sustain? No envelope needed either... */ - sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE); - cmsg(CMSG_INFO, VERB_DEBUG, - " - No loop, removing sustain and envelope"); - } - else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100) - { - /* Envelope rates all maxed out? Envelope end at a high "offset"? - That's a weird envelope. Take it out. */ - sp->modes &= ~MODES_ENVELOPE; - cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope"); - } - else if (!(sp->modes & MODES_SUSTAIN)) - { - /* No sustain? Then no envelope. I don't know if this is - justified, but patches without sustain usually don't need the - envelope either... at least the Gravis ones. They're mostly - drums. I think. */ - sp->modes &= ~MODES_ENVELOPE; - cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope"); - } - } + t = sp->loop_start; + sp->loop_start = sp->data_length - sp->loop_end; + sp->loop_end = sp->data_length - t; - sp->attenuation = 0; + sp->modes &= ~PATCH_BACKWARD; + sp->modes |= PATCH_LOOPEN; /* just in case */ + } - for (j = ATTACK; j < DELAY; j++) - { - sp->envelope_rate[j] = convert_envelope_rate(song, tmp[j]); - sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]); - } - if (sf2flag) - { - if (sf2delay > 5) - { - sf2delay = 5; - } - sp->envelope_rate[DELAY] = (int)( (sf2delay * song->rate) / 1000 ); - } - else - { - sp->envelope_rate[DELAY] = 0; - } - sp->envelope_offset[DELAY] = 0; - - for (j = ATTACK; j < DELAY; j++) - { - sp->modulation_rate[j] = float(sp->envelope_rate[j]); - sp->modulation_offset[j] = float(sp->envelope_offset[j]); - } - sp->modulation_rate[DELAY] = sp->modulation_offset[DELAY] = 0; - sp->modEnvToFilterFc = 0; - sp->modEnvToPitch = 0; - sp->lfo_sweep_increment = 0; - sp->lfo_phase_increment = 0; - sp->modLfoToFilterFc = 0; - - /* Then read the sample data */ - if (((sp->modes & MODES_16BIT) && sp->data_length/2 > MAX_SAMPLE_SIZE) || - (!(sp->modes & MODES_16BIT) && sp->data_length > MAX_SAMPLE_SIZE)) - { - goto fail; - } - sp->data = (sample_t *)safe_malloc(sp->data_length + 1); - - if (sp->data_length != fp->Read(sp->data, sp->data_length)) - goto fail; - - convert_sample_data(sp, sp->data); - - /* Reverse reverse loops and pass them off as normal loops */ - if (sp->modes & MODES_REVERSE) - { - int t; - /* The GUS apparently plays reverse loops by reversing the - whole sample. We do the same because the GUS does not SUCK. */ - - 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]; - - t = sp->loop_start; - sp->loop_start = sp->data_length - sp->loop_end; - sp->loop_end = sp->data_length - t; - - sp->modes &= ~MODES_REVERSE; - sp->modes |= MODES_LOOPING; /* just in case */ - } - - if (amp != -1) - { - sp->volume = (amp) / 100.f; - } - else if (sf2flag) - { - sp->volume = (sample_volume) / 255.f; - } - else - { + if (amp != -1) + { + sp->volume = (amp) / 100.f; + } + else + { #if defined(ADJUST_SAMPLE_VOLUMES) - /* Try to determine a volume scaling factor for the sample. - This is a very crude adjustment, but things sound more - balanced with it. Still, this should be a runtime option. */ - int i, numsamps = sp->data_length; - sample_t maxamp = 0, a; - sample_t *tmp; - for (i = numsamps, tmp = sp->data; i; --i) - { - a = abs(*tmp++); - if (a > maxamp) - maxamp = a; - } - sp->volume = 1 / maxamp; - cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume); + /* Try to determine a volume scaling factor for the sample. + This is a very crude adjustment, but things sound more + balanced with it. Still, this should be a runtime option. */ + int i; + sample_t maxamp = 0, a; + sample_t *tmp; + for (i = sp->data_length, tmp = sp->data; i; --i) + { + a = abs(*tmp++); + if (a > maxamp) + maxamp = a; + } + sp->volume = 1 / maxamp; + cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f\n", sp->volume); #else - sp->volume = 1; + sp->volume = 1; #endif - } + } - /* Then fractional samples */ - sp->data_length <<= FRACTION_BITS; - sp->loop_start <<= FRACTION_BITS; - sp->loop_end <<= FRACTION_BITS; + /* Then fractional samples */ + sp->data_length <<= FRACTION_BITS; + sp->loop_start <<= FRACTION_BITS; + sp->loop_end <<= FRACTION_BITS; - /* Adjust for fractional loop points. */ - sp->loop_start |= (fractions & 0x0F) << (FRACTION_BITS-4); - sp->loop_end |= ((fractions>>4) & 0x0F) << (FRACTION_BITS-4); - - /* If this instrument will always be played on the same note, - and it's not looped, we can resample it now. */ - if (sp->note_to_use && !(sp->modes & MODES_LOOPING)) - pre_resample(song, sp); - - if (strip_tail == 1) - { - /* Let's not really, just say we did. */ - cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail"); - sp->data_length = sp->loop_end; - } - } /* end of sample loop */ - } /* end of stereo layer loop */ - } /* end of vlayer loop */ + /* Adjust for fractional loop points. */ + sp->loop_start |= (patch_data.Fractions & 0x0F) << (FRACTION_BITS-4); + sp->loop_end |= (patch_data.Fractions & 0xF0) << (FRACTION_BITS-4-4); + /* If this instrument will always be played on the same note, + and it's not looped, we can resample it now. */ + if (sp->scale_factor == 0 && !(sp->modes & PATCH_LOOPEN)) + { + pre_resample(song, sp); + } + if (strip_tail == 1) + { + /* Let's not really, just say we did. */ + cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail\n"); + sp->data_length = sp->loop_end; + } + } delete fp; - return headlp; + return ip; } void convert_sample_data(Sample *sp, const void *data) @@ -752,7 +503,7 @@ void convert_sample_data(Sample *sp, const void *data) /* convert everything to 32-bit floating point data */ sample_t *newdata = NULL; - switch (sp->modes & (MODES_16BIT | MODES_UNSIGNED)) + switch (sp->modes & (PATCH_16 | PATCH_UNSIGNED)) { case 0: { /* 8-bit, signed */ @@ -772,7 +523,7 @@ void convert_sample_data(Sample *sp, const void *data) break; } - case MODES_UNSIGNED: + case PATCH_UNSIGNED: { /* 8-bit, unsigned */ BYTE *cp = (BYTE *)data; newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t)); @@ -791,7 +542,7 @@ void convert_sample_data(Sample *sp, const void *data) break; } - case MODES_16BIT: + case PATCH_16: { /* 16-bit, signed */ SWORD *cp = (SWORD *)data; /* Convert these to samples */ @@ -814,7 +565,7 @@ void convert_sample_data(Sample *sp, const void *data) break; } - case MODES_16BIT | MODES_UNSIGNED: + case PATCH_16 | PATCH_UNSIGNED: { /* 16-bit, unsigned */ WORD *cp = (WORD *)data; /* Convert these to samples */ @@ -853,71 +604,61 @@ static int fill_bank(Renderer *song, int dr, int b) if (bank == NULL) { cmsg(CMSG_ERROR, VERB_NORMAL, - "Huh. Tried to load instruments in non-existent %s %d", + "Huh. Tried to load instruments in non-existent %s %d\n", (dr) ? "drumset" : "tone bank", b); return 0; } for (i = 0; i < MAXPROG; i++) { - if (bank->tone[i].layer == MAGIC_LOAD_INSTRUMENT) + if (bank->instrument[i] == MAGIC_LOAD_INSTRUMENT) { - bank->tone[i].layer = load_instrument_dls(song, dr, b, i); - if (bank->tone[i].layer != NULL) + bank->instrument[i] = load_instrument_dls(song, dr, b, i); + if (bank->instrument[i] != NULL) { continue; } if (bank->tone[i].name.IsEmpty()) { - 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"); - if (b!=0) + cmsg(CMSG_WARNING, (b != 0) ? VERB_VERBOSE : VERB_NORMAL, + "No instrument mapped to %s %d, program %d%s\n", + (dr) ? "drum set" : "tone bank", b, i, + (b != 0) ? "" : " - this instrument will not be heard"); + if (b != 0) { /* Mark the corresponding instrument in the default - bank / drumset for loading (if it isn't already) */ + bank / drumset for loading (if it isn't already) */ if (!dr) { - if (!(standard_tonebank.tone[i].layer)) - standard_tonebank.tone[i].layer= - MAGIC_LOAD_INSTRUMENT; + if (tonebank[0]->instrument[i] != NULL) + { + tonebank[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT; + } } else { - if (!(standard_drumset.tone[i].layer)) - standard_drumset.tone[i].layer= - MAGIC_LOAD_INSTRUMENT; + if (drumset[0]->instrument[i] != NULL) + { + drumset[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT; + } } } - bank->tone[i].layer=0; + bank->instrument[i] = NULL; errors++; } - else if (!(bank->tone[i].layer= + else if (!(bank->instrument[i] = load_instrument(song, bank->tone[i].name, - bank->tone[i].font_type, - (dr) ? 1 : 0, - bank->tone[i].pan, - bank->tone[i].amp, - bank->tone[i].tuning, - (bank->tone[i].note!=-1) ? - bank->tone[i].note : - ((dr) ? i : -1), - (bank->tone[i].strip_loop!=-1) ? - bank->tone[i].strip_loop : - ((dr) ? 1 : -1), - (bank->tone[i].strip_envelope != -1) ? - bank->tone[i].strip_envelope : - ((dr) ? 1 : -1), - bank->tone[i].strip_tail, - b, - ((dr) ? i + 128 : i), - bank->tone[i].sf_ix - ))) + (dr) ? 1 : 0, + bank->tone[i].pan, + bank->tone[i].amp, + (bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1), + (bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1), + (bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1), + bank->tone[i].strip_tail))) { cmsg(CMSG_ERROR, VERB_NORMAL, - "Couldn't load instrument %s (%s %d, program %d)", + "Couldn't load instrument %s (%s %d, program %d)\n", bank->tone[i].name.GetChars(), - (dr)? "drum set" : "tone bank", b, i); + (dr) ? "drum set" : "tone bank", b, i); errors++; } } @@ -940,24 +681,34 @@ int Renderer::load_missing_instruments() void free_instruments() { - int i = 128; + int i = MAXBANK; while (i--) { if (tonebank[i] != NULL) - free_bank(0,i); + { + delete tonebank[i]; + tonebank[i] = NULL; + } if (drumset[i] != NULL) - free_bank(1,i); + { + delete drumset[i]; + drumset[i] = NULL; + } } } int Renderer::set_default_instrument(const char *name) { - InstrumentLayer *lp; - if (!(lp = load_instrument(this, name, FONT_NORMAL, 0, -1, -1, 0, -1, -1, -1, -1, 0, -1, -1))) + Instrument *ip; + if ((ip = load_instrument(this, name, 0, -1, -1, -1, 0, 0, 0)) == NULL) + { return -1; - if (default_instrument) - free_layer(default_instrument); - default_instrument = lp; + } + if (default_instrument != NULL) + { + delete default_instrument; + } + default_instrument = ip; default_program = SPECIAL_PROGRAM; return 0; } diff --git a/src/timidity/instrum_dls.cpp b/src/timidity/instrum_dls.cpp index 5828b806e..7900a55d9 100644 --- a/src/timidity/instrum_dls.cpp +++ b/src/timidity/instrum_dls.cpp @@ -1121,29 +1121,29 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins, DLS_Region *rgn = &ins->regions[index]; DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex]; - if (!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE)) - { - sample->exclusiveClass = (SBYTE)rgn->header->usKeyGroup; - } + sample->self_nonexclusive = !!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE); + sample->key_group = (SBYTE)rgn->header->usKeyGroup; sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow)); sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh)); sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote)); sample->low_vel = rgn->header->RangeVelocity.usLow; sample->high_vel = rgn->header->RangeVelocity.usHigh; - sample->modes = wave->format->wBitsPerSample == 8 ? MODES_UNSIGNED : MODES_16BIT; + sample->modes = wave->format->wBitsPerSample == 8 ? PATCH_UNSIGNED : PATCH_16; sample->sample_rate = wave->format->dwSamplesPerSec; sample->data = NULL; sample->data_length = wave->length; convert_sample_data(sample, wave->data); - if (rgn->wsmp->cSampleLoops) { - sample->modes |= (MODES_LOOPING|MODES_SUSTAIN); + if (rgn->wsmp->cSampleLoops) + { + sample->modes |= (PATCH_LOOPEN | PATCH_SUSTAIN); sample->loop_start = rgn->wsmp_loop->ulStart / 2; sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2); } sample->volume = 1.0f; - if (sample->modes & MODES_SUSTAIN) { + if (sample->modes & PATCH_SUSTAIN) + { int value; double attack, hold, decay, release; int sustain; CONNECTIONLIST *art = NULL; @@ -1192,12 +1192,7 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins, sample->envelope_offset[RELEASEC] = to_offset(0); sample->envelope_rate[RELEASEC] = to_offset(1); - sample->modes |= MODES_ENVELOPE; - } - for (int j = ATTACK; j < DELAY; j++) - { - sample->modulation_rate[j] = float(sample->envelope_rate[j]); - sample->modulation_offset[j] = float(sample->envelope_offset[j]); + sample->modes |= PATCH_NO_SRELEASE; } sample->data_length <<= FRACTION_BITS; @@ -1205,55 +1200,54 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins, sample->loop_end <<= FRACTION_BITS; } -InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument) +Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument) { - InstrumentLayer *layer; + Instrument *inst; DWORD i; DLS_Instrument *dls_ins = NULL; if (song->patches == NULL) + { return NULL; - + } drum = drum ? 0x80000000 : 0; - for (i = 0; i < song->patches->cInstruments; ++i) { + for (i = 0; i < song->patches->cInstruments; ++i) + { dls_ins = &song->patches->instruments[i]; if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum && ((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank && dls_ins->header->Locale.ulInstrument == (ULONG)instrument) break; } - if (i == song->patches->cInstruments && !bank) { - for (i = 0; i < song->patches->cInstruments; ++i) { + if (i == song->patches->cInstruments && bank == 0) + { + for (i = 0; i < song->patches->cInstruments; ++i) + { dls_ins = &song->patches->instruments[i]; if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum && dls_ins->header->Locale.ulInstrument == (ULONG)instrument) break; } } - if (i == song->patches->cInstruments) { + if (i == song->patches->cInstruments) + { // SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank)); return NULL; } - layer = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer)); - layer->lo = 0; - layer->hi = 127; - layer->instrument = (Instrument *)safe_malloc(sizeof(Instrument)); - layer->instrument->type = INST_DLS; - layer->instrument->samples = dls_ins->header->cRegions; - layer->instrument->sample = (Sample *)safe_malloc(layer->instrument->samples * sizeof(Sample)); - layer->instrument->left_samples = layer->instrument->samples; - layer->instrument->left_sample = layer->instrument->sample; - layer->instrument->right_samples = 0; - layer->instrument->right_sample = NULL; - memset(layer->instrument->sample, 0, layer->instrument->samples * sizeof(Sample)); + inst = (Instrument *)safe_malloc(sizeof(Instrument)); + inst->type = INST_DLS; + inst->samples = dls_ins->header->cRegions; + inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample)); + memset(inst->sample, 0, inst->samples * sizeof(Sample)); /* printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples); */ - for (i = 0; i < dls_ins->header->cRegions; ++i) { - load_region_dls(song, &layer->instrument->sample[i], dls_ins, i); + for (i = 0; i < dls_ins->header->cRegions; ++i) + { + load_region_dls(song, &inst->sample[i], dls_ins, i); } - return layer; + return inst; } #endif /* !TEST_MAIN_DLS */ diff --git a/src/timidity/mix.cpp b/src/timidity/mix.cpp index 92a23138b..34db6b40e 100644 --- a/src/timidity/mix.cpp +++ b/src/timidity/mix.cpp @@ -37,15 +37,14 @@ int recompute_envelope(Voice *v) stage = v->envelope_stage; - if (stage >= DELAY) + if (stage > RELEASEC) { /* Envelope ran out. */ - int tmp = (v->status == VOICE_DIE); /* Already displayed as dead */ v->status = VOICE_FREE; return 1; } - if (v->sample->modes & MODES_ENVELOPE) + if (v->sample->modes & PATCH_NO_SRELEASE) { if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED) { @@ -60,7 +59,9 @@ int recompute_envelope(Voice *v) v->envelope_stage = stage + 1; if (v->envelope_volume == v->sample->envelope_offset[stage]) + { return recompute_envelope(v); + } v->envelope_target = v->sample->envelope_offset[stage]; v->envelope_increment = v->sample->envelope_rate[stage]; if (v->envelope_target < v->envelope_volume) @@ -75,28 +76,30 @@ void apply_envelope_to_amp(Voice *v) { ramp = v->right_amp; - if (v->tremolo_phase_increment) + if (v->tremolo_phase_increment != 0) { lamp *= v->tremolo_volume; ramp *= v->tremolo_volume; } - if (v->sample->modes & MODES_ENVELOPE) + if (v->sample->modes & PATCH_NO_SRELEASE) { double vol = calc_vol(v->envelope_volume / float(1 << 30)); lamp *= vol; ramp *= vol; } - v->left_mix = float(lamp); v->right_mix = float(ramp); } else { - if (v->tremolo_phase_increment) + if (v->tremolo_phase_increment != 0) + { lamp *= v->tremolo_volume; - if (v->sample->modes & MODES_ENVELOPE) + } + if (v->sample->modes & PATCH_NO_SRELEASE) + { lamp *= calc_vol(v->envelope_volume / float(1 << 30)); - + } v->left_mix = float(lamp); } } @@ -104,13 +107,14 @@ void apply_envelope_to_amp(Voice *v) 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))) { v->envelope_volume = v->envelope_target; if (recompute_envelope(v)) + { return 1; + } } return 0; } @@ -119,7 +123,7 @@ static void update_tremolo(Voice *v) { int depth = v->sample->tremolo_depth << 7; - if (v->tremolo_sweep) + if (v->tremolo_sweep != 0) { /* Update sweep position */ @@ -151,12 +155,14 @@ static void update_tremolo(Voice *v) /* Returns 1 if the note died */ static int update_signal(Voice *v) { - if (v->envelope_increment && update_envelope(v)) + if (v->envelope_increment != 0 && update_envelope(v)) + { return 1; - - if (v->tremolo_phase_increment) + } + if (v->tremolo_phase_increment != 0) + { update_tremolo(v); - + } apply_envelope_to_amp(v); return 0; } diff --git a/src/timidity/playmidi.cpp b/src/timidity/playmidi.cpp index ca35be26a..9a2a2139c 100644 --- a/src/timidity/playmidi.cpp +++ b/src/timidity/playmidi.cpp @@ -31,210 +31,12 @@ namespace Timidity { -static bool opt_stereo_surround = false; -bool adjust_panning_immediately = false; - -/* $Id: tables.c 1404 2004-08-21 12:27:02Z slouken $ Greg Lee */ -const BYTE xmap[XMAPMAX][5] = -{ - { SFXBANK, 0, 0, 120, 0 }, - { SFXBANK, 0, 1, 120, 1 }, - { SFXBANK, 0, 2, 120, 2 }, - { SFXBANK, 0, 3, 120, 3 }, - { SFXBANK, 0, 4, 120, 4 }, - { SFXBANK, 0, 5, 120, 5 }, - { SFXBANK, 0, 16, 120, 16 }, - { SFXBANK, 0, 32, 120, 32 }, - { SFXBANK, 0, 33, 120, 33 }, - { SFXBANK, 0, 34, 120, 34 }, - { SFXBANK, 0, 35, 120, 35 }, - { SFXBANK, 0, 36, 120, 36 }, - { SFXBANK, 0, 48, 120, 48 }, - { SFXBANK, 0, 49, 120, 49 }, - { SFXBANK, 0, 50, 120, 50 }, - { SFXBANK, 0, 51, 120, 51 }, - { SFXBANK, 0, 52, 120, 52 }, - { SFXBANK, 0, 54, 120, 54 }, - { SFXBANK, 0, 55, 120, 55 }, - { SFXBANK, 0, 64, 120, 64 }, - { SFXBANK, 0, 65, 120, 65 }, - { SFXBANK, 0, 66, 120, 66 }, - { SFXBANK, 0, 67, 120, 67 }, - { SFXBANK, 0, 68, 120, 68 }, - { SFXBANK, 0, 69, 120, 69 }, - { SFXBANK, 0, 70, 120, 70 }, - { SFXBANK, 0, 80, 120, 80 }, - { SFXBANK, 0, 81, 120, 81 }, - { SFXBANK, 0, 82, 120, 82 }, - { SFXBANK, 0, 83, 120, 83 }, - { SFXBANK, 0, 84, 120, 84 }, - { SFXBANK, 0, 85, 120, 85 }, - { SFXBANK, 0, 86, 120, 86 }, - { SFXBANK, 0, 87, 120, 87 }, - { SFXBANK, 0, 88, 120, 88 }, - { SFXBANK, 0, 89, 120, 89 }, - { SFXBANK, 0, 90, 120, 90 }, - { SFXBANK, 0, 96, 120, 96 }, - { SFXBANK, 0, 97, 120, 97 }, - { SFXBANK, 0, 98, 120, 98 }, - { SFXBANK, 0, 99, 120, 99 }, - { SFXBANK, 0, 100, 120, 100 }, - { SFXBANK, 0, 101, 120, 101 }, - { SFXBANK, 0, 112, 120, 112 }, - { SFXBANK, 0, 113, 120, 113 }, - { SFXBANK, 0, 114, 120, 114 }, - { SFXBANK, 0, 115, 120, 115 }, - { SFXDRUM1, 0, 36, 121, 36 }, - { SFXDRUM1, 0, 37, 121, 37 }, - { SFXDRUM1, 0, 38, 121, 38 }, - { SFXDRUM1, 0, 39, 121, 39 }, - { SFXDRUM1, 0, 40, 121, 40 }, - { SFXDRUM1, 0, 41, 121, 41 }, - { SFXDRUM1, 0, 52, 121, 52 }, - { SFXDRUM1, 0, 68, 121, 68 }, - { SFXDRUM1, 0, 69, 121, 69 }, - { SFXDRUM1, 0, 70, 121, 70 }, - { SFXDRUM1, 0, 71, 121, 71 }, - { SFXDRUM1, 0, 72, 121, 72 }, - { SFXDRUM1, 0, 84, 121, 84 }, - { SFXDRUM1, 0, 85, 121, 85 }, - { SFXDRUM1, 0, 86, 121, 86 }, - { SFXDRUM1, 0, 87, 121, 87 }, - { SFXDRUM1, 0, 88, 121, 88 }, - { SFXDRUM1, 0, 90, 121, 90 }, - { SFXDRUM1, 0, 91, 121, 91 }, - { SFXDRUM1, 1, 36, 122, 36 }, - { SFXDRUM1, 1, 37, 122, 37 }, - { SFXDRUM1, 1, 38, 122, 38 }, - { SFXDRUM1, 1, 39, 122, 39 }, - { SFXDRUM1, 1, 40, 122, 40 }, - { SFXDRUM1, 1, 41, 122, 41 }, - { SFXDRUM1, 1, 42, 122, 42 }, - { SFXDRUM1, 1, 52, 122, 52 }, - { SFXDRUM1, 1, 53, 122, 53 }, - { SFXDRUM1, 1, 54, 122, 54 }, - { SFXDRUM1, 1, 55, 122, 55 }, - { SFXDRUM1, 1, 56, 122, 56 }, - { SFXDRUM1, 1, 57, 122, 57 }, - { SFXDRUM1, 1, 58, 122, 58 }, - { SFXDRUM1, 1, 59, 122, 59 }, - { SFXDRUM1, 1, 60, 122, 60 }, - { SFXDRUM1, 1, 61, 122, 61 }, - { SFXDRUM1, 1, 62, 122, 62 }, - { SFXDRUM1, 1, 68, 122, 68 }, - { SFXDRUM1, 1, 69, 122, 69 }, - { SFXDRUM1, 1, 70, 122, 70 }, - { SFXDRUM1, 1, 71, 122, 71 }, - { SFXDRUM1, 1, 72, 122, 72 }, - { SFXDRUM1, 1, 73, 122, 73 }, - { SFXDRUM1, 1, 84, 122, 84 }, - { SFXDRUM1, 1, 85, 122, 85 }, - { SFXDRUM1, 1, 86, 122, 86 }, - { SFXDRUM1, 1, 87, 122, 87 }, - { XGDRUM, 0, 25, 40, 38 }, - { XGDRUM, 0, 26, 40, 40 }, - { XGDRUM, 0, 27, 40, 39 }, - { XGDRUM, 0, 28, 40, 30 }, - { XGDRUM, 0, 29, 0, 25 }, - { XGDRUM, 0, 30, 0, 85 }, - { XGDRUM, 0, 31, 0, 38 }, - { XGDRUM, 0, 32, 0, 37 }, - { XGDRUM, 0, 33, 0, 36 }, - { XGDRUM, 0, 34, 0, 38 }, - { XGDRUM, 0, 62, 0, 101 }, - { XGDRUM, 0, 63, 0, 102 }, - { XGDRUM, 0, 64, 0, 103 }, - { XGDRUM, 8, 25, 40, 38 }, - { XGDRUM, 8, 26, 40, 40 }, - { XGDRUM, 8, 27, 40, 39 }, - { XGDRUM, 8, 28, 40, 40 }, - { XGDRUM, 8, 29, 8, 25 }, - { XGDRUM, 8, 30, 8, 85 }, - { XGDRUM, 8, 31, 8, 38 }, - { XGDRUM, 8, 32, 8, 37 }, - { XGDRUM, 8, 33, 8, 36 }, - { XGDRUM, 8, 34, 8, 38 }, - { XGDRUM, 8, 62, 8, 101 }, - { XGDRUM, 8, 63, 8, 102 }, - { XGDRUM, 8, 64, 8, 103 }, - { XGDRUM, 16, 25, 40, 38 }, - { XGDRUM, 16, 26, 40, 40 }, - { XGDRUM, 16, 27, 40, 39 }, - { XGDRUM, 16, 28, 40, 40 }, - { XGDRUM, 16, 29, 16, 25 }, - { XGDRUM, 16, 30, 16, 85 }, - { XGDRUM, 16, 31, 16, 38 }, - { XGDRUM, 16, 32, 16, 37 }, - { XGDRUM, 16, 33, 16, 36 }, - { XGDRUM, 16, 34, 16, 38 }, - { XGDRUM, 16, 62, 16, 101 }, - { XGDRUM, 16, 63, 16, 102 }, - { XGDRUM, 16, 64, 16, 103 }, - { XGDRUM, 24, 25, 40, 38 }, - { XGDRUM, 24, 26, 40, 40 }, - { XGDRUM, 24, 27, 40, 39 }, - { XGDRUM, 24, 28, 24, 100 }, - { XGDRUM, 24, 29, 24, 25 }, - { XGDRUM, 24, 30, 24, 15 }, - { XGDRUM, 24, 31, 24, 38 }, - { XGDRUM, 24, 32, 24, 37 }, - { XGDRUM, 24, 33, 24, 36 }, - { XGDRUM, 24, 34, 24, 38 }, - { XGDRUM, 24, 62, 24, 101 }, - { XGDRUM, 24, 63, 24, 102 }, - { XGDRUM, 24, 64, 24, 103 }, - { XGDRUM, 24, 78, 0, 17 }, - { XGDRUM, 24, 79, 0, 18 }, - { XGDRUM, 25, 25, 40, 38 }, - { XGDRUM, 25, 26, 40, 40 }, - { XGDRUM, 25, 27, 40, 39 }, - { XGDRUM, 25, 28, 25, 100 }, - { XGDRUM, 25, 29, 25, 25 }, - { XGDRUM, 25, 30, 25, 15 }, - { XGDRUM, 25, 31, 25, 38 }, - { XGDRUM, 25, 32, 25, 37 }, - { XGDRUM, 25, 33, 25, 36 }, - { XGDRUM, 25, 34, 25, 38 }, - { XGDRUM, 25, 78, 0, 17 }, - { XGDRUM, 25, 79, 0, 18 }, - { XGDRUM, 32, 25, 40, 38 }, - { XGDRUM, 32, 26, 40, 40 }, - { XGDRUM, 32, 27, 40, 39 }, - { XGDRUM, 32, 28, 40, 40 }, - { XGDRUM, 32, 29, 32, 25 }, - { XGDRUM, 32, 30, 32, 85 }, - { XGDRUM, 32, 31, 32, 38 }, - { XGDRUM, 32, 32, 32, 37 }, - { XGDRUM, 32, 33, 32, 36 }, - { XGDRUM, 32, 34, 32, 38 }, - { XGDRUM, 32, 62, 32, 101 }, - { XGDRUM, 32, 63, 32, 102 }, - { XGDRUM, 32, 64, 32, 103 }, - { XGDRUM, 40, 25, 40, 38 }, - { XGDRUM, 40, 26, 40, 40 }, - { XGDRUM, 40, 27, 40, 39 }, - { XGDRUM, 40, 28, 40, 40 }, - { XGDRUM, 40, 29, 40, 25 }, - { XGDRUM, 40, 30, 40, 85 }, - { XGDRUM, 40, 31, 40, 39 }, - { XGDRUM, 40, 32, 40, 37 }, - { XGDRUM, 40, 33, 40, 36 }, - { XGDRUM, 40, 34, 40, 38 }, - { XGDRUM, 40, 38, 40, 39 }, - { XGDRUM, 40, 39, 0, 39 }, - { XGDRUM, 40, 40, 40, 38 }, - { XGDRUM, 40, 42, 0, 42 }, - { XGDRUM, 40, 46, 0, 46 }, - { XGDRUM, 40, 62, 40, 101 }, - { XGDRUM, 40, 63, 40, 102 }, - { XGDRUM, 40, 64, 40, 103 }, - { XGDRUM, 40, 87, 40, 87 } -}; - void Renderer::reset_voices() { for (int i = 0; i < MAX_VOICES; i++) + { voice[i].status = VOICE_FREE; + } } /* Process the Reset All Controllers event */ @@ -248,9 +50,6 @@ void Renderer::reset_controllers(int c) channel[c].mono = 0; channel[c].rpn = RPN_RESET; channel[c].nrpn = RPN_RESET; - - channel[c].reverberation = 0; - channel[c].chorusdepth = 0; } void Renderer::reset_midi() @@ -263,18 +62,13 @@ void Renderer::reset_midi() channel[i].panning = NO_PANNING; channel[i].pitchsens = 200; channel[i].bank = 0; /* tone bank or drum set */ - channel[i].harmoniccontent = 64; - channel[i].releasetime = 64; - channel[i].attacktime = 64; - channel[i].brightness = 64; - channel[i].sfx = 0; } reset_voices(); } void Renderer::select_sample(int v, Instrument *ip, int vel) { - float f, cdiff, diff, midfreq; + double f, cdiff, diff; int s, i; Sample *sp, *closest; @@ -300,22 +94,16 @@ void Renderer::select_sample(int v, Instrument *ip, int vel) } /* - No suitable sample found! We'll select the sample whose root - frequency is closest to the one we want. (Actually we should - probably convert the low, high, and root frequencies to MIDI note - values and compare those.) */ + No suitable sample found! We'll select the sample whose root + frequency is closest to the one we want. (Actually we should + probably convert the low, high, and root frequencies to MIDI note + values and compare those.) */ cdiff = 1e10; closest = sp = ip->sample; - midfreq = float(sp->low_freq + sp->high_freq) / 2; for (i = 0; i < s; i++) { - diff = sp->root_freq - f; - /* But the root freq. can perfectly well lie outside the keyrange - * frequencies, so let's try: - */ - /* diff = midfreq - f; */ - if (diff < 0) diff = -diff; + diff = fabs(sp->root_freq - f); if (diff < cdiff) { cdiff = diff; @@ -327,61 +115,6 @@ void Renderer::select_sample(int v, Instrument *ip, int vel) return; } - - -void Renderer::select_stereo_samples(int v, InstrumentLayer *lp, int vel) -{ - Instrument *ip; - InstrumentLayer *nlp, *bestvel; - int diffvel, midvel, mindiff; - - /* select closest velocity */ - bestvel = lp; - mindiff = 500; - for (nlp = lp; nlp; nlp = nlp->next) - { - midvel = (nlp->hi + nlp->lo)/2; - if (!midvel) - { - diffvel = 127; - } - else if (voice[v].velocity < nlp->lo || voice[v].velocity > nlp->hi) - { - diffvel = 200; - } - else - { - diffvel = voice[v].velocity - midvel; - } - if (diffvel < 0) - { - diffvel = -diffvel; - } - if (diffvel < mindiff) - { - mindiff = diffvel; - bestvel = nlp; - } - } - ip = bestvel->instrument; - - if (ip->right_sample) - { - ip->sample = ip->right_sample; - ip->samples = ip->right_samples; - select_sample(v, ip, vel); - voice[v].right_sample = voice[v].sample; - } - else - { - voice[v].right_sample = NULL; - } - ip->sample = ip->left_sample; - ip->samples = ip->left_samples; - select_sample(v, ip, vel); -} - - void Renderer::recompute_freq(int v) { Channel *ch = &channel[voice[v].channel]; @@ -390,17 +123,16 @@ void Renderer::recompute_freq(int v) pb = ch->pitchbend; double a; - if (!voice[v].sample->sample_rate) + if (voice[v].sample->sample_rate == 0) + { return; + } - if (voice[v].vibrato_control_ratio) + if (voice[v].vibrato_control_ratio != 0) { /* This instrument has vibrato. Invalidate any precomputed - sample_increments. */ - - int i = VIBRATO_SAMPLE_INCREMENTS; - while (i--) - voice[v].vibrato_sample_increment[i]=0; + sample_increments. */ + memset(voice[v].vibrato_sample_increment, 0, sizeof(voice[v].vibrato_sample_increment)); } if (pb == 0x2000 || pb < 0 || pb > 0x3FFF) @@ -437,34 +169,24 @@ void Renderer::recompute_freq(int v) void Renderer::recompute_amp(Voice *v) { - double tempamp; int chan = v->channel; int panning = v->panning; double vol = channel[chan].volume / 16383.f; - double expr = calc_vol(channel[chan].expression / 16383.f); - double vel = calc_vol(v->velocity / 127.f); + double expr = channel[chan].expression / 16383.f; + double vel = /*calc_vol*/(v->velocity / 127.f); + double tempamp = vel * calc_vol(vol * expr) * v->sample->volume; - if (channel[chan].kit) - { - int note = v->sample->note_to_use; - if (note > 0 && drumvolume[chan][note] >= 0) { vol = drumvolume[chan][note] / 127.f; } - if (note > 0 && drumpanpot[chan][note] >= 0) { panning = drumvolume[chan][note]; panning |= panning << 7; } - } - - vol = calc_vol(vol); - tempamp = vel * vol * expr * v->sample->volume; - - if (panning > (60 << 7) && panning < (68 << 7)) + if (panning >= 0x1DBB && panning < 0x2244) { v->panned = PANNED_CENTER; v->left_amp = (float)(tempamp * 0.70710678118654752440084436210485); // * sqrt(0.5) } - else if (panning < (5 << 7)) + else if (panning == 0) { v->panned = PANNED_LEFT; v->left_amp = (float)tempamp; } - else if (panning > (123 << 7)) + else if (panning == 0x3FFF) { v->panned = PANNED_RIGHT; v->left_amp = (float)tempamp; /* left_amp will be used */ @@ -478,471 +200,75 @@ void Renderer::recompute_amp(Voice *v) } } - -#define NOT_CLONE 0 -#define STEREO_CLONE 1 -#define REVERB_CLONE 2 -#define CHORUS_CLONE 3 - - -/* just a variant of note_on() */ -int Renderer::vc_alloc(int j) -{ - int i = voices; - - while (i--) - { - if (i != j && (voice[i].status == VOICE_FREE)) - { - return i; - } - } - return -1; -} - -void Renderer::kill_others(int i) +void Renderer::kill_key_group(int i) { int j = voices; - if (!voice[i].sample->exclusiveClass) return; - + if (voice[i].sample->key_group == 0) + { + return; + } while (j--) { - if (voice[j].status == VOICE_FREE || - voice[j].status == VOICE_OFF || - voice[j].status == VOICE_DIE) continue; + if (voice[j].status != VOICE_ON && voice[j].status != VOICE_SUSTAINED) continue; if (i == j) continue; if (voice[i].channel != voice[j].channel) continue; - if (voice[j].sample->note_to_use) - { - if (voice[j].sample->exclusiveClass != voice[i].sample->exclusiveClass) continue; - kill_note(j); - } + if (voice[j].sample->key_group != voice[i].sample->key_group) continue; + kill_note(j); } } - -void Renderer::clone_voice(Instrument *ip, int v, int note, int vel, int clone_type, int variationbank) +float Renderer::calculate_scaled_frequency(Sample *sp, int note) { - int w, played_note, chorus = 0, reverb = 0, milli; - int chan = voice[v].channel; - - // [RH] Don't do the other clones. - if (clone_type != STEREO_CLONE) - { - return; - } - - if (clone_type == STEREO_CLONE) - { - if (!voice[v].right_sample && variationbank != 3) return; - if (variationbank == 6) return; - } - - if (channel[chan].kit) - { - reverb = drumreverberation[chan][voice[v].note]; - chorus = drumchorusdepth[chan][voice[v].note]; - } - else - { - reverb = channel[chan].reverberation; - chorus = channel[chan].chorusdepth; - } - - if (clone_type == REVERB_CLONE) chorus = 0; - else if (clone_type == CHORUS_CLONE) reverb = 0; - else if (clone_type == STEREO_CLONE) reverb = chorus = 0; - - if (reverb > 127) reverb = 127; - if (chorus > 127) chorus = 127; - - if (clone_type == CHORUS_CLONE) - { - if (variationbank == 32) chorus = 30; - else if (variationbank == 33) chorus = 60; - else if (variationbank == 34) chorus = 90; - } - - chorus /= 2; /* This is an ad hoc adjustment. */ - - if (!reverb && !chorus && clone_type != STEREO_CLONE) return; - - if ( (w = vc_alloc(v)) < 0 ) return; - - voice[w] = voice[v]; - if (clone_type == STEREO_CLONE) voice[v].clone_voice = w; - voice[w].clone_voice = v; - voice[w].clone_type = clone_type; - voice[w].velocity = vel; - - milli = int(rate / 1000); - - if (clone_type == STEREO_CLONE) - { - int left, right, leftpan, rightpan; - int panrequest = voice[v].panning; - voice[w].sample = voice[v].right_sample; - if (variationbank == 3) - { - voice[v].panning = 0; - voice[w].panning = 127; - } - else - { - if (voice[v].sample->panning > voice[w].sample->panning) - { - left = w; - right = v; - } - else - { - left = v; - right = w; - } -#define INSTRUMENT_SEPARATION 12 - leftpan = panrequest - INSTRUMENT_SEPARATION / 2; - rightpan = leftpan + INSTRUMENT_SEPARATION; - if (leftpan < 0) - { - leftpan = 0; - rightpan = leftpan + INSTRUMENT_SEPARATION; - } - if (rightpan > 127) - { - rightpan = 127; - leftpan = rightpan - INSTRUMENT_SEPARATION; - } - voice[left].panning = leftpan; - voice[right].panning = rightpan; - voice[right].echo_delay = 20 * milli; - } - } - - voice[w].volume = voice[w].sample->volume; - - if (reverb) - { - if (opt_stereo_surround) - { - if (voice[w].panning > 64) - voice[w].panning = 127; - else - voice[w].panning = 0; - } - else - { - if (voice[v].panning < 64) - voice[w].panning = 64 + reverb/2; - else - voice[w].panning = 64 - reverb/2; - } - - /* try 98->99 for melodic instruments ? (bit much for percussion) */ - /* voice[w].volume *= calc_vol(((127 - reverb) / 8 + 98) / 127.f); */ - voice[w].volume = float(voice[w].volume * calc_vol((911 - reverb) / (8 * 127.f))); - - voice[w].echo_delay += reverb * milli; - voice[w].envelope_rate[DECAY] *= 2; - voice[w].envelope_rate[RELEASE] /= 2; - - if (XG_System_reverb_type >= 0) - { - int subtype = XG_System_reverb_type & 0x07; - int rtype = XG_System_reverb_type >> 3; - switch (rtype) - { - case 0: /* no effect */ - break; - case 1: /* hall */ - if (subtype) voice[w].echo_delay += 100 * milli; - break; - case 2: /* room */ - voice[w].echo_delay /= 2; - break; - case 3: /* stage */ - voice[w].velocity = voice[v].velocity; - break; - case 4: /* plate */ - voice[w].panning = voice[v].panning; - break; - case 16: /* white room */ - voice[w].echo_delay = 0; - break; - case 17: /* tunnel */ - voice[w].echo_delay *= 2; - voice[w].velocity /= 2; - break; - case 18: /* canyon */ - voice[w].echo_delay *= 2; - break; - case 19: /* basement */ - voice[w].velocity /= 2; - break; - default: - break; - } - } - } - played_note = voice[w].sample->note_to_use; - if (!played_note) - { - played_note = note & 0x7f; - if (variationbank == 35) played_note += 12; - else if (variationbank == 36) played_note -= 12; - else if (variationbank == 37) played_note += 7; - else if (variationbank == 36) played_note -= 7; - } -#if 0 - played_note = ( (played_note - voice[w].sample->freq_center) * voice[w].sample->freq_scale ) / 1024 + - voice[w].sample->freq_center; -#endif - voice[w].note = played_note; - voice[w].orig_frequency = note_to_freq(played_note); - - if (chorus) - { - if (opt_stereo_surround) - { - if (voice[v].panning < 64) - voice[w].panning = voice[v].panning + 32; - else - voice[w].panning = voice[v].panning - 32; - } - - if (!voice[w].vibrato_control_ratio) - { - voice[w].vibrato_control_ratio = 100; - voice[w].vibrato_depth = 6; - voice[w].vibrato_sweep = 74; - } - voice[w].volume *= 0.40f; - voice[v].volume = voice[w].volume; - recompute_amp(&voice[v]); - apply_envelope_to_amp(&voice[v]); - - voice[w].vibrato_sweep = chorus/2; - voice[w].vibrato_depth /= 2; - if (!voice[w].vibrato_depth) voice[w].vibrato_depth = 2; - voice[w].vibrato_control_ratio /= 2; - voice[w].echo_delay += 30 * milli; - - if (XG_System_chorus_type >= 0) - { - int subtype = XG_System_chorus_type & 0x07; - int chtype = 0x0f & (XG_System_chorus_type >> 3); - float chorus_factor; - - switch (chtype) - { - case 0: /* no effect */ - break; - case 1: /* chorus */ - chorus /= 3; - chorus_factor = pow(2.f, chorus / (256.f * 12.f)); - if(channel[ voice[w].channel ].pitchbend + chorus < 0x2000) - { - voice[w].orig_frequency = voice[w].orig_frequency * chorus_factor; - } - else - { - voice[w].orig_frequency = voice[w].orig_frequency / chorus_factor; - } - if (subtype) - { - voice[w].vibrato_depth *= 2; - } - break; - case 2: /* celeste */ - voice[w].orig_frequency += (voice[w].orig_frequency/128) * chorus; - break; - case 3: /* flanger */ - voice[w].vibrato_control_ratio = 10; - voice[w].vibrato_depth = 100; - voice[w].vibrato_sweep = 8; - voice[w].echo_delay += 200 * milli; - break; - case 4: /* symphonic : cf Children of the Night /128 bad, /1024 ok */ - voice[w].orig_frequency += (voice[w].orig_frequency/512) * chorus; - voice[v].orig_frequency -= (voice[v].orig_frequency/512) * chorus; - recompute_freq(v); - break; - case 8: /* phaser */ - break; - default: - break; - } - } - else - { - float chorus_factor; - chorus /= 3; - chorus_factor = pow(2.f, chorus / (256.f * 12.f)); - if (channel[ voice[w].channel ].pitchbend + chorus < 0x2000) - { - voice[w].orig_frequency = voice[w].orig_frequency * chorus_factor; - } - else - { - voice[w].orig_frequency = voice[w].orig_frequency / chorus_factor; - } - } - } -#if 0 - voice[w].loop_start = voice[w].sample->loop_start; - voice[w].loop_end = voice[w].sample->loop_end; -#endif - voice[w].echo_delay_count = voice[w].echo_delay; - if (reverb) voice[w].echo_delay *= 2; - - recompute_freq(w); - recompute_amp(&voice[w]); - if (voice[w].sample->modes & MODES_ENVELOPE) - { - /* Ramp up from 0 */ - voice[w].envelope_stage = ATTACK; - voice[w].modulation_stage = ATTACK; - voice[w].envelope_volume = 0; - voice[w].modulation_volume = 0; - voice[w].control_counter = 0; - voice[w].modulation_counter = 0; - recompute_envelope(&voice[w]); - /*recompute_modulation(w);*/ - } - else - { - voice[w].envelope_increment = 0; - voice[w].modulation_increment = 0; - } - apply_envelope_to_amp(&voice[w]); + double scalednote = (note - sp->scale_note) * sp->scale_factor / 1024.0 + sp->scale_note; + return (float)note_to_freq(scalednote); } - -void Renderer::xremap(int *banknumpt, int *this_notept, int this_kit) +void Renderer::start_note(int chan, int note, int vel, int i) { - int i, newmap; - int banknum = *banknumpt; - int this_note = *this_notept; - int newbank, newnote; - - if (!this_kit) - { - if (banknum == SFXBANK && tonebank[SFXBANK]) - { - return; - } - if (banknum == SFXBANK && tonebank[120]) - { - *banknumpt = 120; - } - return; - } - if (this_kit != 127 && this_kit != 126) - { - return; - } - for (i = 0; i < XMAPMAX; i++) - { - newmap = xmap[i][0]; - if (!newmap) return; - if (this_kit == 127 && newmap != XGDRUM) continue; - if (this_kit == 126 && newmap != SFXDRUM1) continue; - if (xmap[i][1] != banknum) continue; - if (xmap[i][3] != this_note) continue; - newbank = xmap[i][2]; - newnote = xmap[i][4]; - if (newbank == banknum && newnote == this_note) return; - if (!drumset[newbank]) return; - if (!drumset[newbank]->tone[newnote].layer) return; - if (drumset[newbank]->tone[newnote].layer == MAGIC_LOAD_INSTRUMENT) return; - *banknumpt = newbank; - *this_notept = newnote; - return; - } -} - - -void Renderer::start_note(int ch, int this_note, int this_velocity, int i) -{ - InstrumentLayer *lp; Instrument *ip; - int j, banknum; - int played_note, drumpan = NO_PANNING; - int rt; - int attacktime, releasetime, decaytime, variationbank; - int brightness = channel[ch].brightness; - int harmoniccontent = channel[ch].harmoniccontent; - int drumsflag = channel[ch].kit; - int this_prog = channel[ch].program; + int bank = channel[chan].bank; + int prog = channel[chan].program; - if (channel[ch].sfx) + if (ISDRUMCHANNEL(chan)) { - banknum = channel[ch].sfx; - } - else - { - banknum = channel[ch].bank; - } - - voice[i].velocity = this_velocity; - - if (XG_System_On) xremap(&banknum, &this_note, drumsflag); - /* if (current_config_pc42b) pcmap(&banknum, &this_note, &this_prog, &drumsflag); */ - - if (drumsflag) - { - if (NULL == drumset[banknum] || NULL == (lp = drumset[banknum]->tone[this_note].layer)) + if (NULL == drumset[bank] || NULL == (ip = drumset[bank]->instrument[note])) { - if (!(lp = drumset[0]->tone[this_note].layer)) + if (!(ip = drumset[0]->instrument[note])) return; /* No instrument? Then we can't play. */ } - ip = lp->instrument; if (ip->type == INST_GUS && ip->samples != 1) { cmsg(CMSG_WARNING, VERB_VERBOSE, "Strange: percussion instrument with %d samples!", ip->samples); } - - if (ip->sample->note_to_use) /* Do we have a fixed pitch? */ - { - voice[i].orig_frequency = note_to_freq(ip->sample->note_to_use); - drumpan = drumpanpot[ch][(int)ip->sample->note_to_use]; - drumpan |= drumpan << 7; - } - else - voice[i].orig_frequency = note_to_freq(this_note & 0x7F); } else { - if (channel[ch].program == SPECIAL_PROGRAM) + if (channel[chan].program == SPECIAL_PROGRAM) { - lp = default_instrument; + ip = default_instrument; } - else if (NULL == tonebank[channel[ch].bank] || NULL == (lp = tonebank[channel[ch].bank]->tone[channel[ch].program].layer)) + else if (NULL == tonebank[bank] || NULL == (ip = tonebank[bank]->instrument[prog])) { - if (NULL == (lp = tonebank[0]->tone[this_prog].layer)) + if (NULL == (ip = tonebank[0]->instrument[prog])) return; /* No instrument? Then we can't play. */ } - ip = lp->instrument; - if (ip->sample->note_to_use) /* Fixed-pitch instrument? */ - voice[i].orig_frequency = note_to_freq(ip->sample->note_to_use); - else - voice[i].orig_frequency = note_to_freq(this_note & 0x7F); } + if (ip->sample->scale_factor != 1024) + { + voice[i].orig_frequency = calculate_scaled_frequency(ip->sample, note & 0x7F); + } + else + { + voice[i].orig_frequency = note_to_freq(note & 0x7F); + } + select_sample(i, ip, vel); - select_stereo_samples(i, lp, this_velocity); - - played_note = voice[i].sample->note_to_use; - - if (!played_note || !drumsflag) played_note = this_note & 0x7f; -#if 0 - played_note = ( (played_note - voice[i].sample->freq_center) * voice[i].sample->freq_scale ) / 1024 + - voice[i].sample->freq_center; -#endif voice[i].status = VOICE_ON; - voice[i].channel = ch; - voice[i].note = played_note; - voice[i].velocity = this_velocity; + voice[i].channel = chan; + voice[i].note = note; + voice[i].velocity = vel; voice[i].sample_offset = 0; voice[i].sample_increment = 0; /* make sure it isn't negative */ @@ -953,160 +279,25 @@ void Renderer::start_note(int ch, int this_note, int this_velocity, int i) voice[i].vibrato_sweep = voice[i].sample->vibrato_sweep_increment; voice[i].vibrato_sweep_position = 0; - voice[i].vibrato_depth = voice[i].sample->vibrato_depth; voice[i].vibrato_control_ratio = voice[i].sample->vibrato_control_ratio; - voice[i].vibrato_control_counter = voice[i].vibrato_phase=0; -// voice[i].vibrato_delay = voice[i].sample->vibrato_delay; + voice[i].vibrato_control_counter = voice[i].vibrato_phase = 0; - kill_others(i); + kill_key_group(i); - for (j = 0; j < VIBRATO_SAMPLE_INCREMENTS; j++) - voice[i].vibrato_sample_increment[j] = 0; + memset(voice[i].vibrato_sample_increment, 0, sizeof(voice[i].vibrato_sample_increment)); - attacktime = channel[ch].attacktime; - releasetime = channel[ch].releasetime; - decaytime = 64; - variationbank = channel[ch].variationbank; - - switch (variationbank) + if (channel[chan].panning != NO_PANNING) { - case 8: - attacktime = 64+32; - break; - case 12: - decaytime = 64-32; - break; - case 16: - brightness = 64+16; - break; - case 17: - brightness = 64+32; - break; - case 18: - brightness = 64-16; - break; - case 19: - brightness = 64-32; - break; - case 20: - harmoniccontent = 64+16; - break; -#if 0 - case 24: - voice[i].modEnvToFilterFc=2.0; - voice[i].sample->cutoff_freq = 800; - break; - case 25: - voice[i].modEnvToFilterFc=-2.0; - voice[i].sample->cutoff_freq = 800; - break; - case 27: - voice[i].modLfoToFilterFc=2.0; - voice[i].lfo_phase_increment=109; - voice[i].lfo_sweep=122; - voice[i].sample->cutoff_freq = 800; - break; - case 28: - voice[i].modLfoToFilterFc=-2.0; - voice[i].lfo_phase_increment=109; - voice[i].lfo_sweep=122; - voice[i].sample->cutoff_freq = 800; - break; -#endif - default: - break; - } - - for (j = ATTACK; j < MAXPOINT; j++) - { - voice[i].envelope_rate[j] = voice[i].sample->envelope_rate[j]; - voice[i].envelope_offset[j] = voice[i].sample->envelope_offset[j]; - } - - voice[i].echo_delay = voice[i].envelope_rate[DELAY]; - voice[i].echo_delay_count = voice[i].echo_delay; - - if (attacktime != 64) - { - rt = voice[i].envelope_rate[ATTACK]; - rt = rt + ( (64-attacktime)*rt ) / 100; - if (rt > 1000) - { - voice[i].envelope_rate[ATTACK] = rt; - } - } - if (releasetime != 64) - { - rt = voice[i].envelope_rate[RELEASE]; - rt = rt + ( (64-releasetime)*rt ) / 100; - if (rt > 1000) - { - voice[i].envelope_rate[RELEASE] = rt; - } - } - if (decaytime != 64) - { - rt = voice[i].envelope_rate[DECAY]; - rt = rt + ( (64-decaytime)*rt ) / 100; - if (rt > 1000) - { - voice[i].envelope_rate[DECAY] = rt; - } - } - - if (channel[ch].panning != NO_PANNING) - { - voice[i].panning = channel[ch].panning; + voice[i].panning = channel[chan].panning; } else { voice[i].panning = voice[i].sample->panning; } - if (drumpan != NO_PANNING) - { - voice[i].panning = drumpan; - } - - if (variationbank == 1) - { - int pan = voice[i].panning; - int disturb = 0; - /* If they're close up (no reverb) and you are behind the pianist, - * high notes come from the right, so we'll spread piano etc. notes - * out horizontally according to their pitches. - */ - if (this_prog < 21) - { - int n = voice[i].velocity - 32; - if (n < 0) n = 0; - if (n > 64) n = 64; - pan = pan/2 + n; - } - /* For other types of instruments, the music sounds more alive if - * notes come from slightly different directions. However, instruments - * do drift around in a sometimes disconcerting way, so the following - * might not be such a good idea. - */ - else - { - disturb = (voice[i].velocity/32 % 8) + (voice[i].note % 8); /* /16? */ - } - - if (pan < 64) - { - pan += disturb; - } - else - { - pan -= disturb; - } - pan = pan < 0 ? 0 : pan > 127 ? 127 : pan; - voice[i].panning = pan | (pan << 7); - } recompute_freq(i); recompute_amp(&voice[i]); - if (voice[i].sample->modes & MODES_ENVELOPE) + if (voice[i].sample->modes & PATCH_NO_SRELEASE) { /* Ramp up from 0 */ voice[i].envelope_stage = ATTACK; @@ -1119,25 +310,13 @@ void Renderer::start_note(int ch, int this_note, int this_velocity, int i) voice[i].envelope_increment = 0; } apply_envelope_to_amp(&voice[i]); - - voice[i].clone_voice = -1; - voice[i].clone_type = NOT_CLONE; - - clone_voice(ip, i, this_note, this_velocity, STEREO_CLONE, variationbank); - clone_voice(ip, i, this_note, this_velocity, CHORUS_CLONE, variationbank); - clone_voice(ip, i, this_note, this_velocity, REVERB_CLONE, variationbank); } void Renderer::kill_note(int i) { voice[i].status = VOICE_DIE; - if (voice[i].clone_voice >= 0) - { - voice[ voice[i].clone_voice ].status = VOICE_DIE; - } } - /* Only one instance of a note can be playing on a single channel. */ void Renderer::note_on(int chan, int note, int vel) { @@ -1150,7 +329,7 @@ void Renderer::note_on(int chan, int note, int vel) { lowest = i; /* Can't get a lower volume than silence */ } - else if (voice[i].channel == chan && (voice[i].note == note || channel[chan].mono)) + else if (voice[i].channel == chan && ((voice[i].note == note && !voice[i].sample->self_nonexclusive) || channel[chan].mono)) { kill_note(i); } @@ -1169,10 +348,7 @@ void Renderer::note_on(int chan, int note, int vel) i = voices; while (i--) { - if ( (voice[i].status != VOICE_ON && - voice[i].status != VOICE_DIE && - voice[i].status != VOICE_FREE) && - (!voice[i].clone_type)) + if (voice[i].status != VOICE_ON && voice[i].status != VOICE_DIE) { v = voice[i].left_mix; if ((voice[i].panned == PANNED_MYSTERY) && (voice[i].right_mix > v)) @@ -1190,25 +366,10 @@ void Renderer::note_on(int chan, int note, int vel) if (lowest != -1) { - int cl = voice[lowest].clone_voice; - /* This can still cause a click, but if we had a free voice to - spare for ramping down this note, we wouldn't need to kill it - in the first place... Still, this needs to be fixed. Perhaps - we could use a reserve of voices to play dying notes only. */ - - if (cl >= 0) - { - if (voice[cl].clone_type == STEREO_CLONE || - (!voice[cl].clone_type && voice[lowest].clone_type == STEREO_CLONE)) - { - voice[cl].status = VOICE_FREE; - } - else if (voice[cl].clone_voice == lowest) - { - voice[cl].clone_voice = -1; - } - } + spare for ramping down this note, we wouldn't need to kill it + in the first place... Still, this needs to be fixed. Perhaps + we could use a reserve of voices to play dying notes only. */ cut_notes++; voice[lowest].status = VOICE_FREE; @@ -1222,7 +383,7 @@ void Renderer::note_on(int chan, int note, int vel) void Renderer::finish_note(int i) { - if (voice[i].sample->modes & MODES_ENVELOPE) + if (voice[i].sample->modes & PATCH_NO_SRELEASE) { /* We need to get the envelope out of Sustain stage */ voice[i].envelope_stage = RELEASE; @@ -1233,22 +394,15 @@ void Renderer::finish_note(int i) else { /* Set status to OFF so resample_voice() will let this voice out - of its loop, if any. In any case, this voice dies when it - hits the end of its data (ofs>=data_length). */ + of its loop, if any. In any case, this voice dies when it + hits the end of its data (ofs >= data_length). */ voice[i].status = VOICE_OFF; } - - int v; - if ( (v = voice[i].clone_voice) >= 0) - { - voice[i].clone_voice = -1; - finish_note(v); - } } void Renderer::note_off(int chan, int note, int vel) { - int i = voices, v; + int i = voices; while (i--) { if (voice[i].status == VOICE_ON && @@ -1258,32 +412,28 @@ void Renderer::note_off(int chan, int note, int vel) if (channel[chan].sustain) { voice[i].status = VOICE_SUSTAINED; - - if ( (v = voice[i].clone_voice) >= 0) - { - if (voice[v].status == VOICE_ON) - voice[v].status = VOICE_SUSTAINED; - } } else { finish_note(i); } - return; + if (!voice[i].sample->self_nonexclusive) + { + return; + } } } } /* Process the All Notes Off event */ -void Renderer::all_notes_off(int c) +void Renderer::all_notes_off(int chan) { int i = voices; - cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c); while (i--) { - if (voice[i].status == VOICE_ON && voice[i].channel == c) + if (voice[i].status == VOICE_ON && voice[i].channel == chan) { - if (channel[c].sustain) + if (channel[chan].sustain) { voice[i].status = VOICE_SUSTAINED; } @@ -1296,12 +446,12 @@ void Renderer::all_notes_off(int c) } /* Process the All Sounds Off event */ -void Renderer::all_sounds_off(int c) +void Renderer::all_sounds_off(int chan) { int i = voices; while (i--) { - if (voice[i].channel == c && + if (voice[i].channel == chan && voice[i].status != VOICE_FREE && voice[i].status != VOICE_DIE) { @@ -1322,55 +472,59 @@ void Renderer::adjust_pressure(int chan, int note, int amount) voice[i].velocity = amount; recompute_amp(&voice[i]); apply_envelope_to_amp(&voice[i]); - return; + if (!(voice[i].sample->self_nonexclusive)) + { + return; + } } } } -void Renderer::adjust_panning(int c) +void Renderer::adjust_panning(int chan) { int i = voices; while (i--) { - if ((voice[i].channel == c) && + if ((voice[i].channel == chan) && (voice[i].status == VOICE_ON || voice[i].status == VOICE_SUSTAINED)) { - if (voice[i].clone_type != NOT_CLONE) continue; - voice[i].panning = channel[c].panning; + voice[i].panning = channel[chan].panning; recompute_amp(&voice[i]); apply_envelope_to_amp(&voice[i]); } } } -void Renderer::drop_sustain(int c) +void Renderer::drop_sustain(int chan) { int i = voices; while (i--) { - if (voice[i].status == VOICE_SUSTAINED && voice[i].channel == c) + if (voice[i].status == VOICE_SUSTAINED && voice[i].channel == chan) + { finish_note(i); + } } } -void Renderer::adjust_pitchbend(int c) +void Renderer::adjust_pitchbend(int chan) { int i = voices; while (i--) { - if (voice[i].status != VOICE_FREE && voice[i].channel == c) + if (voice[i].status != VOICE_FREE && voice[i].channel == chan) { recompute_freq(i); } } } -void Renderer::adjust_volume(int c) +void Renderer::adjust_volume(int chan) { int i = voices; while (i--) { - if (voice[i].channel == c && + if (voice[i].channel == chan && (voice[i].status == VOICE_ON || voice[i].status == VOICE_SUSTAINED)) { recompute_amp(&voice[i]); @@ -1387,7 +541,6 @@ void Renderer::HandleEvent(int status, int parm1, int parm2) switch (command) { case ME_NOTEON: - parm1 += channel[chan].transpose; if (parm2 == 0) { note_off(chan, parm1, 0); @@ -1399,7 +552,6 @@ void Renderer::HandleEvent(int status, int parm1, int parm2) break; case ME_NOTEOFF: - parm1 += channel[chan].transpose; note_off(chan, parm1, parm2); break; @@ -1412,8 +564,8 @@ void Renderer::HandleEvent(int status, int parm1, int parm2) break; case ME_PROGRAM: - /* if (ISDRUMCHANNEL(chan)) { */ - if (channel[chan].kit) { + if (ISDRUMCHANNEL(chan)) + { /* Change drum set */ channel[chan].bank = parm1; } @@ -1447,29 +599,13 @@ void Renderer::HandleController(int chan, int ctrl, int val) continuous controller. This will cause lots of warnings about undefined tone banks. */ case CTRL_BANK_SELECT: - if (XG_System_On) - { - if (val == SFX_BANKTYPE) - { - channel[chan].sfx = SFXBANK; - channel[chan].kit = 0; - } - else - { - channel[chan].sfx = 0; - channel[chan].kit = val; - } - } - else - { - channel[chan].bank = val; - } + channel[chan].bank = val; break; case CTRL_BANK_SELECT+32: - if (XG_System_On) + if (val == 0) { - channel[chan].bank = val; + channel[chan].bank = 0; } break; @@ -1495,18 +631,12 @@ void Renderer::HandleController(int chan, int ctrl, int val) case CTRL_PAN: channel[chan].panning = (channel[chan].panning & 0x007F) | (val << 7); - if (adjust_panning_immediately) - { - adjust_panning(chan); - } + adjust_panning(chan); break; case CTRL_PAN+32: channel[chan].panning = (channel[chan].panning & 0x3F80) | (val); - if (adjust_panning_immediately) - { - adjust_panning(chan); - } + adjust_panning(chan); break; case CTRL_SUSTAIN: @@ -1517,30 +647,6 @@ void Renderer::HandleController(int chan, int ctrl, int val) } break; - case CTRL_HARMONICCONTENT: - channel[chan].harmoniccontent = val; - break; - - case CTRL_RELEASETIME: - channel[chan].releasetime = val; - break; - - case CTRL_ATTACKTIME: - channel[chan].attacktime = val; - break; - - case CTRL_BRIGHTNESS: - channel[chan].brightness = val; - break; - - case CTRL_REVERBERATION: - channel[chan].reverberation = val; - break; - - case CTRL_CHORUSDEPTH: - channel[chan].chorusdepth = val; - break; - case CTRL_NRPN_LSB: channel[chan].nrpn = (channel[chan].nrpn & 0x3F80) | (val); channel[chan].nrpn_mode = true; @@ -1623,47 +729,12 @@ void Renderer::DataEntryFineRPN(int chan, int rpn, int val) } } -// [RH] Q. What device are we pretending to be by responding to these NRPNs? void Renderer::DataEntryCoarseNRPN(int chan, int nrpn, int val) { - switch (nrpn & 0x3F80) - { - case 0x0080: - if (nrpn == NRPN_BRIGHTNESS) - { - channel[chan].brightness = val; - } - else if (nrpn == NRPN_HARMONICCONTENT) - { - channel[chan].harmoniccontent = val; - } - break; - - case NRPN_DRUMVOLUME: - drumvolume[chan][nrpn & 0x007F] = val; - break; - - case NRPN_DRUMPANPOT: - if (val == 0) - { - val = 127 * rand() / RAND_MAX; - } - drumpanpot[chan][nrpn & 0x007F] = val; - break; - - case NRPN_DRUMREVERBERATION: - drumreverberation[chan][nrpn & 0x007F] = val; - break; - - case NRPN_DRUMCHORUSDEPTH: - drumchorusdepth[chan][nrpn & 0x007F] = val; - break; - } } void Renderer::DataEntryFineNRPN(int chan, int nrpn, int val) { - // We don't care about fine data entry for any NRPN at this time. } void Renderer::HandleLongMessage(const BYTE *data, int len) @@ -1673,25 +744,7 @@ void Renderer::HandleLongMessage(const BYTE *data, int len) void Renderer::Reset() { - int i; - lost_notes = cut_notes = 0; - GM_System_On = GS_System_On = XG_System_On = 0; - XG_System_reverb_type = XG_System_chorus_type = XG_System_variation_type = 0; - memset(&drumvolume, -1, sizeof(drumvolume)); - memset(&drumchorusdepth, -1, sizeof(drumchorusdepth)); - memset(&drumreverberation, -1, sizeof(drumreverberation)); - memset(&drumpanpot, NO_PANNING, sizeof(drumpanpot)); - for (i = 0; i < MAXCHAN; ++i) - { - channel[i].kit = ISDRUMCHANNEL(i) ? 127 : 0; - channel[i].brightness = 64; - channel[i].harmoniccontent = 64; - channel[i].variationbank = 0; - channel[i].chorusdepth = 0; - channel[i].reverberation = 0; - channel[i].transpose = 0; - } reset_midi(); } diff --git a/src/timidity/resample.cpp b/src/timidity/resample.cpp index 13180da93..5569eea56 100644 --- a/src/timidity/resample.cpp +++ b/src/timidity/resample.cpp @@ -215,12 +215,12 @@ static sample_t *rs_bidir(sample_t *resample_buffer, Voice *vp, int count) /* We only need to compute one half of the vibrato sine cycle */ static int vib_phase_to_inc_ptr(int phase) { - if (phase < VIBRATO_SAMPLE_INCREMENTS/2) - return VIBRATO_SAMPLE_INCREMENTS/2-1-phase; - else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2) - return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase; + if (phase < VIBRATO_SAMPLE_INCREMENTS / 2) + return VIBRATO_SAMPLE_INCREMENTS / 2 - 1 - phase; + else if (phase >= VIBRATO_SAMPLE_INCREMENTS * 3 / 2) + return VIBRATO_SAMPLE_INCREMENTS * 5 / 2 - 1 - phase; else - return phase-VIBRATO_SAMPLE_INCREMENTS/2; + return phase - VIBRATO_SAMPLE_INCREMENTS / 2; } static int update_vibrato(float output_rate, Voice *vp, int sign) @@ -229,8 +229,8 @@ static int update_vibrato(float output_rate, Voice *vp, int sign) int phase; double a, pb; - if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1) - vp->vibrato_phase=0; + if (vp->vibrato_phase++ >= 2 * VIBRATO_SAMPLE_INCREMENTS - 1) + vp->vibrato_phase = 0; phase = vib_phase_to_inc_ptr(vp->vibrato_phase); if (vp->vibrato_sample_increment[phase]) @@ -244,7 +244,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign) /* Need to compute this sample increment. */ depth = vp->sample->vibrato_depth << 7; - if (vp->vibrato_sweep) + if (vp->vibrato_sweep != 0) { /* Need to update sweep */ vp->vibrato_sweep_position += vp->vibrato_sweep; @@ -265,7 +265,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign) pb = (sine(vp->vibrato_phase * (1.0/(2*VIBRATO_SAMPLE_INCREMENTS))) * (double)(depth) * VIBRATO_AMPLITUDE_TUNING); - a *= pow(2.0, pb / (8191 * 12.f)); + a *= pow(2.0, pb / (8192 * 12.f)); /* If the sweep's over, we can store the newly computed sample_increment */ if (!vp->vibrato_sweep) @@ -511,11 +511,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr) if (vp->vibrato_control_ratio) { - if ((modes & MODES_LOOPING) && - ((modes & MODES_ENVELOPE) || + if ((modes & PATCH_LOOPEN) && + ((modes & PATCH_NO_SRELEASE) || (vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED))) { - if (modes & MODES_PINGPONG) + if (modes & PATCH_BIDIR) return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr); else return rs_vib_loop(song->resample_buffer, song->rate, vp, *countptr); @@ -527,11 +527,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr) } else { - if ((modes & MODES_LOOPING) && - ((modes & MODES_ENVELOPE) || + if ((modes & PATCH_LOOPEN) && + ((modes & PATCH_NO_SRELEASE) || (vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED))) { - if (modes & MODES_PINGPONG) + if (modes & PATCH_BIDIR) return rs_bidir(song->resample_buffer, vp, *countptr); else return rs_loop(song->resample_buffer, vp, *countptr); @@ -554,11 +554,14 @@ void pre_resample(Renderer *song, Sample *sp) "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; - 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); + if (sp->scale_factor != 0) + return; - a = (sp->sample_rate * note_to_freq(sp->note_to_use)) / (sp->root_freq * song->rate); + cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)\n", + sp->scale_note, + note_name[sp->scale_note % 12], (sp->scale_note & 0x7F) / 12); + + a = (sp->sample_rate * note_to_freq(sp->scale_note)) / (sp->root_freq * song->rate); if (a <= 0) return; newlen = (int)(sp->data_length / a); diff --git a/src/timidity/timidity.cpp b/src/timidity/timidity.cpp index 19fd0cdda..24c4725d2 100644 --- a/src/timidity/timidity.cpp +++ b/src/timidity/timidity.cpp @@ -413,6 +413,13 @@ void FreeAll() int LoadConfig(const char *filename) { + /* !!! FIXME: This may be ugly, but slightly less so than requiring the + * default search path to have only one element. I think. + * + * We only need to include the likely locations for the config + * file itself since that file should contain any other directory + * that needs to be added to the search path. + */ clear_pathlist(); #ifdef _WIN32 add_to_pathlist("C:\\TIMIDITY"); @@ -443,25 +450,21 @@ Renderer::Renderer(float sample_rate) { rate = sample_rate; patches = NULL; - default_instrument = NULL; -#ifdef FAST_DECAY - fast_decay = true; -#else - fast_decay = false; -#endif resample_buffer_size = 0; resample_buffer = NULL; + adjust_panning_immediately = false; control_ratio = clamp(int(rate / CONTROLS_PER_SECOND), 1, MAX_CONTROL_RATIO); + + lost_notes = 0; + cut_notes = 0; + + default_instrument = NULL; + default_program = DEFAULT_PROGRAM; if (def_instr_name.IsNotEmpty()) set_default_instrument(def_instr_name); voices = DEFAULT_VOICES; - memset(voice, 0, sizeof(voice)); - memset(drumvolume, 0, sizeof(drumvolume)); - memset(drumpanpot, 0, sizeof(drumpanpot)); - memset(drumreverberation, 0, sizeof(drumreverberation)); - memset(drumchorusdepth, 0, sizeof(drumchorusdepth)); drumchannels = DEFAULT_DRUMCHANNELS; } @@ -492,22 +495,7 @@ void Renderer::ComputeOutput(float *buffer, int count) { if (v->status != VOICE_FREE) { - if (v->sample_offset == 0 && v->echo_delay_count) - { - if (v->echo_delay_count >= count) - { - v->echo_delay_count -= count; - } - else - { - mix_voice(this, buffer + v->echo_delay_count, v, count - v->echo_delay_count); - v->echo_delay_count = 0; - } - } - else - { - mix_voice(this, buffer, v, count); - } + mix_voice(this, buffer, v, count); } } } @@ -520,6 +508,11 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr) { return; } + if (banknum != 0) + { + /* Mark the standard bank in case it's not defined by this one. */ + MarkInstrument(0, percussion, instr); + } if (percussion) { bank = drumset[banknum]; @@ -532,9 +525,9 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr) { return; } - if (bank->tone[instr].layer == NULL) + if (bank->instrument[instr] == NULL) { - bank->tone[instr].layer = MAGIC_LOAD_INSTRUMENT; + bank->instrument[instr] = MAGIC_LOAD_INSTRUMENT; } } @@ -557,9 +550,6 @@ void cmsg(int type, int verbosity_level, const char *fmt, ...) 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 4ba2233bb..2fbfb6848 100644 --- a/src/timidity/timidity.h +++ b/src/timidity/timidity.h @@ -33,33 +33,27 @@ config.h */ /* Acoustic Grand Piano seems to be the usual default instrument. */ -#define DEFAULT_PROGRAM 0 +#define DEFAULT_PROGRAM 0 /* 9 here is MIDI channel 10, which is the standard percussion channel. Some files (notably C:\WINDOWS\CANYON.MID) think that 16 is one too. On the other hand, some files know that 16 is not a drum channel and try to play music on it. This is now a runtime option, so this isn't a critical choice anymore. */ -#define DEFAULT_DRUMCHANNELS (1<<9) -/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/ +#define DEFAULT_DRUMCHANNELS (1<<9) +/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/ -/* Default sampling rate, default polyphony, and maximum polyphony. - All but the last can be overridden from the command line. */ -#define DEFAULT_RATE 32000 -#define DEFAULT_VOICES 32 -#define MAX_VOICES 256 -#define MAXCHAN 16 -#define MAXNOTE 128 +/* Default polyphony, and maximum polyphony. */ +#define DEFAULT_VOICES 32 +#define MAX_VOICES 256 + +#define MAXCHAN 16 +#define MAXNOTE 128 /* 1000 here will give a control ratio of 22:1 with 22 kHz output. Higher CONTROLS_PER_SECOND values allow more accurate rendering of envelopes and tremolo. The cost is CPU time. */ -#define CONTROLS_PER_SECOND 1000 - -/* Make envelopes twice as fast. Saves ~20% CPU time (notes decay - faster) and sounds more like a GUS. There is now a command line - option to toggle this as well. */ -//#define FAST_DECAY +#define CONTROLS_PER_SECOND 1000 /* How many bits to use for the fractional part of sample positions. This affects tonal accuracy. The entire position counter must fit @@ -67,7 +61,7 @@ config.h a sample is 1048576 samples (2 megabytes in memory). The GUS gets by with just 9 bits and a little help from its friends... "The GUS does not SUCK!!!" -- a happy user :) */ -#define FRACTION_BITS 12 +#define FRACTION_BITS 12 /* For some reason the sample volume is always set to maximum in all patch files. Define this for a crude adjustment that may help @@ -76,7 +70,7 @@ config.h /* The number of samples to use for ramping out a dying note. Affects click removal. */ -#define MAX_DIE_TIME 20 +#define MAX_DIE_TIME 20 /**************************************************************************/ /* Anything below this shouldn't need to be changed unless you're porting @@ -84,37 +78,37 @@ config.h /**************************************************************************/ /* change FRACTION_BITS above, not these */ -#define INTEGER_BITS (32 - FRACTION_BITS) -#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS) -#define FRACTION_MASK (~ INTEGER_MASK) -#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS) +#define INTEGER_BITS (32 - FRACTION_BITS) +#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS) +#define FRACTION_MASK (~ INTEGER_MASK) +#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS) /* This is enforced by some computations that must fit in an int */ -#define MAX_CONTROL_RATIO 255 +#define MAX_CONTROL_RATIO 255 -#define MAX_AMPLIFICATION 800 +#define MAX_AMPLIFICATION 800 /* The TiMiditiy configuration file */ #define CONFIG_FILE "timidity.cfg" typedef float sample_t; typedef float final_volume_t; -#define FINAL_VOLUME(v) (v) +#define FINAL_VOLUME(v) (v) -#define FSCALE(a,b) ((a) * (float)(1<<(b))) -#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b)))) +#define FSCALE(a,b) ((a) * (float)(1<<(b))) +#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b)))) /* Vibrato and tremolo Choices of the Day */ -#define SWEEP_TUNING 38 -#define VIBRATO_AMPLITUDE_TUNING 1.0L -#define VIBRATO_RATE_TUNING 38 -#define TREMOLO_AMPLITUDE_TUNING 1.0L -#define TREMOLO_RATE_TUNING 38 +#define SWEEP_TUNING 38 +#define VIBRATO_AMPLITUDE_TUNING 1.0 +#define VIBRATO_RATE_TUNING 38 +#define TREMOLO_AMPLITUDE_TUNING 1.0 +#define TREMOLO_RATE_TUNING 38 -#define SWEEP_SHIFT 16 -#define RATE_SHIFT 5 +#define SWEEP_SHIFT 16 +#define RATE_SHIFT 5 -#define VIBRATO_SAMPLE_INCREMENTS 32 +#define VIBRATO_SAMPLE_INCREMENTS 32 #ifndef PI #define PI 3.14159265358979323846 @@ -188,21 +182,20 @@ FileReader *open_filereader(const char *name, int open, int *plumpnum); controls.h */ -#define CMSG_INFO 0 -#define CMSG_WARNING 1 -#define CMSG_ERROR 2 -#define CMSG_FATAL 3 -#define CMSG_TRACE 4 -#define CMSG_TIME 5 -#define CMSG_TOTAL 6 -#define CMSG_FILE 7 -#define CMSG_TEXT 8 +enum +{ + CMSG_INFO, + CMSG_WARNING, + CMSG_ERROR +}; -#define VERB_NORMAL 0 -#define VERB_VERBOSE 1 -#define VERB_NOISY 2 -#define VERB_DEBUG 3 -#define VERB_DEBUG_SILLY 4 +enum +{ + VERB_NORMAL, + VERB_VERBOSE, + VERB_NOISY, + VERB_DEBUG +}; void cmsg(int type, int verbosity_level, const char *fmt, ...); @@ -217,114 +210,174 @@ struct Sample loop_start, loop_end, data_length, sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq; SDWORD - envelope_rate[7], envelope_offset[7]; + envelope_rate[6], envelope_offset[6]; float - modulation_rate[7], modulation_offset[7]; - float - volume, resonance, - modEnvToFilterFc, modEnvToPitch, modLfoToFilterFc; + volume; sample_t *data; SDWORD tremolo_sweep_increment, tremolo_phase_increment, - lfo_sweep_increment, lfo_phase_increment, - vibrato_sweep_increment, vibrato_control_ratio, - cutoff_freq; + vibrato_sweep_increment, vibrato_control_ratio; BYTE - reverberation, chorusdepth, tremolo_depth, vibrato_depth, - modes, - attenuation; + modes; WORD - freq_center, panning; - SBYTE - note_to_use, exclusiveClass; + panning, scale_factor; SWORD - keyToModEnvHold, keyToModEnvDecay, - keyToVolEnvHold, keyToVolEnvDecay; - SDWORD - freq_scale; + scale_note; + bool + self_nonexclusive; + BYTE + key_group; }; void convert_sample_data(Sample *sample, const void *data); void free_instruments(); -/* Bits in modes: */ -#define MODES_16BIT (1<<0) -#define MODES_UNSIGNED (1<<1) -#define MODES_LOOPING (1<<2) -#define MODES_PINGPONG (1<<3) -#define MODES_REVERSE (1<<4) -#define MODES_SUSTAIN (1<<5) -#define MODES_ENVELOPE (1<<6) -#define MODES_FAST_RELEASE (1<<7) +/* Patch definition: */ +enum +{ + HEADER_SIZE = 12, + ID_SIZE = 10, + DESC_SIZE = 60, + RESERVED_SIZE = 40, + PATCH_HEADER_RESERVED_SIZE = 36, + LAYER_RESERVED_SIZE = 40, + PATCH_DATA_RESERVED_SIZE = 36, + INST_NAME_SIZE = 16, + ENVELOPES = 6, + MAX_LAYERS = 4 +}; +#define GF1_HEADER_TEXT "GF1PATCH110" -#define INST_GUS 0 -#define INST_SF2 1 -#define INST_DLS 2 +enum +{ + PATCH_16 = (1<<0), + PATCH_UNSIGNED = (1<<1), + PATCH_LOOPEN = (1<<2), + PATCH_BIDIR = (1<<3), + PATCH_BACKWARD = (1<<4), + PATCH_SUSTAIN = (1<<5), + PATCH_NO_SRELEASE = (1<<6), + PATCH_FAST_REL = (1<<7) +}; + +#ifdef _MSC_VER +#pragma pack(push, 1) +#define GCC_PACKED +#else +#define GCC_PACKED __attribute__((__packed__)) +#endif + +struct GF1PatchHeader +{ + char Header[HEADER_SIZE]; + char GravisID[ID_SIZE]; /* Id = "ID#000002" */ + char Description[DESC_SIZE]; + BYTE Instruments; + BYTE Voices; + BYTE Channels; + WORD WaveForms; + WORD MasterVolume; + DWORD DataSize; + BYTE Reserved[PATCH_HEADER_RESERVED_SIZE]; +} GCC_PACKED; + +struct GF1InstrumentData +{ + WORD Instrument; + char InstrumentName[INST_NAME_SIZE]; + int InstrumentSize; + BYTE Layers; + BYTE Reserved[RESERVED_SIZE]; +} GCC_PACKED; + +struct GF1LayerData +{ + BYTE LayerDuplicate; + BYTE Layer; + int LayerSize; + BYTE Samples; + BYTE Reserved[LAYER_RESERVED_SIZE]; +} GCC_PACKED; + +struct GF1PatchData +{ + char WaveName[7]; + BYTE Fractions; + int WaveSize; + int StartLoop; + int EndLoop; + WORD SampleRate; + int LowFrequency; + int HighFrequency; + int RootFrequency; + SWORD Tune; + BYTE Balance; + BYTE EnvelopeRate[6]; + BYTE EnvelopeOffset[6]; + BYTE TremoloSweep; + BYTE TremoloRate; + BYTE TremoloDepth; + BYTE VibratoSweep; + BYTE VibratoRate; + BYTE VibratoDepth; + BYTE Modes; + SWORD ScaleFrequency; + WORD ScaleFactor; /* From 0 to 2048 or 0 to 2 */ + BYTE Reserved[PATCH_DATA_RESERVED_SIZE]; +} GCC_PACKED; +#ifdef _MSC_VER +#pragma pack(pop) +#endif +#undef GCC_PACKED + +enum +{ + INST_GUS, + INST_DLS +}; struct Instrument { + Instrument(); + ~Instrument(); + int type; int samples; Sample *sample; - int left_samples; - Sample *left_sample; - int right_samples; - Sample *right_sample; }; -struct InstrumentLayer -{ - BYTE lo, hi; - Instrument *instrument; - InstrumentLayer *next; -}; - -struct cfg_type -{ - int font_code; - int num; - const char *name; -}; - -#define FONT_NORMAL 0 -#define FONT_FFF 1 -#define FONT_SBK 2 -#define FONT_TONESET 3 -#define FONT_DRUMSET 4 -#define FONT_PRESET 5 - struct ToneBankElement { - ToneBankElement() : layer(NULL), font_type(0), sf_ix(0), tuning(0), + ToneBankElement() : note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0) {} FString name; - InstrumentLayer *layer; - int font_type, sf_ix, tuning; int note, amp, pan, strip_loop, strip_envelope, strip_tail; }; /* A hack to delay instrument loading until after reading the entire MIDI file. */ -#define MAGIC_LOAD_INSTRUMENT ((InstrumentLayer *)(-1)) +#define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1)) -#define MAXPROG 128 -#define MAXBANK 130 -#define SFXBANK (MAXBANK-1) -#define SFXDRUM1 (MAXBANK-2) -#define SFXDRUM2 (MAXBANK-1) -#define XGDRUM 1 +enum +{ + MAXPROG = 128, + MAXBANK = 128 +}; struct ToneBank { - FString name; - ToneBankElement tone[MAXPROG]; + ToneBank(); + ~ToneBank(); + + ToneBankElement *tone; + Instrument *instrument[MAXPROG]; }; -#define SPECIAL_PROGRAM -1 +#define SPECIAL_PROGRAM -1 extern void pcmap(int *b, int *v, int *p, int *drums); @@ -341,60 +394,55 @@ playmidi.h */ /* Midi events */ -#define ME_NOTEOFF 0x80 -#define ME_NOTEON 0x90 -#define ME_KEYPRESSURE 0xA0 -#define ME_CONTROLCHANGE 0xB0 -#define ME_PROGRAM 0xC0 -#define ME_CHANNELPRESSURE 0xD0 -#define ME_PITCHWHEEL 0xE0 +enum +{ + ME_NOTEOFF = 0x80, + ME_NOTEON = 0x90, + ME_KEYPRESSURE = 0xA0, + ME_CONTROLCHANGE = 0xB0, + ME_PROGRAM = 0xC0, + ME_CHANNELPRESSURE = 0xD0, + ME_PITCHWHEEL = 0xE0 +}; /* Controllers */ -#define CTRL_BANK_SELECT 0 -#define CTRL_DATA_ENTRY 6 -#define CTRL_VOLUME 7 -#define CTRL_PAN 10 -#define CTRL_EXPRESSION 11 -#define CTRL_SUSTAIN 64 -#define CTRL_HARMONICCONTENT 71 -#define CTRL_RELEASETIME 72 -#define CTRL_ATTACKTIME 73 -#define CTRL_BRIGHTNESS 74 -#define CTRL_REVERBERATION 91 -#define CTRL_CHORUSDEPTH 93 -#define CTRL_NRPN_LSB 98 -#define CTRL_NRPN_MSB 99 -#define CTRL_RPN_LSB 100 -#define CTRL_RPN_MSB 101 -#define CTRL_ALL_SOUNDS_OFF 120 -#define CTRL_RESET_CONTROLLERS 121 -#define CTRL_ALL_NOTES_OFF 123 - -/* NRPNs */ -#define NRPN_BRIGHTNESS 0x00A0 -#define NRPN_HARMONICCONTENT 0x00A1 -#define NRPN_DRUMVOLUME (26<<7) // drum number in low 7 bits -#define NRPN_DRUMPANPOT (28<<7) // " -#define NRPN_DRUMREVERBERATION (29<<7) // " -#define NRPN_DRUMCHORUSDEPTH (30<<7) // " +enum +{ + CTRL_BANK_SELECT = 0, + CTRL_DATA_ENTRY = 6, + CTRL_VOLUME = 7, + CTRL_PAN = 10, + CTRL_EXPRESSION = 11, + CTRL_SUSTAIN = 64, + CTRL_HARMONICCONTENT = 71, + CTRL_RELEASETIME = 72, + CTRL_ATTACKTIME = 73, + CTRL_BRIGHTNESS = 74, + CTRL_REVERBERATION = 91, + CTRL_CHORUSDEPTH = 93, + CTRL_NRPN_LSB = 98, + CTRL_NRPN_MSB = 99, + CTRL_RPN_LSB = 100, + CTRL_RPN_MSB = 101, + CTRL_ALL_SOUNDS_OFF = 120, + CTRL_RESET_CONTROLLERS = 121, + CTRL_ALL_NOTES_OFF = 123 +}; /* RPNs */ -#define RPN_PITCH_SENS 0x0000 -#define RPN_FINE_TUNING 0x0001 -#define RPN_COARSE_TUNING 0x0002 -#define RPN_RESET 0x3fff - -#define SFX_BANKTYPE 64 +enum +{ + RPN_PITCH_SENS = 0x0000, + RPN_FINE_TUNING = 0x0001, + RPN_COARSE_TUNING = 0x0002, + RPN_RESET = 0x3fff +}; struct Channel { int bank, program, sustain, pitchbend, mono, /* one note only on this channel -- not implemented yet */ - /* new stuff */ - variationbank, reverberation, chorusdepth, harmoniccontent, - releasetime, attacktime, brightness, kit, sfx, - /* end new */ pitchsens; WORD volume, expression; @@ -404,84 +452,71 @@ struct Channel rpn, nrpn; bool nrpn_mode; - char - transpose; float pitchfactor; /* precomputed pitch bend factor to save some fdiv's */ }; /* Causes the instrument's default panning to be used. */ -#define NO_PANNING -1 +#define NO_PANNING -1 /* envelope points */ -#define MAXPOINT 7 +#define MAXPOINT 6 struct Voice { BYTE - status, channel, note, velocity, clone_type; + status, channel, note, velocity; Sample *sample; - Sample *left_sample; - Sample *right_sample; - int clone_voice; float orig_frequency, frequency; int - sample_offset, loop_start, loop_end; - int - envelope_volume, modulation_volume; - int - envelope_target, modulation_target; - int - tremolo_sweep, tremolo_sweep_position, tremolo_phase, - lfo_sweep, lfo_sweep_position, lfo_phase, - vibrato_sweep, vibrato_sweep_position, vibrato_depth, - echo_delay_count; - int - echo_delay, - sample_increment, - envelope_increment, - modulation_increment, - tremolo_phase_increment, - lfo_phase_increment; + sample_offset, sample_increment, + envelope_volume, envelope_target, envelope_increment, + tremolo_sweep, tremolo_sweep_position, + tremolo_phase, tremolo_phase_increment, + vibrato_sweep, vibrato_sweep_position; final_volume_t left_mix, right_mix; float - left_amp, right_amp, - volume, tremolo_volume, lfo_volume; + left_amp, right_amp, tremolo_volume; int vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS]; - int - envelope_rate[MAXPOINT], envelope_offset[MAXPOINT]; int vibrato_phase, vibrato_control_ratio, vibrato_control_counter, - envelope_stage, modulation_stage, control_counter, - modulation_delay, modulation_counter, panning, panned; + envelope_stage, control_counter, panning, panned; }; /* Voice status options: */ -#define VOICE_FREE 0 -#define VOICE_ON 1 -#define VOICE_SUSTAINED 2 -#define VOICE_OFF 3 -#define VOICE_DIE 4 +enum +{ + VOICE_FREE, + VOICE_ON, + VOICE_SUSTAINED, + VOICE_OFF, + VOICE_DIE +}; /* Voice panned options: */ -#define PANNED_MYSTERY 0 -#define PANNED_LEFT 1 -#define PANNED_RIGHT 2 -#define PANNED_CENTER 3 +enum +{ + PANNED_MYSTERY, + PANNED_LEFT, + PANNED_RIGHT, + PANNED_CENTER +}; /* Anything but PANNED_MYSTERY only uses the left volume */ /* Envelope stages: */ -#define ATTACK 0 -#define HOLD 1 -#define DECAY 2 -#define RELEASE 3 -#define RELEASEB 4 -#define RELEASEC 5 -#define DELAY 6 +enum +{ + ATTACK, + HOLD, + DECAY, + RELEASE, + RELEASEB, + RELEASEC +}; #define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c)))) @@ -498,9 +533,7 @@ tables.h #define sine(x) (sin((2*PI/1024.0) * (x))) #define note_to_freq(x) (float(8175.7989473096690661233836992789 * pow(2.0, (x) / 12.0))) -#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0))) - -#define XMAPMAX 800 +#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0))) /* timidity.h @@ -517,27 +550,16 @@ struct Renderer { float rate; DLS_Data *patches; - InstrumentLayer *default_instrument; + Instrument *default_instrument; int default_program; - bool fast_decay; int resample_buffer_size; sample_t *resample_buffer; Channel channel[16]; Voice voice[MAX_VOICES]; - signed char drumvolume[MAXCHAN][MAXNOTE]; - signed char drumpanpot[MAXCHAN][MAXNOTE]; - signed char drumreverberation[MAXCHAN][MAXNOTE]; - signed char drumchorusdepth[MAXCHAN][MAXNOTE]; int control_ratio, amp_with_poly; int drumchannels; int adjust_panning_immediately; int voices; - int GM_System_On; - int XG_System_On; - int GS_System_On; - int XG_System_reverb_type; - int XG_System_chorus_type; - int XG_System_variation_type; int lost_notes, cut_notes; Renderer(float sample_rate); @@ -558,10 +580,8 @@ struct Renderer int convert_vibrato_rate(BYTE rate); void recompute_amp(Voice *v); - int vc_alloc(int not_this_voice); - void kill_others(int voice); - void clone_voice(Instrument *ip, int v, int note, int vel, int clone_type, int variationbank); - void xremap(int *banknumpt, int *this_notept, int this_kit); + void kill_key_group(int voice); + float calculate_scaled_frequency(Sample *sample, int note); void start_note(int chan, int note, int vel, int voice); void note_on(int chan, int note, int vel); @@ -579,7 +599,6 @@ struct Renderer void reset_midi(); void select_sample(int voice, Instrument *instr, int vel); - void select_stereo_samples(int voice, InstrumentLayer *layer, int vel); void recompute_freq(int voice); void kill_note(int voice);