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

Jose Pablo Carballo jose.carballo at ridgerun.com
Thu Aug 14 13:12:58 PDT 2014


On Thu, Aug 14, 2014 at 12:34 PM, lvqcl <lvqcl.mail at gmail.com> wrote:
> Jose Pablo Carballo <jose.carballo at ridgerun.com> 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;
  }


More information about the flac-dev mailing list