Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread Martijn van Beurden

Op 14-08-14 om 02:15 schreef Jose Pablo Carballo:
> Now I've been trying to modify this example to encode a 2ch, 24 bps,
> 96000 sample rate WAV file. I have to say I'm a bit lost on how I
> should read the input file in this case, and how should I pack the
> data to feed the encoder. Any guidance regarding the use of libFLAC,
> the understanding of the format, or anything else that you can notice
> where I'm complete lost, I'll appreciate your help.

I recommend taking a look at the API documentation: 
http://xiph.org/flac/api/group__flac__stream__encoder.html It 
looks like you haven't used 
FLAC__stream_encoder_set_sample_rate() and 
FLAC__stream_encoder_set_bits_per_sample() for example.

___
flac-dev mailing list
flac-dev@xiph.org
http://lists.xiph.org/mailman/listinfo/flac-dev


Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread Jose Pablo Carballo
On Thu, Aug 14, 2014 at 1:13 AM, Martijn van Beurden  wrote:
>
> Op 14-08-14 om 02:15 schreef Jose Pablo Carballo:
>> Now I've been trying to modify this example to encode a 2ch, 24 bps,
>> 96000 sample rate WAV file. I have to say I'm a bit lost on how I
>> should read the input file in this case, and how should I pack the
>> data to feed the encoder. Any guidance regarding the use of libFLAC,
>> the understanding of the format, or anything else that you can notice
>> where I'm complete lost, I'll appreciate your help.
>
> I recommend taking a look at the API documentation:
> http://xiph.org/flac/api/group__flac__stream__encoder.html It
> looks like you haven't used
> FLAC__stream_encoder_set_sample_rate() and
> FLAC__stream_encoder_set_bits_per_sample() for example.
>

Well, my modifications are over the encode encoder test program:
https://git.xiph.org/?p=flac.git;a=blob;f=examples/c/encode/file/main.c;hb=HEAD
. It does call those setters. What I'm trying to do is to convert this
example to work with a 96000 sample rate and 24 bits per sample.
___
flac-dev mailing list
flac-dev@xiph.org
http://lists.xiph.org/mailman/listinfo/flac-dev


Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread Jose Pablo Carballo
Ian's explanation below was helpful:

On Thu, Aug 14, 2014 at 7:53 AM, Ian Nartowicz  wrote:
> The sample rate should take care of itself.  I suspect your difficulty is how
> the 24 bit samples are represented in the WAV data and how to pack them into
> the Flac buffer?
>
> WAV samples are stored in either 8, 16, or 32 bit words, using the smallest
> word size that will fit the sample bits. The words are always little-endian
> formatted and samples smaller than the word size are padded with zero bits.
> Samples are stored with the channels interleaved.
>
> There are two formats to construct the buffer to be submitted to the Flac
> encoder.  The sample program uses the interleaved format which is submitted to
> FLAC__stream_encoder_process_interleaved().  In this format, multiple channels
> are all contained in the same buffer, with the the sample values for each
> channel arranged one after the other, followed by the values for all the
> channels of the next sample, etc.  Aka interleaved.  The other format is
> non-interleaved, where the samples for each channel are stored in separate
> buffers, and an array of those buffers is passed to
> FLAC__stream_encoder_process().  Use whichever is more convenient for you to
> construct from your input data.  Note that the channel order for Flac is not
> the same as for WAVE, although they happen to match for 2 channels.
>
> Each sample value (ie. the 8-24 bits representing a single channel for a 
> single
> sample) is constructed by storing the bits in the low order (the documentation
> calls it "right-justified") of the smallest word that will contain them.  In
> the specific case of 24-bit samples, they need to be stored in the four bytes
> of an int32 with the most significant byte being zero.  This may look 
> identical
> to the WAVE input, but the endianness is native instead of little-endian so it
> isn't safe to simply copy a WAVE sample into the Flac buffer unless you can
> guarantee you are on a little-endian platform.
>
> A cross-platform 24-bit sample packing into a FLAC__int32 would look something
> like this:
> input_buffer[sample * 3 + 2] << 16 |
> input_buffer[sample * 3 + 1] << 8 |
> input_buffer[sample * 3 + 0]
>
> Or you may choose a different method for mapping the sample words from WAVE to
> Flac. The sample word sizes should match and the interleaved buffer formats
> should match (for two channels, not for larger channel counts), only the
> endianness of each word is different. You may even write different code for 
> the
> two endianness cases, which would probably be more efficient.
>
> --ian

