[squeak-dev] MixedSound (& consequently stereo) is badly broken in both 32-bit and 64-bit versions

Eliot Miranda eliot.miranda at gmail.com
Sat Sep 19 18:43:34 UTC 2020


Hi Dan, Hi Stef, Hi Levente, Hi Christoph,


   this is not a bug.  I'm just noting something for our collective
understanding and pointing to a potential improvement in the sound system.
This is concerning the code
in SampledSound>>#mixSampleCount:into:startingAt:leftVol:rightVol:.  If you
look at the results of mixing down a 16KHz sound into e.g. a 22.1KHz sound
(the default sampling rate for a mix down) then if the input is a 220Hz
sine wave at 16KHz (A below middle C, computed in the example below) then
the first few samples look like this

a SoundBuffer(4 19 42 75 117 166 222 285 353 425 ...

When we mix this down the corresponding range of samples in the stereo
22.1Khz mixed-down sound is

a SoundBuffer(4 4 4 4 18 18 41 41 41 41 74 74 116 116 165 165 165 165 221
221 284 284 284 284 352 352 424 424 500 500 ...

Now this comes because of the scaled indexing in
SampledSound>>#mixSampleCount:into:startingAt:leftVol:rightVol:
and is to be expected.  The input sample rate is less than the output
sample rate so the algorithm smears mixed output samples until the next
matching input sample is reached.

The improvement would be not to smear, but to interpolate.  If we added
(say, simple linear) interpolation then the algorithm would instead produce

a SoundBuffer(4 4 11 11 18 18 41 41 57 57 74 74 116 116 165 165 193 193 221
221 284 284 318 318 352 352 424 424 500 500 ...


Now I (we?) just have to find time to work on this ;-)

On Sat, Sep 19, 2020 at 10:56 AM Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> Hi Stef,
>
> On Sat, Sep 19, 2020 at 1:17 AM Stéphane Rollandin <lecteur at zogotounga.net>
> wrote:
>
>> >      if you play the example you’ll see that the first version works
>> fine.  The second version, which adds MixedSound yo create stereo doesn’t.
>> That proves that the issue is in MixedSound.  Please just try the two
>> examples.
>>
>> Right. What I can see If I do
>>
>> | samples sineTable sound |
>> "1 second of A below middle C (220Hz). 16000 / 220 is 72.72 recurring"
>> sineTable := SoundPlayer sineTable: 73.
>> sineTable doWithIndex:
>>         [:sample :index| sineTable at: index put: sample // 4].
>> samples := SoundBuffer new: 16000.
>> 1 to: samples size by: sineTable size do:
>>         [:i| samples replaceFrom: i to: (i + sineTable size - 1 min:
>> 16000)
>> with: sineTable startingAt: 1].
>> 1 to: 146 do:
>>         [:i|
>>         samples at: i put: ((samples at: i) * i / 146) asInteger.
>>         samples at: 16001 - i put: ((samples at: 16001 - i) * i / 146)
>> asInteger].
>> sound := SampledSound samples: samples samplingRate: 16000.
>> sound := MixedSound new
>>                         add: sound pan: 0.25;
>>                         add: sound pan: 0.75;
>>                         yourself.
>> (SampledSound samples: sound monoSamples samplingRate: sound
>> originalSamplingRate) edit
>>
>> in the muO image I pointed to in my previous message, is a phasing
>> problem leading to periodic glitches (the attached image is directly
>> taken from the muO editor)
>>
>
> [image: image.png]
>
> Interesting!!  I don't see this in my data, but I do see evidence of an
> off-by-one error in misdown.  Here's the start, first zero crossing, and
> end of the mono sound (the original samples sound buffer)
>
>  { samples first: 8. samples copyFrom: 70 to: 77. samples last: 8 }
> {a SoundBuffer(4 19 42 75 117 166 222 285) .
>  a SoundBuffer(-1003 -682 -347 0 356 720 1088 1457) .
>  a SoundBuffer(221 222 213 196 170 136 96 50)}
>
> So these look fine and smooth.
>
> But here's the corresponding data from the computeSamplesForSeconds:
> result of the MixedSound:
> { self first: 16. self copyFrom: 70 * 2 to: 77 * 2 + 1. self last: 16 }
>  {a SoundBuffer(4 4 4 4 18 18 41 41 41 41 74 74 116 116 165 165) .
>   a SoundBuffer(-2712 -2712 -2712 -2836 -2836 -2940 -2940 -2940 -2940
> -3022 -3022 -3084 -3084 -3124 -3124 -3214) .
>   a SoundBuffer(212 212 212 212 196 196 169 169 169 169 136 136 96 96 49
> 49)}
>
> The data *should* start with a SoundBuffer(4 4 18 18...
> The data ends well.  But the first crossing is completely wrong.
>
> Strange, because it sounds ok...
>
> Let me count the crossings using:
> | sign crossings |
> crossings := 0.
> sign := self first sign.
> self do:
> [:each|
> each sign = sign negated ifTrue:
> [crossings := crossings + 1.
> sign := each sign]].
> crossings
>
> Both give 438 as expected.  Strange.  Why is there no crossing between 140
> and 154 in the mixed down sound?
>
>
> Ah, ok, the sample rate has changed:
>
>
> | sign crossings ncrossings |
> ncrossings := 0.
> crossings := OrderedCollection new.
> sign := self first sign.
> self doWithIndex:
> [:each :idx|
> each sign = sign negated ifTrue:
> [crossings add: idx - 1 -> idx.
> ncrossings := ncrossings + 1.
> sign := each sign]].
> { crossings first: 4. ncrossings } {an OrderedCollection(100->101 202->203
> 302->303 404->405) . 438}
>
>
> So everything is fine *except for* the extra sample at the beginning.
> That's clearly an error, right?
>
> I'm looking at this..
>>
>> Stef
>>
>
> _,,,^..^,,,_
> best, Eliot
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20200919/e3d7598f/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 19346 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20200919/e3d7598f/attachment.png>


More information about the Squeak-dev mailing list