3 ** This program is distributed under the GNU General Public License, version 2.
4 ** A copy of this license is included with this source.
6 ** Copyright 2002, Stan Seibert <volsung@xiph.org>
17 #include <sys/types.h>
19 #include <flac/metadata.h>
26 #if !defined(FLAC_API_VERSION_CURRENT) || (FLAC_API_VERSION_CURRENT < 8)
27 #define NEED_EASYFLAC 1
31 static FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
32 static FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
33 static void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
34 static void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
36 static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
37 static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
38 static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
39 static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
40 static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data);
43 static void resize_buffer(flacfile *flac, int newchannels, int newsamples);
44 static void copy_comments (vorbis_comment *v_comments, FLAC__StreamMetadata_VorbisComment *f_comments);
47 int flac_id(unsigned char *buf, int len)
49 if (len < 4) return 0;
51 return memcmp(buf, "fLaC", 4) == 0;
55 int oggflac_id(unsigned char *buf, int len)
57 if (len < 33) return 0;
59 return memcmp(buf, "OggS", 4) == 0 &&
60 (memcmp (buf+28, "\177FLAC", 5) == 0 || flac_id(buf+28, len - 28));
64 int flac_open(FILE *in, oe_enc_opt *opt, unsigned char *oldbuf, int buflen)
66 flacfile *flac = malloc(sizeof(flacfile));
71 flac->totalsamples = 0;
72 flac->comments = NULL;
76 /* Setup empty audio buffer that will be resized on first frame
83 /* Copy old input data over */
84 flac->oldbuf = malloc(buflen);
85 flac->oldbuf_len = buflen;
86 memcpy(flac->oldbuf, oldbuf, buflen);
87 flac->oldbuf_start = 0;
89 /* Need to save FILE pointer for read callback */
92 /* Setup FLAC decoder */
94 flac->decoder = EasyFLAC__stream_decoder_new(oggflac_id(oldbuf, buflen));
95 EasyFLAC__set_client_data(flac->decoder, flac);
96 EasyFLAC__set_read_callback(flac->decoder, &easyflac_read_callback);
97 EasyFLAC__set_write_callback(flac->decoder, &easyflac_write_callback);
98 EasyFLAC__set_metadata_callback(flac->decoder, &easyflac_metadata_callback);
99 EasyFLAC__set_error_callback(flac->decoder, &easyflac_error_callback);
100 EasyFLAC__set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_STREAMINFO);
101 EasyFLAC__set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
102 EasyFLAC__init(flac->decoder);
104 flac->decoder = FLAC__stream_decoder_new();
105 FLAC__stream_decoder_set_md5_checking(flac->decoder, false);
106 FLAC__stream_decoder_set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_STREAMINFO);
107 FLAC__stream_decoder_set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
108 if(oggflac_id(oldbuf, buflen))
109 FLAC__stream_decoder_init_ogg_stream(flac->decoder, read_callback, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, eof_callback, write_callback, metadata_callback, error_callback, flac);
111 FLAC__stream_decoder_init_stream(flac->decoder, read_callback, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, eof_callback, write_callback, metadata_callback, error_callback, flac);
114 /* Callback will set the total samples and sample rate */
116 EasyFLAC__process_until_end_of_metadata(flac->decoder);
118 FLAC__stream_decoder_process_until_end_of_metadata(flac->decoder);
121 /* Callback will set the number of channels and resize the
124 EasyFLAC__process_single(flac->decoder);
126 FLAC__stream_decoder_process_single(flac->decoder);
129 /* Copy format info for caller */
130 opt->rate = flac->rate;
131 opt->channels = flac->channels;
132 /* flac->total_samples_per_channel was already set by metadata
133 callback when metadata was processed. */
134 opt->total_samples_per_channel = flac->totalsamples;
135 /* Copy Vorbis-style comments from FLAC file (read in metadata
137 if (flac->comments != NULL && opt->copy_comments)
138 copy_comments(opt->comments, &flac->comments->data.vorbis_comment);
139 opt->read_samples = flac_read;
140 opt->readdata = (void *)flac;
145 /* FLAC follows the WAV channel ordering pattern; we must permute to
146 put things in Vorbis channel order */
147 static int wav_permute_matrix[8][8] =
150 {0,1}, /* 2.0 stereo */
151 {0,2,1}, /* 3.0 channel ('wide') stereo */
152 {0,1,2,3}, /* 4.0 discrete quadraphonic */
153 {0,2,1,3,4}, /* 5.0 surround */
154 {0,2,1,4,5,3}, /* 5.1 surround */
155 {0,2,1,4,5,6,3}, /* 6.1 surround */
156 {0,2,1,6,7,4,5,3} /* 7.1 surround (classic theater 8-track) */
159 long flac_read(void *in, float **buffer, int samples)
161 flacfile *flac = (flacfile *)in;
162 long realsamples = 0;
165 while (realsamples < samples)
167 if (flac->buf_fill > 0)
169 int copy = flac->buf_fill < (samples - realsamples) ?
170 flac->buf_fill : (samples - realsamples);
172 for (i = 0; i < flac->channels; i++){
173 int permute = wav_permute_matrix[flac->channels-1][i];
174 for (j = 0; j < copy; j++)
175 buffer[i][j+realsamples] =
176 flac->buf[permute][j+flac->buf_start];
178 flac->buf_start += copy;
179 flac->buf_fill -= copy;
185 ret = EasyFLAC__process_single(flac->decoder);
187 EasyFLAC__get_state(flac->decoder)
188 == FLAC__STREAM_DECODER_END_OF_STREAM)
189 flac->eos = 1; /* Bail out! */
191 ret = FLAC__stream_decoder_process_single(flac->decoder);
193 FLAC__stream_decoder_get_state(flac->decoder)
194 == FLAC__STREAM_DECODER_END_OF_STREAM)
195 flac->eos = 1; /* Bail out! */
204 void flac_close(void *info)
207 flacfile *flac = (flacfile *) info;
209 for (i = 0; i < flac->channels; i++)
214 free(flac->comments);
216 EasyFLAC__finish(flac->decoder);
217 EasyFLAC__stream_decoder_delete(flac->decoder);
219 FLAC__stream_decoder_finish(flac->decoder);
220 FLAC__stream_decoder_delete(flac->decoder);
226 FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
228 FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
231 flacfile *flac = (flacfile *) client_data;
233 int oldbuf_fill = flac->oldbuf_len - flac->oldbuf_start;
235 /* Immediately return if errors occured */
239 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
241 else if(ferror(flac->in))
244 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
252 copy = oldbuf_fill < (*bytes - i) ? oldbuf_fill : (*bytes - i);
253 memcpy(buffer + i, flac->oldbuf, copy);
255 flac->oldbuf_start += copy;
259 i += fread(buffer+i, sizeof(FLAC__byte), *bytes - i, flac->in);
263 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
267 FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
269 FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
272 flacfile *flac = (flacfile *) client_data;
273 int samples = frame->header.blocksize;
274 int channels = frame->header.channels;
275 int bits_per_sample = frame->header.bits_per_sample;
278 resize_buffer(flac, channels, samples);
280 for (i = 0; i < channels; i++)
281 for (j = 0; j < samples; j++)
282 flac->buf[i][j] = buffer[i][j] /
283 (float) (1 << (bits_per_sample - 1));
286 flac->buf_fill = samples;
288 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
292 void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
294 void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
297 flacfile *flac = (flacfile *) client_data;
299 switch (metadata->type)
301 case FLAC__METADATA_TYPE_STREAMINFO:
302 flac->totalsamples = metadata->data.stream_info.total_samples;
303 flac->rate = metadata->data.stream_info.sample_rate;
306 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
307 flac->comments = FLAC__metadata_object_clone(metadata);
315 void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
317 void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
320 flacfile *flac = (flacfile *) client_data;
325 FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
327 flacfile *flac = (flacfile *) client_data;
329 return feof(flac->in)? true : false;
333 void resize_buffer(flacfile *flac, int newchannels, int newsamples)
337 if (newchannels == flac->channels && newsamples == flac->buf_len)
345 /* Not the most efficient approach, but it is easy to follow */
346 if(newchannels != flac->channels)
348 /* Deallocate all of the sample vectors */
349 for (i = 0; i < flac->channels; i++)
352 flac->buf = realloc(flac->buf, sizeof(float*) * newchannels);
353 flac->channels = newchannels;
357 for (i = 0; i < newchannels; i++)
358 flac->buf[i] = malloc(sizeof(float) * newsamples);
360 flac->buf_len = newsamples;
365 void copy_comments (vorbis_comment *v_comments, FLAC__StreamMetadata_VorbisComment *f_comments)
369 for (i = 0; i < f_comments->num_comments; i++)
371 char *comment = malloc(f_comments->comments[i].length + 1);
372 memset(comment, '\0', f_comments->comments[i].length + 1);
373 strncpy(comment, f_comments->comments[i].entry, f_comments->comments[i].length);
374 vorbis_comment_add(v_comments, comment);