jiro4989 / wave

The wave is a tiny WAV sound module
https://jiro4989.github.io/wave/wave.html
22 stars 0 forks source link

readFrames result different from other packages #12

Open 3210jr opened 1 year ago

3210jr commented 1 year ago

Hey @jiro4989, thanks for the awesome package!

This might be a skill issue or a misunderstanding on my part, but the outputs of wav.readFrames looks like this:

@[126, 0, 126, 0, 118, 0, 112, 0, 121, 0, 125, 0, 118, 0, 118, 0, 123, 0, 126, 0, 117]

While the output from scipy.io's wavfile package looks like this:

array([ 126,  126,  118,  112,  121,  125,  118,  118,  123,  126,  117,
        116,  118,  103,  100,  112,  111,  101,  106,  117,  115,  125])

It seems like the values are the same only that the nim version has "0"'s in between the values. This continues up to around the 400th frame and the results no longer match at all.

I am using: nim v2.0

The wave file I'm reading has the following metadata:

(riffChunkDescriptor: (id: "RIFF", size: 12503872, format: "WAVE"), formatSubChunk: (id: "fmt ", size: 16, format: 1, numChannels: 1, sampleRate: 44100, byteRate: 88200, blockAlign: 2, bitsPerSample: 16, extendedSize: 0, extended: @[]), dataSubChunk: (id: "data", size: 12503636, data: ...), factSubChunk: nil, audioStartPos: 44)

Is there some more information that you need?

Thanks again!

jiro4989 commented 1 year ago

readFrames is a very simple procedure that just reads streams of dataSubChunk one byte at a time. (readFrames)

Please wait while I check the WAVE file specifications.

jiro4989 commented 1 year ago

@3210jr I am late. The cause is not using bitsPerSample.

My wave library currently processes frames as 8bit data. But your wave file has bitsPerSample of 16. In other words, it must be processed as 16bit.

The wBitsPerSample field specifies the number of bits of data used to represent each sample of each channel. If there are multiple channels, the sample size is the same for each channel.

Ref: https://www.aelius.com/njh/wavemetatools/doc/riffmci.pdf

This is my BUG.

The return value of the readFrames procedure is a byte sequence (seq[byte]). In other words, only 1 byte frames can be returned correctly. Therefore, it is necessary to change it so that it can handle N byte frames. But it is BREAKING CHANGES.

For now, I will add a procedure that can handle N byte frames to maintain backward compatibility.

Ref

Python wave can handle N byte frames. See: https://github.com/python/cpython/blob/3.12/Lib/wave.py#L365-L367