<div dir="ltr"><div>We do have variableDoubleWordSubclass:es now, is it possible and would you be willing to make and instantiate a new kind of SoundBuffer24 to represent them correctly?</div><div><br></div><div><div>Otherwise, will this #createSoundBufferFrom:bitsPerSample: API, do up-conversion as well (e.g., a 16-bit file to 24-bits?), or just down-conversion?  IMO, we should consider moving these "conversion utilities" outward into their own domain, and let Squeak's Sound domain be pure and rigid (signaling Errors when something's wrong), ready for the domain of DSP.</div><div><br></div><div>That's cool if your goal is to improve Playback (as suggested by your commit note), I would just hate to see an automatic and silent truncation of the users input domain (their recordings) without their knowledge.  With no Warning of any kind, it could be worse than getting noise in certain cases..</div></div><div><br></div><div>Regards,</div><div>  Chris</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Dec 25, 2019 at 2:53 PM <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">A new version of Sound was added to project The Inbox:<br>
<a href="http://source.squeak.org/inbox/Sound-tobe.67.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/inbox/Sound-tobe.67.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Sound-tobe.67<br>
Author: tobe<br>
Time: 25 December 2019, 9:52:59.799378 pm<br>
UUID: 3cf4e2e2-48db-4cb4-bbe4-46a2a464e38f<br>
Ancestors: Sound-eem.66<br>
<br>
Support loading 24bit Wave files by converting to 16bit<br>
<br>
While Squeak expects Sound files to be in 16bit format in its SoudBuffer, with this change we now fall back to losing precision of 24bit files instead of pretending to load them and then playing back noise.<br>
<br>
=============== Diff against Sound-eem.66 ===============<br>
<br>
Item was added:<br>
+ ----- Method: SampledSound class>>convertBytesTo24BitSamples: (in category 'utilities') -----<br>
+ convertBytesTo24BitSamples: aByteArray<br>
+ <br>
+       | data n src |<br>
+       n := aByteArray size // 3.<br>
+       data := SoundBuffer newMonoSampleCount: n.<br>
+       src := 1.<br>
+       1 to: n do: [:i | | b1 b2 b3 w |<br>
+               b1 := aByteArray at: src.<br>
+               b2 := aByteArray at: src + 1.<br>
+               b3 := aByteArray at: src + 2.<br>
+               <br>
+               " SoundBuffer only support 16bit at this time, so we divide the amplitudes here to fit "<br>
+               w := ((b3 bitShift: 16) + (b2 bitShift: 8) + b1) // (2 ** 8).<br>
+               w > 32767 ifTrue: [w := w - 65536].<br>
+               data at: i put: w.<br>
+               src := src + 3].<br>
+       <br>
+       ^ data!<br>
<br>
Item was added:<br>
+ ----- Method: SampledSound class>>createSoundBufferFrom:bitsPerSample: (in category 'instance creation') -----<br>
+ createSoundBufferFrom: aByteArray bitsPerSample: aNumber<br>
+ <br>
+       aNumber = 8 ifTrue: [^ self convert8bitUnsignedTo16Bit: aByteArray].<br>
+       aNumber = 16 ifTrue: [^ self convertBytesTo16BitSamples: aByteArray mostSignificantByteFirst: false].<br>
+       aNumber = 24 ifTrue: [^ self convertBytesTo24BitSamples: aByteArray].<br>
+       ^ self error: 'Sound files with ', aNumber asString, ' bits per sample are currently not supported'!<br>
<br>
Item was changed:<br>
  ----- Method: SampledSound class>>fromWaveStream: (in category 'instance creation') -----<br>
  fromWaveStream: fileStream<br>
<br>
        | stream header data type channels samplingRate blockAlign bitsPerSample leftAndRight |<br>
        header := self readWaveChunk: 'fmt ' inRIFF: fileStream.<br>
        data := self readWaveChunk: 'data' inRIFF: fileStream.<br>
        fileStream close.<br>
        stream := ReadStream on: header.<br>
        type := self next16BitWord: false from: stream.<br>
        type = 1 ifFalse: [^ self error:'Unexpected wave format'].<br>
        channels := self next16BitWord: false from: stream.<br>
        (channels < 1 or: [channels > 2])<br>
                ifTrue: [^ self error: 'Unexpected number of wave channels'].<br>
        samplingRate := self next32BitWord: false from: stream.<br>
        stream skip: 4. "skip average bytes per second"<br>
        blockAlign := self next16BitWord: false from: stream.<br>
        bitsPerSample := self next16BitWord: false from: stream.<br>
        (bitsPerSample = 8 or: [bitsPerSample = 16])<br>
                ifFalse: [  "recompute bits per sample"<br>
                        bitsPerSample := (blockAlign // channels) * 8].<br>
+       <br>
+       data := self createSoundBufferFrom: data bitsPerSample: bitsPerSample.<br>
+       <br>
- <br>
-       bitsPerSample = 8<br>
-               ifTrue: [data := self convert8bitUnsignedTo16Bit: data]<br>
-               ifFalse: [data := self convertBytesTo16BitSamples: data mostSignificantByteFirst: false].<br>
- <br>
        channels = 2 ifTrue: [<br>
                leftAndRight := data splitStereo.<br>
                ^ MixedSound new<br>
                        add: (self samples: leftAndRight first samplingRate: samplingRate) pan: 0.0;<br>
                        add: (self samples: leftAndRight last samplingRate: samplingRate) pan: 1.0;<br>
                        yourself].<br>
<br>
        ^ self samples: data samplingRate: samplingRate<br>
  !<br>
<br>
<br>
</blockquote></div>