Based on this, the code I wrote to fill the pcm buffer looks like this:

pcm[i] = (FLAC__int32)buffer[3*i+2];
pcm[i] <<= 8;
pcm[i] |= (FLAC__int32)buffer[3*i+1];
pcm[i] <<= 8;
pcm[i] |= (FLAC__int32)buffer[3*i];

Thanks for your help.
___
flac-dev mailing list
flac-dev@xiph.org
http://lists.xiph.org/mailman/listinfo/flac-dev


Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread Bastiaan Timmer
> pcm[i] = (FLAC__int32)buffer[3*i+2];
> pcm[i] <<= 8;
> pcm[i] |= (FLAC__int32)buffer[3*i+1];
> pcm[i] <<= 8;
> pcm[i] |= (FLAC__int32)buffer[3*i];



(I might be mistaken but) I think you should realize the 24 bit sample has a 
sign bit in the last of the bytes. Casting the FLAC__byte from the buffer to 
FLAC__int32 will not trat the sign bit as such leading to huge, incorrect 
values (and in a quick tes, to an encoding error). So you should change the 
cast in the first line to a FLAC__int8. The casts in the next lines aren't 
needed at all I think. I was writing up an example for you and came up with the 
following (this is extremely ugly and ineffecient, but should accept 24, 16, or 
any other bits-per-sample):

size_t i;
for (i = 0; i < need*channels; ++i)
{
  pcm[i] = 0;
  size_t s;
  for (s = 0; s < (bps / 8 - 1); ++s)
    pcm[i] |= buffer[(bps / 8) * i + s] << (8 * s);
  pcm[i] |= (FLAC__int8)buffer[(bps / 8) * i + s] << (8 * s);
}
___
flac-dev mailing list
flac-dev@xiph.org
http://lists.xiph.org/mailman/listinfo/flac-dev


Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread lvqcl
Jose Pablo Carballo  wrote:

> - channels = 2;
> - bps = 16;
> + channels = ((unsigned)buffer[23] << 8) | buffer[22];
> + bps = ((unsigned)buffer[35] << 8) | buffer[34];
>   total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
> | buffer[41]) << 8) | buffer[40]) / 4;
>

I suspect that the expression for total_samples should be not

(.) / 4

but

(.) / (channels * bps/8)
___
flac-dev mailing list
flac-dev@xiph.org
http://lists.xiph.org/mailman/listinfo/flac-dev


Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread Jose Pablo Carballo
On Thu, Aug 14, 2014 at 12:34 PM, lvqcl  wrote:
> Jose Pablo Carballo  wrote:
>
>> - channels = 2;
>> - bps = 16;
>> + channels = ((unsigned)buffer[23] << 8) | buffer[22];
>> + bps = ((unsigned)buffer[35] << 8) | buffer[34];
>>   total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
>> | buffer[41]) << 8) | buffer[40]) / 4;
>>
>
> I suspect that the expression for total_samples should be not
>
> (.) / 4
>
> but
>
> (.) / (channels * bps/8)

Yes, that's correct.

Here is the final diff I used to use the example to convert the 24bps file:

diff --git a/examples/c/encode/file/main.c b/examples/c/encode/file/main.c
index e3bdea8..b1cf374 100644
--- a/examples/c/encode/file/main.c
+++ b/examples/c/encode/file/main.c
@@ -40,8 +40,10 @@ static void progress_callback(const
FLAC__StreamEncoder *encoder, FLAC__uint64 b

 #define READSIZE 1024

+#define BPS 24 /* Bits per sample */
+
 static unsigned total_samples = 0; /* can use a 32-bit number due to
WAVE size limitations */
-static FLAC__byte buffer[READSIZE/*samples*/ * 2/*bytes_per_sample*/
* 2/*channels*/]; /* we read the WAVE data into here */
+static FLAC__byte buffer[READSIZE/*samples*/ * BPS/8
/*bytes_per_sample*/ * 2/*channels*/]; /* we read the WAVE data into
here */
 static FLAC__int32 pcm[READSIZE/*samples*/ * 2/*channels*/];

 int main(int argc, char *argv[])
@@ -73,14 +75,18 @@ int main(int argc, char *argv[])
  memcmp(buffer+8, "WAVEfmt \020\000\000\000\001\000\002\000", 16) ||
  memcmp(buffer+32, "\004\000\020\000data", 8)
  ) {
+#if BPS == 16
  fprintf(stderr, "ERROR: invalid/unsupported WAVE file, only 16bps
stereo WAVE in canonical form allowed\n");
  fclose(fin);
  return 1;
+#elif BPS == 24
+ /* TODO: check wav header for 24bps */
+#endif
  }
  sample_rate = ((unsigned)buffer[27] << 8) | buffer[26]) << 8) |
