<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>Underscore selectors in the Trunk? Is this really necessary? Depending on your preferences, you might not even be able to load this code, and I would not consider this Smalltalkish at all ... Is this a known idiom? :-)</p>
<p><br>
</p>
<p>Best,</p>
<p>Christoph</p>
<div id="x_Signature">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:rgb(0,0,0); font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div name="x_divtagdefaultwrapper" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:; margin:0">
<div><font size="2" color="#808080"></font></div>
</div>
</div>
</div>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von commits@source.squeak.org <commits@source.squeak.org><br>
<b>Gesendet:</b> Samstag, 19. September 2020 18:11:42<br>
<b>An:</b> squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org<br>
<b>Betreff:</b> [squeak-dev] The Trunk: Sound-eem.74.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Eliot Miranda uploaded a new version of Sound to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Sound-eem.74.mcz">http://source.squeak.org/trunk/Sound-eem.74.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Sound-eem.74<br>
Author: eem<br>
Time: 19 September 2020, 9:11:40.666386 am<br>
UUID: 42a3c2d9-0bed-4310-bcf1-cbe0f3d0653b<br>
Ancestors: Sound-eem.73<br>
<br>
Oops! stopPlayerProcess *must* stop the sound system when sent from startPlayerProcessBufferSize:rate:stereo:sound:.  Spo refactor a bit, renaming stopPlayerProcess to stopPlayerProcess: to take a hardStop boolean.  When quitting the argument is false.<br>
<br>
Add a 64-bit specific, integer-overflow agnostic version of mixSampleCount:into:startingAt:leftVol:rightVol:, for creating a simpler inline primitive in the 64-bit VM.<br>
<br>
=============== Diff against Sound-eem.73 ===============<br>
<br>
Item was changed:<br>
  ----- Method: AbstractSound class>>translatedPrimitives (in category 'primitive generation') -----<br>
  translatedPrimitives<br>
         ^#(<br>
                 (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)<br>
                 (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)<br>
                 (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)<br>
                 (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)<br>
+                (SampledSound _64bitMixSampleCount:into:startingAt:leftVol:rightVol:)<br>
                 (ReverbSound applyReverbTo:startingAt:count:)<br>
         ).<br>
  !<br>
<br>
Item was added:<br>
+ ----- Method: SampledSound>>_64bitMixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----<br>
+ _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol<br>
+        "Mix the given number of samples with the samples already in the given buffer starting at the given index.<br>
+         Assume that the buffer size is at least (index + count) - 1."<br>
+ <br>
+        | lastIndex outIndex sampleIndex sample i s |<br>
+        <inline: #always><br>
+        <var: #aSoundBuffer type: #'short int *'><br>
+        <var: #samples type: #'short int *'><br>
+ <br>
+        lastIndex := (startIndex + n) - 1.<br>
+        outIndex := startIndex.    "index of next stereo output sample pair"<br>
+        sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).<br>
+        [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue:<br>
+                [sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.<br>
+                leftVol > 0 ifTrue:<br>
+                        [i := (2 * outIndex) - 1.<br>
+                        s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).<br>
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"<br>
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"<br>
+                        aSoundBuffer at: i put: s].<br>
+                rightVol > 0 ifTrue:<br>
+                        [i := 2 * outIndex.<br>
+                        s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).<br>
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"<br>
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"<br>
+                        aSoundBuffer at: i put: s].<br>
+ <br>
+                scaledVolIncr ~= 0 ifTrue:<br>
+                        [scaledVol := scaledVol + scaledVolIncr.<br>
+                        ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:<br>
+                         [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])<br>
+                                ifTrue:  "reached the limit; stop incrementing"<br>
+                                        [scaledVol := scaledVolLimit.<br>
+                                        scaledVolIncr := 0]].<br>
+ <br>
+                scaledIndex := scaledIndex + scaledIncrement.<br>
+ <br>
+                sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).<br>
+                outIndex := outIndex + 1].<br>
+        count := count - n<br>
+ !<br>
<br>
Item was changed:<br>
  ----- Method: SampledSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----<br>
  mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol<br>
+        "Mix the given number of samples with the samples already in the given buffer starting at the given index.<br>
+         Assume that the buffer size is at least (index + count) - 1."<br>
-        "Mix the given number of samples with the samples already in the given buffer starting at the given index. Assume that the buffer size is at least (index + count) - 1."<br>
  <br>
         | lastIndex outIndex sampleIndex sample i s overflow |<br>
+        <primitive:'primitiveMixSampledSound' module: 'SoundGenerationPlugin'><br>
+        <var: #aSoundBuffer type: #'short int *'><br>
+        <var: #samples type: #'short int *'><br>
-        <primitive:'primitiveMixSampledSound' module:'SoundGenerationPlugin'><br>
-        <var: #aSoundBuffer declareC: 'short int *aSoundBuffer'><br>
-        <var: #samples declareC: 'short int *samples'><br>
  <br>
