From 565af6b95abf99664b12dc1b5cfc39f9b5e6f2f8 Mon Sep 17 00:00:00 2001 From: Luis Michaelis Date: Mon, 29 Apr 2024 18:43:35 +0200 Subject: [PATCH] fix(DmSynth,tsf): alter TSF to allow for weighing mixed PCM This patch drastically improves the volume issues we're having with some soundtracks, though it does not fully solve it. --- src/Synth.c | 8 ++++---- vendor/TinySoundFont/tsf.h | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Synth.c b/src/Synth.c index 1ae8b84..caf472e 100644 --- a/src/Synth.c +++ b/src/Synth.c @@ -102,6 +102,8 @@ void DmSynth_sendBandUpdate(DmSynth* slf, DmBand* band) { float pan = (ins->flags & DmInstrument_PAN) ? (float) ins->pan / DmInt_MIDI_MAX : DmInt_PAN_CENTER; float vol = (ins->flags & DmInstrument_VOLUME) ? (float) ins->volume / DmInt_MIDI_MAX : DmInt_VOLUME_MAX; + tsf_set_volume(t, 1.0f); + bool res = tsf_channel_set_pan(t, 0, pan); if (!res) { Dm_report(DmLogLevel_ERROR, "DmSynth: tsf_channel_set_pan encountered an error."); @@ -241,12 +243,10 @@ size_t DmSynth_render(DmSynth* slf, void* buf, size_t len, DmRenderOptions fmt) tsf_set_output(slf->channels[i].synth, TSF_MONO, 44100, 0); } - tsf_set_volume(slf->channels[i].synth, slf->channels[i].volume); - if (fmt & DmRender_FLOAT) { - tsf_render_float(slf->channels[i].synth, buf, (int) len / channels, true); + tsf_render_float(slf->channels[i].synth, buf, (int) len / channels, true, slf->channels[i].volume); } else { - tsf_render_short(slf->channels[i].synth, buf, (int) len / channels, true); + tsf_render_short(slf->channels[i].synth, buf, (int) len / channels, true, slf->channels[i].volume); } } diff --git a/vendor/TinySoundFont/tsf.h b/vendor/TinySoundFont/tsf.h index f6c0db9..7e194ba 100644 --- a/vendor/TinySoundFont/tsf.h +++ b/vendor/TinySoundFont/tsf.h @@ -167,8 +167,8 @@ TSFDEF int tsf_active_voice_count(tsf* f); // buffer: target buffer of size samples * output_channels * sizeof(type) // samples: number of samples to render // flag_mixing: if 0 clear the buffer first, otherwise mix into existing data -TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing CPP_DEFAULT0); -TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing CPP_DEFAULT0); +TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing, float factor); +TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing, float factor); // Higher level channel based functions, set up channel parameters // channel: channel number @@ -1172,7 +1172,7 @@ static void tsf_voice_calcpitchratio(struct tsf_voice* v, float pitchShift, floa v->pitchOutputFactor = v->region->sample_rate / (tsf_timecents2Secsd(v->region->pitch_keycenter * 100.0) * outSampleRate); } -static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, int numSamples) +static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, int numSamples, float factor) { struct tsf_region* region = v->region; float* input = f->fontSamples; @@ -1252,8 +1252,8 @@ static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, i // Low-pass filter. if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val); - *outL++ += val * gainLeft; - *outL++ += val * gainRight; + *outL++ += val * gainLeft * factor; + *outL++ += val * gainRight * factor; // Next sample. tmpSourceSamplePosition += pitchRatio; @@ -1273,8 +1273,8 @@ static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, i // Low-pass filter. if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val); - *outL++ += val * gainLeft; - *outR++ += val * gainRight; + *outL++ += val * gainLeft * factor; + *outR++ += val * gainRight * factor; // Next sample. tmpSourceSamplePosition += pitchRatio; @@ -1293,7 +1293,7 @@ static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, i // Low-pass filter. if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val); - *outL++ += val * gainMono; + *outL++ += val * gainMono * factor; // Next sample. tmpSourceSamplePosition += pitchRatio; @@ -1661,7 +1661,7 @@ TSFDEF int tsf_active_voice_count(tsf* f) return count; } -TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing) +TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing, float factor) { float outputSamples[TSF_RENDER_SHORTBUFFERBLOCK]; int channels = (f->outputmode == TSF_MONO ? 1 : 2), maxChannelSamples = TSF_RENDER_SHORTBUFFERBLOCK / channels; @@ -1670,7 +1670,7 @@ TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing int channelSamples = (samples > maxChannelSamples ? maxChannelSamples : samples); short* bufferEnd = buffer + channelSamples * channels; float *floatSamples = outputSamples; - tsf_render_float(f, floatSamples, channelSamples, TSF_FALSE); + tsf_render_float(f, floatSamples, channelSamples, TSF_FALSE, factor); samples -= channelSamples; if (flag_mixing) @@ -1689,13 +1689,13 @@ TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing } } -TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing) +TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing, float factor) { struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; if (!flag_mixing) TSF_MEMSET(buffer, 0, (f->outputmode == TSF_MONO ? 1 : 2) * sizeof(float) * samples); for (; v != vEnd; v++) if (v->playingPreset != -1) - tsf_voice_render(f, v, buffer, samples); + tsf_voice_render(f, v, buffer, samples, factor); } static void tsf_channel_setup_voice(tsf* f, struct tsf_voice* v)