[squeak-dev] The Inbox: Sound-dtl.67.mcz
Levente Uzonyi
leves at caesar.elte.hu
Wed Dec 11 11:32:41 UTC 2019
On Wed, 11 Dec 2019, commits at source.squeak.org wrote:
> David T. Lewis uploaded a new version of Sound to project The Inbox:
> http://source.squeak.org/inbox/Sound-dtl.67.mcz
>
> ==================== Summary ====================
>
> Name: Sound-dtl.67
> Author: dtl
> Time: 10 December 2019, 10:51:04.985835 pm
> UUID: ca970845-8428-41f9-b83c-f64a6cc732c1
> Ancestors: Sound-eem.66
>
> Sound mixing improvements by St?phane Rollandin (spfa).
> Allow adjusting volume of mixed sounds while playing.
> Original discussion at http://forum.world.st/Adjusting-the-volume-of-a-sound-as-it-s-playing-td5102562.html
> Patches posted to squeak-dev at http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-December/205440.html
>
> =============== Diff against Sound-eem.66 ===============
>
> Item was changed:
> ----- Method: AbstractSound>>loudness (in category 'volume') -----
> loudness
> "Answer the current volume setting for this sound."
>
> + self hasVolumeEnvelope ifTrue: [^ self volumeEnvelope scale].
I don't see #hasVolumeEnvelope and #volumeEnvelope in the Trunk.
> +
> + ^ scaledVol asFloat / ScaleFactor!
> - ^ scaledVol asFloat / ScaleFactor asFloat!
This seems to be a place where the currently unused FloatScaleFactor
variable could be used.
>
> Item was changed:
> ----- Method: MixedSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'sound generation') -----
> mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
> "Play a number of sounds concurrently. The level of each sound can be set independently for the left and right channels."
>
> | snd left right |
> 1 to: sounds size do: [:i |
> (soundDone at: i) ifFalse: [
> snd := sounds at: i.
> + left := (leftVol * (leftVols at: i) * scaledVol / ScaleFactor) // ScaleFactor.
> + right := (rightVol * (rightVols at: i) * scaledVol / ScaleFactor) // ScaleFactor.
Assuming that leftVol, rightVol are integers, and leftVols and rightVols
are arrays of integers, #/ is very likely to introduce Fractions, and the
triple multiplication may introduce LargeIntegers in 32-bit images.
(due to the use of #///, leftVol and rightVol are sometimes Floats, so
the above doesn't apply for those cases).
#// may introduce noise without dithering. Perhaps it would be better to
precalculate a constant outside the loop (e.g: scaledVol /
FloatScaleFactor / FloatScaleFactor), and inside the loop multiply with
that constant. I'm not an audio engineer, so I don't know if it's better
to round than to truncate there, but truncation (as it is happening now
via #//) will introduce some noise for sure, which could be masked by
dithering.
> - left := (leftVol * (leftVols at: i)) // ScaleFactor.
> - right := (rightVol * (rightVols at: i)) // ScaleFactor.
> snd samplesRemaining > 0
> ifTrue: [
> snd mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: left rightVol: right]
> ifFalse: [soundDone at: i put: true]]].
> !
>
> Item was changed:
> ----- Method: RepeatingSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'sound generation') -----
> mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
> "Play a collection of sounds in sequence."
> "(RepeatingSound new
> setSound: FMSound majorScale
> iterations: 2) play"
>
> | i count samplesNeeded |
> iteration <= 0 ifTrue: [^ self].
> i := startIndex.
> samplesNeeded := n.
> [samplesNeeded > 0] whileTrue: [
> count := sound samplesRemaining min: samplesNeeded.
> count = 0 ifTrue: [
> iterationCount == #forever
> ifFalse: [
> iteration := iteration - 1.
> iteration <= 0 ifTrue: [^ self]]. "done"
> sound reset.
> count := sound samplesRemaining min: samplesNeeded.
> count = 0 ifTrue: [^ self]]. "zero length sound"
> sound mixSampleCount: count
> into: aSoundBuffer
> startingAt: i
> + leftVol: leftVol * scaledVol // ScaleFactor
> + rightVol: rightVol * scaledVol // ScaleFactor.
Since this method is sent with Float leftVol and rightVol arguments,
perhaps it's worth keeping precision by not truncating to integers here
too.
Levente
> - leftVol: leftVol
> - rightVol: rightVol.
> i := i + count.
> samplesNeeded := samplesNeeded - count].
> !
>
> Item was changed:
> ----- Method: SequentialSound>>mixSampleCount:into:startingAt:leftVol:rightVol: (in category 'sound generation') -----
> mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
> "Play a collection of sounds in sequence."
> "PluckedSound chromaticScale play"
>
> + | finalIndex i snd remaining count leftScaledVol rightScaledVol |
> - | finalIndex i snd remaining count |
> currentIndex = 0 ifTrue: [^ self]. "already done"
> +
> + leftScaledVol := leftVol * scaledVol /// ScaleFactor.
> + rightScaledVol := rightVol * scaledVol /// ScaleFactor.
> +
> finalIndex := (startIndex + n) - 1.
> i := startIndex.
> [i <= finalIndex] whileTrue: [
> snd := (sounds at: currentIndex).
> [(remaining := snd samplesRemaining) <= 0] whileTrue: [
> "find next undone sound"
> currentIndex < sounds size
> ifTrue: [
> currentIndex := currentIndex + 1.
> snd := (sounds at: currentIndex)]
> ifFalse: [
> currentIndex := 0.
> ^ self]]. "no more sounds"
> count := (finalIndex - i) + 1.
> remaining < count ifTrue: [count := remaining].
> + snd mixSampleCount: count into: aSoundBuffer startingAt: i
> + leftVol: leftScaledVol
> + rightVol: rightScaledVol.
> - snd mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: leftVol rightVol: rightVol.
> i := i + count].
> !
>
>
More information about the Squeak-dev
mailing list
|