From: Anton Baskanov <baskanov@gmail.com> This makes the FIR array index in the inner loop to advance in fixed steps equal to fir_step. As a side effect this also eliminates the FIR step rounding. --- dlls/dsound/fir.h | 2 -- dlls/dsound/mixer.c | 68 +++++++++++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/dlls/dsound/fir.h b/dlls/dsound/fir.h index 24d93645d12..67bbe292f0d 100644 --- a/dlls/dsound/fir.h +++ b/dlls/dsound/fir.h @@ -86,7 +86,6 @@ int main() fprintf(stderr, "q %f\n", (double)output.q); fprintf(stderr, "status %s\n", get_pm_status_str(output.status)); - printf("static const int fir_len = %d;\n", fir_len); printf("static const int fir_width = %d;\n", fir_width); printf("static const int fir_step = %d;\n", fir_step); printf("static const float fir[] = {"); @@ -104,7 +103,6 @@ int main() printf("};\n"); } */ -static const int fir_len = 8193; static const int fir_width = 64; static const int fir_step = 128; static const float fir[] = { diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index c940efe3b07..00697dd0012 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -315,28 +315,27 @@ static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count) return count; } +/** + * Note that this function will overwrite up to fir_width - 1 frames before and + * after output[]. + */ static void downsample(LONG64 freq_adjust_num, LONG64 freq_adjust_den, LONG64 freq_acc_start, - UINT dsbfirstep, float firgain, UINT count, float *input, float *output) + float firgain, UINT required_input, float *input, float *output) { - UINT i; - - for(i = 0; i < count; ++i) { - LONG64 ipos_num = freq_acc_start + i * freq_adjust_num; - UINT ipos = ipos_num / freq_adjust_den; + int j; - UINT idx_num = ipos_num % freq_adjust_den * dsbfirstep; - UINT idx = dsbfirstep - 1 - idx_num / freq_adjust_den; - float rem = 1.0f - idx_num % freq_adjust_den / (float)freq_adjust_den; + for (j = 0; j < required_input; ++j) { + LONG64 opos_num = freq_adjust_den - freq_acc_start + j * freq_adjust_den + freq_adjust_num - 1; + /* opos is in the range [-(fir_width - 1), count) */ + int opos = opos_num / freq_adjust_num - fir_width; - int fir_used = (fir_len - 1 - idx + dsbfirstep - 1) / dsbfirstep; + UINT idx_num = (freq_adjust_num - 1 - opos_num % freq_adjust_num) * fir_step; + UINT idx = idx_num / freq_adjust_num; + float rem = idx_num % freq_adjust_num / (float)freq_adjust_num; - int j; - float sum = 0.0; - float* cache = &input[ipos]; - - for (j = 0; j < fir_used; j++) - sum += (fir[idx + j * dsbfirstep] * (1.0f - rem) + fir[idx + j * dsbfirstep + 1] * rem) * cache[j]; - output[i] = sum * firgain; + UINT i; + for (i = 0; i < fir_width; ++i) + output[opos + i] += (fir[idx + i * fir_step] * (1.0f - rem) + fir[idx + i * fir_step + 1] * rem) * input[j] * firgain; } } @@ -364,14 +363,20 @@ static void upsample(LONG64 freq_adjust_num, LONG64 freq_adjust_den, LONG64 freq } } +/** + * Note that this function will overwrite up to fir_width - 1 frames before and + * after output[]. + */ static void resample(LONG64 freq_adjust_num, LONG64 freq_adjust_den, LONG64 freq_acc_start, - UINT dsbfirstep, float firgain, UINT count, float *input, float *output) + float firgain, UINT required_input, UINT count, float *input, float *output) { - if (freq_adjust_num > freq_adjust_den) - downsample(freq_adjust_num, freq_adjust_den, freq_acc_start, dsbfirstep, firgain, count, + if (freq_adjust_num > freq_adjust_den) { + memset(output, 0, count * sizeof(float)); + downsample(freq_adjust_num, freq_adjust_den, freq_acc_start, firgain, required_input, input, output); - else + } else { upsample(freq_adjust_num, freq_adjust_den, freq_acc_start, count, input, output); + } } static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum) @@ -383,17 +388,19 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * LONG64 freqAcc_start = *freqAccNum; LONG64 freqAcc_end = freqAcc_start + count * dsb->freqAdjustNum; - UINT dsbfirstep = dsb->firstep; UINT channels = dsb->mix_channels; UINT max_ipos = (freqAcc_start + count * dsb->freqAdjustNum) / dsb->freqAdjustDen; - UINT fir_cachesize = (fir_len + dsbfirstep - 2) / dsbfirstep; - UINT required_input = (freqAcc_start + (count - 1) * dsb->freqAdjustNum) / dsb->freqAdjustDen + - max(fir_width, fir_cachesize); + UINT required_input = max( + (freqAcc_start + (count - 1) * dsb->freqAdjustNum) / dsb->freqAdjustDen + fir_width, + (freqAcc_start + (count - 1 + fir_width) * dsb->freqAdjustNum) / dsb->freqAdjustDen); float *intermediate, *output, *itmp; DWORD len = required_input * channels; - len += count * channels; + /* Allocate an output buffer for each channel with padding on both ends as + * required by the resample function. Padding at the end of one channel + * buffer is reused as a start padding for the next channel buffer. */ + len += fir_width - 1 + (count + fir_width - 1) * channels; len *= sizeof(float); *freqAccNum = freqAcc_end % dsb->freqAdjustDen; @@ -410,7 +417,7 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * } intermediate = dsb->device->cp_buffer; - output = intermediate + required_input * channels; + output = intermediate + required_input * channels + fir_width - 1; if(dsb->use_committed) { committed_samples = (dsb->writelead - dsb->committed_mixpos) / istride; @@ -432,12 +439,13 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * } for (channel = 0; channel < channels; channel++) - resample(dsb->freqAdjustNum, dsb->freqAdjustDen, freqAcc_start, dsbfirstep, dsb->firgain, - count, intermediate + channel * required_input, output + channel * count); + resample(dsb->freqAdjustNum, dsb->freqAdjustDen, freqAcc_start, dsb->firgain, + required_input, count, intermediate + channel * required_input, + output + channel * (fir_width - 1 + count)); for(i = 0; i < count; ++i) for (channel = 0; channel < channels; channel++) - dsb->put(dsb, i * ostride, channel, output[channel * count + i]); + dsb->put(dsb, i * ostride, channel, output[channel * (fir_width - 1 + count) + i]); return max_ipos; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10255