main.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* example_c_decode_file - Simple FLAC file decoder using libFLAC
  2. * Copyright (C) 2007-2009 Josh Coalson
  3. * Copyright (C) 2011-2023 Xiph.Org Foundation
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19. /*
  20. * This example shows how to use libFLAC to decode a FLAC file to a WAVE
  21. * file. It only supports 16-bit stereo files.
  22. *
  23. * Complete API documentation can be found at:
  24. * http://xiph.org/flac/api/
  25. */
  26. #ifdef HAVE_CONFIG_H
  27. # include <config.h>
  28. #endif
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include "share/compat.h"
  32. #include "FLAC/stream_decoder.h"
  33. static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
  34. static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
  35. static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
  36. static FLAC__uint64 total_samples = 0;
  37. static unsigned sample_rate = 0;
  38. static unsigned channels = 0;
  39. static unsigned bps = 0;
  40. static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 x)
  41. {
  42. return
  43. fputc(x, f) != EOF &&
  44. fputc(x >> 8, f) != EOF
  45. ;
  46. }
  47. static FLAC__bool write_little_endian_int16(FILE *f, FLAC__int16 x)
  48. {
  49. return write_little_endian_uint16(f, (FLAC__uint16)x);
  50. }
  51. static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 x)
  52. {
  53. return
  54. fputc(x, f) != EOF &&
  55. fputc(x >> 8, f) != EOF &&
  56. fputc(x >> 16, f) != EOF &&
  57. fputc(x >> 24, f) != EOF
  58. ;
  59. }
  60. int main(int argc, char *argv[])
  61. {
  62. FLAC__bool ok = true;
  63. FLAC__StreamDecoder *decoder = 0;
  64. FLAC__StreamDecoderInitStatus init_status;
  65. FILE *fout;
  66. if(argc != 3) {
  67. fprintf(stderr, "usage: %s infile.flac outfile.wav\n", argv[0]);
  68. return 1;
  69. }
  70. if((fout = fopen(argv[2], "wb")) == NULL) {
  71. fprintf(stderr, "ERROR: opening %s for output\n", argv[2]);
  72. return 1;
  73. }
  74. if((decoder = FLAC__stream_decoder_new()) == NULL) {
  75. fprintf(stderr, "ERROR: allocating decoder\n");
  76. fclose(fout);
  77. return 1;
  78. }
  79. (void)FLAC__stream_decoder_set_md5_checking(decoder, true);
  80. init_status = FLAC__stream_decoder_init_file(decoder, argv[1], write_callback, metadata_callback, error_callback, /*client_data=*/fout);
  81. if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
  82. fprintf(stderr, "ERROR: initializing decoder: %s\n", FLAC__StreamDecoderInitStatusString[init_status]);
  83. ok = false;
  84. }
  85. if(ok) {
  86. ok = FLAC__stream_decoder_process_until_end_of_stream(decoder);
  87. fprintf(stderr, "decoding: %s\n", ok? "succeeded" : "FAILED");
  88. fprintf(stderr, " state: %s\n", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(decoder)]);
  89. }
  90. FLAC__stream_decoder_delete(decoder);
  91. fclose(fout);
  92. return 0;
  93. }
  94. FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
  95. {
  96. FILE *f = (FILE*)client_data;
  97. const FLAC__uint32 total_size = (FLAC__uint32)(total_samples * channels * (bps/8));
  98. size_t i;
  99. (void)decoder;
  100. if(total_samples == 0) {
  101. fprintf(stderr, "ERROR: this example only works for FLAC files that have a total_samples count in STREAMINFO\n");
  102. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  103. }
  104. if(channels != 2 || bps != 16) {
  105. fprintf(stderr, "ERROR: this example only supports 16bit stereo streams\n");
  106. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  107. }
  108. if(frame->header.channels != 2) {
  109. fprintf(stderr, "ERROR: This frame contains %u channels (should be 2)\n", frame->header.channels);
  110. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  111. }
  112. if(buffer [0] == NULL) {
  113. fprintf(stderr, "ERROR: buffer [0] is NULL\n");
  114. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  115. }
  116. if(buffer [1] == NULL) {
  117. fprintf(stderr, "ERROR: buffer [1] is NULL\n");
  118. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  119. }
  120. /* write WAVE header before we write the first frame */
  121. if(frame->header.number.sample_number == 0) {
  122. if(
  123. fwrite("RIFF", 1, 4, f) < 4 ||
  124. !write_little_endian_uint32(f, total_size + 36) ||
  125. fwrite("WAVEfmt ", 1, 8, f) < 8 ||
  126. !write_little_endian_uint32(f, 16) ||
  127. !write_little_endian_uint16(f, 1) ||
  128. !write_little_endian_uint16(f, (FLAC__uint16)channels) ||
  129. !write_little_endian_uint32(f, sample_rate) ||
  130. !write_little_endian_uint32(f, sample_rate * channels * (bps/8)) ||
  131. !write_little_endian_uint16(f, (FLAC__uint16)(channels * (bps/8))) || /* block align */
  132. !write_little_endian_uint16(f, (FLAC__uint16)bps) ||
  133. fwrite("data", 1, 4, f) < 4 ||
  134. !write_little_endian_uint32(f, total_size)
  135. ) {
  136. fprintf(stderr, "ERROR: write error\n");
  137. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  138. }
  139. }
  140. /* write decoded PCM samples */
  141. for(i = 0; i < frame->header.blocksize; i++) {
  142. if(
  143. !write_little_endian_int16(f, (FLAC__int16)buffer[0][i]) || /* left channel */
  144. !write_little_endian_int16(f, (FLAC__int16)buffer[1][i]) /* right channel */
  145. ) {
  146. fprintf(stderr, "ERROR: write error\n");
  147. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  148. }
  149. }
  150. return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  151. }
  152. void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
  153. {
  154. (void)decoder, (void)client_data;
  155. /* print some stats */
  156. if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
  157. /* save for later */
  158. total_samples = metadata->data.stream_info.total_samples;
  159. sample_rate = metadata->data.stream_info.sample_rate;
  160. channels = metadata->data.stream_info.channels;
  161. bps = metadata->data.stream_info.bits_per_sample;
  162. fprintf(stderr, "sample rate : %u Hz\n", sample_rate);
  163. fprintf(stderr, "channels : %u\n", channels);
  164. fprintf(stderr, "bits per sample: %u\n", bps);
  165. fprintf(stderr, "total samples : %" PRIu64 "\n", total_samples);
  166. }
  167. }
  168. void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
  169. {
  170. (void)decoder, (void)client_data;
  171. fprintf(stderr, "Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
  172. }