buffer[25]) << 8) | buffer[24];
- channels = 2;
- bps = 16;
- total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
| buffer[41]) << 8) | buffer[40]) / 4;
+ channels = ((unsigned)buffer[23] << 8) | buffer[22];
+ bps = ((unsigned)buffer[35] << 8) | buffer[34];
+ total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
| buffer[41]) << 8) | buffer[40]) / (channels * bps/8);

  /* allocate the encoder */
  if((encoder = FLAC__stream_encoder_new()) == NULL) {
@@ -89,7 +95,12 @@ int main(int argc, char *argv[])
  return 1;
  }

- ok &= FLAC__stream_encoder_set_verify(encoder, true);
+ if (bps == 16) {
+ /* TODO: Understand why verify doesn't work for 24bps - fails with
+ *   FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA when calling
+ *   FLAC__stream_encoder_process_interleaved().*/
+ ok &= FLAC__stream_encoder_set_verify(encoder, true);
+ }
  ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
  ok &= FLAC__stream_encoder_set_channels(encoder, channels);
  ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
@@ -138,11 +149,23 @@ int main(int argc, char *argv[])
  /* convert the packed little-endian 16-bit PCM samples from WAVE
into an interleaved FLAC__int32 buffer for libFLAC */
  size_t i;
  for(i = 0; i < need*channels; i++) {
- /* inefficient but simple and works on big- or little-endian machines */
- pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8)
| (FLAC__int16)buffer[2*i]);
+ if (bps == 16) {
+ /* inefficient but simple and works on big- or little-endian machines */
+ pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8)
| (FLAC__int16)buffer[2*i]);
+ } else if (bps == 24) {
+ pcm[i] = (FLAC__int32)buffer[3*i+2];
+ pcm[i] <<= 8;
+ pcm[i] |= (FLAC__int32)buffer[3*i+1];
+ pcm[i] <<= 8;
+ pcm[i] |= (FLAC__int32)buffer[3*i];
+ }
  }
  /* feed samples to encoder */
  ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need);
+ if (!ok) {
+ fprintf(stderr, "encoding: FLAC__stream_encoder_process_interleaved FAILED");
+ fprintf(stderr, "   state: %s\n",
FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]);
+ }
  }
  left -= need;
  }
___
flac-dev mailing list
flac-dev@xiph.org
http://lists.xiph.org/mailman/listinfo/flac-dev


Re: [flac-dev] Encoder example for 24-bit files

2014-08-14 Thread Jose Pablo Carballo
Probably attaching the file is more readable.

Thanks for your help.

On Thu, Aug 14, 2014 at 2:12 PM, Jose Pablo Carballo
 wrote:
