mmig/libflac.js

Issue with decoding 24 bit audio with libflac.js

Closed this issue · 7 comments

G4Vi commented
$ metaflac --list 5sec.flac 
METADATA block #0
  type: 0 (STREAMINFO)
  is last: false
  length: 34
  minimum blocksize: 4096 samples
  maximum blocksize: 4096 samples
  minimum framesize: 0 bytes
  maximum framesize: 0 bytes
  sample_rate: 96000 Hz
  channels: 2
  bits-per-sample: 24
  total samples: 480000
  MD5 signature: 00000000000000000000000000000000
METADATA block #1
  type: 4 (VORBIS_COMMENT)
  is last: true
  length: 40
  vendor string: reference libFLAC 1.3.0 20130526
  comments: 0
$ flac -d 5sec.flac 

flac 1.3.0, Copyright (C) 2000-2009, 2011-2013  Josh Coalson & Xiph.Org Foundation
flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are
welcome to redistribute it under certain conditions.  Type `flac' for details.

5sec.flac: WARNING, cannot check MD5 signature since it was unset in the STREAMINFO
done         
$ xxd -l 88 5sec.wav 
0000000: 5249 4646 24f2 2b00 5741 5645 666d 7420  RIFF$.+.WAVEfmt 
0000010: 1000 0000 0100 0200 0077 0100 00ca 0800  .........w......
0000020: 0600 1800 6461 7461 00f2 2b00 0237 f43c  ....data..+..7.<
0000030: f8fe fb6a f424 e8fd 6d55 f4ea ccfc 42e6  ...j.$..mU....B.
0000040: f310 bcfb a41c f3d7 bcfa a81a f255 c8f9  .............U..
0000050: f70e f1be e4f8 d333                      .......3

Notice how the first samples do not contain the byte 0xFF.

When 5sec.flac is decoded using decodeFlac, looking at decData[0][0], the data differs.

0: 2 (0x02)​​​​​​
1: 55 (0x37)
​​​​​​2: 244 (0xf4)
​​​​​​3: 255 (0xff)​​​​​​
4: 251 (0xfb)
​​​​​​5: 106 (0x6A)
6: 244 (0xF4)

At first I thought that libflac.js was filling decData with the 4 byte representation of the sample i.e. sign extending from the 24 bit sample to make an int32, but the size of decData does not match up with that.

decData.length
> 118
decData[0][0]
>Uint8Array(12288)
decData[117][0].length
>2304

((117 * 12288)+2304)/4 = 360000
proves decodeFlac is not returning 480000 4 byte samples. However it could be producing 480000 3 byte samples:
((117 * 12288)+2304)/3 = 480000

libflac.js version information:

$ ls -la libflac.js/
630 Aug 22  2019 check-support.js
12734 Oct 20  2019 data-util.js
3114 Oct 20  2019 decode-func.js
382439 Oct 20  2019 libflac4-1.3.2.js
261913 Aug 22  2019 libflac4-1.3.2.wasm.js
22018 Aug 22  2019 libflac4-1.3.2.wasm.wasm
4096 Oct 21  2019 min
$ ls -la libflac.js/min
365681 Aug 22  2019 libflac4-1.3.2.min.js
3474 Aug 22  2019 libflac4-1.3.2.min.js.mem
8975 Aug 22  2019 libflac4-1.3.2.min.js.symbols
122711 Aug 22  2019 libflac4-1.3.2.min.wasm.js
7475 Aug 22  2019 libflac4-1.3.2.min.wasm.js.symbols
124292 Aug 22  2019 libflac4-1.3.2.min.wasm.wasm

would it be possible to make the test audio file 5sec.flac available?

@G4Vi thank you for providing the test file

the problem is basically, that the current implementation does not take padding for "uneven" bit-sizes into account (that is sizes other than 8, 16, 32, ...)

so the data that is returned in the write-callback is too small (since the values for 24-bit are padded to fit in 32-bit)

(and then on the application-side of the code, e.g. for writing the WAV data, the padding needs to be removed)

-> so basically what you also described in your comment:
currently the application treats the decoded data as 3-byte samples, whereas in reality they are 4-byte samples with 1 padding byte

I'll fix this soon, but it will probably take me a week or so, to do this properly

G4Vi commented

@russaa Thanks for looking into it.

I wonder how this ties in to the "triplication" issue if at all.

in ties in in so much, as it does not occur in this case
so the heuristic dealing with the "triplication issue" needs to be disabled for this, otherwise it could destroy the padding/data

I have updated the github repo for correctly decoding 24-bit samples (the new library version is now 5.2.0-beta.1)

the npm package is not updated yet though:
when I have a little more, I would like to check how/if it works for other bits-per-sample settings first, and then update the package

G4Vi commented

I tested out 5.2.0-beta.1, it works great on my 24 bit flac audio files, Thanks.

The padding error message in interleave, helped me discover a bug in my re-encoding end that was silently ignored by various decoders.