The distorsion that lead to my previous patch was in fact caused by the resampling of an 11025Hz signal to 48kHz. According to the signal processing literature I could find, what we do is a '1st Order Linear Interpolation Filter' and that is considered a poor filter. That literature says we should be using an 'nth Order Interpolation / Decimation' filter.
I didn't really feel motivated enough to implement such a beast, plus this is more the job of a sound library than of Wine. I hope aRts, ESound, Jack and friends implement such a filter so it will hopefully soon be a moot point soon anyway. However one easy thing we can do is to try not to do any resampling unless absolutely necessary. This means first trying simple 8/16bits or mono/stereo conversions first. If we find a match the sound quality will be better and the conversion will use less CPU.
Changelog:
Francois Gouget <fgouget@codeweavers.com>
* dlls/winmm/wavemap/wavemap.c
Our resampling algorithm is quite primitive so try simple 8/16 mono/stereo conversions first. Only resample if we cannot avoid it.
--
Francois Gouget
fgouget@codeweavers.com
Index: dlls/winmm/wavemap/wavemap.c =================================================================== RCS file: /home/wine/wine/dlls/winmm/wavemap/wavemap.c,v retrieving revision 1.26 diff -u -r1.26 wavemap.c --- dlls/winmm/wavemap/wavemap.c 13 Dec 2002 02:18:20 -0000 1.26 +++ dlls/winmm/wavemap/wavemap.c 13 Dec 2002 19:18:56 -0000 @@ -185,6 +191,19 @@ #define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \ if (wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags | WAVE_FORMAT_DIRECT) == MMSYSERR_NOERROR) \ {wom->avgSpeedInner = wfx.nAvgBytesPerSec; goto found;} + + /* Our resampling algorithm is quite primitive so first try + * to just change the bit depth and number of channels + */ + for (i = ndlo; i < ndhi; i++) { + wfx.nSamplesPerSec=lpDesc->lpFormat->nSamplesPerSec; + wfx.nChannels = lpDesc->lpFormat->nChannels; + TRY(wfx.nSamplesPerSec, 16); + TRY(wfx.nSamplesPerSec, 8); + wfx.nChannels ^= 3; + TRY(wfx.nSamplesPerSec, 16); + TRY(wfx.nSamplesPerSec, 8); + } for (i = ndlo; i < ndhi; i++) { /* first try with same stereo/mono option as source */