Rillke/flac.js

Encoding Raw Data to Flac

mertakdut opened this issue · 11 comments

Hello,

Getting an error while trying to encode raw data which I decoded by using Web Audio Api's decodeAudioData method.

var fileName = "pcmData";
var encodedName = "encoded.flac";

var args = [
  "--sample-rate=16",
  "--sign=signed",
  "--channels=1",
  "--bps=16",
  "--endian=big",
  fileName
];

var inData = {};
inData[fileName] = buffer;

var outData = {};
outData[encodedName] = {
  // Its MIME type
  'MIME': 'audio/flac'
};

worker.postMessage({
  command: 'encode',
  args: args,
  outData: outData,
  fileData: inData
});

Worker message gives me,

e.data.reply= err
e.data.values[0]= No such file or directory

Hey @mertakdut

  1. please use pcmData.raw as fileName
  2. please use pcmData.flac as encodedName (most important bit here: either you catch the flac generated file or you specify the -o option to force an output file name)
  3. buffer should be an Uint8Array.
  4. --sample-rate=16000
  5. Please submit an improvement to README.md (or to the code) so you or future visitors won't stumble over that issue.
var fr = new FileReader();
fr.onloadend = function() {

var fileName = "pcmData.raw";
var encodedName = "pcmData.flac";

var args = [
  "--sample-rate=16000",
  "--sign=signed",
  "--channels=1",
  "--bps=16",
  "--endian=little",
  fileName
];

var inData = {};
inData[fileName] = new Uint8Array(fr.result);

var outData = {};
outData[encodedName] = {
  // Its MIME type
  'MIME': 'audio/flac'
};
worker.onmessage = function() {console.log(arguments);}
worker.postMessage({
  command: 'encode',
  args: args,
  outData: outData,
  fileData: inData
});

};
fr.readAsArrayBuffer( document.getElementById('abc').files[0] );

Since I am getting float32Array from decodeAudioData output AudioBuffer.getChannelData, I need to convert the float32array to uInt8Array. When I use it with new Uint8Array(float32Array.buffer) the data is corrupted; only hearing sizzling sound.

Once I solve the problem, I'll provide the code for raw data encoding.

When I use it with new Uint8Array(float32Array.buffer) the data is corrupted; only hearing sizzling sound.

Maybe there is a way to pass the float32-data directly to the flac command line executable. No time right now to look into this.

convert the float32array to uInt8Array

Looking for function floatTo16BitPCM?

https://github.com/mattdiamond/Recorderjs/blob/08e7abd99739be6946f19f6806ccb368138f2dd3/src/recorder.js#L142

The uInt8Array is for internal processing only getting offsets and file size calculations right etc. You shouldn't have to reduce the bit per sample (bps).

Maybe upload your audio sample here so others can help?

Here is the raw data (I'll be breaking the copyrights if they decode & play the file :)). It can be tested with options (I suggest through Audacity File -> Import -> Raw Data...):

  • Encoding: 32-bit float
  • Byte Order: Little-endian
  • Channels: 1 Channel (Mono)
  • Sample Rate: 16000 Hz

I'll check the flac for direct float32 input.

Looking for function floatTo16BitPCM?

Tried this (and close alternatives) with "--sign=signed" argument.

var output = new Int8Array(input.length);

for (var i = 0; i < input.length; i++) {
  var s = Math.max(-1, Math.min(1, input[i]));
  output[i] = s < 0 ? s * 0x0080 : s * 0x007F;
}

return output;

Outputs:

pcmData.raw: ERROR: got partial sample

Okay. Now able to convert float32 to uint8 without corrupting IEEE 754 representation.

var output = new Uint8Array(float32Array.length);

for (var i = 0; i < float32Array.length; i++) {
  var tmp = Math.max(-1, Math.min(1, float32Array[i]));
  tmp = tmp < 0 ? (tmp * 0x8000) : (tmp * 0x7FFF);
  tmp = tmp / 256;
  output[i] = tmp + 128;
}

return output;

But issue11 gets in the way: Integer Overflow.

My tests with flac 1.3.2 win64, Uint8 encoded data with command flac --endian=little --sign=unsigned --channels=1 --bps=8 --sample-rate=16000 path/to/uint8comi have been successful.

Again the raw data can be tested by using Audacity's Import Raw Data feature. Encoding should be set to Unsigned 8-bit PCM.

But issue11 gets in the way: Integer Overflow.

That is now fixed. Sorry for the long delay.

It's working now. Shall we put the pcm conversion example to readme for further information? Usage section is quite dull atm.

@mertakdut Great :) Can you submit a pull request?

Done.