<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>