blob: 3eb43f5016d2cfe69cbf860ee11be5c8e26cdc43 [file] [log] [blame]
Josh Coalson26560dd2001-02-08 00:38:41 +00001/* libFLAC - Free Lossless Audio Codec library
Josh Coalson305ae2e2002-01-26 17:36:39 +00002 * Copyright (C) 2000,2001,2002 Josh Coalson
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00003 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000020#include <stdio.h>
21#include <stdlib.h> /* for malloc() */
22#include <string.h> /* for memcpy() */
Josh Coalson1b689822001-05-31 20:11:02 +000023#include "FLAC/assert.h"
Josh Coalsond86e03b2002-08-03 21:56:15 +000024#include "FLAC/stream_decoder.h"
Josh Coalson0a15c142001-06-13 17:59:57 +000025#include "protected/stream_encoder.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000026#include "private/bitbuffer.h"
Josh Coalsoneef56702001-03-30 00:45:22 +000027#include "private/bitmath.h"
Josh Coalson215af572001-03-27 01:15:58 +000028#include "private/crc.h"
Josh Coalsoncf30f502001-05-23 20:57:44 +000029#include "private/cpu.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000030#include "private/fixed.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000031#include "private/format.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000032#include "private/lpc.h"
Josh Coalsonfa37f1c2001-01-12 23:55:11 +000033#include "private/md5.h"
Josh Coalsond98c43d2001-05-13 05:17:01 +000034#include "private/memory.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000035#include "private/stream_encoder_framing.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000036
37#ifdef min
38#undef min
39#endif
40#define min(x,y) ((x)<(y)?(x):(y))
41
42#ifdef max
43#undef max
44#endif
45#define max(x,y) ((x)>(y)?(x):(y))
46
Josh Coalsond86e03b2002-08-03 21:56:15 +000047typedef struct {
48 FLAC__int32 *data[FLAC__MAX_CHANNELS];
49 unsigned size; /* of each data[] in samples */
50 unsigned tail;
51} verify_input_fifo;
52
53typedef struct {
54 const FLAC__byte *data;
55 unsigned capacity;
56 unsigned bytes;
57} verify_output;
58
59typedef enum {
60 ENCODER_IN_MAGIC = 0,
61 ENCODER_IN_METADATA = 1,
62 ENCODER_IN_AUDIO = 2
63} EncoderStateHint;
64
Josh Coalson0a15c142001-06-13 17:59:57 +000065/***********************************************************************
66 *
67 * Private class method prototypes
68 *
69 ***********************************************************************/
70
Josh Coalsonf1eff452002-07-31 07:05:33 +000071static void set_defaults_(FLAC__StreamEncoder *encoder);
72static void free_(FLAC__StreamEncoder *encoder);
73static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
Josh Coalsond86e03b2002-08-03 21:56:15 +000074static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples);
Josh Coalsonf1eff452002-07-31 07:05:33 +000075static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
76static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
Josh Coalson6fe72f72002-08-20 04:01:59 +000077
78static FLAC__bool process_subframe_(
79 FLAC__StreamEncoder *encoder,
80 unsigned min_partition_order,
81 unsigned max_partition_order,
82 FLAC__bool precompute_partition_sums,
83 FLAC__bool verbatim_only,
84 const FLAC__FrameHeader *frame_header,
85 unsigned subframe_bps,
86 const FLAC__int32 integer_signal[],
87 const FLAC__real real_signal[],
88 FLAC__Subframe *subframe[2],
89 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
90 FLAC__int32 *residual[2],
91 unsigned *best_subframe,
92 unsigned *best_bits
93);
94
95static FLAC__bool add_subframe_(
96 FLAC__StreamEncoder *encoder,
97 const FLAC__FrameHeader *frame_header,
98 unsigned subframe_bps,
99 const FLAC__Subframe *subframe,
100 FLAC__BitBuffer *frame
101);
102
103static unsigned evaluate_constant_subframe_(
104 const FLAC__int32 signal,
105 unsigned subframe_bps,
106 FLAC__Subframe *subframe
107);
108
109static unsigned evaluate_fixed_subframe_(
110 FLAC__StreamEncoder *encoder,
111 const FLAC__int32 signal[],
112 FLAC__int32 residual[],
113 FLAC__uint32 abs_residual[],
114 FLAC__uint64 abs_residual_partition_sums[],
115 unsigned raw_bits_per_partition[],
116 unsigned blocksize,
117 unsigned subframe_bps,
118 unsigned order,
119 unsigned rice_parameter,
120 unsigned min_partition_order,
121 unsigned max_partition_order,
122 FLAC__bool precompute_partition_sums,
123 FLAC__bool do_escape_coding,
124 unsigned rice_parameter_search_dist,
125 FLAC__Subframe *subframe,
126 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
127);
128
129static unsigned evaluate_lpc_subframe_(
130 FLAC__StreamEncoder *encoder,
131 const FLAC__int32 signal[],
132 FLAC__int32 residual[],
133 FLAC__uint32 abs_residual[],
134 FLAC__uint64 abs_residual_partition_sums[],
135 unsigned raw_bits_per_partition[],
136 const FLAC__real lp_coeff[],
137 unsigned blocksize,
138 unsigned subframe_bps,
139 unsigned order,
140 unsigned qlp_coeff_precision,
141 unsigned rice_parameter,
142 unsigned min_partition_order,
143 unsigned max_partition_order,
144 FLAC__bool precompute_partition_sums,
145 FLAC__bool do_escape_coding,
146 unsigned rice_parameter_search_dist,
147 FLAC__Subframe *subframe,
148 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
149);
150
151static unsigned evaluate_verbatim_subframe_(
152 const FLAC__int32 signal[],
153 unsigned blocksize,
154 unsigned subframe_bps,
155 FLAC__Subframe *subframe
156);
157
158static unsigned find_best_partition_order_(
159 struct FLAC__StreamEncoderPrivate *private_,
160 const FLAC__int32 residual[],
161 FLAC__uint32 abs_residual[],
162 FLAC__uint64 abs_residual_partition_sums[],
163 unsigned raw_bits_per_partition[],
164 unsigned residual_samples,
165 unsigned predictor_order,
166 unsigned rice_parameter,
167 unsigned min_partition_order,
168 unsigned max_partition_order,
169 FLAC__bool precompute_partition_sums,
170 FLAC__bool do_escape_coding,
171 unsigned rice_parameter_search_dist,
172 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
173);
174
175static void precompute_partition_info_sums_(
176 const FLAC__uint32 abs_residual[],
177 FLAC__uint64 abs_residual_partition_sums[],
178 unsigned residual_samples,
179 unsigned predictor_order,
180 unsigned min_partition_order,
181 unsigned max_partition_order
182);
183
184static void precompute_partition_info_escapes_(
185 const FLAC__int32 residual[],
186 unsigned raw_bits_per_partition[],
187 unsigned residual_samples,
188 unsigned predictor_order,
189 unsigned min_partition_order,
190 unsigned max_partition_order
191);
192
Josh Coalson8395d022001-07-12 21:25:22 +0000193#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +0000194static FLAC__bool set_partitioned_rice_(
195 const FLAC__uint32 abs_residual[],
196 const FLAC__int32 residual[],
197 const unsigned residual_samples,
198 const unsigned predictor_order,
199 const unsigned suggested_rice_parameter,
200 const unsigned rice_parameter_search_dist,
201 const unsigned partition_order,
202 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
203 unsigned *bits
204);
205
206static FLAC__bool set_partitioned_rice_with_precompute_(
207 const FLAC__int32 residual[],
208 const FLAC__uint64 abs_residual_partition_sums[],
209 const unsigned raw_bits_per_partition[],
210 const unsigned residual_samples,
211 const unsigned predictor_order,
212 const unsigned suggested_rice_parameter,
213 const unsigned rice_parameter_search_dist,
214 const unsigned partition_order,
215 const FLAC__bool search_for_escapes,
216 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
217 unsigned *bits
218);
Josh Coalson8395d022001-07-12 21:25:22 +0000219#else
Josh Coalson6fe72f72002-08-20 04:01:59 +0000220static FLAC__bool set_partitioned_rice_(
221 const FLAC__uint32 abs_residual[],
222 const unsigned residual_samples,
223 const unsigned predictor_order,
224 const unsigned suggested_rice_parameter,
225 const unsigned rice_parameter_search_dist,
226 const unsigned partition_order,
227 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
228 unsigned *bits
229);
230
231static FLAC__bool set_partitioned_rice_with_precompute_(
232 const FLAC__uint32 abs_residual[],
233 const FLAC__uint64 abs_residual_partition_sums[],
234 const unsigned raw_bits_per_partition[],
235 const unsigned residual_samples,
236 const unsigned predictor_order,
237 const unsigned suggested_rice_parameter,
238 const unsigned rice_parameter_search_dist,
239 const unsigned partition_order,
240 const FLAC__bool search_for_escapes,
241 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
242 unsigned *bits
243);
Josh Coalson0a15c142001-06-13 17:59:57 +0000244#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000245
Josh Coalsonf1eff452002-07-31 07:05:33 +0000246static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples);
Josh Coalson6fe72f72002-08-20 04:01:59 +0000247
Josh Coalsond86e03b2002-08-03 21:56:15 +0000248/* verify-related routines: */
Josh Coalson6fe72f72002-08-20 04:01:59 +0000249static void append_to_verify_fifo_(
250 verify_input_fifo *fifo,
251 const FLAC__int32 * const input[],
252 unsigned input_offset,
253 unsigned channels,
254 unsigned wide_samples
255);
256
257static void append_to_verify_fifo_interleaved_(
258 verify_input_fifo *fifo,
259 const FLAC__int32 input[],
260 unsigned input_offset,
261 unsigned channels,
262 unsigned wide_samples
263);
264
265static FLAC__StreamDecoderReadStatus verify_read_callback_(
266 const FLAC__StreamDecoder *decoder,
267 FLAC__byte buffer[],
268 unsigned *bytes,
269 void *client_data
270);
271
272static FLAC__StreamDecoderWriteStatus verify_write_callback_(
273 const FLAC__StreamDecoder *decoder,
274 const FLAC__Frame *frame,
275 const FLAC__int32 * const buffer[],
276 void *client_data
277);
278
279static void verify_metadata_callback_(
280 const FLAC__StreamDecoder *decoder,
281 const FLAC__StreamMetadata *metadata,
282 void *client_data
283);
284
285static void verify_error_callback_(
286 const FLAC__StreamDecoder *decoder,
287 FLAC__StreamDecoderErrorStatus status,
288 void *client_data
289);
290
Josh Coalson0a15c142001-06-13 17:59:57 +0000291
292/***********************************************************************
293 *
294 * Private class data
295 *
296 ***********************************************************************/
297
298typedef struct FLAC__StreamEncoderPrivate {
Josh Coalson8395d022001-07-12 21:25:22 +0000299 unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */
Josh Coalson77e3f312001-06-23 03:03:24 +0000300 FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */
301 FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */
302 FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* the floating-point version of the input signal */
303 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 +0000304 unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */
305 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 +0000306 FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
307 FLAC__int32 *residual_workspace_mid_side[2][2];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000308 FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
309 FLAC__Subframe subframe_workspace_mid_side[2][2];
310 FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
311 FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
Josh Coalsona37ba462002-08-19 21:36:39 +0000312 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2];
313 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2];
314 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2];
315 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2];
Josh Coalson8395d022001-07-12 21:25:22 +0000316 unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index into the above workspaces */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000317 unsigned best_subframe_mid_side[2];
Josh Coalson8395d022001-07-12 21:25:22 +0000318 unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000319 unsigned best_subframe_bits_mid_side[2];
Josh Coalson77e3f312001-06-23 03:03:24 +0000320 FLAC__uint32 *abs_residual; /* workspace where abs(candidate residual) is stored */
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000321 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 +0000322 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 +0000323 FLAC__BitBuffer *frame; /* the current frame being worked on */
Josh Coalson8395d022001-07-12 21:25:22 +0000324 double loose_mid_side_stereo_frames_exact; /* exact number of frames the encoder will use before trying both independent and mid/side frames again */
325 unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
326 unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000327 FLAC__ChannelAssignment last_channel_assignment;
Josh Coalsoncc682512002-06-08 04:53:42 +0000328 FLAC__StreamMetadata metadata;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000329 unsigned current_sample_number;
330 unsigned current_frame_number;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +0000331 struct MD5Context md5context;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000332 FLAC__CPUInfo cpuinfo;
Josh Coalson77e3f312001-06-23 03:03:24 +0000333 unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
334 void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
335 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[]);
336 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 +0000337 FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */
338 FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */
339 FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */
340 FLAC__bool precompute_partition_sums; /* our initial guess as to whether precomputing the partitions sums will be a speed improvement */
Josh Coalson681c2932002-08-01 08:19:37 +0000341 FLAC__StreamEncoderWriteCallback write_callback;
342 FLAC__StreamEncoderMetadataCallback metadata_callback;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000343 void *client_data;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000344 /* unaligned (original) pointers to allocated data */
Josh Coalson77e3f312001-06-23 03:03:24 +0000345 FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
346 FLAC__int32 *integer_signal_mid_side_unaligned[2];
347 FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
348 FLAC__real *real_signal_mid_side_unaligned[2];
349 FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
350 FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
351 FLAC__uint32 *abs_residual_unaligned;
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000352 FLAC__uint64 *abs_residual_partition_sums_unaligned;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000353 unsigned *raw_bits_per_partition_unaligned;
Josh Coalson8084b052001-11-01 00:27:29 +0000354 /*
355 * These fields have been moved here from private function local
356 * declarations merely to save stack space during encoding.
357 */
Josh Coalsonf1eff452002-07-31 07:05:33 +0000358 FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
Josh Coalsona37ba462002-08-19 21:36:39 +0000359 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000360 /*
361 * The data for the verify section
362 */
363 struct {
364 FLAC__StreamDecoder *decoder;
365 EncoderStateHint state_hint;
366 FLAC__bool needs_magic_hack;
367 verify_input_fifo input_fifo;
368 verify_output output;
369 struct {
370 FLAC__uint64 absolute_sample;
371 unsigned frame_number;
372 unsigned channel;
373 unsigned sample;
374 FLAC__int32 expected;
375 FLAC__int32 got;
376 } error_stats;
377 } verify;
Josh Coalson3262b0d2002-08-14 20:58:42 +0000378 FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
Josh Coalson0a15c142001-06-13 17:59:57 +0000379} FLAC__StreamEncoderPrivate;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000380
Josh Coalson0a15c142001-06-13 17:59:57 +0000381/***********************************************************************
382 *
383 * Public static class data
384 *
385 ***********************************************************************/
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000386
Josh Coalson57ba6f42002-06-07 05:27:37 +0000387const char * const FLAC__StreamEncoderStateString[] = {
Josh Coalson0a15c142001-06-13 17:59:57 +0000388 "FLAC__STREAM_ENCODER_OK",
Josh Coalsond86e03b2002-08-03 21:56:15 +0000389 "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
390 "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
Josh Coalson00e53872001-06-16 07:32:25 +0000391 "FLAC__STREAM_ENCODER_INVALID_CALLBACK",
Josh Coalson0a15c142001-06-13 17:59:57 +0000392 "FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS",
393 "FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE",
394 "FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE",
395 "FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE",
396 "FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION",
397 "FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH",
398 "FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
399 "FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE",
400 "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
401 "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
402 "FLAC__STREAM_ENCODER_FRAMING_ERROR",
Josh Coalson66075c12002-06-01 05:39:38 +0000403 "FLAC__STREAM_ENCODER_INVALID_METADATA",
Josh Coalson0a15c142001-06-13 17:59:57 +0000404 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
405 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
406 "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
407 "FLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
408 "FLAC__STREAM_ENCODER_UNINITIALIZED"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000409};
410
Josh Coalson57ba6f42002-06-07 05:27:37 +0000411const char * const FLAC__StreamEncoderWriteStatusString[] = {
Josh Coalson5c491a12002-08-01 06:39:40 +0000412 "FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
413 "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000414};
415
Josh Coalson0a15c142001-06-13 17:59:57 +0000416/***********************************************************************
417 *
418 * Class constructor/destructor
419 *
Josh Coalsond86e03b2002-08-03 21:56:15 +0000420 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000421FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000422{
Josh Coalson0a15c142001-06-13 17:59:57 +0000423 FLAC__StreamEncoder *encoder;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000424 unsigned i;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000425
Josh Coalson0a15c142001-06-13 17:59:57 +0000426 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000427
Josh Coalson0a15c142001-06-13 17:59:57 +0000428 encoder = (FLAC__StreamEncoder*)malloc(sizeof(FLAC__StreamEncoder));
429 if(encoder == 0) {
430 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000431 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000432 memset(encoder, 0, sizeof(FLAC__StreamEncoder));
433
Josh Coalsonfa697a92001-08-16 20:07:29 +0000434 encoder->protected_ = (FLAC__StreamEncoderProtected*)malloc(sizeof(FLAC__StreamEncoderProtected));
435 if(encoder->protected_ == 0) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000436 free(encoder);
437 return 0;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000438 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000439 memset(encoder->protected_, 0, sizeof(FLAC__StreamEncoderProtected));
440
Josh Coalsonfa697a92001-08-16 20:07:29 +0000441 encoder->private_ = (FLAC__StreamEncoderPrivate*)malloc(sizeof(FLAC__StreamEncoderPrivate));
442 if(encoder->private_ == 0) {
443 free(encoder->protected_);
Josh Coalson0a15c142001-06-13 17:59:57 +0000444 free(encoder);
445 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000446 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000447 memset(encoder->private_, 0, sizeof(FLAC__StreamEncoderPrivate));
448
Josh Coalsonaec256b2002-03-12 16:19:54 +0000449 encoder->private_->frame = FLAC__bitbuffer_new();
450 if(encoder->private_->frame == 0) {
451 free(encoder->private_);
452 free(encoder->protected_);
453 free(encoder);
454 return 0;
455 }
Josh Coalsond98c43d2001-05-13 05:17:01 +0000456
Josh Coalsonf1eff452002-07-31 07:05:33 +0000457 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000458
Josh Coalson3262b0d2002-08-14 20:58:42 +0000459 encoder->private_->is_being_deleted = false;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000460
461 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
462 encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
463 encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
464 }
465 for(i = 0; i < 2; i++) {
466 encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
467 encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
468 }
469 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000470 encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
471 encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000472 }
473 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000474 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
475 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 +0000476 }
477
478 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000479 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
480 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000481 }
482 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000483 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
484 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 +0000485 }
486 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000487 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000488
Josh Coalsonfa697a92001-08-16 20:07:29 +0000489 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000490
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000491 return encoder;
492}
493
Josh Coalson0a15c142001-06-13 17:59:57 +0000494void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000495{
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000496 unsigned i;
497
Josh Coalsonf1eff452002-07-31 07:05:33 +0000498 FLAC__ASSERT(0 != encoder);
499 FLAC__ASSERT(0 != encoder->protected_);
500 FLAC__ASSERT(0 != encoder->private_);
501 FLAC__ASSERT(0 != encoder->private_->frame);
Josh Coalson0a15c142001-06-13 17:59:57 +0000502
Josh Coalson3262b0d2002-08-14 20:58:42 +0000503 encoder->private_->is_being_deleted = true;
504
505 FLAC__stream_encoder_finish(encoder);
506
Josh Coalsond86e03b2002-08-03 21:56:15 +0000507 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
508 FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000509
510 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000511 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
512 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000513 }
514 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000515 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
516 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 +0000517 }
518 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000519 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000520
Josh Coalsonaec256b2002-03-12 16:19:54 +0000521 FLAC__bitbuffer_delete(encoder->private_->frame);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000522 free(encoder->private_);
523 free(encoder->protected_);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000524 free(encoder);
525}
526
Josh Coalson0a15c142001-06-13 17:59:57 +0000527/***********************************************************************
528 *
529 * Public class methods
530 *
531 ***********************************************************************/
532
Josh Coalson00e53872001-06-16 07:32:25 +0000533FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000534{
535 unsigned i;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000536 FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000537
Josh Coalsonf1eff452002-07-31 07:05:33 +0000538 FLAC__ASSERT(0 != encoder);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000539
Josh Coalsonfa697a92001-08-16 20:07:29 +0000540 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
541 return encoder->protected_->state = FLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000542
Josh Coalsonfa697a92001-08-16 20:07:29 +0000543 encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000544
Josh Coalsonfa697a92001-08-16 20:07:29 +0000545 if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
546 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_CALLBACK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000547
Josh Coalsonfa697a92001-08-16 20:07:29 +0000548 if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
549 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson69f1ee02001-01-24 00:54:43 +0000550
Josh Coalsonfa697a92001-08-16 20:07:29 +0000551 if(encoder->protected_->do_mid_side_stereo && encoder->protected_->channels != 2)
552 return encoder->protected_->state = FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH;
Josh Coalsond37d1352001-05-30 23:09:31 +0000553
Josh Coalsonfa697a92001-08-16 20:07:29 +0000554 if(encoder->protected_->loose_mid_side_stereo && !encoder->protected_->do_mid_side_stereo)
555 return encoder->protected_->state = FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000556
Josh Coalsonfa697a92001-08-16 20:07:29 +0000557 if(encoder->protected_->bits_per_sample >= 32)
558 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 +0000559
Josh Coalson76c68bc2002-05-17 06:22:02 +0000560 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 +0000561 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000562
Josh Coalson0833f342002-07-15 05:31:55 +0000563 if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000564 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000565
Josh Coalsonfa697a92001-08-16 20:07:29 +0000566 if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
567 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE;
Josh Coalson0a15c142001-06-13 17:59:57 +0000568
Josh Coalsonfa697a92001-08-16 20:07:29 +0000569 if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
570 return encoder->protected_->state = FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
Josh Coalson0a15c142001-06-13 17:59:57 +0000571
Josh Coalsonfa697a92001-08-16 20:07:29 +0000572 if(encoder->protected_->qlp_coeff_precision == 0) {
573 if(encoder->protected_->bits_per_sample < 16) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000574 /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
575 /* @@@ until then we'll make a guess */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000576 encoder->protected_->qlp_coeff_precision = max(5, 2 + encoder->protected_->bits_per_sample / 2);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000577 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000578 else if(encoder->protected_->bits_per_sample == 16) {
579 if(encoder->protected_->blocksize <= 192)
580 encoder->protected_->qlp_coeff_precision = 7;
581 else if(encoder->protected_->blocksize <= 384)
582 encoder->protected_->qlp_coeff_precision = 8;
583 else if(encoder->protected_->blocksize <= 576)
584 encoder->protected_->qlp_coeff_precision = 9;
585 else if(encoder->protected_->blocksize <= 1152)
586 encoder->protected_->qlp_coeff_precision = 10;
587 else if(encoder->protected_->blocksize <= 2304)
588 encoder->protected_->qlp_coeff_precision = 11;
589 else if(encoder->protected_->blocksize <= 4608)
590 encoder->protected_->qlp_coeff_precision = 12;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000591 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000592 encoder->protected_->qlp_coeff_precision = 13;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000593 }
594 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000595 encoder->protected_->qlp_coeff_precision = min(13, 8*sizeof(FLAC__int32) - encoder->protected_->bits_per_sample - 1 - 2); /* @@@ -2 to keep things 32-bit safe */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000596 }
597 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000598 else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision + encoder->protected_->bits_per_sample >= 8*sizeof(FLAC__uint32) || encoder->protected_->qlp_coeff_precision >= (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
599 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000600
Josh Coalsonfa697a92001-08-16 20:07:29 +0000601 if(encoder->protected_->streamable_subset) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000602 /*@@@ add check for blocksize here */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000603 if(encoder->protected_->bits_per_sample != 8 && encoder->protected_->bits_per_sample != 12 && encoder->protected_->bits_per_sample != 16 && encoder->protected_->bits_per_sample != 20 && encoder->protected_->bits_per_sample != 24)
604 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
605 if(encoder->protected_->sample_rate > 655350)
606 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000607 }
608
Josh Coalsonfa697a92001-08-16 20:07:29 +0000609 if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
610 encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
611 if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
612 encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000613
Josh Coalson66075c12002-06-01 05:39:38 +0000614 /* validate metadata */
615 if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
616 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000617 metadata_has_seektable = false;
618 metadata_has_vorbis_comment = false;
Josh Coalson66075c12002-06-01 05:39:38 +0000619 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
620 if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
621 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
622 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000623 if(metadata_has_seektable) /* only one is allowed */
624 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
625 metadata_has_seektable = true;
Josh Coalson0833f342002-07-15 05:31:55 +0000626 if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table))
Josh Coalson66075c12002-06-01 05:39:38 +0000627 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
628 }
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000629 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
630 if(metadata_has_vorbis_comment) /* only one is allowed */
631 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
632 metadata_has_vorbis_comment = true;
633 }
Josh Coalson66075c12002-06-01 05:39:38 +0000634 }
635
Josh Coalsonfa697a92001-08-16 20:07:29 +0000636 encoder->private_->input_capacity = 0;
637 for(i = 0; i < encoder->protected_->channels; i++) {
638 encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
639 encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000640 }
641 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000642 encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
643 encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000644 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000645 for(i = 0; i < encoder->protected_->channels; i++) {
646 encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
647 encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
648 encoder->private_->best_subframe[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000649 }
650 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000651 encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
652 encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
653 encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000654 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000655 encoder->private_->abs_residual_unaligned = encoder->private_->abs_residual = 0;
656 encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
657 encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
658 encoder->private_->loose_mid_side_stereo_frames_exact = (double)encoder->protected_->sample_rate * 0.4 / (double)encoder->protected_->blocksize;
659 encoder->private_->loose_mid_side_stereo_frames = (unsigned)(encoder->private_->loose_mid_side_stereo_frames_exact + 0.5);
660 if(encoder->private_->loose_mid_side_stereo_frames == 0)
661 encoder->private_->loose_mid_side_stereo_frames = 1;
662 encoder->private_->loose_mid_side_stereo_frame_count = 0;
663 encoder->private_->current_sample_number = 0;
664 encoder->private_->current_frame_number = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000665
Josh Coalsonfa697a92001-08-16 20:07:29 +0000666 encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
667 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? */
668 encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
Josh Coalson8395d022001-07-12 21:25:22 +0000669
Josh Coalsoncf30f502001-05-23 20:57:44 +0000670 /*
671 * get the CPU info and set the function pointers
672 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000673 FLAC__cpu_info(&encoder->private_->cpuinfo);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000674 /* first default to the non-asm routines */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000675 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
676 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
677 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
678 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000679 /* now override with asm where appropriate */
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000680#ifndef FLAC__NO_ASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000681 if(encoder->private_->cpuinfo.use_asm) {
Josh Coalsoncf30f502001-05-23 20:57:44 +0000682#ifdef FLAC__CPU_IA32
Josh Coalsonfa697a92001-08-16 20:07:29 +0000683 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
Josh Coalson034d38e2001-05-24 19:29:30 +0000684#ifdef FLAC__HAS_NASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000685 if(0 && encoder->private_->cpuinfo.data.ia32.sse) {
686 if(encoder->protected_->max_lpc_order < 4)
687 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
688 else if(encoder->protected_->max_lpc_order < 8)
689 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
690 else if(encoder->protected_->max_lpc_order < 12)
691 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000692 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000693 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000694 }
Josh Coalson395938e2001-11-15 21:53:25 +0000695 else if(encoder->private_->cpuinfo.data.ia32._3dnow)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000696 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
Josh Coalsonaa255362001-05-31 06:17:41 +0000697 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000698 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
699 if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
700 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
701 if(encoder->private_->cpuinfo.data.ia32.mmx) {
702 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
703 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 +0000704 }
705 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000706 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
707 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 +0000708 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000709#endif
Josh Coalson034d38e2001-05-24 19:29:30 +0000710#endif
Josh Coalson021ad3b2001-07-18 00:25:52 +0000711 }
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000712#endif
Josh Coalson8395d022001-07-12 21:25:22 +0000713 /* finally override based on wide-ness if necessary */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000714 if(encoder->private_->use_wide_by_block) {
715 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
Josh Coalson8395d022001-07-12 21:25:22 +0000716 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000717
Josh Coalson8395d022001-07-12 21:25:22 +0000718 /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000719 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 +0000720
Josh Coalsonf1eff452002-07-31 07:05:33 +0000721 if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000722 /* the above function sets the state for us in case of an error */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000723 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000724 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000725
726 if(!FLAC__bitbuffer_init(encoder->private_->frame))
727 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000728
729 /*
Josh Coalsond86e03b2002-08-03 21:56:15 +0000730 * Set up the verify stuff if necessary
731 */
732 if(encoder->protected_->verify) {
733 /*
734 * First, set up the fifo which will hold the
735 * original signal to compare against
736 */
737 encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize;
738 for(i = 0; i < encoder->protected_->channels; i++) {
739 if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size)))
740 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
741 }
742 encoder->private_->verify.input_fifo.tail = 0;
743
744 /*
745 * Now set up a stream decoder for verification
746 */
747 encoder->private_->verify.decoder = FLAC__stream_decoder_new();
748 if(0 == encoder->private_->verify.decoder)
749 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
750
751 FLAC__stream_decoder_set_read_callback(encoder->private_->verify.decoder, verify_read_callback_);
752 FLAC__stream_decoder_set_write_callback(encoder->private_->verify.decoder, verify_write_callback_);
753 FLAC__stream_decoder_set_metadata_callback(encoder->private_->verify.decoder, verify_metadata_callback_);
754 FLAC__stream_decoder_set_error_callback(encoder->private_->verify.decoder, verify_error_callback_);
755 FLAC__stream_decoder_set_client_data(encoder->private_->verify.decoder, encoder);
756 if(FLAC__stream_decoder_init(encoder->private_->verify.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
757 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
758 }
Josh Coalson589f8c72002-08-07 23:54:55 +0000759 encoder->private_->verify.error_stats.absolute_sample = 0;
760 encoder->private_->verify.error_stats.frame_number = 0;
761 encoder->private_->verify.error_stats.channel = 0;
762 encoder->private_->verify.error_stats.sample = 0;
763 encoder->private_->verify.error_stats.expected = 0;
764 encoder->private_->verify.error_stats.got = 0;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000765
766 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000767 * write the stream header
768 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000769 if(encoder->protected_->verify)
770 encoder->private_->verify.state_hint = ENCODER_IN_MAGIC;
Josh Coalsonaec256b2002-03-12 16:19:54 +0000771 if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000772 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000773 if(!write_bitbuffer_(encoder, 0)) {
774 /* the above function sets the state for us in case of an error */
775 return encoder->protected_->state;
776 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000777
Josh Coalson5c491a12002-08-01 06:39:40 +0000778 /*
779 * write the STREAMINFO metadata block
780 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000781 if(encoder->protected_->verify)
782 encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000783 encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000784 encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000785 encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
786 encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
787 encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
788 encoder->private_->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
789 encoder->private_->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
790 encoder->private_->metadata.data.stream_info.sample_rate = encoder->protected_->sample_rate;
791 encoder->private_->metadata.data.stream_info.channels = encoder->protected_->channels;
792 encoder->private_->metadata.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
793 encoder->private_->metadata.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
794 memset(encoder->private_->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
795 MD5Init(&encoder->private_->md5context);
Josh Coalson5c491a12002-08-01 06:39:40 +0000796 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
797 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
798 return false;
799 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000800 if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000801 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000802 if(!write_bitbuffer_(encoder, 0)) {
803 /* the above function sets the state for us in case of an error */
804 return encoder->protected_->state;
805 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000806
Josh Coalson5c491a12002-08-01 06:39:40 +0000807 /*
808 * Now that the STREAMINFO block is written, we can init this to an
809 * absurdly-high value...
810 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000811 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 +0000812 /* ... and clear this to 0 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000813 encoder->private_->metadata.data.stream_info.total_samples = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000814
Josh Coalson5c491a12002-08-01 06:39:40 +0000815 /*
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000816 * Check to see if the supplied metadata contains a VORBIS_COMMENT;
817 * if not, we will write an empty one (FLAC__add_metadata_block()
818 * automatically supplies the vendor string).
819 */
820 if(!metadata_has_vorbis_comment) {
821 FLAC__StreamMetadata vorbis_comment;
822 vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
823 vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0);
824 vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */
825 vorbis_comment.data.vorbis_comment.vendor_string.length = 0;
826 vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
827 vorbis_comment.data.vorbis_comment.num_comments = 0;
828 vorbis_comment.data.vorbis_comment.comments = 0;
829 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
830 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
831 return false;
832 }
833 if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame))
834 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
835 if(!write_bitbuffer_(encoder, 0)) {
836 /* the above function sets the state for us in case of an error */
837 return encoder->protected_->state;
838 }
839 }
840
841 /*
Josh Coalson5c491a12002-08-01 06:39:40 +0000842 * write the user's metadata blocks
843 */
844 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
845 encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
846 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
847 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
848 return false;
849 }
850 if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame))
851 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000852 if(!write_bitbuffer_(encoder, 0)) {
853 /* the above function sets the state for us in case of an error */
854 return encoder->protected_->state;
855 }
Josh Coalson5c491a12002-08-01 06:39:40 +0000856 }
857
Josh Coalsond86e03b2002-08-03 21:56:15 +0000858 if(encoder->protected_->verify)
859 encoder->private_->verify.state_hint = ENCODER_IN_AUDIO;
860
Josh Coalsonfa697a92001-08-16 20:07:29 +0000861 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000862}
863
Josh Coalson0a15c142001-06-13 17:59:57 +0000864void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000865{
Josh Coalsonf1eff452002-07-31 07:05:33 +0000866 FLAC__ASSERT(0 != encoder);
Josh Coalson2b245f22002-08-07 17:10:50 +0000867
Josh Coalsonfa697a92001-08-16 20:07:29 +0000868 if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000869 return;
Josh Coalson2b245f22002-08-07 17:10:50 +0000870
Josh Coalson3262b0d2002-08-14 20:58:42 +0000871 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000872 if(encoder->private_->current_sample_number != 0) {
873 encoder->protected_->blocksize = encoder->private_->current_sample_number;
874 process_frame_(encoder, true); /* true => is last frame */
875 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000876 }
Josh Coalson2b245f22002-08-07 17:10:50 +0000877
Josh Coalsonfa697a92001-08-16 20:07:29 +0000878 MD5Final(encoder->private_->metadata.data.stream_info.md5sum, &encoder->private_->md5context);
Josh Coalson2b245f22002-08-07 17:10:50 +0000879
Josh Coalson3262b0d2002-08-14 20:58:42 +0000880 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000881 encoder->private_->metadata_callback(encoder, &encoder->private_->metadata, encoder->private_->client_data);
882 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000883
Josh Coalsond86e03b2002-08-03 21:56:15 +0000884 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
885 FLAC__stream_decoder_finish(encoder->private_->verify.decoder);
886
Josh Coalsonf1eff452002-07-31 07:05:33 +0000887 free_(encoder);
888 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000889
Josh Coalsonfa697a92001-08-16 20:07:29 +0000890 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000891}
892
Josh Coalsond86e03b2002-08-03 21:56:15 +0000893FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)
894{
895 FLAC__ASSERT(0 != encoder);
896 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
897 return false;
898 encoder->protected_->verify = value;
899 return true;
900}
901
Josh Coalson16556042002-05-29 05:51:24 +0000902FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000903{
Josh Coalson92031602002-07-24 06:02:11 +0000904 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000905 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000906 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000907 encoder->protected_->streamable_subset = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000908 return true;
909}
910
Josh Coalson16556042002-05-29 05:51:24 +0000911FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000912{
Josh Coalson92031602002-07-24 06:02:11 +0000913 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000914 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000915 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000916 encoder->protected_->do_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000917 return true;
918}
919
Josh Coalson16556042002-05-29 05:51:24 +0000920FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000921{
Josh Coalson92031602002-07-24 06:02:11 +0000922 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000923 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000924 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000925 encoder->protected_->loose_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000926 return true;
927}
928
Josh Coalson16556042002-05-29 05:51:24 +0000929FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000930{
Josh Coalson92031602002-07-24 06:02:11 +0000931 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000932 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000933 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000934 encoder->protected_->channels = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000935 return true;
936}
937
Josh Coalson16556042002-05-29 05:51:24 +0000938FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000939{
Josh Coalson92031602002-07-24 06:02:11 +0000940 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000941 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000942 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000943 encoder->protected_->bits_per_sample = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000944 return true;
945}
946
Josh Coalson16556042002-05-29 05:51:24 +0000947FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000948{
Josh Coalson92031602002-07-24 06:02:11 +0000949 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000950 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000951 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000952 encoder->protected_->sample_rate = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000953 return true;
954}
955
Josh Coalson16556042002-05-29 05:51:24 +0000956FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000957{
Josh Coalson92031602002-07-24 06:02:11 +0000958 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000959 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000960 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000961 encoder->protected_->blocksize = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000962 return true;
963}
964
Josh Coalson16556042002-05-29 05:51:24 +0000965FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000966{
Josh Coalson92031602002-07-24 06:02:11 +0000967 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000968 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000969 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000970 encoder->protected_->max_lpc_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000971 return true;
972}
973
Josh Coalson16556042002-05-29 05:51:24 +0000974FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000975{
Josh Coalson92031602002-07-24 06:02:11 +0000976 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000977 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000978 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000979 encoder->protected_->qlp_coeff_precision = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000980 return true;
981}
982
Josh Coalson16556042002-05-29 05:51:24 +0000983FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000984{
Josh Coalson92031602002-07-24 06:02:11 +0000985 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000986 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000987 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000988 encoder->protected_->do_qlp_coeff_prec_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000989 return true;
990}
991
Josh Coalson16556042002-05-29 05:51:24 +0000992FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson8395d022001-07-12 21:25:22 +0000993{
Josh Coalson92031602002-07-24 06:02:11 +0000994 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000995 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson8395d022001-07-12 21:25:22 +0000996 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +0000997#if 0
998 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000999 encoder->protected_->do_escape_coding = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001000#else
1001 (void)value;
1002#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001003 return true;
1004}
1005
Josh Coalson16556042002-05-29 05:51:24 +00001006FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001007{
Josh Coalson92031602002-07-24 06:02:11 +00001008 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001009 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001010 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001011 encoder->protected_->do_exhaustive_model_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001012 return true;
1013}
1014
Josh Coalson16556042002-05-29 05:51:24 +00001015FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001016{
Josh Coalson92031602002-07-24 06:02:11 +00001017 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001018 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001019 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001020 encoder->protected_->min_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001021 return true;
1022}
1023
Josh Coalson16556042002-05-29 05:51:24 +00001024FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001025{
Josh Coalson92031602002-07-24 06:02:11 +00001026 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001027 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001028 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001029 encoder->protected_->max_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001030 return true;
1031}
1032
Josh Coalson16556042002-05-29 05:51:24 +00001033FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001034{
Josh Coalson92031602002-07-24 06:02:11 +00001035 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001036 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001037 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001038#if 0
1039 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001040 encoder->protected_->rice_parameter_search_dist = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001041#else
1042 (void)value;
1043#endif
Josh Coalson00e53872001-06-16 07:32:25 +00001044 return true;
1045}
1046
Josh Coalson16556042002-05-29 05:51:24 +00001047FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)
Josh Coalson00e53872001-06-16 07:32:25 +00001048{
Josh Coalson92031602002-07-24 06:02:11 +00001049 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001050 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001051 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001052 encoder->protected_->total_samples_estimate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001053 return true;
1054}
1055
Josh Coalsoncc682512002-06-08 04:53:42 +00001056FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
Josh Coalson00e53872001-06-16 07:32:25 +00001057{
Josh Coalson92031602002-07-24 06:02:11 +00001058 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001059 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001060 return false;
Josh Coalson66075c12002-06-01 05:39:38 +00001061 encoder->protected_->metadata = metadata;
1062 encoder->protected_->num_metadata_blocks = num_blocks;
Josh Coalson00e53872001-06-16 07:32:25 +00001063 return true;
1064}
1065
Josh Coalson681c2932002-08-01 08:19:37 +00001066FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001067{
Josh Coalson92031602002-07-24 06:02:11 +00001068 FLAC__ASSERT(0 != encoder);
1069 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001070 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001071 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001072 encoder->private_->write_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001073 return true;
1074}
1075
Josh Coalson681c2932002-08-01 08:19:37 +00001076FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderMetadataCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001077{
Josh Coalson92031602002-07-24 06:02:11 +00001078 FLAC__ASSERT(0 != encoder);
1079 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001080 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001081 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001082 encoder->private_->metadata_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001083 return true;
1084}
1085
Josh Coalson16556042002-05-29 05:51:24 +00001086FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value)
Josh Coalson00e53872001-06-16 07:32:25 +00001087{
Josh Coalson92031602002-07-24 06:02:11 +00001088 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001089 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001090 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001091 encoder->private_->client_data = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001092 return true;
1093}
1094
1095FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001096{
Josh Coalson92031602002-07-24 06:02:11 +00001097 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001098 return encoder->protected_->state;
Josh Coalson0a15c142001-06-13 17:59:57 +00001099}
1100
Josh Coalsond86e03b2002-08-03 21:56:15 +00001101FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder)
1102{
1103 FLAC__ASSERT(0 != encoder);
1104 if(encoder->protected_->verify)
1105 return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder);
1106 else
1107 return FLAC__STREAM_DECODER_UNINITIALIZED;
1108}
1109
Josh Coalson589f8c72002-08-07 23:54:55 +00001110void 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)
1111{
1112 FLAC__ASSERT(0 != encoder);
1113 if(0 != absolute_sample)
1114 *absolute_sample = encoder->private_->verify.error_stats.absolute_sample;
1115 if(0 != frame_number)
1116 *frame_number = encoder->private_->verify.error_stats.frame_number;
1117 if(0 != channel)
1118 *channel = encoder->private_->verify.error_stats.channel;
1119 if(0 != sample)
1120 *sample = encoder->private_->verify.error_stats.sample;
1121 if(0 != expected)
1122 *expected = encoder->private_->verify.error_stats.expected;
1123 if(0 != got)
1124 *got = encoder->private_->verify.error_stats.got;
1125}
1126
Josh Coalsond86e03b2002-08-03 21:56:15 +00001127FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder)
1128{
1129 FLAC__ASSERT(0 != encoder);
1130 return encoder->protected_->verify;
1131}
1132
Josh Coalson77e3f312001-06-23 03:03:24 +00001133FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001134{
Josh Coalson92031602002-07-24 06:02:11 +00001135 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001136 return encoder->protected_->streamable_subset;
Josh Coalson0a15c142001-06-13 17:59:57 +00001137}
1138
Josh Coalson77e3f312001-06-23 03:03:24 +00001139FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001140{
Josh Coalson92031602002-07-24 06:02:11 +00001141 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001142 return encoder->protected_->do_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001143}
1144
Josh Coalson77e3f312001-06-23 03:03:24 +00001145FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001146{
Josh Coalson92031602002-07-24 06:02:11 +00001147 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001148 return encoder->protected_->loose_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001149}
1150
Josh Coalson00e53872001-06-16 07:32:25 +00001151unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001152{
Josh Coalson92031602002-07-24 06:02:11 +00001153 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001154 return encoder->protected_->channels;
Josh Coalson0a15c142001-06-13 17:59:57 +00001155}
1156
Josh Coalson00e53872001-06-16 07:32:25 +00001157unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001158{
Josh Coalson92031602002-07-24 06:02:11 +00001159 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001160 return encoder->protected_->bits_per_sample;
Josh Coalson0a15c142001-06-13 17:59:57 +00001161}
1162
Josh Coalson00e53872001-06-16 07:32:25 +00001163unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001164{
Josh Coalson92031602002-07-24 06:02:11 +00001165 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001166 return encoder->protected_->sample_rate;
Josh Coalson0a15c142001-06-13 17:59:57 +00001167}
1168
Josh Coalson00e53872001-06-16 07:32:25 +00001169unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001170{
Josh Coalson92031602002-07-24 06:02:11 +00001171 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001172 return encoder->protected_->blocksize;
Josh Coalson0a15c142001-06-13 17:59:57 +00001173}
1174
Josh Coalson00e53872001-06-16 07:32:25 +00001175unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001176{
Josh Coalson92031602002-07-24 06:02:11 +00001177 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001178 return encoder->protected_->max_lpc_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001179}
1180
Josh Coalson00e53872001-06-16 07:32:25 +00001181unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001182{
Josh Coalson92031602002-07-24 06:02:11 +00001183 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001184 return encoder->protected_->qlp_coeff_precision;
Josh Coalson0a15c142001-06-13 17:59:57 +00001185}
1186
Josh Coalson77e3f312001-06-23 03:03:24 +00001187FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001188{
Josh Coalson92031602002-07-24 06:02:11 +00001189 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001190 return encoder->protected_->do_qlp_coeff_prec_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001191}
1192
Josh Coalson8395d022001-07-12 21:25:22 +00001193FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder)
1194{
Josh Coalson92031602002-07-24 06:02:11 +00001195 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001196 return encoder->protected_->do_escape_coding;
Josh Coalson8395d022001-07-12 21:25:22 +00001197}
1198
Josh Coalson77e3f312001-06-23 03:03:24 +00001199FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001200{
Josh Coalson92031602002-07-24 06:02:11 +00001201 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001202 return encoder->protected_->do_exhaustive_model_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001203}
1204
Josh Coalson00e53872001-06-16 07:32:25 +00001205unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001206{
Josh Coalson92031602002-07-24 06:02:11 +00001207 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001208 return encoder->protected_->min_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001209}
1210
Josh Coalson00e53872001-06-16 07:32:25 +00001211unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001212{
Josh Coalson92031602002-07-24 06:02:11 +00001213 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001214 return encoder->protected_->max_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001215}
1216
Josh Coalson00e53872001-06-16 07:32:25 +00001217unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001218{
Josh Coalson92031602002-07-24 06:02:11 +00001219 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001220 return encoder->protected_->rice_parameter_search_dist;
Josh Coalson0a15c142001-06-13 17:59:57 +00001221}
1222
Josh Coalson3a7b2c92002-08-02 07:38:20 +00001223FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder)
1224{
1225 FLAC__ASSERT(0 != encoder);
1226 return encoder->protected_->total_samples_estimate;
1227}
1228
Josh Coalson57ba6f42002-06-07 05:27:37 +00001229FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001230{
1231 unsigned i, j, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001232 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001233 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001234
Josh Coalsonf1eff452002-07-31 07:05:33 +00001235 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001236 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001237
1238 j = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001239 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001240 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001241 if(encoder->protected_->verify)
1242 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1243
Josh Coalsonfa697a92001-08-16 20:07:29 +00001244 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001245 x = mid = side = buffer[0][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001246 encoder->private_->integer_signal[0][i] = x;
1247 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001248 x = buffer[1][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001249 encoder->private_->integer_signal[1][i] = x;
1250 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001251 mid += x;
1252 side -= x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001253 mid >>= 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001254 encoder->private_->integer_signal_mid_side[1][i] = side;
1255 encoder->private_->integer_signal_mid_side[0][i] = mid;
1256 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1257 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1258 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001259 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001260 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001261 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001262 return false;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001263 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001264 } while(j < samples);
1265 }
1266 else {
1267 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001268 if(encoder->protected_->verify)
1269 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1270
Josh Coalsonfa697a92001-08-16 20:07:29 +00001271 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001272 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001273 x = buffer[channel][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001274 encoder->private_->integer_signal[channel][i] = x;
1275 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001276 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001277 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001278 }
1279 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001280 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001281 return false;
1282 }
1283 } while(j < samples);
1284 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001285
1286 return true;
1287}
1288
Josh Coalson57ba6f42002-06-07 05:27:37 +00001289FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001290{
1291 unsigned i, j, k, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001292 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001293 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001294
Josh Coalsonf1eff452002-07-31 07:05:33 +00001295 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001296 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001297
1298 j = k = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001299 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001300 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001301 if(encoder->protected_->verify)
1302 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1303
Josh Coalsonfa697a92001-08-16 20:07:29 +00001304 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001305 x = mid = side = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001306 encoder->private_->integer_signal[0][i] = x;
1307 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001308 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001309 encoder->private_->integer_signal[1][i] = x;
1310 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001311 mid += x;
1312 side -= x;
1313 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001314 encoder->private_->integer_signal_mid_side[1][i] = side;
1315 encoder->private_->integer_signal_mid_side[0][i] = mid;
1316 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1317 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1318 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001319 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001320 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001321 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001322 return false;
1323 }
1324 } while(j < samples);
1325 }
1326 else {
1327 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001328 if(encoder->protected_->verify)
1329 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1330
Josh Coalsonfa697a92001-08-16 20:07:29 +00001331 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001332 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001333 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001334 encoder->private_->integer_signal[channel][i] = x;
1335 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001336 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001337 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001338 }
1339 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001340 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001341 return false;
1342 }
1343 } while(j < samples);
1344 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001345
1346 return true;
1347}
1348
Josh Coalsonf1eff452002-07-31 07:05:33 +00001349/***********************************************************************
1350 *
1351 * Private class methods
1352 *
1353 ***********************************************************************/
1354
1355void set_defaults_(FLAC__StreamEncoder *encoder)
Josh Coalson92031602002-07-24 06:02:11 +00001356{
1357 FLAC__ASSERT(0 != encoder);
1358
Josh Coalsond86e03b2002-08-03 21:56:15 +00001359 encoder->protected_->verify = false;
Josh Coalson92031602002-07-24 06:02:11 +00001360 encoder->protected_->streamable_subset = true;
1361 encoder->protected_->do_mid_side_stereo = false;
1362 encoder->protected_->loose_mid_side_stereo = false;
1363 encoder->protected_->channels = 2;
1364 encoder->protected_->bits_per_sample = 16;
1365 encoder->protected_->sample_rate = 44100;
1366 encoder->protected_->blocksize = 1152;
1367 encoder->protected_->max_lpc_order = 0;
1368 encoder->protected_->qlp_coeff_precision = 0;
1369 encoder->protected_->do_qlp_coeff_prec_search = false;
1370 encoder->protected_->do_exhaustive_model_search = false;
1371 encoder->protected_->do_escape_coding = false;
1372 encoder->protected_->min_residual_partition_order = 0;
1373 encoder->protected_->max_residual_partition_order = 0;
1374 encoder->protected_->rice_parameter_search_dist = 0;
1375 encoder->protected_->total_samples_estimate = 0;
1376 encoder->protected_->metadata = 0;
1377 encoder->protected_->num_metadata_blocks = 0;
1378
1379 encoder->private_->write_callback = 0;
1380 encoder->private_->metadata_callback = 0;
1381 encoder->private_->client_data = 0;
1382}
1383
Josh Coalsonf1eff452002-07-31 07:05:33 +00001384void free_(FLAC__StreamEncoder *encoder)
Josh Coalson639aeb02002-07-25 05:38:23 +00001385{
1386 unsigned i, channel;
1387
Josh Coalsonf1eff452002-07-31 07:05:33 +00001388 FLAC__ASSERT(0 != encoder);
Josh Coalson639aeb02002-07-25 05:38:23 +00001389 for(i = 0; i < encoder->protected_->channels; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001390 if(0 != encoder->private_->integer_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001391 free(encoder->private_->integer_signal_unaligned[i]);
1392 encoder->private_->integer_signal_unaligned[i] = 0;
1393 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001394 if(0 != encoder->private_->real_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001395 free(encoder->private_->real_signal_unaligned[i]);
1396 encoder->private_->real_signal_unaligned[i] = 0;
1397 }
1398 }
1399 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001400 if(0 != encoder->private_->integer_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001401 free(encoder->private_->integer_signal_mid_side_unaligned[i]);
1402 encoder->private_->integer_signal_mid_side_unaligned[i] = 0;
1403 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001404 if(0 != encoder->private_->real_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001405 free(encoder->private_->real_signal_mid_side_unaligned[i]);
1406 encoder->private_->real_signal_mid_side_unaligned[i] = 0;
1407 }
1408 }
1409 for(channel = 0; channel < encoder->protected_->channels; channel++) {
1410 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001411 if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001412 free(encoder->private_->residual_workspace_unaligned[channel][i]);
1413 encoder->private_->residual_workspace_unaligned[channel][i] = 0;
1414 }
1415 }
1416 }
1417 for(channel = 0; channel < 2; channel++) {
1418 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001419 if(0 != encoder->private_->residual_workspace_mid_side_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001420 free(encoder->private_->residual_workspace_mid_side_unaligned[channel][i]);
1421 encoder->private_->residual_workspace_mid_side_unaligned[channel][i] = 0;
1422 }
1423 }
1424 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001425 if(0 != encoder->private_->abs_residual_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001426 free(encoder->private_->abs_residual_unaligned);
1427 encoder->private_->abs_residual_unaligned = 0;
1428 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001429 if(0 != encoder->private_->abs_residual_partition_sums_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001430 free(encoder->private_->abs_residual_partition_sums_unaligned);
1431 encoder->private_->abs_residual_partition_sums_unaligned = 0;
1432 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001433 if(0 != encoder->private_->raw_bits_per_partition_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001434 free(encoder->private_->raw_bits_per_partition_unaligned);
1435 encoder->private_->raw_bits_per_partition_unaligned = 0;
1436 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001437 if(encoder->protected_->verify) {
1438 for(i = 0; i < encoder->protected_->channels; i++) {
1439 if(0 != encoder->private_->verify.input_fifo.data[i]) {
1440 free(encoder->private_->verify.input_fifo.data[i]);
1441 encoder->private_->verify.input_fifo.data[i] = 0;
1442 }
1443 }
1444 }
Josh Coalson639aeb02002-07-25 05:38:23 +00001445 FLAC__bitbuffer_free(encoder->private_->frame);
1446}
1447
Josh Coalsonf1eff452002-07-31 07:05:33 +00001448FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001449{
Josh Coalson77e3f312001-06-23 03:03:24 +00001450 FLAC__bool ok;
Josh Coalson0a15c142001-06-13 17:59:57 +00001451 unsigned i, channel;
1452
1453 FLAC__ASSERT(new_size > 0);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001454 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
1455 FLAC__ASSERT(encoder->private_->current_sample_number == 0);
Josh Coalson0a15c142001-06-13 17:59:57 +00001456
1457 /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001458 if(new_size <= encoder->private_->input_capacity)
Josh Coalson0a15c142001-06-13 17:59:57 +00001459 return true;
1460
1461 ok = true;
Josh Coalson8395d022001-07-12 21:25:22 +00001462
1463 /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx() requires that the input arrays (in our case the integer signals) have a buffer of up to 3 zeroes in front (at negative indices) for alignment purposes; we use 4 to keep the data well-aligned. */
1464
Josh Coalsonfa697a92001-08-16 20:07:29 +00001465 for(i = 0; ok && i < encoder->protected_->channels; i++) {
1466 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size+4, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]);
1467 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]);
1468 memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4);
1469 encoder->private_->integer_signal[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001470 }
1471 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001472 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]);
1473 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]);
1474 memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4);
1475 encoder->private_->integer_signal_mid_side[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001476 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001477 for(channel = 0; ok && channel < encoder->protected_->channels; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001478 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001479 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 +00001480 }
1481 }
1482 for(channel = 0; ok && channel < 2; channel++) {
1483 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001484 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 +00001485 }
1486 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001487 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->private_->abs_residual_unaligned, &encoder->private_->abs_residual);
1488 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 */
1489 ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_size * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums);
1490 if(encoder->protected_->do_escape_coding)
1491 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 +00001492
1493 if(ok)
Josh Coalsonfa697a92001-08-16 20:07:29 +00001494 encoder->private_->input_capacity = new_size;
Josh Coalson0a15c142001-06-13 17:59:57 +00001495 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00001496 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson0a15c142001-06-13 17:59:57 +00001497
1498 return ok;
1499}
1500
Josh Coalsond86e03b2002-08-03 21:56:15 +00001501FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
Josh Coalson5c491a12002-08-01 06:39:40 +00001502{
1503 const FLAC__byte *buffer;
1504 unsigned bytes;
1505
1506 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1507
1508 FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
1509
Josh Coalsond86e03b2002-08-03 21:56:15 +00001510 if(encoder->protected_->verify) {
1511 encoder->private_->verify.output.data = buffer;
1512 encoder->private_->verify.output.bytes = bytes;
1513 if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) {
1514 encoder->private_->verify.needs_magic_hack = true;
1515 }
1516 else {
1517 if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) {
1518 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1519 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
1520 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
1521 return false;
1522 }
1523 }
1524 }
1525
1526 if(encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
1527 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
Josh Coalson5c491a12002-08-01 06:39:40 +00001528 return false;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001529 }
Josh Coalson5c491a12002-08-01 06:39:40 +00001530
1531 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1532
Josh Coalsond86e03b2002-08-03 21:56:15 +00001533 if(samples > 0) {
1534 encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize);
1535 encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize);
1536 }
1537
Josh Coalson5c491a12002-08-01 06:39:40 +00001538 return true;
1539}
1540
Josh Coalsonf1eff452002-07-31 07:05:33 +00001541FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson0a15c142001-06-13 17:59:57 +00001542{
Josh Coalsonfa697a92001-08-16 20:07:29 +00001543 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001544
1545 /*
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001546 * Accumulate raw signal to the MD5 signature
1547 */
Josh Coalson57ba6f42002-06-07 05:27:37 +00001548 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 +00001549 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001550 return false;
1551 }
1552
1553 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001554 * Process the frame header and subframes into the frame bitbuffer
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001555 */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001556 if(!process_subframes_(encoder, is_last_frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001557 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001558 return false;
1559 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001560
1561 /*
1562 * Zero-pad the frame to a byte_boundary
1563 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001564 if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001565 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001566 return false;
1567 }
1568
1569 /*
Josh Coalson215af572001-03-27 01:15:58 +00001570 * CRC-16 the whole thing
1571 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001572 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1573 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 +00001574
1575 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001576 * Write it
1577 */
Josh Coalsond86e03b2002-08-03 21:56:15 +00001578 if(!write_bitbuffer_(encoder, encoder->protected_->blocksize)) {
1579 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001580 return false;
1581 }
1582
1583 /*
1584 * Get ready for the next frame
1585 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001586 encoder->private_->current_sample_number = 0;
1587 encoder->private_->current_frame_number++;
1588 encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001589
1590 return true;
1591}
1592
Josh Coalsonf1eff452002-07-31 07:05:33 +00001593FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001594{
1595 FLAC__FrameHeader frame_header;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001596 unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00001597 FLAC__bool do_independent, do_mid_side, precompute_partition_sums;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001598
1599 /*
Josh Coalson60f77d72001-04-25 02:16:36 +00001600 * Calculate the min,max Rice partition orders
Josh Coalson94e02cd2001-01-25 10:41:06 +00001601 */
1602 if(is_last_frame) {
1603 max_partition_order = 0;
1604 }
1605 else {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001606 max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize);
1607 max_partition_order = min(max_partition_order, encoder->protected_->max_residual_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001608 }
Josh Coalson60f77d72001-04-25 02:16:36 +00001609 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001610
Josh Coalsonfa697a92001-08-16 20:07:29 +00001611 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 +00001612
Josh Coalson94e02cd2001-01-25 10:41:06 +00001613 /*
1614 * Setup the frame
1615 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001616 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001617 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001618 return false;
1619 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001620 frame_header.blocksize = encoder->protected_->blocksize;
1621 frame_header.sample_rate = encoder->protected_->sample_rate;
1622 frame_header.channels = encoder->protected_->channels;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001623 frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001624 frame_header.bits_per_sample = encoder->protected_->bits_per_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00001625 frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001626 frame_header.number.frame_number = encoder->private_->current_frame_number;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001627
1628 /*
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001629 * Figure out what channel assignments to try
1630 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001631 if(encoder->protected_->do_mid_side_stereo) {
1632 if(encoder->protected_->loose_mid_side_stereo) {
1633 if(encoder->private_->loose_mid_side_stereo_frame_count == 0) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001634 do_independent = true;
1635 do_mid_side = true;
1636 }
1637 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001638 do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001639 do_mid_side = !do_independent;
1640 }
1641 }
1642 else {
1643 do_independent = true;
1644 do_mid_side = true;
1645 }
1646 }
1647 else {
1648 do_independent = true;
1649 do_mid_side = false;
1650 }
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001651
Josh Coalson1b689822001-05-31 20:11:02 +00001652 FLAC__ASSERT(do_independent || do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001653
1654 /*
Josh Coalson82b73242001-03-28 22:17:05 +00001655 * Check for wasted bits; set effective bps for each subframe
Josh Coalson859bc542001-03-27 22:22:27 +00001656 */
1657 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001658 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001659 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001660 encoder->private_->subframe_workspace[channel][0].wasted_bits = encoder->private_->subframe_workspace[channel][1].wasted_bits = w;
1661 encoder->private_->subframe_bps[channel] = encoder->protected_->bits_per_sample - w;
Josh Coalson82b73242001-03-28 22:17:05 +00001662 }
Josh Coalson859bc542001-03-27 22:22:27 +00001663 }
1664 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001665 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson82b73242001-03-28 22:17:05 +00001666 for(channel = 0; channel < 2; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001667 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001668 encoder->private_->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private_->subframe_workspace_mid_side[channel][1].wasted_bits = w;
1669 encoder->private_->subframe_bps_mid_side[channel] = encoder->protected_->bits_per_sample - w + (channel==0? 0:1);
Josh Coalson82b73242001-03-28 22:17:05 +00001670 }
Josh Coalson859bc542001-03-27 22:22:27 +00001671 }
1672
1673 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001674 * First do a normal encoding pass of each independent channel
1675 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001676 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001677 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001678 if(!
1679 process_subframe_(
1680 encoder,
1681 min_partition_order,
1682 max_partition_order,
1683 precompute_partition_sums,
1684 false,
1685 &frame_header,
1686 encoder->private_->subframe_bps[channel],
1687 encoder->private_->integer_signal[channel],
1688 encoder->private_->real_signal[channel],
1689 encoder->private_->subframe_workspace_ptr[channel],
1690 encoder->private_->partitioned_rice_contents_workspace_ptr[channel],
1691 encoder->private_->residual_workspace[channel],
1692 encoder->private_->best_subframe+channel,
1693 encoder->private_->best_subframe_bits+channel
1694 )
1695 )
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001696 return false;
1697 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001698 }
1699
1700 /*
1701 * Now do mid and side channels if requested
1702 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001703 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001704 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001705
1706 for(channel = 0; channel < 2; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001707 if(!
1708 process_subframe_(
1709 encoder,
1710 min_partition_order,
1711 max_partition_order,
1712 precompute_partition_sums,
1713 false,
1714 &frame_header,
1715 encoder->private_->subframe_bps_mid_side[channel],
1716 encoder->private_->integer_signal_mid_side[channel],
1717 encoder->private_->real_signal_mid_side[channel],
1718 encoder->private_->subframe_workspace_ptr_mid_side[channel],
1719 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel],
1720 encoder->private_->residual_workspace_mid_side[channel],
1721 encoder->private_->best_subframe_mid_side+channel,
1722 encoder->private_->best_subframe_bits_mid_side+channel
1723 )
1724 )
Josh Coalson94e02cd2001-01-25 10:41:06 +00001725 return false;
1726 }
1727 }
1728
1729 /*
1730 * Compose the frame bitbuffer
1731 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001732 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +00001733 unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
1734 FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001735 FLAC__ChannelAssignment channel_assignment;
1736
Josh Coalsonfa697a92001-08-16 20:07:29 +00001737 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001738
Josh Coalsonfa697a92001-08-16 20:07:29 +00001739 if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) {
1740 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 +00001741 }
1742 else {
1743 unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
1744 unsigned min_bits;
1745 FLAC__ChannelAssignment ca;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001746
Josh Coalson1b689822001-05-31 20:11:02 +00001747 FLAC__ASSERT(do_independent && do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001748
1749 /* We have to figure out which channel assignent results in the smallest frame */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001750 bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1];
1751 bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1];
1752 bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1];
1753 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 +00001754
1755 for(channel_assignment = 0, min_bits = bits[0], ca = 1; ca <= 3; ca++) {
1756 if(bits[ca] < min_bits) {
1757 min_bits = bits[ca];
1758 channel_assignment = ca;
1759 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001760 }
1761 }
1762
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001763 frame_header.channel_assignment = channel_assignment;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001764
Josh Coalsonaec256b2002-03-12 16:19:54 +00001765 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001766 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001767 return false;
1768 }
1769
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001770 switch(channel_assignment) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001771 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001772 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1773 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001774 break;
1775 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001776 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1777 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001778 break;
1779 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001780 left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
1781 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001782 break;
1783 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001784 left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]];
1785 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001786 break;
1787 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001788 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001789 }
Josh Coalson82b73242001-03-28 22:17:05 +00001790
1791 switch(channel_assignment) {
1792 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001793 left_bps = encoder->private_->subframe_bps [0];
1794 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001795 break;
1796 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001797 left_bps = encoder->private_->subframe_bps [0];
1798 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001799 break;
1800 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001801 left_bps = encoder->private_->subframe_bps_mid_side[1];
1802 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001803 break;
1804 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001805 left_bps = encoder->private_->subframe_bps_mid_side[0];
1806 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001807 break;
1808 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001809 FLAC__ASSERT(0);
Josh Coalson82b73242001-03-28 22:17:05 +00001810 }
1811
1812 /* note that encoder_add_subframe_ sets the state for us in case of an error */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001813 if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001814 return false;
Josh Coalsonf1eff452002-07-31 07:05:33 +00001815 if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001816 return false;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001817 }
1818 else {
Josh Coalsonaec256b2002-03-12 16:19:54 +00001819 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001820 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001821 return false;
1822 }
1823
Josh Coalsonfa697a92001-08-16 20:07:29 +00001824 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001825 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 +00001826 /* the above function sets the state for us in case of an error */
1827 return false;
1828 }
1829 }
1830 }
1831
Josh Coalsonfa697a92001-08-16 20:07:29 +00001832 if(encoder->protected_->loose_mid_side_stereo) {
1833 encoder->private_->loose_mid_side_stereo_frame_count++;
1834 if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames)
1835 encoder->private_->loose_mid_side_stereo_frame_count = 0;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001836 }
1837
Josh Coalsonfa697a92001-08-16 20:07:29 +00001838 encoder->private_->last_channel_assignment = frame_header.channel_assignment;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001839
Josh Coalson94e02cd2001-01-25 10:41:06 +00001840 return true;
1841}
1842
Josh Coalson6fe72f72002-08-20 04:01:59 +00001843FLAC__bool process_subframe_(
1844 FLAC__StreamEncoder *encoder,
1845 unsigned min_partition_order,
1846 unsigned max_partition_order,
1847 FLAC__bool precompute_partition_sums,
1848 FLAC__bool verbatim_only,
1849 const FLAC__FrameHeader *frame_header,
1850 unsigned subframe_bps,
1851 const FLAC__int32 integer_signal[],
1852 const FLAC__real real_signal[],
1853 FLAC__Subframe *subframe[2],
1854 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
1855 FLAC__int32 *residual[2],
1856 unsigned *best_subframe,
1857 unsigned *best_bits
1858)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001859{
Josh Coalson77e3f312001-06-23 03:03:24 +00001860 FLAC__real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
1861 FLAC__real lpc_residual_bits_per_sample;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001862 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 +00001863 FLAC__real lpc_error[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001864 unsigned min_lpc_order, max_lpc_order, lpc_order;
1865 unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
1866 unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
1867 unsigned rice_parameter;
1868 unsigned _candidate_bits, _best_bits;
1869 unsigned _best_subframe;
1870
1871 /* verbatim subframe is the baseline against which we measure other compressed subframes */
1872 _best_subframe = 0;
Josh Coalsonf1eff452002-07-31 07:05:33 +00001873 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001874
1875 if(!verbatim_only && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
1876 /* check for constant subframe */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001877 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 Coalson94e02cd2001-01-25 10:41:06 +00001878 if(fixed_residual_bits_per_sample[1] == 0.0) {
1879 /* the above means integer_signal+FLAC__MAX_FIXED_ORDER is constant, now we just have to check the warmup samples */
1880 unsigned i, signal_is_constant = true;
1881 for(i = 1; i <= FLAC__MAX_FIXED_ORDER; i++) {
1882 if(integer_signal[0] != integer_signal[i]) {
1883 signal_is_constant = false;
1884 break;
1885 }
1886 }
1887 if(signal_is_constant) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001888 _candidate_bits = evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001889 if(_candidate_bits < _best_bits) {
1890 _best_subframe = !_best_subframe;
1891 _best_bits = _candidate_bits;
1892 }
1893 }
1894 }
1895 else {
1896 /* encode fixed */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001897 if(encoder->protected_->do_exhaustive_model_search) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001898 min_fixed_order = 0;
1899 max_fixed_order = FLAC__MAX_FIXED_ORDER;
1900 }
1901 else {
1902 min_fixed_order = max_fixed_order = guess_fixed_order;
1903 }
1904 for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
Josh Coalson77e3f312001-06-23 03:03:24 +00001905 if(fixed_residual_bits_per_sample[fixed_order] >= (FLAC__real)subframe_bps)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001906 continue; /* don't even try */
Josh Coalson46f2ae82001-02-08 00:27:21 +00001907 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 */
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001908#ifndef FLAC__SYMMETRIC_RICE
Josh Coalson46f2ae82001-02-08 00:27:21 +00001909 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00001910#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001911 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00001912#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00001913 fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
1914#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001915 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00001916 }
Josh Coalson6fe72f72002-08-20 04:01:59 +00001917 _candidate_bits =
1918 evaluate_fixed_subframe_(
1919 encoder,
1920 integer_signal,
1921 residual[!_best_subframe],
1922 encoder->private_->abs_residual,
1923 encoder->private_->abs_residual_partition_sums,
1924 encoder->private_->raw_bits_per_partition,
1925 frame_header->blocksize,
1926 subframe_bps,
1927 fixed_order,
1928 rice_parameter,
1929 min_partition_order,
1930 max_partition_order,
1931 precompute_partition_sums,
1932 encoder->protected_->do_escape_coding,
1933 encoder->protected_->rice_parameter_search_dist,
1934 subframe[!_best_subframe],
1935 partitioned_rice_contents[!_best_subframe]
1936 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00001937 if(_candidate_bits < _best_bits) {
1938 _best_subframe = !_best_subframe;
1939 _best_bits = _candidate_bits;
1940 }
1941 }
1942
1943 /* encode lpc */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001944 if(encoder->protected_->max_lpc_order > 0) {
1945 if(encoder->protected_->max_lpc_order >= frame_header->blocksize)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001946 max_lpc_order = frame_header->blocksize-1;
1947 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00001948 max_lpc_order = encoder->protected_->max_lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001949 if(max_lpc_order > 0) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001950 encoder->private_->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001951 /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
1952 if(autoc[0] != 0.0) {
Josh Coalson8084b052001-11-01 00:27:29 +00001953 FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001954 if(encoder->protected_->do_exhaustive_model_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001955 min_lpc_order = 1;
1956 }
1957 else {
Josh Coalson82b73242001-03-28 22:17:05 +00001958 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 +00001959 min_lpc_order = max_lpc_order = guess_lpc_order;
1960 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001961 if(encoder->protected_->do_qlp_coeff_prec_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001962 min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00001963 max_qlp_coeff_precision = min(8*sizeof(FLAC__int32) - subframe_bps - 1 - 2, (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)-1); /* -2 to keep things 32-bit safe */
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001964 }
1965 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001966 min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001967 }
1968 for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
1969 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 +00001970 if(lpc_residual_bits_per_sample >= (FLAC__real)subframe_bps)
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001971 continue; /* don't even try */
1972 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 +00001973#ifndef FLAC__SYMMETRIC_RICE
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001974 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00001975#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001976 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00001977#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00001978 fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
1979#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001980 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00001981 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001982 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 +00001983 _candidate_bits =
1984 evaluate_lpc_subframe_(
1985 encoder,
1986 integer_signal,
1987 residual[!_best_subframe],
1988 encoder->private_->abs_residual,
1989 encoder->private_->abs_residual_partition_sums,
1990 encoder->private_->raw_bits_per_partition,
1991 encoder->private_->lp_coeff[lpc_order-1],
1992 frame_header->blocksize,
1993 subframe_bps,
1994 lpc_order,
1995 qlp_coeff_precision,
1996 rice_parameter,
1997 min_partition_order,
1998 max_partition_order,
1999 precompute_partition_sums,
2000 encoder->protected_->do_escape_coding,
2001 encoder->protected_->rice_parameter_search_dist,
2002 subframe[!_best_subframe],
2003 partitioned_rice_contents[!_best_subframe]
2004 );
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002005 if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
2006 if(_candidate_bits < _best_bits) {
2007 _best_subframe = !_best_subframe;
2008 _best_bits = _candidate_bits;
2009 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002010 }
2011 }
2012 }
2013 }
2014 }
2015 }
2016 }
2017 }
2018
2019 *best_subframe = _best_subframe;
2020 *best_bits = _best_bits;
2021
2022 return true;
2023}
2024
Josh Coalson6fe72f72002-08-20 04:01:59 +00002025FLAC__bool add_subframe_(
2026 FLAC__StreamEncoder *encoder,
2027 const FLAC__FrameHeader *frame_header,
2028 unsigned subframe_bps,
2029 const FLAC__Subframe *subframe,
2030 FLAC__BitBuffer *frame
2031)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002032{
2033 switch(subframe->type) {
2034 case FLAC__SUBFRAME_TYPE_CONSTANT:
Josh Coalson82b73242001-03-28 22:17:05 +00002035 if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002036 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002037 return false;
2038 }
2039 break;
2040 case FLAC__SUBFRAME_TYPE_FIXED:
Josh Coalson82b73242001-03-28 22:17:05 +00002041 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 +00002042 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002043 return false;
2044 }
2045 break;
2046 case FLAC__SUBFRAME_TYPE_LPC:
Josh Coalson82b73242001-03-28 22:17:05 +00002047 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 +00002048 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002049 return false;
2050 }
2051 break;
2052 case FLAC__SUBFRAME_TYPE_VERBATIM:
Josh Coalson82b73242001-03-28 22:17:05 +00002053 if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002054 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002055 return false;
2056 }
2057 break;
2058 default:
Josh Coalson1b689822001-05-31 20:11:02 +00002059 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002060 }
2061
2062 return true;
2063}
2064
Josh Coalson6fe72f72002-08-20 04:01:59 +00002065unsigned evaluate_constant_subframe_(
2066 const FLAC__int32 signal,
2067 unsigned subframe_bps,
2068 FLAC__Subframe *subframe
2069)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002070{
2071 subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
2072 subframe->data.constant.value = signal;
2073
Josh Coalson82b73242001-03-28 22:17:05 +00002074 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 +00002075}
2076
Josh Coalson6fe72f72002-08-20 04:01:59 +00002077unsigned evaluate_fixed_subframe_(
2078 FLAC__StreamEncoder *encoder,
2079 const FLAC__int32 signal[],
2080 FLAC__int32 residual[],
2081 FLAC__uint32 abs_residual[],
2082 FLAC__uint64 abs_residual_partition_sums[],
2083 unsigned raw_bits_per_partition[],
2084 unsigned blocksize,
2085 unsigned subframe_bps,
2086 unsigned order,
2087 unsigned rice_parameter,
2088 unsigned min_partition_order,
2089 unsigned max_partition_order,
2090 FLAC__bool precompute_partition_sums,
2091 FLAC__bool do_escape_coding,
2092 unsigned rice_parameter_search_dist,
2093 FLAC__Subframe *subframe,
2094 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2095)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002096{
2097 unsigned i, residual_bits;
2098 const unsigned residual_samples = blocksize - order;
2099
2100 FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
2101
2102 subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
2103
2104 subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002105 subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002106 subframe->data.fixed.residual = residual;
2107
Josh Coalson6fe72f72002-08-20 04:01:59 +00002108 residual_bits =
2109 find_best_partition_order_(
2110 encoder->private_,
2111 residual,
2112 abs_residual,
2113 abs_residual_partition_sums,
2114 raw_bits_per_partition,
2115 residual_samples,
2116 order,
2117 rice_parameter,
2118 min_partition_order,
2119 max_partition_order,
2120 precompute_partition_sums,
2121 do_escape_coding,
2122 rice_parameter_search_dist,
2123 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2124 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002125
2126 subframe->data.fixed.order = order;
2127 for(i = 0; i < order; i++)
2128 subframe->data.fixed.warmup[i] = signal[i];
2129
Josh Coalson82b73242001-03-28 22:17:05 +00002130 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 +00002131}
2132
Josh Coalson6fe72f72002-08-20 04:01:59 +00002133unsigned evaluate_lpc_subframe_(
2134 FLAC__StreamEncoder *encoder,
2135 const FLAC__int32 signal[],
2136 FLAC__int32 residual[],
2137 FLAC__uint32 abs_residual[],
2138 FLAC__uint64 abs_residual_partition_sums[],
2139 unsigned raw_bits_per_partition[],
2140 const FLAC__real lp_coeff[],
2141 unsigned blocksize,
2142 unsigned subframe_bps,
2143 unsigned order,
2144 unsigned qlp_coeff_precision,
2145 unsigned rice_parameter,
2146 unsigned min_partition_order,
2147 unsigned max_partition_order,
2148 FLAC__bool precompute_partition_sums,
2149 FLAC__bool do_escape_coding,
2150 unsigned rice_parameter_search_dist,
2151 FLAC__Subframe *subframe,
2152 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2153)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002154{
Josh Coalson77e3f312001-06-23 03:03:24 +00002155 FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00002156 unsigned i, residual_bits;
2157 int quantization, ret;
2158 const unsigned residual_samples = blocksize - order;
2159
Josh Coalson82b73242001-03-28 22:17:05 +00002160 ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, subframe_bps, qlp_coeff, &quantization);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002161 if(ret != 0)
2162 return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
2163
Josh Coalson92d42402001-05-31 20:53:19 +00002164 if(subframe_bps <= 16 && qlp_coeff_precision <= 16)
Josh Coalsonfa697a92001-08-16 20:07:29 +00002165 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalson92d42402001-05-31 20:53:19 +00002166 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00002167 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002168
2169 subframe->type = FLAC__SUBFRAME_TYPE_LPC;
2170
2171 subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002172 subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002173 subframe->data.lpc.residual = residual;
2174
Josh Coalson6fe72f72002-08-20 04:01:59 +00002175 residual_bits =
2176 find_best_partition_order_(
2177 encoder->private_,
2178 residual,
2179 abs_residual,
2180 abs_residual_partition_sums,
2181 raw_bits_per_partition,
2182 residual_samples,
2183 order,
2184 rice_parameter,
2185 min_partition_order,
2186 max_partition_order,
2187 precompute_partition_sums,
2188 do_escape_coding,
2189 rice_parameter_search_dist,
2190 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2191 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002192
2193 subframe->data.lpc.order = order;
2194 subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
2195 subframe->data.lpc.quantization_level = quantization;
Josh Coalson77e3f312001-06-23 03:03:24 +00002196 memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002197 for(i = 0; i < order; i++)
2198 subframe->data.lpc.warmup[i] = signal[i];
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 + 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 +00002201}
2202
Josh Coalson6fe72f72002-08-20 04:01:59 +00002203unsigned evaluate_verbatim_subframe_(
2204 const FLAC__int32 signal[],
2205 unsigned blocksize,
2206 unsigned subframe_bps,
2207 FLAC__Subframe *subframe
2208)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002209{
2210 subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
2211
2212 subframe->data.verbatim.data = signal;
2213
Josh Coalson82b73242001-03-28 22:17:05 +00002214 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 +00002215}
2216
Josh Coalson6fe72f72002-08-20 04:01:59 +00002217unsigned find_best_partition_order_(
2218 FLAC__StreamEncoderPrivate *private_,
2219 const FLAC__int32 residual[],
2220 FLAC__uint32 abs_residual[],
2221 FLAC__uint64 abs_residual_partition_sums[],
2222 unsigned raw_bits_per_partition[],
2223 unsigned residual_samples,
2224 unsigned predictor_order,
2225 unsigned rice_parameter,
2226 unsigned min_partition_order,
2227 unsigned max_partition_order,
2228 FLAC__bool precompute_partition_sums,
2229 FLAC__bool do_escape_coding,
2230 unsigned rice_parameter_search_dist,
2231 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
2232)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002233{
Josh Coalson77e3f312001-06-23 03:03:24 +00002234 FLAC__int32 r;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002235 unsigned residual_bits, best_residual_bits = 0;
Josh Coalsonafcd8772001-04-18 22:59:25 +00002236 unsigned residual_sample;
Josh Coalson8084b052001-11-01 00:27:29 +00002237 unsigned best_parameters_index = 0;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002238 const unsigned blocksize = residual_samples + predictor_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002239
Josh Coalson2051dd42001-04-12 22:22:34 +00002240 /* compute abs(residual) for use later */
2241 for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
2242 r = residual[residual_sample];
Josh Coalson77e3f312001-06-23 03:03:24 +00002243 abs_residual[residual_sample] = (FLAC__uint32)(r<0? -r : r);
Josh Coalson2051dd42001-04-12 22:22:34 +00002244 }
2245
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002246 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 +00002247 min_partition_order = min(min_partition_order, max_partition_order);
2248
Josh Coalson8395d022001-07-12 21:25:22 +00002249 if(precompute_partition_sums) {
2250 int partition_order;
2251 unsigned sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002252
Josh Coalsonf1eff452002-07-31 07:05:33 +00002253 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 +00002254
2255 if(do_escape_coding)
Josh Coalsonf1eff452002-07-31 07:05:33 +00002256 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 +00002257
2258 for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
2259#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002260 if(!
2261 set_partitioned_rice_with_precompute_(
2262 residual,
2263 abs_residual_partition_sums+sum,
2264 raw_bits_per_partition+sum,
2265 residual_samples,
2266 predictor_order,
2267 rice_parameter,
2268 rice_parameter_search_dist,
2269 (unsigned)partition_order,
2270 do_escape_coding,
2271 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2272 &residual_bits
2273 )
2274 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002275#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002276 if(!
2277 set_partitioned_rice_with_precompute_(
2278 abs_residual,
2279 abs_residual_partition_sums+sum,
2280 raw_bits_per_partition+sum,
2281 residual_samples,
2282 predictor_order,
2283 rice_parameter,
2284 rice_parameter_search_dist,
2285 (unsigned)partition_order,
2286 do_escape_coding,
2287 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2288 &residual_bits
2289 )
2290 )
Josh Coalson8395d022001-07-12 21:25:22 +00002291#endif
2292 {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002293 FLAC__ASSERT(best_residual_bits != 0);
2294 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002295 }
2296 sum += 1u << partition_order;
2297 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2298 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002299 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002300 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002301 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00002302 }
2303 }
Josh Coalson8395d022001-07-12 21:25:22 +00002304 else {
2305 unsigned partition_order;
2306 for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
2307#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002308 if(!
2309 set_partitioned_rice_(
2310 abs_residual,
2311 residual,
2312 residual_samples,
2313 predictor_order,
2314 rice_parameter,
2315 rice_parameter_search_dist,
2316 partition_order,
2317 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2318 &residual_bits
2319 )
2320 )
Josh Coalson8395d022001-07-12 21:25:22 +00002321#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002322 if(!
2323 set_partitioned_rice_(
2324 abs_residual,
2325 residual_samples,
2326 predictor_order,
2327 rice_parameter,
2328 rice_parameter_search_dist,
2329 partition_order,
2330 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2331 &residual_bits
2332 )
2333 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002334#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002335 {
2336 FLAC__ASSERT(best_residual_bits != 0);
2337 break;
2338 }
2339 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2340 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002341 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002342 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002343 }
2344 }
2345 }
2346
Josh Coalsona37ba462002-08-19 21:36:39 +00002347 /*
2348 * We are allowed to de-const the pointer based on our special knowledhe;
2349 * it is const to the outside world.
2350 */
2351 {
2352 FLAC__EntropyCodingMethod_PartitionedRiceContents* best_partitioned_rice_contents = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_partitioned_rice->contents;
2353 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(best_partitioned_rice_contents, max(6, best_partitioned_rice->order));
2354 memcpy(best_partitioned_rice_contents->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2355 memcpy(best_partitioned_rice_contents->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2356 }
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002357
2358 return best_residual_bits;
2359}
2360
Josh Coalson6fe72f72002-08-20 04:01:59 +00002361void precompute_partition_info_sums_(
2362 const FLAC__uint32 abs_residual[],
2363 FLAC__uint64 abs_residual_partition_sums[],
2364 unsigned residual_samples,
2365 unsigned predictor_order,
2366 unsigned min_partition_order,
2367 unsigned max_partition_order
2368)
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002369{
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002370 int partition_order;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002371 unsigned from_partition, to_partition = 0;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002372 const unsigned blocksize = residual_samples + predictor_order;
2373
Josh Coalsonaef013c2001-04-24 01:25:42 +00002374 /* first do max_partition_order */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002375 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002376 FLAC__uint64 abs_residual_partition_sum;
Josh Coalson77e3f312001-06-23 03:03:24 +00002377 FLAC__uint32 abs_r;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002378 unsigned partition, partition_sample, partition_samples, residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002379 const unsigned partitions = 1u << partition_order;
2380 const unsigned default_partition_samples = blocksize >> partition_order;
2381
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002382 FLAC__ASSERT(default_partition_samples > predictor_order);
2383
2384 for(partition = residual_sample = 0; partition < partitions; partition++) {
2385 partition_samples = default_partition_samples;
2386 if(partition == 0)
2387 partition_samples -= predictor_order;
2388 abs_residual_partition_sum = 0;
2389 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2390 abs_r = abs_residual[residual_sample];
2391 abs_residual_partition_sum += abs_r;
2392 residual_sample++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002393 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002394 abs_residual_partition_sums[partition] = abs_residual_partition_sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002395 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002396 to_partition = partitions;
2397 break;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002398 }
Josh Coalsonf76a3612001-04-18 02:28:11 +00002399
Josh Coalson8395d022001-07-12 21:25:22 +00002400 /* now merge partitions for lower orders */
Josh Coalson6bd17572001-05-25 19:02:01 +00002401 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002402 FLAC__uint64 s;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002403 unsigned i;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002404 const unsigned partitions = 1u << partition_order;
2405 for(i = 0; i < partitions; i++) {
Josh Coalsonaef013c2001-04-24 01:25:42 +00002406 s = abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002407 from_partition++;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002408 abs_residual_partition_sums[to_partition] = s + abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002409 from_partition++;
2410 to_partition++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002411 }
2412 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002413}
Josh Coalson8395d022001-07-12 21:25:22 +00002414
Josh Coalson6fe72f72002-08-20 04:01:59 +00002415void precompute_partition_info_escapes_(
2416 const FLAC__int32 residual[],
2417 unsigned raw_bits_per_partition[],
2418 unsigned residual_samples,
2419 unsigned predictor_order,
2420 unsigned min_partition_order,
2421 unsigned max_partition_order
2422)
Josh Coalson8395d022001-07-12 21:25:22 +00002423{
2424 int partition_order;
2425 unsigned from_partition, to_partition = 0;
2426 const unsigned blocksize = residual_samples + predictor_order;
2427
2428 /* first do max_partition_order */
2429 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
2430 FLAC__int32 r, residual_partition_min, residual_partition_max;
2431 unsigned silog2_min, silog2_max;
2432 unsigned partition, partition_sample, partition_samples, residual_sample;
2433 const unsigned partitions = 1u << partition_order;
2434 const unsigned default_partition_samples = blocksize >> partition_order;
2435
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002436 FLAC__ASSERT(default_partition_samples > predictor_order);
2437
2438 for(partition = residual_sample = 0; partition < partitions; partition++) {
2439 partition_samples = default_partition_samples;
2440 if(partition == 0)
2441 partition_samples -= predictor_order;
2442 residual_partition_min = residual_partition_max = 0;
2443 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2444 r = residual[residual_sample];
2445 if(r < residual_partition_min)
2446 residual_partition_min = r;
2447 else if(r > residual_partition_max)
2448 residual_partition_max = r;
2449 residual_sample++;
Josh Coalson8395d022001-07-12 21:25:22 +00002450 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002451 silog2_min = FLAC__bitmath_silog2(residual_partition_min);
2452 silog2_max = FLAC__bitmath_silog2(residual_partition_max);
2453 raw_bits_per_partition[partition] = max(silog2_min, silog2_max);
Josh Coalson8395d022001-07-12 21:25:22 +00002454 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002455 to_partition = partitions;
2456 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002457 }
2458
2459 /* now merge partitions for lower orders */
2460 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
2461 unsigned m;
2462 unsigned i;
2463 const unsigned partitions = 1u << partition_order;
2464 for(i = 0; i < partitions; i++) {
2465 m = raw_bits_per_partition[from_partition];
2466 from_partition++;
2467 raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]);
2468 from_partition++;
2469 to_partition++;
2470 }
2471 }
2472}
Josh Coalson94e02cd2001-01-25 10:41:06 +00002473
Josh Coalson352e0f62001-03-20 22:55:50 +00002474#ifdef VARIABLE_RICE_BITS
2475#undef VARIABLE_RICE_BITS
2476#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002477#ifndef DONT_ESTIMATE_RICE_BITS
Josh Coalson352e0f62001-03-20 22:55:50 +00002478#define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
Josh Coalson8395d022001-07-12 21:25:22 +00002479#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002480
Josh Coalson8395d022001-07-12 21:25:22 +00002481#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002482FLAC__bool set_partitioned_rice_(
2483 const FLAC__uint32 abs_residual[],
2484 const FLAC__int32 residual[],
2485 const unsigned residual_samples,
2486 const unsigned predictor_order,
2487 const unsigned suggested_rice_parameter,
2488 const unsigned rice_parameter_search_dist,
2489 const unsigned partition_order,
2490 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2491 unsigned *bits
2492)
Josh Coalson8395d022001-07-12 21:25:22 +00002493#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002494FLAC__bool set_partitioned_rice_(
2495 const FLAC__uint32 abs_residual[],
2496 const unsigned residual_samples,
2497 const unsigned predictor_order,
2498 const unsigned suggested_rice_parameter,
2499 const unsigned rice_parameter_search_dist,
2500 const unsigned partition_order,
2501 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2502 unsigned *bits
2503)
Josh Coalson8395d022001-07-12 21:25:22 +00002504#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002505{
Josh Coalson034dfab2001-04-27 19:10:23 +00002506 unsigned rice_parameter, partition_bits;
2507#ifndef NO_RICE_SEARCH
2508 unsigned best_partition_bits;
2509 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2510#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002511 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002512 unsigned *parameters;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002513
Josh Coalson1b689822001-05-31 20:11:02 +00002514 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
Josh Coalson2051dd42001-04-12 22:22:34 +00002515
Josh Coalsona37ba462002-08-19 21:36:39 +00002516 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2517 parameters = partitioned_rice_contents->parameters;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002518
Josh Coalson94e02cd2001-01-25 10:41:06 +00002519 if(partition_order == 0) {
2520 unsigned i;
Josh Coalson352e0f62001-03-20 22:55:50 +00002521
Josh Coalson034dfab2001-04-27 19:10:23 +00002522#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002523 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002524 if(suggested_rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002525 min_rice_parameter = 0;
2526 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002527 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2528 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002529 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002530#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002531 fprintf(stderr, "clipping rice_parameter (%u -> %u) @2\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2532#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002533 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002534 }
2535 }
2536 else
2537 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
2538
2539 best_partition_bits = 0xffffffff;
2540 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2541#endif
2542#ifdef VARIABLE_RICE_BITS
2543#ifdef FLAC__SYMMETRIC_RICE
2544 partition_bits = (2+rice_parameter) * residual_samples;
2545#else
2546 const unsigned rice_parameter_estimate = rice_parameter-1;
2547 partition_bits = (1+rice_parameter) * residual_samples;
2548#endif
2549#else
2550 partition_bits = 0;
2551#endif
2552 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2553 for(i = 0; i < residual_samples; i++) {
2554#ifdef VARIABLE_RICE_BITS
2555#ifdef FLAC__SYMMETRIC_RICE
2556 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
2557#else
2558 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
2559#endif
2560#else
2561 partition_bits += FLAC__bitbuffer_rice_bits(residual[i], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2562#endif
2563 }
2564#ifndef NO_RICE_SEARCH
2565 if(partition_bits < best_partition_bits) {
2566 best_rice_parameter = rice_parameter;
2567 best_partition_bits = partition_bits;
2568 }
2569 }
2570#endif
2571 parameters[0] = best_rice_parameter;
2572 bits_ += best_partition_bits;
2573 }
2574 else {
2575 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002576 unsigned partition_samples;
2577 FLAC__uint64 mean, k;
Josh Coalson8395d022001-07-12 21:25:22 +00002578 const unsigned partitions = 1u << partition_order;
2579 for(partition = residual_sample = 0; partition < partitions; partition++) {
2580 partition_samples = (residual_samples+predictor_order) >> partition_order;
2581 if(partition == 0) {
2582 if(partition_samples <= predictor_order)
2583 return false;
2584 else
2585 partition_samples -= predictor_order;
2586 }
2587 mean = 0;
2588 save_residual_sample = residual_sample;
2589 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++)
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002590 mean += abs_residual[residual_sample];
Josh Coalson8395d022001-07-12 21:25:22 +00002591 residual_sample = save_residual_sample;
2592#ifdef FLAC__SYMMETRIC_RICE
2593 mean += partition_samples >> 1; /* for rounding effect */
2594 mean /= partition_samples;
2595
2596 /* calc rice_parameter = floor(log2(mean)) */
2597 rice_parameter = 0;
2598 mean>>=1;
2599 while(mean) {
2600 rice_parameter++;
2601 mean >>= 1;
2602 }
2603#else
2604 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002605 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson8395d022001-07-12 21:25:22 +00002606 ;
2607#endif
2608 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002609#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002610 fprintf(stderr, "clipping rice_parameter (%u -> %u) @3\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2611#endif
2612 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2613 }
2614
2615#ifndef NO_RICE_SEARCH
2616 if(rice_parameter_search_dist) {
2617 if(rice_parameter < rice_parameter_search_dist)
2618 min_rice_parameter = 0;
2619 else
2620 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2621 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
2622 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002623#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002624 fprintf(stderr, "clipping rice_parameter (%u -> %u) @4\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2625#endif
2626 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2627 }
2628 }
2629 else
2630 min_rice_parameter = max_rice_parameter = rice_parameter;
2631
2632 best_partition_bits = 0xffffffff;
2633 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2634#endif
2635#ifdef VARIABLE_RICE_BITS
2636#ifdef FLAC__SYMMETRIC_RICE
2637 partition_bits = (2+rice_parameter) * partition_samples;
2638#else
2639 const unsigned rice_parameter_estimate = rice_parameter-1;
2640 partition_bits = (1+rice_parameter) * partition_samples;
2641#endif
2642#else
2643 partition_bits = 0;
2644#endif
2645 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2646 save_residual_sample = residual_sample;
2647 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
2648#ifdef VARIABLE_RICE_BITS
2649#ifdef FLAC__SYMMETRIC_RICE
2650 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
2651#else
2652 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
2653#endif
2654#else
2655 partition_bits += FLAC__bitbuffer_rice_bits(residual[residual_sample], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2656#endif
2657 }
2658#ifndef NO_RICE_SEARCH
2659 if(rice_parameter != max_rice_parameter)
2660 residual_sample = save_residual_sample;
2661 if(partition_bits < best_partition_bits) {
2662 best_rice_parameter = rice_parameter;
2663 best_partition_bits = partition_bits;
2664 }
2665 }
2666#endif
2667 parameters[partition] = best_rice_parameter;
2668 bits_ += best_partition_bits;
2669 }
2670 }
2671
2672 *bits = bits_;
2673 return true;
2674}
2675
2676#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002677FLAC__bool set_partitioned_rice_with_precompute_(
2678 const FLAC__int32 residual[],
2679 const FLAC__uint64 abs_residual_partition_sums[],
2680 const unsigned raw_bits_per_partition[],
2681 const unsigned residual_samples,
2682 const unsigned predictor_order,
2683 const unsigned suggested_rice_parameter,
2684 const unsigned rice_parameter_search_dist,
2685 const unsigned partition_order,
2686 const FLAC__bool search_for_escapes,
2687 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2688 unsigned *bits
2689)
Josh Coalson8395d022001-07-12 21:25:22 +00002690#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002691FLAC__bool set_partitioned_rice_with_precompute_(
2692 const FLAC__uint32 abs_residual[],
2693 const FLAC__uint64 abs_residual_partition_sums[],
2694 const unsigned raw_bits_per_partition[],
2695 const unsigned residual_samples,
2696 const unsigned predictor_order,
2697 const unsigned suggested_rice_parameter,
2698 const unsigned rice_parameter_search_dist,
2699 const unsigned partition_order,
2700 const FLAC__bool search_for_escapes,
2701 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2702 unsigned *bits
2703)
Josh Coalson8395d022001-07-12 21:25:22 +00002704#endif
2705{
2706 unsigned rice_parameter, partition_bits;
2707#ifndef NO_RICE_SEARCH
2708 unsigned best_partition_bits;
2709 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2710#endif
2711 unsigned flat_bits;
2712 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002713 unsigned *parameters, *raw_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002714
2715 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
2716
Josh Coalsona37ba462002-08-19 21:36:39 +00002717 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2718 parameters = partitioned_rice_contents->parameters;
2719 raw_bits = partitioned_rice_contents->raw_bits;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002720
Josh Coalson8395d022001-07-12 21:25:22 +00002721 if(partition_order == 0) {
2722 unsigned i;
2723
2724#ifndef NO_RICE_SEARCH
2725 if(rice_parameter_search_dist) {
2726 if(suggested_rice_parameter < rice_parameter_search_dist)
2727 min_rice_parameter = 0;
2728 else
2729 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2730 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
2731 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002732#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002733 fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2734#endif
2735 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2736 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002737 }
2738 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002739 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
Josh Coalson2051dd42001-04-12 22:22:34 +00002740
Josh Coalson034dfab2001-04-27 19:10:23 +00002741 best_partition_bits = 0xffffffff;
2742 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2743#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002744#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002745#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002746 partition_bits = (2+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002747#else
Josh Coalson352e0f62001-03-20 22:55:50 +00002748 const unsigned rice_parameter_estimate = rice_parameter-1;
Josh Coalson034dfab2001-04-27 19:10:23 +00002749 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002750#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002751#else
2752 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002753#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002754 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson352e0f62001-03-20 22:55:50 +00002755 for(i = 0; i < residual_samples; i++) {
2756#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002757#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson2051dd42001-04-12 22:22:34 +00002758 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002759#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002760 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002761#endif
2762#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002763 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 +00002764#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002765 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002766#ifndef NO_RICE_SEARCH
2767 if(partition_bits < best_partition_bits) {
2768 best_rice_parameter = rice_parameter;
2769 best_partition_bits = partition_bits;
Josh Coalson352e0f62001-03-20 22:55:50 +00002770 }
2771 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002772#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002773 if(search_for_escapes) {
2774 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;
2775 if(flat_bits <= best_partition_bits) {
2776 raw_bits[0] = raw_bits_per_partition[0];
2777 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2778 best_partition_bits = flat_bits;
2779 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002780 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002781 parameters[0] = best_rice_parameter;
2782 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002783 }
2784 else {
Josh Coalson4dacd192001-06-06 21:11:44 +00002785 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002786 unsigned partition_samples;
2787 FLAC__uint64 mean, k;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002788 const unsigned partitions = 1u << partition_order;
Josh Coalson4dacd192001-06-06 21:11:44 +00002789 for(partition = residual_sample = 0; partition < partitions; partition++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002790 partition_samples = (residual_samples+predictor_order) >> partition_order;
Josh Coalson034dfab2001-04-27 19:10:23 +00002791 if(partition == 0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002792 if(partition_samples <= predictor_order)
2793 return false;
2794 else
2795 partition_samples -= predictor_order;
2796 }
Josh Coalson05d20792001-06-29 23:12:26 +00002797 mean = abs_residual_partition_sums[partition];
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002798#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson05d20792001-06-29 23:12:26 +00002799 mean += partition_samples >> 1; /* for rounding effect */
2800 mean /= partition_samples;
2801
Josh Coalson034dfab2001-04-27 19:10:23 +00002802 /* calc rice_parameter = floor(log2(mean)) */
2803 rice_parameter = 0;
2804 mean>>=1;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002805 while(mean) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002806 rice_parameter++;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002807 mean >>= 1;
2808 }
Josh Coalsonb9433f92001-03-17 01:07:00 +00002809#else
Josh Coalson05d20792001-06-29 23:12:26 +00002810 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002811 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson05d20792001-06-29 23:12:26 +00002812 ;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002813#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002814 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002815#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002816 fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2817#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002818 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002819 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002820
Josh Coalson034dfab2001-04-27 19:10:23 +00002821#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002822 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002823 if(rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002824 min_rice_parameter = 0;
2825 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002826 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2827 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002828 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002829#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002830 fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2831#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002832 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002833 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002834 }
2835 else
2836 min_rice_parameter = max_rice_parameter = rice_parameter;
Josh Coalson60f77d72001-04-25 02:16:36 +00002837
Josh Coalson034dfab2001-04-27 19:10:23 +00002838 best_partition_bits = 0xffffffff;
2839 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2840#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002841#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002842#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002843 partition_bits = (2+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002844#else
Josh Coalson034dfab2001-04-27 19:10:23 +00002845 const unsigned rice_parameter_estimate = rice_parameter-1;
2846 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002847#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002848#else
2849 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002850#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002851 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson4dacd192001-06-06 21:11:44 +00002852 save_residual_sample = residual_sample;
2853 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
Josh Coalson352e0f62001-03-20 22:55:50 +00002854#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002855#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson4dacd192001-06-06 21:11:44 +00002856 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002857#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002858 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002859#endif
2860#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002861 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 +00002862#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002863 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002864#ifndef NO_RICE_SEARCH
Josh Coalson4dacd192001-06-06 21:11:44 +00002865 if(rice_parameter != max_rice_parameter)
2866 residual_sample = save_residual_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00002867 if(partition_bits < best_partition_bits) {
2868 best_rice_parameter = rice_parameter;
2869 best_partition_bits = partition_bits;
2870 }
Josh Coalson2051dd42001-04-12 22:22:34 +00002871 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002872#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002873 if(search_for_escapes) {
2874 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;
2875 if(flat_bits <= best_partition_bits) {
2876 raw_bits[partition] = raw_bits_per_partition[partition];
2877 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2878 best_partition_bits = flat_bits;
2879 }
Josh Coalson2051dd42001-04-12 22:22:34 +00002880 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002881 parameters[partition] = best_rice_parameter;
2882 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002883 }
2884 }
2885
2886 *bits = bits_;
2887 return true;
2888}
Josh Coalson859bc542001-03-27 22:22:27 +00002889
Josh Coalsonf1eff452002-07-31 07:05:33 +00002890unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples)
Josh Coalson859bc542001-03-27 22:22:27 +00002891{
2892 unsigned i, shift;
Josh Coalson77e3f312001-06-23 03:03:24 +00002893 FLAC__int32 x = 0;
Josh Coalson859bc542001-03-27 22:22:27 +00002894
2895 for(i = 0; i < samples && !(x&1); i++)
2896 x |= signal[i];
2897
2898 if(x == 0) {
2899 shift = 0;
2900 }
2901 else {
2902 for(shift = 0; !(x&1); shift++)
2903 x >>= 1;
2904 }
2905
2906 if(shift > 0) {
2907 for(i = 0; i < samples; i++)
2908 signal[i] >>= shift;
2909 }
2910
2911 return shift;
2912}
Josh Coalsond86e03b2002-08-03 21:56:15 +00002913
2914void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
2915{
2916 unsigned channel;
2917
2918 for(channel = 0; channel < channels; channel++)
2919 memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples);
2920
2921 fifo->tail += wide_samples;
2922
2923 FLAC__ASSERT(fifo->tail <= fifo->size);
2924}
2925
2926void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
2927{
2928 unsigned channel;
2929 unsigned sample, wide_sample;
2930 unsigned tail = fifo->tail;
2931
2932 sample = input_offset * channels;
2933 for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
2934 for(channel = 0; channel < channels; channel++)
2935 fifo->data[channel][tail] = input[sample++];
2936 tail++;
2937 }
2938 fifo->tail = tail;
2939
2940 FLAC__ASSERT(fifo->tail <= fifo->size);
2941}
2942
2943FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
2944{
2945 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
2946 const unsigned encoded_bytes = encoder->private_->verify.output.bytes;
2947 (void)decoder;
2948
2949 if(encoder->private_->verify.needs_magic_hack) {
2950 FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH);
2951 *bytes = FLAC__STREAM_SYNC_LENGTH;
2952 memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes);
2953 encoder->private_->verify.needs_magic_hack = false;
2954 }
2955 else {
2956 if(encoded_bytes == 0) {
Josh Coalsonfc2b7372002-08-16 05:39:34 +00002957 /*
2958 * If we get here, a FIFO underflow has occurred,
2959 * which means there is a bug somewhere.
2960 */
2961 FLAC__ASSERT(0);
Josh Coalsond86e03b2002-08-03 21:56:15 +00002962 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
2963 }
2964 else if(encoded_bytes < *bytes)
2965 *bytes = encoded_bytes;
2966 memcpy(buffer, encoder->private_->verify.output.data, *bytes);
2967 encoder->private_->verify.output.data += *bytes;
2968 encoder->private_->verify.output.bytes -= *bytes;
2969 }
2970
2971 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
2972}
2973
2974FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
2975{
2976 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data;
2977 unsigned channel;
2978 const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
2979 const unsigned blocksize = frame->header.blocksize;
2980 const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize;
2981
2982 for(channel = 0; channel < channels; channel++) {
2983 if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) {
2984 unsigned i, sample = 0;
2985 FLAC__int32 expect = 0, got = 0;
2986
2987 for(i = 0; i < blocksize; i++) {
2988 if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) {
2989 sample = i;
2990 expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i];
2991 got = (FLAC__int32)buffer[channel][i];
2992 break;
2993 }
2994 }
2995 FLAC__ASSERT(i < blocksize);
2996 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
2997 encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample;
Josh Coalson5f39e9f2002-08-21 05:27:01 +00002998 encoder->private_->verify.error_stats.frame_number = (unsigned)(frame->header.number.sample_number / blocksize);
Josh Coalsond86e03b2002-08-03 21:56:15 +00002999 encoder->private_->verify.error_stats.channel = channel;
3000 encoder->private_->verify.error_stats.sample = sample;
3001 encoder->private_->verify.error_stats.expected = expect;
3002 encoder->private_->verify.error_stats.got = got;
3003 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA;
3004 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
3005 }
3006 }
3007 /* dequeue the frame from the fifo */
3008 for(channel = 0; channel < channels; channel++) {
3009 memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail - blocksize);
3010 }
3011 encoder->private_->verify.input_fifo.tail -= blocksize;
3012 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
3013}
3014
3015void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
3016{
3017 (void)decoder, (void)metadata, (void)client_data;
3018}
3019
3020void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
3021{
3022 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3023 (void)decoder, (void)status;
3024 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
3025}