Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 1 | /* libFLAC++ - Free Lossless Audio Codec library |
Josh Coalson | 0395dac | 2006-04-25 06:59:33 +0000 | [diff] [blame] | 2 | * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 3 | * |
Josh Coalson | afd8107 | 2003-01-31 23:34:56 +0000 | [diff] [blame] | 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 7 | * |
Josh Coalson | afd8107 | 2003-01-31 23:34:56 +0000 | [diff] [blame] | 8 | * - Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 10 | * |
Josh Coalson | afd8107 | 2003-01-31 23:34:56 +0000 | [diff] [blame] | 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. |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 30 | */ |
| 31 | |
| 32 | #include "FLAC++/encoder.h" |
| 33 | #include "FLAC/assert.h" |
| 34 | |
Josh Coalson | b7eeec1 | 2003-12-18 05:16:44 +0000 | [diff] [blame] | 35 | #ifdef _MSC_VER |
| 36 | // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning) |
| 37 | #pragma warning ( disable : 4800 ) |
| 38 | #endif |
| 39 | |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 40 | namespace FLAC { |
| 41 | namespace Encoder { |
| 42 | |
| 43 | File::File(): |
| 44 | encoder_(::FLAC__file_encoder_new()) |
| 45 | { } |
| 46 | |
| 47 | File::~File() |
| 48 | { |
| 49 | if(0 != encoder_) { |
| 50 | ::FLAC__file_encoder_finish(encoder_); |
| 51 | ::FLAC__file_encoder_delete(encoder_); |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | bool File::is_valid() const |
| 56 | { |
| 57 | return 0 != encoder_; |
| 58 | } |
| 59 | |
Josh Coalson | d86e03b | 2002-08-03 21:56:15 +0000 | [diff] [blame] | 60 | bool File::set_verify(bool value) |
| 61 | { |
| 62 | FLAC__ASSERT(is_valid()); |
| 63 | return (bool)::FLAC__file_encoder_set_verify(encoder_, value); |
| 64 | } |
| 65 | |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 66 | bool File::set_streamable_subset(bool value) |
| 67 | { |
| 68 | FLAC__ASSERT(is_valid()); |
| 69 | return (bool)::FLAC__file_encoder_set_streamable_subset(encoder_, value); |
| 70 | } |
| 71 | |
| 72 | bool File::set_do_mid_side_stereo(bool value) |
| 73 | { |
| 74 | FLAC__ASSERT(is_valid()); |
| 75 | return (bool)::FLAC__file_encoder_set_do_mid_side_stereo(encoder_, value); |
| 76 | } |
| 77 | |
| 78 | bool File::set_loose_mid_side_stereo(bool value) |
| 79 | { |
| 80 | FLAC__ASSERT(is_valid()); |
| 81 | return (bool)::FLAC__file_encoder_set_loose_mid_side_stereo(encoder_, value); |
| 82 | } |
| 83 | |
| 84 | bool File::set_channels(unsigned value) |
| 85 | { |
| 86 | FLAC__ASSERT(is_valid()); |
| 87 | return (bool)::FLAC__file_encoder_set_channels(encoder_, value); |
| 88 | } |
| 89 | |
| 90 | bool File::set_bits_per_sample(unsigned value) |
| 91 | { |
| 92 | FLAC__ASSERT(is_valid()); |
| 93 | return (bool)::FLAC__file_encoder_set_bits_per_sample(encoder_, value); |
| 94 | } |
| 95 | |
| 96 | bool File::set_sample_rate(unsigned value) |
| 97 | { |
| 98 | FLAC__ASSERT(is_valid()); |
| 99 | return (bool)::FLAC__file_encoder_set_sample_rate(encoder_, value); |
| 100 | } |
| 101 | |
| 102 | bool File::set_blocksize(unsigned value) |
| 103 | { |
| 104 | FLAC__ASSERT(is_valid()); |
| 105 | return (bool)::FLAC__file_encoder_set_blocksize(encoder_, value); |
| 106 | } |
| 107 | |
Josh Coalson | 6126c83 | 2006-05-03 00:20:47 +0000 | [diff] [blame^] | 108 | bool File::set_apodization(const char *specification) |
Josh Coalson | c4fe269 | 2006-05-01 05:27:13 +0000 | [diff] [blame] | 109 | { |
| 110 | FLAC__ASSERT(is_valid()); |
| 111 | return (bool)::FLAC__file_encoder_set_apodization(encoder_, specification); |
| 112 | } |
| 113 | |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 114 | bool File::set_max_lpc_order(unsigned value) |
| 115 | { |
| 116 | FLAC__ASSERT(is_valid()); |
| 117 | return (bool)::FLAC__file_encoder_set_max_lpc_order(encoder_, value); |
| 118 | } |
| 119 | |
| 120 | bool File::set_qlp_coeff_precision(unsigned value) |
| 121 | { |
| 122 | FLAC__ASSERT(is_valid()); |
| 123 | return (bool)::FLAC__file_encoder_set_qlp_coeff_precision(encoder_, value); |
| 124 | } |
| 125 | |
| 126 | bool File::set_do_qlp_coeff_prec_search(bool value) |
| 127 | { |
| 128 | FLAC__ASSERT(is_valid()); |
| 129 | return (bool)::FLAC__file_encoder_set_do_qlp_coeff_prec_search(encoder_, value); |
| 130 | } |
| 131 | |
| 132 | bool File::set_do_escape_coding(bool value) |
| 133 | { |
| 134 | FLAC__ASSERT(is_valid()); |
| 135 | return (bool)::FLAC__file_encoder_set_do_escape_coding(encoder_, value); |
| 136 | } |
| 137 | |
| 138 | bool File::set_do_exhaustive_model_search(bool value) |
| 139 | { |
| 140 | FLAC__ASSERT(is_valid()); |
| 141 | return (bool)::FLAC__file_encoder_set_do_exhaustive_model_search(encoder_, value); |
| 142 | } |
| 143 | |
| 144 | bool File::set_min_residual_partition_order(unsigned value) |
| 145 | { |
| 146 | FLAC__ASSERT(is_valid()); |
| 147 | return (bool)::FLAC__file_encoder_set_min_residual_partition_order(encoder_, value); |
| 148 | } |
| 149 | |
| 150 | bool File::set_max_residual_partition_order(unsigned value) |
| 151 | { |
| 152 | FLAC__ASSERT(is_valid()); |
| 153 | return (bool)::FLAC__file_encoder_set_max_residual_partition_order(encoder_, value); |
| 154 | } |
| 155 | |
| 156 | bool File::set_rice_parameter_search_dist(unsigned value) |
| 157 | { |
| 158 | FLAC__ASSERT(is_valid()); |
| 159 | return (bool)::FLAC__file_encoder_set_rice_parameter_search_dist(encoder_, value); |
| 160 | } |
| 161 | |
| 162 | bool File::set_total_samples_estimate(FLAC__uint64 value) |
| 163 | { |
| 164 | FLAC__ASSERT(is_valid()); |
| 165 | return (bool)::FLAC__file_encoder_set_total_samples_estimate(encoder_, value); |
| 166 | } |
| 167 | |
| 168 | bool File::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks) |
| 169 | { |
| 170 | FLAC__ASSERT(is_valid()); |
| 171 | return (bool)::FLAC__file_encoder_set_metadata(encoder_, metadata, num_blocks); |
| 172 | } |
| 173 | |
Josh Coalson | 091d84f | 2004-07-22 01:04:22 +0000 | [diff] [blame] | 174 | bool File::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks) |
| 175 | { |
| 176 | FLAC__ASSERT(is_valid()); |
Josh Coalson | f4c1a8e | 2005-01-27 03:55:35 +0000 | [diff] [blame] | 177 | #if (defined _MSC_VER) || (defined __SUNPRO_CC) |
Josh Coalson | 990f741 | 2004-07-23 05:16:11 +0000 | [diff] [blame] | 178 | // MSVC++ can't handle: |
| 179 | // ::FLAC__StreamMetadata *m[num_blocks]; |
| 180 | // so we do this ugly workaround |
| 181 | ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks]; |
| 182 | #else |
Josh Coalson | 091d84f | 2004-07-22 01:04:22 +0000 | [diff] [blame] | 183 | ::FLAC__StreamMetadata *m[num_blocks]; |
Josh Coalson | 990f741 | 2004-07-23 05:16:11 +0000 | [diff] [blame] | 184 | #endif |
Josh Coalson | 091d84f | 2004-07-22 01:04:22 +0000 | [diff] [blame] | 185 | for(unsigned i = 0; i < num_blocks; i++) { |
| 186 | // we can get away with this since we know the encoder will only correct the is_last flags |
| 187 | m[i] = const_cast< ::FLAC__StreamMetadata*>((::FLAC__StreamMetadata*)metadata[i]); |
| 188 | } |
Josh Coalson | f4c1a8e | 2005-01-27 03:55:35 +0000 | [diff] [blame] | 189 | #if (defined _MSC_VER) || (defined __SUNPRO_CC) |
Josh Coalson | 990f741 | 2004-07-23 05:16:11 +0000 | [diff] [blame] | 190 | // complete the hack |
| 191 | const bool ok = (bool)::FLAC__file_encoder_set_metadata(encoder_, m, num_blocks); |
| 192 | delete [] m; |
| 193 | return ok; |
| 194 | #else |
Josh Coalson | 091d84f | 2004-07-22 01:04:22 +0000 | [diff] [blame] | 195 | return (bool)::FLAC__file_encoder_set_metadata(encoder_, m, num_blocks); |
Josh Coalson | 990f741 | 2004-07-23 05:16:11 +0000 | [diff] [blame] | 196 | #endif |
Josh Coalson | 091d84f | 2004-07-22 01:04:22 +0000 | [diff] [blame] | 197 | } |
| 198 | |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 199 | bool File::set_filename(const char *value) |
| 200 | { |
| 201 | FLAC__ASSERT(is_valid()); |
| 202 | return (bool)::FLAC__file_encoder_set_filename(encoder_, value); |
| 203 | } |
| 204 | |
| 205 | File::State File::get_state() const |
| 206 | { |
| 207 | FLAC__ASSERT(is_valid()); |
| 208 | return State(::FLAC__file_encoder_get_state(encoder_)); |
| 209 | } |
| 210 | |
| 211 | SeekableStream::State File::get_seekable_stream_encoder_state() const |
| 212 | { |
| 213 | FLAC__ASSERT(is_valid()); |
| 214 | return SeekableStream::State(::FLAC__file_encoder_get_seekable_stream_encoder_state(encoder_)); |
| 215 | } |
| 216 | |
| 217 | Stream::State File::get_stream_encoder_state() const |
| 218 | { |
| 219 | FLAC__ASSERT(is_valid()); |
| 220 | return Stream::State(::FLAC__file_encoder_get_stream_encoder_state(encoder_)); |
| 221 | } |
| 222 | |
Josh Coalson | d86e03b | 2002-08-03 21:56:15 +0000 | [diff] [blame] | 223 | Decoder::Stream::State File::get_verify_decoder_state() const |
| 224 | { |
| 225 | FLAC__ASSERT(is_valid()); |
| 226 | return Decoder::Stream::State(::FLAC__file_encoder_get_verify_decoder_state(encoder_)); |
| 227 | } |
| 228 | |
Josh Coalson | 589f8c7 | 2002-08-07 23:54:55 +0000 | [diff] [blame] | 229 | void File::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) |
| 230 | { |
| 231 | FLAC__ASSERT(is_valid()); |
Josh Coalson | 5f39e9f | 2002-08-21 05:27:01 +0000 | [diff] [blame] | 232 | ::FLAC__file_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got); |
Josh Coalson | 589f8c7 | 2002-08-07 23:54:55 +0000 | [diff] [blame] | 233 | } |
| 234 | |
Josh Coalson | d86e03b | 2002-08-03 21:56:15 +0000 | [diff] [blame] | 235 | bool File::get_verify() const |
| 236 | { |
| 237 | FLAC__ASSERT(is_valid()); |
| 238 | return (bool)::FLAC__file_encoder_get_verify(encoder_); |
| 239 | } |
| 240 | |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 241 | bool File::get_streamable_subset() const |
| 242 | { |
| 243 | FLAC__ASSERT(is_valid()); |
| 244 | return (bool)::FLAC__file_encoder_get_streamable_subset(encoder_); |
| 245 | } |
| 246 | |
| 247 | bool File::get_do_mid_side_stereo() const |
| 248 | { |
| 249 | FLAC__ASSERT(is_valid()); |
| 250 | return (bool)::FLAC__file_encoder_get_do_mid_side_stereo(encoder_); |
| 251 | } |
| 252 | |
| 253 | bool File::get_loose_mid_side_stereo() const |
| 254 | { |
| 255 | FLAC__ASSERT(is_valid()); |
| 256 | return (bool)::FLAC__file_encoder_get_loose_mid_side_stereo(encoder_); |
| 257 | } |
| 258 | |
| 259 | unsigned File::get_channels() const |
| 260 | { |
| 261 | FLAC__ASSERT(is_valid()); |
| 262 | return ::FLAC__file_encoder_get_channels(encoder_); |
| 263 | } |
| 264 | |
| 265 | unsigned File::get_bits_per_sample() const |
| 266 | { |
| 267 | FLAC__ASSERT(is_valid()); |
| 268 | return ::FLAC__file_encoder_get_bits_per_sample(encoder_); |
| 269 | } |
| 270 | |
| 271 | unsigned File::get_sample_rate() const |
| 272 | { |
| 273 | FLAC__ASSERT(is_valid()); |
| 274 | return ::FLAC__file_encoder_get_sample_rate(encoder_); |
| 275 | } |
| 276 | |
| 277 | unsigned File::get_blocksize() const |
| 278 | { |
| 279 | FLAC__ASSERT(is_valid()); |
| 280 | return ::FLAC__file_encoder_get_blocksize(encoder_); |
| 281 | } |
| 282 | |
| 283 | unsigned File::get_max_lpc_order() const |
| 284 | { |
| 285 | FLAC__ASSERT(is_valid()); |
| 286 | return ::FLAC__file_encoder_get_max_lpc_order(encoder_); |
| 287 | } |
| 288 | |
| 289 | unsigned File::get_qlp_coeff_precision() const |
| 290 | { |
| 291 | FLAC__ASSERT(is_valid()); |
| 292 | return ::FLAC__file_encoder_get_qlp_coeff_precision(encoder_); |
| 293 | } |
| 294 | |
| 295 | bool File::get_do_qlp_coeff_prec_search() const |
| 296 | { |
| 297 | FLAC__ASSERT(is_valid()); |
| 298 | return (bool)::FLAC__file_encoder_get_do_qlp_coeff_prec_search(encoder_); |
| 299 | } |
| 300 | |
| 301 | bool File::get_do_escape_coding() const |
| 302 | { |
| 303 | FLAC__ASSERT(is_valid()); |
| 304 | return (bool)::FLAC__file_encoder_get_do_escape_coding(encoder_); |
| 305 | } |
| 306 | |
| 307 | bool File::get_do_exhaustive_model_search() const |
| 308 | { |
| 309 | FLAC__ASSERT(is_valid()); |
| 310 | return (bool)::FLAC__file_encoder_get_do_exhaustive_model_search(encoder_); |
| 311 | } |
| 312 | |
| 313 | unsigned File::get_min_residual_partition_order() const |
| 314 | { |
| 315 | FLAC__ASSERT(is_valid()); |
| 316 | return ::FLAC__file_encoder_get_min_residual_partition_order(encoder_); |
| 317 | } |
| 318 | |
| 319 | unsigned File::get_max_residual_partition_order() const |
| 320 | { |
| 321 | FLAC__ASSERT(is_valid()); |
| 322 | return ::FLAC__file_encoder_get_max_residual_partition_order(encoder_); |
| 323 | } |
| 324 | |
| 325 | unsigned File::get_rice_parameter_search_dist() const |
| 326 | { |
| 327 | FLAC__ASSERT(is_valid()); |
| 328 | return ::FLAC__file_encoder_get_rice_parameter_search_dist(encoder_); |
| 329 | } |
| 330 | |
Josh Coalson | b5bc249 | 2002-08-02 07:40:38 +0000 | [diff] [blame] | 331 | FLAC__uint64 File::get_total_samples_estimate() const |
| 332 | { |
| 333 | FLAC__ASSERT(is_valid()); |
| 334 | return ::FLAC__file_encoder_get_total_samples_estimate(encoder_); |
| 335 | } |
| 336 | |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 337 | File::State File::init() |
| 338 | { |
| 339 | FLAC__ASSERT(is_valid()); |
Josh Coalson | b5bc249 | 2002-08-02 07:40:38 +0000 | [diff] [blame] | 340 | ::FLAC__file_encoder_set_progress_callback(encoder_, progress_callback_); |
| 341 | ::FLAC__file_encoder_set_client_data(encoder_, (void*)this); |
Josh Coalson | ebece62 | 2002-08-02 06:03:18 +0000 | [diff] [blame] | 342 | return State(::FLAC__file_encoder_init(encoder_)); |
| 343 | } |
| 344 | |
| 345 | void File::finish() |
| 346 | { |
| 347 | FLAC__ASSERT(is_valid()); |
| 348 | ::FLAC__file_encoder_finish(encoder_); |
| 349 | } |
| 350 | |
| 351 | bool File::process(const FLAC__int32 * const buffer[], unsigned samples) |
| 352 | { |
| 353 | FLAC__ASSERT(is_valid()); |
| 354 | return (bool)::FLAC__file_encoder_process(encoder_, buffer, samples); |
| 355 | } |
| 356 | |
| 357 | bool File::process_interleaved(const FLAC__int32 buffer[], unsigned samples) |
| 358 | { |
| 359 | FLAC__ASSERT(is_valid()); |
| 360 | return (bool)::FLAC__file_encoder_process_interleaved(encoder_, buffer, samples); |
| 361 | } |
| 362 | |
Josh Coalson | 2ea0839 | 2002-08-08 22:55:45 +0000 | [diff] [blame] | 363 | void File::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate) |
Josh Coalson | b5bc249 | 2002-08-02 07:40:38 +0000 | [diff] [blame] | 364 | { |
Josh Coalson | 2ea0839 | 2002-08-08 22:55:45 +0000 | [diff] [blame] | 365 | (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate; |
Josh Coalson | b5bc249 | 2002-08-02 07:40:38 +0000 | [diff] [blame] | 366 | } |
| 367 | |
Josh Coalson | 2ea0839 | 2002-08-08 22:55:45 +0000 | [diff] [blame] | 368 | void File::progress_callback_(const ::FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data) |
Josh Coalson | b5bc249 | 2002-08-02 07:40:38 +0000 | [diff] [blame] | 369 | { |
| 370 | (void)encoder; |
| 371 | FLAC__ASSERT(0 != client_data); |
| 372 | File *instance = reinterpret_cast<File *>(client_data); |
| 373 | FLAC__ASSERT(0 != instance); |
Josh Coalson | 2ea0839 | 2002-08-08 22:55:45 +0000 | [diff] [blame] | 374 | instance->progress_callback(bytes_written, samples_written, frames_written, total_frames_estimate); |
Josh Coalson | b5bc249 | 2002-08-02 07:40:38 +0000 | [diff] [blame] | 375 | } |
| 376 | |
Josh Coalson | c71bfe9 | 2005-01-25 02:27:20 +0000 | [diff] [blame] | 377 | } |
| 378 | } |