1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2 * Copyright (C) 2002,2003,2004 Josh Coalson
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <stdlib.h> /* for malloc() */
34 #include <string.h> /* for strlen(), strcpy() */
35 #include "FLAC/assert.h"
36 #include "OggFLAC/seekable_stream_encoder.h"
37 #include "protected/file_encoder.h"
42 #define max(x,y) ((x)>(y)?(x):(y))
44 /***********************************************************************
46 * Private class method prototypes
48 ***********************************************************************/
50 /* unpublished debug routines */
51 extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
52 extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
53 extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
55 static void set_defaults_(OggFLAC__FileEncoder *encoder);
56 static OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
57 static FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
58 static FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
59 static FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
61 /***********************************************************************
65 ***********************************************************************/
67 typedef struct OggFLAC__FileEncoderPrivate {
68 OggFLAC__FileEncoderProgressCallback progress_callback;
71 FLAC__uint64 bytes_written;
72 FLAC__uint64 samples_written;
73 unsigned frames_written;
74 unsigned total_frames_estimate;
75 OggFLAC__SeekableStreamEncoder *seekable_stream_encoder;
77 } OggFLAC__FileEncoderPrivate;
79 /***********************************************************************
81 * Public static class data
83 ***********************************************************************/
85 OggFLAC_API const char * const OggFLAC__FileEncoderStateString[] = {
86 "OggFLAC__FILE_ENCODER_OK",
87 "OggFLAC__FILE_ENCODER_NO_FILENAME",
88 "OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR",
89 "OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING",
90 "OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE",
91 "OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR",
92 "OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED",
93 "OggFLAC__FILE_ENCODER_UNINITIALIZED"
97 /***********************************************************************
99 * Class constructor/destructor
101 ***********************************************************************/
103 OggFLAC_API OggFLAC__FileEncoder *OggFLAC__file_encoder_new()
105 OggFLAC__FileEncoder *encoder;
107 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
109 encoder = (OggFLAC__FileEncoder*)calloc(1, sizeof(OggFLAC__FileEncoder));
114 encoder->protected_ = (OggFLAC__FileEncoderProtected*)calloc(1, sizeof(OggFLAC__FileEncoderProtected));
115 if(encoder->protected_ == 0) {
120 encoder->private_ = (OggFLAC__FileEncoderPrivate*)calloc(1, sizeof(OggFLAC__FileEncoderPrivate));
121 if(encoder->private_ == 0) {
122 free(encoder->protected_);
127 encoder->private_->seekable_stream_encoder = OggFLAC__seekable_stream_encoder_new();
128 if(0 == encoder->private_->seekable_stream_encoder) {
129 free(encoder->private_);
130 free(encoder->protected_);
135 encoder->private_->file = 0;
137 set_defaults_(encoder);
139 encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED;
144 OggFLAC_API void OggFLAC__file_encoder_delete(OggFLAC__FileEncoder *encoder)
146 FLAC__ASSERT(0 != encoder);
147 FLAC__ASSERT(0 != encoder->protected_);
148 FLAC__ASSERT(0 != encoder->private_);
149 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
151 (void)OggFLAC__file_encoder_finish(encoder);
153 OggFLAC__seekable_stream_encoder_delete(encoder->private_->seekable_stream_encoder);
155 free(encoder->private_);
156 free(encoder->protected_);
160 /***********************************************************************
162 * Public class methods
164 ***********************************************************************/
166 OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_init(OggFLAC__FileEncoder *encoder)
168 FLAC__ASSERT(0 != encoder);
170 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
171 return encoder->protected_->state = OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED;
173 if(0 == encoder->private_->filename)
174 return encoder->protected_->state = OggFLAC__FILE_ENCODER_NO_FILENAME;
176 encoder->private_->file = fopen(encoder->private_->filename, "w+b");
178 if(encoder->private_->file == 0)
179 return encoder->protected_->state = OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE;
181 encoder->private_->bytes_written = 0;
182 encoder->private_->samples_written = 0;
183 encoder->private_->frames_written = 0;
185 OggFLAC__seekable_stream_encoder_set_read_callback(encoder->private_->seekable_stream_encoder, read_callback_);
186 OggFLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_);
187 OggFLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->seekable_stream_encoder, tell_callback_);
188 OggFLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_);
189 OggFLAC__seekable_stream_encoder_set_client_data(encoder->private_->seekable_stream_encoder, encoder);
191 if(OggFLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != OggFLAC__SEEKABLE_STREAM_ENCODER_OK)
192 return encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
195 unsigned blocksize = OggFLAC__file_encoder_get_blocksize(encoder);
197 FLAC__ASSERT(blocksize != 0);
198 encoder->private_->total_frames_estimate = (unsigned)((OggFLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
201 return encoder->protected_->state = OggFLAC__FILE_ENCODER_OK;
204 OggFLAC_API void OggFLAC__file_encoder_finish(OggFLAC__FileEncoder *encoder)
206 FLAC__ASSERT(0 != encoder);
208 if(encoder->protected_->state == OggFLAC__FILE_ENCODER_UNINITIALIZED)
211 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
213 /* OggFLAC__seekable_stream_encoder_finish() might write data so we must close the file after it. */
215 OggFLAC__seekable_stream_encoder_finish(encoder->private_->seekable_stream_encoder);
217 if(0 != encoder->private_->file) {
218 fclose(encoder->private_->file);
219 encoder->private_->file = 0;
222 if(0 != encoder->private_->filename) {
223 free(encoder->private_->filename);
224 encoder->private_->filename = 0;
227 set_defaults_(encoder);
229 encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED;
232 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_serial_number(OggFLAC__FileEncoder *encoder, long serial_number)
234 FLAC__ASSERT(0 != encoder);
235 FLAC__ASSERT(0 != encoder->private_);
236 FLAC__ASSERT(0 != encoder->protected_);
237 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
238 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
240 return OggFLAC__seekable_stream_encoder_set_serial_number(encoder->private_->seekable_stream_encoder, serial_number);
243 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_verify(OggFLAC__FileEncoder *encoder, FLAC__bool value)
245 FLAC__ASSERT(0 != encoder);
246 FLAC__ASSERT(0 != encoder->private_);
247 FLAC__ASSERT(0 != encoder->protected_);
248 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
249 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
251 return OggFLAC__seekable_stream_encoder_set_verify(encoder->private_->seekable_stream_encoder, value);
254 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_streamable_subset(OggFLAC__FileEncoder *encoder, FLAC__bool value)
256 FLAC__ASSERT(0 != encoder);
257 FLAC__ASSERT(0 != encoder->private_);
258 FLAC__ASSERT(0 != encoder->protected_);
259 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
260 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
262 return OggFLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->seekable_stream_encoder, value);
265 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value)
267 FLAC__ASSERT(0 != encoder);
268 FLAC__ASSERT(0 != encoder->private_);
269 FLAC__ASSERT(0 != encoder->protected_);
270 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
271 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
273 return OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
276 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_loose_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value)
278 FLAC__ASSERT(0 != encoder);
279 FLAC__ASSERT(0 != encoder->private_);
280 FLAC__ASSERT(0 != encoder->protected_);
281 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
282 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
284 return OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
287 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_channels(OggFLAC__FileEncoder *encoder, unsigned value)
289 FLAC__ASSERT(0 != encoder);
290 FLAC__ASSERT(0 != encoder->private_);
291 FLAC__ASSERT(0 != encoder->protected_);
292 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
293 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
295 return OggFLAC__seekable_stream_encoder_set_channels(encoder->private_->seekable_stream_encoder, value);
298 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_bits_per_sample(OggFLAC__FileEncoder *encoder, unsigned value)
300 FLAC__ASSERT(0 != encoder);
301 FLAC__ASSERT(0 != encoder->private_);
302 FLAC__ASSERT(0 != encoder->protected_);
303 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
304 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
306 return OggFLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->seekable_stream_encoder, value);
309 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_sample_rate(OggFLAC__FileEncoder *encoder, unsigned value)
311 FLAC__ASSERT(0 != encoder);
312 FLAC__ASSERT(0 != encoder->private_);
313 FLAC__ASSERT(0 != encoder->protected_);
314 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
315 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
317 return OggFLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->seekable_stream_encoder, value);
320 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder *encoder, unsigned value)
322 FLAC__ASSERT(0 != encoder);
323 FLAC__ASSERT(0 != encoder->private_);
324 FLAC__ASSERT(0 != encoder->protected_);
325 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
326 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
328 return OggFLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
331 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_lpc_order(OggFLAC__FileEncoder *encoder, unsigned value)
333 FLAC__ASSERT(0 != encoder);
334 FLAC__ASSERT(0 != encoder->private_);
335 FLAC__ASSERT(0 != encoder->protected_);
336 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
337 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
339 return OggFLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->seekable_stream_encoder, value);
342 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_qlp_coeff_precision(OggFLAC__FileEncoder *encoder, unsigned value)
344 FLAC__ASSERT(0 != encoder);
345 FLAC__ASSERT(0 != encoder->private_);
346 FLAC__ASSERT(0 != encoder->protected_);
347 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
348 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
350 return OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->seekable_stream_encoder, value);
353 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(OggFLAC__FileEncoder *encoder, FLAC__bool value)
355 FLAC__ASSERT(0 != encoder);
356 FLAC__ASSERT(0 != encoder->private_);
357 FLAC__ASSERT(0 != encoder->protected_);
358 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
359 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
361 return OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder, value);
364 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_escape_coding(OggFLAC__FileEncoder *encoder, FLAC__bool value)
366 FLAC__ASSERT(0 != encoder);
367 FLAC__ASSERT(0 != encoder->private_);
368 FLAC__ASSERT(0 != encoder->protected_);
369 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
370 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
372 return OggFLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->seekable_stream_encoder, value);
375 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_exhaustive_model_search(OggFLAC__FileEncoder *encoder, FLAC__bool value)
377 FLAC__ASSERT(0 != encoder);
378 FLAC__ASSERT(0 != encoder->private_);
379 FLAC__ASSERT(0 != encoder->protected_);
380 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
381 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
383 return OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder, value);
386 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_min_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value)
388 FLAC__ASSERT(0 != encoder);
389 FLAC__ASSERT(0 != encoder->private_);
390 FLAC__ASSERT(0 != encoder->protected_);
391 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
392 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
394 return OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
397 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value)
399 FLAC__ASSERT(0 != encoder);
400 FLAC__ASSERT(0 != encoder->private_);
401 FLAC__ASSERT(0 != encoder->protected_);
402 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
403 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
405 return OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
408 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_rice_parameter_search_dist(OggFLAC__FileEncoder *encoder, unsigned value)
410 FLAC__ASSERT(0 != encoder);
411 FLAC__ASSERT(0 != encoder->private_);
412 FLAC__ASSERT(0 != encoder->protected_);
413 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
414 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
416 return OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder, value);
419 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC__FileEncoder *encoder, FLAC__uint64 value)
421 FLAC__ASSERT(0 != encoder);
422 FLAC__ASSERT(0 != encoder->private_);
423 FLAC__ASSERT(0 != encoder->protected_);
424 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
425 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
427 return OggFLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->seekable_stream_encoder, value);
430 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_metadata(OggFLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
432 FLAC__ASSERT(0 != encoder);
433 FLAC__ASSERT(0 != encoder->private_);
434 FLAC__ASSERT(0 != encoder->protected_);
435 FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
436 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
438 return OggFLAC__seekable_stream_encoder_set_metadata(encoder->private_->seekable_stream_encoder, metadata, num_blocks);
441 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_filename(OggFLAC__FileEncoder *encoder, const char *value)
443 FLAC__ASSERT(0 != encoder);
444 FLAC__ASSERT(0 != encoder->private_);
445 FLAC__ASSERT(0 != encoder->protected_);
446 FLAC__ASSERT(0 != value);
447 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
449 if(0 != encoder->private_->filename) {
450 free(encoder->private_->filename);
451 encoder->private_->filename = 0;
453 if(0 == (encoder->private_->filename = (char*)malloc(strlen(value)+1))) {
454 encoder->protected_->state = OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR;
457 strcpy(encoder->private_->filename, value);
461 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_progress_callback(OggFLAC__FileEncoder *encoder, OggFLAC__FileEncoderProgressCallback value)
463 FLAC__ASSERT(0 != encoder);
464 FLAC__ASSERT(0 != encoder->private_);
465 FLAC__ASSERT(0 != encoder->protected_);
466 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
468 encoder->private_->progress_callback = value;
472 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_client_data(OggFLAC__FileEncoder *encoder, void *value)
474 FLAC__ASSERT(0 != encoder);
475 FLAC__ASSERT(0 != encoder->private_);
476 FLAC__ASSERT(0 != encoder->protected_);
477 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
479 encoder->private_->client_data = value;
484 * These three functions are not static, but not publically exposed in
485 * include/OggFLAC/ either. They are used by the test suite.
487 OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_constant_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
489 FLAC__ASSERT(0 != encoder);
490 FLAC__ASSERT(0 != encoder->private_);
491 FLAC__ASSERT(0 != encoder->protected_);
492 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
494 return OggFLAC__seekable_stream_encoder_disable_constant_subframes(encoder->private_->seekable_stream_encoder, value);
497 OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_fixed_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
499 FLAC__ASSERT(0 != encoder);
500 FLAC__ASSERT(0 != encoder->private_);
501 FLAC__ASSERT(0 != encoder->protected_);
502 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
504 return OggFLAC__seekable_stream_encoder_disable_fixed_subframes(encoder->private_->seekable_stream_encoder, value);
507 OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
509 FLAC__ASSERT(0 != encoder);
510 FLAC__ASSERT(0 != encoder->private_);
511 FLAC__ASSERT(0 != encoder->protected_);
512 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
514 return OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(encoder->private_->seekable_stream_encoder, value);
517 OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_get_state(const OggFLAC__FileEncoder *encoder)
519 FLAC__ASSERT(0 != encoder);
520 FLAC__ASSERT(0 != encoder->protected_);
521 return encoder->protected_->state;
524 OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__file_encoder_get_seekable_stream_encoder_state(const OggFLAC__FileEncoder *encoder)
526 FLAC__ASSERT(0 != encoder);
527 FLAC__ASSERT(0 != encoder->private_);
528 return OggFLAC__seekable_stream_encoder_get_state(encoder->private_->seekable_stream_encoder);
531 OggFLAC_API FLAC__StreamEncoderState OggFLAC__file_encoder_get_FLAC_stream_encoder_state(const OggFLAC__FileEncoder *encoder)
533 FLAC__ASSERT(0 != encoder);
534 FLAC__ASSERT(0 != encoder->private_);
535 return OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder->private_->seekable_stream_encoder);
538 OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_encoder_get_verify_decoder_state(const OggFLAC__FileEncoder *encoder)
540 FLAC__ASSERT(0 != encoder);
541 FLAC__ASSERT(0 != encoder->private_);
542 return OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->seekable_stream_encoder);
545 OggFLAC_API const char *OggFLAC__file_encoder_get_resolved_state_string(const OggFLAC__FileEncoder *encoder)
547 if(encoder->protected_->state != OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR)
548 return OggFLAC__FileEncoderStateString[encoder->protected_->state];
550 return OggFLAC__seekable_stream_encoder_get_resolved_state_string(encoder->private_->seekable_stream_encoder);
553 OggFLAC_API void OggFLAC__file_encoder_get_verify_decoder_error_stats(const OggFLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
555 FLAC__ASSERT(0 != encoder);
556 FLAC__ASSERT(0 != encoder->private_);
557 OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder->private_->seekable_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
560 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_verify(const OggFLAC__FileEncoder *encoder)
562 FLAC__ASSERT(0 != encoder);
563 FLAC__ASSERT(0 != encoder->private_);
564 return OggFLAC__seekable_stream_encoder_get_verify(encoder->private_->seekable_stream_encoder);
567 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_streamable_subset(const OggFLAC__FileEncoder *encoder)
569 FLAC__ASSERT(0 != encoder);
570 FLAC__ASSERT(0 != encoder->private_);
571 return OggFLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->seekable_stream_encoder);
574 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_mid_side_stereo(const OggFLAC__FileEncoder *encoder)
576 FLAC__ASSERT(0 != encoder);
577 FLAC__ASSERT(0 != encoder->private_);
578 return OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->seekable_stream_encoder);
581 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_loose_mid_side_stereo(const OggFLAC__FileEncoder *encoder)
583 FLAC__ASSERT(0 != encoder);
584 FLAC__ASSERT(0 != encoder->private_);
585 return OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder);
588 OggFLAC_API unsigned OggFLAC__file_encoder_get_channels(const OggFLAC__FileEncoder *encoder)
590 FLAC__ASSERT(0 != encoder);
591 FLAC__ASSERT(0 != encoder->private_);
592 return OggFLAC__seekable_stream_encoder_get_channels(encoder->private_->seekable_stream_encoder);
595 OggFLAC_API unsigned OggFLAC__file_encoder_get_bits_per_sample(const OggFLAC__FileEncoder *encoder)
597 FLAC__ASSERT(0 != encoder);
598 FLAC__ASSERT(0 != encoder->private_);
599 return OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->seekable_stream_encoder);
602 OggFLAC_API unsigned OggFLAC__file_encoder_get_sample_rate(const OggFLAC__FileEncoder *encoder)
604 FLAC__ASSERT(0 != encoder);
605 FLAC__ASSERT(0 != encoder->private_);
606 return OggFLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->seekable_stream_encoder);
609 OggFLAC_API unsigned OggFLAC__file_encoder_get_blocksize(const OggFLAC__FileEncoder *encoder)
611 FLAC__ASSERT(0 != encoder);
612 FLAC__ASSERT(0 != encoder->private_);
613 return OggFLAC__seekable_stream_encoder_get_blocksize(encoder->private_->seekable_stream_encoder);
616 OggFLAC_API unsigned OggFLAC__file_encoder_get_max_lpc_order(const OggFLAC__FileEncoder *encoder)
618 FLAC__ASSERT(0 != encoder);
619 FLAC__ASSERT(0 != encoder->private_);
620 return OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder->private_->seekable_stream_encoder);
623 OggFLAC_API unsigned OggFLAC__file_encoder_get_qlp_coeff_precision(const OggFLAC__FileEncoder *encoder)
625 FLAC__ASSERT(0 != encoder);
626 FLAC__ASSERT(0 != encoder->private_);
627 return OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->seekable_stream_encoder);
630 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__FileEncoder *encoder)
632 FLAC__ASSERT(0 != encoder);
633 FLAC__ASSERT(0 != encoder->private_);
634 return OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder);
637 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_escape_coding(const OggFLAC__FileEncoder *encoder)
639 FLAC__ASSERT(0 != encoder);
640 FLAC__ASSERT(0 != encoder->private_);
641 return OggFLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->seekable_stream_encoder);
644 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_exhaustive_model_search(const OggFLAC__FileEncoder *encoder)
646 FLAC__ASSERT(0 != encoder);
647 FLAC__ASSERT(0 != encoder->private_);
648 return OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder);
651 OggFLAC_API unsigned OggFLAC__file_encoder_get_min_residual_partition_order(const OggFLAC__FileEncoder *encoder)
653 FLAC__ASSERT(0 != encoder);
654 FLAC__ASSERT(0 != encoder->private_);
655 return OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->seekable_stream_encoder);
658 OggFLAC_API unsigned OggFLAC__file_encoder_get_max_residual_partition_order(const OggFLAC__FileEncoder *encoder)
660 FLAC__ASSERT(0 != encoder);
661 FLAC__ASSERT(0 != encoder->private_);
662 return OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->seekable_stream_encoder);
665 OggFLAC_API unsigned OggFLAC__file_encoder_get_rice_parameter_search_dist(const OggFLAC__FileEncoder *encoder)
667 FLAC__ASSERT(0 != encoder);
668 FLAC__ASSERT(0 != encoder->private_);
669 return OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder);
672 OggFLAC_API FLAC__uint64 OggFLAC__file_encoder_get_total_samples_estimate(const OggFLAC__FileEncoder *encoder)
674 FLAC__ASSERT(0 != encoder);
675 FLAC__ASSERT(0 != encoder->private_);
676 return OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder);
679 OggFLAC_API FLAC__bool OggFLAC__file_encoder_process(OggFLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
681 FLAC__ASSERT(0 != encoder);
682 FLAC__ASSERT(0 != encoder->private_);
683 if(!OggFLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples)) {
684 encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
691 /* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
692 OggFLAC_API FLAC__bool OggFLAC__file_encoder_process_interleaved(OggFLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
694 FLAC__ASSERT(0 != encoder);
695 FLAC__ASSERT(0 != encoder->private_);
696 if(!OggFLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples)) {
697 encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
705 /***********************************************************************
707 * Private class methods
709 ***********************************************************************/
711 void set_defaults_(OggFLAC__FileEncoder *encoder)
713 FLAC__ASSERT(0 != encoder);
714 FLAC__ASSERT(0 != encoder->private_);
716 encoder->private_->progress_callback = 0;
717 encoder->private_->client_data = 0;
718 encoder->private_->total_frames_estimate = 0;
719 encoder->private_->filename = 0;
722 OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
724 OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
728 FLAC__ASSERT(0 != file_encoder);
730 *bytes = (unsigned)fread(buffer, 1, *bytes, file_encoder->private_->file);
732 if (feof(file_encoder->private_->file))
733 return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
734 else if (ferror(file_encoder->private_->file))
735 return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT;
737 return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
740 FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
742 OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
746 FLAC__ASSERT(0 != file_encoder);
748 if(fseek(file_encoder->private_->file, (long)absolute_byte_offset, SEEK_SET) < 0)
749 return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR;
751 return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
754 FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
756 OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
761 FLAC__ASSERT(0 != file_encoder);
763 offset = ftell(file_encoder->private_->file);
766 return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR;
769 *absolute_byte_offset = (FLAC__uint64)offset;
770 return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
774 #ifdef FLAC__VALGRIND_TESTING
775 static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
777 size_t ret = fwrite(ptr, size, nmemb, stream);
783 #define local__fwrite fwrite
786 FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
788 OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
792 FLAC__ASSERT(0 != file_encoder);
794 if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) {
795 file_encoder->private_->bytes_written += bytes;
796 file_encoder->private_->samples_written += samples;
797 /* we keep a high watermark on the number of frames written
798 * because when the encoder goes back to write metadata,
799 * 'current_frame' will drop back to 0.
801 file_encoder->private_->frames_written = max(file_encoder->private_->frames_written, current_frame+1);
802 /*@@@ We would like to add an '&& samples > 0' to the if
803 * clause here but currently because of the nature of our Ogg
804 * writing implementation, 'samples' is always 0 (see
805 * ogg_encoder_aspect.c). The downside is extra progress
808 if(0 != file_encoder->private_->progress_callback)
809 file_encoder->private_->progress_callback(file_encoder, file_encoder->private_->bytes_written, file_encoder->private_->samples_written, file_encoder->private_->frames_written, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data);
810 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
813 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;