1/* libFLAC++ - Free Lossless Audio Codec library 2 * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 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. 14 * 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. 18 * 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. 30 */ 31 32#include "FLAC++/encoder.h" 33#include "FLAC++/metadata.h" 34#include "FLAC/assert.h" 35 36#ifdef _MSC_VER 37// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning) 38#pragma warning ( disable : 4800 ) 39#endif 40 41namespace FLAC { 42 namespace Encoder { 43 44 // ------------------------------------------------------------ 45 // 46 // Stream 47 // 48 // ------------------------------------------------------------ 49 50 Stream::Stream(): 51 encoder_(::FLAC__stream_encoder_new()) 52 { } 53 54 Stream::~Stream() 55 { 56 if(0 != encoder_) { 57 (void)::FLAC__stream_encoder_finish(encoder_); 58 ::FLAC__stream_encoder_delete(encoder_); 59 } 60 } 61 62 bool Stream::is_valid() const 63 { 64 return 0 != encoder_; 65 } 66 67 bool Stream::set_ogg_serial_number(long value) 68 { 69 FLAC__ASSERT(is_valid()); 70 return (bool)::FLAC__stream_encoder_set_ogg_serial_number(encoder_, value); 71 } 72 73 bool Stream::set_verify(bool value) 74 { 75 FLAC__ASSERT(is_valid()); 76 return (bool)::FLAC__stream_encoder_set_verify(encoder_, value); 77 } 78 79 bool Stream::set_streamable_subset(bool value) 80 { 81 FLAC__ASSERT(is_valid()); 82 return (bool)::FLAC__stream_encoder_set_streamable_subset(encoder_, value); 83 } 84 85 bool Stream::set_channels(unsigned value) 86 { 87 FLAC__ASSERT(is_valid()); 88 return (bool)::FLAC__stream_encoder_set_channels(encoder_, value); 89 } 90 91 bool Stream::set_bits_per_sample(unsigned value) 92 { 93 FLAC__ASSERT(is_valid()); 94 return (bool)::FLAC__stream_encoder_set_bits_per_sample(encoder_, value); 95 } 96 97 bool Stream::set_sample_rate(unsigned value) 98 { 99 FLAC__ASSERT(is_valid()); 100 return (bool)::FLAC__stream_encoder_set_sample_rate(encoder_, value); 101 } 102 103 bool Stream::set_compression_level(unsigned value) 104 { 105 FLAC__ASSERT(is_valid()); 106 return (bool)::FLAC__stream_encoder_set_compression_level(encoder_, value); 107 } 108 109 bool Stream::set_blocksize(unsigned value) 110 { 111 FLAC__ASSERT(is_valid()); 112 return (bool)::FLAC__stream_encoder_set_blocksize(encoder_, value); 113 } 114 115 bool Stream::set_do_mid_side_stereo(bool value) 116 { 117 FLAC__ASSERT(is_valid()); 118 return (bool)::FLAC__stream_encoder_set_do_mid_side_stereo(encoder_, value); 119 } 120 121 bool Stream::set_loose_mid_side_stereo(bool value) 122 { 123 FLAC__ASSERT(is_valid()); 124 return (bool)::FLAC__stream_encoder_set_loose_mid_side_stereo(encoder_, value); 125 } 126 127 bool Stream::set_apodization(const char *specification) 128 { 129 FLAC__ASSERT(is_valid()); 130 return (bool)::FLAC__stream_encoder_set_apodization(encoder_, specification); 131 } 132 133 bool Stream::set_max_lpc_order(unsigned value) 134 { 135 FLAC__ASSERT(is_valid()); 136 return (bool)::FLAC__stream_encoder_set_max_lpc_order(encoder_, value); 137 } 138 139 bool Stream::set_qlp_coeff_precision(unsigned value) 140 { 141 FLAC__ASSERT(is_valid()); 142 return (bool)::FLAC__stream_encoder_set_qlp_coeff_precision(encoder_, value); 143 } 144 145 bool Stream::set_do_qlp_coeff_prec_search(bool value) 146 { 147 FLAC__ASSERT(is_valid()); 148 return (bool)::FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder_, value); 149 } 150 151 bool Stream::set_do_escape_coding(bool value) 152 { 153 FLAC__ASSERT(is_valid()); 154 return (bool)::FLAC__stream_encoder_set_do_escape_coding(encoder_, value); 155 } 156 157 bool Stream::set_do_exhaustive_model_search(bool value) 158 { 159 FLAC__ASSERT(is_valid()); 160 return (bool)::FLAC__stream_encoder_set_do_exhaustive_model_search(encoder_, value); 161 } 162 163 bool Stream::set_min_residual_partition_order(unsigned value) 164 { 165 FLAC__ASSERT(is_valid()); 166 return (bool)::FLAC__stream_encoder_set_min_residual_partition_order(encoder_, value); 167 } 168 169 bool Stream::set_max_residual_partition_order(unsigned value) 170 { 171 FLAC__ASSERT(is_valid()); 172 return (bool)::FLAC__stream_encoder_set_max_residual_partition_order(encoder_, value); 173 } 174 175 bool Stream::set_rice_parameter_search_dist(unsigned value) 176 { 177 FLAC__ASSERT(is_valid()); 178 return (bool)::FLAC__stream_encoder_set_rice_parameter_search_dist(encoder_, value); 179 } 180 181 bool Stream::set_total_samples_estimate(FLAC__uint64 value) 182 { 183 FLAC__ASSERT(is_valid()); 184 return (bool)::FLAC__stream_encoder_set_total_samples_estimate(encoder_, value); 185 } 186 187 bool Stream::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks) 188 { 189 FLAC__ASSERT(is_valid()); 190 return (bool)::FLAC__stream_encoder_set_metadata(encoder_, metadata, num_blocks); 191 } 192 193 bool Stream::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks) 194 { 195 FLAC__ASSERT(is_valid()); 196#if (defined _MSC_VER) || (defined __BORLANDC__) || (defined __SUNPRO_CC) 197 // MSVC++ can't handle: 198 // ::FLAC__StreamMetadata *m[num_blocks]; 199 // so we do this ugly workaround 200 ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks]; 201#else 202 ::FLAC__StreamMetadata *m[num_blocks]; 203#endif 204 for(unsigned i = 0; i < num_blocks; i++) { 205 // we can get away with the const_cast since we know the encoder will only correct the is_last flags 206 m[i] = const_cast< ::FLAC__StreamMetadata*>((const ::FLAC__StreamMetadata*)metadata[i]); 207 } 208#if (defined _MSC_VER) || (defined __BORLANDC__) || (defined __SUNPRO_CC) 209 // complete the hack 210 const bool ok = (bool)::FLAC__stream_encoder_set_metadata(encoder_, m, num_blocks); 211 delete [] m; 212 return ok; 213#else 214 return (bool)::FLAC__stream_encoder_set_metadata(encoder_, m, num_blocks); 215#endif 216 } 217 218 Stream::State Stream::get_state() const 219 { 220 FLAC__ASSERT(is_valid()); 221 return State(::FLAC__stream_encoder_get_state(encoder_)); 222 } 223 224 Decoder::Stream::State Stream::get_verify_decoder_state() const 225 { 226 FLAC__ASSERT(is_valid()); 227 return Decoder::Stream::State(::FLAC__stream_encoder_get_verify_decoder_state(encoder_)); 228 } 229 230 void Stream::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) 231 { 232 FLAC__ASSERT(is_valid()); 233 ::FLAC__stream_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got); 234 } 235 236 bool Stream::get_verify() const 237 { 238 FLAC__ASSERT(is_valid()); 239 return (bool)::FLAC__stream_encoder_get_verify(encoder_); 240 } 241 242 bool Stream::get_streamable_subset() const 243 { 244 FLAC__ASSERT(is_valid()); 245 return (bool)::FLAC__stream_encoder_get_streamable_subset(encoder_); 246 } 247 248 bool Stream::get_do_mid_side_stereo() const 249 { 250 FLAC__ASSERT(is_valid()); 251 return (bool)::FLAC__stream_encoder_get_do_mid_side_stereo(encoder_); 252 } 253 254 bool Stream::get_loose_mid_side_stereo() const 255 { 256 FLAC__ASSERT(is_valid()); 257 return (bool)::FLAC__stream_encoder_get_loose_mid_side_stereo(encoder_); 258 } 259 260 unsigned Stream::get_channels() const 261 { 262 FLAC__ASSERT(is_valid()); 263 return ::FLAC__stream_encoder_get_channels(encoder_); 264 } 265 266 unsigned Stream::get_bits_per_sample() const 267 { 268 FLAC__ASSERT(is_valid()); 269 return ::FLAC__stream_encoder_get_bits_per_sample(encoder_); 270 } 271 272 unsigned Stream::get_sample_rate() const 273 { 274 FLAC__ASSERT(is_valid()); 275 return ::FLAC__stream_encoder_get_sample_rate(encoder_); 276 } 277 278 unsigned Stream::get_blocksize() const 279 { 280 FLAC__ASSERT(is_valid()); 281 return ::FLAC__stream_encoder_get_blocksize(encoder_); 282 } 283 284 unsigned Stream::get_max_lpc_order() const 285 { 286 FLAC__ASSERT(is_valid()); 287 return ::FLAC__stream_encoder_get_max_lpc_order(encoder_); 288 } 289 290 unsigned Stream::get_qlp_coeff_precision() const 291 { 292 FLAC__ASSERT(is_valid()); 293 return ::FLAC__stream_encoder_get_qlp_coeff_precision(encoder_); 294 } 295 296 bool Stream::get_do_qlp_coeff_prec_search() const 297 { 298 FLAC__ASSERT(is_valid()); 299 return (bool)::FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder_); 300 } 301 302 bool Stream::get_do_escape_coding() const 303 { 304 FLAC__ASSERT(is_valid()); 305 return (bool)::FLAC__stream_encoder_get_do_escape_coding(encoder_); 306 } 307 308 bool Stream::get_do_exhaustive_model_search() const 309 { 310 FLAC__ASSERT(is_valid()); 311 return (bool)::FLAC__stream_encoder_get_do_exhaustive_model_search(encoder_); 312 } 313 314 unsigned Stream::get_min_residual_partition_order() const 315 { 316 FLAC__ASSERT(is_valid()); 317 return ::FLAC__stream_encoder_get_min_residual_partition_order(encoder_); 318 } 319 320 unsigned Stream::get_max_residual_partition_order() const 321 { 322 FLAC__ASSERT(is_valid()); 323 return ::FLAC__stream_encoder_get_max_residual_partition_order(encoder_); 324 } 325 326 unsigned Stream::get_rice_parameter_search_dist() const 327 { 328 FLAC__ASSERT(is_valid()); 329 return ::FLAC__stream_encoder_get_rice_parameter_search_dist(encoder_); 330 } 331 332 FLAC__uint64 Stream::get_total_samples_estimate() const 333 { 334 FLAC__ASSERT(is_valid()); 335 return ::FLAC__stream_encoder_get_total_samples_estimate(encoder_); 336 } 337 338 ::FLAC__StreamEncoderInitStatus Stream::init() 339 { 340 FLAC__ASSERT(is_valid()); 341 return ::FLAC__stream_encoder_init_stream(encoder_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this); 342 } 343 344 ::FLAC__StreamEncoderInitStatus Stream::init_ogg() 345 { 346 FLAC__ASSERT(is_valid()); 347 return ::FLAC__stream_encoder_init_ogg_stream(encoder_, read_callback_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this); 348 } 349 350 bool Stream::finish() 351 { 352 FLAC__ASSERT(is_valid()); 353 return (bool)::FLAC__stream_encoder_finish(encoder_); 354 } 355 356 bool Stream::process(const FLAC__int32 * const buffer[], unsigned samples) 357 { 358 FLAC__ASSERT(is_valid()); 359 return (bool)::FLAC__stream_encoder_process(encoder_, buffer, samples); 360 } 361 362 bool Stream::process_interleaved(const FLAC__int32 buffer[], unsigned samples) 363 { 364 FLAC__ASSERT(is_valid()); 365 return (bool)::FLAC__stream_encoder_process_interleaved(encoder_, buffer, samples); 366 } 367 368 ::FLAC__StreamEncoderReadStatus Stream::read_callback(FLAC__byte buffer[], size_t *bytes) 369 { 370 (void)buffer, (void)bytes; 371 return ::FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED; 372 } 373 374 ::FLAC__StreamEncoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset) 375 { 376 (void)absolute_byte_offset; 377 return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED; 378 } 379 380 ::FLAC__StreamEncoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset) 381 { 382 (void)absolute_byte_offset; 383 return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; 384 } 385 386 void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata) 387 { 388 (void)metadata; 389 } 390 391 ::FLAC__StreamEncoderReadStatus Stream::read_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data) 392 { 393 (void)encoder; 394 FLAC__ASSERT(0 != client_data); 395 Stream *instance = reinterpret_cast<Stream *>(client_data); 396 FLAC__ASSERT(0 != instance); 397 return instance->read_callback(buffer, bytes); 398 } 399 400 ::FLAC__StreamEncoderWriteStatus Stream::write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data) 401 { 402 (void)encoder; 403 FLAC__ASSERT(0 != client_data); 404 Stream *instance = reinterpret_cast<Stream *>(client_data); 405 FLAC__ASSERT(0 != instance); 406 return instance->write_callback(buffer, bytes, samples, current_frame); 407 } 408 409 ::FLAC__StreamEncoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) 410 { 411 (void)encoder; 412 FLAC__ASSERT(0 != client_data); 413 Stream *instance = reinterpret_cast<Stream *>(client_data); 414 FLAC__ASSERT(0 != instance); 415 return instance->seek_callback(absolute_byte_offset); 416 } 417 418 ::FLAC__StreamEncoderTellStatus Stream::tell_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) 419 { 420 (void)encoder; 421 FLAC__ASSERT(0 != client_data); 422 Stream *instance = reinterpret_cast<Stream *>(client_data); 423 FLAC__ASSERT(0 != instance); 424 return instance->tell_callback(absolute_byte_offset); 425 } 426 427 void Stream::metadata_callback_(const ::FLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data) 428 { 429 (void)encoder; 430 FLAC__ASSERT(0 != client_data); 431 Stream *instance = reinterpret_cast<Stream *>(client_data); 432 FLAC__ASSERT(0 != instance); 433 instance->metadata_callback(metadata); 434 } 435 436 // ------------------------------------------------------------ 437 // 438 // File 439 // 440 // ------------------------------------------------------------ 441 442 File::File(): 443 Stream() 444 { } 445 446 File::~File() 447 { 448 } 449 450 ::FLAC__StreamEncoderInitStatus File::init(FILE *file) 451 { 452 FLAC__ASSERT(is_valid()); 453 return ::FLAC__stream_encoder_init_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this); 454 } 455 456 ::FLAC__StreamEncoderInitStatus File::init(const char *filename) 457 { 458 FLAC__ASSERT(is_valid()); 459 return ::FLAC__stream_encoder_init_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this); 460 } 461 462 ::FLAC__StreamEncoderInitStatus File::init(const std::string &filename) 463 { 464 return init(filename.c_str()); 465 } 466 467 ::FLAC__StreamEncoderInitStatus File::init_ogg(FILE *file) 468 { 469 FLAC__ASSERT(is_valid()); 470 return ::FLAC__stream_encoder_init_ogg_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this); 471 } 472 473 ::FLAC__StreamEncoderInitStatus File::init_ogg(const char *filename) 474 { 475 FLAC__ASSERT(is_valid()); 476 return ::FLAC__stream_encoder_init_ogg_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this); 477 } 478 479 ::FLAC__StreamEncoderInitStatus File::init_ogg(const std::string &filename) 480 { 481 return init_ogg(filename.c_str()); 482 } 483 484 // This is a dummy to satisfy the pure virtual from Stream; the 485 // read callback will never be called since we are initializing 486 // with FLAC__stream_decoder_init_FILE() or 487 // FLAC__stream_decoder_init_file() and those supply the read 488 // callback internally. 489 ::FLAC__StreamEncoderWriteStatus File::write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame) 490 { 491 (void)buffer, (void)bytes, (void)samples, (void)current_frame; 492 FLAC__ASSERT(false); 493 return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; // double protection 494 } 495 496 void File::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate) 497 { 498 (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate; 499 } 500 501 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) 502 { 503 (void)encoder; 504 FLAC__ASSERT(0 != client_data); 505 File *instance = reinterpret_cast<File *>(client_data); 506 FLAC__ASSERT(0 != instance); 507 instance->progress_callback(bytes_written, samples_written, frames_written, total_frames_estimate); 508 } 509 510 } 511} 512