The Trunk: Sound-eem.74.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Sound-eem.74.mcz

commits-2
Eliot Miranda uploaded a new version of Sound to project The Trunk:
http://source.squeak.org/trunk/Sound-eem.74.mcz

==================== Summary ====================

Name: Sound-eem.74
Author: eem
Time: 19 September 2020, 9:11:40.666386 am
UUID: 42a3c2d9-0bed-4310-bcf1-cbe0f3d0653b
Ancestors: Sound-eem.73

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.

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.

=============== Diff against Sound-eem.73 ===============

Item was changed:
  ----- Method: AbstractSound class>>translatedPrimitives (in category 'primitive generation') -----
  translatedPrimitives
  ^#(
  (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
+ (SampledSound _64bitMixSampleCount:into:startingAt:leftVol:rightVol:)
  (ReverbSound applyReverbTo:startingAt:count:)
  ).
  !

Item was added:
+ ----- Method: SampledSound>>_64bitMixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
+ _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+ "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."
+
+ | lastIndex outIndex sampleIndex sample i s |
+ <inline: #always>
+ <var: #aSoundBuffer type: #'short int *'>
+ <var: #samples type: #'short int *'>
+
+ lastIndex := (startIndex + n) - 1.
+ outIndex := startIndex.    "index of next stereo output sample pair"
+ sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+ [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue:
+ [sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
+ leftVol > 0 ifTrue:
+ [i := (2 * outIndex) - 1.
+ s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
+ s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+ s < -32767 ifTrue: [s := -32767].  "clipping!!"
+ aSoundBuffer at: i put: s].
+ rightVol > 0 ifTrue:
+ [i := 2 * outIndex.
+ s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
+ s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+ s < -32767 ifTrue: [s := -32767].  "clipping!!"
+ aSoundBuffer at: i put: s].
+
+ scaledVolIncr ~= 0 ifTrue:
+ [scaledVol := scaledVol + scaledVolIncr.
+ ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
+ [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
+ ifTrue:  "reached the limit; stop incrementing"
+ [scaledVol := scaledVolLimit.
+ scaledVolIncr := 0]].
+
+ scaledIndex := scaledIndex + scaledIncrement.
+
+ sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+ outIndex := outIndex + 1].
+ count := count - n
+ !

Item was changed:
  ----- Method: SampledSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
  mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+ "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."
- "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."
 
  | lastIndex outIndex sampleIndex sample i s overflow |
+ <primitive:'primitiveMixSampledSound' module: 'SoundGenerationPlugin'>
+ <var: #aSoundBuffer type: #'short int *'>
+ <var: #samples type: #'short int *'>
- <primitive:'primitiveMixSampledSound' module:'SoundGenerationPlugin'>
- <var: #aSoundBuffer declareC: 'short int *aSoundBuffer'>
- <var: #samples declareC: 'short int *samples'>
 
+ SmallInteger maxVal > 16r3FFFFFFF ifTrue: "In 64-bits we don't have to worry about 2^15 * 2^15 overflow"
+ [^self _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol].
  lastIndex := (startIndex + n) - 1.
  outIndex := startIndex.    "index of next stereo output sample pair"
  sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
  [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue: [
  sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
  leftVol > 0 ifTrue: [
  i := (2 * outIndex) - 1.
  s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
  s >  32767 ifTrue: [s :=  32767].  "clipping!!"
  s < -32767 ifTrue: [s := -32767].  "clipping!!"
  aSoundBuffer at: i put: s].
  rightVol > 0 ifTrue: [
  i := 2 * outIndex.
  s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
  s >  32767 ifTrue: [s :=  32767].  "clipping!!"
  s < -32767 ifTrue: [s := -32767].  "clipping!!"
  aSoundBuffer at: i put: s].
 
  scaledVolIncr ~= 0 ifTrue: [
  scaledVol := scaledVol + scaledVolIncr.
  ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
  [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
  ifTrue: [  "reached the limit; stop incrementing"
  scaledVol := scaledVolLimit.
  scaledVolIncr := 0]].
 
  scaledIndex := scaledIndex + scaledIncrement.
  scaledIndex >= ScaledIndexOverflow ifTrue: [
  overflow := scaledIndex >> IncrementFractionBits.
  indexHighBits := indexHighBits + overflow.
  scaledIndex := scaledIndex - (overflow << IncrementFractionBits)].
 
  sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
  outIndex := outIndex + 1].
+ count := count - n!
- count := count - n.
- !

Item was changed:
  ----- Method: SoundPlayer class>>shutDown: (in category 'snapshotting') -----
  shutDown: quitting
  "Stop player process, for example before snapshotting."
 
+ quitting ifTrue:
+ [self stopPlayerProcess: false.
+ ReverbState := nil]!
- quitting ifTrue: [
- self stopPlayerProcess.
- ReverbState := nil].!

Item was changed:
  ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') -----
  startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound
  "Start the sound player process. Terminate the old process, if any."
  "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false"
 
+ self stopPlayerProcess: true.
+ aSound ifNotNil: "stopPlayerProcess: ensures ActiveSounds are empty..."
+ [ActiveSounds add: aSound].
- self stopPlayerProcess.
- aSound
- ifNil:[ActiveSounds := OrderedCollection new]
- ifNotNil:[ActiveSounds := OrderedCollection with: aSound].
  Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.
+ LastBuffer ifNotNil:
+ [LastBuffer := SoundBuffer basicNew: Buffer basicSize].
- LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].
  PlayerSemaphore := Semaphore forMutualExclusion.
  SamplingRate := samplesPerSecond.
  Stereo := stereoFlag.
  SoundSupported := true. "Assume so"
  UseReadySemaphore := true.  "set to false if ready semaphore not supported by VM"
  Smalltalk newExternalSemaphoreDo: [ :semaphore :index |
  ReadyForBuffer := semaphore.
  self primSoundStartBufferSize: Buffer stereoSampleCount
  rate: samplesPerSecond
  stereo: Stereo
  semaIndex: index ].
  "Check if sound start prim was successful"
  SoundSupported ifFalse:[
  Smalltalk unregisterExternalObject: ReadyForBuffer.
  ReadyForBuffer := nil.
  ^self ].
  UseReadySemaphore
  ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]
  ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].
  UseReverb ifTrue: [self startReverb].
 
  PlayerProcess
  name: 'Sound Player (', ActiveSounds size asString, ')';
  priority: Processor userInterruptPriority;
  resume!

Item was removed:
- ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') -----
- stopPlayerProcess
- "Stop the sound player process."
- "SoundPlayer stopPlayerProcess"
-
- PlayerProcess ifNotNil:
- [PlayerProcess ~~ Processor activeProcess ifTrue:
- [PlayerProcess terminate].
- PlayerProcess := nil].
- "Don't load the SoundPlugin if it is not in use..."
- self soundPluginActive ifTrue: [self primSoundStop].
- ActiveSounds isEmpty ifFalse:
- [ActiveSounds := OrderedCollection new].
- Buffer := nil.
- PlayerSemaphore isEmpty ifFalse:
- [PlayerSemaphore := Semaphore forMutualExclusion].
- ReadyForBuffer ifNotNil:
- [Smalltalk unregisterExternalObject: ReadyForBuffer.
- ReadyForBuffer := nil]!

Item was added:
+ ----- Method: SoundPlayer class>>stopPlayerProcess: (in category 'player process') -----
+ stopPlayerProcess: hardStop
+ "Stop the sound player process."
+ "SoundPlayer stopPlayerProcess"
+
+ PlayerProcess ifNotNil:
+ [PlayerProcess ~~ Processor activeProcess ifTrue:
+ [PlayerProcess terminate].
+ PlayerProcess := nil].
+ (hardStop or: [self soundPluginActive]) ifTrue: [self primSoundStop].
+ ActiveSounds isEmpty ifFalse:
+ [ActiveSounds := OrderedCollection new].
+ Buffer := nil.
+ PlayerSemaphore isEmpty ifFalse:
+ [PlayerSemaphore := Semaphore forMutualExclusion].
+ ReadyForBuffer ifNotNil:
+ [Smalltalk unregisterExternalObject: ReadyForBuffer.
+ ReadyForBuffer := nil]!


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Sound-eem.74.mcz

Christoph Thiede

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? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von [hidden email] <[hidden email]>
Gesendet: Samstag, 19. September 2020 18:11:42
An: [hidden email]; [hidden email]
Betreff: [squeak-dev] The Trunk: Sound-eem.74.mcz
 
Eliot Miranda uploaded a new version of Sound to project The Trunk:
http://source.squeak.org/trunk/Sound-eem.74.mcz

==================== Summary ====================

Name: Sound-eem.74
Author: eem
Time: 19 September 2020, 9:11:40.666386 am
UUID: 42a3c2d9-0bed-4310-bcf1-cbe0f3d0653b
Ancestors: Sound-eem.73

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.

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.

=============== Diff against Sound-eem.73 ===============

Item was changed:
  ----- Method: AbstractSound class>>translatedPrimitives (in category 'primitive generation') -----
  translatedPrimitives
         ^#(
                 (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
+                (SampledSound _64bitMixSampleCount:into:startingAt:leftVol:rightVol:)
                 (ReverbSound applyReverbTo:startingAt:count:)
         ).
  !

Item was added:
+ ----- Method: SampledSound>>_64bitMixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
+ _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+        "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."
+
+        | lastIndex outIndex sampleIndex sample i s |
+        <inline: #always>
+        <var: #aSoundBuffer type: #'short int *'>
+        <var: #samples type: #'short int *'>
+
+        lastIndex := (startIndex + n) - 1.
+        outIndex := startIndex.    "index of next stereo output sample pair"
+        sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+        [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue:
+                [sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
+                leftVol > 0 ifTrue:
+                        [i := (2 * outIndex) - 1.
+                        s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"
+                        aSoundBuffer at: i put: s].
+                rightVol > 0 ifTrue:
+                        [i := 2 * outIndex.
+                        s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"
+                        aSoundBuffer at: i put: s].
+
+                scaledVolIncr ~= 0 ifTrue:
+                        [scaledVol := scaledVol + scaledVolIncr.
+                        ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
+                         [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
+                                ifTrue:  "reached the limit; stop incrementing"
+                                        [scaledVol := scaledVolLimit.
+                                        scaledVolIncr := 0]].
+
+                scaledIndex := scaledIndex + scaledIncrement.
+
+                sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+                outIndex := outIndex + 1].
+        count := count - n
+ !

Item was changed:
  ----- Method: SampledSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
  mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+        "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."
-        "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."
 
         | lastIndex outIndex sampleIndex sample i s overflow |
+        <primitive:'primitiveMixSampledSound' module: 'SoundGenerationPlugin'>
+        <var: #aSoundBuffer type: #'short int *'>
+        <var: #samples type: #'short int *'>
-        <primitive:'primitiveMixSampledSound' module:'SoundGenerationPlugin'>
-        <var: #aSoundBuffer declareC: 'short int *aSoundBuffer'>
-        <var: #samples declareC: 'short int *samples'>
 
+        SmallInteger maxVal > 16r3FFFFFFF ifTrue: "In 64-bits we don't have to worry about 2^15 * 2^15 overflow"
+                [^self _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol].
         lastIndex := (startIndex + n) - 1.
         outIndex := startIndex.    "index of next stereo output sample pair"
         sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
         [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue: [
                 sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
                 leftVol > 0 ifTrue: [
                         i := (2 * outIndex) - 1.
                         s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"
                         aSoundBuffer at: i put: s].
                 rightVol > 0 ifTrue: [
                         i := 2 * outIndex.
                         s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"
                         aSoundBuffer at: i put: s].
 
                 scaledVolIncr ~= 0 ifTrue: [
                         scaledVol := scaledVol + scaledVolIncr.
                         ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
                          [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
                                 ifTrue: [  "reached the limit; stop incrementing"
                                         scaledVol := scaledVolLimit.
                                         scaledVolIncr := 0]].
 
                 scaledIndex := scaledIndex + scaledIncrement.
                 scaledIndex >= ScaledIndexOverflow ifTrue: [
                         overflow := scaledIndex >> IncrementFractionBits.
                         indexHighBits := indexHighBits + overflow.
                         scaledIndex := scaledIndex - (overflow << IncrementFractionBits)].
 
                 sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
                 outIndex := outIndex + 1].
+        count := count - n!
-        count := count - n.
- !

Item was changed:
  ----- Method: SoundPlayer class>>shutDown: (in category 'snapshotting') -----
  shutDown: quitting
         "Stop player process, for example before snapshotting."
 
+        quitting ifTrue:
+                [self stopPlayerProcess: false.
+                 ReverbState := nil]!
-        quitting ifTrue: [
-                self stopPlayerProcess.
-                ReverbState := nil].!

Item was changed:
  ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') -----
  startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound
         "Start the sound player process. Terminate the old process, if any."
         "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false"
 
+        self stopPlayerProcess: true.
+        aSound ifNotNil: "stopPlayerProcess: ensures ActiveSounds are empty..."
+                [ActiveSounds add: aSound].
-        self stopPlayerProcess.
-        aSound
-                ifNil:[ActiveSounds := OrderedCollection new]
-                ifNotNil:[ActiveSounds := OrderedCollection with: aSound].
         Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.
+        LastBuffer ifNotNil:
+                [LastBuffer := SoundBuffer basicNew: Buffer basicSize].
-        LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].
         PlayerSemaphore := Semaphore forMutualExclusion.
         SamplingRate := samplesPerSecond.
         Stereo := stereoFlag.
         SoundSupported := true. "Assume so"
         UseReadySemaphore := true.  "set to false if ready semaphore not supported by VM"
         Smalltalk newExternalSemaphoreDo: [ :semaphore :index |
                 ReadyForBuffer := semaphore.
                 self primSoundStartBufferSize: Buffer stereoSampleCount
                         rate: samplesPerSecond
                         stereo: Stereo
                         semaIndex: index ].
         "Check if sound start prim was successful"
         SoundSupported ifFalse:[
                 Smalltalk unregisterExternalObject: ReadyForBuffer.
                 ReadyForBuffer := nil.
                 ^self ].
         UseReadySemaphore
                 ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]
                 ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].
         UseReverb ifTrue: [self startReverb].
 
         PlayerProcess
                 name: 'Sound Player (', ActiveSounds size asString, ')';
                 priority: Processor userInterruptPriority;
                 resume!

Item was removed:
- ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') -----
- stopPlayerProcess
-        "Stop the sound player process."
-        "SoundPlayer stopPlayerProcess"
-
-        PlayerProcess ifNotNil:
-                [PlayerProcess ~~ Processor activeProcess ifTrue:
-                        [PlayerProcess terminate].
-                 PlayerProcess := nil].
-        "Don't load the SoundPlugin if it is not in use..."
-        self soundPluginActive ifTrue: [self primSoundStop].
-        ActiveSounds isEmpty ifFalse:
-                [ActiveSounds := OrderedCollection new].
-        Buffer := nil.
-        PlayerSemaphore isEmpty ifFalse:
-                [PlayerSemaphore := Semaphore forMutualExclusion].
-        ReadyForBuffer ifNotNil:
-                [Smalltalk unregisterExternalObject: ReadyForBuffer.
-                 ReadyForBuffer := nil]!

Item was added:
+ ----- Method: SoundPlayer class>>stopPlayerProcess: (in category 'player process') -----
+ stopPlayerProcess: hardStop
+        "Stop the sound player process."
+        "SoundPlayer stopPlayerProcess"
+
+        PlayerProcess ifNotNil:
+                [PlayerProcess ~~ Processor activeProcess ifTrue:
+                        [PlayerProcess terminate].
+                 PlayerProcess := nil].
+        (hardStop or: [self soundPluginActive]) ifTrue: [self primSoundStop].
+        ActiveSounds isEmpty ifFalse:
+                [ActiveSounds := OrderedCollection new].
+        Buffer := nil.
+        PlayerSemaphore isEmpty ifFalse:
+                [PlayerSemaphore := Semaphore forMutualExclusion].
+        ReadyForBuffer ifNotNil:
+                [Smalltalk unregisterExternalObject: ReadyForBuffer.
+                 ReadyForBuffer := nil]!




Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Sound-eem.74.mcz

Eliot Miranda-2
Hi Christoph,

On Mon, Sep 21, 2020 at 12:35 PM Thiede, Christoph <[hidden email]> wrote:

Underscore selectors in the Trunk? Is this really necessary?

No, but it leads to a much nicer sounding selector name than any of sixtyFourBitMixSampleCount:into:startingAt:leftVol:rightVol:, mix64BitSampleCount:into:startingAt:leftVol:rightVol:, or mixSampleCount64:into:startingAt:leftVol:rightVol:.  I can change it if it really offends you, but I did it for a reason.  I wanted it to read as "this is the 64-bit version of mixSampleCount:into:startingAt:leftVol:rightVol:", and I didn't want it to be over long.  Note that "mix64BitSampleCOunt:" et al are ambiguous.  The samples are not 64-bits, the algorithm is for 64-bits.  But remember that this is a strange method anyway, a translated primitive, with lots of C weirdness in it.  Complaining about the selector is the least of the problems with it ;-)

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? :-)


Well, underscores have neen allowed in Smalltalk for a long time now.  It does lead to some nice usage when interfacing with C.  I certwinly do not use it for normal SMalltalk code. But I would miss it badly if it didn't exist.  I use selectors such as strcpy:_:_: (which maps to strcpy(3)) routinely in the VMMaker.

Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von [hidden email] <[hidden email]>
Gesendet: Samstag, 19. September 2020 18:11:42
An: [hidden email]; [hidden email]
Betreff: [squeak-dev] The Trunk: Sound-eem.74.mcz
 
Eliot Miranda uploaded a new version of Sound to project The Trunk:
http://source.squeak.org/trunk/Sound-eem.74.mcz

==================== Summary ====================

Name: Sound-eem.74
Author: eem
Time: 19 September 2020, 9:11:40.666386 am
UUID: 42a3c2d9-0bed-4310-bcf1-cbe0f3d0653b
Ancestors: Sound-eem.73

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.

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.

=============== Diff against Sound-eem.73 ===============

Item was changed:
  ----- Method: AbstractSound class>>translatedPrimitives (in category 'primitive generation') -----
  translatedPrimitives
         ^#(
                 (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
+                (SampledSound _64bitMixSampleCount:into:startingAt:leftVol:rightVol:)
                 (ReverbSound applyReverbTo:startingAt:count:)
         ).
  !

Item was added:
+ ----- Method: SampledSound>>_64bitMixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
+ _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+        "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."
+
+        | lastIndex outIndex sampleIndex sample i s |
+        <inline: #always>
+        <var: #aSoundBuffer type: #'short int *'>
+        <var: #samples type: #'short int *'>
+
+        lastIndex := (startIndex + n) - 1.
+        outIndex := startIndex.    "index of next stereo output sample pair"
+        sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+        [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue:
+                [sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
+                leftVol > 0 ifTrue:
+                        [i := (2 * outIndex) - 1.
+                        s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"
+                        aSoundBuffer at: i put: s].
+                rightVol > 0 ifTrue:
+                        [i := 2 * outIndex.
+                        s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"
+                        aSoundBuffer at: i put: s].
+
+                scaledVolIncr ~= 0 ifTrue:
+                        [scaledVol := scaledVol + scaledVolIncr.
+                        ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
+                         [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
+                                ifTrue:  "reached the limit; stop incrementing"
+                                        [scaledVol := scaledVolLimit.
+                                        scaledVolIncr := 0]].
+
+                scaledIndex := scaledIndex + scaledIncrement.
+
+                sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+                outIndex := outIndex + 1].
+        count := count - n
+ !

Item was changed:
  ----- Method: SampledSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
  mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+        "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."
-        "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."
 
         | lastIndex outIndex sampleIndex sample i s overflow |
+        <primitive:'primitiveMixSampledSound' module: 'SoundGenerationPlugin'>
+        <var: #aSoundBuffer type: #'short int *'>
+        <var: #samples type: #'short int *'>
-        <primitive:'primitiveMixSampledSound' module:'SoundGenerationPlugin'>
-        <var: #aSoundBuffer declareC: 'short int *aSoundBuffer'>
-        <var: #samples declareC: 'short int *samples'>
 
+        SmallInteger maxVal > 16r3FFFFFFF ifTrue: "In 64-bits we don't have to worry about 2^15 * 2^15 overflow"
+                [^self _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol].
         lastIndex := (startIndex + n) - 1.
         outIndex := startIndex.    "index of next stereo output sample pair"
         sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
         [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue: [
                 sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
                 leftVol > 0 ifTrue: [
                         i := (2 * outIndex) - 1.
                         s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"
                         aSoundBuffer at: i put: s].
                 rightVol > 0 ifTrue: [
                         i := 2 * outIndex.
                         s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"
                         aSoundBuffer at: i put: s].
 
                 scaledVolIncr ~= 0 ifTrue: [
                         scaledVol := scaledVol + scaledVolIncr.
                         ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
                          [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
                                 ifTrue: [  "reached the limit; stop incrementing"
                                         scaledVol := scaledVolLimit.
                                         scaledVolIncr := 0]].
 
                 scaledIndex := scaledIndex + scaledIncrement.
                 scaledIndex >= ScaledIndexOverflow ifTrue: [
                         overflow := scaledIndex >> IncrementFractionBits.
                         indexHighBits := indexHighBits + overflow.
                         scaledIndex := scaledIndex - (overflow << IncrementFractionBits)].
 
                 sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
                 outIndex := outIndex + 1].
+        count := count - n!
-        count := count - n.
- !

Item was changed:
  ----- Method: SoundPlayer class>>shutDown: (in category 'snapshotting') -----
  shutDown: quitting
         "Stop player process, for example before snapshotting."
 
+        quitting ifTrue:
+                [self stopPlayerProcess: false.
+                 ReverbState := nil]!
-        quitting ifTrue: [
-                self stopPlayerProcess.
-                ReverbState := nil].!

Item was changed:
  ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') -----
  startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound
         "Start the sound player process. Terminate the old process, if any."
         "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false"
 
+        self stopPlayerProcess: true.
+        aSound ifNotNil: "stopPlayerProcess: ensures ActiveSounds are empty..."
+                [ActiveSounds add: aSound].
-        self stopPlayerProcess.
-        aSound
-                ifNil:[ActiveSounds := OrderedCollection new]
-                ifNotNil:[ActiveSounds := OrderedCollection with: aSound].
         Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.
+        LastBuffer ifNotNil:
+                [LastBuffer := SoundBuffer basicNew: Buffer basicSize].
-        LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].
         PlayerSemaphore := Semaphore forMutualExclusion.
         SamplingRate := samplesPerSecond.
         Stereo := stereoFlag.
         SoundSupported := true. "Assume so"
         UseReadySemaphore := true.  "set to false if ready semaphore not supported by VM"
         Smalltalk newExternalSemaphoreDo: [ :semaphore :index |
                 ReadyForBuffer := semaphore.
                 self primSoundStartBufferSize: Buffer stereoSampleCount
                         rate: samplesPerSecond
                         stereo: Stereo
                         semaIndex: index ].
         "Check if sound start prim was successful"
         SoundSupported ifFalse:[
                 Smalltalk unregisterExternalObject: ReadyForBuffer.
                 ReadyForBuffer := nil.
                 ^self ].
         UseReadySemaphore
                 ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]
                 ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].
         UseReverb ifTrue: [self startReverb].
 
         PlayerProcess
                 name: 'Sound Player (', ActiveSounds size asString, ')';
                 priority: Processor userInterruptPriority;
                 resume!

Item was removed:
- ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') -----
- stopPlayerProcess
-        "Stop the sound player process."
-        "SoundPlayer stopPlayerProcess"
-
-        PlayerProcess ifNotNil:
-                [PlayerProcess ~~ Processor activeProcess ifTrue:
-                        [PlayerProcess terminate].
-                 PlayerProcess := nil].
-        "Don't load the SoundPlugin if it is not in use..."
-        self soundPluginActive ifTrue: [self primSoundStop].
-        ActiveSounds isEmpty ifFalse:
-                [ActiveSounds := OrderedCollection new].
-        Buffer := nil.
-        PlayerSemaphore isEmpty ifFalse:
-                [PlayerSemaphore := Semaphore forMutualExclusion].
-        ReadyForBuffer ifNotNil:
-                [Smalltalk unregisterExternalObject: ReadyForBuffer.
-                 ReadyForBuffer := nil]!

Item was added:
+ ----- Method: SoundPlayer class>>stopPlayerProcess: (in category 'player process') -----
+ stopPlayerProcess: hardStop
+        "Stop the sound player process."
+        "SoundPlayer stopPlayerProcess"
+
+        PlayerProcess ifNotNil:
+                [PlayerProcess ~~ Processor activeProcess ifTrue:
+                        [PlayerProcess terminate].
+                 PlayerProcess := nil].
+        (hardStop or: [self soundPluginActive]) ifTrue: [self primSoundStop].
+        ActiveSounds isEmpty ifFalse:
+                [ActiveSounds := OrderedCollection new].
+        Buffer := nil.
+        PlayerSemaphore isEmpty ifFalse:
+                [PlayerSemaphore := Semaphore forMutualExclusion].
+        ReadyForBuffer ifNotNil:
+                [Smalltalk unregisterExternalObject: ReadyForBuffer.
+                 ReadyForBuffer := nil]!





--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Sound-eem.74.mcz

timrowledge


> On 2020-09-21, at 12:50 PM, Eliot Miranda <[hidden email]> wrote:
>
> Hi Christoph,
>
> On Mon, Sep 21, 2020 at 12:35 PM Thiede, Christoph <[hidden email]> wrote:
> Underscore selectors in the Trunk? Is this really necessary?

I have to say I really, really, don't like underscores in selectors myself. But there's a lot of stuff I don't like that I have to put up with, absent my invincible army of flying monkeys.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
A flash of light, a cloud of dust, and...  What was the question?



Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Sound-eem.74.mcz

Chris Muller-3
In reply to this post by Eliot Miranda-2

Underscore selectors in the Trunk? Is this really necessary? 

No, but it leads to a much nicer sounding selector name than any of sixtyFourBitMixSampleCount:into:startingAt:leftVol:rightVol:, mix64BitSampleCount:into:startingAt:leftVol:rightVol:, or mixSampleCount64:into:startingAt:leftVol:rightVol:.  I can change it if it really

IMO, underscores should NOT be any part of the OOTB API!  All three of those alternatives are better Smalltalk convention than the underscore name.  Underscore selectors should be reserved for external frameworks that need it to do their meta stuff.  This blurs any chance for such a convention, while moving the entire trunk community across this line into needing to set Allow Underscore Selectors, and yet, leaves the Preference in the image, extraneous, I guess..?  All for the aesthetic of one selector?


offends you, but I did it for a reason.  I wanted it to read as "this is the 64-bit version of mixSampleCount:into:startingAt:leftVol:rightVol:", and I didn't want it to be over long.  Note that "mix64BitSampleCOunt:" et al are ambiguous.  The samples are not 64-bits, the algorithm is for 64-bits.  But remember that this is a strange method anyway, a translated primitive, with lots of C weirdness in it.  Complaining about the selector is the least of the problems with it ;-)

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? :-)


Well, underscores have neen allowed in Smalltalk for a long time now.  It does lead to some nice usage when interfacing with C.  I certwinly do not use it for normal SMalltalk code. But I would miss it badly if it didn't exist.  I use selectors such as strcpy:_:_: (which maps to strcpy(3)) routinely in the VMMaker.

Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von [hidden email] <[hidden email]>
Gesendet: Samstag, 19. September 2020 18:11:42
An: [hidden email]; [hidden email]
Betreff: [squeak-dev] The Trunk: Sound-eem.74.mcz
 
Eliot Miranda uploaded a new version of Sound to project The Trunk:
http://source.squeak.org/trunk/Sound-eem.74.mcz

==================== Summary ====================

Name: Sound-eem.74
Author: eem
Time: 19 September 2020, 9:11:40.666386 am
UUID: 42a3c2d9-0bed-4310-bcf1-cbe0f3d0653b
Ancestors: Sound-eem.73

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.

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.

=============== Diff against Sound-eem.73 ===============

Item was changed:
  ----- Method: AbstractSound class>>translatedPrimitives (in category 'primitive generation') -----
  translatedPrimitives
         ^#(
                 (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
                 (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
+                (SampledSound _64bitMixSampleCount:into:startingAt:leftVol:rightVol:)
                 (ReverbSound applyReverbTo:startingAt:count:)
         ).
  !

Item was added:
+ ----- Method: SampledSound>>_64bitMixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
+ _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+        "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."
+
+        | lastIndex outIndex sampleIndex sample i s |
+        <inline: #always>
+        <var: #aSoundBuffer type: #'short int *'>
+        <var: #samples type: #'short int *'>
+
+        lastIndex := (startIndex + n) - 1.
+        outIndex := startIndex.    "index of next stereo output sample pair"
+        sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+        [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue:
+                [sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
+                leftVol > 0 ifTrue:
+                        [i := (2 * outIndex) - 1.
+                        s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"
+                        aSoundBuffer at: i put: s].
+                rightVol > 0 ifTrue:
+                        [i := 2 * outIndex.
+                        s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
+                        s >  32767 ifTrue: [s :=  32767].  "clipping!!"
+                        s < -32767 ifTrue: [s := -32767].  "clipping!!"
+                        aSoundBuffer at: i put: s].
+
+                scaledVolIncr ~= 0 ifTrue:
+                        [scaledVol := scaledVol + scaledVolIncr.
+                        ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
+                         [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
+                                ifTrue:  "reached the limit; stop incrementing"
+                                        [scaledVol := scaledVolLimit.
+                                        scaledVolIncr := 0]].
+
+                scaledIndex := scaledIndex + scaledIncrement.
+
+                sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
+                outIndex := outIndex + 1].
+        count := count - n
+ !

Item was changed:
  ----- Method: SampledSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'playing') -----
  mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
+        "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."
-        "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."
 
         | lastIndex outIndex sampleIndex sample i s overflow |
+        <primitive:'primitiveMixSampledSound' module: 'SoundGenerationPlugin'>
+        <var: #aSoundBuffer type: #'short int *'>
+        <var: #samples type: #'short int *'>
-        <primitive:'primitiveMixSampledSound' module:'SoundGenerationPlugin'>
-        <var: #aSoundBuffer declareC: 'short int *aSoundBuffer'>
-        <var: #samples declareC: 'short int *samples'>
 
+        SmallInteger maxVal > 16r3FFFFFFF ifTrue: "In 64-bits we don't have to worry about 2^15 * 2^15 overflow"
+                [^self _64bitMixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol].
         lastIndex := (startIndex + n) - 1.
         outIndex := startIndex.    "index of next stereo output sample pair"
         sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
         [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue: [
                 sample := ((samples at: sampleIndex) * scaledVol) // ScaleFactor.
                 leftVol > 0 ifTrue: [
                         i := (2 * outIndex) - 1.
                         s := (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"
                         aSoundBuffer at: i put: s].
                 rightVol > 0 ifTrue: [
                         i := 2 * outIndex.
                         s := (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
                         s >  32767 ifTrue: [s :=  32767].  "clipping!!"
                         s < -32767 ifTrue: [s := -32767].  "clipping!!"
                         aSoundBuffer at: i put: s].
 
                 scaledVolIncr ~= 0 ifTrue: [
                         scaledVol := scaledVol + scaledVolIncr.
                         ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
                          [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
                                 ifTrue: [  "reached the limit; stop incrementing"
                                         scaledVol := scaledVolLimit.
                                         scaledVolIncr := 0]].
 
                 scaledIndex := scaledIndex + scaledIncrement.
                 scaledIndex >= ScaledIndexOverflow ifTrue: [
                         overflow := scaledIndex >> IncrementFractionBits.
                         indexHighBits := indexHighBits + overflow.
                         scaledIndex := scaledIndex - (overflow << IncrementFractionBits)].
 
                 sampleIndex := indexHighBits + (scaledIndex >> IncrementFractionBits).
                 outIndex := outIndex + 1].
+        count := count - n!
-        count := count - n.
- !

Item was changed:
  ----- Method: SoundPlayer class>>shutDown: (in category 'snapshotting') -----
  shutDown: quitting
         "Stop player process, for example before snapshotting."
 
+        quitting ifTrue:
+                [self stopPlayerProcess: false.
+                 ReverbState := nil]!
-        quitting ifTrue: [
-                self stopPlayerProcess.
-                ReverbState := nil].!

Item was changed:
  ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') -----
  startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound
         "Start the sound player process. Terminate the old process, if any."
         "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false"
 
+        self stopPlayerProcess: true.
+        aSound ifNotNil: "stopPlayerProcess: ensures ActiveSounds are empty..."
+                [ActiveSounds add: aSound].
-        self stopPlayerProcess.
-        aSound
-                ifNil:[ActiveSounds := OrderedCollection new]
-                ifNotNil:[ActiveSounds := OrderedCollection with: aSound].
         Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.
+        LastBuffer ifNotNil:
+                [LastBuffer := SoundBuffer basicNew: Buffer basicSize].
-        LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].
         PlayerSemaphore := Semaphore forMutualExclusion.
         SamplingRate := samplesPerSecond.
         Stereo := stereoFlag.
         SoundSupported := true. "Assume so"
         UseReadySemaphore := true.  "set to false if ready semaphore not supported by VM"
         Smalltalk newExternalSemaphoreDo: [ :semaphore :index |
                 ReadyForBuffer := semaphore.
                 self primSoundStartBufferSize: Buffer stereoSampleCount
                         rate: samplesPerSecond
                         stereo: Stereo
                         semaIndex: index ].
         "Check if sound start prim was successful"
         SoundSupported ifFalse:[
                 Smalltalk unregisterExternalObject: ReadyForBuffer.
                 ReadyForBuffer := nil.
                 ^self ].
         UseReadySemaphore
                 ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]
                 ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].
         UseReverb ifTrue: [self startReverb].
 
         PlayerProcess
                 name: 'Sound Player (', ActiveSounds size asString, ')';
                 priority: Processor userInterruptPriority;
                 resume!

Item was removed:
- ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') -----
- stopPlayerProcess
-        "Stop the sound player process."
-        "SoundPlayer stopPlayerProcess"
-
-        PlayerProcess ifNotNil:
-                [PlayerProcess ~~ Processor activeProcess ifTrue:
-                        [PlayerProcess terminate].
-                 PlayerProcess := nil].
-        "Don't load the SoundPlugin if it is not in use..."
-        self soundPluginActive ifTrue: [self primSoundStop].
-        ActiveSounds isEmpty ifFalse:
-                [ActiveSounds := OrderedCollection new].
-        Buffer := nil.
-        PlayerSemaphore isEmpty ifFalse:
-                [PlayerSemaphore := Semaphore forMutualExclusion].
-        ReadyForBuffer ifNotNil:
-                [Smalltalk unregisterExternalObject: ReadyForBuffer.
-                 ReadyForBuffer := nil]!

Item was added:
+ ----- Method: SoundPlayer class>>stopPlayerProcess: (in category 'player process') -----
+ stopPlayerProcess: hardStop
+        "Stop the sound player process."
+        "SoundPlayer stopPlayerProcess"
+
+        PlayerProcess ifNotNil:
+                [PlayerProcess ~~ Processor activeProcess ifTrue:
+                        [PlayerProcess terminate].
+                 PlayerProcess := nil].
+        (hardStop or: [self soundPluginActive]) ifTrue: [self primSoundStop].
+        ActiveSounds isEmpty ifFalse:
+                [ActiveSounds := OrderedCollection new].
+        Buffer := nil.
+        PlayerSemaphore isEmpty ifFalse:
+                [PlayerSemaphore := Semaphore forMutualExclusion].
+        ReadyForBuffer ifNotNil:
+                [Smalltalk unregisterExternalObject: ReadyForBuffer.
+                 ReadyForBuffer := nil]!





--
_,,,^..^,,,_
best, Eliot