jolonf / flac-pascal

FLAC decoder in Pascal
The Unlicense
8 stars 0 forks source link

Does it work? #1

Open Dingo64 opened 2 years ago

Dingo64 commented 2 years ago

I tried it under Lazarus but it didn't convert FLAC to PCM properly. I tested on 2 different FLAC files. I used your original FLACWriteLongIntAsBytes function and then I replaced it with a simplified one:

procedure FLACWriteLongIntAsBytes(output: TStream; value: LongInt; byteCount: Integer);
begin
  output.WriteWord(value and $FFFF);
  output.WriteWord(value shr 16);
end;  

FLAC1: 48 kHz, mono, 32bits/sample FLAC2: 44.1 kHz, stereo, 32bits/sample

Then I used FFMPEG to convert .pcm to .wav: ffmpeg.exe -f u32le -ar 48000 -ac 1 -i test1.pcm -ar 48000 -ac 1 out1.wav ffmpeg.exe -f u32le -ar 44100 -ac 2 -i test2.pcm -ar 48000 -ac 1 out2.wav

The number of samples, sample rate, bits per second returned by streamInfoBlock is correct. The output .wav file has correct duration- same as original. It even kinda sounds similar but with a lot of "scratches".

Maybe I am using ffmpeg incorrectly? Or perhaps this library doesn't like my FLAC files? Can you upload a FLAC file it works fine with? Or how you convert .pcm to .wav?

jolonf commented 2 years ago

I was opening the .pcm files directly with Audacity. There could be an issue with byte order?

I don't recall testing 32 bit FLACs.

Note this isn't well tested. I basically wrote it and then moved onto other projects.

Dingo64 commented 2 years ago

Thank you. This info is very helpful. I tested with 16bit flac + Audacity and works fine. I'll test other bit-depths and let you know.

Dingo64 commented 2 years ago

16 bit flac files work great. I import them into Audacity as: "Signed 16 bit PCM" + "Big endian".

24 bit flac files almost sound good but there are "scratches". Settings same as above.

I tried changing order of bytes saved to disk in FLACWriteLongIntAsBytes but it didn't get me anywhere.

I use Lazarus on Windows (so it's Intel with Little endian). Perhaps you use a Big endian processor?

jolonf commented 2 years ago

I just tried a 24 bit file and got the same result, it plays at the correct speed and volume, and you can hear the music but there is additional static. The overall waveform in Audacity looks mostly the same. I will have a look into it.

I was using an Intel Mac when I wrote the software (using an M1 Mac now). I wrote it out BigEndian as that is the 'standard' network byte order.

jolonf commented 2 years ago

Just an update: I used Audacity to convert a FLAC to raw PCM to compare with flac-pascal's output. Audacity only supports exporting in little endian I've just rearranged them manually below. There is a difference even in the first stereo sample pair.

Here are the first few samples (3 bytes per line):

flac-pascal:   audacity:

000000         000000
000000         FFFFFF  <-- First error on right channel
FFFFFF         FFFFFF
000000         000002
000001         000000
000000         FFFFFE

Note these are small differences and most likely not caused by endianness. FFFFFF is -1 and FFFFFE is -2.

I wrote a short program to test the reading and writing functions from flac-pascal (FLACWriteLongIntAsBytes and TBitRead.ReadSignedBits). Writing out and reading back in the values above and some other values worked fine. I have tried some non 8-bit boundaries but not all.

The interesting thing is that the first sample for each channel is a "warm-up" sample for the LPC decoder (e.g. not encoded). Also there is no channel decorrelation, so there is no further processing on the sample. So for the right channel, flac-pascal reads in 000000 when it should be FFFFFF. Turning on debug logging for flac-pascal shows that the first sample for the second channel is 0, whereas it should be -1.

Because it is the first sample, which is unencoded, and there is no channel decorrelation, it makes it a bit easier to track down, but will take some time...

Dingo64 commented 2 years ago

Thank you for taking the time considering you moved on to other projects. Much appreciated! It will be a very useful library for Lazarus/Delphi because there doesn't seem to be any alternative in pure Pascal.

jolonf commented 2 years ago

It looks like Audacity is doing some processing on the data. I used ffmpeg and the first 3.36 seconds is identical to flac-pascal but is different after that.

I am using the first track from this Linn recording of Handel's messiah:

https://www.linnrecords.com/recording-handel-messiah-dublin-version-1742

It starts with 3 seconds of silence, although it isn't completely silent and flac-pascal decodes those first 297,077 samples correctly.

I used this ffmpeg command to produce the raw PCM:

ffmpeg -i test.flac -f s24be -acodec pcm_s24be output.raw

And this command to find the first difference:

diff --suppress-common-lines -y <(xxd test.pcm) <(xxd output.raw) | more

This could be a little trickier to hunt down. Although I did find one bug in the Verbatim decoding (it should use ReadSignedBits), however fixing that didn't change the output:

https://github.com/jolonf/flac-pascal/blob/9472162584b9cc069b3cad73aaa50fe608cb6394/flac.pas#L546

Dingo64 commented 2 years ago

Maybe this "near-silence" is not a good sample to test? Kinda seems like flac-pascal is truncating/changing the values which don't fit into 16bit.

Dingo64 commented 2 years ago

Hi, any progress? :)