<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:large">Hi Levente, Hi Stef,<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Sep 19, 2020 at 4:47 AM Levente Uzonyi <<a href="mailto:leves@caesar.elte.hu">leves@caesar.elte.hu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Hi Eliot,<br>
<br>
On Fri, 18 Sep 2020, Eliot Miranda wrote:<br>
<br>
> Hi All,<br>
> <br>
>      the SampledSound>>#mixSampleCount:into:startingAt:leftVol:rightVol: method looks to be badly broken.  I don't understand the index scaling (yet) so I thought I'd throw this out there and see if anyone can spot when and<br>
> why this broke.<br>
> <br>
> Here's a simple example that generates a second long A below middle C (220Hz), smoothing start and stop, and then plays it, so far so good:<br>
> <br>
> | samples sineTable sound |<br>
> "1 second of A below middle C (220Hz). 16000 / 220 is 72.72 recurring"<br>
> sineTable := SoundPlayer sineTable: 73.<br>
> sineTable doWithIndex: "And let's not deafen anyone..."<br>
> [:sample :index| sineTable at: index put: sample // 4].<br>
> samples := SoundBuffer new: 16000.<br>
> 1 to: samples size by: sineTable size do:<br>
> [:i| samples replaceFrom: i to: (i + sineTable size - 1 min: 16000) with: sineTable startingAt: 1].<br>
> 1 to: 146 do: "smooth start and end of the sound"<br>
> [:i|<br>
> samples at: i put: ((samples at: i) * i / 146) asInteger.<br>
> samples at: 16001 - i put: ((samples at: 16001 - i) * i / 146) asInteger].<br>
> (SampledSound samples: samples samplingRate: 16000) play<br>
> <br>
> Now let's create a stereo sound image and try and play that:<br>
> <br>
> | samples sineTable sound |<br>
> "1 second of A below middle C (220Hz). 16000 / 220 is 72.72 recurring"<br>
> sineTable := SoundPlayer sineTable: 73.<br>
> sineTable doWithIndex:<br>
> [:sample :index| sineTable at: index put: sample // 4].<br>
> samples := SoundBuffer new: 16000.<br>
> 1 to: samples size by: sineTable size do:<br>
> [:i| samples replaceFrom: i to: (i + sineTable size - 1 min: 16000) with: sineTable startingAt: 1].<br>
> 1 to: 146 do:<br>
> [:i|<br>
> samples at: i put: ((samples at: i) * i / 146) asInteger.<br>
> samples at: 16001 - i put: ((samples at: 16001 - i) * i / 146) asInteger].<br>
> sound := SampledSound samples: samples samplingRate: 16000.<br>
> sound := MixedSound new<br>
> add: sound pan: 0.25;<br>
> add: sound pan: 0.75;<br>
<br>
If you replace the above line with<br>
<br>
> add: sound copy pan: 0.75;<br>
<br>
then the produced sound should be okay. Sound objects have state, and if <br>
you pass the same object twice, the state will be messed up.<br></blockquote><div><br></div><div class="gmail_default" style="font-size:large">Thank you!  This has cost me a day.  I'd say that it fails the principle of least astonishment.  I'm going to see if I can add a check to add:pan: or the mixdown step that would warn of this requirement.  </div><div class="gmail_default" style="font-size:large"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Levente<br>
<br>
> yourself.<br>
> sound play<br>
> <br>
> Eek!!<br>
> <br>
> You can examine the mixing without hurting your ears by replacing<br>
>     "sound play"<br>
> with<br>
>     "sound computeSamplesForSeconds: sound duration"<br>
> which invokes the mixing directly.<br>
> <br>
> Any help making sense of this gratefully received.  Some comments around the<br>
> <br>
> scaledIndex := scaledIndex + scaledIncrement.<br>
> scaledIndex >= ScaledIndexOverflow ifTrue: [<br>
> overflow := scaledIndex >> IncrementFractionBits.<br>
> indexHighBits := indexHighBits + overflow.<br>
> scaledIndex := scaledIndex - (overflow << IncrementFractionBits)].<br>
> <br>
> in SampledSound>>#mixSampleCount:into:startingAt:leftVol:rightVol: would be most welcome.<br>
> <br>
> And if you simply comment out the primitive teh Smaklltalk code produces garbage also, so the problem does not seem to be Slang but the algorithm itself.<br>
> <br>
> _,,,^..^,,,_<br>
> best, Eliot<br>
> <br>
><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div></div>