1 /* libFLAC++ - Free Lossless Audio Codec library
2 * Copyright (C) 2002-2009 Josh Coalson
3 * Copyright (C) 2011-2013 Xiph.Org Foundation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * - Neither the name of the Xiph.org Foundation nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "FLAC++/encoder.h"
34 #include "FLAC++/metadata.h"
35 #include "FLAC/assert.h"
38 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
39 #pragma warning ( disable : 4800 )
45 // ------------------------------------------------------------
49 // ------------------------------------------------------------
52 encoder_(::FLAC__stream_encoder_new())
58 (void)::FLAC__stream_encoder_finish(encoder_);
59 ::FLAC__stream_encoder_delete(encoder_);
63 bool Stream::is_valid() const
68 bool Stream::set_ogg_serial_number(long value)
70 FLAC__ASSERT(is_valid());
71 return (bool)::FLAC__stream_encoder_set_ogg_serial_number(encoder_, value);
74 bool Stream::set_verify(bool value)
76 FLAC__ASSERT(is_valid());
77 return (bool)::FLAC__stream_encoder_set_verify(encoder_, value);
80 bool Stream::set_streamable_subset(bool value)
82 FLAC__ASSERT(is_valid());
83 return (bool)::FLAC__stream_encoder_set_streamable_subset(encoder_, value);
86 bool Stream::set_channels(unsigned value)
88 FLAC__ASSERT(is_valid());
89 return (bool)::FLAC__stream_encoder_set_channels(encoder_, value);
92 bool Stream::set_bits_per_sample(unsigned value)
94 FLAC__ASSERT(is_valid());
95 return (bool)::FLAC__stream_encoder_set_bits_per_sample(encoder_, value);
98 bool Stream::set_sample_rate(unsigned value)
100 FLAC__ASSERT(is_valid());
101 return (bool)::FLAC__stream_encoder_set_sample_rate(encoder_, value);
104 bool Stream::set_compression_level(unsigned value)
106 FLAC__ASSERT(is_valid());
107 return (bool)::FLAC__stream_encoder_set_compression_level(encoder_, value);
110 bool Stream::set_blocksize(unsigned value)
112 FLAC__ASSERT(is_valid());
113 return (bool)::FLAC__stream_encoder_set_blocksize(encoder_, value);
116 bool Stream::set_do_mid_side_stereo(bool value)
118 FLAC__ASSERT(is_valid());
119 return (bool)::FLAC__stream_encoder_set_do_mid_side_stereo(encoder_, value);
122 bool Stream::set_loose_mid_side_stereo(bool value)
124 FLAC__ASSERT(is_valid());
125 return (bool)::FLAC__stream_encoder_set_loose_mid_side_stereo(encoder_, value);
128 bool Stream::set_apodization(const char *specification)
130 FLAC__ASSERT(is_valid());
131 return (bool)::FLAC__stream_encoder_set_apodization(encoder_, specification);
134 bool Stream::set_max_lpc_order(unsigned value)
136 FLAC__ASSERT(is_valid());
137 return (bool)::FLAC__stream_encoder_set_max_lpc_order(encoder_, value);
140 bool Stream::set_qlp_coeff_precision(unsigned value)
142 FLAC__ASSERT(is_valid());
143 return (bool)::FLAC__stream_encoder_set_qlp_coeff_precision(encoder_, value);
146 bool Stream::set_do_qlp_coeff_prec_search(bool value)
148 FLAC__ASSERT(is_valid());
149 return (bool)::FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder_, value);
152 bool Stream::set_do_escape_coding(bool value)
154 FLAC__ASSERT(is_valid());
155 return (bool)::FLAC__stream_encoder_set_do_escape_coding(encoder_, value);
158 bool Stream::set_do_exhaustive_model_search(bool value)
160 FLAC__ASSERT(is_valid());
161 return (bool)::FLAC__stream_encoder_set_do_exhaustive_model_search(encoder_, value);
164 bool Stream::set_min_residual_partition_order(unsigned value)
166 FLAC__ASSERT(is_valid());
167 return (bool)::FLAC__stream_encoder_set_min_residual_partition_order(encoder_, value);
170 bool Stream::set_max_residual_partition_order(unsigned value)
172 FLAC__ASSERT(is_valid());
173 return (bool)::FLAC__stream_encoder_set_max_residual_partition_order(encoder_, value);
176 bool Stream::set_rice_parameter_search_dist(unsigned value)
178 FLAC__ASSERT(is_valid());
179 return (bool)::FLAC__stream_encoder_set_rice_parameter_search_dist(encoder_, value);
182 bool Stream::set_total_samples_estimate(FLAC__uint64 value)
184 FLAC__ASSERT(is_valid());
185 return (bool)::FLAC__stream_encoder_set_total_samples_estimate(encoder_, value);
188 bool Stream::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks)
190 FLAC__ASSERT(is_valid());
191 return (bool)::FLAC__stream_encoder_set_metadata(encoder_, metadata, num_blocks);
194 bool Stream::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks)
196 FLAC__ASSERT(is_valid());
197 #ifndef HAVE_CXX_VARARRAYS
198 // some compilers (MSVC++, Borland C, SunPro, some GCCs w/ -pedantic) can't handle:
199 // ::FLAC__StreamMetadata *m[num_blocks];
200 // so we do this ugly workaround
201 ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks];
203 ::FLAC__StreamMetadata *m[num_blocks];
205 for(unsigned i = 0; i < num_blocks; i++) {
206 // we can get away with the const_cast since we know the encoder will only correct the is_last flags
207 m[i] = const_cast< ::FLAC__StreamMetadata*>(static_cast<const ::FLAC__StreamMetadata*>(*metadata[i]));
209 #ifndef HAVE_CXX_VARARRAYS
211 const bool ok = (bool)::FLAC__stream_encoder_set_metadata(encoder_, m, num_blocks);
215 return (bool)::FLAC__stream_encoder_set_metadata(encoder_, m, num_blocks);
219 Stream::State Stream::get_state() const
221 FLAC__ASSERT(is_valid());
222 return State(::FLAC__stream_encoder_get_state(encoder_));
225 Decoder::Stream::State Stream::get_verify_decoder_state() const
227 FLAC__ASSERT(is_valid());
228 return Decoder::Stream::State(::FLAC__stream_encoder_get_verify_decoder_state(encoder_));
231 void Stream::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
233 FLAC__ASSERT(is_valid());
234 ::FLAC__stream_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got);
237 bool Stream::get_verify() const
239 FLAC__ASSERT(is_valid());
240 return (bool)::FLAC__stream_encoder_get_verify(encoder_);
243 bool Stream::get_streamable_subset() const
245 FLAC__ASSERT(is_valid());
246 return (bool)::FLAC__stream_encoder_get_streamable_subset(encoder_);
249 bool Stream::get_do_mid_side_stereo() const
251 FLAC__ASSERT(is_valid());
252 return (bool)::FLAC__stream_encoder_get_do_mid_side_stereo(encoder_);
255 bool Stream::get_loose_mid_side_stereo() const
257 FLAC__ASSERT(is_valid());
258 return (bool)::FLAC__stream_encoder_get_loose_mid_side_stereo(encoder_);
261 unsigned Stream::get_channels() const
263 FLAC__ASSERT(is_valid());
264 return ::FLAC__stream_encoder_get_channels(encoder_);
267 unsigned Stream::get_bits_per_sample() const
269 FLAC__ASSERT(is_valid());
270 return ::FLAC__stream_encoder_get_bits_per_sample(encoder_);
273 unsigned Stream::get_sample_rate() const
275 FLAC__ASSERT(is_valid());
276 return ::FLAC__stream_encoder_get_sample_rate(encoder_);
279 unsigned Stream::get_blocksize() const
281 FLAC__ASSERT(is_valid());
282 return ::FLAC__stream_encoder_get_blocksize(encoder_);
285 unsigned Stream::get_max_lpc_order() const
287 FLAC__ASSERT(is_valid());
288 return ::FLAC__stream_encoder_get_max_lpc_order(encoder_);
291 unsigned Stream::get_qlp_coeff_precision() const
293 FLAC__ASSERT(is_valid());
294 return ::FLAC__stream_encoder_get_qlp_coeff_precision(encoder_);
297 bool Stream::get_do_qlp_coeff_prec_search() const
299 FLAC__ASSERT(is_valid());
300 return (bool)::FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder_);
303 bool Stream::get_do_escape_coding() const
305 FLAC__ASSERT(is_valid());
306 return (bool)::FLAC__stream_encoder_get_do_escape_coding(encoder_);
309 bool Stream::get_do_exhaustive_model_search() const
311 FLAC__ASSERT(is_valid());
312 return (bool)::FLAC__stream_encoder_get_do_exhaustive_model_search(encoder_);
315 unsigned Stream::get_min_residual_partition_order() const
317 FLAC__ASSERT(is_valid());
318 return ::FLAC__stream_encoder_get_min_residual_partition_order(encoder_);
321 unsigned Stream::get_max_residual_partition_order() const
323 FLAC__ASSERT(is_valid());
324 return ::FLAC__stream_encoder_get_max_residual_partition_order(encoder_);
327 unsigned Stream::get_rice_parameter_search_dist() const
329 FLAC__ASSERT(is_valid());
330 return ::FLAC__stream_encoder_get_rice_parameter_search_dist(encoder_);
333 FLAC__uint64 Stream::get_total_samples_estimate() const
335 FLAC__ASSERT(is_valid());
336 return ::FLAC__stream_encoder_get_total_samples_estimate(encoder_);
339 ::FLAC__StreamEncoderInitStatus Stream::init()
341 FLAC__ASSERT(is_valid());
342 return ::FLAC__stream_encoder_init_stream(encoder_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this);
345 ::FLAC__StreamEncoderInitStatus Stream::init_ogg()
347 FLAC__ASSERT(is_valid());
348 return ::FLAC__stream_encoder_init_ogg_stream(encoder_, read_callback_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this);
351 bool Stream::finish()
353 FLAC__ASSERT(is_valid());
354 return (bool)::FLAC__stream_encoder_finish(encoder_);
357 bool Stream::process(const FLAC__int32 * const buffer[], unsigned samples)
359 FLAC__ASSERT(is_valid());
360 return (bool)::FLAC__stream_encoder_process(encoder_, buffer, samples);
363 bool Stream::process_interleaved(const FLAC__int32 buffer[], unsigned samples)
365 FLAC__ASSERT(is_valid());
366 return (bool)::FLAC__stream_encoder_process_interleaved(encoder_, buffer, samples);
369 ::FLAC__StreamEncoderReadStatus Stream::read_callback(FLAC__byte buffer[], size_t *bytes)
371 (void)buffer, (void)bytes;
372 return ::FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED;
375 ::FLAC__StreamEncoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset)
377 (void)absolute_byte_offset;
378 return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
381 ::FLAC__StreamEncoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset)
383 (void)absolute_byte_offset;
384 return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
387 void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata)
392 ::FLAC__StreamEncoderReadStatus Stream::read_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
395 FLAC__ASSERT(0 != client_data);
396 Stream *instance = reinterpret_cast<Stream *>(client_data);
397 FLAC__ASSERT(0 != instance);
398 return instance->read_callback(buffer, bytes);
401 ::FLAC__StreamEncoderWriteStatus Stream::write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data)
404 FLAC__ASSERT(0 != client_data);
405 Stream *instance = reinterpret_cast<Stream *>(client_data);
406 FLAC__ASSERT(0 != instance);
407 return instance->write_callback(buffer, bytes, samples, current_frame);
410 ::FLAC__StreamEncoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
413 FLAC__ASSERT(0 != client_data);
414 Stream *instance = reinterpret_cast<Stream *>(client_data);
415 FLAC__ASSERT(0 != instance);
416 return instance->seek_callback(absolute_byte_offset);
419 ::FLAC__StreamEncoderTellStatus Stream::tell_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
422 FLAC__ASSERT(0 != client_data);
423 Stream *instance = reinterpret_cast<Stream *>(client_data);
424 FLAC__ASSERT(0 != instance);
425 return instance->tell_callback(absolute_byte_offset);
428 void Stream::metadata_callback_(const ::FLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
431 FLAC__ASSERT(0 != client_data);
432 Stream *instance = reinterpret_cast<Stream *>(client_data);
433 FLAC__ASSERT(0 != instance);
434 instance->metadata_callback(metadata);
437 // ------------------------------------------------------------
441 // ------------------------------------------------------------
451 ::FLAC__StreamEncoderInitStatus File::init(FILE *file)
453 FLAC__ASSERT(is_valid());
454 return ::FLAC__stream_encoder_init_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this);
457 ::FLAC__StreamEncoderInitStatus File::init(const char *filename)
459 FLAC__ASSERT(is_valid());
460 return ::FLAC__stream_encoder_init_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this);
463 ::FLAC__StreamEncoderInitStatus File::init(const std::string &filename)
465 return init(filename.c_str());
468 ::FLAC__StreamEncoderInitStatus File::init_ogg(FILE *file)
470 FLAC__ASSERT(is_valid());
471 return ::FLAC__stream_encoder_init_ogg_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this);
474 ::FLAC__StreamEncoderInitStatus File::init_ogg(const char *filename)
476 FLAC__ASSERT(is_valid());
477 return ::FLAC__stream_encoder_init_ogg_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this);
480 ::FLAC__StreamEncoderInitStatus File::init_ogg(const std::string &filename)
482 return init_ogg(filename.c_str());
485 // This is a dummy to satisfy the pure virtual from Stream; the
486 // read callback will never be called since we are initializing
487 // with FLAC__stream_decoder_init_FILE() or
488 // FLAC__stream_decoder_init_file() and those supply the read
489 // callback internally.
490 ::FLAC__StreamEncoderWriteStatus File::write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame)
492 (void)buffer, (void)bytes, (void)samples, (void)current_frame;
494 return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; // double protection
497 void File::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
499 (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
502 void File::progress_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
505 FLAC__ASSERT(0 != client_data);
506 File *instance = reinterpret_cast<File *>(client_data);
507 FLAC__ASSERT(0 != instance);
508 instance->progress_callback(bytes_written, samples_written, frames_written, total_frames_estimate);