blob: ca033b0676ec0cc202d644d18df91b6ca65a7a7a [file] [log] [blame]
Josh Coalson26560dd2001-02-08 00:38:41 +00001/* libFLAC - Free Lossless Audio Codec library
Josh Coalson95643902004-01-17 04:14:43 +00002 * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00003 *
Josh Coalsonafd81072003-01-31 23:34:56 +00004 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00007 *
Josh Coalsonafd81072003-01-31 23:34:56 +00008 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000010 *
Josh Coalsonafd81072003-01-31 23:34:56 +000011 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000030 */
31
Josh Coalsone6b3bbe2002-10-08 06:03:25 +000032#include <limits.h>
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000033#include <stdio.h>
34#include <stdlib.h> /* for malloc() */
35#include <string.h> /* for memcpy() */
Josh Coalson1b689822001-05-31 20:11:02 +000036#include "FLAC/assert.h"
Josh Coalsond86e03b2002-08-03 21:56:15 +000037#include "FLAC/stream_decoder.h"
Josh Coalson0a15c142001-06-13 17:59:57 +000038#include "protected/stream_encoder.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000039#include "private/bitbuffer.h"
Josh Coalsoneef56702001-03-30 00:45:22 +000040#include "private/bitmath.h"
Josh Coalson215af572001-03-27 01:15:58 +000041#include "private/crc.h"
Josh Coalsoncf30f502001-05-23 20:57:44 +000042#include "private/cpu.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000043#include "private/fixed.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000044#include "private/format.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000045#include "private/lpc.h"
Josh Coalsonfa37f1c2001-01-12 23:55:11 +000046#include "private/md5.h"
Josh Coalsond98c43d2001-05-13 05:17:01 +000047#include "private/memory.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000048#include "private/stream_encoder_framing.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000049
Josh Coalson5e31be12002-12-04 07:07:35 +000050#ifdef HAVE_CONFIG_H
51#include <config.h>
52#endif
53
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000054#ifdef min
55#undef min
56#endif
57#define min(x,y) ((x)<(y)?(x):(y))
58
59#ifdef max
60#undef max
61#endif
62#define max(x,y) ((x)>(y)?(x):(y))
63
Josh Coalsond86e03b2002-08-03 21:56:15 +000064typedef struct {
65 FLAC__int32 *data[FLAC__MAX_CHANNELS];
66 unsigned size; /* of each data[] in samples */
67 unsigned tail;
68} verify_input_fifo;
69
70typedef struct {
71 const FLAC__byte *data;
72 unsigned capacity;
73 unsigned bytes;
74} verify_output;
75
76typedef enum {
77 ENCODER_IN_MAGIC = 0,
78 ENCODER_IN_METADATA = 1,
79 ENCODER_IN_AUDIO = 2
80} EncoderStateHint;
81
Josh Coalson0a15c142001-06-13 17:59:57 +000082/***********************************************************************
83 *
84 * Private class method prototypes
85 *
86 ***********************************************************************/
87
Josh Coalsonf1eff452002-07-31 07:05:33 +000088static void set_defaults_(FLAC__StreamEncoder *encoder);
89static void free_(FLAC__StreamEncoder *encoder);
90static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
Josh Coalsond86e03b2002-08-03 21:56:15 +000091static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples);
Josh Coalsonf1eff452002-07-31 07:05:33 +000092static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
93static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
Josh Coalson6fe72f72002-08-20 04:01:59 +000094
95static FLAC__bool process_subframe_(
96 FLAC__StreamEncoder *encoder,
97 unsigned min_partition_order,
98 unsigned max_partition_order,
99 FLAC__bool precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +0000100 const FLAC__FrameHeader *frame_header,
101 unsigned subframe_bps,
102 const FLAC__int32 integer_signal[],
103 const FLAC__real real_signal[],
104 FLAC__Subframe *subframe[2],
105 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
106 FLAC__int32 *residual[2],
107 unsigned *best_subframe,
108 unsigned *best_bits
109);
110
111static FLAC__bool add_subframe_(
112 FLAC__StreamEncoder *encoder,
113 const FLAC__FrameHeader *frame_header,
114 unsigned subframe_bps,
115 const FLAC__Subframe *subframe,
116 FLAC__BitBuffer *frame
117);
118
119static unsigned evaluate_constant_subframe_(
120 const FLAC__int32 signal,
121 unsigned subframe_bps,
122 FLAC__Subframe *subframe
123);
124
125static unsigned evaluate_fixed_subframe_(
126 FLAC__StreamEncoder *encoder,
127 const FLAC__int32 signal[],
128 FLAC__int32 residual[],
129 FLAC__uint32 abs_residual[],
130 FLAC__uint64 abs_residual_partition_sums[],
131 unsigned raw_bits_per_partition[],
132 unsigned blocksize,
133 unsigned subframe_bps,
134 unsigned order,
135 unsigned rice_parameter,
136 unsigned min_partition_order,
137 unsigned max_partition_order,
138 FLAC__bool precompute_partition_sums,
139 FLAC__bool do_escape_coding,
140 unsigned rice_parameter_search_dist,
141 FLAC__Subframe *subframe,
142 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
143);
144
145static unsigned evaluate_lpc_subframe_(
146 FLAC__StreamEncoder *encoder,
147 const FLAC__int32 signal[],
148 FLAC__int32 residual[],
149 FLAC__uint32 abs_residual[],
150 FLAC__uint64 abs_residual_partition_sums[],
151 unsigned raw_bits_per_partition[],
152 const FLAC__real lp_coeff[],
153 unsigned blocksize,
154 unsigned subframe_bps,
155 unsigned order,
156 unsigned qlp_coeff_precision,
157 unsigned rice_parameter,
158 unsigned min_partition_order,
159 unsigned max_partition_order,
160 FLAC__bool precompute_partition_sums,
161 FLAC__bool do_escape_coding,
162 unsigned rice_parameter_search_dist,
163 FLAC__Subframe *subframe,
164 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
165);
166
167static unsigned evaluate_verbatim_subframe_(
168 const FLAC__int32 signal[],
169 unsigned blocksize,
170 unsigned subframe_bps,
171 FLAC__Subframe *subframe
172);
173
174static unsigned find_best_partition_order_(
175 struct FLAC__StreamEncoderPrivate *private_,
176 const FLAC__int32 residual[],
177 FLAC__uint32 abs_residual[],
178 FLAC__uint64 abs_residual_partition_sums[],
179 unsigned raw_bits_per_partition[],
180 unsigned residual_samples,
181 unsigned predictor_order,
182 unsigned rice_parameter,
183 unsigned min_partition_order,
184 unsigned max_partition_order,
185 FLAC__bool precompute_partition_sums,
186 FLAC__bool do_escape_coding,
187 unsigned rice_parameter_search_dist,
188 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
189);
190
191static void precompute_partition_info_sums_(
192 const FLAC__uint32 abs_residual[],
193 FLAC__uint64 abs_residual_partition_sums[],
194 unsigned residual_samples,
195 unsigned predictor_order,
196 unsigned min_partition_order,
197 unsigned max_partition_order
198);
199
200static void precompute_partition_info_escapes_(
201 const FLAC__int32 residual[],
202 unsigned raw_bits_per_partition[],
203 unsigned residual_samples,
204 unsigned predictor_order,
205 unsigned min_partition_order,
206 unsigned max_partition_order
207);
208
Josh Coalson8395d022001-07-12 21:25:22 +0000209#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +0000210static FLAC__bool set_partitioned_rice_(
211 const FLAC__uint32 abs_residual[],
212 const FLAC__int32 residual[],
213 const unsigned residual_samples,
214 const unsigned predictor_order,
215 const unsigned suggested_rice_parameter,
216 const unsigned rice_parameter_search_dist,
217 const unsigned partition_order,
218 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
219 unsigned *bits
220);
221
222static FLAC__bool set_partitioned_rice_with_precompute_(
223 const FLAC__int32 residual[],
224 const FLAC__uint64 abs_residual_partition_sums[],
225 const unsigned raw_bits_per_partition[],
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 const FLAC__bool search_for_escapes,
232 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
233 unsigned *bits
234);
Josh Coalson8395d022001-07-12 21:25:22 +0000235#else
Josh Coalson6fe72f72002-08-20 04:01:59 +0000236static FLAC__bool set_partitioned_rice_(
237 const FLAC__uint32 abs_residual[],
238 const unsigned residual_samples,
239 const unsigned predictor_order,
240 const unsigned suggested_rice_parameter,
241 const unsigned rice_parameter_search_dist,
242 const unsigned partition_order,
243 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
244 unsigned *bits
245);
246
247static FLAC__bool set_partitioned_rice_with_precompute_(
248 const FLAC__uint32 abs_residual[],
249 const FLAC__uint64 abs_residual_partition_sums[],
250 const unsigned raw_bits_per_partition[],
251 const unsigned residual_samples,
252 const unsigned predictor_order,
253 const unsigned suggested_rice_parameter,
254 const unsigned rice_parameter_search_dist,
255 const unsigned partition_order,
256 const FLAC__bool search_for_escapes,
257 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
258 unsigned *bits
259);
Josh Coalson0a15c142001-06-13 17:59:57 +0000260#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000261
Josh Coalsonf1eff452002-07-31 07:05:33 +0000262static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples);
Josh Coalson6fe72f72002-08-20 04:01:59 +0000263
Josh Coalsond86e03b2002-08-03 21:56:15 +0000264/* verify-related routines: */
Josh Coalson6fe72f72002-08-20 04:01:59 +0000265static void append_to_verify_fifo_(
266 verify_input_fifo *fifo,
267 const FLAC__int32 * const input[],
268 unsigned input_offset,
269 unsigned channels,
270 unsigned wide_samples
271);
272
273static void append_to_verify_fifo_interleaved_(
274 verify_input_fifo *fifo,
275 const FLAC__int32 input[],
276 unsigned input_offset,
277 unsigned channels,
278 unsigned wide_samples
279);
280
281static FLAC__StreamDecoderReadStatus verify_read_callback_(
282 const FLAC__StreamDecoder *decoder,
283 FLAC__byte buffer[],
284 unsigned *bytes,
285 void *client_data
286);
287
288static FLAC__StreamDecoderWriteStatus verify_write_callback_(
289 const FLAC__StreamDecoder *decoder,
290 const FLAC__Frame *frame,
291 const FLAC__int32 * const buffer[],
292 void *client_data
293);
294
295static void verify_metadata_callback_(
296 const FLAC__StreamDecoder *decoder,
297 const FLAC__StreamMetadata *metadata,
298 void *client_data
299);
300
301static void verify_error_callback_(
302 const FLAC__StreamDecoder *decoder,
303 FLAC__StreamDecoderErrorStatus status,
304 void *client_data
305);
306
Josh Coalson0a15c142001-06-13 17:59:57 +0000307
308/***********************************************************************
309 *
310 * Private class data
311 *
312 ***********************************************************************/
313
314typedef struct FLAC__StreamEncoderPrivate {
Josh Coalson8395d022001-07-12 21:25:22 +0000315 unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */
Josh Coalson77e3f312001-06-23 03:03:24 +0000316 FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */
317 FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */
318 FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* the floating-point version of the input signal */
319 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 +0000320 unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */
321 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 +0000322 FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
323 FLAC__int32 *residual_workspace_mid_side[2][2];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000324 FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
325 FLAC__Subframe subframe_workspace_mid_side[2][2];
326 FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
327 FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
Josh Coalsona37ba462002-08-19 21:36:39 +0000328 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2];
329 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2];
330 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2];
331 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2];
Josh Coalson8395d022001-07-12 21:25:22 +0000332 unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index into the above workspaces */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000333 unsigned best_subframe_mid_side[2];
Josh Coalson8395d022001-07-12 21:25:22 +0000334 unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000335 unsigned best_subframe_bits_mid_side[2];
Josh Coalson77e3f312001-06-23 03:03:24 +0000336 FLAC__uint32 *abs_residual; /* workspace where abs(candidate residual) is stored */
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000337 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 +0000338 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 +0000339 FLAC__BitBuffer *frame; /* the current frame being worked on */
Josh Coalson8395d022001-07-12 21:25:22 +0000340 double loose_mid_side_stereo_frames_exact; /* exact number of frames the encoder will use before trying both independent and mid/side frames again */
341 unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
342 unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000343 FLAC__ChannelAssignment last_channel_assignment;
Josh Coalsoncc682512002-06-08 04:53:42 +0000344 FLAC__StreamMetadata metadata;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000345 unsigned current_sample_number;
346 unsigned current_frame_number;
Josh Coalson3e7a96e2004-07-23 05:18:22 +0000347 struct FLAC__MD5Context md5context;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000348 FLAC__CPUInfo cpuinfo;
Josh Coalson77e3f312001-06-23 03:03:24 +0000349 unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
350 void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
351 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 +0000352 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 +0000353 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 +0000354 FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */
355 FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */
356 FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */
357 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 +0000358 FLAC__bool disable_constant_subframes;
359 FLAC__bool disable_fixed_subframes;
360 FLAC__bool disable_verbatim_subframes;
Josh Coalson681c2932002-08-01 08:19:37 +0000361 FLAC__StreamEncoderWriteCallback write_callback;
362 FLAC__StreamEncoderMetadataCallback metadata_callback;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000363 void *client_data;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000364 /* unaligned (original) pointers to allocated data */
Josh Coalson77e3f312001-06-23 03:03:24 +0000365 FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
366 FLAC__int32 *integer_signal_mid_side_unaligned[2];
367 FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
368 FLAC__real *real_signal_mid_side_unaligned[2];
369 FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
370 FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
371 FLAC__uint32 *abs_residual_unaligned;
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000372 FLAC__uint64 *abs_residual_partition_sums_unaligned;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000373 unsigned *raw_bits_per_partition_unaligned;
Josh Coalson8084b052001-11-01 00:27:29 +0000374 /*
375 * These fields have been moved here from private function local
376 * declarations merely to save stack space during encoding.
377 */
Josh Coalsonf1eff452002-07-31 07:05:33 +0000378 FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
Josh Coalsona37ba462002-08-19 21:36:39 +0000379 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000380 /*
381 * The data for the verify section
382 */
383 struct {
384 FLAC__StreamDecoder *decoder;
385 EncoderStateHint state_hint;
386 FLAC__bool needs_magic_hack;
387 verify_input_fifo input_fifo;
388 verify_output output;
389 struct {
390 FLAC__uint64 absolute_sample;
391 unsigned frame_number;
392 unsigned channel;
393 unsigned sample;
394 FLAC__int32 expected;
395 FLAC__int32 got;
396 } error_stats;
397 } verify;
Josh Coalson3262b0d2002-08-14 20:58:42 +0000398 FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
Josh Coalson0a15c142001-06-13 17:59:57 +0000399} FLAC__StreamEncoderPrivate;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000400
Josh Coalson0a15c142001-06-13 17:59:57 +0000401/***********************************************************************
402 *
403 * Public static class data
404 *
405 ***********************************************************************/
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000406
Josh Coalson6afed9f2002-10-16 22:29:47 +0000407FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
Josh Coalson0a15c142001-06-13 17:59:57 +0000408 "FLAC__STREAM_ENCODER_OK",
Josh Coalsond86e03b2002-08-03 21:56:15 +0000409 "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
410 "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
Josh Coalson00e53872001-06-16 07:32:25 +0000411 "FLAC__STREAM_ENCODER_INVALID_CALLBACK",
Josh Coalson0a15c142001-06-13 17:59:57 +0000412 "FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS",
413 "FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE",
414 "FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE",
415 "FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE",
Josh Coalson20ac2c12002-08-30 05:47:14 +0000416 "FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER",
Josh Coalson0a15c142001-06-13 17:59:57 +0000417 "FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION",
418 "FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH",
419 "FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
420 "FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE",
421 "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
422 "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
423 "FLAC__STREAM_ENCODER_FRAMING_ERROR",
Josh Coalson66075c12002-06-01 05:39:38 +0000424 "FLAC__STREAM_ENCODER_INVALID_METADATA",
Josh Coalson0a15c142001-06-13 17:59:57 +0000425 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
426 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
427 "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
428 "FLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
429 "FLAC__STREAM_ENCODER_UNINITIALIZED"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000430};
431
Josh Coalson6afed9f2002-10-16 22:29:47 +0000432FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
Josh Coalson5c491a12002-08-01 06:39:40 +0000433 "FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
434 "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000435};
436
Josh Coalson0a15c142001-06-13 17:59:57 +0000437/***********************************************************************
438 *
439 * Class constructor/destructor
440 *
Josh Coalsond86e03b2002-08-03 21:56:15 +0000441 */
Josh Coalson6afed9f2002-10-16 22:29:47 +0000442FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000443{
Josh Coalson0a15c142001-06-13 17:59:57 +0000444 FLAC__StreamEncoder *encoder;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000445 unsigned i;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000446
Josh Coalson0a15c142001-06-13 17:59:57 +0000447 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000448
Josh Coalsonea7155f2002-10-18 05:49:19 +0000449 encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder));
Josh Coalson0a15c142001-06-13 17:59:57 +0000450 if(encoder == 0) {
451 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000452 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000453
Josh Coalsonea7155f2002-10-18 05:49:19 +0000454 encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected));
Josh Coalsonfa697a92001-08-16 20:07:29 +0000455 if(encoder->protected_ == 0) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000456 free(encoder);
457 return 0;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000458 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000459
Josh Coalsonea7155f2002-10-18 05:49:19 +0000460 encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
Josh Coalsonfa697a92001-08-16 20:07:29 +0000461 if(encoder->private_ == 0) {
462 free(encoder->protected_);
Josh Coalson0a15c142001-06-13 17:59:57 +0000463 free(encoder);
464 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000465 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000466
Josh Coalsonaec256b2002-03-12 16:19:54 +0000467 encoder->private_->frame = FLAC__bitbuffer_new();
468 if(encoder->private_->frame == 0) {
469 free(encoder->private_);
470 free(encoder->protected_);
471 free(encoder);
472 return 0;
473 }
Josh Coalsond98c43d2001-05-13 05:17:01 +0000474
Josh Coalsonf1eff452002-07-31 07:05:33 +0000475 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000476
Josh Coalson3262b0d2002-08-14 20:58:42 +0000477 encoder->private_->is_being_deleted = false;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000478
479 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
480 encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
481 encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
482 }
483 for(i = 0; i < 2; i++) {
484 encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
485 encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
486 }
487 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000488 encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
489 encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000490 }
491 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000492 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
493 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 +0000494 }
495
496 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000497 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
498 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000499 }
500 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000501 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
502 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 +0000503 }
504 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000505 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000506
Josh Coalsonfa697a92001-08-16 20:07:29 +0000507 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000508
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000509 return encoder;
510}
511
Josh Coalson6afed9f2002-10-16 22:29:47 +0000512FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000513{
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000514 unsigned i;
515
Josh Coalsonf1eff452002-07-31 07:05:33 +0000516 FLAC__ASSERT(0 != encoder);
517 FLAC__ASSERT(0 != encoder->protected_);
518 FLAC__ASSERT(0 != encoder->private_);
519 FLAC__ASSERT(0 != encoder->private_->frame);
Josh Coalson0a15c142001-06-13 17:59:57 +0000520
Josh Coalson3262b0d2002-08-14 20:58:42 +0000521 encoder->private_->is_being_deleted = true;
522
523 FLAC__stream_encoder_finish(encoder);
524
Josh Coalson4fa90592002-12-04 07:01:37 +0000525 if(0 != encoder->private_->verify.decoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +0000526 FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000527
528 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000529 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
530 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000531 }
532 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000533 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
534 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 +0000535 }
536 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000537 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000538
Josh Coalsonaec256b2002-03-12 16:19:54 +0000539 FLAC__bitbuffer_delete(encoder->private_->frame);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000540 free(encoder->private_);
541 free(encoder->protected_);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000542 free(encoder);
543}
544
Josh Coalson0a15c142001-06-13 17:59:57 +0000545/***********************************************************************
546 *
547 * Public class methods
548 *
549 ***********************************************************************/
550
Josh Coalson6afed9f2002-10-16 22:29:47 +0000551FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000552{
553 unsigned i;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000554 FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000555
Josh Coalsonf1eff452002-07-31 07:05:33 +0000556 FLAC__ASSERT(0 != encoder);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000557
Josh Coalsonfa697a92001-08-16 20:07:29 +0000558 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
559 return encoder->protected_->state = FLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000560
Josh Coalsonfa697a92001-08-16 20:07:29 +0000561 encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000562
Josh Coalsonfa697a92001-08-16 20:07:29 +0000563 if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
564 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_CALLBACK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000565
Josh Coalsonfa697a92001-08-16 20:07:29 +0000566 if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
567 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson69f1ee02001-01-24 00:54:43 +0000568
Josh Coalsonfa697a92001-08-16 20:07:29 +0000569 if(encoder->protected_->do_mid_side_stereo && encoder->protected_->channels != 2)
570 return encoder->protected_->state = FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH;
Josh Coalsond37d1352001-05-30 23:09:31 +0000571
Josh Coalsonfa697a92001-08-16 20:07:29 +0000572 if(encoder->protected_->loose_mid_side_stereo && !encoder->protected_->do_mid_side_stereo)
573 return encoder->protected_->state = FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000574
Josh Coalsonfa697a92001-08-16 20:07:29 +0000575 if(encoder->protected_->bits_per_sample >= 32)
576 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 +0000577
Josh Coalson76c68bc2002-05-17 06:22:02 +0000578 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 +0000579 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000580
Josh Coalson0833f342002-07-15 05:31:55 +0000581 if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000582 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000583
Josh Coalsonfa697a92001-08-16 20:07:29 +0000584 if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
585 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE;
Josh Coalson0a15c142001-06-13 17:59:57 +0000586
Josh Coalson20ac2c12002-08-30 05:47:14 +0000587 if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
588 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER;
589
Josh Coalsonfa697a92001-08-16 20:07:29 +0000590 if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
591 return encoder->protected_->state = FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
Josh Coalson0a15c142001-06-13 17:59:57 +0000592
Josh Coalsonfa697a92001-08-16 20:07:29 +0000593 if(encoder->protected_->qlp_coeff_precision == 0) {
594 if(encoder->protected_->bits_per_sample < 16) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000595 /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
596 /* @@@ until then we'll make a guess */
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000597 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 +0000598 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000599 else if(encoder->protected_->bits_per_sample == 16) {
600 if(encoder->protected_->blocksize <= 192)
601 encoder->protected_->qlp_coeff_precision = 7;
602 else if(encoder->protected_->blocksize <= 384)
603 encoder->protected_->qlp_coeff_precision = 8;
604 else if(encoder->protected_->blocksize <= 576)
605 encoder->protected_->qlp_coeff_precision = 9;
606 else if(encoder->protected_->blocksize <= 1152)
607 encoder->protected_->qlp_coeff_precision = 10;
608 else if(encoder->protected_->blocksize <= 2304)
609 encoder->protected_->qlp_coeff_precision = 11;
610 else if(encoder->protected_->blocksize <= 4608)
611 encoder->protected_->qlp_coeff_precision = 12;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000612 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000613 encoder->protected_->qlp_coeff_precision = 13;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000614 }
615 else {
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000616 if(encoder->protected_->blocksize <= 384)
617 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-2;
618 else if(encoder->protected_->blocksize <= 1152)
619 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-1;
620 else
621 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000622 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000623 FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000624 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000625 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 +0000626 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000627
Josh Coalsonfa697a92001-08-16 20:07:29 +0000628 if(encoder->protected_->streamable_subset) {
Josh Coalson20ac2c12002-08-30 05:47:14 +0000629 if(
630 encoder->protected_->blocksize != 192 &&
631 encoder->protected_->blocksize != 576 &&
632 encoder->protected_->blocksize != 1152 &&
633 encoder->protected_->blocksize != 2304 &&
634 encoder->protected_->blocksize != 4608 &&
635 encoder->protected_->blocksize != 256 &&
636 encoder->protected_->blocksize != 512 &&
637 encoder->protected_->blocksize != 1024 &&
638 encoder->protected_->blocksize != 2048 &&
639 encoder->protected_->blocksize != 4096 &&
640 encoder->protected_->blocksize != 8192 &&
641 encoder->protected_->blocksize != 16384
642 )
Josh Coalsonfa697a92001-08-16 20:07:29 +0000643 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalson20ac2c12002-08-30 05:47:14 +0000644 if(
645 encoder->protected_->sample_rate != 8000 &&
646 encoder->protected_->sample_rate != 16000 &&
647 encoder->protected_->sample_rate != 22050 &&
648 encoder->protected_->sample_rate != 24000 &&
649 encoder->protected_->sample_rate != 32000 &&
650 encoder->protected_->sample_rate != 44100 &&
651 encoder->protected_->sample_rate != 48000 &&
652 encoder->protected_->sample_rate != 96000
653 )
654 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
655 if(
656 encoder->protected_->bits_per_sample != 8 &&
657 encoder->protected_->bits_per_sample != 12 &&
658 encoder->protected_->bits_per_sample != 16 &&
659 encoder->protected_->bits_per_sample != 20 &&
660 encoder->protected_->bits_per_sample != 24
661 )
662 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonc1c8d492002-09-26 04:42:10 +0000663 if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000664 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000665 }
666
Josh Coalsonfa697a92001-08-16 20:07:29 +0000667 if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
668 encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
669 if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
670 encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000671
Josh Coalson66075c12002-06-01 05:39:38 +0000672 /* validate metadata */
673 if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
674 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000675 metadata_has_seektable = false;
676 metadata_has_vorbis_comment = false;
Josh Coalson66075c12002-06-01 05:39:38 +0000677 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
Josh Coalsond0609472003-01-10 05:37:13 +0000678 if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
Josh Coalson66075c12002-06-01 05:39:38 +0000679 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
680 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000681 if(metadata_has_seektable) /* only one is allowed */
682 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
683 metadata_has_seektable = true;
Josh Coalson0833f342002-07-15 05:31:55 +0000684 if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table))
Josh Coalson66075c12002-06-01 05:39:38 +0000685 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
686 }
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000687 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
688 if(metadata_has_vorbis_comment) /* only one is allowed */
689 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
690 metadata_has_vorbis_comment = true;
691 }
Josh Coalsone4869382002-11-15 05:41:48 +0000692 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_CUESHEET) {
Josh Coalson8f0c71b2002-12-05 06:37:46 +0000693 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 +0000694 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
695 }
Josh Coalson66075c12002-06-01 05:39:38 +0000696 }
697
Josh Coalsonfa697a92001-08-16 20:07:29 +0000698 encoder->private_->input_capacity = 0;
699 for(i = 0; i < encoder->protected_->channels; i++) {
700 encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
701 encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000702 }
703 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000704 encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
705 encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000706 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000707 for(i = 0; i < encoder->protected_->channels; i++) {
708 encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
709 encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
710 encoder->private_->best_subframe[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000711 }
712 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000713 encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
714 encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
715 encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000716 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000717 encoder->private_->abs_residual_unaligned = encoder->private_->abs_residual = 0;
718 encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
719 encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
720 encoder->private_->loose_mid_side_stereo_frames_exact = (double)encoder->protected_->sample_rate * 0.4 / (double)encoder->protected_->blocksize;
721 encoder->private_->loose_mid_side_stereo_frames = (unsigned)(encoder->private_->loose_mid_side_stereo_frames_exact + 0.5);
722 if(encoder->private_->loose_mid_side_stereo_frames == 0)
723 encoder->private_->loose_mid_side_stereo_frames = 1;
724 encoder->private_->loose_mid_side_stereo_frame_count = 0;
725 encoder->private_->current_sample_number = 0;
726 encoder->private_->current_frame_number = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000727
Josh Coalsonfa697a92001-08-16 20:07:29 +0000728 encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
729 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? */
730 encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
Josh Coalson8395d022001-07-12 21:25:22 +0000731
Josh Coalsoncf30f502001-05-23 20:57:44 +0000732 /*
733 * get the CPU info and set the function pointers
734 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000735 FLAC__cpu_info(&encoder->private_->cpuinfo);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000736 /* first default to the non-asm routines */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000737 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
738 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
739 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000740 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 +0000741 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000742 /* now override with asm where appropriate */
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000743#ifndef FLAC__NO_ASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000744 if(encoder->private_->cpuinfo.use_asm) {
Josh Coalsoncf30f502001-05-23 20:57:44 +0000745#ifdef FLAC__CPU_IA32
Josh Coalsonfa697a92001-08-16 20:07:29 +0000746 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
Josh Coalson034d38e2001-05-24 19:29:30 +0000747#ifdef FLAC__HAS_NASM
Josh Coalson48cbe662002-12-30 23:38:14 +0000748#ifdef FLAC__SSE_OS
749 if(encoder->private_->cpuinfo.data.ia32.sse) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000750 if(encoder->protected_->max_lpc_order < 4)
751 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
752 else if(encoder->protected_->max_lpc_order < 8)
753 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
754 else if(encoder->protected_->max_lpc_order < 12)
755 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000756 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000757 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000758 }
Josh Coalson48cbe662002-12-30 23:38:14 +0000759 else
760#endif
761 if(encoder->private_->cpuinfo.data.ia32._3dnow)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000762 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
Josh Coalsonaa255362001-05-31 06:17:41 +0000763 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000764 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
765 if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
766 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
767 if(encoder->private_->cpuinfo.data.ia32.mmx) {
768 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
769 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 +0000770 }
771 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000772 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
773 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 +0000774 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000775#endif
Josh Coalson034d38e2001-05-24 19:29:30 +0000776#endif
Josh Coalson021ad3b2001-07-18 00:25:52 +0000777 }
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000778#endif
Josh Coalson8395d022001-07-12 21:25:22 +0000779 /* finally override based on wide-ness if necessary */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000780 if(encoder->private_->use_wide_by_block) {
781 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
Josh Coalson8395d022001-07-12 21:25:22 +0000782 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000783
Josh Coalson8395d022001-07-12 21:25:22 +0000784 /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000785 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 +0000786
Josh Coalsonf1eff452002-07-31 07:05:33 +0000787 if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000788 /* the above function sets the state for us in case of an error */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000789 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000790 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000791
792 if(!FLAC__bitbuffer_init(encoder->private_->frame))
793 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000794
795 /*
Josh Coalsond86e03b2002-08-03 21:56:15 +0000796 * Set up the verify stuff if necessary
797 */
798 if(encoder->protected_->verify) {
799 /*
800 * First, set up the fifo which will hold the
801 * original signal to compare against
802 */
803 encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize;
804 for(i = 0; i < encoder->protected_->channels; i++) {
805 if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size)))
806 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
807 }
808 encoder->private_->verify.input_fifo.tail = 0;
809
810 /*
811 * Now set up a stream decoder for verification
812 */
813 encoder->private_->verify.decoder = FLAC__stream_decoder_new();
814 if(0 == encoder->private_->verify.decoder)
815 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
816
817 FLAC__stream_decoder_set_read_callback(encoder->private_->verify.decoder, verify_read_callback_);
818 FLAC__stream_decoder_set_write_callback(encoder->private_->verify.decoder, verify_write_callback_);
819 FLAC__stream_decoder_set_metadata_callback(encoder->private_->verify.decoder, verify_metadata_callback_);
820 FLAC__stream_decoder_set_error_callback(encoder->private_->verify.decoder, verify_error_callback_);
821 FLAC__stream_decoder_set_client_data(encoder->private_->verify.decoder, encoder);
822 if(FLAC__stream_decoder_init(encoder->private_->verify.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
823 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
824 }
Josh Coalson589f8c72002-08-07 23:54:55 +0000825 encoder->private_->verify.error_stats.absolute_sample = 0;
826 encoder->private_->verify.error_stats.frame_number = 0;
827 encoder->private_->verify.error_stats.channel = 0;
828 encoder->private_->verify.error_stats.sample = 0;
829 encoder->private_->verify.error_stats.expected = 0;
830 encoder->private_->verify.error_stats.got = 0;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000831
832 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000833 * write the stream header
834 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000835 if(encoder->protected_->verify)
836 encoder->private_->verify.state_hint = ENCODER_IN_MAGIC;
Josh Coalsonaec256b2002-03-12 16:19:54 +0000837 if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000838 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000839 if(!write_bitbuffer_(encoder, 0)) {
840 /* the above function sets the state for us in case of an error */
841 return encoder->protected_->state;
842 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000843
Josh Coalson5c491a12002-08-01 06:39:40 +0000844 /*
845 * write the STREAMINFO metadata block
846 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000847 if(encoder->protected_->verify)
848 encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000849 encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000850 encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000851 encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
852 encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
853 encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
854 encoder->private_->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
855 encoder->private_->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
856 encoder->private_->metadata.data.stream_info.sample_rate = encoder->protected_->sample_rate;
857 encoder->private_->metadata.data.stream_info.channels = encoder->protected_->channels;
858 encoder->private_->metadata.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
859 encoder->private_->metadata.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
860 memset(encoder->private_->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
Josh Coalson3e7a96e2004-07-23 05:18:22 +0000861 FLAC__MD5Init(&encoder->private_->md5context);
Josh Coalson7424d2f2002-11-06 07:10:38 +0000862 if(!FLAC__bitbuffer_clear(encoder->private_->frame))
863 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonaec256b2002-03-12 16:19:54 +0000864 if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000865 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000866 if(!write_bitbuffer_(encoder, 0)) {
867 /* the above function sets the state for us in case of an error */
868 return encoder->protected_->state;
869 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000870
Josh Coalson5c491a12002-08-01 06:39:40 +0000871 /*
872 * Now that the STREAMINFO block is written, we can init this to an
873 * absurdly-high value...
874 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000875 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 +0000876 /* ... and clear this to 0 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000877 encoder->private_->metadata.data.stream_info.total_samples = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000878
Josh Coalson5c491a12002-08-01 06:39:40 +0000879 /*
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000880 * Check to see if the supplied metadata contains a VORBIS_COMMENT;
881 * if not, we will write an empty one (FLAC__add_metadata_block()
882 * automatically supplies the vendor string).
Josh Coalson69cfda72004-09-10 00:38:21 +0000883 *
884 * WATCHOUT: libOggFLAC depends on us to write this block after the
885 * STREAMINFO since that's what the mapping requires. (In the case
886 * that metadata_has_vorbis_comment it true it will have already
887 * insured that the metadata list is properly ordered.)
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000888 */
889 if(!metadata_has_vorbis_comment) {
890 FLAC__StreamMetadata vorbis_comment;
891 vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
892 vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0);
893 vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */
894 vorbis_comment.data.vorbis_comment.vendor_string.length = 0;
895 vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
896 vorbis_comment.data.vorbis_comment.num_comments = 0;
897 vorbis_comment.data.vorbis_comment.comments = 0;
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 Coalsoncb9d93a2002-08-25 05:27:15 +0000900 if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame))
901 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
902 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 }
906 }
907
908 /*
Josh Coalson5c491a12002-08-01 06:39:40 +0000909 * write the user's metadata blocks
910 */
911 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
912 encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
Josh Coalson7424d2f2002-11-06 07:10:38 +0000913 if(!FLAC__bitbuffer_clear(encoder->private_->frame))
914 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson5c491a12002-08-01 06:39:40 +0000915 if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame))
916 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000917 if(!write_bitbuffer_(encoder, 0)) {
918 /* the above function sets the state for us in case of an error */
919 return encoder->protected_->state;
920 }
Josh Coalson5c491a12002-08-01 06:39:40 +0000921 }
922
Josh Coalsond86e03b2002-08-03 21:56:15 +0000923 if(encoder->protected_->verify)
924 encoder->private_->verify.state_hint = ENCODER_IN_AUDIO;
925
Josh Coalsonfa697a92001-08-16 20:07:29 +0000926 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000927}
928
Josh Coalson6afed9f2002-10-16 22:29:47 +0000929FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000930{
Josh Coalsonf1eff452002-07-31 07:05:33 +0000931 FLAC__ASSERT(0 != encoder);
Josh Coalson2b245f22002-08-07 17:10:50 +0000932
Josh Coalsonfa697a92001-08-16 20:07:29 +0000933 if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000934 return;
Josh Coalson2b245f22002-08-07 17:10:50 +0000935
Josh Coalson3262b0d2002-08-14 20:58:42 +0000936 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000937 if(encoder->private_->current_sample_number != 0) {
938 encoder->protected_->blocksize = encoder->private_->current_sample_number;
939 process_frame_(encoder, true); /* true => is last frame */
940 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000941 }
Josh Coalson2b245f22002-08-07 17:10:50 +0000942
Josh Coalson3e7a96e2004-07-23 05:18:22 +0000943 FLAC__MD5Final(encoder->private_->metadata.data.stream_info.md5sum, &encoder->private_->md5context);
Josh Coalson2b245f22002-08-07 17:10:50 +0000944
Josh Coalson3262b0d2002-08-14 20:58:42 +0000945 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000946 encoder->private_->metadata_callback(encoder, &encoder->private_->metadata, encoder->private_->client_data);
947 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000948
Josh Coalsond86e03b2002-08-03 21:56:15 +0000949 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
950 FLAC__stream_decoder_finish(encoder->private_->verify.decoder);
951
Josh Coalsonf1eff452002-07-31 07:05:33 +0000952 free_(encoder);
953 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000954
Josh Coalsonfa697a92001-08-16 20:07:29 +0000955 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000956}
957
Josh Coalson6afed9f2002-10-16 22:29:47 +0000958FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsond86e03b2002-08-03 21:56:15 +0000959{
960 FLAC__ASSERT(0 != encoder);
961 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
962 return false;
963 encoder->protected_->verify = value;
964 return true;
965}
966
Josh Coalson6afed9f2002-10-16 22:29:47 +0000967FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000968{
Josh Coalson92031602002-07-24 06:02:11 +0000969 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000970 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000971 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000972 encoder->protected_->streamable_subset = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000973 return true;
974}
975
Josh Coalson6afed9f2002-10-16 22:29:47 +0000976FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000977{
Josh Coalson92031602002-07-24 06:02:11 +0000978 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000979 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000980 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000981 encoder->protected_->do_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000982 return true;
983}
984
Josh Coalson6afed9f2002-10-16 22:29:47 +0000985FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000986{
Josh Coalson92031602002-07-24 06:02:11 +0000987 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000988 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000989 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000990 encoder->protected_->loose_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000991 return true;
992}
993
Josh Coalson6afed9f2002-10-16 22:29:47 +0000994FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000995{
Josh Coalson92031602002-07-24 06:02:11 +0000996 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000997 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000998 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000999 encoder->protected_->channels = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001000 return true;
1001}
1002
Josh Coalson6afed9f2002-10-16 22:29:47 +00001003FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001004{
Josh Coalson92031602002-07-24 06:02:11 +00001005 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001006 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001007 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001008 encoder->protected_->bits_per_sample = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001009 return true;
1010}
1011
Josh Coalson6afed9f2002-10-16 22:29:47 +00001012FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001013{
Josh Coalson92031602002-07-24 06:02:11 +00001014 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001015 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001016 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001017 encoder->protected_->sample_rate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001018 return true;
1019}
1020
Josh Coalson6afed9f2002-10-16 22:29:47 +00001021FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001022{
Josh Coalson92031602002-07-24 06:02:11 +00001023 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001024 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001025 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001026 encoder->protected_->blocksize = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001027 return true;
1028}
1029
Josh Coalson6afed9f2002-10-16 22:29:47 +00001030FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001031{
Josh Coalson92031602002-07-24 06:02:11 +00001032 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001033 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001034 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001035 encoder->protected_->max_lpc_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001036 return true;
1037}
1038
Josh Coalson6afed9f2002-10-16 22:29:47 +00001039FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001040{
Josh Coalson92031602002-07-24 06:02:11 +00001041 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001042 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001043 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001044 encoder->protected_->qlp_coeff_precision = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001045 return true;
1046}
1047
Josh Coalson6afed9f2002-10-16 22:29:47 +00001048FLAC_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 +00001049{
Josh Coalson92031602002-07-24 06:02:11 +00001050 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001051 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001052 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001053 encoder->protected_->do_qlp_coeff_prec_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001054 return true;
1055}
1056
Josh Coalson6afed9f2002-10-16 22:29:47 +00001057FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson8395d022001-07-12 21:25:22 +00001058{
Josh Coalson92031602002-07-24 06:02:11 +00001059 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001060 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson8395d022001-07-12 21:25:22 +00001061 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001062#if 0
1063 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001064 encoder->protected_->do_escape_coding = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001065#else
1066 (void)value;
1067#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001068 return true;
1069}
1070
Josh Coalson6afed9f2002-10-16 22:29:47 +00001071FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001072{
Josh Coalson92031602002-07-24 06:02:11 +00001073 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001074 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001075 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001076 encoder->protected_->do_exhaustive_model_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001077 return true;
1078}
1079
Josh Coalson6afed9f2002-10-16 22:29:47 +00001080FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001081{
Josh Coalson92031602002-07-24 06:02:11 +00001082 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001083 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001084 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001085 encoder->protected_->min_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001086 return true;
1087}
1088
Josh Coalson6afed9f2002-10-16 22:29:47 +00001089FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001090{
Josh Coalson92031602002-07-24 06:02:11 +00001091 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001092 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001093 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001094 encoder->protected_->max_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001095 return true;
1096}
1097
Josh Coalson6afed9f2002-10-16 22:29:47 +00001098FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001099{
Josh Coalson92031602002-07-24 06:02:11 +00001100 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001101 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001102 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001103#if 0
1104 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001105 encoder->protected_->rice_parameter_search_dist = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001106#else
1107 (void)value;
1108#endif
Josh Coalson00e53872001-06-16 07:32:25 +00001109 return true;
1110}
1111
Josh Coalson6afed9f2002-10-16 22:29:47 +00001112FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)
Josh Coalson00e53872001-06-16 07:32:25 +00001113{
Josh Coalson92031602002-07-24 06:02:11 +00001114 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001115 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001116 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001117 encoder->protected_->total_samples_estimate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001118 return true;
1119}
1120
Josh Coalson6afed9f2002-10-16 22:29:47 +00001121FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
Josh Coalson00e53872001-06-16 07:32:25 +00001122{
Josh Coalson92031602002-07-24 06:02:11 +00001123 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001124 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001125 return false;
Josh Coalson66075c12002-06-01 05:39:38 +00001126 encoder->protected_->metadata = metadata;
1127 encoder->protected_->num_metadata_blocks = num_blocks;
Josh Coalson00e53872001-06-16 07:32:25 +00001128 return true;
1129}
1130
Josh Coalson6afed9f2002-10-16 22:29:47 +00001131FLAC_API FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001132{
Josh Coalson92031602002-07-24 06:02:11 +00001133 FLAC__ASSERT(0 != encoder);
1134 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001135 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001136 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001137 encoder->private_->write_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001138 return true;
1139}
1140
Josh Coalson6afed9f2002-10-16 22:29:47 +00001141FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderMetadataCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001142{
Josh Coalson92031602002-07-24 06:02:11 +00001143 FLAC__ASSERT(0 != encoder);
1144 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001145 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001146 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001147 encoder->private_->metadata_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001148 return true;
1149}
1150
Josh Coalson6afed9f2002-10-16 22:29:47 +00001151FLAC_API FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value)
Josh Coalson00e53872001-06-16 07:32:25 +00001152{
Josh Coalson92031602002-07-24 06:02:11 +00001153 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001154 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001155 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001156 encoder->private_->client_data = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001157 return true;
1158}
1159
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001160/*
1161 * These three functions are not static, but not publically exposed in
1162 * include/FLAC/ either. They are used by the test suite.
1163 */
Josh Coalson6afed9f2002-10-16 22:29:47 +00001164FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001165{
1166 FLAC__ASSERT(0 != encoder);
1167 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1168 return false;
1169 encoder->private_->disable_constant_subframes = value;
1170 return true;
1171}
1172
Josh Coalson6afed9f2002-10-16 22:29:47 +00001173FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001174{
1175 FLAC__ASSERT(0 != encoder);
1176 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1177 return false;
1178 encoder->private_->disable_fixed_subframes = value;
1179 return true;
1180}
1181
Josh Coalson6afed9f2002-10-16 22:29:47 +00001182FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001183{
1184 FLAC__ASSERT(0 != encoder);
1185 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1186 return false;
1187 encoder->private_->disable_verbatim_subframes = value;
1188 return true;
1189}
1190
Josh Coalson6afed9f2002-10-16 22:29:47 +00001191FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001192{
Josh Coalson92031602002-07-24 06:02:11 +00001193 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001194 return encoder->protected_->state;
Josh Coalson0a15c142001-06-13 17:59:57 +00001195}
1196
Josh Coalson6afed9f2002-10-16 22:29:47 +00001197FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001198{
1199 FLAC__ASSERT(0 != encoder);
1200 if(encoder->protected_->verify)
1201 return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder);
1202 else
1203 return FLAC__STREAM_DECODER_UNINITIALIZED;
1204}
1205
Josh Coalson02954222002-11-08 06:16:31 +00001206FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder)
1207{
1208 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR)
1209 return FLAC__StreamEncoderStateString[encoder->protected_->state];
1210 else
Josh Coalson807140d2003-09-24 22:10:51 +00001211 return FLAC__stream_decoder_get_resolved_state_string(encoder->private_->verify.decoder);
Josh Coalson02954222002-11-08 06:16:31 +00001212}
1213
Josh Coalson6afed9f2002-10-16 22:29:47 +00001214FLAC_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 +00001215{
1216 FLAC__ASSERT(0 != encoder);
1217 if(0 != absolute_sample)
1218 *absolute_sample = encoder->private_->verify.error_stats.absolute_sample;
1219 if(0 != frame_number)
1220 *frame_number = encoder->private_->verify.error_stats.frame_number;
1221 if(0 != channel)
1222 *channel = encoder->private_->verify.error_stats.channel;
1223 if(0 != sample)
1224 *sample = encoder->private_->verify.error_stats.sample;
1225 if(0 != expected)
1226 *expected = encoder->private_->verify.error_stats.expected;
1227 if(0 != got)
1228 *got = encoder->private_->verify.error_stats.got;
1229}
1230
Josh Coalson6afed9f2002-10-16 22:29:47 +00001231FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001232{
1233 FLAC__ASSERT(0 != encoder);
1234 return encoder->protected_->verify;
1235}
1236
Josh Coalson6afed9f2002-10-16 22:29:47 +00001237FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001238{
Josh Coalson92031602002-07-24 06:02:11 +00001239 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001240 return encoder->protected_->streamable_subset;
Josh Coalson0a15c142001-06-13 17:59:57 +00001241}
1242
Josh Coalson6afed9f2002-10-16 22:29:47 +00001243FLAC_API FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001244{
Josh Coalson92031602002-07-24 06:02:11 +00001245 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001246 return encoder->protected_->do_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001247}
1248
Josh Coalson6afed9f2002-10-16 22:29:47 +00001249FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001250{
Josh Coalson92031602002-07-24 06:02:11 +00001251 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001252 return encoder->protected_->loose_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001253}
1254
Josh Coalson6afed9f2002-10-16 22:29:47 +00001255FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001256{
Josh Coalson92031602002-07-24 06:02:11 +00001257 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001258 return encoder->protected_->channels;
Josh Coalson0a15c142001-06-13 17:59:57 +00001259}
1260
Josh Coalson6afed9f2002-10-16 22:29:47 +00001261FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001262{
Josh Coalson92031602002-07-24 06:02:11 +00001263 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001264 return encoder->protected_->bits_per_sample;
Josh Coalson0a15c142001-06-13 17:59:57 +00001265}
1266
Josh Coalson6afed9f2002-10-16 22:29:47 +00001267FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001268{
Josh Coalson92031602002-07-24 06:02:11 +00001269 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001270 return encoder->protected_->sample_rate;
Josh Coalson0a15c142001-06-13 17:59:57 +00001271}
1272
Josh Coalson6afed9f2002-10-16 22:29:47 +00001273FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001274{
Josh Coalson92031602002-07-24 06:02:11 +00001275 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001276 return encoder->protected_->blocksize;
Josh Coalson0a15c142001-06-13 17:59:57 +00001277}
1278
Josh Coalson6afed9f2002-10-16 22:29:47 +00001279FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001280{
Josh Coalson92031602002-07-24 06:02:11 +00001281 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001282 return encoder->protected_->max_lpc_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001283}
1284
Josh Coalson6afed9f2002-10-16 22:29:47 +00001285FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001286{
Josh Coalson92031602002-07-24 06:02:11 +00001287 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001288 return encoder->protected_->qlp_coeff_precision;
Josh Coalson0a15c142001-06-13 17:59:57 +00001289}
1290
Josh Coalson6afed9f2002-10-16 22:29:47 +00001291FLAC_API FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001292{
Josh Coalson92031602002-07-24 06:02:11 +00001293 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001294 return encoder->protected_->do_qlp_coeff_prec_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001295}
1296
Josh Coalson6afed9f2002-10-16 22:29:47 +00001297FLAC_API FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder)
Josh Coalson8395d022001-07-12 21:25:22 +00001298{
Josh Coalson92031602002-07-24 06:02:11 +00001299 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001300 return encoder->protected_->do_escape_coding;
Josh Coalson8395d022001-07-12 21:25:22 +00001301}
1302
Josh Coalson6afed9f2002-10-16 22:29:47 +00001303FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001304{
Josh Coalson92031602002-07-24 06:02:11 +00001305 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001306 return encoder->protected_->do_exhaustive_model_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001307}
1308
Josh Coalson6afed9f2002-10-16 22:29:47 +00001309FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001310{
Josh Coalson92031602002-07-24 06:02:11 +00001311 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001312 return encoder->protected_->min_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001313}
1314
Josh Coalson6afed9f2002-10-16 22:29:47 +00001315FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001316{
Josh Coalson92031602002-07-24 06:02:11 +00001317 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001318 return encoder->protected_->max_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001319}
1320
Josh Coalson6afed9f2002-10-16 22:29:47 +00001321FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001322{
Josh Coalson92031602002-07-24 06:02:11 +00001323 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001324 return encoder->protected_->rice_parameter_search_dist;
Josh Coalson0a15c142001-06-13 17:59:57 +00001325}
1326
Josh Coalson6afed9f2002-10-16 22:29:47 +00001327FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder)
Josh Coalson3a7b2c92002-08-02 07:38:20 +00001328{
1329 FLAC__ASSERT(0 != encoder);
1330 return encoder->protected_->total_samples_estimate;
1331}
1332
Josh Coalson6afed9f2002-10-16 22:29:47 +00001333FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001334{
1335 unsigned i, j, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001336 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001337 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001338
Josh Coalsonf1eff452002-07-31 07:05:33 +00001339 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001340 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001341
1342 j = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001343 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001344 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001345 if(encoder->protected_->verify)
1346 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1347
Josh Coalsonfa697a92001-08-16 20:07:29 +00001348 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001349 x = mid = side = buffer[0][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001350 encoder->private_->integer_signal[0][i] = x;
1351 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001352 x = buffer[1][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001353 encoder->private_->integer_signal[1][i] = x;
1354 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001355 mid += x;
1356 side -= x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001357 mid >>= 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001358 encoder->private_->integer_signal_mid_side[1][i] = side;
1359 encoder->private_->integer_signal_mid_side[0][i] = mid;
1360 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1361 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1362 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001363 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001364 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001365 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001366 return false;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001367 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001368 } while(j < samples);
1369 }
1370 else {
1371 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001372 if(encoder->protected_->verify)
1373 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1374
Josh Coalsonfa697a92001-08-16 20:07:29 +00001375 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001376 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001377 x = buffer[channel][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001378 encoder->private_->integer_signal[channel][i] = x;
1379 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001380 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001381 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001382 }
1383 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001384 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001385 return false;
1386 }
1387 } while(j < samples);
1388 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001389
1390 return true;
1391}
1392
Josh Coalson6afed9f2002-10-16 22:29:47 +00001393FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001394{
1395 unsigned i, j, k, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001396 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001397 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001398
Josh Coalsonf1eff452002-07-31 07:05:33 +00001399 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001400 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001401
1402 j = k = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001403 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001404 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001405 if(encoder->protected_->verify)
1406 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1407
Josh Coalsonfa697a92001-08-16 20:07:29 +00001408 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001409 x = mid = side = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001410 encoder->private_->integer_signal[0][i] = x;
1411 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001412 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001413 encoder->private_->integer_signal[1][i] = x;
1414 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001415 mid += x;
1416 side -= x;
1417 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001418 encoder->private_->integer_signal_mid_side[1][i] = side;
1419 encoder->private_->integer_signal_mid_side[0][i] = mid;
1420 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1421 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1422 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001423 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001424 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001425 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001426 return false;
1427 }
1428 } while(j < samples);
1429 }
1430 else {
1431 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001432 if(encoder->protected_->verify)
1433 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1434
Josh Coalsonfa697a92001-08-16 20:07:29 +00001435 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001436 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001437 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001438 encoder->private_->integer_signal[channel][i] = x;
1439 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001440 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001441 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001442 }
1443 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001444 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001445 return false;
1446 }
1447 } while(j < samples);
1448 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001449
1450 return true;
1451}
1452
Josh Coalsonf1eff452002-07-31 07:05:33 +00001453/***********************************************************************
1454 *
1455 * Private class methods
1456 *
1457 ***********************************************************************/
1458
1459void set_defaults_(FLAC__StreamEncoder *encoder)
Josh Coalson92031602002-07-24 06:02:11 +00001460{
1461 FLAC__ASSERT(0 != encoder);
1462
Josh Coalsond86e03b2002-08-03 21:56:15 +00001463 encoder->protected_->verify = false;
Josh Coalson92031602002-07-24 06:02:11 +00001464 encoder->protected_->streamable_subset = true;
1465 encoder->protected_->do_mid_side_stereo = false;
1466 encoder->protected_->loose_mid_side_stereo = false;
1467 encoder->protected_->channels = 2;
1468 encoder->protected_->bits_per_sample = 16;
1469 encoder->protected_->sample_rate = 44100;
1470 encoder->protected_->blocksize = 1152;
1471 encoder->protected_->max_lpc_order = 0;
1472 encoder->protected_->qlp_coeff_precision = 0;
1473 encoder->protected_->do_qlp_coeff_prec_search = false;
1474 encoder->protected_->do_exhaustive_model_search = false;
1475 encoder->protected_->do_escape_coding = false;
1476 encoder->protected_->min_residual_partition_order = 0;
1477 encoder->protected_->max_residual_partition_order = 0;
1478 encoder->protected_->rice_parameter_search_dist = 0;
1479 encoder->protected_->total_samples_estimate = 0;
1480 encoder->protected_->metadata = 0;
1481 encoder->protected_->num_metadata_blocks = 0;
1482
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001483 encoder->private_->disable_constant_subframes = false;
1484 encoder->private_->disable_fixed_subframes = false;
1485 encoder->private_->disable_verbatim_subframes = false;
Josh Coalson92031602002-07-24 06:02:11 +00001486 encoder->private_->write_callback = 0;
1487 encoder->private_->metadata_callback = 0;
1488 encoder->private_->client_data = 0;
1489}
1490
Josh Coalsonf1eff452002-07-31 07:05:33 +00001491void free_(FLAC__StreamEncoder *encoder)
Josh Coalson639aeb02002-07-25 05:38:23 +00001492{
1493 unsigned i, channel;
1494
Josh Coalsonf1eff452002-07-31 07:05:33 +00001495 FLAC__ASSERT(0 != encoder);
Josh Coalson639aeb02002-07-25 05:38:23 +00001496 for(i = 0; i < encoder->protected_->channels; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001497 if(0 != encoder->private_->integer_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001498 free(encoder->private_->integer_signal_unaligned[i]);
1499 encoder->private_->integer_signal_unaligned[i] = 0;
1500 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001501 if(0 != encoder->private_->real_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001502 free(encoder->private_->real_signal_unaligned[i]);
1503 encoder->private_->real_signal_unaligned[i] = 0;
1504 }
1505 }
1506 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001507 if(0 != encoder->private_->integer_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001508 free(encoder->private_->integer_signal_mid_side_unaligned[i]);
1509 encoder->private_->integer_signal_mid_side_unaligned[i] = 0;
1510 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001511 if(0 != encoder->private_->real_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001512 free(encoder->private_->real_signal_mid_side_unaligned[i]);
1513 encoder->private_->real_signal_mid_side_unaligned[i] = 0;
1514 }
1515 }
1516 for(channel = 0; channel < encoder->protected_->channels; channel++) {
1517 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001518 if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001519 free(encoder->private_->residual_workspace_unaligned[channel][i]);
1520 encoder->private_->residual_workspace_unaligned[channel][i] = 0;
1521 }
1522 }
1523 }
1524 for(channel = 0; channel < 2; channel++) {
1525 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001526 if(0 != encoder->private_->residual_workspace_mid_side_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001527 free(encoder->private_->residual_workspace_mid_side_unaligned[channel][i]);
1528 encoder->private_->residual_workspace_mid_side_unaligned[channel][i] = 0;
1529 }
1530 }
1531 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001532 if(0 != encoder->private_->abs_residual_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001533 free(encoder->private_->abs_residual_unaligned);
1534 encoder->private_->abs_residual_unaligned = 0;
1535 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001536 if(0 != encoder->private_->abs_residual_partition_sums_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001537 free(encoder->private_->abs_residual_partition_sums_unaligned);
1538 encoder->private_->abs_residual_partition_sums_unaligned = 0;
1539 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001540 if(0 != encoder->private_->raw_bits_per_partition_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001541 free(encoder->private_->raw_bits_per_partition_unaligned);
1542 encoder->private_->raw_bits_per_partition_unaligned = 0;
1543 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001544 if(encoder->protected_->verify) {
1545 for(i = 0; i < encoder->protected_->channels; i++) {
1546 if(0 != encoder->private_->verify.input_fifo.data[i]) {
1547 free(encoder->private_->verify.input_fifo.data[i]);
1548 encoder->private_->verify.input_fifo.data[i] = 0;
1549 }
1550 }
1551 }
Josh Coalson639aeb02002-07-25 05:38:23 +00001552 FLAC__bitbuffer_free(encoder->private_->frame);
1553}
1554
Josh Coalsonf1eff452002-07-31 07:05:33 +00001555FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001556{
Josh Coalson77e3f312001-06-23 03:03:24 +00001557 FLAC__bool ok;
Josh Coalson0a15c142001-06-13 17:59:57 +00001558 unsigned i, channel;
1559
1560 FLAC__ASSERT(new_size > 0);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001561 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
1562 FLAC__ASSERT(encoder->private_->current_sample_number == 0);
Josh Coalson0a15c142001-06-13 17:59:57 +00001563
1564 /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001565 if(new_size <= encoder->private_->input_capacity)
Josh Coalson0a15c142001-06-13 17:59:57 +00001566 return true;
1567
1568 ok = true;
Josh Coalson8395d022001-07-12 21:25:22 +00001569
Josh Coalsonc9c0d132002-10-04 05:29:05 +00001570 /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx()
1571 * requires that the input arrays (in our case the integer signals)
1572 * have a buffer of up to 3 zeroes in front (at negative indices) for
1573 * alignment purposes; we use 4 to keep the data well-aligned.
1574 */
Josh Coalson8395d022001-07-12 21:25:22 +00001575
Josh Coalsonfa697a92001-08-16 20:07:29 +00001576 for(i = 0; ok && i < encoder->protected_->channels; i++) {
1577 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size+4, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]);
1578 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]);
1579 memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4);
1580 encoder->private_->integer_signal[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001581 }
1582 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001583 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]);
1584 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]);
1585 memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4);
1586 encoder->private_->integer_signal_mid_side[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001587 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001588 for(channel = 0; ok && channel < encoder->protected_->channels; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001589 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001590 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 +00001591 }
1592 }
1593 for(channel = 0; ok && channel < 2; channel++) {
1594 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001595 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 +00001596 }
1597 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001598 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->private_->abs_residual_unaligned, &encoder->private_->abs_residual);
1599 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 */
1600 ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_size * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums);
1601 if(encoder->protected_->do_escape_coding)
1602 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 +00001603
1604 if(ok)
Josh Coalsonfa697a92001-08-16 20:07:29 +00001605 encoder->private_->input_capacity = new_size;
Josh Coalson0a15c142001-06-13 17:59:57 +00001606 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00001607 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson0a15c142001-06-13 17:59:57 +00001608
1609 return ok;
1610}
1611
Josh Coalsond86e03b2002-08-03 21:56:15 +00001612FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
Josh Coalson5c491a12002-08-01 06:39:40 +00001613{
1614 const FLAC__byte *buffer;
1615 unsigned bytes;
1616
1617 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1618
1619 FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
1620
Josh Coalsond86e03b2002-08-03 21:56:15 +00001621 if(encoder->protected_->verify) {
1622 encoder->private_->verify.output.data = buffer;
1623 encoder->private_->verify.output.bytes = bytes;
1624 if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) {
1625 encoder->private_->verify.needs_magic_hack = true;
1626 }
1627 else {
1628 if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) {
1629 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1630 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
1631 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
1632 return false;
1633 }
1634 }
1635 }
1636
1637 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 +00001638 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
Josh Coalsond86e03b2002-08-03 21:56:15 +00001639 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
Josh Coalson5c491a12002-08-01 06:39:40 +00001640 return false;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001641 }
Josh Coalson5c491a12002-08-01 06:39:40 +00001642
1643 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1644
Josh Coalsond86e03b2002-08-03 21:56:15 +00001645 if(samples > 0) {
1646 encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize);
1647 encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize);
1648 }
1649
Josh Coalson5c491a12002-08-01 06:39:40 +00001650 return true;
1651}
1652
Josh Coalsonf1eff452002-07-31 07:05:33 +00001653FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson0a15c142001-06-13 17:59:57 +00001654{
Josh Coalsonfa697a92001-08-16 20:07:29 +00001655 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001656
1657 /*
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001658 * Accumulate raw signal to the MD5 signature
1659 */
Josh Coalson57ba6f42002-06-07 05:27:37 +00001660 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 +00001661 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001662 return false;
1663 }
1664
1665 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001666 * Process the frame header and subframes into the frame bitbuffer
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001667 */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001668 if(!process_subframes_(encoder, is_last_frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001669 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001670 return false;
1671 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001672
1673 /*
1674 * Zero-pad the frame to a byte_boundary
1675 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001676 if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001677 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001678 return false;
1679 }
1680
1681 /*
Josh Coalson215af572001-03-27 01:15:58 +00001682 * CRC-16 the whole thing
1683 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001684 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1685 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 +00001686
1687 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001688 * Write it
1689 */
Josh Coalsond86e03b2002-08-03 21:56:15 +00001690 if(!write_bitbuffer_(encoder, encoder->protected_->blocksize)) {
1691 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001692 return false;
1693 }
1694
1695 /*
1696 * Get ready for the next frame
1697 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001698 encoder->private_->current_sample_number = 0;
1699 encoder->private_->current_frame_number++;
1700 encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001701
1702 return true;
1703}
1704
Josh Coalsonf1eff452002-07-31 07:05:33 +00001705FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001706{
1707 FLAC__FrameHeader frame_header;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001708 unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00001709 FLAC__bool do_independent, do_mid_side, precompute_partition_sums;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001710
1711 /*
Josh Coalson60f77d72001-04-25 02:16:36 +00001712 * Calculate the min,max Rice partition orders
Josh Coalson94e02cd2001-01-25 10:41:06 +00001713 */
1714 if(is_last_frame) {
1715 max_partition_order = 0;
1716 }
1717 else {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001718 max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize);
1719 max_partition_order = min(max_partition_order, encoder->protected_->max_residual_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001720 }
Josh Coalson60f77d72001-04-25 02:16:36 +00001721 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001722
Josh Coalsonfa697a92001-08-16 20:07:29 +00001723 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 +00001724
Josh Coalson94e02cd2001-01-25 10:41:06 +00001725 /*
1726 * Setup the frame
1727 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001728 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001729 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001730 return false;
1731 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001732 frame_header.blocksize = encoder->protected_->blocksize;
1733 frame_header.sample_rate = encoder->protected_->sample_rate;
1734 frame_header.channels = encoder->protected_->channels;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001735 frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001736 frame_header.bits_per_sample = encoder->protected_->bits_per_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00001737 frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001738 frame_header.number.frame_number = encoder->private_->current_frame_number;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001739
1740 /*
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001741 * Figure out what channel assignments to try
1742 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001743 if(encoder->protected_->do_mid_side_stereo) {
1744 if(encoder->protected_->loose_mid_side_stereo) {
1745 if(encoder->private_->loose_mid_side_stereo_frame_count == 0) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001746 do_independent = true;
1747 do_mid_side = true;
1748 }
1749 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001750 do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001751 do_mid_side = !do_independent;
1752 }
1753 }
1754 else {
1755 do_independent = true;
1756 do_mid_side = true;
1757 }
1758 }
1759 else {
1760 do_independent = true;
1761 do_mid_side = false;
1762 }
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001763
Josh Coalson1b689822001-05-31 20:11:02 +00001764 FLAC__ASSERT(do_independent || do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001765
1766 /*
Josh Coalson82b73242001-03-28 22:17:05 +00001767 * Check for wasted bits; set effective bps for each subframe
Josh Coalson859bc542001-03-27 22:22:27 +00001768 */
1769 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001770 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001771 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001772 encoder->private_->subframe_workspace[channel][0].wasted_bits = encoder->private_->subframe_workspace[channel][1].wasted_bits = w;
1773 encoder->private_->subframe_bps[channel] = encoder->protected_->bits_per_sample - w;
Josh Coalson82b73242001-03-28 22:17:05 +00001774 }
Josh Coalson859bc542001-03-27 22:22:27 +00001775 }
1776 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001777 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson82b73242001-03-28 22:17:05 +00001778 for(channel = 0; channel < 2; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001779 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001780 encoder->private_->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private_->subframe_workspace_mid_side[channel][1].wasted_bits = w;
1781 encoder->private_->subframe_bps_mid_side[channel] = encoder->protected_->bits_per_sample - w + (channel==0? 0:1);
Josh Coalson82b73242001-03-28 22:17:05 +00001782 }
Josh Coalson859bc542001-03-27 22:22:27 +00001783 }
1784
1785 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001786 * First do a normal encoding pass of each independent channel
1787 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001788 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001789 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001790 if(!
1791 process_subframe_(
1792 encoder,
1793 min_partition_order,
1794 max_partition_order,
1795 precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00001796 &frame_header,
1797 encoder->private_->subframe_bps[channel],
1798 encoder->private_->integer_signal[channel],
1799 encoder->private_->real_signal[channel],
1800 encoder->private_->subframe_workspace_ptr[channel],
1801 encoder->private_->partitioned_rice_contents_workspace_ptr[channel],
1802 encoder->private_->residual_workspace[channel],
1803 encoder->private_->best_subframe+channel,
1804 encoder->private_->best_subframe_bits+channel
1805 )
1806 )
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001807 return false;
1808 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001809 }
1810
1811 /*
1812 * Now do mid and side channels if requested
1813 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001814 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001815 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001816
1817 for(channel = 0; channel < 2; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001818 if(!
1819 process_subframe_(
1820 encoder,
1821 min_partition_order,
1822 max_partition_order,
1823 precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00001824 &frame_header,
1825 encoder->private_->subframe_bps_mid_side[channel],
1826 encoder->private_->integer_signal_mid_side[channel],
1827 encoder->private_->real_signal_mid_side[channel],
1828 encoder->private_->subframe_workspace_ptr_mid_side[channel],
1829 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel],
1830 encoder->private_->residual_workspace_mid_side[channel],
1831 encoder->private_->best_subframe_mid_side+channel,
1832 encoder->private_->best_subframe_bits_mid_side+channel
1833 )
1834 )
Josh Coalson94e02cd2001-01-25 10:41:06 +00001835 return false;
1836 }
1837 }
1838
1839 /*
1840 * Compose the frame bitbuffer
1841 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001842 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +00001843 unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
1844 FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001845 FLAC__ChannelAssignment channel_assignment;
1846
Josh Coalsonfa697a92001-08-16 20:07:29 +00001847 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001848
Josh Coalsonfa697a92001-08-16 20:07:29 +00001849 if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) {
1850 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 +00001851 }
1852 else {
1853 unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
1854 unsigned min_bits;
1855 FLAC__ChannelAssignment ca;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001856
Josh Coalson1b689822001-05-31 20:11:02 +00001857 FLAC__ASSERT(do_independent && do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001858
1859 /* We have to figure out which channel assignent results in the smallest frame */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001860 bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1];
1861 bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1];
1862 bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1];
1863 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 +00001864
Josh Coalson7424d2f2002-11-06 07:10:38 +00001865 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 +00001866 if(bits[ca] < min_bits) {
1867 min_bits = bits[ca];
1868 channel_assignment = ca;
1869 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001870 }
1871 }
1872
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001873 frame_header.channel_assignment = channel_assignment;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001874
Josh Coalson3e7a96e2004-07-23 05:18:22 +00001875 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001876 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001877 return false;
1878 }
1879
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001880 switch(channel_assignment) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001881 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001882 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1883 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001884 break;
1885 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001886 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1887 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001888 break;
1889 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001890 left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
1891 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001892 break;
1893 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001894 left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]];
1895 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001896 break;
1897 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001898 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001899 }
Josh Coalson82b73242001-03-28 22:17:05 +00001900
1901 switch(channel_assignment) {
1902 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001903 left_bps = encoder->private_->subframe_bps [0];
1904 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001905 break;
1906 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001907 left_bps = encoder->private_->subframe_bps [0];
1908 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001909 break;
1910 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001911 left_bps = encoder->private_->subframe_bps_mid_side[1];
1912 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001913 break;
1914 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001915 left_bps = encoder->private_->subframe_bps_mid_side[0];
1916 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001917 break;
1918 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001919 FLAC__ASSERT(0);
Josh Coalson82b73242001-03-28 22:17:05 +00001920 }
1921
1922 /* note that encoder_add_subframe_ sets the state for us in case of an error */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001923 if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001924 return false;
Josh Coalsonf1eff452002-07-31 07:05:33 +00001925 if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001926 return false;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001927 }
1928 else {
Josh Coalson3e7a96e2004-07-23 05:18:22 +00001929 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001930 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001931 return false;
1932 }
1933
Josh Coalsonfa697a92001-08-16 20:07:29 +00001934 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001935 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 +00001936 /* the above function sets the state for us in case of an error */
1937 return false;
1938 }
1939 }
1940 }
1941
Josh Coalsonfa697a92001-08-16 20:07:29 +00001942 if(encoder->protected_->loose_mid_side_stereo) {
1943 encoder->private_->loose_mid_side_stereo_frame_count++;
1944 if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames)
1945 encoder->private_->loose_mid_side_stereo_frame_count = 0;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001946 }
1947
Josh Coalsonfa697a92001-08-16 20:07:29 +00001948 encoder->private_->last_channel_assignment = frame_header.channel_assignment;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001949
Josh Coalson94e02cd2001-01-25 10:41:06 +00001950 return true;
1951}
1952
Josh Coalson6fe72f72002-08-20 04:01:59 +00001953FLAC__bool process_subframe_(
1954 FLAC__StreamEncoder *encoder,
1955 unsigned min_partition_order,
1956 unsigned max_partition_order,
1957 FLAC__bool precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00001958 const FLAC__FrameHeader *frame_header,
1959 unsigned subframe_bps,
1960 const FLAC__int32 integer_signal[],
1961 const FLAC__real real_signal[],
1962 FLAC__Subframe *subframe[2],
1963 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
1964 FLAC__int32 *residual[2],
1965 unsigned *best_subframe,
1966 unsigned *best_bits
1967)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001968{
Josh Coalson77e3f312001-06-23 03:03:24 +00001969 FLAC__real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
1970 FLAC__real lpc_residual_bits_per_sample;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001971 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 +00001972 FLAC__real lpc_error[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001973 unsigned min_lpc_order, max_lpc_order, lpc_order;
1974 unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
1975 unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
1976 unsigned rice_parameter;
1977 unsigned _candidate_bits, _best_bits;
1978 unsigned _best_subframe;
1979
1980 /* verbatim subframe is the baseline against which we measure other compressed subframes */
1981 _best_subframe = 0;
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001982 if(encoder->private_->disable_verbatim_subframes && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER)
1983 _best_bits = UINT_MAX;
1984 else
1985 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001986
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001987 if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
1988 unsigned signal_is_constant = false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001989 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 +00001990 /* check for constant subframe */
1991 if(!encoder->private_->disable_constant_subframes && fixed_residual_bits_per_sample[1] == 0.0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001992 /* 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 +00001993 unsigned i;
1994 signal_is_constant = true;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001995 for(i = 1; i <= FLAC__MAX_FIXED_ORDER; i++) {
1996 if(integer_signal[0] != integer_signal[i]) {
1997 signal_is_constant = false;
1998 break;
1999 }
2000 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002001 }
2002 if(signal_is_constant) {
2003 _candidate_bits = evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
2004 if(_candidate_bits < _best_bits) {
2005 _best_subframe = !_best_subframe;
2006 _best_bits = _candidate_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002007 }
2008 }
2009 else {
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002010 if(!encoder->private_->disable_fixed_subframes || (encoder->protected_->max_lpc_order == 0 && _best_bits == UINT_MAX)) {
2011 /* encode fixed */
2012 if(encoder->protected_->do_exhaustive_model_search) {
2013 min_fixed_order = 0;
2014 max_fixed_order = FLAC__MAX_FIXED_ORDER;
Josh Coalson8395d022001-07-12 21:25:22 +00002015 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002016 else {
2017 min_fixed_order = max_fixed_order = guess_fixed_order;
2018 }
2019 for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
2020 if(fixed_residual_bits_per_sample[fixed_order] >= (FLAC__real)subframe_bps)
2021 continue; /* don't even try */
2022 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 */
2023#ifndef FLAC__SYMMETRIC_RICE
2024 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
2025#endif
2026 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
2027#ifdef DEBUG_VERBOSE
2028 fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2029#endif
2030 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2031 }
2032 _candidate_bits =
2033 evaluate_fixed_subframe_(
2034 encoder,
2035 integer_signal,
2036 residual[!_best_subframe],
2037 encoder->private_->abs_residual,
2038 encoder->private_->abs_residual_partition_sums,
2039 encoder->private_->raw_bits_per_partition,
2040 frame_header->blocksize,
2041 subframe_bps,
2042 fixed_order,
2043 rice_parameter,
2044 min_partition_order,
2045 max_partition_order,
2046 precompute_partition_sums,
2047 encoder->protected_->do_escape_coding,
2048 encoder->protected_->rice_parameter_search_dist,
2049 subframe[!_best_subframe],
2050 partitioned_rice_contents[!_best_subframe]
2051 );
2052 if(_candidate_bits < _best_bits) {
2053 _best_subframe = !_best_subframe;
2054 _best_bits = _candidate_bits;
2055 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002056 }
2057 }
2058
2059 /* encode lpc */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002060 if(encoder->protected_->max_lpc_order > 0) {
2061 if(encoder->protected_->max_lpc_order >= frame_header->blocksize)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002062 max_lpc_order = frame_header->blocksize-1;
2063 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00002064 max_lpc_order = encoder->protected_->max_lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002065 if(max_lpc_order > 0) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002066 encoder->private_->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002067 /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
2068 if(autoc[0] != 0.0) {
Josh Coalson8084b052001-11-01 00:27:29 +00002069 FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
Josh Coalsonfa697a92001-08-16 20:07:29 +00002070 if(encoder->protected_->do_exhaustive_model_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002071 min_lpc_order = 1;
2072 }
2073 else {
Josh Coalson82b73242001-03-28 22:17:05 +00002074 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 +00002075 min_lpc_order = max_lpc_order = guess_lpc_order;
2076 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002077 for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
2078 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 +00002079 if(lpc_residual_bits_per_sample >= (FLAC__real)subframe_bps)
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002080 continue; /* don't even try */
2081 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 +00002082#ifndef FLAC__SYMMETRIC_RICE
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002083 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00002084#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002085 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002086#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002087 fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2088#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002089 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002090 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002091 if(encoder->protected_->do_qlp_coeff_prec_search) {
2092 min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
2093 /* ensure a 32-bit datapath throughout for 16bps or less */
2094 if(subframe_bps <= 16)
2095 max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION);
2096 else
2097 max_qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
2098 }
2099 else {
2100 min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
2101 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002102 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 +00002103 _candidate_bits =
2104 evaluate_lpc_subframe_(
2105 encoder,
2106 integer_signal,
2107 residual[!_best_subframe],
2108 encoder->private_->abs_residual,
2109 encoder->private_->abs_residual_partition_sums,
2110 encoder->private_->raw_bits_per_partition,
2111 encoder->private_->lp_coeff[lpc_order-1],
2112 frame_header->blocksize,
2113 subframe_bps,
2114 lpc_order,
2115 qlp_coeff_precision,
2116 rice_parameter,
2117 min_partition_order,
2118 max_partition_order,
2119 precompute_partition_sums,
2120 encoder->protected_->do_escape_coding,
2121 encoder->protected_->rice_parameter_search_dist,
2122 subframe[!_best_subframe],
2123 partitioned_rice_contents[!_best_subframe]
2124 );
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002125 if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
2126 if(_candidate_bits < _best_bits) {
2127 _best_subframe = !_best_subframe;
2128 _best_bits = _candidate_bits;
2129 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002130 }
2131 }
2132 }
2133 }
2134 }
2135 }
2136 }
2137 }
2138
Josh Coalson72695802002-10-11 06:25:16 +00002139 /* under rare circumstances this can happen when all but lpc subframe types are disabled: */
2140 if(_best_bits == UINT_MAX) {
2141 FLAC__ASSERT(_best_subframe == 0);
2142 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
2143 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002144
Josh Coalson94e02cd2001-01-25 10:41:06 +00002145 *best_subframe = _best_subframe;
2146 *best_bits = _best_bits;
2147
2148 return true;
2149}
2150
Josh Coalson6fe72f72002-08-20 04:01:59 +00002151FLAC__bool add_subframe_(
2152 FLAC__StreamEncoder *encoder,
2153 const FLAC__FrameHeader *frame_header,
2154 unsigned subframe_bps,
2155 const FLAC__Subframe *subframe,
2156 FLAC__BitBuffer *frame
2157)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002158{
2159 switch(subframe->type) {
2160 case FLAC__SUBFRAME_TYPE_CONSTANT:
Josh Coalson82b73242001-03-28 22:17:05 +00002161 if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002162 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002163 return false;
2164 }
2165 break;
2166 case FLAC__SUBFRAME_TYPE_FIXED:
Josh Coalson82b73242001-03-28 22:17:05 +00002167 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 +00002168 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002169 return false;
2170 }
2171 break;
2172 case FLAC__SUBFRAME_TYPE_LPC:
Josh Coalson82b73242001-03-28 22:17:05 +00002173 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 +00002174 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002175 return false;
2176 }
2177 break;
2178 case FLAC__SUBFRAME_TYPE_VERBATIM:
Josh Coalson82b73242001-03-28 22:17:05 +00002179 if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002180 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002181 return false;
2182 }
2183 break;
2184 default:
Josh Coalson1b689822001-05-31 20:11:02 +00002185 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002186 }
2187
2188 return true;
2189}
2190
Josh Coalson6fe72f72002-08-20 04:01:59 +00002191unsigned evaluate_constant_subframe_(
2192 const FLAC__int32 signal,
2193 unsigned subframe_bps,
2194 FLAC__Subframe *subframe
2195)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002196{
2197 subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
2198 subframe->data.constant.value = signal;
2199
Josh Coalson82b73242001-03-28 22:17:05 +00002200 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 +00002201}
2202
Josh Coalson6fe72f72002-08-20 04:01:59 +00002203unsigned evaluate_fixed_subframe_(
2204 FLAC__StreamEncoder *encoder,
2205 const FLAC__int32 signal[],
2206 FLAC__int32 residual[],
2207 FLAC__uint32 abs_residual[],
2208 FLAC__uint64 abs_residual_partition_sums[],
2209 unsigned raw_bits_per_partition[],
2210 unsigned blocksize,
2211 unsigned subframe_bps,
2212 unsigned order,
2213 unsigned rice_parameter,
2214 unsigned min_partition_order,
2215 unsigned max_partition_order,
2216 FLAC__bool precompute_partition_sums,
2217 FLAC__bool do_escape_coding,
2218 unsigned rice_parameter_search_dist,
2219 FLAC__Subframe *subframe,
2220 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2221)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002222{
2223 unsigned i, residual_bits;
2224 const unsigned residual_samples = blocksize - order;
2225
2226 FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
2227
2228 subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
2229
2230 subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002231 subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002232 subframe->data.fixed.residual = residual;
2233
Josh Coalson6fe72f72002-08-20 04:01:59 +00002234 residual_bits =
2235 find_best_partition_order_(
2236 encoder->private_,
2237 residual,
2238 abs_residual,
2239 abs_residual_partition_sums,
2240 raw_bits_per_partition,
2241 residual_samples,
2242 order,
2243 rice_parameter,
2244 min_partition_order,
2245 max_partition_order,
2246 precompute_partition_sums,
2247 do_escape_coding,
2248 rice_parameter_search_dist,
2249 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2250 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002251
2252 subframe->data.fixed.order = order;
2253 for(i = 0; i < order; i++)
2254 subframe->data.fixed.warmup[i] = signal[i];
2255
Josh Coalson82b73242001-03-28 22:17:05 +00002256 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 +00002257}
2258
Josh Coalson6fe72f72002-08-20 04:01:59 +00002259unsigned evaluate_lpc_subframe_(
2260 FLAC__StreamEncoder *encoder,
2261 const FLAC__int32 signal[],
2262 FLAC__int32 residual[],
2263 FLAC__uint32 abs_residual[],
2264 FLAC__uint64 abs_residual_partition_sums[],
2265 unsigned raw_bits_per_partition[],
2266 const FLAC__real lp_coeff[],
2267 unsigned blocksize,
2268 unsigned subframe_bps,
2269 unsigned order,
2270 unsigned qlp_coeff_precision,
2271 unsigned rice_parameter,
2272 unsigned min_partition_order,
2273 unsigned max_partition_order,
2274 FLAC__bool precompute_partition_sums,
2275 FLAC__bool do_escape_coding,
2276 unsigned rice_parameter_search_dist,
2277 FLAC__Subframe *subframe,
2278 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2279)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002280{
Josh Coalson77e3f312001-06-23 03:03:24 +00002281 FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00002282 unsigned i, residual_bits;
2283 int quantization, ret;
2284 const unsigned residual_samples = blocksize - order;
2285
Josh Coalson20ac2c12002-08-30 05:47:14 +00002286 /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */
2287 if(subframe_bps <= 16) {
2288 FLAC__ASSERT(order > 0);
2289 FLAC__ASSERT(order <= FLAC__MAX_LPC_ORDER);
2290 qlp_coeff_precision = min(qlp_coeff_precision, 32 - subframe_bps - FLAC__bitmath_ilog2(order));
2291 }
2292
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002293 ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, qlp_coeff, &quantization);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002294 if(ret != 0)
2295 return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
2296
Josh Coalsonfb9d18f2002-10-21 07:04:07 +00002297 if(subframe_bps + qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32)
2298 if(subframe_bps <= 16 && qlp_coeff_precision <= 16)
2299 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
2300 else
2301 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 +00002302 else
2303 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 +00002304
2305 subframe->type = FLAC__SUBFRAME_TYPE_LPC;
2306
2307 subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002308 subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002309 subframe->data.lpc.residual = residual;
2310
Josh Coalson6fe72f72002-08-20 04:01:59 +00002311 residual_bits =
2312 find_best_partition_order_(
2313 encoder->private_,
2314 residual,
2315 abs_residual,
2316 abs_residual_partition_sums,
2317 raw_bits_per_partition,
2318 residual_samples,
2319 order,
2320 rice_parameter,
2321 min_partition_order,
2322 max_partition_order,
2323 precompute_partition_sums,
2324 do_escape_coding,
2325 rice_parameter_search_dist,
2326 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2327 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002328
2329 subframe->data.lpc.order = order;
2330 subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
2331 subframe->data.lpc.quantization_level = quantization;
Josh Coalson77e3f312001-06-23 03:03:24 +00002332 memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002333 for(i = 0; i < order; i++)
2334 subframe->data.lpc.warmup[i] = signal[i];
2335
Josh Coalson82b73242001-03-28 22:17:05 +00002336 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 +00002337}
2338
Josh Coalson6fe72f72002-08-20 04:01:59 +00002339unsigned evaluate_verbatim_subframe_(
2340 const FLAC__int32 signal[],
2341 unsigned blocksize,
2342 unsigned subframe_bps,
2343 FLAC__Subframe *subframe
2344)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002345{
2346 subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
2347
2348 subframe->data.verbatim.data = signal;
2349
Josh Coalson82b73242001-03-28 22:17:05 +00002350 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 +00002351}
2352
Josh Coalson6fe72f72002-08-20 04:01:59 +00002353unsigned find_best_partition_order_(
2354 FLAC__StreamEncoderPrivate *private_,
2355 const FLAC__int32 residual[],
2356 FLAC__uint32 abs_residual[],
2357 FLAC__uint64 abs_residual_partition_sums[],
2358 unsigned raw_bits_per_partition[],
2359 unsigned residual_samples,
2360 unsigned predictor_order,
2361 unsigned rice_parameter,
2362 unsigned min_partition_order,
2363 unsigned max_partition_order,
2364 FLAC__bool precompute_partition_sums,
2365 FLAC__bool do_escape_coding,
2366 unsigned rice_parameter_search_dist,
2367 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
2368)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002369{
Josh Coalson77e3f312001-06-23 03:03:24 +00002370 FLAC__int32 r;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002371 unsigned residual_bits, best_residual_bits = 0;
Josh Coalsonafcd8772001-04-18 22:59:25 +00002372 unsigned residual_sample;
Josh Coalson8084b052001-11-01 00:27:29 +00002373 unsigned best_parameters_index = 0;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002374 const unsigned blocksize = residual_samples + predictor_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002375
Josh Coalson2051dd42001-04-12 22:22:34 +00002376 /* compute abs(residual) for use later */
2377 for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
2378 r = residual[residual_sample];
Josh Coalson77e3f312001-06-23 03:03:24 +00002379 abs_residual[residual_sample] = (FLAC__uint32)(r<0? -r : r);
Josh Coalson2051dd42001-04-12 22:22:34 +00002380 }
2381
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002382 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 +00002383 min_partition_order = min(min_partition_order, max_partition_order);
2384
Josh Coalson8395d022001-07-12 21:25:22 +00002385 if(precompute_partition_sums) {
2386 int partition_order;
2387 unsigned sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002388
Josh Coalsonf1eff452002-07-31 07:05:33 +00002389 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 +00002390
2391 if(do_escape_coding)
Josh Coalsonf1eff452002-07-31 07:05:33 +00002392 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 +00002393
2394 for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
2395#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002396 if(!
2397 set_partitioned_rice_with_precompute_(
2398 residual,
2399 abs_residual_partition_sums+sum,
2400 raw_bits_per_partition+sum,
2401 residual_samples,
2402 predictor_order,
2403 rice_parameter,
2404 rice_parameter_search_dist,
2405 (unsigned)partition_order,
2406 do_escape_coding,
2407 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2408 &residual_bits
2409 )
2410 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002411#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002412 if(!
2413 set_partitioned_rice_with_precompute_(
2414 abs_residual,
2415 abs_residual_partition_sums+sum,
2416 raw_bits_per_partition+sum,
2417 residual_samples,
2418 predictor_order,
2419 rice_parameter,
2420 rice_parameter_search_dist,
2421 (unsigned)partition_order,
2422 do_escape_coding,
2423 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2424 &residual_bits
2425 )
2426 )
Josh Coalson8395d022001-07-12 21:25:22 +00002427#endif
2428 {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002429 FLAC__ASSERT(best_residual_bits != 0);
2430 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002431 }
2432 sum += 1u << partition_order;
2433 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2434 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002435 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002436 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002437 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00002438 }
2439 }
Josh Coalson8395d022001-07-12 21:25:22 +00002440 else {
2441 unsigned partition_order;
2442 for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
2443#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002444 if(!
2445 set_partitioned_rice_(
2446 abs_residual,
2447 residual,
2448 residual_samples,
2449 predictor_order,
2450 rice_parameter,
2451 rice_parameter_search_dist,
2452 partition_order,
2453 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2454 &residual_bits
2455 )
2456 )
Josh Coalson8395d022001-07-12 21:25:22 +00002457#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002458 if(!
2459 set_partitioned_rice_(
2460 abs_residual,
2461 residual_samples,
2462 predictor_order,
2463 rice_parameter,
2464 rice_parameter_search_dist,
2465 partition_order,
2466 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2467 &residual_bits
2468 )
2469 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002470#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002471 {
2472 FLAC__ASSERT(best_residual_bits != 0);
2473 break;
2474 }
2475 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2476 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002477 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002478 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002479 }
2480 }
2481 }
2482
Josh Coalsona37ba462002-08-19 21:36:39 +00002483 /*
Josh Coalson20ac2c12002-08-30 05:47:14 +00002484 * We are allowed to de-const the pointer based on our special knowledge;
Josh Coalsona37ba462002-08-19 21:36:39 +00002485 * it is const to the outside world.
2486 */
2487 {
2488 FLAC__EntropyCodingMethod_PartitionedRiceContents* best_partitioned_rice_contents = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_partitioned_rice->contents;
2489 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(best_partitioned_rice_contents, max(6, best_partitioned_rice->order));
2490 memcpy(best_partitioned_rice_contents->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2491 memcpy(best_partitioned_rice_contents->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2492 }
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002493
2494 return best_residual_bits;
2495}
2496
Josh Coalson6fe72f72002-08-20 04:01:59 +00002497void precompute_partition_info_sums_(
2498 const FLAC__uint32 abs_residual[],
2499 FLAC__uint64 abs_residual_partition_sums[],
2500 unsigned residual_samples,
2501 unsigned predictor_order,
2502 unsigned min_partition_order,
2503 unsigned max_partition_order
2504)
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002505{
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002506 int partition_order;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002507 unsigned from_partition, to_partition = 0;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002508 const unsigned blocksize = residual_samples + predictor_order;
2509
Josh Coalsonaef013c2001-04-24 01:25:42 +00002510 /* first do max_partition_order */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002511 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002512 FLAC__uint64 abs_residual_partition_sum;
Josh Coalson77e3f312001-06-23 03:03:24 +00002513 FLAC__uint32 abs_r;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002514 unsigned partition, partition_sample, partition_samples, residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002515 const unsigned partitions = 1u << partition_order;
2516 const unsigned default_partition_samples = blocksize >> partition_order;
2517
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002518 FLAC__ASSERT(default_partition_samples > predictor_order);
2519
2520 for(partition = residual_sample = 0; partition < partitions; partition++) {
2521 partition_samples = default_partition_samples;
2522 if(partition == 0)
2523 partition_samples -= predictor_order;
2524 abs_residual_partition_sum = 0;
2525 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2526 abs_r = abs_residual[residual_sample];
2527 abs_residual_partition_sum += abs_r;
2528 residual_sample++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002529 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002530 abs_residual_partition_sums[partition] = abs_residual_partition_sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002531 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002532 to_partition = partitions;
2533 break;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002534 }
Josh Coalsonf76a3612001-04-18 02:28:11 +00002535
Josh Coalson8395d022001-07-12 21:25:22 +00002536 /* now merge partitions for lower orders */
Josh Coalson6bd17572001-05-25 19:02:01 +00002537 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002538 FLAC__uint64 s;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002539 unsigned i;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002540 const unsigned partitions = 1u << partition_order;
2541 for(i = 0; i < partitions; i++) {
Josh Coalsonaef013c2001-04-24 01:25:42 +00002542 s = abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002543 from_partition++;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002544 abs_residual_partition_sums[to_partition] = s + abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002545 from_partition++;
2546 to_partition++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002547 }
2548 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002549}
Josh Coalson8395d022001-07-12 21:25:22 +00002550
Josh Coalson6fe72f72002-08-20 04:01:59 +00002551void precompute_partition_info_escapes_(
2552 const FLAC__int32 residual[],
2553 unsigned raw_bits_per_partition[],
2554 unsigned residual_samples,
2555 unsigned predictor_order,
2556 unsigned min_partition_order,
2557 unsigned max_partition_order
2558)
Josh Coalson8395d022001-07-12 21:25:22 +00002559{
2560 int partition_order;
2561 unsigned from_partition, to_partition = 0;
2562 const unsigned blocksize = residual_samples + predictor_order;
2563
2564 /* first do max_partition_order */
2565 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
2566 FLAC__int32 r, residual_partition_min, residual_partition_max;
2567 unsigned silog2_min, silog2_max;
2568 unsigned partition, partition_sample, partition_samples, residual_sample;
2569 const unsigned partitions = 1u << partition_order;
2570 const unsigned default_partition_samples = blocksize >> partition_order;
2571
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002572 FLAC__ASSERT(default_partition_samples > predictor_order);
2573
2574 for(partition = residual_sample = 0; partition < partitions; partition++) {
2575 partition_samples = default_partition_samples;
2576 if(partition == 0)
2577 partition_samples -= predictor_order;
2578 residual_partition_min = residual_partition_max = 0;
2579 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2580 r = residual[residual_sample];
2581 if(r < residual_partition_min)
2582 residual_partition_min = r;
2583 else if(r > residual_partition_max)
2584 residual_partition_max = r;
2585 residual_sample++;
Josh Coalson8395d022001-07-12 21:25:22 +00002586 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002587 silog2_min = FLAC__bitmath_silog2(residual_partition_min);
2588 silog2_max = FLAC__bitmath_silog2(residual_partition_max);
2589 raw_bits_per_partition[partition] = max(silog2_min, silog2_max);
Josh Coalson8395d022001-07-12 21:25:22 +00002590 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002591 to_partition = partitions;
2592 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002593 }
2594
2595 /* now merge partitions for lower orders */
2596 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
2597 unsigned m;
2598 unsigned i;
2599 const unsigned partitions = 1u << partition_order;
2600 for(i = 0; i < partitions; i++) {
2601 m = raw_bits_per_partition[from_partition];
2602 from_partition++;
2603 raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]);
2604 from_partition++;
2605 to_partition++;
2606 }
2607 }
2608}
Josh Coalson94e02cd2001-01-25 10:41:06 +00002609
Josh Coalson352e0f62001-03-20 22:55:50 +00002610#ifdef VARIABLE_RICE_BITS
2611#undef VARIABLE_RICE_BITS
2612#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002613#ifndef DONT_ESTIMATE_RICE_BITS
Josh Coalson352e0f62001-03-20 22:55:50 +00002614#define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
Josh Coalson8395d022001-07-12 21:25:22 +00002615#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002616
Josh Coalson8395d022001-07-12 21:25:22 +00002617#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002618FLAC__bool set_partitioned_rice_(
2619 const FLAC__uint32 abs_residual[],
2620 const FLAC__int32 residual[],
2621 const unsigned residual_samples,
2622 const unsigned predictor_order,
2623 const unsigned suggested_rice_parameter,
2624 const unsigned rice_parameter_search_dist,
2625 const unsigned partition_order,
2626 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2627 unsigned *bits
2628)
Josh Coalson8395d022001-07-12 21:25:22 +00002629#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002630FLAC__bool set_partitioned_rice_(
2631 const FLAC__uint32 abs_residual[],
2632 const unsigned residual_samples,
2633 const unsigned predictor_order,
2634 const unsigned suggested_rice_parameter,
2635 const unsigned rice_parameter_search_dist,
2636 const unsigned partition_order,
2637 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2638 unsigned *bits
2639)
Josh Coalson8395d022001-07-12 21:25:22 +00002640#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002641{
Josh Coalson034dfab2001-04-27 19:10:23 +00002642 unsigned rice_parameter, partition_bits;
2643#ifndef NO_RICE_SEARCH
2644 unsigned best_partition_bits;
2645 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2646#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002647 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002648 unsigned *parameters;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002649
Josh Coalson1b689822001-05-31 20:11:02 +00002650 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
Josh Coalson2051dd42001-04-12 22:22:34 +00002651
Josh Coalsona37ba462002-08-19 21:36:39 +00002652 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2653 parameters = partitioned_rice_contents->parameters;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002654
Josh Coalson94e02cd2001-01-25 10:41:06 +00002655 if(partition_order == 0) {
2656 unsigned i;
Josh Coalson352e0f62001-03-20 22:55:50 +00002657
Josh Coalson034dfab2001-04-27 19:10:23 +00002658#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002659 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002660 if(suggested_rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002661 min_rice_parameter = 0;
2662 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002663 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2664 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002665 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002666#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002667 fprintf(stderr, "clipping rice_parameter (%u -> %u) @2\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2668#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002669 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002670 }
2671 }
2672 else
2673 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
2674
2675 best_partition_bits = 0xffffffff;
2676 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2677#endif
2678#ifdef VARIABLE_RICE_BITS
2679#ifdef FLAC__SYMMETRIC_RICE
2680 partition_bits = (2+rice_parameter) * residual_samples;
2681#else
2682 const unsigned rice_parameter_estimate = rice_parameter-1;
2683 partition_bits = (1+rice_parameter) * residual_samples;
2684#endif
2685#else
2686 partition_bits = 0;
2687#endif
2688 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2689 for(i = 0; i < residual_samples; i++) {
2690#ifdef VARIABLE_RICE_BITS
2691#ifdef FLAC__SYMMETRIC_RICE
2692 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
2693#else
2694 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
2695#endif
2696#else
2697 partition_bits += FLAC__bitbuffer_rice_bits(residual[i], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2698#endif
2699 }
2700#ifndef NO_RICE_SEARCH
2701 if(partition_bits < best_partition_bits) {
2702 best_rice_parameter = rice_parameter;
2703 best_partition_bits = partition_bits;
2704 }
2705 }
2706#endif
2707 parameters[0] = best_rice_parameter;
2708 bits_ += best_partition_bits;
2709 }
2710 else {
2711 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002712 unsigned partition_samples;
2713 FLAC__uint64 mean, k;
Josh Coalson8395d022001-07-12 21:25:22 +00002714 const unsigned partitions = 1u << partition_order;
2715 for(partition = residual_sample = 0; partition < partitions; partition++) {
2716 partition_samples = (residual_samples+predictor_order) >> partition_order;
2717 if(partition == 0) {
2718 if(partition_samples <= predictor_order)
2719 return false;
2720 else
2721 partition_samples -= predictor_order;
2722 }
2723 mean = 0;
2724 save_residual_sample = residual_sample;
2725 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++)
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002726 mean += abs_residual[residual_sample];
Josh Coalson8395d022001-07-12 21:25:22 +00002727 residual_sample = save_residual_sample;
2728#ifdef FLAC__SYMMETRIC_RICE
2729 mean += partition_samples >> 1; /* for rounding effect */
2730 mean /= partition_samples;
2731
2732 /* calc rice_parameter = floor(log2(mean)) */
2733 rice_parameter = 0;
2734 mean>>=1;
2735 while(mean) {
2736 rice_parameter++;
2737 mean >>= 1;
2738 }
2739#else
2740 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002741 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson8395d022001-07-12 21:25:22 +00002742 ;
2743#endif
2744 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002745#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002746 fprintf(stderr, "clipping rice_parameter (%u -> %u) @3\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2747#endif
2748 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2749 }
2750
2751#ifndef NO_RICE_SEARCH
2752 if(rice_parameter_search_dist) {
2753 if(rice_parameter < rice_parameter_search_dist)
2754 min_rice_parameter = 0;
2755 else
2756 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2757 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
2758 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002759#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002760 fprintf(stderr, "clipping rice_parameter (%u -> %u) @4\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2761#endif
2762 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2763 }
2764 }
2765 else
2766 min_rice_parameter = max_rice_parameter = rice_parameter;
2767
2768 best_partition_bits = 0xffffffff;
2769 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2770#endif
2771#ifdef VARIABLE_RICE_BITS
2772#ifdef FLAC__SYMMETRIC_RICE
2773 partition_bits = (2+rice_parameter) * partition_samples;
2774#else
2775 const unsigned rice_parameter_estimate = rice_parameter-1;
2776 partition_bits = (1+rice_parameter) * partition_samples;
2777#endif
2778#else
2779 partition_bits = 0;
2780#endif
2781 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2782 save_residual_sample = residual_sample;
2783 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
2784#ifdef VARIABLE_RICE_BITS
2785#ifdef FLAC__SYMMETRIC_RICE
2786 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
2787#else
2788 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
2789#endif
2790#else
2791 partition_bits += FLAC__bitbuffer_rice_bits(residual[residual_sample], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2792#endif
2793 }
2794#ifndef NO_RICE_SEARCH
2795 if(rice_parameter != max_rice_parameter)
2796 residual_sample = save_residual_sample;
2797 if(partition_bits < best_partition_bits) {
2798 best_rice_parameter = rice_parameter;
2799 best_partition_bits = partition_bits;
2800 }
2801 }
2802#endif
2803 parameters[partition] = best_rice_parameter;
2804 bits_ += best_partition_bits;
2805 }
2806 }
2807
2808 *bits = bits_;
2809 return true;
2810}
2811
2812#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002813FLAC__bool set_partitioned_rice_with_precompute_(
2814 const FLAC__int32 residual[],
2815 const FLAC__uint64 abs_residual_partition_sums[],
2816 const unsigned raw_bits_per_partition[],
2817 const unsigned residual_samples,
2818 const unsigned predictor_order,
2819 const unsigned suggested_rice_parameter,
2820 const unsigned rice_parameter_search_dist,
2821 const unsigned partition_order,
2822 const FLAC__bool search_for_escapes,
2823 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2824 unsigned *bits
2825)
Josh Coalson8395d022001-07-12 21:25:22 +00002826#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002827FLAC__bool set_partitioned_rice_with_precompute_(
2828 const FLAC__uint32 abs_residual[],
2829 const FLAC__uint64 abs_residual_partition_sums[],
2830 const unsigned raw_bits_per_partition[],
2831 const unsigned residual_samples,
2832 const unsigned predictor_order,
2833 const unsigned suggested_rice_parameter,
2834 const unsigned rice_parameter_search_dist,
2835 const unsigned partition_order,
2836 const FLAC__bool search_for_escapes,
2837 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2838 unsigned *bits
2839)
Josh Coalson8395d022001-07-12 21:25:22 +00002840#endif
2841{
2842 unsigned rice_parameter, partition_bits;
2843#ifndef NO_RICE_SEARCH
2844 unsigned best_partition_bits;
2845 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2846#endif
2847 unsigned flat_bits;
2848 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002849 unsigned *parameters, *raw_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002850
2851 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
2852
Josh Coalsona37ba462002-08-19 21:36:39 +00002853 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2854 parameters = partitioned_rice_contents->parameters;
2855 raw_bits = partitioned_rice_contents->raw_bits;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002856
Josh Coalson8395d022001-07-12 21:25:22 +00002857 if(partition_order == 0) {
2858 unsigned i;
2859
2860#ifndef NO_RICE_SEARCH
2861 if(rice_parameter_search_dist) {
2862 if(suggested_rice_parameter < rice_parameter_search_dist)
2863 min_rice_parameter = 0;
2864 else
2865 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2866 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
2867 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002868#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002869 fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2870#endif
2871 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2872 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002873 }
2874 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002875 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
Josh Coalson2051dd42001-04-12 22:22:34 +00002876
Josh Coalson034dfab2001-04-27 19:10:23 +00002877 best_partition_bits = 0xffffffff;
2878 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2879#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002880#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002881#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002882 partition_bits = (2+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002883#else
Josh Coalson352e0f62001-03-20 22:55:50 +00002884 const unsigned rice_parameter_estimate = rice_parameter-1;
Josh Coalson034dfab2001-04-27 19:10:23 +00002885 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002886#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002887#else
2888 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002889#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002890 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson352e0f62001-03-20 22:55:50 +00002891 for(i = 0; i < residual_samples; i++) {
2892#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002893#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson2051dd42001-04-12 22:22:34 +00002894 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002895#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002896 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002897#endif
2898#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002899 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 +00002900#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002901 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002902#ifndef NO_RICE_SEARCH
2903 if(partition_bits < best_partition_bits) {
2904 best_rice_parameter = rice_parameter;
2905 best_partition_bits = partition_bits;
Josh Coalson352e0f62001-03-20 22:55:50 +00002906 }
2907 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002908#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002909 if(search_for_escapes) {
2910 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;
2911 if(flat_bits <= best_partition_bits) {
2912 raw_bits[0] = raw_bits_per_partition[0];
2913 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2914 best_partition_bits = flat_bits;
2915 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002916 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002917 parameters[0] = best_rice_parameter;
2918 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002919 }
2920 else {
Josh Coalson4dacd192001-06-06 21:11:44 +00002921 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002922 unsigned partition_samples;
2923 FLAC__uint64 mean, k;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002924 const unsigned partitions = 1u << partition_order;
Josh Coalson4dacd192001-06-06 21:11:44 +00002925 for(partition = residual_sample = 0; partition < partitions; partition++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002926 partition_samples = (residual_samples+predictor_order) >> partition_order;
Josh Coalson034dfab2001-04-27 19:10:23 +00002927 if(partition == 0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002928 if(partition_samples <= predictor_order)
2929 return false;
2930 else
2931 partition_samples -= predictor_order;
2932 }
Josh Coalson05d20792001-06-29 23:12:26 +00002933 mean = abs_residual_partition_sums[partition];
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002934#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson05d20792001-06-29 23:12:26 +00002935 mean += partition_samples >> 1; /* for rounding effect */
2936 mean /= partition_samples;
2937
Josh Coalson034dfab2001-04-27 19:10:23 +00002938 /* calc rice_parameter = floor(log2(mean)) */
2939 rice_parameter = 0;
2940 mean>>=1;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002941 while(mean) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002942 rice_parameter++;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002943 mean >>= 1;
2944 }
Josh Coalsonb9433f92001-03-17 01:07:00 +00002945#else
Josh Coalson05d20792001-06-29 23:12:26 +00002946 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002947 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson05d20792001-06-29 23:12:26 +00002948 ;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002949#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002950 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002951#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002952 fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2953#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002954 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002955 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002956
Josh Coalson034dfab2001-04-27 19:10:23 +00002957#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002958 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002959 if(rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002960 min_rice_parameter = 0;
2961 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002962 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2963 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002964 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002965#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002966 fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2967#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002968 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002969 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002970 }
2971 else
2972 min_rice_parameter = max_rice_parameter = rice_parameter;
Josh Coalson60f77d72001-04-25 02:16:36 +00002973
Josh Coalson034dfab2001-04-27 19:10:23 +00002974 best_partition_bits = 0xffffffff;
2975 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2976#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002977#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002978#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002979 partition_bits = (2+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002980#else
Josh Coalson034dfab2001-04-27 19:10:23 +00002981 const unsigned rice_parameter_estimate = rice_parameter-1;
2982 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002983#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002984#else
2985 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002986#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002987 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson4dacd192001-06-06 21:11:44 +00002988 save_residual_sample = residual_sample;
2989 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
Josh Coalson352e0f62001-03-20 22:55:50 +00002990#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002991#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson4dacd192001-06-06 21:11:44 +00002992 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002993#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002994 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002995#endif
2996#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002997 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 +00002998#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002999 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003000#ifndef NO_RICE_SEARCH
Josh Coalson4dacd192001-06-06 21:11:44 +00003001 if(rice_parameter != max_rice_parameter)
3002 residual_sample = save_residual_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00003003 if(partition_bits < best_partition_bits) {
3004 best_rice_parameter = rice_parameter;
3005 best_partition_bits = partition_bits;
3006 }
Josh Coalson2051dd42001-04-12 22:22:34 +00003007 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003008#endif
Josh Coalson8395d022001-07-12 21:25:22 +00003009 if(search_for_escapes) {
3010 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;
3011 if(flat_bits <= best_partition_bits) {
3012 raw_bits[partition] = raw_bits_per_partition[partition];
3013 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
3014 best_partition_bits = flat_bits;
3015 }
Josh Coalson2051dd42001-04-12 22:22:34 +00003016 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003017 parameters[partition] = best_rice_parameter;
3018 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003019 }
3020 }
3021
3022 *bits = bits_;
3023 return true;
3024}
Josh Coalson859bc542001-03-27 22:22:27 +00003025
Josh Coalsonf1eff452002-07-31 07:05:33 +00003026unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples)
Josh Coalson859bc542001-03-27 22:22:27 +00003027{
3028 unsigned i, shift;
Josh Coalson77e3f312001-06-23 03:03:24 +00003029 FLAC__int32 x = 0;
Josh Coalson859bc542001-03-27 22:22:27 +00003030
3031 for(i = 0; i < samples && !(x&1); i++)
3032 x |= signal[i];
3033
3034 if(x == 0) {
3035 shift = 0;
3036 }
3037 else {
3038 for(shift = 0; !(x&1); shift++)
3039 x >>= 1;
3040 }
3041
3042 if(shift > 0) {
3043 for(i = 0; i < samples; i++)
3044 signal[i] >>= shift;
3045 }
3046
3047 return shift;
3048}
Josh Coalsond86e03b2002-08-03 21:56:15 +00003049
3050void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
3051{
3052 unsigned channel;
3053
3054 for(channel = 0; channel < channels; channel++)
3055 memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples);
3056
3057 fifo->tail += wide_samples;
3058
3059 FLAC__ASSERT(fifo->tail <= fifo->size);
3060}
3061
3062void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
3063{
3064 unsigned channel;
3065 unsigned sample, wide_sample;
3066 unsigned tail = fifo->tail;
3067
3068 sample = input_offset * channels;
3069 for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
3070 for(channel = 0; channel < channels; channel++)
3071 fifo->data[channel][tail] = input[sample++];
3072 tail++;
3073 }
3074 fifo->tail = tail;
3075
3076 FLAC__ASSERT(fifo->tail <= fifo->size);
3077}
3078
3079FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
3080{
3081 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3082 const unsigned encoded_bytes = encoder->private_->verify.output.bytes;
3083 (void)decoder;
3084
3085 if(encoder->private_->verify.needs_magic_hack) {
3086 FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH);
3087 *bytes = FLAC__STREAM_SYNC_LENGTH;
3088 memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes);
3089 encoder->private_->verify.needs_magic_hack = false;
3090 }
3091 else {
3092 if(encoded_bytes == 0) {
Josh Coalsonfc2b7372002-08-16 05:39:34 +00003093 /*
3094 * If we get here, a FIFO underflow has occurred,
3095 * which means there is a bug somewhere.
3096 */
3097 FLAC__ASSERT(0);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003098 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
3099 }
3100 else if(encoded_bytes < *bytes)
3101 *bytes = encoded_bytes;
3102 memcpy(buffer, encoder->private_->verify.output.data, *bytes);
3103 encoder->private_->verify.output.data += *bytes;
3104 encoder->private_->verify.output.bytes -= *bytes;
3105 }
3106
3107 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
3108}
3109
3110FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
3111{
3112 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data;
3113 unsigned channel;
3114 const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
3115 const unsigned blocksize = frame->header.blocksize;
3116 const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize;
3117
3118 for(channel = 0; channel < channels; channel++) {
3119 if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) {
3120 unsigned i, sample = 0;
3121 FLAC__int32 expect = 0, got = 0;
3122
3123 for(i = 0; i < blocksize; i++) {
3124 if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) {
3125 sample = i;
3126 expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i];
3127 got = (FLAC__int32)buffer[channel][i];
3128 break;
3129 }
3130 }
3131 FLAC__ASSERT(i < blocksize);
3132 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
3133 encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample;
Josh Coalson5f39e9f2002-08-21 05:27:01 +00003134 encoder->private_->verify.error_stats.frame_number = (unsigned)(frame->header.number.sample_number / blocksize);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003135 encoder->private_->verify.error_stats.channel = channel;
3136 encoder->private_->verify.error_stats.sample = sample;
3137 encoder->private_->verify.error_stats.expected = expect;
3138 encoder->private_->verify.error_stats.got = got;
3139 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA;
3140 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
3141 }
3142 }
3143 /* dequeue the frame from the fifo */
3144 for(channel = 0; channel < channels; channel++) {
3145 memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail - blocksize);
3146 }
3147 encoder->private_->verify.input_fifo.tail -= blocksize;
3148 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
3149}
3150
3151void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
3152{
3153 (void)decoder, (void)metadata, (void)client_data;
3154}
3155
3156void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
3157{
3158 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3159 (void)decoder, (void)status;
3160 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
3161}