+        SmallInteger maxVal > 16r3FFFFFFF ifTrue: "In 64-bits we don't have to worry about 2^15 * 2^15 overflow"<br>
+                [^self _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol].<br>
         lastIndex := (startIndex + n) - 1.<br>
         outIndex := startIndex.    "index of next stereo output sample pair"<br>
         sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).<br>
         [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue: [<br>
                 sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.<br>
                 leftVol > 0 ifTrue: [<br>
                         i := (2 * outIndex) - 1.<br>
                         s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).<br>
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"<br>
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"<br>
                         aSoundBuffer at: i put: s].<br>
                 rightVol > 0 ifTrue: [<br>
                         i := 2 * outIndex.<br>
                         s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).<br>
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"<br>
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"<br>
                         aSoundBuffer at: i put: s].<br>
  <br>
                 scaledVolIncr ~= 0 ifTrue: [<br>
                         scaledVol := scaledVol + scaledVolIncr.<br>
                         ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:<br>
                          [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])<br>
                                 ifTrue: [  "reached the limit; stop incrementing"<br>
                                         scaledVol := scaledVolLimit.<br>
                                         scaledVolIncr := 0]].<br>
  <br>
                 scaledIndex := scaledIndex + scaledIncrement.<br>
                 scaledIndex >= ScaledIndexOverflow ifTrue: [<br>
                         overflow := scaledIndex >> IncrementFractionBits.<br>
                         indexHighBits := indexHighBits + overflow.<br>
                         scaledIndex := scaledIndex - (overflow << IncrementFractionBits)].<br>
  <br>
                 sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).<br>
                 outIndex := outIndex + 1].<br>
+        count := count - n!<br>
-        count := count - n.<br>
- !<br>
<br>
Item was changed:<br>
  ----- Method: SoundPlayer class>>shutDown: (in category 'snapshotting') -----<br>
  shutDown: quitting<br>
         "Stop player process, for example before snapshotting."<br>
  <br>
+        quitting ifTrue:<br>
+                [self stopPlayerProcess: false.<br>
+                 ReverbState := nil]!<br>
-        quitting ifTrue: [<br>
-                self stopPlayerProcess.<br>
-                ReverbState := nil].!<br>
<br>
Item was changed:<br>
  ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') -----<br>
  startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound<br>
         "Start the sound player process. Terminate the old process, if any."<br>
         "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false"<br>
  <br>
+        self stopPlayerProcess: true.<br>
+        aSound ifNotNil: "stopPlayerProcess: ensures ActiveSounds are empty..."<br>
+                [ActiveSounds add: aSound].<br>
-        self stopPlayerProcess.<br>
-        aSound<br>
-                ifNil:[ActiveSounds := OrderedCollection new]<br>
-                ifNotNil:[ActiveSounds := OrderedCollection with: aSound].<br>
         Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.<br>
+        LastBuffer ifNotNil:<br>
+                [LastBuffer := SoundBuffer basicNew: Buffer basicSize].<br>
-        LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].<br>
         PlayerSemaphore := Semaphore forMutualExclusion.<br>
         SamplingRate := samplesPerSecond.<br>
         Stereo := stereoFlag.<br>
         SoundSupported := true. "Assume so"<br>
         UseReadySemaphore := true.  "set to false if ready semaphore not supported by VM"<br>
         Smalltalk newExternalSemaphoreDo: [ :semaphore :index |<br>
                 ReadyForBuffer := semaphore.<br>
                 self primSoundStartBufferSize: Buffer stereoSampleCount<br>
                         rate: samplesPerSecond<br>
                         stereo: Stereo<br>
                         semaIndex: index ].<br>
         "Check if sound start prim was successful"<br>
         SoundSupported ifFalse:[<br>
                 Smalltalk unregisterExternalObject: ReadyForBuffer.<br>
                 ReadyForBuffer := nil.<br>
                 ^self ].<br>
         UseReadySemaphore<br>
                 ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]<br>
                 ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].<br>
         UseReverb ifTrue: [self startReverb].<br>
  <br>
         PlayerProcess<br>
                 name: 'Sound Player (', ActiveSounds size asString, ')';<br>
                 priority: Processor userInterruptPriority;<br>
                 resume!<br>
<br>
Item was removed:<br>
- ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') -----<br>
- stopPlayerProcess<br>
-        "Stop the sound player process."<br>
-        "SoundPlayer stopPlayerProcess"<br>
- <br>
-        PlayerProcess ifNotNil:<br>
-                [PlayerProcess ~~ Processor activeProcess ifTrue:<br>
-                        [PlayerProcess terminate].<br>
-                 PlayerProcess := nil].<br>
-        "Don't load the SoundPlugin if it is not in use..."<br>
-        self soundPluginActive ifTrue: [self primSoundStop].<br>
-        ActiveSounds isEmpty ifFalse:<br>
-                [ActiveSounds := OrderedCollection new].<br>
-        Buffer := nil.<br>
-        PlayerSemaphore isEmpty ifFalse:<br>
-                [PlayerSemaphore := Semaphore forMutualExclusion].<br>
-        ReadyForBuffer ifNotNil:<br>
-                [Smalltalk unregisterExternalObject: ReadyForBuffer.<br>
-                 ReadyForBuffer := nil]!<br>
<br>
Item was added:<br>
+ ----- Method: SoundPlayer class>>stopPlayerProcess: (in category 'player process') -----<br>
+ stopPlayerProcess: hardStop<br>
+        "Stop the sound player process."<br>
+        "SoundPlayer stopPlayerProcess"<br>
+ <br>
+        PlayerProcess ifNotNil:<br>
+                [PlayerProcess ~~ Processor activeProcess ifTrue:<br>
+                        [PlayerProcess terminate].<br>
+                 PlayerProcess := nil].<br>
+        (hardStop or: [self soundPluginActive]) ifTrue: [self primSoundStop].<br>
+        ActiveSounds isEmpty ifFalse:<br>
+                [ActiveSounds := OrderedCollection new].<br>
+        Buffer := nil.<br>
+        PlayerSemaphore isEmpty ifFalse:<br>
+                [PlayerSemaphore := Semaphore forMutualExclusion].<br>
+        ReadyForBuffer ifNotNil:<br>
+                [Smalltalk unregisterExternalObject: ReadyForBuffer.<br>
+                 ReadyForBuffer := nil]!<br>
<br>
<br>
</div>
</span></font>
</body>
</html>