blob: f69e45b2bfa83bd4a72a434812b2ddb75b6fddfa [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",
Josh Coalson20ac2c12002-08-30 05:47:14 +0000396 "FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER",
Josh Coalson0a15c142001-06-13 17:59:57 +0000397 "FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION",
398 "FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH",
399 "FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
400 "FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE",
401 "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
402 "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
403 "FLAC__STREAM_ENCODER_FRAMING_ERROR",
Josh Coalson66075c12002-06-01 05:39:38 +0000404 "FLAC__STREAM_ENCODER_INVALID_METADATA",
Josh Coalson0a15c142001-06-13 17:59:57 +0000405 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
406 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
407 "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
408 "FLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
409 "FLAC__STREAM_ENCODER_UNINITIALIZED"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000410};
411
Josh Coalson57ba6f42002-06-07 05:27:37 +0000412const char * const FLAC__StreamEncoderWriteStatusString[] = {
Josh Coalson5c491a12002-08-01 06:39:40 +0000413 "FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
414 "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000415};
416
Josh Coalson0a15c142001-06-13 17:59:57 +0000417/***********************************************************************
418 *
419 * Class constructor/destructor
420 *
Josh Coalsond86e03b2002-08-03 21:56:15 +0000421 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000422FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000423{
Josh Coalson0a15c142001-06-13 17:59:57 +0000424 FLAC__StreamEncoder *encoder;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000425 unsigned i;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000426
Josh Coalson0a15c142001-06-13 17:59:57 +0000427 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000428
Josh Coalson0a15c142001-06-13 17:59:57 +0000429 encoder = (FLAC__StreamEncoder*)malloc(sizeof(FLAC__StreamEncoder));
430 if(encoder == 0) {
431 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000432 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000433 memset(encoder, 0, sizeof(FLAC__StreamEncoder));
434
Josh Coalsonfa697a92001-08-16 20:07:29 +0000435 encoder->protected_ = (FLAC__StreamEncoderProtected*)malloc(sizeof(FLAC__StreamEncoderProtected));
436 if(encoder->protected_ == 0) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000437 free(encoder);
438 return 0;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000439 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000440 memset(encoder->protected_, 0, sizeof(FLAC__StreamEncoderProtected));
441
Josh Coalsonfa697a92001-08-16 20:07:29 +0000442 encoder->private_ = (FLAC__StreamEncoderPrivate*)malloc(sizeof(FLAC__StreamEncoderPrivate));
443 if(encoder->private_ == 0) {
444 free(encoder->protected_);
Josh Coalson0a15c142001-06-13 17:59:57 +0000445 free(encoder);
446 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000447 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000448 memset(encoder->private_, 0, sizeof(FLAC__StreamEncoderPrivate));
449
Josh Coalsonaec256b2002-03-12 16:19:54 +0000450 encoder->private_->frame = FLAC__bitbuffer_new();
451 if(encoder->private_->frame == 0) {
452 free(encoder->private_);
453 free(encoder->protected_);
454 free(encoder);
455 return 0;
456 }
Josh Coalsond98c43d2001-05-13 05:17:01 +0000457
Josh Coalsonf1eff452002-07-31 07:05:33 +0000458 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000459
Josh Coalson3262b0d2002-08-14 20:58:42 +0000460 encoder->private_->is_being_deleted = false;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000461
462 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
463 encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
464 encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
465 }
466 for(i = 0; i < 2; i++) {
467 encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
468 encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
469 }
470 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000471 encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
472 encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000473 }
474 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000475 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
476 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 +0000477 }
478
479 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000480 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
481 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000482 }
483 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000484 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
485 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 +0000486 }
487 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000488 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000489
Josh Coalsonfa697a92001-08-16 20:07:29 +0000490 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000491
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000492 return encoder;
493}
494
Josh Coalson0a15c142001-06-13 17:59:57 +0000495void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000496{
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000497 unsigned i;
498
Josh Coalsonf1eff452002-07-31 07:05:33 +0000499 FLAC__ASSERT(0 != encoder);
500 FLAC__ASSERT(0 != encoder->protected_);
501 FLAC__ASSERT(0 != encoder->private_);
502 FLAC__ASSERT(0 != encoder->private_->frame);
Josh Coalson0a15c142001-06-13 17:59:57 +0000503
Josh Coalson3262b0d2002-08-14 20:58:42 +0000504 encoder->private_->is_being_deleted = true;
505
506 FLAC__stream_encoder_finish(encoder);
507
Josh Coalsond86e03b2002-08-03 21:56:15 +0000508 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
509 FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000510
511 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000512 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
513 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000514 }
515 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000516 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
517 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 +0000518 }
519 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000520 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000521
Josh Coalsonaec256b2002-03-12 16:19:54 +0000522 FLAC__bitbuffer_delete(encoder->private_->frame);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000523 free(encoder->private_);
524 free(encoder->protected_);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000525 free(encoder);
526}
527
Josh Coalson0a15c142001-06-13 17:59:57 +0000528/***********************************************************************
529 *
530 * Public class methods
531 *
532 ***********************************************************************/
533
Josh Coalson00e53872001-06-16 07:32:25 +0000534FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000535{
536 unsigned i;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000537 FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000538
Josh Coalsonf1eff452002-07-31 07:05:33 +0000539 FLAC__ASSERT(0 != encoder);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000540
Josh Coalsonfa697a92001-08-16 20:07:29 +0000541 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
542 return encoder->protected_->state = FLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000543
Josh Coalsonfa697a92001-08-16 20:07:29 +0000544 encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000545
Josh Coalsonfa697a92001-08-16 20:07:29 +0000546 if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
547 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_CALLBACK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000548
Josh Coalsonfa697a92001-08-16 20:07:29 +0000549 if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
550 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson69f1ee02001-01-24 00:54:43 +0000551
Josh Coalsonfa697a92001-08-16 20:07:29 +0000552 if(encoder->protected_->do_mid_side_stereo && encoder->protected_->channels != 2)
553 return encoder->protected_->state = FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH;
Josh Coalsond37d1352001-05-30 23:09:31 +0000554
Josh Coalsonfa697a92001-08-16 20:07:29 +0000555 if(encoder->protected_->loose_mid_side_stereo && !encoder->protected_->do_mid_side_stereo)
556 return encoder->protected_->state = FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000557
Josh Coalsonfa697a92001-08-16 20:07:29 +0000558 if(encoder->protected_->bits_per_sample >= 32)
559 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 +0000560
Josh Coalson76c68bc2002-05-17 06:22:02 +0000561 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 +0000562 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000563
Josh Coalson0833f342002-07-15 05:31:55 +0000564 if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000565 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000566
Josh Coalsonfa697a92001-08-16 20:07:29 +0000567 if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
568 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE;
Josh Coalson0a15c142001-06-13 17:59:57 +0000569
Josh Coalson20ac2c12002-08-30 05:47:14 +0000570 if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
571 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER;
572
Josh Coalsonfa697a92001-08-16 20:07:29 +0000573 if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
574 return encoder->protected_->state = FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
Josh Coalson0a15c142001-06-13 17:59:57 +0000575
Josh Coalsonfa697a92001-08-16 20:07:29 +0000576 if(encoder->protected_->qlp_coeff_precision == 0) {
577 if(encoder->protected_->bits_per_sample < 16) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000578 /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
579 /* @@@ until then we'll make a guess */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000580 encoder->protected_->qlp_coeff_precision = max(5, 2 + encoder->protected_->bits_per_sample / 2);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000581 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000582 else if(encoder->protected_->bits_per_sample == 16) {
583 if(encoder->protected_->blocksize <= 192)
584 encoder->protected_->qlp_coeff_precision = 7;
585 else if(encoder->protected_->blocksize <= 384)
586 encoder->protected_->qlp_coeff_precision = 8;
587 else if(encoder->protected_->blocksize <= 576)
588 encoder->protected_->qlp_coeff_precision = 9;
589 else if(encoder->protected_->blocksize <= 1152)
590 encoder->protected_->qlp_coeff_precision = 10;
591 else if(encoder->protected_->blocksize <= 2304)
592 encoder->protected_->qlp_coeff_precision = 11;
593 else if(encoder->protected_->blocksize <= 4608)
594 encoder->protected_->qlp_coeff_precision = 12;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000595 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000596 encoder->protected_->qlp_coeff_precision = 13;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000597 }
598 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000599 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 +0000600 }
601 }
Josh Coalson20ac2c12002-08-30 05:47:14 +0000602 else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision >= (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000603 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000604
Josh Coalsonfa697a92001-08-16 20:07:29 +0000605 if(encoder->protected_->streamable_subset) {
Josh Coalson20ac2c12002-08-30 05:47:14 +0000606 if(
607 encoder->protected_->blocksize != 192 &&
608 encoder->protected_->blocksize != 576 &&
609 encoder->protected_->blocksize != 1152 &&
610 encoder->protected_->blocksize != 2304 &&
611 encoder->protected_->blocksize != 4608 &&
612 encoder->protected_->blocksize != 256 &&
613 encoder->protected_->blocksize != 512 &&
614 encoder->protected_->blocksize != 1024 &&
615 encoder->protected_->blocksize != 2048 &&
616 encoder->protected_->blocksize != 4096 &&
617 encoder->protected_->blocksize != 8192 &&
618 encoder->protected_->blocksize != 16384
619 )
Josh Coalsonfa697a92001-08-16 20:07:29 +0000620 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalson20ac2c12002-08-30 05:47:14 +0000621 if(
622 encoder->protected_->sample_rate != 8000 &&
623 encoder->protected_->sample_rate != 16000 &&
624 encoder->protected_->sample_rate != 22050 &&
625 encoder->protected_->sample_rate != 24000 &&
626 encoder->protected_->sample_rate != 32000 &&
627 encoder->protected_->sample_rate != 44100 &&
628 encoder->protected_->sample_rate != 48000 &&
629 encoder->protected_->sample_rate != 96000
630 )
631 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
632 if(
633 encoder->protected_->bits_per_sample != 8 &&
634 encoder->protected_->bits_per_sample != 12 &&
635 encoder->protected_->bits_per_sample != 16 &&
636 encoder->protected_->bits_per_sample != 20 &&
637 encoder->protected_->bits_per_sample != 24
638 )
639 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
640 if(encoder->protected_->max_residual_partition_order > 8)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000641 return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000642 }
643
Josh Coalsonfa697a92001-08-16 20:07:29 +0000644 if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
645 encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
646 if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
647 encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000648
Josh Coalson66075c12002-06-01 05:39:38 +0000649 /* validate metadata */
650 if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
651 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000652 metadata_has_seektable = false;
653 metadata_has_vorbis_comment = false;
Josh Coalson66075c12002-06-01 05:39:38 +0000654 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
655 if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
656 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
657 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000658 if(metadata_has_seektable) /* only one is allowed */
659 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
660 metadata_has_seektable = true;
Josh Coalson0833f342002-07-15 05:31:55 +0000661 if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table))
Josh Coalson66075c12002-06-01 05:39:38 +0000662 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
663 }
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000664 else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
665 if(metadata_has_vorbis_comment) /* only one is allowed */
666 return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
667 metadata_has_vorbis_comment = true;
668 }
Josh Coalson66075c12002-06-01 05:39:38 +0000669 }
670
Josh Coalsonfa697a92001-08-16 20:07:29 +0000671 encoder->private_->input_capacity = 0;
672 for(i = 0; i < encoder->protected_->channels; i++) {
673 encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
674 encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000675 }
676 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000677 encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
678 encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000679 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000680 for(i = 0; i < encoder->protected_->channels; i++) {
681 encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
682 encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
683 encoder->private_->best_subframe[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000684 }
685 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000686 encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
687 encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
688 encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000689 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000690 encoder->private_->abs_residual_unaligned = encoder->private_->abs_residual = 0;
691 encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
692 encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
693 encoder->private_->loose_mid_side_stereo_frames_exact = (double)encoder->protected_->sample_rate * 0.4 / (double)encoder->protected_->blocksize;
694 encoder->private_->loose_mid_side_stereo_frames = (unsigned)(encoder->private_->loose_mid_side_stereo_frames_exact + 0.5);
695 if(encoder->private_->loose_mid_side_stereo_frames == 0)
696 encoder->private_->loose_mid_side_stereo_frames = 1;
697 encoder->private_->loose_mid_side_stereo_frame_count = 0;
698 encoder->private_->current_sample_number = 0;
699 encoder->private_->current_frame_number = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000700
Josh Coalsonfa697a92001-08-16 20:07:29 +0000701 encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
702 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? */
703 encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
Josh Coalson8395d022001-07-12 21:25:22 +0000704
Josh Coalsoncf30f502001-05-23 20:57:44 +0000705 /*
706 * get the CPU info and set the function pointers
707 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000708 FLAC__cpu_info(&encoder->private_->cpuinfo);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000709 /* first default to the non-asm routines */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000710 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
711 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
712 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
713 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000714 /* now override with asm where appropriate */
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000715#ifndef FLAC__NO_ASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000716 if(encoder->private_->cpuinfo.use_asm) {
Josh Coalsoncf30f502001-05-23 20:57:44 +0000717#ifdef FLAC__CPU_IA32
Josh Coalsonfa697a92001-08-16 20:07:29 +0000718 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
Josh Coalson034d38e2001-05-24 19:29:30 +0000719#ifdef FLAC__HAS_NASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000720 if(0 && encoder->private_->cpuinfo.data.ia32.sse) {
721 if(encoder->protected_->max_lpc_order < 4)
722 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
723 else if(encoder->protected_->max_lpc_order < 8)
724 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
725 else if(encoder->protected_->max_lpc_order < 12)
726 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000727 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000728 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000729 }
Josh Coalson395938e2001-11-15 21:53:25 +0000730 else if(encoder->private_->cpuinfo.data.ia32._3dnow)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000731 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
Josh Coalsonaa255362001-05-31 06:17:41 +0000732 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000733 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
734 if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
735 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
736 if(encoder->private_->cpuinfo.data.ia32.mmx) {
737 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
738 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 +0000739 }
740 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000741 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
742 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 +0000743 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000744#endif
Josh Coalson034d38e2001-05-24 19:29:30 +0000745#endif
Josh Coalson021ad3b2001-07-18 00:25:52 +0000746 }
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000747#endif
Josh Coalson8395d022001-07-12 21:25:22 +0000748 /* finally override based on wide-ness if necessary */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000749 if(encoder->private_->use_wide_by_block) {
750 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
Josh Coalson8395d022001-07-12 21:25:22 +0000751 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000752
Josh Coalson8395d022001-07-12 21:25:22 +0000753 /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000754 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 +0000755
Josh Coalsonf1eff452002-07-31 07:05:33 +0000756 if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000757 /* the above function sets the state for us in case of an error */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000758 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000759 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000760
761 if(!FLAC__bitbuffer_init(encoder->private_->frame))
762 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000763
764 /*
Josh Coalsond86e03b2002-08-03 21:56:15 +0000765 * Set up the verify stuff if necessary
766 */
767 if(encoder->protected_->verify) {
768 /*
769 * First, set up the fifo which will hold the
770 * original signal to compare against
771 */
772 encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize;
773 for(i = 0; i < encoder->protected_->channels; i++) {
774 if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size)))
775 return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
776 }
777 encoder->private_->verify.input_fifo.tail = 0;
778
779 /*
780 * Now set up a stream decoder for verification
781 */
782 encoder->private_->verify.decoder = FLAC__stream_decoder_new();
783 if(0 == encoder->private_->verify.decoder)
784 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
785
786 FLAC__stream_decoder_set_read_callback(encoder->private_->verify.decoder, verify_read_callback_);
787 FLAC__stream_decoder_set_write_callback(encoder->private_->verify.decoder, verify_write_callback_);
788 FLAC__stream_decoder_set_metadata_callback(encoder->private_->verify.decoder, verify_metadata_callback_);
789 FLAC__stream_decoder_set_error_callback(encoder->private_->verify.decoder, verify_error_callback_);
790 FLAC__stream_decoder_set_client_data(encoder->private_->verify.decoder, encoder);
791 if(FLAC__stream_decoder_init(encoder->private_->verify.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
792 return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
793 }
Josh Coalson589f8c72002-08-07 23:54:55 +0000794 encoder->private_->verify.error_stats.absolute_sample = 0;
795 encoder->private_->verify.error_stats.frame_number = 0;
796 encoder->private_->verify.error_stats.channel = 0;
797 encoder->private_->verify.error_stats.sample = 0;
798 encoder->private_->verify.error_stats.expected = 0;
799 encoder->private_->verify.error_stats.got = 0;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000800
801 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000802 * write the stream header
803 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000804 if(encoder->protected_->verify)
805 encoder->private_->verify.state_hint = ENCODER_IN_MAGIC;
Josh Coalsonaec256b2002-03-12 16:19:54 +0000806 if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000807 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000808 if(!write_bitbuffer_(encoder, 0)) {
809 /* the above function sets the state for us in case of an error */
810 return encoder->protected_->state;
811 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000812
Josh Coalson5c491a12002-08-01 06:39:40 +0000813 /*
814 * write the STREAMINFO metadata block
815 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000816 if(encoder->protected_->verify)
817 encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000818 encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000819 encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000820 encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
821 encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
822 encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
823 encoder->private_->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
824 encoder->private_->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
825 encoder->private_->metadata.data.stream_info.sample_rate = encoder->protected_->sample_rate;
826 encoder->private_->metadata.data.stream_info.channels = encoder->protected_->channels;
827 encoder->private_->metadata.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
828 encoder->private_->metadata.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
829 memset(encoder->private_->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
830 MD5Init(&encoder->private_->md5context);
Josh Coalson5c491a12002-08-01 06:39:40 +0000831 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
832 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
833 return false;
834 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000835 if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
Josh Coalsonfa697a92001-08-16 20:07:29 +0000836 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000837 if(!write_bitbuffer_(encoder, 0)) {
838 /* the above function sets the state for us in case of an error */
839 return encoder->protected_->state;
840 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000841
Josh Coalson5c491a12002-08-01 06:39:40 +0000842 /*
843 * Now that the STREAMINFO block is written, we can init this to an
844 * absurdly-high value...
845 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000846 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 +0000847 /* ... and clear this to 0 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000848 encoder->private_->metadata.data.stream_info.total_samples = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000849
Josh Coalson5c491a12002-08-01 06:39:40 +0000850 /*
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000851 * Check to see if the supplied metadata contains a VORBIS_COMMENT;
852 * if not, we will write an empty one (FLAC__add_metadata_block()
853 * automatically supplies the vendor string).
854 */
855 if(!metadata_has_vorbis_comment) {
856 FLAC__StreamMetadata vorbis_comment;
857 vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
858 vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0);
859 vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */
860 vorbis_comment.data.vorbis_comment.vendor_string.length = 0;
861 vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
862 vorbis_comment.data.vorbis_comment.num_comments = 0;
863 vorbis_comment.data.vorbis_comment.comments = 0;
864 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
865 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
866 return false;
867 }
868 if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame))
869 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
870 if(!write_bitbuffer_(encoder, 0)) {
871 /* the above function sets the state for us in case of an error */
872 return encoder->protected_->state;
873 }
874 }
875
876 /*
Josh Coalson5c491a12002-08-01 06:39:40 +0000877 * write the user's metadata blocks
878 */
879 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
880 encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
881 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
882 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
883 return false;
884 }
885 if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame))
886 return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000887 if(!write_bitbuffer_(encoder, 0)) {
888 /* the above function sets the state for us in case of an error */
889 return encoder->protected_->state;
890 }
Josh Coalson5c491a12002-08-01 06:39:40 +0000891 }
892
Josh Coalsond86e03b2002-08-03 21:56:15 +0000893 if(encoder->protected_->verify)
894 encoder->private_->verify.state_hint = ENCODER_IN_AUDIO;
895
Josh Coalsonfa697a92001-08-16 20:07:29 +0000896 return encoder->protected_->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000897}
898
Josh Coalson0a15c142001-06-13 17:59:57 +0000899void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000900{
Josh Coalsonf1eff452002-07-31 07:05:33 +0000901 FLAC__ASSERT(0 != encoder);
Josh Coalson2b245f22002-08-07 17:10:50 +0000902
Josh Coalsonfa697a92001-08-16 20:07:29 +0000903 if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000904 return;
Josh Coalson2b245f22002-08-07 17:10:50 +0000905
Josh Coalson3262b0d2002-08-14 20:58:42 +0000906 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000907 if(encoder->private_->current_sample_number != 0) {
908 encoder->protected_->blocksize = encoder->private_->current_sample_number;
909 process_frame_(encoder, true); /* true => is last frame */
910 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000911 }
Josh Coalson2b245f22002-08-07 17:10:50 +0000912
Josh Coalsonfa697a92001-08-16 20:07:29 +0000913 MD5Final(encoder->private_->metadata.data.stream_info.md5sum, &encoder->private_->md5context);
Josh Coalson2b245f22002-08-07 17:10:50 +0000914
Josh Coalson3262b0d2002-08-14 20:58:42 +0000915 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +0000916 encoder->private_->metadata_callback(encoder, &encoder->private_->metadata, encoder->private_->client_data);
917 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000918
Josh Coalsond86e03b2002-08-03 21:56:15 +0000919 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
920 FLAC__stream_decoder_finish(encoder->private_->verify.decoder);
921
Josh Coalsonf1eff452002-07-31 07:05:33 +0000922 free_(encoder);
923 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000924
Josh Coalsonfa697a92001-08-16 20:07:29 +0000925 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000926}
927
Josh Coalsond86e03b2002-08-03 21:56:15 +0000928FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)
929{
930 FLAC__ASSERT(0 != encoder);
931 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
932 return false;
933 encoder->protected_->verify = value;
934 return true;
935}
936
Josh Coalson16556042002-05-29 05:51:24 +0000937FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000938{
Josh Coalson92031602002-07-24 06:02:11 +0000939 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000940 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000941 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000942 encoder->protected_->streamable_subset = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000943 return true;
944}
945
Josh Coalson16556042002-05-29 05:51:24 +0000946FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000947{
Josh Coalson92031602002-07-24 06:02:11 +0000948 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000949 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000950 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000951 encoder->protected_->do_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000952 return true;
953}
954
Josh Coalson16556042002-05-29 05:51:24 +0000955FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +0000956{
Josh Coalson92031602002-07-24 06:02:11 +0000957 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000958 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000959 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000960 encoder->protected_->loose_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000961 return true;
962}
963
Josh Coalson16556042002-05-29 05:51:24 +0000964FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000965{
Josh Coalson92031602002-07-24 06:02:11 +0000966 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000967 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000968 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000969 encoder->protected_->channels = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000970 return true;
971}
972
Josh Coalson16556042002-05-29 05:51:24 +0000973FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000974{
Josh Coalson92031602002-07-24 06:02:11 +0000975 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000976 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000977 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000978 encoder->protected_->bits_per_sample = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000979 return true;
980}
981
Josh Coalson16556042002-05-29 05:51:24 +0000982FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000983{
Josh Coalson92031602002-07-24 06:02:11 +0000984 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000985 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000986 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000987 encoder->protected_->sample_rate = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000988 return true;
989}
990
Josh Coalson16556042002-05-29 05:51:24 +0000991FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +0000992{
Josh Coalson92031602002-07-24 06:02:11 +0000993 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000994 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +0000995 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000996 encoder->protected_->blocksize = value;
Josh Coalson00e53872001-06-16 07:32:25 +0000997 return true;
998}
999
Josh Coalson16556042002-05-29 05:51:24 +00001000FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001001{
Josh Coalson92031602002-07-24 06:02:11 +00001002 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001003 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001004 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001005 encoder->protected_->max_lpc_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001006 return true;
1007}
1008
Josh Coalson16556042002-05-29 05:51:24 +00001009FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001010{
Josh Coalson92031602002-07-24 06:02:11 +00001011 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001012 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001013 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001014 encoder->protected_->qlp_coeff_precision = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001015 return true;
1016}
1017
Josh Coalson16556042002-05-29 05:51:24 +00001018FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001019{
Josh Coalson92031602002-07-24 06:02:11 +00001020 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001021 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001022 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001023 encoder->protected_->do_qlp_coeff_prec_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001024 return true;
1025}
1026
Josh Coalson16556042002-05-29 05:51:24 +00001027FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson8395d022001-07-12 21:25:22 +00001028{
Josh Coalson92031602002-07-24 06:02:11 +00001029 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001030 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson8395d022001-07-12 21:25:22 +00001031 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001032#if 0
1033 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001034 encoder->protected_->do_escape_coding = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001035#else
1036 (void)value;
1037#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001038 return true;
1039}
1040
Josh Coalson16556042002-05-29 05:51:24 +00001041FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001042{
Josh Coalson92031602002-07-24 06:02:11 +00001043 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001044 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001045 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001046 encoder->protected_->do_exhaustive_model_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001047 return true;
1048}
1049
Josh Coalson16556042002-05-29 05:51:24 +00001050FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001051{
Josh Coalson92031602002-07-24 06:02:11 +00001052 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001053 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001054 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001055 encoder->protected_->min_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001056 return true;
1057}
1058
Josh Coalson16556042002-05-29 05:51:24 +00001059FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001060{
Josh Coalson92031602002-07-24 06:02:11 +00001061 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001062 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001063 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001064 encoder->protected_->max_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001065 return true;
1066}
1067
Josh Coalson16556042002-05-29 05:51:24 +00001068FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001069{
Josh Coalson92031602002-07-24 06:02:11 +00001070 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001071 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001072 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001073#if 0
1074 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001075 encoder->protected_->rice_parameter_search_dist = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001076#else
1077 (void)value;
1078#endif
Josh Coalson00e53872001-06-16 07:32:25 +00001079 return true;
1080}
1081
Josh Coalson16556042002-05-29 05:51:24 +00001082FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)
Josh Coalson00e53872001-06-16 07:32:25 +00001083{
Josh Coalson92031602002-07-24 06:02:11 +00001084 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001085 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001086 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001087 encoder->protected_->total_samples_estimate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001088 return true;
1089}
1090
Josh Coalsoncc682512002-06-08 04:53:42 +00001091FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
Josh Coalson00e53872001-06-16 07:32:25 +00001092{
Josh Coalson92031602002-07-24 06:02:11 +00001093 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001094 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001095 return false;
Josh Coalson66075c12002-06-01 05:39:38 +00001096 encoder->protected_->metadata = metadata;
1097 encoder->protected_->num_metadata_blocks = num_blocks;
Josh Coalson00e53872001-06-16 07:32:25 +00001098 return true;
1099}
1100
Josh Coalson681c2932002-08-01 08:19:37 +00001101FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001102{
Josh Coalson92031602002-07-24 06:02:11 +00001103 FLAC__ASSERT(0 != encoder);
1104 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001105 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001106 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001107 encoder->private_->write_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001108 return true;
1109}
1110
Josh Coalson681c2932002-08-01 08:19:37 +00001111FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderMetadataCallback value)
Josh Coalson00e53872001-06-16 07:32:25 +00001112{
Josh Coalson92031602002-07-24 06:02:11 +00001113 FLAC__ASSERT(0 != encoder);
1114 FLAC__ASSERT(0 != value);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001115 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001116 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001117 encoder->private_->metadata_callback = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001118 return true;
1119}
1120
Josh Coalson16556042002-05-29 05:51:24 +00001121FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value)
Josh Coalson00e53872001-06-16 07:32:25 +00001122{
Josh Coalson92031602002-07-24 06:02:11 +00001123 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001124 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001125 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001126 encoder->private_->client_data = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001127 return true;
1128}
1129
1130FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001131{
Josh Coalson92031602002-07-24 06:02:11 +00001132 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001133 return encoder->protected_->state;
Josh Coalson0a15c142001-06-13 17:59:57 +00001134}
1135
Josh Coalsond86e03b2002-08-03 21:56:15 +00001136FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder)
1137{
1138 FLAC__ASSERT(0 != encoder);
1139 if(encoder->protected_->verify)
1140 return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder);
1141 else
1142 return FLAC__STREAM_DECODER_UNINITIALIZED;
1143}
1144
Josh Coalson589f8c72002-08-07 23:54:55 +00001145void 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)
1146{
1147 FLAC__ASSERT(0 != encoder);
1148 if(0 != absolute_sample)
1149 *absolute_sample = encoder->private_->verify.error_stats.absolute_sample;
1150 if(0 != frame_number)
1151 *frame_number = encoder->private_->verify.error_stats.frame_number;
1152 if(0 != channel)
1153 *channel = encoder->private_->verify.error_stats.channel;
1154 if(0 != sample)
1155 *sample = encoder->private_->verify.error_stats.sample;
1156 if(0 != expected)
1157 *expected = encoder->private_->verify.error_stats.expected;
1158 if(0 != got)
1159 *got = encoder->private_->verify.error_stats.got;
1160}
1161
Josh Coalsond86e03b2002-08-03 21:56:15 +00001162FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder)
1163{
1164 FLAC__ASSERT(0 != encoder);
1165 return encoder->protected_->verify;
1166}
1167
Josh Coalson77e3f312001-06-23 03:03:24 +00001168FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001169{
Josh Coalson92031602002-07-24 06:02:11 +00001170 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001171 return encoder->protected_->streamable_subset;
Josh Coalson0a15c142001-06-13 17:59:57 +00001172}
1173
Josh Coalson77e3f312001-06-23 03:03:24 +00001174FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001175{
Josh Coalson92031602002-07-24 06:02:11 +00001176 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001177 return encoder->protected_->do_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001178}
1179
Josh Coalson77e3f312001-06-23 03:03:24 +00001180FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001181{
Josh Coalson92031602002-07-24 06:02:11 +00001182 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001183 return encoder->protected_->loose_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001184}
1185
Josh Coalson00e53872001-06-16 07:32:25 +00001186unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001187{
Josh Coalson92031602002-07-24 06:02:11 +00001188 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001189 return encoder->protected_->channels;
Josh Coalson0a15c142001-06-13 17:59:57 +00001190}
1191
Josh Coalson00e53872001-06-16 07:32:25 +00001192unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001193{
Josh Coalson92031602002-07-24 06:02:11 +00001194 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001195 return encoder->protected_->bits_per_sample;
Josh Coalson0a15c142001-06-13 17:59:57 +00001196}
1197
Josh Coalson00e53872001-06-16 07:32:25 +00001198unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001199{
Josh Coalson92031602002-07-24 06:02:11 +00001200 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001201 return encoder->protected_->sample_rate;
Josh Coalson0a15c142001-06-13 17:59:57 +00001202}
1203
Josh Coalson00e53872001-06-16 07:32:25 +00001204unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001205{
Josh Coalson92031602002-07-24 06:02:11 +00001206 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001207 return encoder->protected_->blocksize;
Josh Coalson0a15c142001-06-13 17:59:57 +00001208}
1209
Josh Coalson00e53872001-06-16 07:32:25 +00001210unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001211{
Josh Coalson92031602002-07-24 06:02:11 +00001212 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001213 return encoder->protected_->max_lpc_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001214}
1215
Josh Coalson00e53872001-06-16 07:32:25 +00001216unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001217{
Josh Coalson92031602002-07-24 06:02:11 +00001218 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001219 return encoder->protected_->qlp_coeff_precision;
Josh Coalson0a15c142001-06-13 17:59:57 +00001220}
1221
Josh Coalson77e3f312001-06-23 03:03:24 +00001222FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001223{
Josh Coalson92031602002-07-24 06:02:11 +00001224 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001225 return encoder->protected_->do_qlp_coeff_prec_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001226}
1227
Josh Coalson8395d022001-07-12 21:25:22 +00001228FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder)
1229{
Josh Coalson92031602002-07-24 06:02:11 +00001230 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001231 return encoder->protected_->do_escape_coding;
Josh Coalson8395d022001-07-12 21:25:22 +00001232}
1233
Josh Coalson77e3f312001-06-23 03:03:24 +00001234FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001235{
Josh Coalson92031602002-07-24 06:02:11 +00001236 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001237 return encoder->protected_->do_exhaustive_model_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001238}
1239
Josh Coalson00e53872001-06-16 07:32:25 +00001240unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001241{
Josh Coalson92031602002-07-24 06:02:11 +00001242 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001243 return encoder->protected_->min_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001244}
1245
Josh Coalson00e53872001-06-16 07:32:25 +00001246unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001247{
Josh Coalson92031602002-07-24 06:02:11 +00001248 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001249 return encoder->protected_->max_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001250}
1251
Josh Coalson00e53872001-06-16 07:32:25 +00001252unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001253{
Josh Coalson92031602002-07-24 06:02:11 +00001254 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001255 return encoder->protected_->rice_parameter_search_dist;
Josh Coalson0a15c142001-06-13 17:59:57 +00001256}
1257
Josh Coalson3a7b2c92002-08-02 07:38:20 +00001258FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder)
1259{
1260 FLAC__ASSERT(0 != encoder);
1261 return encoder->protected_->total_samples_estimate;
1262}
1263
Josh Coalson57ba6f42002-06-07 05:27:37 +00001264FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001265{
1266 unsigned i, j, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001267 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001268 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001269
Josh Coalsonf1eff452002-07-31 07:05:33 +00001270 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001271 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001272
1273 j = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001274 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001275 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001276 if(encoder->protected_->verify)
1277 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1278
Josh Coalsonfa697a92001-08-16 20:07:29 +00001279 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001280 x = mid = side = buffer[0][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001281 encoder->private_->integer_signal[0][i] = x;
1282 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001283 x = buffer[1][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001284 encoder->private_->integer_signal[1][i] = x;
1285 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001286 mid += x;
1287 side -= x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001288 mid >>= 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001289 encoder->private_->integer_signal_mid_side[1][i] = side;
1290 encoder->private_->integer_signal_mid_side[0][i] = mid;
1291 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1292 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1293 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001294 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001295 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001296 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001297 return false;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001298 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001299 } while(j < samples);
1300 }
1301 else {
1302 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001303 if(encoder->protected_->verify)
1304 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1305
Josh Coalsonfa697a92001-08-16 20:07:29 +00001306 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001307 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001308 x = buffer[channel][j];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001309 encoder->private_->integer_signal[channel][i] = x;
1310 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001311 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001312 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001313 }
1314 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001315 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001316 return false;
1317 }
1318 } while(j < samples);
1319 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001320
1321 return true;
1322}
1323
Josh Coalson57ba6f42002-06-07 05:27:37 +00001324FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001325{
1326 unsigned i, j, k, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001327 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001328 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001329
Josh Coalsonf1eff452002-07-31 07:05:33 +00001330 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001331 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001332
1333 j = k = 0;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001334 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001335 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001336 if(encoder->protected_->verify)
1337 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1338
Josh Coalsonfa697a92001-08-16 20:07:29 +00001339 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001340 x = mid = side = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001341 encoder->private_->integer_signal[0][i] = x;
1342 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson57ba6f42002-06-07 05:27:37 +00001343 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001344 encoder->private_->integer_signal[1][i] = x;
1345 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001346 mid += x;
1347 side -= x;
1348 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001349 encoder->private_->integer_signal_mid_side[1][i] = side;
1350 encoder->private_->integer_signal_mid_side[0][i] = mid;
1351 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1352 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
1353 encoder->private_->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001354 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001355 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001356 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001357 return false;
1358 }
1359 } while(j < samples);
1360 }
1361 else {
1362 do {
Josh Coalsond86e03b2002-08-03 21:56:15 +00001363 if(encoder->protected_->verify)
1364 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1365
Josh Coalsonfa697a92001-08-16 20:07:29 +00001366 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +00001367 for(channel = 0; channel < channels; channel++) {
Josh Coalson57ba6f42002-06-07 05:27:37 +00001368 x = buffer[k++];
Josh Coalsonfa697a92001-08-16 20:07:29 +00001369 encoder->private_->integer_signal[channel][i] = x;
1370 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +00001371 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001372 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001373 }
1374 if(i == blocksize) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001375 if(!process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +00001376 return false;
1377 }
1378 } while(j < samples);
1379 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001380
1381 return true;
1382}
1383
Josh Coalsonf1eff452002-07-31 07:05:33 +00001384/***********************************************************************
1385 *
1386 * Private class methods
1387 *
1388 ***********************************************************************/
1389
1390void set_defaults_(FLAC__StreamEncoder *encoder)
Josh Coalson92031602002-07-24 06:02:11 +00001391{
1392 FLAC__ASSERT(0 != encoder);
1393
Josh Coalsond86e03b2002-08-03 21:56:15 +00001394 encoder->protected_->verify = false;
Josh Coalson92031602002-07-24 06:02:11 +00001395 encoder->protected_->streamable_subset = true;
1396 encoder->protected_->do_mid_side_stereo = false;
1397 encoder->protected_->loose_mid_side_stereo = false;
1398 encoder->protected_->channels = 2;
1399 encoder->protected_->bits_per_sample = 16;
1400 encoder->protected_->sample_rate = 44100;
1401 encoder->protected_->blocksize = 1152;
1402 encoder->protected_->max_lpc_order = 0;
1403 encoder->protected_->qlp_coeff_precision = 0;
1404 encoder->protected_->do_qlp_coeff_prec_search = false;
1405 encoder->protected_->do_exhaustive_model_search = false;
1406 encoder->protected_->do_escape_coding = false;
1407 encoder->protected_->min_residual_partition_order = 0;
1408 encoder->protected_->max_residual_partition_order = 0;
1409 encoder->protected_->rice_parameter_search_dist = 0;
1410 encoder->protected_->total_samples_estimate = 0;
1411 encoder->protected_->metadata = 0;
1412 encoder->protected_->num_metadata_blocks = 0;
1413
1414 encoder->private_->write_callback = 0;
1415 encoder->private_->metadata_callback = 0;
1416 encoder->private_->client_data = 0;
1417}
1418
Josh Coalsonf1eff452002-07-31 07:05:33 +00001419void free_(FLAC__StreamEncoder *encoder)
Josh Coalson639aeb02002-07-25 05:38:23 +00001420{
1421 unsigned i, channel;
1422
Josh Coalsonf1eff452002-07-31 07:05:33 +00001423 FLAC__ASSERT(0 != encoder);
Josh Coalson639aeb02002-07-25 05:38:23 +00001424 for(i = 0; i < encoder->protected_->channels; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001425 if(0 != encoder->private_->integer_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001426 free(encoder->private_->integer_signal_unaligned[i]);
1427 encoder->private_->integer_signal_unaligned[i] = 0;
1428 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001429 if(0 != encoder->private_->real_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001430 free(encoder->private_->real_signal_unaligned[i]);
1431 encoder->private_->real_signal_unaligned[i] = 0;
1432 }
1433 }
1434 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001435 if(0 != encoder->private_->integer_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001436 free(encoder->private_->integer_signal_mid_side_unaligned[i]);
1437 encoder->private_->integer_signal_mid_side_unaligned[i] = 0;
1438 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001439 if(0 != encoder->private_->real_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001440 free(encoder->private_->real_signal_mid_side_unaligned[i]);
1441 encoder->private_->real_signal_mid_side_unaligned[i] = 0;
1442 }
1443 }
1444 for(channel = 0; channel < encoder->protected_->channels; channel++) {
1445 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001446 if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001447 free(encoder->private_->residual_workspace_unaligned[channel][i]);
1448 encoder->private_->residual_workspace_unaligned[channel][i] = 0;
1449 }
1450 }
1451 }
1452 for(channel = 0; channel < 2; channel++) {
1453 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001454 if(0 != encoder->private_->residual_workspace_mid_side_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001455 free(encoder->private_->residual_workspace_mid_side_unaligned[channel][i]);
1456 encoder->private_->residual_workspace_mid_side_unaligned[channel][i] = 0;
1457 }
1458 }
1459 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001460 if(0 != encoder->private_->abs_residual_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001461 free(encoder->private_->abs_residual_unaligned);
1462 encoder->private_->abs_residual_unaligned = 0;
1463 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001464 if(0 != encoder->private_->abs_residual_partition_sums_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001465 free(encoder->private_->abs_residual_partition_sums_unaligned);
1466 encoder->private_->abs_residual_partition_sums_unaligned = 0;
1467 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00001468 if(0 != encoder->private_->raw_bits_per_partition_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001469 free(encoder->private_->raw_bits_per_partition_unaligned);
1470 encoder->private_->raw_bits_per_partition_unaligned = 0;
1471 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001472 if(encoder->protected_->verify) {
1473 for(i = 0; i < encoder->protected_->channels; i++) {
1474 if(0 != encoder->private_->verify.input_fifo.data[i]) {
1475 free(encoder->private_->verify.input_fifo.data[i]);
1476 encoder->private_->verify.input_fifo.data[i] = 0;
1477 }
1478 }
1479 }
Josh Coalson639aeb02002-07-25 05:38:23 +00001480 FLAC__bitbuffer_free(encoder->private_->frame);
1481}
1482
Josh Coalsonf1eff452002-07-31 07:05:33 +00001483FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001484{
Josh Coalson77e3f312001-06-23 03:03:24 +00001485 FLAC__bool ok;
Josh Coalson0a15c142001-06-13 17:59:57 +00001486 unsigned i, channel;
1487
1488 FLAC__ASSERT(new_size > 0);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001489 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
1490 FLAC__ASSERT(encoder->private_->current_sample_number == 0);
Josh Coalson0a15c142001-06-13 17:59:57 +00001491
1492 /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001493 if(new_size <= encoder->private_->input_capacity)
Josh Coalson0a15c142001-06-13 17:59:57 +00001494 return true;
1495
1496 ok = true;
Josh Coalson8395d022001-07-12 21:25:22 +00001497
1498 /* 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. */
1499
Josh Coalsonfa697a92001-08-16 20:07:29 +00001500 for(i = 0; ok && i < encoder->protected_->channels; i++) {
1501 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size+4, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]);
1502 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]);
1503 memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4);
1504 encoder->private_->integer_signal[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001505 }
1506 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001507 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]);
1508 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]);
1509 memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4);
1510 encoder->private_->integer_signal_mid_side[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00001511 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001512 for(channel = 0; ok && channel < encoder->protected_->channels; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001513 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001514 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 +00001515 }
1516 }
1517 for(channel = 0; ok && channel < 2; channel++) {
1518 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001519 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 +00001520 }
1521 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001522 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->private_->abs_residual_unaligned, &encoder->private_->abs_residual);
1523 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 */
1524 ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_size * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums);
1525 if(encoder->protected_->do_escape_coding)
1526 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 +00001527
1528 if(ok)
Josh Coalsonfa697a92001-08-16 20:07:29 +00001529 encoder->private_->input_capacity = new_size;
Josh Coalson0a15c142001-06-13 17:59:57 +00001530 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00001531 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson0a15c142001-06-13 17:59:57 +00001532
1533 return ok;
1534}
1535
Josh Coalsond86e03b2002-08-03 21:56:15 +00001536FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
Josh Coalson5c491a12002-08-01 06:39:40 +00001537{
1538 const FLAC__byte *buffer;
1539 unsigned bytes;
1540
1541 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1542
1543 FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
1544
Josh Coalsond86e03b2002-08-03 21:56:15 +00001545 if(encoder->protected_->verify) {
1546 encoder->private_->verify.output.data = buffer;
1547 encoder->private_->verify.output.bytes = bytes;
1548 if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) {
1549 encoder->private_->verify.needs_magic_hack = true;
1550 }
1551 else {
1552 if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) {
1553 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1554 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
1555 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
1556 return false;
1557 }
1558 }
1559 }
1560
1561 if(encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
1562 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
Josh Coalson5c491a12002-08-01 06:39:40 +00001563 return false;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001564 }
Josh Coalson5c491a12002-08-01 06:39:40 +00001565
1566 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
1567
Josh Coalsond86e03b2002-08-03 21:56:15 +00001568 if(samples > 0) {
1569 encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize);
1570 encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize);
1571 }
1572
Josh Coalson5c491a12002-08-01 06:39:40 +00001573 return true;
1574}
1575
Josh Coalsonf1eff452002-07-31 07:05:33 +00001576FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson0a15c142001-06-13 17:59:57 +00001577{
Josh Coalsonfa697a92001-08-16 20:07:29 +00001578 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001579
1580 /*
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001581 * Accumulate raw signal to the MD5 signature
1582 */
Josh Coalson57ba6f42002-06-07 05:27:37 +00001583 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 +00001584 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00001585 return false;
1586 }
1587
1588 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001589 * Process the frame header and subframes into the frame bitbuffer
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001590 */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001591 if(!process_subframes_(encoder, is_last_frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001592 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001593 return false;
1594 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001595
1596 /*
1597 * Zero-pad the frame to a byte_boundary
1598 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001599 if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001600 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001601 return false;
1602 }
1603
1604 /*
Josh Coalson215af572001-03-27 01:15:58 +00001605 * CRC-16 the whole thing
1606 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001607 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
1608 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 +00001609
1610 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001611 * Write it
1612 */
Josh Coalsond86e03b2002-08-03 21:56:15 +00001613 if(!write_bitbuffer_(encoder, encoder->protected_->blocksize)) {
1614 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001615 return false;
1616 }
1617
1618 /*
1619 * Get ready for the next frame
1620 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001621 encoder->private_->current_sample_number = 0;
1622 encoder->private_->current_frame_number++;
1623 encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001624
1625 return true;
1626}
1627
Josh Coalsonf1eff452002-07-31 07:05:33 +00001628FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001629{
1630 FLAC__FrameHeader frame_header;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001631 unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00001632 FLAC__bool do_independent, do_mid_side, precompute_partition_sums;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001633
1634 /*
Josh Coalson60f77d72001-04-25 02:16:36 +00001635 * Calculate the min,max Rice partition orders
Josh Coalson94e02cd2001-01-25 10:41:06 +00001636 */
1637 if(is_last_frame) {
1638 max_partition_order = 0;
1639 }
1640 else {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001641 max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize);
1642 max_partition_order = min(max_partition_order, encoder->protected_->max_residual_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001643 }
Josh Coalson60f77d72001-04-25 02:16:36 +00001644 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001645
Josh Coalsonfa697a92001-08-16 20:07:29 +00001646 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 +00001647
Josh Coalson94e02cd2001-01-25 10:41:06 +00001648 /*
1649 * Setup the frame
1650 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00001651 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001652 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001653 return false;
1654 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001655 frame_header.blocksize = encoder->protected_->blocksize;
1656 frame_header.sample_rate = encoder->protected_->sample_rate;
1657 frame_header.channels = encoder->protected_->channels;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001658 frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001659 frame_header.bits_per_sample = encoder->protected_->bits_per_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00001660 frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001661 frame_header.number.frame_number = encoder->private_->current_frame_number;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001662
1663 /*
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001664 * Figure out what channel assignments to try
1665 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001666 if(encoder->protected_->do_mid_side_stereo) {
1667 if(encoder->protected_->loose_mid_side_stereo) {
1668 if(encoder->private_->loose_mid_side_stereo_frame_count == 0) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001669 do_independent = true;
1670 do_mid_side = true;
1671 }
1672 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001673 do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001674 do_mid_side = !do_independent;
1675 }
1676 }
1677 else {
1678 do_independent = true;
1679 do_mid_side = true;
1680 }
1681 }
1682 else {
1683 do_independent = true;
1684 do_mid_side = false;
1685 }
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001686
Josh Coalson1b689822001-05-31 20:11:02 +00001687 FLAC__ASSERT(do_independent || do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001688
1689 /*
Josh Coalson82b73242001-03-28 22:17:05 +00001690 * Check for wasted bits; set effective bps for each subframe
Josh Coalson859bc542001-03-27 22:22:27 +00001691 */
1692 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001693 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001694 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001695 encoder->private_->subframe_workspace[channel][0].wasted_bits = encoder->private_->subframe_workspace[channel][1].wasted_bits = w;
1696 encoder->private_->subframe_bps[channel] = encoder->protected_->bits_per_sample - w;
Josh Coalson82b73242001-03-28 22:17:05 +00001697 }
Josh Coalson859bc542001-03-27 22:22:27 +00001698 }
1699 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001700 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson82b73242001-03-28 22:17:05 +00001701 for(channel = 0; channel < 2; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00001702 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001703 encoder->private_->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private_->subframe_workspace_mid_side[channel][1].wasted_bits = w;
1704 encoder->private_->subframe_bps_mid_side[channel] = encoder->protected_->bits_per_sample - w + (channel==0? 0:1);
Josh Coalson82b73242001-03-28 22:17:05 +00001705 }
Josh Coalson859bc542001-03-27 22:22:27 +00001706 }
1707
1708 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00001709 * First do a normal encoding pass of each independent channel
1710 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001711 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001712 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001713 if(!
1714 process_subframe_(
1715 encoder,
1716 min_partition_order,
1717 max_partition_order,
1718 precompute_partition_sums,
1719 false,
1720 &frame_header,
1721 encoder->private_->subframe_bps[channel],
1722 encoder->private_->integer_signal[channel],
1723 encoder->private_->real_signal[channel],
1724 encoder->private_->subframe_workspace_ptr[channel],
1725 encoder->private_->partitioned_rice_contents_workspace_ptr[channel],
1726 encoder->private_->residual_workspace[channel],
1727 encoder->private_->best_subframe+channel,
1728 encoder->private_->best_subframe_bits+channel
1729 )
1730 )
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001731 return false;
1732 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001733 }
1734
1735 /*
1736 * Now do mid and side channels if requested
1737 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001738 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001739 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001740
1741 for(channel = 0; channel < 2; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00001742 if(!
1743 process_subframe_(
1744 encoder,
1745 min_partition_order,
1746 max_partition_order,
1747 precompute_partition_sums,
1748 false,
1749 &frame_header,
1750 encoder->private_->subframe_bps_mid_side[channel],
1751 encoder->private_->integer_signal_mid_side[channel],
1752 encoder->private_->real_signal_mid_side[channel],
1753 encoder->private_->subframe_workspace_ptr_mid_side[channel],
1754 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel],
1755 encoder->private_->residual_workspace_mid_side[channel],
1756 encoder->private_->best_subframe_mid_side+channel,
1757 encoder->private_->best_subframe_bits_mid_side+channel
1758 )
1759 )
Josh Coalson94e02cd2001-01-25 10:41:06 +00001760 return false;
1761 }
1762 }
1763
1764 /*
1765 * Compose the frame bitbuffer
1766 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001767 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +00001768 unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
1769 FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001770 FLAC__ChannelAssignment channel_assignment;
1771
Josh Coalsonfa697a92001-08-16 20:07:29 +00001772 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001773
Josh Coalsonfa697a92001-08-16 20:07:29 +00001774 if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) {
1775 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 +00001776 }
1777 else {
1778 unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
1779 unsigned min_bits;
1780 FLAC__ChannelAssignment ca;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001781
Josh Coalson1b689822001-05-31 20:11:02 +00001782 FLAC__ASSERT(do_independent && do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001783
1784 /* We have to figure out which channel assignent results in the smallest frame */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001785 bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1];
1786 bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1];
1787 bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1];
1788 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 +00001789
1790 for(channel_assignment = 0, min_bits = bits[0], ca = 1; ca <= 3; ca++) {
1791 if(bits[ca] < min_bits) {
1792 min_bits = bits[ca];
1793 channel_assignment = ca;
1794 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001795 }
1796 }
1797
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001798 frame_header.channel_assignment = channel_assignment;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001799
Josh Coalsonaec256b2002-03-12 16:19:54 +00001800 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001801 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001802 return false;
1803 }
1804
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001805 switch(channel_assignment) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001806 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001807 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1808 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001809 break;
1810 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001811 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
1812 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001813 break;
1814 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001815 left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
1816 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001817 break;
1818 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001819 left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]];
1820 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001821 break;
1822 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001823 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001824 }
Josh Coalson82b73242001-03-28 22:17:05 +00001825
1826 switch(channel_assignment) {
1827 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001828 left_bps = encoder->private_->subframe_bps [0];
1829 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001830 break;
1831 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001832 left_bps = encoder->private_->subframe_bps [0];
1833 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001834 break;
1835 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001836 left_bps = encoder->private_->subframe_bps_mid_side[1];
1837 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001838 break;
1839 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00001840 left_bps = encoder->private_->subframe_bps_mid_side[0];
1841 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001842 break;
1843 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001844 FLAC__ASSERT(0);
Josh Coalson82b73242001-03-28 22:17:05 +00001845 }
1846
1847 /* note that encoder_add_subframe_ sets the state for us in case of an error */
Josh Coalsonf1eff452002-07-31 07:05:33 +00001848 if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001849 return false;
Josh Coalsonf1eff452002-07-31 07:05:33 +00001850 if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001851 return false;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001852 }
1853 else {
Josh Coalsonaec256b2002-03-12 16:19:54 +00001854 if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001855 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001856 return false;
1857 }
1858
Josh Coalsonfa697a92001-08-16 20:07:29 +00001859 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001860 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 +00001861 /* the above function sets the state for us in case of an error */
1862 return false;
1863 }
1864 }
1865 }
1866
Josh Coalsonfa697a92001-08-16 20:07:29 +00001867 if(encoder->protected_->loose_mid_side_stereo) {
1868 encoder->private_->loose_mid_side_stereo_frame_count++;
1869 if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames)
1870 encoder->private_->loose_mid_side_stereo_frame_count = 0;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001871 }
1872
Josh Coalsonfa697a92001-08-16 20:07:29 +00001873 encoder->private_->last_channel_assignment = frame_header.channel_assignment;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001874
Josh Coalson94e02cd2001-01-25 10:41:06 +00001875 return true;
1876}
1877
Josh Coalson6fe72f72002-08-20 04:01:59 +00001878FLAC__bool process_subframe_(
1879 FLAC__StreamEncoder *encoder,
1880 unsigned min_partition_order,
1881 unsigned max_partition_order,
1882 FLAC__bool precompute_partition_sums,
1883 FLAC__bool verbatim_only,
1884 const FLAC__FrameHeader *frame_header,
1885 unsigned subframe_bps,
1886 const FLAC__int32 integer_signal[],
1887 const FLAC__real real_signal[],
1888 FLAC__Subframe *subframe[2],
1889 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
1890 FLAC__int32 *residual[2],
1891 unsigned *best_subframe,
1892 unsigned *best_bits
1893)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001894{
Josh Coalson77e3f312001-06-23 03:03:24 +00001895 FLAC__real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
1896 FLAC__real lpc_residual_bits_per_sample;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001897 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 +00001898 FLAC__real lpc_error[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001899 unsigned min_lpc_order, max_lpc_order, lpc_order;
1900 unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
1901 unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
1902 unsigned rice_parameter;
1903 unsigned _candidate_bits, _best_bits;
1904 unsigned _best_subframe;
1905
1906 /* verbatim subframe is the baseline against which we measure other compressed subframes */
1907 _best_subframe = 0;
Josh Coalsonf1eff452002-07-31 07:05:33 +00001908 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001909
1910 if(!verbatim_only && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
1911 /* check for constant subframe */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001912 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 +00001913 if(fixed_residual_bits_per_sample[1] == 0.0) {
1914 /* the above means integer_signal+FLAC__MAX_FIXED_ORDER is constant, now we just have to check the warmup samples */
1915 unsigned i, signal_is_constant = true;
1916 for(i = 1; i <= FLAC__MAX_FIXED_ORDER; i++) {
1917 if(integer_signal[0] != integer_signal[i]) {
1918 signal_is_constant = false;
1919 break;
1920 }
1921 }
1922 if(signal_is_constant) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001923 _candidate_bits = evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001924 if(_candidate_bits < _best_bits) {
1925 _best_subframe = !_best_subframe;
1926 _best_bits = _candidate_bits;
1927 }
1928 }
1929 }
1930 else {
1931 /* encode fixed */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001932 if(encoder->protected_->do_exhaustive_model_search) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001933 min_fixed_order = 0;
1934 max_fixed_order = FLAC__MAX_FIXED_ORDER;
1935 }
1936 else {
1937 min_fixed_order = max_fixed_order = guess_fixed_order;
1938 }
1939 for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
Josh Coalson77e3f312001-06-23 03:03:24 +00001940 if(fixed_residual_bits_per_sample[fixed_order] >= (FLAC__real)subframe_bps)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001941 continue; /* don't even try */
Josh Coalson46f2ae82001-02-08 00:27:21 +00001942 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 +00001943#ifndef FLAC__SYMMETRIC_RICE
Josh Coalson46f2ae82001-02-08 00:27:21 +00001944 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00001945#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001946 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00001947#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00001948 fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
1949#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001950 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00001951 }
Josh Coalson6fe72f72002-08-20 04:01:59 +00001952 _candidate_bits =
1953 evaluate_fixed_subframe_(
1954 encoder,
1955 integer_signal,
1956 residual[!_best_subframe],
1957 encoder->private_->abs_residual,
1958 encoder->private_->abs_residual_partition_sums,
1959 encoder->private_->raw_bits_per_partition,
1960 frame_header->blocksize,
1961 subframe_bps,
1962 fixed_order,
1963 rice_parameter,
1964 min_partition_order,
1965 max_partition_order,
1966 precompute_partition_sums,
1967 encoder->protected_->do_escape_coding,
1968 encoder->protected_->rice_parameter_search_dist,
1969 subframe[!_best_subframe],
1970 partitioned_rice_contents[!_best_subframe]
1971 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00001972 if(_candidate_bits < _best_bits) {
1973 _best_subframe = !_best_subframe;
1974 _best_bits = _candidate_bits;
1975 }
1976 }
1977
1978 /* encode lpc */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001979 if(encoder->protected_->max_lpc_order > 0) {
1980 if(encoder->protected_->max_lpc_order >= frame_header->blocksize)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001981 max_lpc_order = frame_header->blocksize-1;
1982 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00001983 max_lpc_order = encoder->protected_->max_lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001984 if(max_lpc_order > 0) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00001985 encoder->private_->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001986 /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
1987 if(autoc[0] != 0.0) {
Josh Coalson8084b052001-11-01 00:27:29 +00001988 FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001989 if(encoder->protected_->do_exhaustive_model_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001990 min_lpc_order = 1;
1991 }
1992 else {
Josh Coalson82b73242001-03-28 22:17:05 +00001993 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 +00001994 min_lpc_order = max_lpc_order = guess_lpc_order;
1995 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00001996 if(encoder->protected_->do_qlp_coeff_prec_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001997 min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00001998 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 +00001999 }
2000 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002001 min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002002 }
2003 for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
2004 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 +00002005 if(lpc_residual_bits_per_sample >= (FLAC__real)subframe_bps)
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002006 continue; /* don't even try */
2007 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 +00002008#ifndef FLAC__SYMMETRIC_RICE
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002009 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00002010#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002011 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002012#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002013 fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2014#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002015 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002016 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002017 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 +00002018 _candidate_bits =
2019 evaluate_lpc_subframe_(
2020 encoder,
2021 integer_signal,
2022 residual[!_best_subframe],
2023 encoder->private_->abs_residual,
2024 encoder->private_->abs_residual_partition_sums,
2025 encoder->private_->raw_bits_per_partition,
2026 encoder->private_->lp_coeff[lpc_order-1],
2027 frame_header->blocksize,
2028 subframe_bps,
2029 lpc_order,
2030 qlp_coeff_precision,
2031 rice_parameter,
2032 min_partition_order,
2033 max_partition_order,
2034 precompute_partition_sums,
2035 encoder->protected_->do_escape_coding,
2036 encoder->protected_->rice_parameter_search_dist,
2037 subframe[!_best_subframe],
2038 partitioned_rice_contents[!_best_subframe]
2039 );
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002040 if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
2041 if(_candidate_bits < _best_bits) {
2042 _best_subframe = !_best_subframe;
2043 _best_bits = _candidate_bits;
2044 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002045 }
2046 }
2047 }
2048 }
2049 }
2050 }
2051 }
2052 }
2053
2054 *best_subframe = _best_subframe;
2055 *best_bits = _best_bits;
2056
2057 return true;
2058}
2059
Josh Coalson6fe72f72002-08-20 04:01:59 +00002060FLAC__bool add_subframe_(
2061 FLAC__StreamEncoder *encoder,
2062 const FLAC__FrameHeader *frame_header,
2063 unsigned subframe_bps,
2064 const FLAC__Subframe *subframe,
2065 FLAC__BitBuffer *frame
2066)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002067{
2068 switch(subframe->type) {
2069 case FLAC__SUBFRAME_TYPE_CONSTANT:
Josh Coalson82b73242001-03-28 22:17:05 +00002070 if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002071 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002072 return false;
2073 }
2074 break;
2075 case FLAC__SUBFRAME_TYPE_FIXED:
Josh Coalson82b73242001-03-28 22:17:05 +00002076 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 +00002077 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002078 return false;
2079 }
2080 break;
2081 case FLAC__SUBFRAME_TYPE_LPC:
Josh Coalson82b73242001-03-28 22:17:05 +00002082 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 +00002083 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002084 return false;
2085 }
2086 break;
2087 case FLAC__SUBFRAME_TYPE_VERBATIM:
Josh Coalson82b73242001-03-28 22:17:05 +00002088 if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002089 encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002090 return false;
2091 }
2092 break;
2093 default:
Josh Coalson1b689822001-05-31 20:11:02 +00002094 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002095 }
2096
2097 return true;
2098}
2099
Josh Coalson6fe72f72002-08-20 04:01:59 +00002100unsigned evaluate_constant_subframe_(
2101 const FLAC__int32 signal,
2102 unsigned subframe_bps,
2103 FLAC__Subframe *subframe
2104)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002105{
2106 subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
2107 subframe->data.constant.value = signal;
2108
Josh Coalson82b73242001-03-28 22:17:05 +00002109 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 +00002110}
2111
Josh Coalson6fe72f72002-08-20 04:01:59 +00002112unsigned evaluate_fixed_subframe_(
2113 FLAC__StreamEncoder *encoder,
2114 const FLAC__int32 signal[],
2115 FLAC__int32 residual[],
2116 FLAC__uint32 abs_residual[],
2117 FLAC__uint64 abs_residual_partition_sums[],
2118 unsigned raw_bits_per_partition[],
2119 unsigned blocksize,
2120 unsigned subframe_bps,
2121 unsigned order,
2122 unsigned rice_parameter,
2123 unsigned min_partition_order,
2124 unsigned max_partition_order,
2125 FLAC__bool precompute_partition_sums,
2126 FLAC__bool do_escape_coding,
2127 unsigned rice_parameter_search_dist,
2128 FLAC__Subframe *subframe,
2129 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2130)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002131{
2132 unsigned i, residual_bits;
2133 const unsigned residual_samples = blocksize - order;
2134
2135 FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
2136
2137 subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
2138
2139 subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002140 subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002141 subframe->data.fixed.residual = residual;
2142
Josh Coalson6fe72f72002-08-20 04:01:59 +00002143 residual_bits =
2144 find_best_partition_order_(
2145 encoder->private_,
2146 residual,
2147 abs_residual,
2148 abs_residual_partition_sums,
2149 raw_bits_per_partition,
2150 residual_samples,
2151 order,
2152 rice_parameter,
2153 min_partition_order,
2154 max_partition_order,
2155 precompute_partition_sums,
2156 do_escape_coding,
2157 rice_parameter_search_dist,
2158 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2159 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002160
2161 subframe->data.fixed.order = order;
2162 for(i = 0; i < order; i++)
2163 subframe->data.fixed.warmup[i] = signal[i];
2164
Josh Coalson82b73242001-03-28 22:17:05 +00002165 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 +00002166}
2167
Josh Coalson6fe72f72002-08-20 04:01:59 +00002168unsigned evaluate_lpc_subframe_(
2169 FLAC__StreamEncoder *encoder,
2170 const FLAC__int32 signal[],
2171 FLAC__int32 residual[],
2172 FLAC__uint32 abs_residual[],
2173 FLAC__uint64 abs_residual_partition_sums[],
2174 unsigned raw_bits_per_partition[],
2175 const FLAC__real lp_coeff[],
2176 unsigned blocksize,
2177 unsigned subframe_bps,
2178 unsigned order,
2179 unsigned qlp_coeff_precision,
2180 unsigned rice_parameter,
2181 unsigned min_partition_order,
2182 unsigned max_partition_order,
2183 FLAC__bool precompute_partition_sums,
2184 FLAC__bool do_escape_coding,
2185 unsigned rice_parameter_search_dist,
2186 FLAC__Subframe *subframe,
2187 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
2188)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002189{
Josh Coalson77e3f312001-06-23 03:03:24 +00002190 FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00002191 unsigned i, residual_bits;
2192 int quantization, ret;
2193 const unsigned residual_samples = blocksize - order;
2194
Josh Coalson20ac2c12002-08-30 05:47:14 +00002195 /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */
2196 if(subframe_bps <= 16) {
2197 FLAC__ASSERT(order > 0);
2198 FLAC__ASSERT(order <= FLAC__MAX_LPC_ORDER);
2199 qlp_coeff_precision = min(qlp_coeff_precision, 32 - subframe_bps - FLAC__bitmath_ilog2(order));
2200 }
2201
Josh Coalson82b73242001-03-28 22:17:05 +00002202 ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, subframe_bps, qlp_coeff, &quantization);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002203 if(ret != 0)
2204 return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
2205
Josh Coalson92d42402001-05-31 20:53:19 +00002206 if(subframe_bps <= 16 && qlp_coeff_precision <= 16)
Josh Coalsonfa697a92001-08-16 20:07:29 +00002207 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 +00002208 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00002209 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 +00002210
2211 subframe->type = FLAC__SUBFRAME_TYPE_LPC;
2212
2213 subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00002214 subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002215 subframe->data.lpc.residual = residual;
2216
Josh Coalson6fe72f72002-08-20 04:01:59 +00002217 residual_bits =
2218 find_best_partition_order_(
2219 encoder->private_,
2220 residual,
2221 abs_residual,
2222 abs_residual_partition_sums,
2223 raw_bits_per_partition,
2224 residual_samples,
2225 order,
2226 rice_parameter,
2227 min_partition_order,
2228 max_partition_order,
2229 precompute_partition_sums,
2230 do_escape_coding,
2231 rice_parameter_search_dist,
2232 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
2233 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00002234
2235 subframe->data.lpc.order = order;
2236 subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
2237 subframe->data.lpc.quantization_level = quantization;
Josh Coalson77e3f312001-06-23 03:03:24 +00002238 memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002239 for(i = 0; i < order; i++)
2240 subframe->data.lpc.warmup[i] = signal[i];
2241
Josh Coalson82b73242001-03-28 22:17:05 +00002242 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 +00002243}
2244
Josh Coalson6fe72f72002-08-20 04:01:59 +00002245unsigned evaluate_verbatim_subframe_(
2246 const FLAC__int32 signal[],
2247 unsigned blocksize,
2248 unsigned subframe_bps,
2249 FLAC__Subframe *subframe
2250)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002251{
2252 subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
2253
2254 subframe->data.verbatim.data = signal;
2255
Josh Coalson82b73242001-03-28 22:17:05 +00002256 return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (blocksize * subframe_bps);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002257}
2258
Josh Coalson6fe72f72002-08-20 04:01:59 +00002259unsigned find_best_partition_order_(
2260 FLAC__StreamEncoderPrivate *private_,
2261 const FLAC__int32 residual[],
2262 FLAC__uint32 abs_residual[],
2263 FLAC__uint64 abs_residual_partition_sums[],
2264 unsigned raw_bits_per_partition[],
2265 unsigned residual_samples,
2266 unsigned predictor_order,
2267 unsigned rice_parameter,
2268 unsigned min_partition_order,
2269 unsigned max_partition_order,
2270 FLAC__bool precompute_partition_sums,
2271 FLAC__bool do_escape_coding,
2272 unsigned rice_parameter_search_dist,
2273 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
2274)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002275{
Josh Coalson77e3f312001-06-23 03:03:24 +00002276 FLAC__int32 r;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002277 unsigned residual_bits, best_residual_bits = 0;
Josh Coalsonafcd8772001-04-18 22:59:25 +00002278 unsigned residual_sample;
Josh Coalson8084b052001-11-01 00:27:29 +00002279 unsigned best_parameters_index = 0;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002280 const unsigned blocksize = residual_samples + predictor_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002281
Josh Coalson2051dd42001-04-12 22:22:34 +00002282 /* compute abs(residual) for use later */
2283 for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
2284 r = residual[residual_sample];
Josh Coalson77e3f312001-06-23 03:03:24 +00002285 abs_residual[residual_sample] = (FLAC__uint32)(r<0? -r : r);
Josh Coalson2051dd42001-04-12 22:22:34 +00002286 }
2287
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002288 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 +00002289 min_partition_order = min(min_partition_order, max_partition_order);
2290
Josh Coalson8395d022001-07-12 21:25:22 +00002291 if(precompute_partition_sums) {
2292 int partition_order;
2293 unsigned sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002294
Josh Coalsonf1eff452002-07-31 07:05:33 +00002295 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 +00002296
2297 if(do_escape_coding)
Josh Coalsonf1eff452002-07-31 07:05:33 +00002298 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 +00002299
2300 for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
2301#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002302 if(!
2303 set_partitioned_rice_with_precompute_(
2304 residual,
2305 abs_residual_partition_sums+sum,
2306 raw_bits_per_partition+sum,
2307 residual_samples,
2308 predictor_order,
2309 rice_parameter,
2310 rice_parameter_search_dist,
2311 (unsigned)partition_order,
2312 do_escape_coding,
2313 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2314 &residual_bits
2315 )
2316 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002317#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002318 if(!
2319 set_partitioned_rice_with_precompute_(
2320 abs_residual,
2321 abs_residual_partition_sums+sum,
2322 raw_bits_per_partition+sum,
2323 residual_samples,
2324 predictor_order,
2325 rice_parameter,
2326 rice_parameter_search_dist,
2327 (unsigned)partition_order,
2328 do_escape_coding,
2329 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2330 &residual_bits
2331 )
2332 )
Josh Coalson8395d022001-07-12 21:25:22 +00002333#endif
2334 {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002335 FLAC__ASSERT(best_residual_bits != 0);
2336 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002337 }
2338 sum += 1u << partition_order;
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 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00002344 }
2345 }
Josh Coalson8395d022001-07-12 21:25:22 +00002346 else {
2347 unsigned partition_order;
2348 for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
2349#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002350 if(!
2351 set_partitioned_rice_(
2352 abs_residual,
2353 residual,
2354 residual_samples,
2355 predictor_order,
2356 rice_parameter,
2357 rice_parameter_search_dist,
2358 partition_order,
2359 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2360 &residual_bits
2361 )
2362 )
Josh Coalson8395d022001-07-12 21:25:22 +00002363#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002364 if(!
2365 set_partitioned_rice_(
2366 abs_residual,
2367 residual_samples,
2368 predictor_order,
2369 rice_parameter,
2370 rice_parameter_search_dist,
2371 partition_order,
2372 &private_->partitioned_rice_contents_extra[!best_parameters_index],
2373 &residual_bits
2374 )
2375 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00002376#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002377 {
2378 FLAC__ASSERT(best_residual_bits != 0);
2379 break;
2380 }
2381 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
2382 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002383 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002384 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002385 }
2386 }
2387 }
2388
Josh Coalsona37ba462002-08-19 21:36:39 +00002389 /*
Josh Coalson20ac2c12002-08-30 05:47:14 +00002390 * We are allowed to de-const the pointer based on our special knowledge;
Josh Coalsona37ba462002-08-19 21:36:39 +00002391 * it is const to the outside world.
2392 */
2393 {
2394 FLAC__EntropyCodingMethod_PartitionedRiceContents* best_partitioned_rice_contents = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_partitioned_rice->contents;
2395 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(best_partitioned_rice_contents, max(6, best_partitioned_rice->order));
2396 memcpy(best_partitioned_rice_contents->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2397 memcpy(best_partitioned_rice_contents->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
2398 }
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002399
2400 return best_residual_bits;
2401}
2402
Josh Coalson6fe72f72002-08-20 04:01:59 +00002403void precompute_partition_info_sums_(
2404 const FLAC__uint32 abs_residual[],
2405 FLAC__uint64 abs_residual_partition_sums[],
2406 unsigned residual_samples,
2407 unsigned predictor_order,
2408 unsigned min_partition_order,
2409 unsigned max_partition_order
2410)
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002411{
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002412 int partition_order;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002413 unsigned from_partition, to_partition = 0;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002414 const unsigned blocksize = residual_samples + predictor_order;
2415
Josh Coalsonaef013c2001-04-24 01:25:42 +00002416 /* first do max_partition_order */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002417 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002418 FLAC__uint64 abs_residual_partition_sum;
Josh Coalson77e3f312001-06-23 03:03:24 +00002419 FLAC__uint32 abs_r;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002420 unsigned partition, partition_sample, partition_samples, residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002421 const unsigned partitions = 1u << partition_order;
2422 const unsigned default_partition_samples = blocksize >> partition_order;
2423
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002424 FLAC__ASSERT(default_partition_samples > predictor_order);
2425
2426 for(partition = residual_sample = 0; partition < partitions; partition++) {
2427 partition_samples = default_partition_samples;
2428 if(partition == 0)
2429 partition_samples -= predictor_order;
2430 abs_residual_partition_sum = 0;
2431 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2432 abs_r = abs_residual[residual_sample];
2433 abs_residual_partition_sum += abs_r;
2434 residual_sample++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002435 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002436 abs_residual_partition_sums[partition] = abs_residual_partition_sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002437 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002438 to_partition = partitions;
2439 break;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002440 }
Josh Coalsonf76a3612001-04-18 02:28:11 +00002441
Josh Coalson8395d022001-07-12 21:25:22 +00002442 /* now merge partitions for lower orders */
Josh Coalson6bd17572001-05-25 19:02:01 +00002443 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002444 FLAC__uint64 s;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002445 unsigned i;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002446 const unsigned partitions = 1u << partition_order;
2447 for(i = 0; i < partitions; i++) {
Josh Coalsonaef013c2001-04-24 01:25:42 +00002448 s = abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002449 from_partition++;
Josh Coalsonaef013c2001-04-24 01:25:42 +00002450 abs_residual_partition_sums[to_partition] = s + abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00002451 from_partition++;
2452 to_partition++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002453 }
2454 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002455}
Josh Coalson8395d022001-07-12 21:25:22 +00002456
Josh Coalson6fe72f72002-08-20 04:01:59 +00002457void precompute_partition_info_escapes_(
2458 const FLAC__int32 residual[],
2459 unsigned raw_bits_per_partition[],
2460 unsigned residual_samples,
2461 unsigned predictor_order,
2462 unsigned min_partition_order,
2463 unsigned max_partition_order
2464)
Josh Coalson8395d022001-07-12 21:25:22 +00002465{
2466 int partition_order;
2467 unsigned from_partition, to_partition = 0;
2468 const unsigned blocksize = residual_samples + predictor_order;
2469
2470 /* first do max_partition_order */
2471 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
2472 FLAC__int32 r, residual_partition_min, residual_partition_max;
2473 unsigned silog2_min, silog2_max;
2474 unsigned partition, partition_sample, partition_samples, residual_sample;
2475 const unsigned partitions = 1u << partition_order;
2476 const unsigned default_partition_samples = blocksize >> partition_order;
2477
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002478 FLAC__ASSERT(default_partition_samples > predictor_order);
2479
2480 for(partition = residual_sample = 0; partition < partitions; partition++) {
2481 partition_samples = default_partition_samples;
2482 if(partition == 0)
2483 partition_samples -= predictor_order;
2484 residual_partition_min = residual_partition_max = 0;
2485 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
2486 r = residual[residual_sample];
2487 if(r < residual_partition_min)
2488 residual_partition_min = r;
2489 else if(r > residual_partition_max)
2490 residual_partition_max = r;
2491 residual_sample++;
Josh Coalson8395d022001-07-12 21:25:22 +00002492 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002493 silog2_min = FLAC__bitmath_silog2(residual_partition_min);
2494 silog2_max = FLAC__bitmath_silog2(residual_partition_max);
2495 raw_bits_per_partition[partition] = max(silog2_min, silog2_max);
Josh Coalson8395d022001-07-12 21:25:22 +00002496 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002497 to_partition = partitions;
2498 break;
Josh Coalson8395d022001-07-12 21:25:22 +00002499 }
2500
2501 /* now merge partitions for lower orders */
2502 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
2503 unsigned m;
2504 unsigned i;
2505 const unsigned partitions = 1u << partition_order;
2506 for(i = 0; i < partitions; i++) {
2507 m = raw_bits_per_partition[from_partition];
2508 from_partition++;
2509 raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]);
2510 from_partition++;
2511 to_partition++;
2512 }
2513 }
2514}
Josh Coalson94e02cd2001-01-25 10:41:06 +00002515
Josh Coalson352e0f62001-03-20 22:55:50 +00002516#ifdef VARIABLE_RICE_BITS
2517#undef VARIABLE_RICE_BITS
2518#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002519#ifndef DONT_ESTIMATE_RICE_BITS
Josh Coalson352e0f62001-03-20 22:55:50 +00002520#define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
Josh Coalson8395d022001-07-12 21:25:22 +00002521#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002522
Josh Coalson8395d022001-07-12 21:25:22 +00002523#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002524FLAC__bool set_partitioned_rice_(
2525 const FLAC__uint32 abs_residual[],
2526 const FLAC__int32 residual[],
2527 const unsigned residual_samples,
2528 const unsigned predictor_order,
2529 const unsigned suggested_rice_parameter,
2530 const unsigned rice_parameter_search_dist,
2531 const unsigned partition_order,
2532 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2533 unsigned *bits
2534)
Josh Coalson8395d022001-07-12 21:25:22 +00002535#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002536FLAC__bool set_partitioned_rice_(
2537 const FLAC__uint32 abs_residual[],
2538 const unsigned residual_samples,
2539 const unsigned predictor_order,
2540 const unsigned suggested_rice_parameter,
2541 const unsigned rice_parameter_search_dist,
2542 const unsigned partition_order,
2543 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2544 unsigned *bits
2545)
Josh Coalson8395d022001-07-12 21:25:22 +00002546#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002547{
Josh Coalson034dfab2001-04-27 19:10:23 +00002548 unsigned rice_parameter, partition_bits;
2549#ifndef NO_RICE_SEARCH
2550 unsigned best_partition_bits;
2551 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2552#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002553 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002554 unsigned *parameters;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002555
Josh Coalson1b689822001-05-31 20:11:02 +00002556 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
Josh Coalson2051dd42001-04-12 22:22:34 +00002557
Josh Coalsona37ba462002-08-19 21:36:39 +00002558 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2559 parameters = partitioned_rice_contents->parameters;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002560
Josh Coalson94e02cd2001-01-25 10:41:06 +00002561 if(partition_order == 0) {
2562 unsigned i;
Josh Coalson352e0f62001-03-20 22:55:50 +00002563
Josh Coalson034dfab2001-04-27 19:10:23 +00002564#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002565 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002566 if(suggested_rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002567 min_rice_parameter = 0;
2568 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002569 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2570 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002571 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002572#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002573 fprintf(stderr, "clipping rice_parameter (%u -> %u) @2\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2574#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002575 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002576 }
2577 }
2578 else
2579 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
2580
2581 best_partition_bits = 0xffffffff;
2582 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2583#endif
2584#ifdef VARIABLE_RICE_BITS
2585#ifdef FLAC__SYMMETRIC_RICE
2586 partition_bits = (2+rice_parameter) * residual_samples;
2587#else
2588 const unsigned rice_parameter_estimate = rice_parameter-1;
2589 partition_bits = (1+rice_parameter) * residual_samples;
2590#endif
2591#else
2592 partition_bits = 0;
2593#endif
2594 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2595 for(i = 0; i < residual_samples; i++) {
2596#ifdef VARIABLE_RICE_BITS
2597#ifdef FLAC__SYMMETRIC_RICE
2598 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
2599#else
2600 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
2601#endif
2602#else
2603 partition_bits += FLAC__bitbuffer_rice_bits(residual[i], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2604#endif
2605 }
2606#ifndef NO_RICE_SEARCH
2607 if(partition_bits < best_partition_bits) {
2608 best_rice_parameter = rice_parameter;
2609 best_partition_bits = partition_bits;
2610 }
2611 }
2612#endif
2613 parameters[0] = best_rice_parameter;
2614 bits_ += best_partition_bits;
2615 }
2616 else {
2617 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002618 unsigned partition_samples;
2619 FLAC__uint64 mean, k;
Josh Coalson8395d022001-07-12 21:25:22 +00002620 const unsigned partitions = 1u << partition_order;
2621 for(partition = residual_sample = 0; partition < partitions; partition++) {
2622 partition_samples = (residual_samples+predictor_order) >> partition_order;
2623 if(partition == 0) {
2624 if(partition_samples <= predictor_order)
2625 return false;
2626 else
2627 partition_samples -= predictor_order;
2628 }
2629 mean = 0;
2630 save_residual_sample = residual_sample;
2631 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++)
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002632 mean += abs_residual[residual_sample];
Josh Coalson8395d022001-07-12 21:25:22 +00002633 residual_sample = save_residual_sample;
2634#ifdef FLAC__SYMMETRIC_RICE
2635 mean += partition_samples >> 1; /* for rounding effect */
2636 mean /= partition_samples;
2637
2638 /* calc rice_parameter = floor(log2(mean)) */
2639 rice_parameter = 0;
2640 mean>>=1;
2641 while(mean) {
2642 rice_parameter++;
2643 mean >>= 1;
2644 }
2645#else
2646 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002647 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson8395d022001-07-12 21:25:22 +00002648 ;
2649#endif
2650 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002651#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002652 fprintf(stderr, "clipping rice_parameter (%u -> %u) @3\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2653#endif
2654 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2655 }
2656
2657#ifndef NO_RICE_SEARCH
2658 if(rice_parameter_search_dist) {
2659 if(rice_parameter < rice_parameter_search_dist)
2660 min_rice_parameter = 0;
2661 else
2662 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2663 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
2664 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002665#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002666 fprintf(stderr, "clipping rice_parameter (%u -> %u) @4\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2667#endif
2668 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2669 }
2670 }
2671 else
2672 min_rice_parameter = max_rice_parameter = rice_parameter;
2673
2674 best_partition_bits = 0xffffffff;
2675 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2676#endif
2677#ifdef VARIABLE_RICE_BITS
2678#ifdef FLAC__SYMMETRIC_RICE
2679 partition_bits = (2+rice_parameter) * partition_samples;
2680#else
2681 const unsigned rice_parameter_estimate = rice_parameter-1;
2682 partition_bits = (1+rice_parameter) * partition_samples;
2683#endif
2684#else
2685 partition_bits = 0;
2686#endif
2687 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
2688 save_residual_sample = residual_sample;
2689 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
2690#ifdef VARIABLE_RICE_BITS
2691#ifdef FLAC__SYMMETRIC_RICE
2692 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
2693#else
2694 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
2695#endif
2696#else
2697 partition_bits += FLAC__bitbuffer_rice_bits(residual[residual_sample], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
2698#endif
2699 }
2700#ifndef NO_RICE_SEARCH
2701 if(rice_parameter != max_rice_parameter)
2702 residual_sample = save_residual_sample;
2703 if(partition_bits < best_partition_bits) {
2704 best_rice_parameter = rice_parameter;
2705 best_partition_bits = partition_bits;
2706 }
2707 }
2708#endif
2709 parameters[partition] = best_rice_parameter;
2710 bits_ += best_partition_bits;
2711 }
2712 }
2713
2714 *bits = bits_;
2715 return true;
2716}
2717
2718#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00002719FLAC__bool set_partitioned_rice_with_precompute_(
2720 const FLAC__int32 residual[],
2721 const FLAC__uint64 abs_residual_partition_sums[],
2722 const unsigned raw_bits_per_partition[],
2723 const unsigned residual_samples,
2724 const unsigned predictor_order,
2725 const unsigned suggested_rice_parameter,
2726 const unsigned rice_parameter_search_dist,
2727 const unsigned partition_order,
2728 const FLAC__bool search_for_escapes,
2729 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2730 unsigned *bits
2731)
Josh Coalson8395d022001-07-12 21:25:22 +00002732#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00002733FLAC__bool set_partitioned_rice_with_precompute_(
2734 const FLAC__uint32 abs_residual[],
2735 const FLAC__uint64 abs_residual_partition_sums[],
2736 const unsigned raw_bits_per_partition[],
2737 const unsigned residual_samples,
2738 const unsigned predictor_order,
2739 const unsigned suggested_rice_parameter,
2740 const unsigned rice_parameter_search_dist,
2741 const unsigned partition_order,
2742 const FLAC__bool search_for_escapes,
2743 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
2744 unsigned *bits
2745)
Josh Coalson8395d022001-07-12 21:25:22 +00002746#endif
2747{
2748 unsigned rice_parameter, partition_bits;
2749#ifndef NO_RICE_SEARCH
2750 unsigned best_partition_bits;
2751 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
2752#endif
2753 unsigned flat_bits;
2754 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002755 unsigned *parameters, *raw_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00002756
2757 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
2758
Josh Coalsona37ba462002-08-19 21:36:39 +00002759 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
2760 parameters = partitioned_rice_contents->parameters;
2761 raw_bits = partitioned_rice_contents->raw_bits;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002762
Josh Coalson8395d022001-07-12 21:25:22 +00002763 if(partition_order == 0) {
2764 unsigned i;
2765
2766#ifndef NO_RICE_SEARCH
2767 if(rice_parameter_search_dist) {
2768 if(suggested_rice_parameter < rice_parameter_search_dist)
2769 min_rice_parameter = 0;
2770 else
2771 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
2772 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
2773 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002774#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002775 fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2776#endif
2777 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2778 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002779 }
2780 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002781 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
Josh Coalson2051dd42001-04-12 22:22:34 +00002782
Josh Coalson034dfab2001-04-27 19:10:23 +00002783 best_partition_bits = 0xffffffff;
2784 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2785#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002786#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002787#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002788 partition_bits = (2+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002789#else
Josh Coalson352e0f62001-03-20 22:55:50 +00002790 const unsigned rice_parameter_estimate = rice_parameter-1;
Josh Coalson034dfab2001-04-27 19:10:23 +00002791 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002792#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002793#else
2794 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002795#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002796 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson352e0f62001-03-20 22:55:50 +00002797 for(i = 0; i < residual_samples; i++) {
2798#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002799#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson2051dd42001-04-12 22:22:34 +00002800 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002801#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002802 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002803#endif
2804#else
Josh Coalson2051dd42001-04-12 22:22:34 +00002805 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 +00002806#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00002807 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002808#ifndef NO_RICE_SEARCH
2809 if(partition_bits < best_partition_bits) {
2810 best_rice_parameter = rice_parameter;
2811 best_partition_bits = partition_bits;
Josh Coalson352e0f62001-03-20 22:55:50 +00002812 }
2813 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002814#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002815 if(search_for_escapes) {
2816 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;
2817 if(flat_bits <= best_partition_bits) {
2818 raw_bits[0] = raw_bits_per_partition[0];
2819 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2820 best_partition_bits = flat_bits;
2821 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002822 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002823 parameters[0] = best_rice_parameter;
2824 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002825 }
2826 else {
Josh Coalson4dacd192001-06-06 21:11:44 +00002827 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002828 unsigned partition_samples;
2829 FLAC__uint64 mean, k;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00002830 const unsigned partitions = 1u << partition_order;
Josh Coalson4dacd192001-06-06 21:11:44 +00002831 for(partition = residual_sample = 0; partition < partitions; partition++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002832 partition_samples = (residual_samples+predictor_order) >> partition_order;
Josh Coalson034dfab2001-04-27 19:10:23 +00002833 if(partition == 0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002834 if(partition_samples <= predictor_order)
2835 return false;
2836 else
2837 partition_samples -= predictor_order;
2838 }
Josh Coalson05d20792001-06-29 23:12:26 +00002839 mean = abs_residual_partition_sums[partition];
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002840#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson05d20792001-06-29 23:12:26 +00002841 mean += partition_samples >> 1; /* for rounding effect */
2842 mean /= partition_samples;
2843
Josh Coalson034dfab2001-04-27 19:10:23 +00002844 /* calc rice_parameter = floor(log2(mean)) */
2845 rice_parameter = 0;
2846 mean>>=1;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002847 while(mean) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002848 rice_parameter++;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002849 mean >>= 1;
2850 }
Josh Coalsonb9433f92001-03-17 01:07:00 +00002851#else
Josh Coalson05d20792001-06-29 23:12:26 +00002852 /* calc rice_parameter ala LOCO-I */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002853 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson05d20792001-06-29 23:12:26 +00002854 ;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002855#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002856 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002857#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002858 fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2859#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002860 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002861 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002862
Josh Coalson034dfab2001-04-27 19:10:23 +00002863#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00002864 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00002865 if(rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00002866 min_rice_parameter = 0;
2867 else
Josh Coalson034dfab2001-04-27 19:10:23 +00002868 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
2869 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00002870 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00002871#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00002872 fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2873#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00002874 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00002875 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002876 }
2877 else
2878 min_rice_parameter = max_rice_parameter = rice_parameter;
Josh Coalson60f77d72001-04-25 02:16:36 +00002879
Josh Coalson034dfab2001-04-27 19:10:23 +00002880 best_partition_bits = 0xffffffff;
2881 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
2882#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00002883#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002884#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00002885 partition_bits = (2+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002886#else
Josh Coalson034dfab2001-04-27 19:10:23 +00002887 const unsigned rice_parameter_estimate = rice_parameter-1;
2888 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00002889#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002890#else
2891 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002892#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002893 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson4dacd192001-06-06 21:11:44 +00002894 save_residual_sample = residual_sample;
2895 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
Josh Coalson352e0f62001-03-20 22:55:50 +00002896#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00002897#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson4dacd192001-06-06 21:11:44 +00002898 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002899#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002900 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00002901#endif
2902#else
Josh Coalson4dacd192001-06-06 21:11:44 +00002903 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 +00002904#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00002905 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002906#ifndef NO_RICE_SEARCH
Josh Coalson4dacd192001-06-06 21:11:44 +00002907 if(rice_parameter != max_rice_parameter)
2908 residual_sample = save_residual_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00002909 if(partition_bits < best_partition_bits) {
2910 best_rice_parameter = rice_parameter;
2911 best_partition_bits = partition_bits;
2912 }
Josh Coalson2051dd42001-04-12 22:22:34 +00002913 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002914#endif
Josh Coalson8395d022001-07-12 21:25:22 +00002915 if(search_for_escapes) {
2916 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;
2917 if(flat_bits <= best_partition_bits) {
2918 raw_bits[partition] = raw_bits_per_partition[partition];
2919 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
2920 best_partition_bits = flat_bits;
2921 }
Josh Coalson2051dd42001-04-12 22:22:34 +00002922 }
Josh Coalson034dfab2001-04-27 19:10:23 +00002923 parameters[partition] = best_rice_parameter;
2924 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002925 }
2926 }
2927
2928 *bits = bits_;
2929 return true;
2930}
Josh Coalson859bc542001-03-27 22:22:27 +00002931
Josh Coalsonf1eff452002-07-31 07:05:33 +00002932unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples)
Josh Coalson859bc542001-03-27 22:22:27 +00002933{
2934 unsigned i, shift;
Josh Coalson77e3f312001-06-23 03:03:24 +00002935 FLAC__int32 x = 0;
Josh Coalson859bc542001-03-27 22:22:27 +00002936
2937 for(i = 0; i < samples && !(x&1); i++)
2938 x |= signal[i];
2939
2940 if(x == 0) {
2941 shift = 0;
2942 }
2943 else {
2944 for(shift = 0; !(x&1); shift++)
2945 x >>= 1;
2946 }
2947
2948 if(shift > 0) {
2949 for(i = 0; i < samples; i++)
2950 signal[i] >>= shift;
2951 }
2952
2953 return shift;
2954}
Josh Coalsond86e03b2002-08-03 21:56:15 +00002955
2956void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
2957{
2958 unsigned channel;
2959
2960 for(channel = 0; channel < channels; channel++)
2961 memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples);
2962
2963 fifo->tail += wide_samples;
2964
2965 FLAC__ASSERT(fifo->tail <= fifo->size);
2966}
2967
2968void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
2969{
2970 unsigned channel;
2971 unsigned sample, wide_sample;
2972 unsigned tail = fifo->tail;
2973
2974 sample = input_offset * channels;
2975 for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
2976 for(channel = 0; channel < channels; channel++)
2977 fifo->data[channel][tail] = input[sample++];
2978 tail++;
2979 }
2980 fifo->tail = tail;
2981
2982 FLAC__ASSERT(fifo->tail <= fifo->size);
2983}
2984
2985FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
2986{
2987 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
2988 const unsigned encoded_bytes = encoder->private_->verify.output.bytes;
2989 (void)decoder;
2990
2991 if(encoder->private_->verify.needs_magic_hack) {
2992 FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH);
2993 *bytes = FLAC__STREAM_SYNC_LENGTH;
2994 memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes);
2995 encoder->private_->verify.needs_magic_hack = false;
2996 }
2997 else {
2998 if(encoded_bytes == 0) {
Josh Coalsonfc2b7372002-08-16 05:39:34 +00002999 /*
3000 * If we get here, a FIFO underflow has occurred,
3001 * which means there is a bug somewhere.
3002 */
3003 FLAC__ASSERT(0);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003004 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
3005 }
3006 else if(encoded_bytes < *bytes)
3007 *bytes = encoded_bytes;
3008 memcpy(buffer, encoder->private_->verify.output.data, *bytes);
3009 encoder->private_->verify.output.data += *bytes;
3010 encoder->private_->verify.output.bytes -= *bytes;
3011 }
3012
3013 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
3014}
3015
3016FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
3017{
3018 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data;
3019 unsigned channel;
3020 const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
3021 const unsigned blocksize = frame->header.blocksize;
3022 const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize;
3023
3024 for(channel = 0; channel < channels; channel++) {
3025 if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) {
3026 unsigned i, sample = 0;
3027 FLAC__int32 expect = 0, got = 0;
3028
3029 for(i = 0; i < blocksize; i++) {
3030 if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) {
3031 sample = i;
3032 expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i];
3033 got = (FLAC__int32)buffer[channel][i];
3034 break;
3035 }
3036 }
3037 FLAC__ASSERT(i < blocksize);
3038 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
3039 encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample;
Josh Coalson5f39e9f2002-08-21 05:27:01 +00003040 encoder->private_->verify.error_stats.frame_number = (unsigned)(frame->header.number.sample_number / blocksize);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003041 encoder->private_->verify.error_stats.channel = channel;
3042 encoder->private_->verify.error_stats.sample = sample;
3043 encoder->private_->verify.error_stats.expected = expect;
3044 encoder->private_->verify.error_stats.got = got;
3045 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA;
3046 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
3047 }
3048 }
3049 /* dequeue the frame from the fifo */
3050 for(channel = 0; channel < channels; channel++) {
3051 memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail - blocksize);
3052 }
3053 encoder->private_->verify.input_fifo.tail -= blocksize;
3054 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
3055}
3056
3057void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
3058{
3059 (void)decoder, (void)metadata, (void)client_data;
3060}
3061
3062void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
3063{
3064 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3065 (void)decoder, (void)status;
3066 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
3067}