General formatting clean-up.
[xiph/unicode.git] / vorbis-tools / oggenc / flac.c
blob3caab82bf21d357b3f2f90f1d4c99b237bfb7b39
1 /* OggEnc
2 **
3 ** This program is distributed under the GNU General Public License, version 2.
4 ** A copy of this license is included with this source.
5 **
6 ** Copyright 2002, Stan Seibert <volsung@xiph.org>
7 **
8 **/
10 #ifdef HAVE_CONFIG_H
11 #include <config.h>
12 #endif
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <math.h>
19 #include <FLAC/metadata.h>
20 #include "audio.h"
21 #include "flac.h"
22 #include "i18n.h"
23 #include "platform.h"
24 #include "resample.h"
26 #if !defined(FLAC_API_VERSION_CURRENT) || (FLAC_API_VERSION_CURRENT < 8)
27 #define NEED_EASYFLAC 1
28 #endif
30 #if NEED_EASYFLAC
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);
35 #else
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);
41 #endif
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 < 32) return 0;
59 return memcmp(buf, "OggS", 4) == 0 &&
60 (memcmp (buf+28, "\177FLAC", 5) || 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));
68 flac->decoder = NULL;
69 flac->channels = 0;
70 flac->rate = 0;
71 flac->totalsamples = 0;
72 flac->comments = NULL;
73 flac->in = NULL;
74 flac->eos = 0;
76 /* Setup empty audio buffer that will be resized on first frame
77 callback */
78 flac->buf = NULL;
79 flac->buf_len = 0;
80 flac->buf_start = 0;
81 flac->buf_fill = 0;
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 */
90 flac->in = in;
92 /* Setup FLAC decoder */
93 #if NEED_EASYFLAC
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);
103 #else
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);
110 else
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);
112 #endif
114 /* Callback will set the total samples and sample rate */
115 #if NEED_EASYFLAC
116 EasyFLAC__process_until_end_of_metadata(flac->decoder);
117 #else
118 FLAC__stream_decoder_process_until_end_of_metadata(flac->decoder);
119 #endif
121 /* Callback will set the number of channels and resize the
122 audio buffer */
123 #if NEED_EASYFLAC
124 EasyFLAC__process_single(flac->decoder);
125 #else
126 FLAC__stream_decoder_process_single(flac->decoder);
127 #endif
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
136 callback)*/
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;
142 return 1;
146 long flac_read(void *in, float **buffer, int samples)
148 flacfile *flac = (flacfile *)in;
149 long realsamples = 0;
150 FLAC__bool ret;
151 int i,j;
152 while (realsamples < samples)
154 if (flac->buf_fill > 0)
156 int copy = flac->buf_fill < (samples - realsamples) ?
157 flac->buf_fill : (samples - realsamples);
159 for (i = 0; i < flac->channels; i++)
160 for (j = 0; j < copy; j++)
161 buffer[i][j+realsamples] =
162 flac->buf[i][j+flac->buf_start];
163 flac->buf_start += copy;
164 flac->buf_fill -= copy;
165 realsamples += copy;
167 else if (!flac->eos)
169 #if NEED_EASYFLAC
170 ret = EasyFLAC__process_single(flac->decoder);
171 if (!ret ||
172 EasyFLAC__get_state(flac->decoder)
173 == FLAC__STREAM_DECODER_END_OF_STREAM)
174 flac->eos = 1; /* Bail out! */
175 #else
176 ret = FLAC__stream_decoder_process_single(flac->decoder);
177 if (!ret ||
178 FLAC__stream_decoder_get_state(flac->decoder)
179 == FLAC__STREAM_DECODER_END_OF_STREAM)
180 flac->eos = 1; /* Bail out! */
181 #endif
182 } else
183 break;
186 return realsamples;
189 void flac_close(void *info)
191 int i;
192 flacfile *flac = (flacfile *) info;
194 for (i = 0; i < flac->channels; i++)
195 free(flac->buf[i]);
197 free(flac->buf);
198 free(flac->oldbuf);
199 free(flac->comments);
200 #if NEED_EASYFLAC
201 EasyFLAC__finish(flac->decoder);
202 EasyFLAC__stream_decoder_delete(flac->decoder);
203 #else
204 FLAC__stream_decoder_finish(flac->decoder);
205 FLAC__stream_decoder_delete(flac->decoder);
206 #endif
207 free(flac);
210 #if NEED_EASYFLAC
211 FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
212 #else
213 FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
214 #endif
216 flacfile *flac = (flacfile *) client_data;
217 int i = 0;
218 int oldbuf_fill = flac->oldbuf_len - flac->oldbuf_start;
220 /* Immediately return if errors occured */
221 if(feof(flac->in))
223 *bytes = 0;
224 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
226 else if(ferror(flac->in))
228 *bytes = 0;
229 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
233 if(oldbuf_fill > 0)
235 int copy;
237 copy = oldbuf_fill < (*bytes - i) ? oldbuf_fill : (*bytes - i);
238 memcpy(buffer + i, flac->oldbuf, copy);
239 i += copy;
240 flac->oldbuf_start += copy;
243 if(i < *bytes)
244 i += fread(buffer+i, sizeof(FLAC__byte), *bytes - i, flac->in);
246 *bytes = i;
248 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
251 #if NEED_EASYFLAC
252 FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
253 #else
254 FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
255 #endif
257 flacfile *flac = (flacfile *) client_data;
258 int samples = frame->header.blocksize;
259 int channels = frame->header.channels;
260 int bits_per_sample = frame->header.bits_per_sample;
261 int i, j;
263 resize_buffer(flac, channels, samples);
265 for (i = 0; i < channels; i++)
266 for (j = 0; j < samples; j++)
267 flac->buf[i][j] = buffer[i][j] /
268 (float) (1 << (bits_per_sample - 1));
270 flac->buf_start = 0;
271 flac->buf_fill = samples;
273 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
276 #if NEED_EASYFLAC
277 void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
278 #else
279 void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
280 #endif
282 flacfile *flac = (flacfile *) client_data;
284 switch (metadata->type)
286 case FLAC__METADATA_TYPE_STREAMINFO:
287 flac->totalsamples = metadata->data.stream_info.total_samples;
288 flac->rate = metadata->data.stream_info.sample_rate;
289 break;
291 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
292 flac->comments = FLAC__metadata_object_clone(metadata);
293 break;
294 default:
295 break;
299 #if NEED_EASYFLAC
300 void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
301 #else
302 void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
303 #endif
305 flacfile *flac = (flacfile *) client_data;
309 #if !NEED_EASYFLAC
310 FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
312 flacfile *flac = (flacfile *) client_data;
314 return feof(flac->in)? true : false;
316 #endif
318 void resize_buffer(flacfile *flac, int newchannels, int newsamples)
320 int i;
322 if (newchannels == flac->channels && newsamples == flac->buf_len)
324 flac->buf_start = 0;
325 flac->buf_fill = 0;
326 return;
330 /* Not the most efficient approach, but it is easy to follow */
331 if(newchannels != flac->channels)
333 /* Deallocate all of the sample vectors */
334 for (i = 0; i < flac->channels; i++)
335 free(flac->buf[i]);
337 flac->buf = realloc(flac->buf, sizeof(float*) * newchannels);
338 flac->channels = newchannels;
342 for (i = 0; i < newchannels; i++)
343 flac->buf[i] = malloc(sizeof(float) * newsamples);
345 flac->buf_len = newsamples;
346 flac->buf_start = 0;
347 flac->buf_fill = 0;
350 void copy_comments (vorbis_comment *v_comments, FLAC__StreamMetadata_VorbisComment *f_comments)
352 int i;
354 for (i = 0; i < f_comments->num_comments; i++)
356 char *comment = malloc(f_comments->comments[i].length + 1);
357 memset(comment, '\0', f_comments->comments[i].length + 1);
358 strncpy(comment, f_comments->comments[i].entry, f_comments->comments[i].length);
359 vorbis_comment_add(v_comments, comment);
360 free(comment);