[squeak-dev] The Inbox: Sound-tobe.67.mcz

Levente Uzonyi leves at caesar.elte.hu
Thu Dec 26 23:35:27 UTC 2019


On Thu, 26 Dec 2019, Chris Muller wrote:

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

DoubleWord means 64-bit per slot, so it's an overkill, a WordArray, which 
has 32-bit per slot would be just fine.
But I'd go for using FloatArrays as the generic sound buffers instead. Why?
- FloatArrays use 32-bit per slot as well.
- They can represent 16-bit and 24-bit wav files without loss.
- Operations on them can keep 24 significant bits no matter what the 
actual magnitude is.
- And, we have some primitives to do vector operations on them (see #*=, 
#+= and friends).
So, while providing better quality than the current (simulated) 16-bit 
buffers, FloatArrays could give us better performance as well.
I think we don't have primitives to convert them back to 16-bit for 
playback yet, but it wouldn't be too hard to add such primitive(s).
Alternatively, a primitive to downsample a FloatArray into a SoundBuffer 
could be added.

Levente

> 
> 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.
> 
> 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..
> 
> Regards,
>   Chris
> 
> 
> 
> 
> 
> 
> On Wed, Dec 25, 2019 at 2:53 PM <commits at source.squeak.org> wrote:
>       A new version of Sound was added to project The Inbox:
>       http://source.squeak.org/inbox/Sound-tobe.67.mcz
>
>       ==================== Summary ====================
>
>       Name: Sound-tobe.67
>       Author: tobe
>       Time: 25 December 2019, 9:52:59.799378 pm
>       UUID: 3cf4e2e2-48db-4cb4-bbe4-46a2a464e38f
>       Ancestors: Sound-eem.66
>
>       Support loading 24bit Wave files by converting to 16bit
>
>       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.
>
>       =============== Diff against Sound-eem.66 ===============
>
>       Item was added:
>       + ----- Method: SampledSound class>>convertBytesTo24BitSamples: (in category 'utilities') -----
>       + convertBytesTo24BitSamples: aByteArray
>       +
>       +       | data n src |
>       +       n := aByteArray size // 3.
>       +       data := SoundBuffer newMonoSampleCount: n.
>       +       src := 1.
>       +       1 to: n do: [:i | | b1 b2 b3 w |
>       +               b1 := aByteArray at: src.
>       +               b2 := aByteArray at: src + 1.
>       +               b3 := aByteArray at: src + 2.
>       +               
>       +               " SoundBuffer only support 16bit at this time, so we divide the amplitudes here to fit "
>       +               w := ((b3 bitShift: 16) + (b2 bitShift: 8) + b1) // (2 ** 8).
>       +               w > 32767 ifTrue: [w := w - 65536].
>       +               data at: i put: w.
>       +               src := src + 3].
>       +       
>       +       ^ data!
>
>       Item was added:
>       + ----- Method: SampledSound class>>createSoundBufferFrom:bitsPerSample: (in category 'instance creation') -----
>       + createSoundBufferFrom: aByteArray bitsPerSample: aNumber
>       +
>       +       aNumber = 8 ifTrue: [^ self convert8bitUnsignedTo16Bit: aByteArray].
>       +       aNumber = 16 ifTrue: [^ self convertBytesTo16BitSamples: aByteArray mostSignificantByteFirst: false].
>       +       aNumber = 24 ifTrue: [^ self convertBytesTo24BitSamples: aByteArray].
>       +       ^ self error: 'Sound files with ', aNumber asString, ' bits per sample are currently not supported'!
>
>       Item was changed:
>         ----- Method: SampledSound class>>fromWaveStream: (in category 'instance creation') -----
>         fromWaveStream: fileStream
>
>               | stream header data type channels samplingRate blockAlign bitsPerSample leftAndRight |
>               header := self readWaveChunk: 'fmt ' inRIFF: fileStream.
>               data := self readWaveChunk: 'data' inRIFF: fileStream.
>               fileStream close.
>               stream := ReadStream on: header.
>               type := self next16BitWord: false from: stream.
>               type = 1 ifFalse: [^ self error:'Unexpected wave format'].
>               channels := self next16BitWord: false from: stream.
>               (channels < 1 or: [channels > 2])
>                       ifTrue: [^ self error: 'Unexpected number of wave channels'].
>               samplingRate := self next32BitWord: false from: stream.
>               stream skip: 4. "skip average bytes per second"
>               blockAlign := self next16BitWord: false from: stream.
>               bitsPerSample := self next16BitWord: false from: stream.
>               (bitsPerSample = 8 or: [bitsPerSample = 16])
>                       ifFalse: [  "recompute bits per sample"
>                               bitsPerSample := (blockAlign // channels) * 8].
>       +       
>       +       data := self createSoundBufferFrom: data bitsPerSample: bitsPerSample.
>       +       
>       -
>       -       bitsPerSample = 8
>       -               ifTrue: [data := self convert8bitUnsignedTo16Bit: data]
>       -               ifFalse: [data := self convertBytesTo16BitSamples: data mostSignificantByteFirst: false].
>       -
>               channels = 2 ifTrue: [
>                       leftAndRight := data splitStereo.
>                       ^ MixedSound new
>                               add: (self samples: leftAndRight first samplingRate: samplingRate) pan: 0.0;
>                               add: (self samples: leftAndRight last samplingRate: samplingRate) pan: 1.0;
>                               yourself].
>
>               ^ self samples: data samplingRate: samplingRate
>         !
> 
> 
> 
>


More information about the Squeak-dev mailing list