blob: 37559589881a044206ff6b7af48f99c4ce93142f [file] [log] [blame]
Josh Coalson26560dd2001-02-08 00:38:41 +00001/* libFLAC - Free Lossless Audio Codec library
Josh Coalson305ae2e2002-01-26 17:36:39 +00002 * Copyright (C) 2000,2001,2002 Josh Coalson
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00003 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
Josh Coalsone6b3bbe2002-10-08 06:03:25 +000020#include <limits.h>
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000021#include <stdio.h>
22#include <stdlib.h> /* for malloc() */
23#include <string.h> /* for memcpy() */
Josh Coalson1b689822001-05-31 20:11:02 +000024#include "FLAC/assert.h"
Josh Coalsond86e03b2002-08-03 21:56:15 +000025#include "FLAC/stream_decoder.h"
Josh Coalson0a15c142001-06-13 17:59:57 +000026#include "protected/stream_encoder.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000027#include "private/bitbuffer.h"
Josh Coalsoneef56702001-03-30 00:45:22 +000028#include "private/bitmath.h"
Josh Coalson215af572001-03-27 01:15:58 +000029#include "private/crc.h"
Josh Coalsoncf30f502001-05-23 20:57:44 +000030#include "private/cpu.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000031#include "private/fixed.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000032#include "private/format.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000033#include "private/lpc.h"
Josh Coalsonfa37f1c2001-01-12 23:55:11 +000034#include "private/md5.h"
Josh Coalsond98c43d2001-05-13 05:17:01 +000035#include "private/memory.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000036#include "private/stream_encoder_framing.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000037
Josh Coalson5e31be12002-12-04 07:07:35 +000038#ifdef HAVE_CONFIG_H
39#include <config.h>
40#endif
41
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000042#ifdef min
43#undef min
44#endif
45#define min(x,y) ((x)<(y)?(x):(y))
46
47#ifdef max
48#undef max
49#endif
50#define max(x,y) ((x)>(y)?(x):(y))
51
Josh Coalsond86e03b2002-08-03 21:56:15 +000052typedef struct {
53 FLAC__int32 *data[FLAC__MAX_CHANNELS];
54 unsigned size; /* of each data[] in samples */
55 unsigned tail;
56} verify_input_fifo;
57
58typedef struct {
59 const FLAC__byte *data;
60 unsigned capacity;
61 unsigned bytes;
62} verify_output;
63
64typedef enum {
65 ENCODER_IN_MAGIC = 0,
66 ENCODER_IN_METADATA = 1,
67 ENCODER_IN_AUDIO = 2
68} EncoderStateHint;
69
Josh Coalson0a15c142001-06-13 17:59:57 +000070/***********************************************************************
71 *
72 * Private class method prototypes
73 *
74 ***********************************************************************/
75
Josh Coalsonf1eff452002-07-31 07:05:33 +000076static void set_defaults_(FLAC__StreamEncoder *encoder);
77static void free_(FLAC__StreamEncoder *encoder);
78static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
Josh Coalsond86e03b2002-08-03 21:56:15 +000079static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples);
Josh Coalsonf1eff452002-07-31 07:05:33 +000080static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
81static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
Josh Coalson6fe72f72002-08-20 04:01:59 +000082
83static FLAC__bool process_subframe_(
84 FLAC__StreamEncoder *encoder,
85 unsigned min_partition_order,
86 unsigned max_partition_order,
87 FLAC__bool precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +000088 const FLAC__FrameHeader *frame_header,
89 unsigned subframe_bps,
90 const FLAC__int32 integer_signal[],
91 const FLAC__real real_signal[],
92 FLAC__Subframe *subframe[2],
93 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
94 FLAC__int32 *residual[2],
95 unsigned *best_subframe,
96 unsigned *best_bits
97);
98
99static FLAC__bool add_subframe_(
100 FLAC__StreamEncoder *encoder,
101 const FLAC__FrameHeader *frame_header,
102 unsigned subframe_bps,
103 const FLAC__Subframe *subframe,
104 FLAC__BitBuffer *frame
105);
106
107static unsigned evaluate_constant_subframe_(
108 const FLAC__int32 signal,
109 unsigned subframe_bps,
110 FLAC__Subframe *subframe
111);
112
113static unsigned evaluate_fixed_subframe_(
114 FLAC__StreamEncoder *encoder,
115 const FLAC__int32 signal[],
116 FLAC__int32 residual[],
117 FLAC__uint32 abs_residual[],
118 FLAC__uint64 abs_residual_partition_sums[],
119 unsigned raw_bits_per_partition[],
120 unsigned blocksize,
121 unsigned subframe_bps,
122 unsigned order,
123 unsigned rice_parameter,
124 unsigned min_partition_order,
125 unsigned max_partition_order,
126 FLAC__bool precompute_partition_sums,
127 FLAC__bool do_escape_coding,
128 unsigned rice_parameter_search_dist,
129 FLAC__Subframe *subframe,
130 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
131);
132
133static unsigned evaluate_lpc_subframe_(
134 FLAC__StreamEncoder *encoder,
135 const FLAC__int32 signal[],
136 FLAC__int32 residual[],
137 FLAC__uint32 abs_residual[],
138 FLAC__uint64 abs_residual_partition_sums[],
139 unsigned raw_bits_per_partition[],
140 const FLAC__real lp_coeff[],
141 unsigned blocksize,
142 unsigned subframe_bps,
143 unsigned order,
144 unsigned qlp_coeff_precision,
145 unsigned rice_parameter,
146 unsigned min_partition_order,
147 unsigned max_partition_order,
148 FLAC__bool precompute_partition_sums,
149 FLAC__bool do_escape_coding,
150 unsigned rice_parameter_search_dist,
151 FLAC__Subframe *subframe,
152 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
153);
154
155static unsigned evaluate_verbatim_subframe_(
156 const FLAC__int32 signal[],
157 unsigned blocksize,
158 unsigned subframe_bps,
159 FLAC__Subframe *subframe
160);
161
162static unsigned find_best_partition_order_(
163 struct FLAC__StreamEncoderPrivate *private_,
164 const FLAC__int32 residual[],
165 FLAC__uint32 abs_residual[],
166 FLAC__uint64 abs_residual_partition_sums[],
167 unsigned raw_bits_per_partition[],
168 unsigned residual_samples,
169 unsigned predictor_order,
170 unsigned rice_parameter,
171 unsigned min_partition_order,
172 unsigned max_partition_order,
173 FLAC__bool precompute_partition_sums,
174 FLAC__bool do_escape_coding,
175 unsigned rice_parameter_search_dist,
176 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
177);
178
179static void precompute_partition_info_sums_(
180 const FLAC__uint32 abs_residual[],
181 FLAC__uint64 abs_residual_partition_sums[],
182 unsigned residual_samples,
183 unsigned predictor_order,
184 unsigned min_partition_order,
185 unsigned max_partition_order
186);
187
188static void precompute_partition_info_escapes_(
189 const FLAC__int32 residual[],
190 unsigned raw_bits_per_partition[],
191 unsigned residual_samples,
192 unsigned predictor_order,
193 unsigned min_partition_order,
194 unsigned max_partition_order
195);
196
Josh Coalson8395d022001-07-12 21:25:22 +0000197#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +0000198static FLAC__bool set_partitioned_rice_(
199 const FLAC__uint32 abs_residual[],
200 const FLAC__int32 residual[],
201 const unsigned residual_samples,
202 const unsigned predictor_order,
203 const unsigned suggested_rice_parameter,
204 const unsigned rice_parameter_search_dist,
205 const unsigned partition_order,
206 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
207 unsigned *bits
208);
209
210static FLAC__bool set_partitioned_rice_with_precompute_(
211 const FLAC__int32 residual[],
212 const FLAC__uint64 abs_residual_partition_sums[],
213 const unsigned raw_bits_per_partition[],
214 const unsigned residual_samples,
215 const unsigned predictor_order,
216 const unsigned suggested_rice_parameter,
217 const unsigned rice_parameter_search_dist,
218 const unsigned partition_order,
219 const FLAC__bool search_for_escapes,
220 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
221 unsigned *bits
222);
Josh Coalson8395d022001-07-12 21:25:22 +0000223#else
Josh Coalson6fe72f72002-08-20 04:01:59 +0000224static FLAC__bool set_partitioned_rice_(
225 const FLAC__uint32 abs_residual[],
226 const unsigned residual_samples,
227 const unsigned predictor_order,
228 const unsigned suggested_rice_parameter,
229 const unsigned rice_parameter_search_dist,
230 const unsigned partition_order,
231 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
232 unsigned *bits
233);
234
235static FLAC__bool set_partitioned_rice_with_precompute_(
236 const FLAC__uint32 abs_residual[],
237 const FLAC__uint64 abs_residual_partition_sums[],
238 const unsigned raw_bits_per_partition[],
239 const unsigned residual_samples,
240 const unsigned predictor_order,
241 const unsigned suggested_rice_parameter,
242 const unsigned rice_parameter_search_dist,
243 const unsigned partition_order,
244 const FLAC__bool search_for_escapes,
245 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
246 unsigned *bits
247);
Josh Coalson0a15c142001-06-13 17:59:57 +0000248#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000249
Josh Coalsonf1eff452002-07-31 07:05:33 +0000250static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples);
Josh Coalson6fe72f72002-08-20 04:01:59 +0000251
Josh Coalsond86e03b2002-08-03 21:56:15 +0000252/* verify-related routines: */
Josh Coalson6fe72f72002-08-20 04:01:59 +0000253static void append_to_verify_fifo_(
254 verify_input_fifo *fifo,
255 const FLAC__int32 * const input[],
256 unsigned input_offset,
257 unsigned channels,
258 unsigned wide_samples
259);
260
261static void append_to_verify_fifo_interleaved_(
262 verify_input_fifo *fifo,
263 const FLAC__int32 input[],
264 unsigned input_offset,
265 unsigned channels,
266 unsigned wide_samples
267);
268
269static FLAC__StreamDecoderReadStatus verify_read_callback_(
270 const FLAC__StreamDecoder *decoder,
271 FLAC__byte buffer[],
272 unsigned *bytes,
273 void *client_data
274);
275
276static FLAC__StreamDecoderWriteStatus verify_write_callback_(
277 const FLAC__StreamDecoder *decoder,
278 const FLAC__Frame *frame,
279 const FLAC__int32 * const buffer[],
280 void *client_data
281);
282
283static void verify_metadata_callback_(
284 const FLAC__StreamDecoder *decoder,
285 const FLAC__StreamMetadata *metadata,
286 void *client_data
287);
288
289static void verify_error_callback_(
290 const FLAC__StreamDecoder *decoder,
291 FLAC__StreamDecoderErrorStatus status,
292 void *client_data
293);
294
Josh Coalson0a15c142001-06-13 17:59:57 +0000295
296/***********************************************************************
297 *
298 * Private class data
299 *
300 ***********************************************************************/
301
302typedef struct FLAC__StreamEncoderPrivate {
Josh Coalson8395d022001-07-12 21:25:22 +0000303 unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */
Josh Coalson77e3f312001-06-23 03:03:24 +0000304 FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */
305 FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */
306 FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* the floating-point version of the input signal */
307 FLAC__real *real_signal_mid_side[2]; /* the floating-point version of the mid-side input signal (stereo only) */
Josh Coalson8395d022001-07-12 21:25:22 +0000308 unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */
309 unsigned subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */
Josh Coalson77e3f312001-06-23 03:03:24 +0000310 FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
311 FLAC__int32 *residual_workspace_mid_side[2][2];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000312 FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
313 FLAC__Subframe subframe_workspace_mid_side[2][2];
314 FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
315 FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
Josh Coalsona37ba462002-08-19 21:36:39 +0000316 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2];
317 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2];
318 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2];
319 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2];
Josh Coalson8395d022001-07-12 21:25:22 +0000320 unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index into the above workspaces */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000321 unsigned best_subframe_mid_side[2];
Josh Coalson8395d022001-07-12 21:25:22 +0000322 unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000323 unsigned best_subframe_bits_mid_side[2];
Josh Coalson77e3f312001-06-23 03:03:24 +0000324 FLAC__uint32 *abs_residual; /* workspace where abs(candidate residual) is stored */
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000325 FLAC__uint64 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */
Josh Coalson8395d022001-07-12 21:25:22 +0000326 unsigned *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */
Josh Coalsonaec256b2002-03-12 16:19:54 +0000327 FLAC__BitBuffer *frame; /* the current frame being worked on */
Josh Coalson8395d022001-07-12 21:25:22 +0000328 double loose_mid_side_stereo_frames_exact; /* exact number of frames the encoder will use before trying both independent and mid/side frames again */
329 unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
330 unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000331 FLAC__ChannelAssignment last_channel_assignment;
Josh Coalsoncc682512002-06-08 04:53:42 +0000332 FLAC__StreamMetadata metadata;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000333 unsigned current_sample_number;
334 unsigned current_frame_number;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +0000335 struct MD5Context md5context;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000336 FLAC__CPUInfo cpuinfo;
Josh Coalson77e3f312001-06-23 03:03:24 +0000337 unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
338 void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
339 void (*local_lpc_compute_residual_from_qlp_coefficients)(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000340 void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
Josh Coalson77e3f312001-06-23 03:03:24 +0000341 void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
Josh Coalson3262b0d2002-08-14 20:58:42 +0000342 FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */
343 FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */
344 FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */
345 FLAC__bool precompute_partition_sums; /* our initial guess as to whether precomputing the partitions sums will be a speed improvement */
Josh Coalsone6b3bbe2002-10-08 06:03:25 +0000346 FLAC__bool disable_constant_subframes;
347 FLAC__bool disable_fixed_subframes;
348 FLAC__bool disable_verbatim_subframes;
Josh Coalson681c2932002-08-01 08:19:37 +0000349 FLAC__StreamEncoderWriteCallback write_callback;
350 FLAC__StreamEncoderMetadataCallback metadata_callback;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000351 void *client_data;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000352 /* unaligned (original) pointers to allocated data */
Josh Coalson77e3f312001-06-23 03:03:24 +0000353 FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
354 FLAC__int32 *integer_signal_mid_side_unaligned[2];
355 FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
356 FLAC__real *real_signal_mid_side_unaligned[2];
357 FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
358 FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
359 FLAC__uint32 *abs_residual_unaligned;
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000360 FLAC__uint64 *abs_residual_partition_sums_unaligned;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000361 unsigned *raw_bits_per_partition_unaligned;
Josh Coalson8084b052001-11-01 00:27:29 +0000362 /*
363 * These fields have been moved here from private function local
364 * declarations merely to save stack space during encoding.
365 */
Josh Coalsonf1eff452002-07-31 07:05:33 +0000366 FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
Josh Coalsona37ba462002-08-19 21:36:39 +0000367 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000368 /*
369 * The data for the verify section
370 */
371 struct {
372 FLAC__StreamDecoder *decoder;
373 EncoderStateHint state_hint;
374 FLAC__bool needs_magic_hack;
375 verify_input_fifo input_fifo;
376 verify_output output;
377 struct {
378 FLAC__uint64 absolute_sample;
379 unsigned frame_number;
380 unsigned channel;
381 unsigned sample;
382 FLAC__int32 expected;
383 FLAC__int32 got;
384 } error_stats;
385 } verify;
Josh Coalson3262b0d2002-08-14 20:58:42 +0000386 FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
Josh Coalson0a15c142001-06-13 17:59:57 +0000387} FLAC__StreamEncoderPrivate;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000388
Josh Coalson0a15c142001-06-13 17:59:57 +0000389/***********************************************************************
390 *
391 * Public static class data
392 *
393 ***********************************************************************/
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000394
Josh Coalson6afed9f2002-10-16 22:29:47 +0000395FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
Josh Coalson0a15c142001-06-13 17:59:57 +0000396 "FLAC__STREAM_ENCODER_OK",
Josh Coalsond86e03b2002-08-03 21:56:15 +0000397 "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
398 "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
Josh Coalson00e53872001-06-16 07:32:25 +0000399 "FLAC__STREAM_ENCODER_INVALID_CALLBACK",
Josh Coalson0a15c142001-06-13 17:59:57 +0000400 "FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS",
401 "FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE",
402 "FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE",
403 "FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE",
Josh Coalson20ac2c12002-08-30 05:47:14 +0000404 "FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER",
Josh Coalson0a15c142001-06-13 17:59:57 +0000405 "FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION",
406 "FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH",
407 "FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
408 "FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE",
409 "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
410 "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
411 "FLAC__STREAM_ENCODER_FRAMING_ERROR",
Josh Coalson66075c12002-06-01 05:39:38 +0000412 "FLAC__STREAM_ENCODER_INVALID_METADATA",
Josh Coalson0a15c142001-06-13 17:59:57 +0000413 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
414 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
415 "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
416 "FLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
417 "FLAC__STREAM_ENCODER_UNINITIALIZED"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000418};
419
Josh Coalson6afed9f2002-10-16 22:29:47 +0000420FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
Josh Coalson5c491a12002-08-01 06:39:40 +0000421 "FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
422 "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000423};
424
Josh Coalson0a15c142001-06-13 17:59:57 +0000425/***********************************************************************
426 *
427 * Class constructor/destructor
428 *
Josh Coalsond86e03b2002-08-03 21:56:15 +0000429 */
Josh Coalson6afed9f2002-10-16 22:29:47 +0000430FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000431{
Josh Coalson0a15c142001-06-13 17:59:57 +0000432 FLAC__StreamEncoder *encoder;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000433 unsigned i;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000434
Josh Coalson0a15c142001-06-13 17:59:57 +0000435 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000436
Josh Coalsonea7155f2002-10-18 05:49:19 +0000437 encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder));
Josh Coalson0a15c142001-06-13 17:59:57 +0000438 if(encoder == 0) {
439 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000440 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000441
Josh Coalsonea7155f2002-10-18 05:49:19 +0000442 encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected));
Josh Coalsonfa697a92001-08-16 20:07:29 +0000443 if(encoder->protected_ == 0) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000444 free(encoder);
445 return 0;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000446 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000447
Josh Coalsonea7155f2002-10-18 05:49:19 +0000448 encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
Josh Coalsonfa697a92001-08-16 20:07:29 +0000449 if(encoder->private_ == 0) {
450 free(encoder->protected_);
Josh Coalson0a15c142001-06-13 17:59:57 +0000451 free(encoder);
452 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000453 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000454
Josh Coalsonaec256b2002-03-12 16:19:54 +0000455 encoder->private_->frame = FLAC__bitbuffer_new();
456 if(encoder->private_->frame == 0) {
457 free(encoder->private_);
458 free(encoder->protected_);
459 free(encoder);
460 return 0;
461 }
Josh Coalsond98c43d2001-05-13 05:17:01 +0000462
Josh Coalsonf1eff452002-07-31 07:05:33 +0000463 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000464
Josh Coalson3262b0d2002-08-14 20:58:42 +0000465 encoder->private_->is_being_deleted = false;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000466
467 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
468 encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
469 encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
470 }
471 for(i = 0; i < 2; i++) {
472 encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
473 encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
474 }
475 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000476 encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
477 encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000478 }
479 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000480 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
481 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][1] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1];
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000482 }
483
484 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000485 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
486 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000487 }
488 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000489 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
490 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000491 }
492 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000493 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000494
Josh Coalsonfa697a92001-08-16 20:07:29 +0000495 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000496
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000497 return encoder;
498}
499
Josh Coalson6afed9f2002-10-16 22:29:47 +0000500FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000501{
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000502 unsigned i;
503
Josh Coalsonf1eff452002-07-31 07:05:33 +0000504 FLAC__ASSERT(0 != encoder);
505 FLAC__ASSERT(0 != encoder->protected_);
506 FLAC__ASSERT(0 != encoder->private_);
507 FLAC__ASSERT(0 != encoder->private_->frame);
Josh Coalson0a15c142001-06-13 17:59:57 +0000508
Josh Coalson3262b0d2002-08-14 20:58:42 +0000509 encoder->private_->is_being_deleted = true;
510
511 FLAC__stream_encoder_finish(encoder);
512
Josh Coalson4fa90592002-12-04 07:01:37 +0000513 if(0 != encoder->private_->verify.decoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +0000514 FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000515
516 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000517 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
518 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000519 }
520 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000521 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
522 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000523 }
524 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000525 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000526
Josh Coalsonaec256b2002-03-12 16:19:54 +0000527 FLAC__bitbuffer_delete(encoder->private_->frame);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000528 free(encoder->private_);
529 free(encoder->protected_);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000530 free(encoder);
531}
532
Josh Coalson0a15c142001-06-13 17:59:57 +0000533/***********************************************************************
534 *
535 * Public class methods
536 *
537 ***********************************************************************/
538
Josh Coalson6afed9f2002-10-16 22:29:47 +0000539FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000540{
541 unsigned i;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000542 FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000543
Josh Coalsonf1eff452002-07-31 07:05:33 +0000544 FLAC__ASSERT(0 != encoder);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000545
Josh Coalsonfa697a92001-08-16 20:07:29 +0000546 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
547 return encoder->protected_->state = FLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000548
Josh Coalsonfa697a92001-08-16 20:07:29 +0000549 encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000550
Josh Coalsonfa697a92001-08-16 20:07:29 +0000551 if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
552 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_CALLBACK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000553
Josh Coalsonfa697a92001-08-16 20:07:29 +0000554 if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
555 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson69f1ee02001-01-24 00:54:43 +0000556
Josh Coalsonfa697a92001-08-16 20:07:29 +0000557 if(encoder->protected_->do_mid_side_stereo && encoder->protected_->channels != 2)
558 return encoder->protected_->state = FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH;
Josh Coalsond37d1352001-05-30 23:09:31 +0000559
Josh Coalsonfa697a92001-08-16 20:07:29 +0000560 if(encoder->protected_->loose_mid_side_stereo && !encoder->protected_->do_mid_side_stereo)
561 return encoder->protected_->state = FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000562
Josh Coalsonfa697a92001-08-16 20:07:29 +0000563 if(encoder->protected_->bits_per_sample >= 32)
564 encoder->protected_->do_mid_side_stereo = false; /* since we do 32-bit math, the side channel would have 33 bps and overflow */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000565
Josh Coalson76c68bc2002-05-17 06:22:02 +0000566 if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000567 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000568
Josh Coalson0833f342002-07-15 05:31:55 +0000569 if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000570 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000571
Josh Coalsonfa697a92001-08-16 20:07:29 +0000572 if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
573 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE;
Josh Coalson0a15c142001-06-13 17:59:57 +0000574
Josh Coalson20ac2c12002-08-30 05:47:14 +0000575 if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
576 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER;
577
Josh Coalsonfa697a92001-08-16 20:07:29 +0000578 if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
579 return encoder->protected_->state = FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
Josh Coalson0a15c142001-06-13 17:59:57 +0000580
Josh Coalsonfa697a92001-08-16 20:07:29 +0000581 if(encoder->protected_->qlp_coeff_precision == 0) {
582 if(encoder->protected_->bits_per_sample < 16) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000583 /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
584 /* @@@ until then we'll make a guess */
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000585 encoder->protected_->qlp_coeff_precision = max(FLAC__MIN_QLP_COEFF_PRECISION, 2 + encoder->protected_->bits_per_sample / 2);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000586 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000587 else if(encoder->protected_->bits_per_sample == 16) {
588 if(encoder->protected_->blocksize <= 192)
589 encoder->protected_->qlp_coeff_precision = 7;
590 else if(encoder->protected_->blocksize <= 384)
591 encoder->protected_->qlp_coeff_precision = 8;
592 else if(encoder->protected_->blocksize <= 576)
593 encoder->protected_->qlp_coeff_precision = 9;
594 else if(encoder->protected_->blocksize <= 1152)
595 encoder->protected_->qlp_coeff_precision = 10;
596 else if(encoder->protected_->blocksize <= 2304)
597 encoder->protected_->qlp_coeff_precision = 11;
598 else if(encoder->protected_->blocksize <= 4608)
599 encoder->protected_->qlp_coeff_precision = 12;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000600 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000601 encoder->protected_->qlp_coeff_precision = 13;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000602 }
603 else {
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000604 if(encoder->protected_->blocksize <= 384)
605 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-2;
606 else if(encoder->protected_->blocksize <= 1152)
607 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-1;
608 else
609 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000610 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000611 FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000612 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000613 else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000614 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000615
Josh Coalsonfa697a92001-08-16 20:07:29 +0000616 if(encoder->protected_->streamable_subset) {
Josh Coalson20ac2c12002-08-30 05:47:14 +0000617 if(
618 encoder->protected_->blocksize != 192 &&
619 encoder->protected_->blocksize != 576 &&
620 encoder->protected_->blocksize != 1152 &&
621 encoder->protected_->blocksize != 2304 &&
622 encoder->protected_->blocksize != 4608 &&
623 encoder->protected_->blocksize != 256 &&
624 encoder->protected_->blocksize != 512 &&
625 encoder->protected_->blocksize != 1024 &&
626 encoder->protected_->blocksize != 2048 &&
627 encoder->protected_->blocksize != 4096 &&
628 encoder->protected_->blocksize != 8192 &&
629 encoder->protected_->blocksize != 16384
630 )
Josh Coalsonfa697a92001-08-16 20:07:29 +0000631 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalson20ac2c12002-08-30 05:47:14 +0000632 if(
633 encoder->protected_->sample_rate != 8000 &&
634 encoder->protected_->sample_rate != 16000 &&
635 encoder->protected_->sample_rate != 22050 &&
636 encoder->protected_->sample_rate != 24000 &&
637 encoder->protected_->sample_rate != 32000 &&
638 encoder->protected_->sample_rate != 44100 &&
639 encoder->protected_->sample_rate != 48000 &&
640 encoder->protected_->sample_rate != 96000
641 )
642 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
643 if(
644 encoder->protected_->bits_per_sample != 8 &&
645 encoder->protected_->bits_per_sample != 12 &&
646 encoder->protected_->bits_per_sample != 16 &&
647 encoder->protected_->bits_per_sample != 20 &&
648 encoder->protected_->bits_per_sample != 24
649 )
650 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonc1c8d492002-09-26 04:42:10 +0000651 if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000652 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000653 }
654
Josh Coalsonfa697a92001-08-16 20:07:29 +0000655 if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
656 encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
657 if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
658 encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000659
Josh Coalson66075c12002-06-01 05:39:38 +0000660 /* validate metadata */
661 if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
662 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000663 metadata_has_seektable = false;
664 metadata_has_vorbis_comment = false;
Josh Coalson66075c12002-06-01 05:39:38 +0000665 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
Josh Coalsone4869382002-11-15 05:41:48 +0000666 if(encoder->protected_->metadata[i]->type >= FLAC__METADATA_TYPE_UNDEFINED)
667 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
668 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
Josh Coalson66075c12002-06-01 05:39:38 +0000669 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
670 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000671 if(metadata_has_seektable) /* only one is allowed */
672 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
673 metadata_has_seektable = true;
Josh Coalson0833f342002-07-15 05:31:55 +0000674 if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table))
Josh Coalson66075c12002-06-01 05:39:38 +0000675 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
676 }
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000677 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
678 if(metadata_has_vorbis_comment) /* only one is allowed */
679 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
680 metadata_has_vorbis_comment = true;
681 }
Josh Coalsone4869382002-11-15 05:41:48 +0000682 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_CUESHEET) {
Josh Coalson8f0c71b2002-12-05 06:37:46 +0000683 if(!FLAC__format_cuesheet_is_legal(&encoder->protected_->metadata[i]->data.cue_sheet, encoder->protected_->metadata[i]->data.cue_sheet.is_cd, /*violation=*/0))
Josh Coalsone4869382002-11-15 05:41:48 +0000684 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
685 }
Josh Coalson66075c12002-06-01 05:39:38 +0000686 }
687
Josh Coalsonfa697a92001-08-16 20:07:29 +0000688 encoder->private_->input_capacity = 0;
689 for(i = 0; i < encoder->protected_->channels; i++) {
690 encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
691 encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000692 }
693 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000694 encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
695 encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000696 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000697 for(i = 0; i < encoder->protected_->channels; i++) {
698 encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
699 encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
700 encoder->private_->best_subframe[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000701 }
702 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000703 encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
704 encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
705 encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000706 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000707 encoder->private_->abs_residual_unaligned = encoder->private_->abs_residual = 0;
708 encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
709 encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
710 encoder->private_->loose_mid_side_stereo_frames_exact = (double)encoder->protected_->sample_rate * 0.4 / (double)encoder->protected_->blocksize;
711 encoder->private_->loose_mid_side_stereo_frames = (unsigned)(encoder->private_->loose_mid_side_stereo_frames_exact + 0.5);
712 if(encoder->private_->loose_mid_side_stereo_frames == 0)
713 encoder->private_->loose_mid_side_stereo_frames = 1;
714 encoder->private_->loose_mid_side_stereo_frame_count = 0;
715 encoder->private_->current_sample_number = 0;
716 encoder->private_->current_frame_number = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000717
Josh Coalsonfa697a92001-08-16 20:07:29 +0000718 encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
719 encoder->private_->use_wide_by_order = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(max(encoder->protected_->max_lpc_order, FLAC__MAX_FIXED_ORDER))+1 > 30); /*@@@ need to use this? */
720 encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
Josh Coalson8395d022001-07-12 21:25:22 +0000721
Josh Coalsoncf30f502001-05-23 20:57:44 +0000722 /*
723 * get the CPU info and set the function pointers
724 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000725 FLAC__cpu_info(&encoder->private_->cpuinfo);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000726 /* first default to the non-asm routines */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000727 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
728 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
729 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000730 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000731 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000732 /* now override with asm where appropriate */
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000733#ifndef FLAC__NO_ASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000734 if(encoder->private_->cpuinfo.use_asm) {
Josh Coalsoncf30f502001-05-23 20:57:44 +0000735#ifdef FLAC__CPU_IA32
Josh Coalsonfa697a92001-08-16 20:07:29 +0000736 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
Josh Coalson034d38e2001-05-24 19:29:30 +0000737#ifdef FLAC__HAS_NASM
Josh Coalson48cbe662002-12-30 23:38:14 +0000738#ifdef FLAC__SSE_OS
739 if(encoder->private_->cpuinfo.data.ia32.sse) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000740 if(encoder->protected_->max_lpc_order < 4)
741 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
742 else if(encoder->protected_->max_lpc_order < 8)
743 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
744 else if(encoder->protected_->max_lpc_order < 12)
745 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000746 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000747 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000748 }
Josh Coalson48cbe662002-12-30 23:38:14 +0000749 else
750#endif
751 if(encoder->private_->cpuinfo.data.ia32._3dnow)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000752 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
Josh Coalsonaa255362001-05-31 06:17:41 +0000753 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000754 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
755 if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
756 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
757 if(encoder->private_->cpuinfo.data.ia32.mmx) {
758 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
759 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000760 }
761 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000762 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
763 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000764 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000765#endif
Josh Coalson034d38e2001-05-24 19:29:30 +0000766#endif
Josh Coalson021ad3b2001-07-18 00:25:52 +0000767 }
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000768#endif
Josh Coalson8395d022001-07-12 21:25:22 +0000769 /* finally override based on wide-ness if necessary */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000770 if(encoder->private_->use_wide_by_block) {
771 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
Josh Coalson8395d022001-07-12 21:25:22 +0000772 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000773
Josh Coalson8395d022001-07-12 21:25:22 +0000774 /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000775 encoder->private_->precompute_partition_sums = (encoder->protected_->max_residual_partition_order > encoder->protected_->min_residual_partition_order) || encoder->protected_->do_escape_coding;
Josh Coalsoneef56702001-03-30 00:45:22 +0000776
Josh Coalsonf1eff452002-07-31 07:05:33 +0000777 if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000778 /* the above function sets the state for us in case of an error */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000779 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000780 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000781
782 if(!FLAC__bitbuffer_init(encoder->private_->frame))
783 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000784
785 /*
Josh Coalsond86e03b2002-08-03 21:56:15 +0000786 * Set up the verify stuff if necessary
787 */
788 if(encoder->protected_->verify) {
789 /*
790 * First, set up the fifo which will hold the
791 * original signal to compare against
792 */
793 encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize;
794 for(i = 0; i < encoder->protected_->channels; i++) {
795 if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size)))
796 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
797 }
798 encoder->private_->verify.input_fifo.tail = 0;
799
800 /*
801 * Now set up a stream decoder for verification
802 */
803 encoder->private_->verify.decoder = FLAC__stream_decoder_new();
804 if(0 == encoder->private_->verify.decoder)
805 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
806
807 FLAC__stream_decoder_set_read_callback(encoder->private_->verify.decoder, verify_read_callback_);
808 FLAC__stream_decoder_set_write_callback(encoder->private_->verify.decoder, verify_write_callback_);
809 FLAC__stream_decoder_set_metadata_callback(encoder->private_->verify.decoder, verify_metadata_callback_);
810 FLAC__stream_decoder_set_error_callback(encoder->private_->verify.decoder, verify_error_callback_);
811 FLAC__stream_decoder_set_client_data(encoder->private_->verify.decoder, encoder);
812 if(FLAC__stream_decoder_init(encoder->private_->verify.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
813 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
814 }
Josh Coalson589f8c72002-08-07 23:54:55 +0000815 encoder->private_->verify.error_stats.absolute_sample = 0;
816 encoder->private_->verify.error_stats.frame_number = 0;
817 encoder->private_->verify.error_stats.channel = 0;
818 encoder->private_->verify.error_stats.sample = 0;
819 encoder->private_->verify.error_stats.expected = 0;
820 encoder->private_->verify.error_stats.got = 0;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000821
822 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000823 * write the stream header
824 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000825 if(encoder->protected_->verify)
826 encoder->private_->verify.state_hint = ENCODER_IN_MAGIC;
Josh Coalsonaec256b2002-03-12 16:19:54 +0000827 if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000828 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000829 if(!write_bitbuffer_(encoder, 0)) {
830 /* the above function sets the state for us in case of an error */
831 return encoder->protected_->state;
832 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000833
Josh Coalson5c491a12002-08-01 06:39:40 +0000834 /*
835 * write the STREAMINFO metadata block
836 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000837 if(encoder->protected_->verify)
838 encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000839 encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000840 encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000841 encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
842 encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
843 encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
844 encoder->private_->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
845 encoder->private_->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
846 encoder->private_->metadata.data.stream_info.sample_rate = encoder->protected_->sample_rate;
847 encoder->private_->metadata.data.stream_info.channels = encoder->protected_->channels;
848 encoder->private_->metadata.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
849 encoder->private_->metadata.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
850 memset(encoder->private_->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
851 MD5Init(&encoder->private_->md5context);
Josh Coalson7424d2f2002-11-06 07:10:38 +0000852 if(!FLAC__bitbuffer_clear(encoder->private_->frame))
853 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonaec256b2002-03-12 16:19:54 +0000854 if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000855 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000856 if(!write_bitbuffer_(encoder, 0)) {
857 /* the above function sets the state for us in case of an error */
858 return encoder->protected_->state;
859 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000860
Josh Coalson5c491a12002-08-01 06:39:40 +0000861 /*
862 * Now that the STREAMINFO block is written, we can init this to an
863 * absurdly-high value...
864 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000865 encoder->private_->metadata.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
Josh Coalsoncbbbb5f2001-01-23 00:41:48 +0000866 /* ... and clear this to 0 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000867 encoder->private_->metadata.data.stream_info.total_samples = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000868
Josh Coalson5c491a12002-08-01 06:39:40 +0000869 /*
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000870 * Check to see if the supplied metadata contains a VORBIS_COMMENT;
871 * if not, we will write an empty one (FLAC__add_metadata_block()
872 * automatically supplies the vendor string).
873 */
874 if(!metadata_has_vorbis_comment) {
875 FLAC__StreamMetadata vorbis_comment;
876 vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
877 vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0);
878 vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */
879 vorbis_comment.data.vorbis_comment.vendor_string.length = 0;
880 vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
881 vorbis_comment.data.vorbis_comment.num_comments = 0;
882 vorbis_comment.data.vorbis_comment.comments = 0;
Josh Coalson7424d2f2002-11-06 07:10:38 +0000883 if(!FLAC__bitbuffer_clear(encoder->private_->frame))
884 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000885 if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame))
886 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
887 if(!write_bitbuffer_(encoder, 0)) {
888 /* the above function sets the state for us in case of an error */
889 return encoder->protected_->state;
890 }
891 }
892
893 /*
Josh Coalson5c491a12002-08-01 06:39:40 +0000894 * write the user's metadata blocks
895 */
896 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
897 encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
Josh Coalson7424d2f2002-11-06 07:10:38 +0000898 if(!FLAC__bitbuffer_clear(encoder->private_->frame))
899 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson5c491a12002-08-01 06:39:40 +0000900 if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame))
901 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000902 if(!write_bitbuffer_(encoder, 0)) {
903 /* the above function sets the state for us in case of an error */
904 return encoder->protected_->state;
905 }
Josh Coalson5c491a12002-08-01 06:39:40 +0000906 }
907
Josh Coalsond86e03b2002-08-03 21:56:15 +0000908 if(encoder->protected_->verify)
909 encoder->private_->verify.state_hint = ENCODER_IN_AUDIO;
910
Josh Coalsonfa697a92001-08-16 20:07:29 +0000911 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000912}
913
Josh Coalson6afed9f2002-10-16 22:29:47 +0000914FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000915{
Josh Coalsonf1eff452002-07-31 07:05:33 +0000916 FLAC__ASSERT(0 != encoder);
Josh Coalson2b245f22002-08-07 17:10:50 +0000917
Josh Coalsonfa697a92001-08-16 20:07:29 +0000918 if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000919 return;
Josh Coalson2b245f22002-08-07 17:10:50 +0000920
Josh Coalson3262b0d2002-08-14 20:58:42 +0000921 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000922 if(encoder->private_->current_sample_number != 0) {
923 encoder->protected_->blocksize = encoder->private_->current_sample_number;
924 process_frame_(encoder, true); /* true => is last frame */
925 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000926 }
Josh Coalson2b245f22002-08-07 17:10:50 +0000927
Josh Coalsonfa697a92001-08-16 20:07:29 +0000928 MD5Final(encoder->private_->metadata.data.stream_info.md5sum, &encoder->private_->md5context);
Josh Coalson2b245f22002-08-07 17:10:50 +0000929
Josh Coalson3262b0d2002-08-14 20:58:42 +0000930 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000931 encoder->private_->metadata_callback(encoder, &encoder->private_->metadata, encoder->private_->client_data);
932 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000933
Josh Coalsond86e03b2002-08-03 21:56:15 +0000934 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
935 FLAC__stream_decoder_finish(encoder->private_->verify.decoder);
936
Josh Coalsonf1eff452002-07-31 07:05:33 +0000937 free_(encoder);
938 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000939
Josh Coalsonfa697a92001-08-16 20:07:29 +0000940 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000941}
942
Josh Coalson6afed9f2002-10-16 22:29:47 +0000943FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsond86e03b2002-08-03 21:56:15 +0000944{
945 FLAC__ASSERT(0 != encoder);
946 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
947 return false;
948 encoder->protected_->verify = value;
949 return true;
950}
951
Josh Coalson6afed9f2002-10-16 22:29:47 +0000952FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000953{
Josh Coalson92031602002-07-24 06:02:11 +0000954 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000955 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000956 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000957 encoder->protected_->streamable_subset = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000958 return true;
959}
960
Josh Coalson6afed9f2002-10-16 22:29:47 +0000961FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000962{
Josh Coalson92031602002-07-24 06:02:11 +0000963 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000964 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000965 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000966 encoder->protected_->do_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000967 return true;
968}
969
Josh Coalson6afed9f2002-10-16 22:29:47 +0000970FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000971{
Josh Coalson92031602002-07-24 06:02:11 +0000972 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000973 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000974 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000975 encoder->protected_->loose_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000976 return true;
977}
978
Josh Coalson6afed9f2002-10-16 22:29:47 +0000979FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000980{
Josh Coalson92031602002-07-24 06:02:11 +0000981 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000982 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000983 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000984 encoder->protected_->channels = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000985 return true;
986}
987
Josh Coalson6afed9f2002-10-16 22:29:47 +0000988FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000989{
Josh Coalson92031602002-07-24 06:02:11 +0000990 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000991 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000992 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000993 encoder->protected_->bits_per_sample = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000994 return true;
995}
996
Josh Coalson6afed9f2002-10-16 22:29:47 +0000997FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000998{
Josh Coalson92031602002-07-24 06:02:11 +0000999 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001000 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001001 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001002 encoder->protected_->sample_rate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001003 return true;
1004}
1005
Josh Coalson6afed9f2002-10-16 22:29:47 +00001006FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001007{
Josh Coalson92031602002-07-24 06:02:11 +00001008 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001009 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001010 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001011 encoder->protected_->blocksize = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001012 return true;
1013}
1014
Josh Coalson6afed9f2002-10-16 22:29:47 +00001015FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001016{
Josh Coalson92031602002-07-24 06:02:11 +00001017 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001018 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001019 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001020 encoder->protected_->max_lpc_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001021 return true;
1022}
1023
Josh Coalson6afed9f2002-10-16 22:29:47 +00001024FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001025{
Josh Coalson92031602002-07-24 06:02:11 +00001026 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001027 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001028 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001029 encoder->protected_->qlp_coeff_precision = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001030 return true;
1031}
1032
Josh Coalson6afed9f2002-10-16 22:29:47 +00001033FLAC_API FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001034{
Josh Coalson92031602002-07-24 06:02:11 +00001035 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001036 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001037 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001038 encoder->protected_->do_qlp_coeff_prec_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001039 return true;
1040}
1041
Josh Coalson6afed9f2002-10-16 22:29:47 +00001042FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson8395d022001-07-12 21:25:22 +00001043{
Josh Coalson92031602002-07-24 06:02:11 +00001044 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001045 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson8395d022001-07-12 21:25:22 +00001046 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001047#if 0
1048 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001049 encoder->protected_->do_escape_coding = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001050#else
1051 (void)value;
1052#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001053 return true;
1054}
1055
Josh Coalson6afed9f2002-10-16 22:29:47 +00001056FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001057{
Josh Coalson92031602002-07-24 06:02:11 +00001058 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001059 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001060 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001061 encoder->protected_->do_exhaustive_model_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001062 return true;
1063}
1064
Josh Coalson6afed9f2002-10-16 22:29:47 +00001065FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001066{
Josh Coalson92031602002-07-24 06:02:11 +00001067 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001068 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001069 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001070 encoder->protected_->min_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001071 return true;
1072}
1073
Josh Coalson6afed9f2002-10-16 22:29:47 +00001074FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001075{
Josh Coalson92031602002-07-24 06:02:11 +00001076 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001077 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001078 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001079 encoder->protected_->max_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001080 return true;
1081}
1082
Josh Coalson6afed9f2002-10-16 22:29:47 +00001083FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001084{
Josh Coalson92031602002-07-24 06:02:11 +00001085 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001086 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001087 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001088#if 0
1089 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001090 encoder->protected_->rice_parameter_search_dist = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001091#else
1092 (void)value;
1093#endif
Josh Coalson00e53872001-06-16 07:32:25 +00001094 return true;
1095}
1096
Josh Coalson6afed9f2002-10-16 22:29:47 +00001097FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)
Josh Coalson00e53872001-06-16 07:32:25 +00001098{
Josh Coalson92031602002-07-24 06:02:11 +00001099 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001100 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001101 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001102 encoder->protected_->total_samples_estimate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001103 return true;
1104}
1105
Josh Coalson6afed9f2002-10-16 22:29:47 +00001106FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
Josh Coalson00e53872001-06-16 07:32:25 +00001107{
Josh Coalson92031602002-07-24 06:02:11 +00001108 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001109 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001110 return false;
Josh Coalson66075c12002-06-01 05:39:38 +00001111 encoder->protected_->metadata = metadata;
1112 encoder->protected_->num_metadata_blocks = num_blocks;
Josh Coalson00e53872001-06-16 07:32:25 +00001113 return true;
1114}
1115
Josh Coalson6afed9f2002-10-16 22:29:47 +00001116FLAC_API FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001117{
Josh Coalson92031602002-07-24 06:02:11 +00001118 FLAC__ASSERT(0 != encoder);
1119 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001120 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001121 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001122 encoder->private_->write_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001123 return true;
1124}
1125
Josh Coalson6afed9f2002-10-16 22:29:47 +00001126FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderMetadataCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001127{
Josh Coalson92031602002-07-24 06:02:11 +00001128 FLAC__ASSERT(0 != encoder);
1129 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001130 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001131 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001132 encoder->private_->metadata_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001133 return true;
1134}
1135
Josh Coalson6afed9f2002-10-16 22:29:47 +00001136FLAC_API FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value)
Josh Coalson00e53872001-06-16 07:32:25 +00001137{
Josh Coalson92031602002-07-24 06:02:11 +00001138 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001139 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001140 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001141 encoder->private_->client_data = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001142 return true;
1143}
1144
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001145/*
1146 * These three functions are not static, but not publically exposed in
1147 * include/FLAC/ either. They are used by the test suite.
1148 */
Josh Coalson6afed9f2002-10-16 22:29:47 +00001149FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001150{
1151 FLAC__ASSERT(0 != encoder);
1152 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1153 return false;
1154 encoder->private_->disable_constant_subframes = value;
1155 return true;
1156}
1157
Josh Coalson6afed9f2002-10-16 22:29:47 +00001158FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001159{
1160 FLAC__ASSERT(0 != encoder);
1161 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1162 return false;
1163 encoder->private_->disable_fixed_subframes = value;
1164 return true;
1165}
1166
Josh Coalson6afed9f2002-10-16 22:29:47 +00001167FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001168{
1169 FLAC__ASSERT(0 != encoder);
1170 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1171 return false;
1172 encoder->private_->disable_verbatim_subframes = value;
1173 return true;
1174}
1175
Josh Coalson6afed9f2002-10-16 22:29:47 +00001176FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001177{
Josh Coalson92031602002-07-24 06:02:11 +00001178 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001179 return encoder->protected_->state;
Josh Coalson0a15c142001-06-13 17:59:57 +00001180}
1181
Josh Coalson6afed9f2002-10-16 22:29:47 +00001182FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001183{
1184 FLAC__ASSERT(0 != encoder);
1185 if(encoder->protected_->verify)
1186 return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder);
1187 else
1188 return FLAC__STREAM_DECODER_UNINITIALIZED;
1189}
1190
Josh Coalson02954222002-11-08 06:16:31 +00001191FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder)
1192{
1193 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR)
1194 return FLAC__StreamEncoderStateString[encoder->protected_->state];
1195 else
1196 return FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(encoder->private_->verify.decoder)];
1197}
1198
Josh Coalson6afed9f2002-10-16 22:29:47 +00001199FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
Josh Coalson589f8c72002-08-07 23:54:55 +00001200{
1201 FLAC__ASSERT(0 != encoder);
1202 if(0 != absolute_sample)
1203 *absolute_sample = encoder->private_->verify.error_stats.absolute_sample;
1204 if(0 != frame_number)
1205 *frame_number = encoder->private_->verify.error_stats.frame_number;
1206 if(0 != channel)
1207 *channel = encoder->private_->verify.error_stats.channel;
1208 if(0 != sample)
1209 *sample = encoder->private_->verify.error_stats.sample;
1210 if(0 != expected)
1211 *expected = encoder->private_->verify.error_stats.expected;
1212 if(0 != got)
1213 *got = encoder->private_->verify.error_stats.got;
1214}
1215
Josh Coalson6afed9f2002-10-16 22:29:47 +00001216FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001217{
1218 FLAC__ASSERT(0 != encoder);
1219 return encoder->protected_->verify;
1220}
1221
Josh Coalson6afed9f2002-10-16 22:29:47 +00001222FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001223{
Josh Coalson92031602002-07-24 06:02:11 +00001224 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001225 return encoder->protected_->streamable_subset;
Josh Coalson0a15c142001-06-13 17:59:57 +00001226}
1227
Josh Coalson6afed9f2002-10-16 22:29:47 +00001228FLAC_API FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001229{
Josh Coalson92031602002-07-24 06:02:11 +00001230 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001231 return encoder->protected_->do_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001232}
1233
Josh Coalson6afed9f2002-10-16 22:29:47 +00001234FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001235{
Josh Coalson92031602002-07-24 06:02:11 +00001236 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001237 return encoder->protected_->loose_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001238}
1239
Josh Coalson6afed9f2002-10-16 22:29:47 +00001240FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001241{
Josh Coalson92031602002-07-24 06:02:11 +00001242 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001243 return encoder->protected_->channels;
Josh Coalson0a15c142001-06-13 17:59:57 +00001244}
1245
Josh Coalson6afed9f2002-10-16 22:29:47 +00001246FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001247{
Josh Coalson92031602002-07-24 06:02:11 +00001248 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001249 return encoder->protected_->bits_per_sample;
Josh Coalson0a15c142001-06-13 17:59:57 +00001250}
1251
Josh Coalson6afed9f2002-10-16 22:29:47 +00001252FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001253{
Josh Coalson92031602002-07-24 06:02:11 +00001254 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001255 return encoder->protected_->sample_rate;
Josh Coalson0a15c142001-06-13 17:59:57 +00001256}
1257
Josh Coalson6afed9f2002-10-16 22:29:47 +00001258FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001259{
Josh Coalson92031602002-07-24 06:02:11 +00001260 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001261 return encoder->protected_->blocksize;
Josh Coalson0a15c142001-06-13 17:59:57 +00001262}
1263
Josh Coalson6afed9f2002-10-16 22:29:47 +00001264FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001265{
Josh Coalson92031602002-07-24 06:02:11 +00001266 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001267 return encoder->protected_->max_lpc_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001268}
1269
Josh Coalson6afed9f2002-10-16 22:29:47 +00001270FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001271{
Josh Coalson92031602002-07-24 06:02:11 +00001272 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001273 return encoder->protected_->qlp_coeff_precision;
Josh Coalson0a15c142001-06-13 17:59:57 +00001274}
1275
Josh Coalson6afed9f2002-10-16 22:29:47 +00001276FLAC_API FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001277{
Josh Coalson92031602002-07-24 06:02:11 +00001278 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001279 return encoder->protected_->do_qlp_coeff_prec_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001280}
1281
Josh Coalson6afed9f2002-10-16 22:29:47 +00001282FLAC_API FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder)
Josh Coalson8395d022001-07-12 21:25:22 +00001283{
Josh Coalson92031602002-07-24 06:02:11 +00001284 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001285 return encoder->protected_->do_escape_coding;
Josh Coalson8395d022001-07-12 21:25:22 +00001286}
1287
Josh Coalson6afed9f2002-10-16 22:29:47 +00001288FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001289{
Josh Coalson92031602002-07-24 06:02:11 +00001290 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001291 return encoder->protected_->do_exhaustive_model_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001292}
1293
Josh Coalson6afed9f2002-10-16 22:29:47 +00001294FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001295{
Josh Coalson92031602002-07-24 06:02:11 +00001296 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001297 return encoder->protected_->min_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001298}
1299
Josh Coalson6afed9f2002-10-16 22:29:47 +00001300FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001301{
Josh Coalson92031602002-07-24 06:02:11 +00001302 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001303 return encoder->protected_->max_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001304}
1305
Josh Coalson6afed9f2002-10-16 22:29:47 +00001306FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001307{
Josh Coalson92031602002-07-24 06:02:11 +00001308 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001309 return encoder->protected_->rice_parameter_search_dist;
Josh Coalson0a15c142001-06-13 17:59:57 +00001310}
1311
Josh Coalson6afed9f2002-10-16 22:29:47 +00001312FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder)
Josh Coalson3a7b2c92002-08-02 07:38:20 +00001313{
1314 FLAC__ASSERT(0 != encoder);
1315 return encoder->protected_->total_samples_estimate;
1316}
1317
Josh Coalson6afed9f2002-10-16 22:29:47 +00001318FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001319{
1320 unsigned i, j, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001321 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001322 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001323
Josh Coalsonf1eff452002-07-31 07:05:33 +00001324 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001325 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001326
1327 j = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001328 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001329 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001330 if(encoder->protected_->verify)
1331 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1332
Josh Coalsonfa697a92001-08-16 20:07:29 +00001333 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001334 x = mid = side = buffer[0][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001335 encoder->private_->integer_signal[0][i] = x;
1336 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001337 x = buffer[1][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001338 encoder->private_->integer_signal[1][i] = x;
1339 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001340 mid += x;
1341 side -= x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001342 mid >>= 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001343 encoder->private_->integer_signal_mid_side[1][i] = side;
1344 encoder->private_->integer_signal_mid_side[0][i] = mid;
1345 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1346 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1347 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001348 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001349 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001350 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001351 return false;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001352 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001353 } while(j < samples);
1354 }
1355 else {
1356 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001357 if(encoder->protected_->verify)
1358 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1359
Josh Coalsonfa697a92001-08-16 20:07:29 +00001360 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001361 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001362 x = buffer[channel][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001363 encoder->private_->integer_signal[channel][i] = x;
1364 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001365 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001366 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001367 }
1368 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001369 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001370 return false;
1371 }
1372 } while(j < samples);
1373 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001374
1375 return true;
1376}
1377
Josh Coalson6afed9f2002-10-16 22:29:47 +00001378FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001379{
1380 unsigned i, j, k, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001381 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001382 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001383
Josh Coalsonf1eff452002-07-31 07:05:33 +00001384 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001385 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001386
1387 j = k = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001388 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001389 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001390 if(encoder->protected_->verify)
1391 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1392
Josh Coalsonfa697a92001-08-16 20:07:29 +00001393 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001394 x = mid = side = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001395 encoder->private_->integer_signal[0][i] = x;
1396 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001397 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001398 encoder->private_->integer_signal[1][i] = x;
1399 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001400 mid += x;
1401 side -= x;
1402 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001403 encoder->private_->integer_signal_mid_side[1][i] = side;
1404 encoder->private_->integer_signal_mid_side[0][i] = mid;
1405 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1406 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1407 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001408 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001409 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001410 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001411 return false;
1412 }
1413 } while(j < samples);
1414 }
1415 else {
1416 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001417 if(encoder->protected_->verify)
1418 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1419
Josh Coalsonfa697a92001-08-16 20:07:29 +00001420 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001421 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001422 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001423 encoder->private_->integer_signal[channel][i] = x;
1424 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001425 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001426 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001427 }
1428 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001429 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001430 return false;
1431 }
1432 } while(j < samples);
1433 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001434
1435 return true;
1436}
1437
Josh Coalsonf1eff452002-07-31 07:05:33 +00001438/***********************************************************************
1439 *
1440 * Private class methods
1441 *
1442 ***********************************************************************/
1443
1444void set_defaults_(FLAC__StreamEncoder *encoder)
Josh Coalson92031602002-07-24 06:02:11 +00001445{
1446 FLAC__ASSERT(0 != encoder);
1447
Josh Coalsond86e03b2002-08-03 21:56:15 +00001448 encoder->protected_->verify = false;
Josh Coalson92031602002-07-24 06:02:11 +00001449 encoder->protected_->streamable_subset = true;
1450 encoder->protected_->do_mid_side_stereo = false;
1451 encoder->protected_->loose_mid_side_stereo = false;
1452 encoder->protected_->channels = 2;
1453 encoder->protected_->bits_per_sample = 16;
1454 encoder->protected_->sample_rate = 44100;
1455 encoder->protected_->blocksize = 1152;
1456 encoder->protected_->max_lpc_order = 0;
1457 encoder->protected_->qlp_coeff_precision = 0;
1458 encoder->protected_->do_qlp_coeff_prec_search = false;
1459 encoder->protected_->do_exhaustive_model_search = false;
1460 encoder->protected_->do_escape_coding = false;
1461 encoder->protected_->min_residual_partition_order = 0;
1462 encoder->protected_->max_residual_partition_order = 0;
1463 encoder->protected_->rice_parameter_search_dist = 0;
1464 encoder->protected_->total_samples_estimate = 0;
1465 encoder->protected_->metadata = 0;
1466 encoder->protected_->num_metadata_blocks = 0;
1467
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001468 encoder->private_->disable_constant_subframes = false;
1469 encoder->private_->disable_fixed_subframes = false;
1470 encoder->private_->disable_verbatim_subframes = false;
Josh Coalson92031602002-07-24 06:02:11 +00001471 encoder->private_->write_callback = 0;
1472 encoder->private_->metadata_callback = 0;
1473 encoder->private_->client_data = 0;
1474}
1475
Josh Coalsonf1eff452002-07-31 07:05:33 +00001476void free_(FLAC__StreamEncoder *encoder)
Josh Coalson639aeb02002-07-25 05:38:23 +00001477{
1478 unsigned i, channel;
1479
Josh Coalsonf1eff452002-07-31 07:05:33 +00001480 FLAC__ASSERT(0 != encoder);
Josh Coalson639aeb02002-07-25 05:38:23 +00001481 for(i = 0; i < encoder->protected_->channels; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001482 if(0 != encoder->private_->integer_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001483 free(encoder->private_->integer_signal_unaligned[i]);
1484 encoder->private_->integer_signal_unaligned[i] = 0;
1485 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001486 if(0 != encoder->private_->real_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001487 free(encoder->private_->real_signal_unaligned[i]);
1488 encoder->private_->real_signal_unaligned[i] = 0;
1489 }
1490 }
1491 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001492 if(0 != encoder->private_->integer_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001493 free(encoder->private_->integer_signal_mid_side_unaligned[i]);
1494 encoder->private_->integer_signal_mid_side_unaligned[i] = 0;
1495 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001496 if(0 != encoder->private_->real_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001497 free(encoder->private_->real_signal_mid_side_unaligned[i]);
1498 encoder->private_->real_signal_mid_side_unaligned[i] = 0;
1499 }
1500 }
1501 for(channel = 0; channel < encoder->protected_->channels; channel++) {
1502 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001503 if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001504 free(encoder->private_->residual_workspace_unaligned[channel][i]);
1505 encoder->private_->residual_workspace_unaligned[channel][i] = 0;
1506 }
1507 }
1508 }
1509 for(channel = 0; channel < 2; channel++) {
1510 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001511 if(0 != encoder->private_->residual_workspace_mid_side_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001512 free(encoder->private_->residual_workspace_mid_side_unaligned[channel][i]);
1513 encoder->private_->residual_workspace_mid_side_unaligned[channel][i] = 0;
1514 }
1515 }
1516 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001517 if(0 != encoder->private_->abs_residual_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001518 free(encoder->private_->abs_residual_unaligned);
1519 encoder->private_->abs_residual_unaligned = 0;
1520 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001521 if(0 != encoder->private_->abs_residual_partition_sums_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001522 free(encoder->private_->abs_residual_partition_sums_unaligned);
1523 encoder->private_->abs_residual_partition_sums_unaligned = 0;
1524 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001525 if(0 != encoder->private_->raw_bits_per_partition_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001526 free(encoder->private_->raw_bits_per_partition_unaligned);
1527 encoder->private_->raw_bits_per_partition_unaligned = 0;
1528 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001529 if(encoder->protected_->verify) {
1530 for(i = 0; i < encoder->protected_->channels; i++) {
1531 if(0 != encoder->private_->verify.input_fifo.data[i]) {
1532 free(encoder->private_->verify.input_fifo.data[i]);
1533 encoder->private_->verify.input_fifo.data[i] = 0;
1534 }
1535 }
1536 }
Josh Coalson639aeb02002-07-25 05:38:23 +00001537 FLAC__bitbuffer_free(encoder->private_->frame);
1538}
1539
Josh Coalsonf1eff452002-07-31 07:05:33 +00001540FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001541{
Josh Coalson77e3f312001-06-23 03:03:24 +00001542 FLAC__bool ok;
Josh Coalson0a15c142001-06-13 17:59:57 +00001543 unsigned i, channel;
1544
1545 FLAC__ASSERT(new_size > 0);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001546 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
1547 FLAC__ASSERT(encoder->private_->current_sample_number == 0);
Josh Coalson0a15c142001-06-13 17:59:57 +00001548
1549 /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001550 if(new_size <= encoder->private_->input_capacity)
Josh Coalson0a15c142001-06-13 17:59:57 +00001551 return true;
1552
1553 ok = true;
Josh Coalson8395d022001-07-12 21:25:22 +00001554
Josh Coalsonc9c0d132002-10-04 05:29:05 +00001555 /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx()
1556 * requires that the input arrays (in our case the integer signals)
1557 * have a buffer of up to 3 zeroes in front (at negative indices) for
1558 * alignment purposes; we use 4 to keep the data well-aligned.
1559 */
Josh Coalson8395d022001-07-12 21:25:22 +00001560
Josh Coalsonfa697a92001-08-16 20:07:29 +00001561 for(i = 0; ok && i < encoder->protected_->channels; i++) {
1562 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size+4, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]);
1563 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]);
1564 memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4);
1565 encoder->private_->integer_signal[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001566 }
1567 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001568 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size+4, &encoder->private_->integer_signal_mid_side_unaligned[i], &encoder->private_->integer_signal_mid_side[i]);
1569 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->real_signal_mid_side_unaligned[i], &encoder->private_->real_signal_mid_side[i]);
1570 memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4);
1571 encoder->private_->integer_signal_mid_side[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001572 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001573 for(channel = 0; ok && channel < encoder->protected_->channels; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001574 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001575 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->private_->residual_workspace_unaligned[channel][i], &encoder->private_->residual_workspace[channel][i]);
Josh Coalson0a15c142001-06-13 17:59:57 +00001576 }
1577 }
1578 for(channel = 0; ok && channel < 2; channel++) {
1579 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001580 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->private_->residual_workspace_mid_side_unaligned[channel][i], &encoder->private_->residual_workspace_mid_side[channel][i]);
Josh Coalson0a15c142001-06-13 17:59:57 +00001581 }
1582 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001583 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->private_->abs_residual_unaligned, &encoder->private_->abs_residual);
1584 if(encoder->private_->precompute_partition_sums || encoder->protected_->do_escape_coding) /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
1585 ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_size * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums);
1586 if(encoder->protected_->do_escape_coding)
1587 ok = ok && FLAC__memory_alloc_aligned_unsigned_array(new_size * 2, &encoder->private_->raw_bits_per_partition_unaligned, &encoder->private_->raw_bits_per_partition);
Josh Coalson0a15c142001-06-13 17:59:57 +00001588
1589 if(ok)
Josh Coalsonfa697a92001-08-16 20:07:29 +00001590 encoder->private_->input_capacity = new_size;
Josh Coalson0a15c142001-06-13 17:59:57 +00001591 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00001592 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson0a15c142001-06-13 17:59:57 +00001593
1594 return ok;
1595}
1596
Josh Coalsond86e03b2002-08-03 21:56:15 +00001597FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
Josh Coalson5c491a12002-08-01 06:39:40 +00001598{
1599 const FLAC__byte *buffer;
1600 unsigned bytes;
1601
1602 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1603
1604 FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
1605
Josh Coalsond86e03b2002-08-03 21:56:15 +00001606 if(encoder->protected_->verify) {
1607 encoder->private_->verify.output.data = buffer;
1608 encoder->private_->verify.output.bytes = bytes;
1609 if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) {
1610 encoder->private_->verify.needs_magic_hack = true;
1611 }
1612 else {
1613 if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) {
1614 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1615 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
1616 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
1617 return false;
1618 }
1619 }
1620 }
1621
1622 if(encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
Josh Coalsondd190232002-12-29 09:30:23 +00001623 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
Josh Coalsond86e03b2002-08-03 21:56:15 +00001624 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
Josh Coalson5c491a12002-08-01 06:39:40 +00001625 return false;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001626 }
Josh Coalson5c491a12002-08-01 06:39:40 +00001627
1628 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1629
Josh Coalsond86e03b2002-08-03 21:56:15 +00001630 if(samples > 0) {
1631 encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize);
1632 encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize);
1633 }
1634
Josh Coalson5c491a12002-08-01 06:39:40 +00001635 return true;
1636}
1637
Josh Coalsonf1eff452002-07-31 07:05:33 +00001638FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson0a15c142001-06-13 17:59:57 +00001639{
Josh Coalsonfa697a92001-08-16 20:07:29 +00001640 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001641
1642 /*
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001643 * Accumulate raw signal to the MD5 signature
1644 */
Josh Coalson57ba6f42002-06-07 05:27:37 +00001645 if(!FLAC__MD5Accumulate(&encoder->private_->md5context, (const FLAC__int32 * const *)encoder->private_->integer_signal, encoder->protected_->channels, encoder->protected_->blocksize, (encoder->protected_->bits_per_sample+7) / 8)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001646 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001647 return false;
1648 }
1649
1650 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001651 * Process the frame header and subframes into the frame bitbuffer
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001652 */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001653 if(!process_subframes_(encoder, is_last_frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001654 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001655 return false;
1656 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001657
1658 /*
1659 * Zero-pad the frame to a byte_boundary
1660 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001661 if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001662 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001663 return false;
1664 }
1665
1666 /*
Josh Coalson215af572001-03-27 01:15:58 +00001667 * CRC-16 the whole thing
1668 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001669 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1670 FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__bitbuffer_get_write_crc16(encoder->private_->frame), FLAC__FRAME_FOOTER_CRC_LEN);
Josh Coalson215af572001-03-27 01:15:58 +00001671
1672 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001673 * Write it
1674 */
Josh Coalsond86e03b2002-08-03 21:56:15 +00001675 if(!write_bitbuffer_(encoder, encoder->protected_->blocksize)) {
1676 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001677 return false;
1678 }
1679
1680 /*
1681 * Get ready for the next frame
1682 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001683 encoder->private_->current_sample_number = 0;
1684 encoder->private_->current_frame_number++;
1685 encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001686
1687 return true;
1688}
1689
Josh Coalsonf1eff452002-07-31 07:05:33 +00001690FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001691{
1692 FLAC__FrameHeader frame_header;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001693 unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00001694 FLAC__bool do_independent, do_mid_side, precompute_partition_sums;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001695
1696 /*
Josh Coalson60f77d72001-04-25 02:16:36 +00001697 * Calculate the min,max Rice partition orders
Josh Coalson94e02cd2001-01-25 10:41:06 +00001698 */
1699 if(is_last_frame) {
1700 max_partition_order = 0;
1701 }
1702 else {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001703 max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize);
1704 max_partition_order = min(max_partition_order, encoder->protected_->max_residual_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001705 }
Josh Coalson60f77d72001-04-25 02:16:36 +00001706 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001707
Josh Coalsonfa697a92001-08-16 20:07:29 +00001708 precompute_partition_sums = encoder->private_->precompute_partition_sums && ((max_partition_order > min_partition_order) || encoder->protected_->do_escape_coding);
Josh Coalson8395d022001-07-12 21:25:22 +00001709
Josh Coalson94e02cd2001-01-25 10:41:06 +00001710 /*
1711 * Setup the frame
1712 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001713 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001714 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001715 return false;
1716 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001717 frame_header.blocksize = encoder->protected_->blocksize;
1718 frame_header.sample_rate = encoder->protected_->sample_rate;
1719 frame_header.channels = encoder->protected_->channels;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001720 frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001721 frame_header.bits_per_sample = encoder->protected_->bits_per_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00001722 frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001723 frame_header.number.frame_number = encoder->private_->current_frame_number;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001724
1725 /*
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001726 * Figure out what channel assignments to try
1727 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001728 if(encoder->protected_->do_mid_side_stereo) {
1729 if(encoder->protected_->loose_mid_side_stereo) {
1730 if(encoder->private_->loose_mid_side_stereo_frame_count == 0) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001731 do_independent = true;
1732 do_mid_side = true;
1733 }
1734 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001735 do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001736 do_mid_side = !do_independent;
1737 }
1738 }
1739 else {
1740 do_independent = true;
1741 do_mid_side = true;
1742 }
1743 }
1744 else {
1745 do_independent = true;
1746 do_mid_side = false;
1747 }
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001748
Josh Coalson1b689822001-05-31 20:11:02 +00001749 FLAC__ASSERT(do_independent || do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001750
1751 /*
Josh Coalson82b73242001-03-28 22:17:05 +00001752 * Check for wasted bits; set effective bps for each subframe
Josh Coalson859bc542001-03-27 22:22:27 +00001753 */
1754 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001755 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001756 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001757 encoder->private_->subframe_workspace[channel][0].wasted_bits = encoder->private_->subframe_workspace[channel][1].wasted_bits = w;
1758 encoder->private_->subframe_bps[channel] = encoder->protected_->bits_per_sample - w;
Josh Coalson82b73242001-03-28 22:17:05 +00001759 }
Josh Coalson859bc542001-03-27 22:22:27 +00001760 }
1761 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001762 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson82b73242001-03-28 22:17:05 +00001763 for(channel = 0; channel < 2; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001764 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001765 encoder->private_->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private_->subframe_workspace_mid_side[channel][1].wasted_bits = w;
1766 encoder->private_->subframe_bps_mid_side[channel] = encoder->protected_->bits_per_sample - w + (channel==0? 0:1);
Josh Coalson82b73242001-03-28 22:17:05 +00001767 }
Josh Coalson859bc542001-03-27 22:22:27 +00001768 }
1769
1770 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001771 * First do a normal encoding pass of each independent channel
1772 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001773 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001774 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001775 if(!
1776 process_subframe_(
1777 encoder,
1778 min_partition_order,
1779 max_partition_order,
1780 precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00001781 &frame_header,
1782 encoder->private_->subframe_bps[channel],
1783 encoder->private_->integer_signal[channel],
1784 encoder->private_->real_signal[channel],
1785 encoder->private_->subframe_workspace_ptr[channel],
1786 encoder->private_->partitioned_rice_contents_workspace_ptr[channel],
1787 encoder->private_->residual_workspace[channel],
1788 encoder->private_->best_subframe+channel,
1789 encoder->private_->best_subframe_bits+channel
1790 )
1791 )
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001792 return false;
1793 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001794 }
1795
1796 /*
1797 * Now do mid and side channels if requested
1798 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001799 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001800 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001801
1802 for(channel = 0; channel < 2; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001803 if(!
1804 process_subframe_(
1805 encoder,
1806 min_partition_order,
1807 max_partition_order,
1808 precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00001809 &frame_header,
1810 encoder->private_->subframe_bps_mid_side[channel],
1811 encoder->private_->integer_signal_mid_side[channel],
1812 encoder->private_->real_signal_mid_side[channel],
1813 encoder->private_->subframe_workspace_ptr_mid_side[channel],
1814 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel],
1815 encoder->private_->residual_workspace_mid_side[channel],
1816 encoder->private_->best_subframe_mid_side+channel,
1817 encoder->private_->best_subframe_bits_mid_side+channel
1818 )
1819 )
Josh Coalson94e02cd2001-01-25 10:41:06 +00001820 return false;
1821 }
1822 }
1823
1824 /*
1825 * Compose the frame bitbuffer
1826 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001827 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +00001828 unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
1829 FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001830 FLAC__ChannelAssignment channel_assignment;
1831
Josh Coalsonfa697a92001-08-16 20:07:29 +00001832 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001833
Josh Coalsonfa697a92001-08-16 20:07:29 +00001834 if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) {
1835 channel_assignment = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT? FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT : FLAC__CHANNEL_ASSIGNMENT_MID_SIDE);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001836 }
1837 else {
1838 unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
1839 unsigned min_bits;
1840 FLAC__ChannelAssignment ca;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001841
Josh Coalson1b689822001-05-31 20:11:02 +00001842 FLAC__ASSERT(do_independent && do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001843
1844 /* We have to figure out which channel assignent results in the smallest frame */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001845 bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1];
1846 bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1];
1847 bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1];
1848 bits[FLAC__CHANNEL_ASSIGNMENT_MID_SIDE ] = encoder->private_->best_subframe_bits_mid_side[0] + encoder->private_->best_subframe_bits_mid_side[1];
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001849
Josh Coalson7424d2f2002-11-06 07:10:38 +00001850 for(channel_assignment = (FLAC__ChannelAssignment)0, min_bits = bits[0], ca = (FLAC__ChannelAssignment)1; (int)ca <= 3; ca = (FLAC__ChannelAssignment)((int)ca + 1)) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001851 if(bits[ca] < min_bits) {
1852 min_bits = bits[ca];
1853 channel_assignment = ca;
1854 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001855 }
1856 }
1857
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001858 frame_header.channel_assignment = channel_assignment;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001859
Josh Coalsonaec256b2002-03-12 16:19:54 +00001860 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001861 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001862 return false;
1863 }
1864
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001865 switch(channel_assignment) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001866 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001867 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1868 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001869 break;
1870 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001871 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1872 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001873 break;
1874 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001875 left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
1876 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001877 break;
1878 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001879 left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]];
1880 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001881 break;
1882 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001883 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001884 }
Josh Coalson82b73242001-03-28 22:17:05 +00001885
1886 switch(channel_assignment) {
1887 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001888 left_bps = encoder->private_->subframe_bps [0];
1889 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001890 break;
1891 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001892 left_bps = encoder->private_->subframe_bps [0];
1893 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001894 break;
1895 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001896 left_bps = encoder->private_->subframe_bps_mid_side[1];
1897 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001898 break;
1899 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001900 left_bps = encoder->private_->subframe_bps_mid_side[0];
1901 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001902 break;
1903 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001904 FLAC__ASSERT(0);
Josh Coalson82b73242001-03-28 22:17:05 +00001905 }
1906
1907 /* note that encoder_add_subframe_ sets the state for us in case of an error */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001908 if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001909 return false;
Josh Coalsonf1eff452002-07-31 07:05:33 +00001910 if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001911 return false;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001912 }
1913 else {
Josh Coalsonaec256b2002-03-12 16:19:54 +00001914 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001915 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001916 return false;
1917 }
1918
Josh Coalsonfa697a92001-08-16 20:07:29 +00001919 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001920 if(!add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001921 /* the above function sets the state for us in case of an error */
1922 return false;
1923 }
1924 }
1925 }
1926
Josh Coalsonfa697a92001-08-16 20:07:29 +00001927 if(encoder->protected_->loose_mid_side_stereo) {
1928 encoder->private_->loose_mid_side_stereo_frame_count++;
1929 if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames)
1930 encoder->private_->loose_mid_side_stereo_frame_count = 0;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001931 }
1932
Josh Coalsonfa697a92001-08-16 20:07:29 +00001933 encoder->private_->last_channel_assignment = frame_header.channel_assignment;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001934
Josh Coalson94e02cd2001-01-25 10:41:06 +00001935 return true;
1936}
1937
Josh Coalson6fe72f72002-08-20 04:01:59 +00001938FLAC__bool process_subframe_(
1939 FLAC__StreamEncoder *encoder,
1940 unsigned min_partition_order,
1941 unsigned max_partition_order,
1942 FLAC__bool precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00001943 const FLAC__FrameHeader *frame_header,
1944 unsigned subframe_bps,
1945 const FLAC__int32 integer_signal[],
1946 const FLAC__real real_signal[],
1947 FLAC__Subframe *subframe[2],
1948 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
1949 FLAC__int32 *residual[2],
1950 unsigned *best_subframe,
1951 unsigned *best_bits
1952)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001953{
Josh Coalson77e3f312001-06-23 03:03:24 +00001954 FLAC__real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
1955 FLAC__real lpc_residual_bits_per_sample;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001956 FLAC__real autoc[FLAC__MAX_LPC_ORDER+1]; /* WATCHOUT: the size is important even though encoder->protected_->max_lpc_order might be less; some asm routines need all the space */
Josh Coalson77e3f312001-06-23 03:03:24 +00001957 FLAC__real lpc_error[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001958 unsigned min_lpc_order, max_lpc_order, lpc_order;
1959 unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
1960 unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
1961 unsigned rice_parameter;
1962 unsigned _candidate_bits, _best_bits;
1963 unsigned _best_subframe;
1964
1965 /* verbatim subframe is the baseline against which we measure other compressed subframes */
1966 _best_subframe = 0;
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001967 if(encoder->private_->disable_verbatim_subframes && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER)
1968 _best_bits = UINT_MAX;
1969 else
1970 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001971
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001972 if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
1973 unsigned signal_is_constant = false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001974 guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample);
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001975 /* check for constant subframe */
1976 if(!encoder->private_->disable_constant_subframes && fixed_residual_bits_per_sample[1] == 0.0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001977 /* the above means integer_signal+FLAC__MAX_FIXED_ORDER is constant, now we just have to check the warmup samples */
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001978 unsigned i;
1979 signal_is_constant = true;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001980 for(i = 1; i <= FLAC__MAX_FIXED_ORDER; i++) {
1981 if(integer_signal[0] != integer_signal[i]) {
1982 signal_is_constant = false;
1983 break;
1984 }
1985 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001986 }
1987 if(signal_is_constant) {
1988 _candidate_bits = evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
1989 if(_candidate_bits < _best_bits) {
1990 _best_subframe = !_best_subframe;
1991 _best_bits = _candidate_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001992 }
1993 }
1994 else {
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001995 if(!encoder->private_->disable_fixed_subframes || (encoder->protected_->max_lpc_order == 0 && _best_bits == UINT_MAX)) {
1996 /* encode fixed */
1997 if(encoder->protected_->do_exhaustive_model_search) {
1998 min_fixed_order = 0;
1999 max_fixed_order = FLAC__MAX_FIXED_ORDER;
Josh Coalson8395d022001-07-12 21:25:22 +00002000 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002001 else {
2002 min_fixed_order = max_fixed_order = guess_fixed_order;
2003 }
2004 for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
2005 if(fixed_residual_bits_per_sample[fixed_order] >= (FLAC__real)subframe_bps)
2006 continue; /* don't even try */
2007 rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > 0.0)? (unsigned)(fixed_residual_bits_per_sample[fixed_order]+0.5) : 0; /* 0.5 is for rounding */
2008#ifndef FLAC__SYMMETRIC_RICE
2009 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
2010#endif
2011 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
2012#ifdef DEBUG_VERBOSE
2013 fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2014#endif
2015 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2016 }
2017 _candidate_bits =
2018 evaluate_fixed_subframe_(
2019 encoder,
2020 integer_signal,
2021 residual[!_best_subframe],
2022 encoder->private_->abs_residual,
2023 encoder->private_->abs_residual_partition_sums,
2024 encoder->private_->raw_bits_per_partition,
2025 frame_header->blocksize,
2026 subframe_bps,
2027 fixed_order,
2028 rice_parameter,
2029 min_partition_order,
2030 max_partition_order,
2031 precompute_partition_sums,
2032 encoder->protected_->do_escape_coding,
2033 encoder->protected_->rice_parameter_search_dist,
2034 subframe[!_best_subframe],
2035 partitioned_rice_contents[!_best_subframe]
2036 );
2037 if(_candidate_bits < _best_bits) {
2038 _best_subframe = !_best_subframe;
2039 _best_bits = _candidate_bits;
2040 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002041 }
2042 }
2043
2044 /* encode lpc */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002045 if(encoder->protected_->max_lpc_order > 0) {
2046 if(encoder->protected_->max_lpc_order >= frame_header->blocksize)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002047 max_lpc_order = frame_header->blocksize-1;
2048 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00002049 max_lpc_order = encoder->protected_->max_lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002050 if(max_lpc_order > 0) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002051 encoder->private_->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002052 /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
2053 if(autoc[0] != 0.0) {
Josh Coalson8084b052001-11-01 00:27:29 +00002054 FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
Josh Coalsonfa697a92001-08-16 20:07:29 +00002055 if(encoder->protected_->do_exhaustive_model_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002056 min_lpc_order = 1;
2057 }
2058 else {
Josh Coalson82b73242001-03-28 22:17:05 +00002059 unsigned guess_lpc_order = FLAC__lpc_compute_best_order(lpc_error, max_lpc_order, frame_header->blocksize, subframe_bps);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002060 min_lpc_order = max_lpc_order = guess_lpc_order;
2061 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002062 for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
2063 lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order);
Josh Coalson77e3f312001-06-23 03:03:24 +00002064 if(lpc_residual_bits_per_sample >= (FLAC__real)subframe_bps)
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002065 continue; /* don't even try */
2066 rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002067#ifndef FLAC__SYMMETRIC_RICE
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002068 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00002069#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002070 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002071#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002072 fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2073#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002074 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002075 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002076 if(encoder->protected_->do_qlp_coeff_prec_search) {
2077 min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
2078 /* ensure a 32-bit datapath throughout for 16bps or less */
2079 if(subframe_bps <= 16)
2080 max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION);
2081 else
2082 max_qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
2083 }
2084 else {
2085 min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
2086 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002087 for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00002088 _candidate_bits =
2089 evaluate_lpc_subframe_(
2090 encoder,
2091 integer_signal,
2092 residual[!_best_subframe],
2093 encoder->private_->abs_residual,
2094 encoder->private_->abs_residual_partition_sums,
2095 encoder->private_->raw_bits_per_partition,
2096 encoder->private_->lp_coeff[lpc_order-1],
2097 frame_header->blocksize,
2098 subframe_bps,
2099 lpc_order,
2100 qlp_coeff_precision,
2101 rice_parameter,
2102 min_partition_order,
2103 max_partition_order,
2104 precompute_partition_sums,
2105 encoder->protected_->do_escape_coding,
2106 encoder->protected_->rice_parameter_search_dist,
2107 subframe[!_best_subframe],
2108 partitioned_rice_contents[!_best_subframe]
2109 );
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002110 if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
2111 if(_candidate_bits < _best_bits) {
2112 _best_subframe = !_best_subframe;
2113 _best_bits = _candidate_bits;
2114 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002115 }
2116 }
2117 }
2118 }
2119 }
2120 }
2121 }
2122 }
2123
Josh Coalson72695802002-10-11 06:25:16 +00002124 /* under rare circumstances this can happen when all but lpc subframe types are disabled: */
2125 if(_best_bits == UINT_MAX) {
2126 FLAC__ASSERT(_best_subframe == 0);
2127 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
2128 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002129
Josh Coalson94e02cd2001-01-25 10:41:06 +00002130 *best_subframe = _best_subframe;
2131 *best_bits = _best_bits;
2132
2133 return true;
2134}
2135
Josh Coalson6fe72f72002-08-20 04:01:59 +00002136FLAC__bool add_subframe_(
2137 FLAC__StreamEncoder *encoder,
2138 const FLAC__FrameHeader *frame_header,
2139 unsigned subframe_bps,
2140 const FLAC__Subframe *subframe,
2141 FLAC__BitBuffer *frame
2142)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002143{
2144 switch(subframe->type) {
2145 case FLAC__SUBFRAME_TYPE_CONSTANT:
Josh Coalson82b73242001-03-28 22:17:05 +00002146 if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002147 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002148 return false;
2149 }
2150 break;
2151 case FLAC__SUBFRAME_TYPE_FIXED:
Josh Coalson82b73242001-03-28 22:17:05 +00002152 if(!FLAC__subframe_add_fixed(&(subframe->data.fixed), frame_header->blocksize - subframe->data.fixed.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002153 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002154 return false;
2155 }
2156 break;
2157 case FLAC__SUBFRAME_TYPE_LPC:
Josh Coalson82b73242001-03-28 22:17:05 +00002158 if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), frame_header->blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002159 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002160 return false;
2161 }
2162 break;
2163 case FLAC__SUBFRAME_TYPE_VERBATIM:
Josh Coalson82b73242001-03-28 22:17:05 +00002164 if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002165 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002166 return false;
2167 }
2168 break;
2169 default:
Josh Coalson1b689822001-05-31 20:11:02 +00002170 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002171 }
2172
2173 return true;
2174}
2175
Josh Coalson6fe72f72002-08-20 04:01:59 +00002176unsigned evaluate_constant_subframe_(
2177 const FLAC__int32 signal,
2178 unsigned subframe_bps,
2179 FLAC__Subframe *subframe
2180)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002181{
2182 subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
2183 subframe->data.constant.value = signal;
2184
Josh Coalson82b73242001-03-28 22:17:05 +00002185 return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe_bps;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002186}
2187
Josh Coalson6fe72f72002-08-20 04:01:59 +00002188unsigned evaluate_fixed_subframe_(
2189 FLAC__StreamEncoder *encoder,
2190 const FLAC__int32 signal[],
2191 FLAC__int32 residual[],
2192 FLAC__uint32 abs_residual[],
2193 FLAC__uint64 abs_residual_partition_sums[],
2194 unsigned raw_bits_per_partition[],
2195 unsigned blocksize,
2196 unsigned subframe_bps,
2197 unsigned order,
2198 unsigned rice_parameter,
2199 unsigned min_partition_order,
2200 unsigned max_partition_order,
2201 FLAC__bool precompute_partition_sums,
2202 FLAC__bool do_escape_coding,
2203 unsigned rice_parameter_search_dist,
2204 FLAC__Subframe *subframe,
2205 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2206)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002207{
2208 unsigned i, residual_bits;
2209 const unsigned residual_samples = blocksize - order;
2210
2211 FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
2212
2213 subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
2214
2215 subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002216 subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002217 subframe->data.fixed.residual = residual;
2218
Josh Coalson6fe72f72002-08-20 04:01:59 +00002219 residual_bits =
2220 find_best_partition_order_(
2221 encoder->private_,
2222 residual,
2223 abs_residual,
2224 abs_residual_partition_sums,
2225 raw_bits_per_partition,
2226 residual_samples,
2227 order,
2228 rice_parameter,
2229 min_partition_order,
2230 max_partition_order,
2231 precompute_partition_sums,
2232 do_escape_coding,
2233 rice_parameter_search_dist,
2234 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2235 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002236
2237 subframe->data.fixed.order = order;
2238 for(i = 0; i < order; i++)
2239 subframe->data.fixed.warmup[i] = signal[i];
2240
Josh Coalson82b73242001-03-28 22:17:05 +00002241 return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (order * subframe_bps) + residual_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002242}
2243
Josh Coalson6fe72f72002-08-20 04:01:59 +00002244unsigned evaluate_lpc_subframe_(
2245 FLAC__StreamEncoder *encoder,
2246 const FLAC__int32 signal[],
2247 FLAC__int32 residual[],
2248 FLAC__uint32 abs_residual[],
2249 FLAC__uint64 abs_residual_partition_sums[],
2250 unsigned raw_bits_per_partition[],
2251 const FLAC__real lp_coeff[],
2252 unsigned blocksize,
2253 unsigned subframe_bps,
2254 unsigned order,
2255 unsigned qlp_coeff_precision,
2256 unsigned rice_parameter,
2257 unsigned min_partition_order,
2258 unsigned max_partition_order,
2259 FLAC__bool precompute_partition_sums,
2260 FLAC__bool do_escape_coding,
2261 unsigned rice_parameter_search_dist,
2262 FLAC__Subframe *subframe,
2263 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2264)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002265{
Josh Coalson77e3f312001-06-23 03:03:24 +00002266 FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00002267 unsigned i, residual_bits;
2268 int quantization, ret;
2269 const unsigned residual_samples = blocksize - order;
2270
Josh Coalson20ac2c12002-08-30 05:47:14 +00002271 /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */
2272 if(subframe_bps <= 16) {
2273 FLAC__ASSERT(order > 0);
2274 FLAC__ASSERT(order <= FLAC__MAX_LPC_ORDER);
2275 qlp_coeff_precision = min(qlp_coeff_precision, 32 - subframe_bps - FLAC__bitmath_ilog2(order));
2276 }
2277
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002278 ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, qlp_coeff, &quantization);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002279 if(ret != 0)
2280 return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
2281
Josh Coalsonfb9d18f2002-10-21 07:04:07 +00002282 if(subframe_bps + qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32)
2283 if(subframe_bps <= 16 && qlp_coeff_precision <= 16)
2284 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
2285 else
2286 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002287 else
2288 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002289
2290 subframe->type = FLAC__SUBFRAME_TYPE_LPC;
2291
2292 subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002293 subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002294 subframe->data.lpc.residual = residual;
2295
Josh Coalson6fe72f72002-08-20 04:01:59 +00002296 residual_bits =
2297 find_best_partition_order_(
2298 encoder->private_,
2299 residual,
2300 abs_residual,
2301 abs_residual_partition_sums,
2302 raw_bits_per_partition,
2303 residual_samples,
2304 order,
2305 rice_parameter,
2306 min_partition_order,
2307 max_partition_order,
2308 precompute_partition_sums,
2309 do_escape_coding,
2310 rice_parameter_search_dist,
2311 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2312 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002313
2314 subframe->data.lpc.order = order;
2315 subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
2316 subframe->data.lpc.quantization_level = quantization;
Josh Coalson77e3f312001-06-23 03:03:24 +00002317 memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002318 for(i = 0; i < order; i++)
2319 subframe->data.lpc.warmup[i] = signal[i];
2320
Josh Coalson82b73242001-03-28 22:17:05 +00002321 return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN + FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN + (order * (qlp_coeff_precision + subframe_bps)) + residual_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002322}
2323
Josh Coalson6fe72f72002-08-20 04:01:59 +00002324unsigned evaluate_verbatim_subframe_(
2325 const FLAC__int32 signal[],
2326 unsigned blocksize,
2327 unsigned subframe_bps,
2328 FLAC__Subframe *subframe
2329)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002330{
2331 subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
2332
2333 subframe->data.verbatim.data = signal;
2334
Josh Coalson82b73242001-03-28 22:17:05 +00002335 return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (blocksize * subframe_bps);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002336}
2337
Josh Coalson6fe72f72002-08-20 04:01:59 +00002338unsigned find_best_partition_order_(
2339 FLAC__StreamEncoderPrivate *private_,
2340 const FLAC__int32 residual[],
2341 FLAC__uint32 abs_residual[],
2342 FLAC__uint64 abs_residual_partition_sums[],
2343 unsigned raw_bits_per_partition[],
2344 unsigned residual_samples,
2345 unsigned predictor_order,
2346 unsigned rice_parameter,
2347 unsigned min_partition_order,
2348 unsigned max_partition_order,
2349 FLAC__bool precompute_partition_sums,
2350 FLAC__bool do_escape_coding,
2351 unsigned rice_parameter_search_dist,
2352 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
2353)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002354{
Josh Coalson77e3f312001-06-23 03:03:24 +00002355 FLAC__int32 r;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002356 unsigned residual_bits, best_residual_bits = 0;
Josh Coalsonafcd8772001-04-18 22:59:25 +00002357 unsigned residual_sample;
Josh Coalson8084b052001-11-01 00:27:29 +00002358 unsigned best_parameters_index = 0;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002359 const unsigned blocksize = residual_samples + predictor_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002360
Josh Coalson2051dd42001-04-12 22:22:34 +00002361 /* compute abs(residual) for use later */
2362 for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
2363 r = residual[residual_sample];
Josh Coalson77e3f312001-06-23 03:03:24 +00002364 abs_residual[residual_sample] = (FLAC__uint32)(r<0? -r : r);
Josh Coalson2051dd42001-04-12 22:22:34 +00002365 }
2366
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002367 max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(max_partition_order, blocksize, predictor_order);
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002368 min_partition_order = min(min_partition_order, max_partition_order);
2369
Josh Coalson8395d022001-07-12 21:25:22 +00002370 if(precompute_partition_sums) {
2371 int partition_order;
2372 unsigned sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002373
Josh Coalsonf1eff452002-07-31 07:05:33 +00002374 precompute_partition_info_sums_(abs_residual, abs_residual_partition_sums, residual_samples, predictor_order, min_partition_order, max_partition_order);
Josh Coalson8395d022001-07-12 21:25:22 +00002375
2376 if(do_escape_coding)
Josh Coalsonf1eff452002-07-31 07:05:33 +00002377 precompute_partition_info_escapes_(residual, raw_bits_per_partition, residual_samples, predictor_order, min_partition_order, max_partition_order);
Josh Coalson8395d022001-07-12 21:25:22 +00002378
2379 for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
2380#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002381 if(!
2382 set_partitioned_rice_with_precompute_(
2383 residual,
2384 abs_residual_partition_sums+sum,
2385 raw_bits_per_partition+sum,
2386 residual_samples,
2387 predictor_order,
2388 rice_parameter,
2389 rice_parameter_search_dist,
2390 (unsigned)partition_order,
2391 do_escape_coding,
2392 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2393 &residual_bits
2394 )
2395 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002396#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002397 if(!
2398 set_partitioned_rice_with_precompute_(
2399 abs_residual,
2400 abs_residual_partition_sums+sum,
2401 raw_bits_per_partition+sum,
2402 residual_samples,
2403 predictor_order,
2404 rice_parameter,
2405 rice_parameter_search_dist,
2406 (unsigned)partition_order,
2407 do_escape_coding,
2408 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2409 &residual_bits
2410 )
2411 )
Josh Coalson8395d022001-07-12 21:25:22 +00002412#endif
2413 {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002414 FLAC__ASSERT(best_residual_bits != 0);
2415 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002416 }
2417 sum += 1u << partition_order;
2418 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2419 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002420 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002421 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002422 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00002423 }
2424 }
Josh Coalson8395d022001-07-12 21:25:22 +00002425 else {
2426 unsigned partition_order;
2427 for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
2428#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002429 if(!
2430 set_partitioned_rice_(
2431 abs_residual,
2432 residual,
2433 residual_samples,
2434 predictor_order,
2435 rice_parameter,
2436 rice_parameter_search_dist,
2437 partition_order,
2438 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2439 &residual_bits
2440 )
2441 )
Josh Coalson8395d022001-07-12 21:25:22 +00002442#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002443 if(!
2444 set_partitioned_rice_(
2445 abs_residual,
2446 residual_samples,
2447 predictor_order,
2448 rice_parameter,
2449 rice_parameter_search_dist,
2450 partition_order,
2451 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2452 &residual_bits
2453 )
2454 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002455#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002456 {
2457 FLAC__ASSERT(best_residual_bits != 0);
2458 break;
2459 }
2460 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2461 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002462 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002463 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002464 }
2465 }
2466 }
2467
Josh Coalsona37ba462002-08-19 21:36:39 +00002468 /*
Josh Coalson20ac2c12002-08-30 05:47:14 +00002469 * We are allowed to de-const the pointer based on our special knowledge;
Josh Coalsona37ba462002-08-19 21:36:39 +00002470 * it is const to the outside world.
2471 */
2472 {
2473 FLAC__EntropyCodingMethod_PartitionedRiceContents* best_partitioned_rice_contents = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_partitioned_rice->contents;
2474 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(best_partitioned_rice_contents, max(6, best_partitioned_rice->order));
2475 memcpy(best_partitioned_rice_contents->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2476 memcpy(best_partitioned_rice_contents->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2477 }
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002478
2479 return best_residual_bits;
2480}
2481
Josh Coalson6fe72f72002-08-20 04:01:59 +00002482void precompute_partition_info_sums_(
2483 const FLAC__uint32 abs_residual[],
2484 FLAC__uint64 abs_residual_partition_sums[],
2485 unsigned residual_samples,
2486 unsigned predictor_order,
2487 unsigned min_partition_order,
2488 unsigned max_partition_order
2489)
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002490{
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002491 int partition_order;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002492 unsigned from_partition, to_partition = 0;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002493 const unsigned blocksize = residual_samples + predictor_order;
2494
Josh Coalsonaef013c2001-04-24 01:25:42 +00002495 /* first do max_partition_order */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002496 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002497 FLAC__uint64 abs_residual_partition_sum;
Josh Coalson77e3f312001-06-23 03:03:24 +00002498 FLAC__uint32 abs_r;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002499 unsigned partition, partition_sample, partition_samples, residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002500 const unsigned partitions = 1u << partition_order;
2501 const unsigned default_partition_samples = blocksize >> partition_order;
2502
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002503 FLAC__ASSERT(default_partition_samples > predictor_order);
2504
2505 for(partition = residual_sample = 0; partition < partitions; partition++) {
2506 partition_samples = default_partition_samples;
2507 if(partition == 0)
2508 partition_samples -= predictor_order;
2509 abs_residual_partition_sum = 0;
2510 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2511 abs_r = abs_residual[residual_sample];
2512 abs_residual_partition_sum += abs_r;
2513 residual_sample++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002514 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002515 abs_residual_partition_sums[partition] = abs_residual_partition_sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002516 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002517 to_partition = partitions;
2518 break;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002519 }
Josh Coalsonf76a3612001-04-18 02:28:11 +00002520
Josh Coalson8395d022001-07-12 21:25:22 +00002521 /* now merge partitions for lower orders */
Josh Coalson6bd17572001-05-25 19:02:01 +00002522 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002523 FLAC__uint64 s;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002524 unsigned i;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002525 const unsigned partitions = 1u << partition_order;
2526 for(i = 0; i < partitions; i++) {
Josh Coalsonaef013c2001-04-24 01:25:42 +00002527 s = abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002528 from_partition++;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002529 abs_residual_partition_sums[to_partition] = s + abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002530 from_partition++;
2531 to_partition++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002532 }
2533 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002534}
Josh Coalson8395d022001-07-12 21:25:22 +00002535
Josh Coalson6fe72f72002-08-20 04:01:59 +00002536void precompute_partition_info_escapes_(
2537 const FLAC__int32 residual[],
2538 unsigned raw_bits_per_partition[],
2539 unsigned residual_samples,
2540 unsigned predictor_order,
2541 unsigned min_partition_order,
2542 unsigned max_partition_order
2543)
Josh Coalson8395d022001-07-12 21:25:22 +00002544{
2545 int partition_order;
2546 unsigned from_partition, to_partition = 0;
2547 const unsigned blocksize = residual_samples + predictor_order;
2548
2549 /* first do max_partition_order */
2550 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
2551 FLAC__int32 r, residual_partition_min, residual_partition_max;
2552 unsigned silog2_min, silog2_max;
2553 unsigned partition, partition_sample, partition_samples, residual_sample;
2554 const unsigned partitions = 1u << partition_order;
2555 const unsigned default_partition_samples = blocksize >> partition_order;
2556
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002557 FLAC__ASSERT(default_partition_samples > predictor_order);
2558
2559 for(partition = residual_sample = 0; partition < partitions; partition++) {
2560 partition_samples = default_partition_samples;
2561 if(partition == 0)
2562 partition_samples -= predictor_order;
2563 residual_partition_min = residual_partition_max = 0;
2564 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2565 r = residual[residual_sample];
2566 if(r < residual_partition_min)
2567 residual_partition_min = r;
2568 else if(r > residual_partition_max)
2569 residual_partition_max = r;
2570 residual_sample++;
Josh Coalson8395d022001-07-12 21:25:22 +00002571 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002572 silog2_min = FLAC__bitmath_silog2(residual_partition_min);
2573 silog2_max = FLAC__bitmath_silog2(residual_partition_max);
2574 raw_bits_per_partition[partition] = max(silog2_min, silog2_max);
Josh Coalson8395d022001-07-12 21:25:22 +00002575 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002576 to_partition = partitions;
2577 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002578 }
2579
2580 /* now merge partitions for lower orders */
2581 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
2582 unsigned m;
2583 unsigned i;
2584 const unsigned partitions = 1u << partition_order;
2585 for(i = 0; i < partitions; i++) {
2586 m = raw_bits_per_partition[from_partition];
2587 from_partition++;
2588 raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]);
2589 from_partition++;
2590 to_partition++;
2591 }
2592 }
2593}
Josh Coalson94e02cd2001-01-25 10:41:06 +00002594
Josh Coalson352e0f62001-03-20 22:55:50 +00002595#ifdef VARIABLE_RICE_BITS
2596#undef VARIABLE_RICE_BITS
2597#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002598#ifndef DONT_ESTIMATE_RICE_BITS
Josh Coalson352e0f62001-03-20 22:55:50 +00002599#define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
Josh Coalson8395d022001-07-12 21:25:22 +00002600#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002601
Josh Coalson8395d022001-07-12 21:25:22 +00002602#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002603FLAC__bool set_partitioned_rice_(
2604 const FLAC__uint32 abs_residual[],
2605 const FLAC__int32 residual[],
2606 const unsigned residual_samples,
2607 const unsigned predictor_order,
2608 const unsigned suggested_rice_parameter,
2609 const unsigned rice_parameter_search_dist,
2610 const unsigned partition_order,
2611 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2612 unsigned *bits
2613)
Josh Coalson8395d022001-07-12 21:25:22 +00002614#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002615FLAC__bool set_partitioned_rice_(
2616 const FLAC__uint32 abs_residual[],
2617 const unsigned residual_samples,
2618 const unsigned predictor_order,
2619 const unsigned suggested_rice_parameter,
2620 const unsigned rice_parameter_search_dist,
2621 const unsigned partition_order,
2622 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2623 unsigned *bits
2624)
Josh Coalson8395d022001-07-12 21:25:22 +00002625#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002626{
Josh Coalson034dfab2001-04-27 19:10:23 +00002627 unsigned rice_parameter, partition_bits;
2628#ifndef NO_RICE_SEARCH
2629 unsigned best_partition_bits;
2630 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2631#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002632 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002633 unsigned *parameters;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002634
Josh Coalson1b689822001-05-31 20:11:02 +00002635 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
Josh Coalson2051dd42001-04-12 22:22:34 +00002636
Josh Coalsona37ba462002-08-19 21:36:39 +00002637 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2638 parameters = partitioned_rice_contents->parameters;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002639
Josh Coalson94e02cd2001-01-25 10:41:06 +00002640 if(partition_order == 0) {
2641 unsigned i;
Josh Coalson352e0f62001-03-20 22:55:50 +00002642
Josh Coalson034dfab2001-04-27 19:10:23 +00002643#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002644 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002645 if(suggested_rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002646 min_rice_parameter = 0;
2647 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002648 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2649 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002650 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002651#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002652 fprintf(stderr, "clipping rice_parameter (%u -> %u) @2\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2653#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002654 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002655 }
2656 }
2657 else
2658 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
2659
2660 best_partition_bits = 0xffffffff;
2661 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2662#endif
2663#ifdef VARIABLE_RICE_BITS
2664#ifdef FLAC__SYMMETRIC_RICE
2665 partition_bits = (2+rice_parameter) * residual_samples;
2666#else
2667 const unsigned rice_parameter_estimate = rice_parameter-1;
2668 partition_bits = (1+rice_parameter) * residual_samples;
2669#endif
2670#else
2671 partition_bits = 0;
2672#endif
2673 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2674 for(i = 0; i < residual_samples; i++) {
2675#ifdef VARIABLE_RICE_BITS
2676#ifdef FLAC__SYMMETRIC_RICE
2677 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
2678#else
2679 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
2680#endif
2681#else
2682 partition_bits += FLAC__bitbuffer_rice_bits(residual[i], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2683#endif
2684 }
2685#ifndef NO_RICE_SEARCH
2686 if(partition_bits < best_partition_bits) {
2687 best_rice_parameter = rice_parameter;
2688 best_partition_bits = partition_bits;
2689 }
2690 }
2691#endif
2692 parameters[0] = best_rice_parameter;
2693 bits_ += best_partition_bits;
2694 }
2695 else {
2696 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002697 unsigned partition_samples;
2698 FLAC__uint64 mean, k;
Josh Coalson8395d022001-07-12 21:25:22 +00002699 const unsigned partitions = 1u << partition_order;
2700 for(partition = residual_sample = 0; partition < partitions; partition++) {
2701 partition_samples = (residual_samples+predictor_order) >> partition_order;
2702 if(partition == 0) {
2703 if(partition_samples <= predictor_order)
2704 return false;
2705 else
2706 partition_samples -= predictor_order;
2707 }
2708 mean = 0;
2709 save_residual_sample = residual_sample;
2710 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++)
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002711 mean += abs_residual[residual_sample];
Josh Coalson8395d022001-07-12 21:25:22 +00002712 residual_sample = save_residual_sample;
2713#ifdef FLAC__SYMMETRIC_RICE
2714 mean += partition_samples >> 1; /* for rounding effect */
2715 mean /= partition_samples;
2716
2717 /* calc rice_parameter = floor(log2(mean)) */
2718 rice_parameter = 0;
2719 mean>>=1;
2720 while(mean) {
2721 rice_parameter++;
2722 mean >>= 1;
2723 }
2724#else
2725 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002726 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson8395d022001-07-12 21:25:22 +00002727 ;
2728#endif
2729 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002730#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002731 fprintf(stderr, "clipping rice_parameter (%u -> %u) @3\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2732#endif
2733 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2734 }
2735
2736#ifndef NO_RICE_SEARCH
2737 if(rice_parameter_search_dist) {
2738 if(rice_parameter < rice_parameter_search_dist)
2739 min_rice_parameter = 0;
2740 else
2741 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2742 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
2743 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002744#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002745 fprintf(stderr, "clipping rice_parameter (%u -> %u) @4\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2746#endif
2747 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2748 }
2749 }
2750 else
2751 min_rice_parameter = max_rice_parameter = rice_parameter;
2752
2753 best_partition_bits = 0xffffffff;
2754 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2755#endif
2756#ifdef VARIABLE_RICE_BITS
2757#ifdef FLAC__SYMMETRIC_RICE
2758 partition_bits = (2+rice_parameter) * partition_samples;
2759#else
2760 const unsigned rice_parameter_estimate = rice_parameter-1;
2761 partition_bits = (1+rice_parameter) * partition_samples;
2762#endif
2763#else
2764 partition_bits = 0;
2765#endif
2766 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2767 save_residual_sample = residual_sample;
2768 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
2769#ifdef VARIABLE_RICE_BITS
2770#ifdef FLAC__SYMMETRIC_RICE
2771 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
2772#else
2773 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
2774#endif
2775#else
2776 partition_bits += FLAC__bitbuffer_rice_bits(residual[residual_sample], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2777#endif
2778 }
2779#ifndef NO_RICE_SEARCH
2780 if(rice_parameter != max_rice_parameter)
2781 residual_sample = save_residual_sample;
2782 if(partition_bits < best_partition_bits) {
2783 best_rice_parameter = rice_parameter;
2784 best_partition_bits = partition_bits;
2785 }
2786 }
2787#endif
2788 parameters[partition] = best_rice_parameter;
2789 bits_ += best_partition_bits;
2790 }
2791 }
2792
2793 *bits = bits_;
2794 return true;
2795}
2796
2797#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002798FLAC__bool set_partitioned_rice_with_precompute_(
2799 const FLAC__int32 residual[],
2800 const FLAC__uint64 abs_residual_partition_sums[],
2801 const unsigned raw_bits_per_partition[],
2802 const unsigned residual_samples,
2803 const unsigned predictor_order,
2804 const unsigned suggested_rice_parameter,
2805 const unsigned rice_parameter_search_dist,
2806 const unsigned partition_order,
2807 const FLAC__bool search_for_escapes,
2808 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2809 unsigned *bits
2810)
Josh Coalson8395d022001-07-12 21:25:22 +00002811#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002812FLAC__bool set_partitioned_rice_with_precompute_(
2813 const FLAC__uint32 abs_residual[],
2814 const FLAC__uint64 abs_residual_partition_sums[],
2815 const unsigned raw_bits_per_partition[],
2816 const unsigned residual_samples,
2817 const unsigned predictor_order,
2818 const unsigned suggested_rice_parameter,
2819 const unsigned rice_parameter_search_dist,
2820 const unsigned partition_order,
2821 const FLAC__bool search_for_escapes,
2822 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2823 unsigned *bits
2824)
Josh Coalson8395d022001-07-12 21:25:22 +00002825#endif
2826{
2827 unsigned rice_parameter, partition_bits;
2828#ifndef NO_RICE_SEARCH
2829 unsigned best_partition_bits;
2830 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2831#endif
2832 unsigned flat_bits;
2833 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002834 unsigned *parameters, *raw_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002835
2836 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
2837
Josh Coalsona37ba462002-08-19 21:36:39 +00002838 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2839 parameters = partitioned_rice_contents->parameters;
2840 raw_bits = partitioned_rice_contents->raw_bits;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002841
Josh Coalson8395d022001-07-12 21:25:22 +00002842 if(partition_order == 0) {
2843 unsigned i;
2844
2845#ifndef NO_RICE_SEARCH
2846 if(rice_parameter_search_dist) {
2847 if(suggested_rice_parameter < rice_parameter_search_dist)
2848 min_rice_parameter = 0;
2849 else
2850 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2851 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
2852 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002853#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002854 fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2855#endif
2856 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2857 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002858 }
2859 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002860 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
Josh Coalson2051dd42001-04-12 22:22:34 +00002861
Josh Coalson034dfab2001-04-27 19:10:23 +00002862 best_partition_bits = 0xffffffff;
2863 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2864#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002865#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002866#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002867 partition_bits = (2+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002868#else
Josh Coalson352e0f62001-03-20 22:55:50 +00002869 const unsigned rice_parameter_estimate = rice_parameter-1;
Josh Coalson034dfab2001-04-27 19:10:23 +00002870 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002871#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002872#else
2873 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002874#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002875 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson352e0f62001-03-20 22:55:50 +00002876 for(i = 0; i < residual_samples; i++) {
2877#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002878#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson2051dd42001-04-12 22:22:34 +00002879 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002880#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002881 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002882#endif
2883#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002884 partition_bits += FLAC__bitbuffer_rice_bits(residual[i], rice_parameter); /* NOTE: we will need to pass in residual[] instead of abs_residual[] */
Josh Coalson94e02cd2001-01-25 10:41:06 +00002885#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002886 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002887#ifndef NO_RICE_SEARCH
2888 if(partition_bits < best_partition_bits) {
2889 best_rice_parameter = rice_parameter;
2890 best_partition_bits = partition_bits;
Josh Coalson352e0f62001-03-20 22:55:50 +00002891 }
2892 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002893#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002894 if(search_for_escapes) {
2895 flat_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[0] * residual_samples;
2896 if(flat_bits <= best_partition_bits) {
2897 raw_bits[0] = raw_bits_per_partition[0];
2898 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2899 best_partition_bits = flat_bits;
2900 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002901 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002902 parameters[0] = best_rice_parameter;
2903 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002904 }
2905 else {
Josh Coalson4dacd192001-06-06 21:11:44 +00002906 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002907 unsigned partition_samples;
2908 FLAC__uint64 mean, k;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002909 const unsigned partitions = 1u << partition_order;
Josh Coalson4dacd192001-06-06 21:11:44 +00002910 for(partition = residual_sample = 0; partition < partitions; partition++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002911 partition_samples = (residual_samples+predictor_order) >> partition_order;
Josh Coalson034dfab2001-04-27 19:10:23 +00002912 if(partition == 0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002913 if(partition_samples <= predictor_order)
2914 return false;
2915 else
2916 partition_samples -= predictor_order;
2917 }
Josh Coalson05d20792001-06-29 23:12:26 +00002918 mean = abs_residual_partition_sums[partition];
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002919#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson05d20792001-06-29 23:12:26 +00002920 mean += partition_samples >> 1; /* for rounding effect */
2921 mean /= partition_samples;
2922
Josh Coalson034dfab2001-04-27 19:10:23 +00002923 /* calc rice_parameter = floor(log2(mean)) */
2924 rice_parameter = 0;
2925 mean>>=1;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002926 while(mean) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002927 rice_parameter++;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002928 mean >>= 1;
2929 }
Josh Coalsonb9433f92001-03-17 01:07:00 +00002930#else
Josh Coalson05d20792001-06-29 23:12:26 +00002931 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002932 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson05d20792001-06-29 23:12:26 +00002933 ;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002934#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002935 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002936#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002937 fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2938#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002939 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002940 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002941
Josh Coalson034dfab2001-04-27 19:10:23 +00002942#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002943 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002944 if(rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002945 min_rice_parameter = 0;
2946 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002947 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2948 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002949 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002950#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002951 fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2952#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002953 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002954 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002955 }
2956 else
2957 min_rice_parameter = max_rice_parameter = rice_parameter;
Josh Coalson60f77d72001-04-25 02:16:36 +00002958
Josh Coalson034dfab2001-04-27 19:10:23 +00002959 best_partition_bits = 0xffffffff;
2960 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2961#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002962#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002963#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002964 partition_bits = (2+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002965#else
Josh Coalson034dfab2001-04-27 19:10:23 +00002966 const unsigned rice_parameter_estimate = rice_parameter-1;
2967 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002968#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002969#else
2970 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002971#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002972 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson4dacd192001-06-06 21:11:44 +00002973 save_residual_sample = residual_sample;
2974 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
Josh Coalson352e0f62001-03-20 22:55:50 +00002975#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002976#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson4dacd192001-06-06 21:11:44 +00002977 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002978#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002979 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002980#endif
2981#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002982 partition_bits += FLAC__bitbuffer_rice_bits(residual[residual_sample], rice_parameter); /* NOTE: we will need to pass in residual[] instead of abs_residual[] */
Josh Coalson94e02cd2001-01-25 10:41:06 +00002983#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002984 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002985#ifndef NO_RICE_SEARCH
Josh Coalson4dacd192001-06-06 21:11:44 +00002986 if(rice_parameter != max_rice_parameter)
2987 residual_sample = save_residual_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00002988 if(partition_bits < best_partition_bits) {
2989 best_rice_parameter = rice_parameter;
2990 best_partition_bits = partition_bits;
2991 }
Josh Coalson2051dd42001-04-12 22:22:34 +00002992 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002993#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002994 if(search_for_escapes) {
2995 flat_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[partition] * partition_samples;
2996 if(flat_bits <= best_partition_bits) {
2997 raw_bits[partition] = raw_bits_per_partition[partition];
2998 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2999 best_partition_bits = flat_bits;
3000 }
Josh Coalson2051dd42001-04-12 22:22:34 +00003001 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003002 parameters[partition] = best_rice_parameter;
3003 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003004 }
3005 }
3006
3007 *bits = bits_;
3008 return true;
3009}
Josh Coalson859bc542001-03-27 22:22:27 +00003010
Josh Coalsonf1eff452002-07-31 07:05:33 +00003011unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples)
Josh Coalson859bc542001-03-27 22:22:27 +00003012{
3013 unsigned i, shift;
Josh Coalson77e3f312001-06-23 03:03:24 +00003014 FLAC__int32 x = 0;
Josh Coalson859bc542001-03-27 22:22:27 +00003015
3016 for(i = 0; i < samples && !(x&1); i++)
3017 x |= signal[i];
3018
3019 if(x == 0) {
3020 shift = 0;
3021 }
3022 else {
3023 for(shift = 0; !(x&1); shift++)
3024 x >>= 1;
3025 }
3026
3027 if(shift > 0) {
3028 for(i = 0; i < samples; i++)
3029 signal[i] >>= shift;
3030 }
3031
3032 return shift;
3033}
Josh Coalsond86e03b2002-08-03 21:56:15 +00003034
3035void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
3036{
3037 unsigned channel;
3038
3039 for(channel = 0; channel < channels; channel++)
3040 memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples);
3041
3042 fifo->tail += wide_samples;
3043
3044 FLAC__ASSERT(fifo->tail <= fifo->size);
3045}
3046
3047void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
3048{
3049 unsigned channel;
3050 unsigned sample, wide_sample;
3051 unsigned tail = fifo->tail;
3052
3053 sample = input_offset * channels;
3054 for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
3055 for(channel = 0; channel < channels; channel++)
3056 fifo->data[channel][tail] = input[sample++];
3057 tail++;
3058 }
3059 fifo->tail = tail;
3060
3061 FLAC__ASSERT(fifo->tail <= fifo->size);
3062}
3063
3064FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
3065{
3066 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3067 const unsigned encoded_bytes = encoder->private_->verify.output.bytes;
3068 (void)decoder;
3069
3070 if(encoder->private_->verify.needs_magic_hack) {
3071 FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH);
3072 *bytes = FLAC__STREAM_SYNC_LENGTH;
3073 memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes);
3074 encoder->private_->verify.needs_magic_hack = false;
3075 }
3076 else {
3077 if(encoded_bytes == 0) {
Josh Coalsonfc2b7372002-08-16 05:39:34 +00003078 /*
3079 * If we get here, a FIFO underflow has occurred,
3080 * which means there is a bug somewhere.
3081 */
3082 FLAC__ASSERT(0);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003083 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
3084 }
3085 else if(encoded_bytes < *bytes)
3086 *bytes = encoded_bytes;
3087 memcpy(buffer, encoder->private_->verify.output.data, *bytes);
3088 encoder->private_->verify.output.data += *bytes;
3089 encoder->private_->verify.output.bytes -= *bytes;
3090 }
3091
3092 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
3093}
3094
3095FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
3096{
3097 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data;
3098 unsigned channel;
3099 const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
3100 const unsigned blocksize = frame->header.blocksize;
3101 const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize;
3102
3103 for(channel = 0; channel < channels; channel++) {
3104 if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) {
3105 unsigned i, sample = 0;
3106 FLAC__int32 expect = 0, got = 0;
3107
3108 for(i = 0; i < blocksize; i++) {
3109 if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) {
3110 sample = i;
3111 expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i];
3112 got = (FLAC__int32)buffer[channel][i];
3113 break;
3114 }
3115 }
3116 FLAC__ASSERT(i < blocksize);
3117 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
3118 encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample;
Josh Coalson5f39e9f2002-08-21 05:27:01 +00003119 encoder->private_->verify.error_stats.frame_number = (unsigned)(frame->header.number.sample_number / blocksize);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003120 encoder->private_->verify.error_stats.channel = channel;
3121 encoder->private_->verify.error_stats.sample = sample;
3122 encoder->private_->verify.error_stats.expected = expect;
3123 encoder->private_->verify.error_stats.got = got;
3124 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA;
3125 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
3126 }
3127 }
3128 /* dequeue the frame from the fifo */
3129 for(channel = 0; channel < channels; channel++) {
3130 memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail - blocksize);
3131 }
3132 encoder->private_->verify.input_fifo.tail -= blocksize;
3133 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
3134}
3135
3136void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
3137{
3138 (void)decoder, (void)metadata, (void)client_data;
3139}
3140
3141void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
3142{
3143 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3144 (void)decoder, (void)status;
3145 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
3146}