> On Thu, Aug 14, 2014 at 12:34 PM, lvqcl  wrote:
>> Jose Pablo Carballo  wrote:
>>
>>> - channels = 2;
>>> - bps = 16;
>>> + channels = ((unsigned)buffer[23] << 8) | buffer[22];
>>> + bps = ((unsigned)buffer[35] << 8) | buffer[34];
>>>   total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
>>> | buffer[41]) << 8) | buffer[40]) / 4;
>>>
>>
>> I suspect that the expression for total_samples should be not
>>
>> (.) / 4
>>
>> but
>>
>> (.) / (channels * bps/8)
>
> Yes, that's correct.
>
> Here is the final diff I used to use the example to convert the 24bps file:
>
> diff --git a/examples/c/encode/file/main.c b/examples/c/encode/file/main.c
> index e3bdea8..b1cf374 100644
> --- a/examples/c/encode/file/main.c
> +++ b/examples/c/encode/file/main.c
> @@ -40,8 +40,10 @@ static void progress_callback(const
> FLAC__StreamEncoder *encoder, FLAC__uint64 b
>
>  #define READSIZE 1024
>
> +#define BPS 24 /* Bits per sample */
> +
>  static unsigned total_samples = 0; /* can use a 32-bit number due to
> WAVE size limitations */
> -static FLAC__byte buffer[READSIZE/*samples*/ * 2/*bytes_per_sample*/
> * 2/*channels*/]; /* we read the WAVE data into here */
> +static FLAC__byte buffer[READSIZE/*samples*/ * BPS/8
> /*bytes_per_sample*/ * 2/*channels*/]; /* we read the WAVE data into
> here */
>  static FLAC__int32 pcm[READSIZE/*samples*/ * 2/*channels*/];
>
>  int main(int argc, char *argv[])
> @@ -73,14 +75,18 @@ int main(int argc, char *argv[])
>   memcmp(buffer+8, "WAVEfmt \020\000\000\000\001\000\002\000", 16) ||
>   memcmp(buffer+32, "\004\000\020\000data", 8)
>   ) {
> +#if BPS == 16
>   fprintf(stderr, "ERROR: invalid/unsupported WAVE file, only 16bps
> stereo WAVE in canonical form allowed\n");
>   fclose(fin);
>   return 1;
> +#elif BPS == 24
> + /* TODO: check wav header for 24bps */
> +#endif
>   }
>   sample_rate = ((unsigned)buffer[27] << 8) | buffer[26]) << 8) |
> buffer[25]) << 8) | buffer[24];
> - channels = 2;
> - bps = 16;
> - total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
> | buffer[41]) << 8) | buffer[40]) / 4;
> + channels = ((unsigned)buffer[23] << 8) | buffer[22];
> + bps = ((unsigned)buffer[35] << 8) | buffer[34];
> + total_samples = (((unsigned)buffer[43] << 8) | buffer[42]) << 8)
> | buffer[41]) << 8) | buffer[40]) / (channels * bps/8);
>
>   /* allocate the encoder */
>   if((encoder = FLAC__stream_encoder_new()) == NULL) {
> @@ -89,7 +95,12 @@ int main(int argc, char *argv[])
>   return 1;
>   }
>
> - ok &= FLAC__stream_encoder_set_verify(encoder, true);
> + if (bps == 16) {
> + /* TODO: Understand why verify doesn't work for 24bps - fails with
> + *   FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA when calling
> + *   FLAC__stream_encoder_process_interleaved().*/
> + ok &= FLAC__stream_encoder_set_verify(encoder, true);
> + }
>   ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
>   ok &= FLAC__stream_encoder_set_channels(encoder, channels);
>   ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
> @@ -138,11 +149,23 @@ int main(int argc, char *argv[])
>   /* convert the packed little-endian 16-bit PCM samples from WAVE
> into an interleaved FLAC__int32 buffer for libFLAC */
>   size_t i;
>   for(i = 0; i < need*channels; i++) {
> - /* inefficient but simple and works on big- or little-endian machines */
> - pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8)
> | (FLAC__int16)buffer[2*i]);
> + if (bps == 16) {
> + /* inefficient but simple and works on big- or little-endian machines */
> + pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8)
> | (FLAC__int16)buffer[2*i]);
> + } else if (bps == 24) {
> + pcm[i] = (FLAC__int32)buffer[3*i+2];
> + pcm[i] <<= 8;
> + pcm[i] |= (FLAC__int32)buffer[3*i+1];
> + pcm[i] <<= 8;
> + pcm[i] |= (FLAC__int32)buffer[3*i];
> + }
>   }
>   /* feed samples to encoder */
>   ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need);
> + if (!ok) {
> + fprintf(stderr, "encoding: FLAC__stream_encoder_process_interleaved 
> FAILED");
> + fprintf(stderr, "   state: %s\n",
> FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]);
> + }
>   }
>   left -= need;
>   }
diff --git a/examples/c/encode/file/main.c b/examples/c/encode/file/main.c
index e3bdea8..b1cf374 100644
--- a/examples/c/encode/file/main.c
+++ b/examples/c/encode/file/main.c
@@ -40,8 +40,10 @@ static void progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 b
 
 #define READSIZE 1024
 
+#define BPS 24 /* Bits per sample */
+
 static unsigned total_samples = 0; /* can use a 32-bit number due to WAVE size limitations */
-static FLAC__byte buffer[READSIZE/*samples*/ * 2/*bytes_per_sample*/ * 2/*channels*/]; /* we read the WAVE data into here */
+static FLAC__byte buffer[READSIZE/*samples*/ * BPS/8 /*bytes_per_sample*/ * 2/*channel