blob: 123708cd3e295c47fc340dd08c45e9a4bcb5909f [file] [log] [blame]
Josh Coalson26560dd2001-02-08 00:38:41 +00001/* libFLAC - Free Lossless Audio Codec library
Josh Coalson0395dac2006-04-25 06:59:33 +00002 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006 Josh Coalson
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00003 *
Josh Coalsonafd81072003-01-31 23:34:56 +00004 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00007 *
Josh Coalsonafd81072003-01-31 23:34:56 +00008 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000010 *
Josh Coalsonafd81072003-01-31 23:34:56 +000011 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000030 */
31
Josh Coalsonbf0f52c2006-04-25 06:38:43 +000032/*@@@@@@*/
Josh Coalson81cbb8e2006-05-01 06:17:24 +000033#undef WINDOW_DEBUG_OUTPUT
Josh Coalsonbf0f52c2006-04-25 06:38:43 +000034
Josh Coalsonb1ec7962006-05-24 04:41:36 +000035#if HAVE_CONFIG_H
36# include <config.h>
37#endif
38
Josh Coalson6b21f662006-09-13 01:42:27 +000039#if defined _MSC_VER || defined __MINGW32__
40#include <io.h> /* for _setmode() */
41#include <fcntl.h> /* for _O_BINARY */
42#endif
43#if defined __CYGWIN__ || defined __EMX__
44#include <io.h> /* for setmode(), O_BINARY */
45#include <fcntl.h> /* for _O_BINARY */
46#endif
Josh Coalsone6b3bbe2002-10-08 06:03:25 +000047#include <limits.h>
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000048#include <stdio.h>
49#include <stdlib.h> /* for malloc() */
50#include <string.h> /* for memcpy() */
Josh Coalson6b21f662006-09-13 01:42:27 +000051#include <sys/types.h> /* for off_t */
52#if defined _MSC_VER || defined __MINGW32__
Josh Coalson825e72c2006-10-03 01:16:59 +000053#if _MSC_VER <= 1200 /* @@@ [2G limit] */
Josh Coalson6b21f662006-09-13 01:42:27 +000054#define fseeko fseek
55#define ftello ftell
56#endif
Josh Coalson825e72c2006-10-03 01:16:59 +000057#endif
Josh Coalson1b689822001-05-31 20:11:02 +000058#include "FLAC/assert.h"
Josh Coalsond86e03b2002-08-03 21:56:15 +000059#include "FLAC/stream_decoder.h"
Josh Coalson0a15c142001-06-13 17:59:57 +000060#include "protected/stream_encoder.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000061#include "private/bitbuffer.h"
Josh Coalsoneef56702001-03-30 00:45:22 +000062#include "private/bitmath.h"
Josh Coalson215af572001-03-27 01:15:58 +000063#include "private/crc.h"
Josh Coalsoncf30f502001-05-23 20:57:44 +000064#include "private/cpu.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000065#include "private/fixed.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000066#include "private/format.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000067#include "private/lpc.h"
Josh Coalsonfa37f1c2001-01-12 23:55:11 +000068#include "private/md5.h"
Josh Coalsond98c43d2001-05-13 05:17:01 +000069#include "private/memory.h"
Josh Coalsonb7023aa2002-08-17 15:23:43 +000070#include "private/stream_encoder_framing.h"
Josh Coalsonbf0f52c2006-04-25 06:38:43 +000071#include "private/window.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000072
73#ifdef min
74#undef min
75#endif
76#define min(x,y) ((x)<(y)?(x):(y))
77
78#ifdef max
79#undef max
80#endif
81#define max(x,y) ((x)>(y)?(x):(y))
82
Josh Coalsond86e03b2002-08-03 21:56:15 +000083typedef struct {
84 FLAC__int32 *data[FLAC__MAX_CHANNELS];
85 unsigned size; /* of each data[] in samples */
86 unsigned tail;
87} verify_input_fifo;
88
89typedef struct {
90 const FLAC__byte *data;
91 unsigned capacity;
92 unsigned bytes;
93} verify_output;
94
95typedef enum {
96 ENCODER_IN_MAGIC = 0,
97 ENCODER_IN_METADATA = 1,
98 ENCODER_IN_AUDIO = 2
99} EncoderStateHint;
100
Josh Coalson0a15c142001-06-13 17:59:57 +0000101/***********************************************************************
102 *
103 * Private class method prototypes
104 *
105 ***********************************************************************/
106
Josh Coalsonf1eff452002-07-31 07:05:33 +0000107static void set_defaults_(FLAC__StreamEncoder *encoder);
108static void free_(FLAC__StreamEncoder *encoder);
109static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
Josh Coalsond86e03b2002-08-03 21:56:15 +0000110static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples);
Josh Coalson6b21f662006-09-13 01:42:27 +0000111static FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples);
112static void update_metadata_(const FLAC__StreamEncoder *encoder);
Josh Coalsonf1eff452002-07-31 07:05:33 +0000113static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
114static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
Josh Coalson6fe72f72002-08-20 04:01:59 +0000115
116static FLAC__bool process_subframe_(
117 FLAC__StreamEncoder *encoder,
118 unsigned min_partition_order,
119 unsigned max_partition_order,
120 FLAC__bool precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +0000121 const FLAC__FrameHeader *frame_header,
122 unsigned subframe_bps,
123 const FLAC__int32 integer_signal[],
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000124#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson6fe72f72002-08-20 04:01:59 +0000125 const FLAC__real real_signal[],
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000126#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000127 FLAC__Subframe *subframe[2],
128 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
129 FLAC__int32 *residual[2],
130 unsigned *best_subframe,
131 unsigned *best_bits
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000132#ifdef WINDOW_DEBUG_OUTPUT
133 ,unsigned subframe_number
134#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000135);
136
137static FLAC__bool add_subframe_(
138 FLAC__StreamEncoder *encoder,
139 const FLAC__FrameHeader *frame_header,
140 unsigned subframe_bps,
141 const FLAC__Subframe *subframe,
142 FLAC__BitBuffer *frame
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000143#ifdef WINDOW_DEBUG_OUTPUT
144,unsigned subframe_bits
145#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000146);
147
148static unsigned evaluate_constant_subframe_(
149 const FLAC__int32 signal,
150 unsigned subframe_bps,
151 FLAC__Subframe *subframe
152);
153
154static unsigned evaluate_fixed_subframe_(
155 FLAC__StreamEncoder *encoder,
156 const FLAC__int32 signal[],
157 FLAC__int32 residual[],
158 FLAC__uint32 abs_residual[],
159 FLAC__uint64 abs_residual_partition_sums[],
160 unsigned raw_bits_per_partition[],
161 unsigned blocksize,
162 unsigned subframe_bps,
163 unsigned order,
164 unsigned rice_parameter,
165 unsigned min_partition_order,
166 unsigned max_partition_order,
167 FLAC__bool precompute_partition_sums,
168 FLAC__bool do_escape_coding,
169 unsigned rice_parameter_search_dist,
170 FLAC__Subframe *subframe,
171 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
172);
173
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000174#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson6fe72f72002-08-20 04:01:59 +0000175static unsigned evaluate_lpc_subframe_(
176 FLAC__StreamEncoder *encoder,
177 const FLAC__int32 signal[],
178 FLAC__int32 residual[],
179 FLAC__uint32 abs_residual[],
180 FLAC__uint64 abs_residual_partition_sums[],
181 unsigned raw_bits_per_partition[],
182 const FLAC__real lp_coeff[],
183 unsigned blocksize,
184 unsigned subframe_bps,
185 unsigned order,
186 unsigned qlp_coeff_precision,
187 unsigned rice_parameter,
188 unsigned min_partition_order,
189 unsigned max_partition_order,
190 FLAC__bool precompute_partition_sums,
191 FLAC__bool do_escape_coding,
192 unsigned rice_parameter_search_dist,
193 FLAC__Subframe *subframe,
194 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000195#ifdef WINDOW_DEBUG_OUTPUT
196 ,unsigned frame_number
197 ,unsigned subframe_number
198 ,FLAC__ApodizationSpecification aspec
199#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000200);
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000201#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000202
203static unsigned evaluate_verbatim_subframe_(
204 const FLAC__int32 signal[],
205 unsigned blocksize,
206 unsigned subframe_bps,
207 FLAC__Subframe *subframe
208);
209
210static unsigned find_best_partition_order_(
211 struct FLAC__StreamEncoderPrivate *private_,
212 const FLAC__int32 residual[],
213 FLAC__uint32 abs_residual[],
214 FLAC__uint64 abs_residual_partition_sums[],
215 unsigned raw_bits_per_partition[],
216 unsigned residual_samples,
217 unsigned predictor_order,
218 unsigned rice_parameter,
219 unsigned min_partition_order,
220 unsigned max_partition_order,
221 FLAC__bool precompute_partition_sums,
222 FLAC__bool do_escape_coding,
223 unsigned rice_parameter_search_dist,
224 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
225);
226
227static void precompute_partition_info_sums_(
228 const FLAC__uint32 abs_residual[],
229 FLAC__uint64 abs_residual_partition_sums[],
230 unsigned residual_samples,
231 unsigned predictor_order,
232 unsigned min_partition_order,
233 unsigned max_partition_order
234);
235
236static void precompute_partition_info_escapes_(
237 const FLAC__int32 residual[],
238 unsigned raw_bits_per_partition[],
239 unsigned residual_samples,
240 unsigned predictor_order,
241 unsigned min_partition_order,
242 unsigned max_partition_order
243);
244
Josh Coalson8395d022001-07-12 21:25:22 +0000245#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +0000246static FLAC__bool set_partitioned_rice_(
247 const FLAC__uint32 abs_residual[],
248 const FLAC__int32 residual[],
249 const unsigned residual_samples,
250 const unsigned predictor_order,
251 const unsigned suggested_rice_parameter,
252 const unsigned rice_parameter_search_dist,
253 const unsigned partition_order,
254 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
255 unsigned *bits
256);
257
258static FLAC__bool set_partitioned_rice_with_precompute_(
259 const FLAC__int32 residual[],
260 const FLAC__uint64 abs_residual_partition_sums[],
261 const unsigned raw_bits_per_partition[],
262 const unsigned residual_samples,
263 const unsigned predictor_order,
264 const unsigned suggested_rice_parameter,
265 const unsigned rice_parameter_search_dist,
266 const unsigned partition_order,
267 const FLAC__bool search_for_escapes,
268 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
269 unsigned *bits
270);
Josh Coalson8395d022001-07-12 21:25:22 +0000271#else
Josh Coalson6fe72f72002-08-20 04:01:59 +0000272static FLAC__bool set_partitioned_rice_(
273 const FLAC__uint32 abs_residual[],
274 const unsigned residual_samples,
275 const unsigned predictor_order,
276 const unsigned suggested_rice_parameter,
277 const unsigned rice_parameter_search_dist,
278 const unsigned partition_order,
279 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
280 unsigned *bits
281);
282
283static FLAC__bool set_partitioned_rice_with_precompute_(
284 const FLAC__uint32 abs_residual[],
285 const FLAC__uint64 abs_residual_partition_sums[],
286 const unsigned raw_bits_per_partition[],
287 const unsigned residual_samples,
288 const unsigned predictor_order,
289 const unsigned suggested_rice_parameter,
290 const unsigned rice_parameter_search_dist,
291 const unsigned partition_order,
292 const FLAC__bool search_for_escapes,
293 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
294 unsigned *bits
295);
Josh Coalson0a15c142001-06-13 17:59:57 +0000296#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +0000297
Josh Coalsonf1eff452002-07-31 07:05:33 +0000298static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples);
Josh Coalson6fe72f72002-08-20 04:01:59 +0000299
Josh Coalsond86e03b2002-08-03 21:56:15 +0000300/* verify-related routines: */
Josh Coalson6fe72f72002-08-20 04:01:59 +0000301static void append_to_verify_fifo_(
302 verify_input_fifo *fifo,
303 const FLAC__int32 * const input[],
304 unsigned input_offset,
305 unsigned channels,
306 unsigned wide_samples
307);
308
309static void append_to_verify_fifo_interleaved_(
310 verify_input_fifo *fifo,
311 const FLAC__int32 input[],
312 unsigned input_offset,
313 unsigned channels,
314 unsigned wide_samples
315);
316
Josh Coalson6b21f662006-09-13 01:42:27 +0000317static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
318static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
319static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
320static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
Josh Coalson6fe72f72002-08-20 04:01:59 +0000321
Josh Coalson6b21f662006-09-13 01:42:27 +0000322static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
323static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
324static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
325static FILE *get_binary_stdout_();
Josh Coalson6fe72f72002-08-20 04:01:59 +0000326
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000327#ifdef WINDOW_DEBUG_OUTPUT
328static const char * const winstr[] = {
329 "bartlett",
330 "bartlett_hann",
331 "blackman",
332 "blackman_harris_4term_92db_sidelobe",
333 "connes",
334 "flattop",
335 "gauss",
336 "hamming",
337 "hann",
338 "kaiser_bessel",
339 "nuttall",
340 "rectangular",
341 "triangle",
342 "tukey",
343 "welch"
344};
345#endif
Josh Coalson0a15c142001-06-13 17:59:57 +0000346
347/***********************************************************************
348 *
349 * Private class data
350 *
351 ***********************************************************************/
352
353typedef struct FLAC__StreamEncoderPrivate {
Josh Coalson8395d022001-07-12 21:25:22 +0000354 unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */
Josh Coalson77e3f312001-06-23 03:03:24 +0000355 FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */
356 FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000357#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson77e3f312001-06-23 03:03:24 +0000358 FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* the floating-point version of the input signal */
359 FLAC__real *real_signal_mid_side[2]; /* the floating-point version of the mid-side input signal (stereo only) */
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000360 FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
361 FLAC__real *windowed_signal; /* the real_signal[] * current window[] */
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000362#endif
Josh Coalson8395d022001-07-12 21:25:22 +0000363 unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */
364 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 +0000365 FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
366 FLAC__int32 *residual_workspace_mid_side[2][2];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000367 FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
368 FLAC__Subframe subframe_workspace_mid_side[2][2];
369 FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
370 FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
Josh Coalsona37ba462002-08-19 21:36:39 +0000371 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2];
372 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2];
373 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2];
374 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2];
Josh Coalson8395d022001-07-12 21:25:22 +0000375 unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index into the above workspaces */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000376 unsigned best_subframe_mid_side[2];
Josh Coalson8395d022001-07-12 21:25:22 +0000377 unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */
Josh Coalson94e02cd2001-01-25 10:41:06 +0000378 unsigned best_subframe_bits_mid_side[2];
Josh Coalson77e3f312001-06-23 03:03:24 +0000379 FLAC__uint32 *abs_residual; /* workspace where abs(candidate residual) is stored */
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000380 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 +0000381 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 +0000382 FLAC__BitBuffer *frame; /* the current frame being worked on */
Josh Coalson8395d022001-07-12 21:25:22 +0000383 unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
384 unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000385 FLAC__ChannelAssignment last_channel_assignment;
Josh Coalson6b21f662006-09-13 01:42:27 +0000386 FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */
387 FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000388 unsigned current_sample_number;
389 unsigned current_frame_number;
Josh Coalson3e7a96e2004-07-23 05:18:22 +0000390 struct FLAC__MD5Context md5context;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000391 FLAC__CPUInfo cpuinfo;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000392#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson09758432004-10-20 00:21:50 +0000393 unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000394#else
395 unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
396#endif
397#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson77e3f312001-06-23 03:03:24 +0000398 void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
Josh Coalson7446e182005-01-26 04:04:38 +0000399 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[]);
400 void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
401 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 Coalson5f2b46d2004-11-09 01:34:01 +0000402#endif
Josh Coalson3262b0d2002-08-14 20:58:42 +0000403 FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */
404 FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */
405 FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */
406 FLAC__bool precompute_partition_sums; /* our initial guess as to whether precomputing the partitions sums will be a speed improvement */
Josh Coalsone6b3bbe2002-10-08 06:03:25 +0000407 FLAC__bool disable_constant_subframes;
408 FLAC__bool disable_fixed_subframes;
409 FLAC__bool disable_verbatim_subframes;
Josh Coalson6b21f662006-09-13 01:42:27 +0000410 FLAC__StreamEncoderSeekCallback seek_callback;
411 FLAC__StreamEncoderTellCallback tell_callback;
Josh Coalson681c2932002-08-01 08:19:37 +0000412 FLAC__StreamEncoderWriteCallback write_callback;
413 FLAC__StreamEncoderMetadataCallback metadata_callback;
Josh Coalson6b21f662006-09-13 01:42:27 +0000414 FLAC__StreamEncoderProgressCallback progress_callback;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000415 void *client_data;
Josh Coalson6b21f662006-09-13 01:42:27 +0000416 unsigned first_seekpoint_to_check;
417 FILE *file; /* only used when encoding to a file */
418 FLAC__uint64 bytes_written;
419 FLAC__uint64 samples_written;
420 unsigned frames_written;
421 unsigned total_frames_estimate;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000422 /* unaligned (original) pointers to allocated data */
Josh Coalson77e3f312001-06-23 03:03:24 +0000423 FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
424 FLAC__int32 *integer_signal_mid_side_unaligned[2];
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000425#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson77e3f312001-06-23 03:03:24 +0000426 FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
427 FLAC__real *real_signal_mid_side_unaligned[2];
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000428 FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
429 FLAC__real *windowed_signal_unaligned;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000430#endif
Josh Coalson77e3f312001-06-23 03:03:24 +0000431 FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
432 FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
433 FLAC__uint32 *abs_residual_unaligned;
Josh Coalsonb3347bd2001-07-16 18:06:41 +0000434 FLAC__uint64 *abs_residual_partition_sums_unaligned;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000435 unsigned *raw_bits_per_partition_unaligned;
Josh Coalson8084b052001-11-01 00:27:29 +0000436 /*
437 * These fields have been moved here from private function local
438 * declarations merely to save stack space during encoding.
439 */
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000440#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonf1eff452002-07-31 07:05:33 +0000441 FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000442#endif
Josh Coalsona37ba462002-08-19 21:36:39 +0000443 FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000444 /*
445 * The data for the verify section
446 */
447 struct {
448 FLAC__StreamDecoder *decoder;
449 EncoderStateHint state_hint;
450 FLAC__bool needs_magic_hack;
451 verify_input_fifo input_fifo;
452 verify_output output;
453 struct {
454 FLAC__uint64 absolute_sample;
455 unsigned frame_number;
456 unsigned channel;
457 unsigned sample;
458 FLAC__int32 expected;
459 FLAC__int32 got;
460 } error_stats;
461 } verify;
Josh Coalson3262b0d2002-08-14 20:58:42 +0000462 FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
Josh Coalson0a15c142001-06-13 17:59:57 +0000463} FLAC__StreamEncoderPrivate;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000464
Josh Coalson0a15c142001-06-13 17:59:57 +0000465/***********************************************************************
466 *
467 * Public static class data
468 *
469 ***********************************************************************/
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000470
Josh Coalson6afed9f2002-10-16 22:29:47 +0000471FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
Josh Coalson0a15c142001-06-13 17:59:57 +0000472 "FLAC__STREAM_ENCODER_OK",
Josh Coalson6b21f662006-09-13 01:42:27 +0000473 "FLAC__STREAM_ENCODER_UNINITIALIZED",
Josh Coalsond86e03b2002-08-03 21:56:15 +0000474 "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
475 "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
Josh Coalson6b21f662006-09-13 01:42:27 +0000476 "FLAC__STREAM_ENCODER_CLIENT_ERROR",
477 "FLAC__STREAM_ENCODER_IO_ERROR",
Josh Coalson0a15c142001-06-13 17:59:57 +0000478 "FLAC__STREAM_ENCODER_FRAMING_ERROR",
Josh Coalson6b21f662006-09-13 01:42:27 +0000479 "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR"
480};
481
482FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = {
483 "FLAC__STREAM_ENCODER_INIT_STATUS_OK",
484 "FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR",
485 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS",
486 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS",
487 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE",
488 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE",
489 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE",
490 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER",
491 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION",
492 "FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_CHANNELS_MISMATCH",
Josh Coalson6b21f662006-09-13 01:42:27 +0000493 "FLAC__STREAM_ENCODER_INIT_STATUS_ILLEGAL_MID_SIDE_FORCE",
494 "FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
495 "FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE",
496 "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA",
497 "FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000498};
499
Josh Coalson6afed9f2002-10-16 22:29:47 +0000500FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
Josh Coalson5c491a12002-08-01 06:39:40 +0000501 "FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
502 "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000503};
504
Josh Coalson6b21f662006-09-13 01:42:27 +0000505FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = {
506 "FLAC__STREAM_ENCODER_SEEK_STATUS_OK",
507 "FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR",
508 "FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED"
509};
510
511FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = {
512 "FLAC__STREAM_ENCODER_TELL_STATUS_OK",
513 "FLAC__STREAM_ENCODER_TELL_STATUS_ERROR",
514 "FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED"
515};
516
Josh Coalson0a15c142001-06-13 17:59:57 +0000517/***********************************************************************
518 *
519 * Class constructor/destructor
520 *
Josh Coalsond86e03b2002-08-03 21:56:15 +0000521 */
Josh Coalson6afed9f2002-10-16 22:29:47 +0000522FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000523{
Josh Coalson0a15c142001-06-13 17:59:57 +0000524 FLAC__StreamEncoder *encoder;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000525 unsigned i;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000526
Josh Coalson0a15c142001-06-13 17:59:57 +0000527 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000528
Josh Coalsonea7155f2002-10-18 05:49:19 +0000529 encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder));
Josh Coalson0a15c142001-06-13 17:59:57 +0000530 if(encoder == 0) {
531 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000532 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000533
Josh Coalsonea7155f2002-10-18 05:49:19 +0000534 encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected));
Josh Coalsonfa697a92001-08-16 20:07:29 +0000535 if(encoder->protected_ == 0) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000536 free(encoder);
537 return 0;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000538 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000539
Josh Coalsonea7155f2002-10-18 05:49:19 +0000540 encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
Josh Coalsonfa697a92001-08-16 20:07:29 +0000541 if(encoder->private_ == 0) {
542 free(encoder->protected_);
Josh Coalson0a15c142001-06-13 17:59:57 +0000543 free(encoder);
544 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000545 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000546
Josh Coalsonaec256b2002-03-12 16:19:54 +0000547 encoder->private_->frame = FLAC__bitbuffer_new();
548 if(encoder->private_->frame == 0) {
549 free(encoder->private_);
550 free(encoder->protected_);
551 free(encoder);
552 return 0;
553 }
Josh Coalsond98c43d2001-05-13 05:17:01 +0000554
Josh Coalson6b21f662006-09-13 01:42:27 +0000555 encoder->private_->file = 0;
556
Josh Coalsonf1eff452002-07-31 07:05:33 +0000557 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +0000558
Josh Coalson3262b0d2002-08-14 20:58:42 +0000559 encoder->private_->is_being_deleted = false;
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000560
561 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
562 encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
563 encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
564 }
565 for(i = 0; i < 2; i++) {
566 encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
567 encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
568 }
569 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000570 encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
571 encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000572 }
573 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000574 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
575 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 +0000576 }
577
578 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000579 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
580 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000581 }
582 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000583 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
584 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 +0000585 }
586 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000587 FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000588
Josh Coalsonfa697a92001-08-16 20:07:29 +0000589 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000590
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000591 return encoder;
592}
593
Josh Coalson6afed9f2002-10-16 22:29:47 +0000594FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000595{
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000596 unsigned i;
597
Josh Coalsonf1eff452002-07-31 07:05:33 +0000598 FLAC__ASSERT(0 != encoder);
599 FLAC__ASSERT(0 != encoder->protected_);
600 FLAC__ASSERT(0 != encoder->private_);
601 FLAC__ASSERT(0 != encoder->private_->frame);
Josh Coalson0a15c142001-06-13 17:59:57 +0000602
Josh Coalson3262b0d2002-08-14 20:58:42 +0000603 encoder->private_->is_being_deleted = true;
604
605 FLAC__stream_encoder_finish(encoder);
606
Josh Coalson4fa90592002-12-04 07:01:37 +0000607 if(0 != encoder->private_->verify.decoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +0000608 FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000609
610 for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000611 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
612 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000613 }
614 for(i = 0; i < 2; i++) {
Josh Coalsona37ba462002-08-19 21:36:39 +0000615 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
616 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 +0000617 }
618 for(i = 0; i < 2; i++)
Josh Coalsona37ba462002-08-19 21:36:39 +0000619 FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
Josh Coalsonb7023aa2002-08-17 15:23:43 +0000620
Josh Coalsonaec256b2002-03-12 16:19:54 +0000621 FLAC__bitbuffer_delete(encoder->private_->frame);
Josh Coalsonfa697a92001-08-16 20:07:29 +0000622 free(encoder->private_);
623 free(encoder->protected_);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000624 free(encoder);
625}
626
Josh Coalson0a15c142001-06-13 17:59:57 +0000627/***********************************************************************
628 *
629 * Public class methods
630 *
631 ***********************************************************************/
632
Josh Coalson6b21f662006-09-13 01:42:27 +0000633FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000634{
635 unsigned i;
Josh Coalson3957c472006-09-24 16:25:42 +0000636 FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000637
Josh Coalsonf1eff452002-07-31 07:05:33 +0000638 FLAC__ASSERT(0 != encoder);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000639
Josh Coalsonfa697a92001-08-16 20:07:29 +0000640 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson6b21f662006-09-13 01:42:27 +0000641 return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000642
Josh Coalson6b21f662006-09-13 01:42:27 +0000643 if(0 == write_callback || (seek_callback && 0 == tell_callback))
644 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000645
Josh Coalsonfa697a92001-08-16 20:07:29 +0000646 if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
Josh Coalson6b21f662006-09-13 01:42:27 +0000647 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson69f1ee02001-01-24 00:54:43 +0000648
Josh Coalsonfa697a92001-08-16 20:07:29 +0000649 if(encoder->protected_->do_mid_side_stereo && encoder->protected_->channels != 2)
Josh Coalson6b21f662006-09-13 01:42:27 +0000650 return FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_CHANNELS_MISMATCH;
Josh Coalsond37d1352001-05-30 23:09:31 +0000651
Josh Coalsonfa697a92001-08-16 20:07:29 +0000652 if(encoder->protected_->loose_mid_side_stereo && !encoder->protected_->do_mid_side_stereo)
Josh Coalson6b21f662006-09-13 01:42:27 +0000653 return FLAC__STREAM_ENCODER_INIT_STATUS_ILLEGAL_MID_SIDE_FORCE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000654
Josh Coalsonfa697a92001-08-16 20:07:29 +0000655 if(encoder->protected_->bits_per_sample >= 32)
Josh Coalson6b21f662006-09-13 01:42:27 +0000656 encoder->protected_->do_mid_side_stereo = false; /* since we currenty do 32-bit math, the side channel would have 33 bps and overflow */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000657
Josh Coalson76c68bc2002-05-17 06:22:02 +0000658 if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
Josh Coalson6b21f662006-09-13 01:42:27 +0000659 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000660
Josh Coalson0833f342002-07-15 05:31:55 +0000661 if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
Josh Coalson6b21f662006-09-13 01:42:27 +0000662 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000663
Josh Coalsonfa697a92001-08-16 20:07:29 +0000664 if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
Josh Coalson6b21f662006-09-13 01:42:27 +0000665 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
Josh Coalson0a15c142001-06-13 17:59:57 +0000666
Josh Coalson20ac2c12002-08-30 05:47:14 +0000667 if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
Josh Coalson6b21f662006-09-13 01:42:27 +0000668 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
Josh Coalson20ac2c12002-08-30 05:47:14 +0000669
Josh Coalsonfa697a92001-08-16 20:07:29 +0000670 if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
Josh Coalson6b21f662006-09-13 01:42:27 +0000671 return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
Josh Coalson0a15c142001-06-13 17:59:57 +0000672
Josh Coalsonfa697a92001-08-16 20:07:29 +0000673 if(encoder->protected_->qlp_coeff_precision == 0) {
674 if(encoder->protected_->bits_per_sample < 16) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000675 /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
676 /* @@@ until then we'll make a guess */
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000677 encoder->protected_->qlp_coeff_precision = max(FLAC__MIN_QLP_COEFF_PRECISION, 2 + encoder->protected_->bits_per_sample / 2);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000678 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000679 else if(encoder->protected_->bits_per_sample == 16) {
680 if(encoder->protected_->blocksize <= 192)
681 encoder->protected_->qlp_coeff_precision = 7;
682 else if(encoder->protected_->blocksize <= 384)
683 encoder->protected_->qlp_coeff_precision = 8;
684 else if(encoder->protected_->blocksize <= 576)
685 encoder->protected_->qlp_coeff_precision = 9;
686 else if(encoder->protected_->blocksize <= 1152)
687 encoder->protected_->qlp_coeff_precision = 10;
688 else if(encoder->protected_->blocksize <= 2304)
689 encoder->protected_->qlp_coeff_precision = 11;
690 else if(encoder->protected_->blocksize <= 4608)
691 encoder->protected_->qlp_coeff_precision = 12;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000692 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000693 encoder->protected_->qlp_coeff_precision = 13;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000694 }
695 else {
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000696 if(encoder->protected_->blocksize <= 384)
697 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-2;
698 else if(encoder->protected_->blocksize <= 1152)
699 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-1;
700 else
701 encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000702 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000703 FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000704 }
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000705 else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
Josh Coalson6b21f662006-09-13 01:42:27 +0000706 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000707
Josh Coalsonfa697a92001-08-16 20:07:29 +0000708 if(encoder->protected_->streamable_subset) {
Josh Coalson20ac2c12002-08-30 05:47:14 +0000709 if(
710 encoder->protected_->blocksize != 192 &&
711 encoder->protected_->blocksize != 576 &&
712 encoder->protected_->blocksize != 1152 &&
713 encoder->protected_->blocksize != 2304 &&
714 encoder->protected_->blocksize != 4608 &&
715 encoder->protected_->blocksize != 256 &&
716 encoder->protected_->blocksize != 512 &&
717 encoder->protected_->blocksize != 1024 &&
718 encoder->protected_->blocksize != 2048 &&
719 encoder->protected_->blocksize != 4096 &&
720 encoder->protected_->blocksize != 8192 &&
721 encoder->protected_->blocksize != 16384
722 )
Josh Coalson6b21f662006-09-13 01:42:27 +0000723 return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
Josh Coalson20ac2c12002-08-30 05:47:14 +0000724 if(
725 encoder->protected_->sample_rate != 8000 &&
726 encoder->protected_->sample_rate != 16000 &&
727 encoder->protected_->sample_rate != 22050 &&
728 encoder->protected_->sample_rate != 24000 &&
729 encoder->protected_->sample_rate != 32000 &&
730 encoder->protected_->sample_rate != 44100 &&
731 encoder->protected_->sample_rate != 48000 &&
732 encoder->protected_->sample_rate != 96000
733 )
Josh Coalson6b21f662006-09-13 01:42:27 +0000734 return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
Josh Coalson20ac2c12002-08-30 05:47:14 +0000735 if(
736 encoder->protected_->bits_per_sample != 8 &&
737 encoder->protected_->bits_per_sample != 12 &&
738 encoder->protected_->bits_per_sample != 16 &&
739 encoder->protected_->bits_per_sample != 20 &&
740 encoder->protected_->bits_per_sample != 24
741 )
Josh Coalson6b21f662006-09-13 01:42:27 +0000742 return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
Josh Coalsonc1c8d492002-09-26 04:42:10 +0000743 if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
Josh Coalson6b21f662006-09-13 01:42:27 +0000744 return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
Josh Coalsond0edb972006-10-07 06:50:08 +0000745 if(
746 encoder->protected_->sample_rate <= 48000 &&
747 (
748 encoder->protected_->blocksize > FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ ||
749 encoder->protected_->max_lpc_order > FLAC__SUBSET_MAX_LPC_ORDER_48000HZ
750 )
751 ) {
752 return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
753 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000754 }
755
Josh Coalsonfa697a92001-08-16 20:07:29 +0000756 if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
757 encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
758 if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
759 encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000760
Josh Coalson66075c12002-06-01 05:39:38 +0000761 /* validate metadata */
762 if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
Josh Coalson6b21f662006-09-13 01:42:27 +0000763 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000764 metadata_has_seektable = false;
765 metadata_has_vorbis_comment = false;
Josh Coalson3957c472006-09-24 16:25:42 +0000766 metadata_picture_has_type1 = false;
767 metadata_picture_has_type2 = false;
Josh Coalson66075c12002-06-01 05:39:38 +0000768 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
Josh Coalson3957c472006-09-24 16:25:42 +0000769 const FLAC__StreamMetadata *m = encoder->protected_->metadata[i];
770 if(m->type == FLAC__METADATA_TYPE_STREAMINFO)
Josh Coalson6b21f662006-09-13 01:42:27 +0000771 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson3957c472006-09-24 16:25:42 +0000772 else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000773 if(metadata_has_seektable) /* only one is allowed */
Josh Coalson6b21f662006-09-13 01:42:27 +0000774 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000775 metadata_has_seektable = true;
Josh Coalson3957c472006-09-24 16:25:42 +0000776 if(!FLAC__format_seektable_is_legal(&m->data.seek_table))
Josh Coalson6b21f662006-09-13 01:42:27 +0000777 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson66075c12002-06-01 05:39:38 +0000778 }
Josh Coalson3957c472006-09-24 16:25:42 +0000779 else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000780 if(metadata_has_vorbis_comment) /* only one is allowed */
Josh Coalson6b21f662006-09-13 01:42:27 +0000781 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +0000782 metadata_has_vorbis_comment = true;
783 }
Josh Coalson3957c472006-09-24 16:25:42 +0000784 else if(m->type == FLAC__METADATA_TYPE_CUESHEET) {
785 if(!FLAC__format_cuesheet_is_legal(&m->data.cue_sheet, m->data.cue_sheet.is_cd, /*violation=*/0))
Josh Coalson6b21f662006-09-13 01:42:27 +0000786 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalsone4869382002-11-15 05:41:48 +0000787 }
Josh Coalson3957c472006-09-24 16:25:42 +0000788 else if(m->type == FLAC__METADATA_TYPE_PICTURE) {
789 if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0))
Josh Coalsone343ab22006-09-23 19:21:19 +0000790 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson3957c472006-09-24 16:25:42 +0000791 if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) {
792 if(metadata_picture_has_type1) /* there should only be 1 per stream */
793 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
794 metadata_picture_has_type1 = true;
795 /* standard icon must be 32x32 pixel PNG */
796 if(
797 m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD &&
798 (
799 (strcmp(m->data.picture.mime_type, "image/png") && strcmp(m->data.picture.mime_type, "-->")) ||
800 m->data.picture.width != 32 ||
801 m->data.picture.height != 32
802 )
803 )
804 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
805 }
806 else if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) {
807 if(metadata_picture_has_type2) /* there should only be 1 per stream */
808 return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
809 metadata_picture_has_type2 = true;
810 }
Josh Coalsone343ab22006-09-23 19:21:19 +0000811 }
Josh Coalson66075c12002-06-01 05:39:38 +0000812 }
813
Josh Coalsonfa697a92001-08-16 20:07:29 +0000814 encoder->private_->input_capacity = 0;
815 for(i = 0; i < encoder->protected_->channels; i++) {
816 encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000817#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonfa697a92001-08-16 20:07:29 +0000818 encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000819#endif
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000820 }
821 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000822 encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000823#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonfa697a92001-08-16 20:07:29 +0000824 encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000825#endif
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000826 }
Josh Coalsonbf0f52c2006-04-25 06:38:43 +0000827#ifndef FLAC__INTEGER_ONLY_LIBRARY
828 for(i = 0; i < encoder->protected_->num_apodizations; i++)
829 encoder->private_->window_unaligned[i] = encoder->private_->window[i] = 0;
830 encoder->private_->windowed_signal_unaligned = encoder->private_->windowed_signal = 0;
831#endif
Josh Coalsonfa697a92001-08-16 20:07:29 +0000832 for(i = 0; i < encoder->protected_->channels; i++) {
833 encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
834 encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
835 encoder->private_->best_subframe[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000836 }
837 for(i = 0; i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000838 encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
839 encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
840 encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000841 }
Josh Coalsonfa697a92001-08-16 20:07:29 +0000842 encoder->private_->abs_residual_unaligned = encoder->private_->abs_residual = 0;
843 encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
844 encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000845#ifndef FLAC__INTEGER_ONLY_LIBRARY
846 encoder->private_->loose_mid_side_stereo_frames = (unsigned)((FLAC__double)encoder->protected_->sample_rate * 0.4 / (FLAC__double)encoder->protected_->blocksize + 0.5);
847#else
848 /* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */
849 /* sample rate can be up to 655350 Hz, and thus use 20 bits, so we do the multiply&divide by hand */
850 FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 655350);
851 FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535);
852 FLAC__ASSERT(encoder->protected_->sample_rate <= 655350);
853 FLAC__ASSERT(encoder->protected_->blocksize <= 65535);
854 encoder->private_->loose_mid_side_stereo_frames = (unsigned)FLAC__fixedpoint_trunc((((FLAC__uint64)(encoder->protected_->sample_rate) * (FLAC__uint64)(26214)) << 16) / (encoder->protected_->blocksize<<16) + FLAC__FP_ONE_HALF);
855#endif
Josh Coalsonfa697a92001-08-16 20:07:29 +0000856 if(encoder->private_->loose_mid_side_stereo_frames == 0)
857 encoder->private_->loose_mid_side_stereo_frames = 1;
858 encoder->private_->loose_mid_side_stereo_frame_count = 0;
859 encoder->private_->current_sample_number = 0;
860 encoder->private_->current_frame_number = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000861
Josh Coalsonfa697a92001-08-16 20:07:29 +0000862 encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
863 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? */
864 encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
Josh Coalson8395d022001-07-12 21:25:22 +0000865
Josh Coalsoncf30f502001-05-23 20:57:44 +0000866 /*
867 * get the CPU info and set the function pointers
868 */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000869 FLAC__cpu_info(&encoder->private_->cpuinfo);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000870 /* first default to the non-asm routines */
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000871#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonfa697a92001-08-16 20:07:29 +0000872 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000873#endif
Josh Coalsonfa697a92001-08-16 20:07:29 +0000874 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000875#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonfa697a92001-08-16 20:07:29 +0000876 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsonc9c0d132002-10-04 05:29:05 +0000877 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000878 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000879#endif
Josh Coalsoncf30f502001-05-23 20:57:44 +0000880 /* now override with asm where appropriate */
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000881#ifndef FLAC__INTEGER_ONLY_LIBRARY
882# ifndef FLAC__NO_ASM
Josh Coalsonfa697a92001-08-16 20:07:29 +0000883 if(encoder->private_->cpuinfo.use_asm) {
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000884# ifdef FLAC__CPU_IA32
Josh Coalsonfa697a92001-08-16 20:07:29 +0000885 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000886# ifdef FLAC__HAS_NASM
887# ifdef FLAC__SSE_OS
Josh Coalson48cbe662002-12-30 23:38:14 +0000888 if(encoder->private_->cpuinfo.data.ia32.sse) {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000889 if(encoder->protected_->max_lpc_order < 4)
890 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
891 else if(encoder->protected_->max_lpc_order < 8)
892 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
893 else if(encoder->protected_->max_lpc_order < 12)
894 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000895 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000896 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
Josh Coalson021ad3b2001-07-18 00:25:52 +0000897 }
Josh Coalson48cbe662002-12-30 23:38:14 +0000898 else
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000899# endif /* FLAC__SSE_OS */
Josh Coalson48cbe662002-12-30 23:38:14 +0000900 if(encoder->private_->cpuinfo.data.ia32._3dnow)
Josh Coalsonfa697a92001-08-16 20:07:29 +0000901 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
Josh Coalsonaa255362001-05-31 06:17:41 +0000902 else
Josh Coalsonfa697a92001-08-16 20:07:29 +0000903 encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
Josh Coalsonfa697a92001-08-16 20:07:29 +0000904 if(encoder->private_->cpuinfo.data.ia32.mmx) {
905 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
906 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 +0000907 }
908 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +0000909 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
910 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 +0000911 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000912 if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
913 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
914# endif /* FLAC__HAS_NASM */
915# endif /* FLAC__CPU_IA32 */
Josh Coalson021ad3b2001-07-18 00:25:52 +0000916 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +0000917# endif /* !FLAC__NO_ASM */
918#endif /* !FLAC__INTEGER_ONLY_LIBRARY */
Josh Coalson8395d022001-07-12 21:25:22 +0000919 /* finally override based on wide-ness if necessary */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000920 if(encoder->private_->use_wide_by_block) {
921 encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
Josh Coalson8395d022001-07-12 21:25:22 +0000922 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000923
Josh Coalson8395d022001-07-12 21:25:22 +0000924 /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
Josh Coalsonfa697a92001-08-16 20:07:29 +0000925 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 +0000926
Josh Coalson6b21f662006-09-13 01:42:27 +0000927 /* set state to OK; from here on, errors are fatal and we'll override the state then */
928 encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
929
930 encoder->private_->write_callback = write_callback;
931 encoder->private_->seek_callback = seek_callback;
932 encoder->private_->tell_callback = tell_callback;
933 encoder->private_->metadata_callback = metadata_callback;
934 encoder->private_->client_data = client_data;
935
Josh Coalsonf1eff452002-07-31 07:05:33 +0000936 if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000937 /* the above function sets the state for us in case of an error */
Josh Coalson6b21f662006-09-13 01:42:27 +0000938 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000939 }
Josh Coalsonaec256b2002-03-12 16:19:54 +0000940
Josh Coalson6b21f662006-09-13 01:42:27 +0000941 if(!FLAC__bitbuffer_init(encoder->private_->frame)) {
942 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
943 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
944 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000945
946 /*
Josh Coalsond86e03b2002-08-03 21:56:15 +0000947 * Set up the verify stuff if necessary
948 */
949 if(encoder->protected_->verify) {
950 /*
951 * First, set up the fifo which will hold the
952 * original signal to compare against
953 */
954 encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize;
955 for(i = 0; i < encoder->protected_->channels; i++) {
Josh Coalson6b21f662006-09-13 01:42:27 +0000956 if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size))) {
957 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
958 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
959 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000960 }
961 encoder->private_->verify.input_fifo.tail = 0;
962
963 /*
964 * Now set up a stream decoder for verification
965 */
966 encoder->private_->verify.decoder = FLAC__stream_decoder_new();
Josh Coalson6b21f662006-09-13 01:42:27 +0000967 if(0 == encoder->private_->verify.decoder) {
968 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
969 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
970 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000971
Josh Coalson6b21f662006-09-13 01:42:27 +0000972 if(FLAC__stream_decoder_init_stream(encoder->private_->verify.decoder, verify_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, verify_write_callback_, verify_metadata_callback_, verify_error_callback_, /*client_data=*/encoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
973 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
974 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
975 }
Josh Coalsond86e03b2002-08-03 21:56:15 +0000976 }
Josh Coalson589f8c72002-08-07 23:54:55 +0000977 encoder->private_->verify.error_stats.absolute_sample = 0;
978 encoder->private_->verify.error_stats.frame_number = 0;
979 encoder->private_->verify.error_stats.channel = 0;
980 encoder->private_->verify.error_stats.sample = 0;
981 encoder->private_->verify.error_stats.expected = 0;
982 encoder->private_->verify.error_stats.got = 0;
Josh Coalsond86e03b2002-08-03 21:56:15 +0000983
984 /*
Josh Coalson6b21f662006-09-13 01:42:27 +0000985 * These must be done before we write any metadata, because that
986 * calls the write_callback, which uses these values.
987 */
988 encoder->private_->first_seekpoint_to_check = 0;
989 encoder->private_->samples_written = 0;
990 encoder->protected_->streaminfo_offset = 0;
991 encoder->protected_->seektable_offset = 0;
992 encoder->protected_->audio_offset = 0;
993
994 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000995 * write the stream header
996 */
Josh Coalsond86e03b2002-08-03 21:56:15 +0000997 if(encoder->protected_->verify)
998 encoder->private_->verify.state_hint = ENCODER_IN_MAGIC;
Josh Coalson6b21f662006-09-13 01:42:27 +0000999 if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN)) {
1000 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
1001 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1002 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001003 if(!write_bitbuffer_(encoder, 0)) {
1004 /* the above function sets the state for us in case of an error */
Josh Coalson6b21f662006-09-13 01:42:27 +00001005 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001006 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001007
Josh Coalson5c491a12002-08-01 06:39:40 +00001008 /*
1009 * write the STREAMINFO metadata block
1010 */
Josh Coalsond86e03b2002-08-03 21:56:15 +00001011 if(encoder->protected_->verify)
1012 encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
Josh Coalson6b21f662006-09-13 01:42:27 +00001013 encoder->private_->streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
1014 encoder->private_->streaminfo.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
1015 encoder->private_->streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
1016 encoder->private_->streaminfo.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
1017 encoder->private_->streaminfo.data.stream_info.max_blocksize = encoder->protected_->blocksize;
1018 encoder->private_->streaminfo.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
1019 encoder->private_->streaminfo.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
1020 encoder->private_->streaminfo.data.stream_info.sample_rate = encoder->protected_->sample_rate;
1021 encoder->private_->streaminfo.data.stream_info.channels = encoder->protected_->channels;
1022 encoder->private_->streaminfo.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
1023 encoder->private_->streaminfo.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
1024 memset(encoder->private_->streaminfo.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
Josh Coalson3e7a96e2004-07-23 05:18:22 +00001025 FLAC__MD5Init(&encoder->private_->md5context);
Josh Coalson6b21f662006-09-13 01:42:27 +00001026 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
1027 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
1028 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1029 }
1030 if(!FLAC__add_metadata_block(&encoder->private_->streaminfo, encoder->private_->frame)) {
1031 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
1032 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1033 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001034 if(!write_bitbuffer_(encoder, 0)) {
1035 /* the above function sets the state for us in case of an error */
Josh Coalson6b21f662006-09-13 01:42:27 +00001036 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001037 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001038
Josh Coalson5c491a12002-08-01 06:39:40 +00001039 /*
1040 * Now that the STREAMINFO block is written, we can init this to an
1041 * absurdly-high value...
1042 */
Josh Coalson6b21f662006-09-13 01:42:27 +00001043 encoder->private_->streaminfo.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
Josh Coalsoncbbbb5f2001-01-23 00:41:48 +00001044 /* ... and clear this to 0 */
Josh Coalson6b21f662006-09-13 01:42:27 +00001045 encoder->private_->streaminfo.data.stream_info.total_samples = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001046
Josh Coalson5c491a12002-08-01 06:39:40 +00001047 /*
Josh Coalsoncb9d93a2002-08-25 05:27:15 +00001048 * Check to see if the supplied metadata contains a VORBIS_COMMENT;
1049 * if not, we will write an empty one (FLAC__add_metadata_block()
1050 * automatically supplies the vendor string).
Josh Coalson69cfda72004-09-10 00:38:21 +00001051 *
1052 * WATCHOUT: libOggFLAC depends on us to write this block after the
1053 * STREAMINFO since that's what the mapping requires. (In the case
Josh Coalson8ddf7fb2004-12-30 00:58:50 +00001054 * that metadata_has_vorbis_comment is true it will have already
Josh Coalson69cfda72004-09-10 00:38:21 +00001055 * insured that the metadata list is properly ordered.)
Josh Coalsoncb9d93a2002-08-25 05:27:15 +00001056 */
1057 if(!metadata_has_vorbis_comment) {
1058 FLAC__StreamMetadata vorbis_comment;
1059 vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
1060 vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0);
1061 vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */
1062 vorbis_comment.data.vorbis_comment.vendor_string.length = 0;
1063 vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
1064 vorbis_comment.data.vorbis_comment.num_comments = 0;
1065 vorbis_comment.data.vorbis_comment.comments = 0;
Josh Coalson6b21f662006-09-13 01:42:27 +00001066 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
1067 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
1068 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1069 }
1070 if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame)) {
1071 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
1072 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1073 }
Josh Coalsoncb9d93a2002-08-25 05:27:15 +00001074 if(!write_bitbuffer_(encoder, 0)) {
1075 /* the above function sets the state for us in case of an error */
Josh Coalson6b21f662006-09-13 01:42:27 +00001076 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalsoncb9d93a2002-08-25 05:27:15 +00001077 }
1078 }
1079
1080 /*
Josh Coalson5c491a12002-08-01 06:39:40 +00001081 * write the user's metadata blocks
1082 */
1083 for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
1084 encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
Josh Coalson6b21f662006-09-13 01:42:27 +00001085 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
1086 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
1087 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1088 }
1089 if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame)) {
1090 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
1091 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1092 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00001093 if(!write_bitbuffer_(encoder, 0)) {
1094 /* the above function sets the state for us in case of an error */
Josh Coalson6b21f662006-09-13 01:42:27 +00001095 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalsond86e03b2002-08-03 21:56:15 +00001096 }
Josh Coalson5c491a12002-08-01 06:39:40 +00001097 }
1098
Josh Coalson6b21f662006-09-13 01:42:27 +00001099 /* now that all the metadata is written, we save the stream offset */
1100 if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */
1101 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
1102 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1103 }
1104
Josh Coalsond86e03b2002-08-03 21:56:15 +00001105 if(encoder->protected_->verify)
1106 encoder->private_->verify.state_hint = ENCODER_IN_AUDIO;
1107
Josh Coalson6b21f662006-09-13 01:42:27 +00001108 return FLAC__STREAM_ENCODER_INIT_STATUS_OK;
1109}
1110
1111FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(FLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
1112{
1113 FLAC__StreamEncoderInitStatus init_status;
1114
1115 FLAC__ASSERT(0 != encoder);
1116 FLAC__ASSERT(0 != file);
1117
1118 /*
1119 * To make sure that our file does not go unclosed after an error, we
1120 * must assign the FILE pointer before any further error can occur in
1121 * this routine.
1122 */
1123 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1124 return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
1125
1126 /* double protection */
1127 if(file == 0) {
1128 encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR;
1129 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1130 }
1131
1132 if(file == stdout)
1133 file = get_binary_stdout_(); /* just to be safe */
1134
1135 encoder->private_->file = file;
1136
1137 encoder->private_->progress_callback = progress_callback;
1138 encoder->private_->bytes_written = 0;
1139 encoder->private_->samples_written = 0;
1140 encoder->private_->frames_written = 0;
1141
1142 init_status = FLAC__stream_encoder_init_stream(encoder, file_write_callback_, file_seek_callback_, file_tell_callback_, /*metadata_callback=*/0, client_data);
1143 if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
1144 /* the above function sets the state for us in case of an error */
1145 return init_status;
1146 }
1147
1148 {
1149 unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder);
1150
1151 FLAC__ASSERT(blocksize != 0);
1152 encoder->private_->total_frames_estimate = (unsigned)((FLAC__stream_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
1153 }
1154
1155 return init_status;
1156}
1157
1158FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
1159{
1160 FILE *file;
1161
1162 FLAC__ASSERT(0 != encoder);
1163
1164 /*
1165 * To make sure that our file does not go unclosed after an error, we
1166 * have to do the same entrance checks here that are later performed
1167 * in FLAC__stream_encoder_init_FILE() before the FILE* is assigned.
1168 */
1169 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1170 return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
1171
1172 file = filename? fopen(filename, "w+b") : stdout;
1173
1174 if(file == 0) {
1175 encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR;
1176 return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
1177 }
1178
1179 return FLAC__stream_encoder_init_FILE(encoder, file, progress_callback, client_data);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001180}
1181
Josh Coalson6afed9f2002-10-16 22:29:47 +00001182FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001183{
Josh Coalsonf1eff452002-07-31 07:05:33 +00001184 FLAC__ASSERT(0 != encoder);
Josh Coalson6b21f662006-09-13 01:42:27 +00001185 FLAC__ASSERT(0 != encoder->private_);
1186 FLAC__ASSERT(0 != encoder->protected_);
Josh Coalson2b245f22002-08-07 17:10:50 +00001187
Josh Coalsonfa697a92001-08-16 20:07:29 +00001188 if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001189 return;
Josh Coalson2b245f22002-08-07 17:10:50 +00001190
Josh Coalson3262b0d2002-08-14 20:58:42 +00001191 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson2b245f22002-08-07 17:10:50 +00001192 if(encoder->private_->current_sample_number != 0) {
1193 encoder->protected_->blocksize = encoder->private_->current_sample_number;
1194 process_frame_(encoder, true); /* true => is last frame */
1195 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001196 }
Josh Coalson2b245f22002-08-07 17:10:50 +00001197
Josh Coalson6b21f662006-09-13 01:42:27 +00001198 FLAC__MD5Final(encoder->private_->streaminfo.data.stream_info.md5sum, &encoder->private_->md5context);
Josh Coalson2b245f22002-08-07 17:10:50 +00001199
Josh Coalson3262b0d2002-08-14 20:58:42 +00001200 if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
Josh Coalson6b21f662006-09-13 01:42:27 +00001201 if(encoder->private_->seek_callback)
1202 update_metadata_(encoder);
1203 if(encoder->private_->metadata_callback)
1204 encoder->private_->metadata_callback(encoder, &encoder->private_->streaminfo, encoder->private_->client_data);
Josh Coalson2b245f22002-08-07 17:10:50 +00001205 }
Josh Coalson0a15c142001-06-13 17:59:57 +00001206
Josh Coalsond86e03b2002-08-03 21:56:15 +00001207 if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
1208 FLAC__stream_decoder_finish(encoder->private_->verify.decoder);
1209
Josh Coalson6b21f662006-09-13 01:42:27 +00001210 if(0 != encoder->private_->file) {
1211 if(encoder->private_->file != stdout)
1212 fclose(encoder->private_->file);
1213 encoder->private_->file = 0;
1214 }
1215
Josh Coalsonf1eff452002-07-31 07:05:33 +00001216 free_(encoder);
1217 set_defaults_(encoder);
Josh Coalson92031602002-07-24 06:02:11 +00001218
Josh Coalsonfa697a92001-08-16 20:07:29 +00001219 encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001220}
1221
Josh Coalson6afed9f2002-10-16 22:29:47 +00001222FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001223{
1224 FLAC__ASSERT(0 != encoder);
1225 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1226 return false;
Josh Coalson47c7b142005-01-29 06:08:58 +00001227#ifndef FLAC__MANDATORY_VERIFY_WHILE_ENCODING
Josh Coalsond86e03b2002-08-03 21:56:15 +00001228 encoder->protected_->verify = value;
Josh Coalson47c7b142005-01-29 06:08:58 +00001229#endif
Josh Coalsond86e03b2002-08-03 21:56:15 +00001230 return true;
1231}
1232
Josh Coalson6afed9f2002-10-16 22:29:47 +00001233FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001234{
Josh Coalson92031602002-07-24 06:02:11 +00001235 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001236 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001237 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001238 encoder->protected_->streamable_subset = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001239 return true;
1240}
1241
Josh Coalson6afed9f2002-10-16 22:29:47 +00001242FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001243{
Josh Coalson92031602002-07-24 06:02:11 +00001244 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001245 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001246 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001247 encoder->protected_->do_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001248 return true;
1249}
1250
Josh Coalson6afed9f2002-10-16 22:29:47 +00001251FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001252{
Josh Coalson92031602002-07-24 06:02:11 +00001253 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001254 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001255 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001256 encoder->protected_->loose_mid_side_stereo = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001257 return true;
1258}
1259
Josh Coalson6afed9f2002-10-16 22:29:47 +00001260FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001261{
Josh Coalson92031602002-07-24 06:02:11 +00001262 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001263 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001264 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001265 encoder->protected_->channels = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001266 return true;
1267}
1268
Josh Coalson6afed9f2002-10-16 22:29:47 +00001269FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001270{
Josh Coalson92031602002-07-24 06:02:11 +00001271 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001272 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001273 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001274 encoder->protected_->bits_per_sample = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001275 return true;
1276}
1277
Josh Coalson6afed9f2002-10-16 22:29:47 +00001278FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001279{
Josh Coalson92031602002-07-24 06:02:11 +00001280 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001281 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001282 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001283 encoder->protected_->sample_rate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001284 return true;
1285}
1286
Josh Coalson6afed9f2002-10-16 22:29:47 +00001287FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001288{
Josh Coalson92031602002-07-24 06:02:11 +00001289 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001290 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001291 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001292 encoder->protected_->blocksize = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001293 return true;
1294}
1295
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00001296FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *encoder, const char *specification)
1297{
1298 FLAC__ASSERT(0 != encoder);
1299 FLAC__ASSERT(0 != specification);
1300 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1301 return false;
1302#ifdef FLAC__INTEGER_ONLY_LIBRARY
1303 (void)specification; /* silently ignore since we haven't integerized; will always use a rectangular window */
1304#else
1305 encoder->protected_->num_apodizations = 0;
1306 while(1) {
1307 const char *s = strchr(specification, ';');
1308 const size_t n = s? (size_t)(s - specification) : strlen(specification);
1309 if (n==8 && 0 == strncmp("bartlett" , specification, n))
1310 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BARTLETT;
1311 else if(n==13 && 0 == strncmp("bartlett_hann", specification, n))
1312 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BARTLETT_HANN;
1313 else if(n==8 && 0 == strncmp("blackman" , specification, n))
1314 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BLACKMAN;
1315 else if(n==26 && 0 == strncmp("blackman_harris_4term_92db", specification, n))
1316 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE;
1317 else if(n==6 && 0 == strncmp("connes" , specification, n))
1318 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_CONNES;
1319 else if(n==7 && 0 == strncmp("flattop" , specification, n))
1320 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_FLATTOP;
1321 else if(n>7 && 0 == strncmp("gauss(" , specification, 6)) {
1322 FLAC__real stddev = (FLAC__real)strtod(specification+6, 0);
1323 if (stddev > 0.0 && stddev <= 0.5) {
1324 encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.gauss.stddev = stddev;
1325 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_GAUSS;
1326 }
1327 }
1328 else if(n==7 && 0 == strncmp("hamming" , specification, n))
1329 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_HAMMING;
1330 else if(n==4 && 0 == strncmp("hann" , specification, n))
1331 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_HANN;
1332 else if(n==13 && 0 == strncmp("kaiser_bessel", specification, n))
1333 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_KAISER_BESSEL;
1334 else if(n==7 && 0 == strncmp("nuttall" , specification, n))
1335 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_NUTTALL;
1336 else if(n==9 && 0 == strncmp("rectangle" , specification, n))
1337 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_RECTANGLE;
1338 else if(n==8 && 0 == strncmp("triangle" , specification, n))
1339 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TRIANGLE;
1340 else if(n>7 && 0 == strncmp("tukey(" , specification, 6)) {
1341 FLAC__real p = (FLAC__real)strtod(specification+6, 0);
1342 if (p >= 0.0 && p <= 1.0) {
1343 encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.tukey.p = p;
1344 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY;
1345 }
1346 }
1347 else if(n==5 && 0 == strncmp("welch" , specification, n))
1348 encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_WELCH;
1349 if (encoder->protected_->num_apodizations == 32)
1350 break;
1351 if (s)
1352 specification = s+1;
1353 else
1354 break;
1355 }
1356 if(encoder->protected_->num_apodizations == 0) {
1357 encoder->protected_->num_apodizations = 1;
Josh Coalson82389362006-05-01 05:58:35 +00001358 encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY;
1359 encoder->protected_->apodizations[0].parameters.tukey.p = 0.5;
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00001360 }
1361#ifdef WINDOW_DEBUG_OUTPUT
1362{unsigned n;for(n=0;n<encoder->protected_->num_apodizations;n++)fprintf(stderr,"@@@@@@ parsed apodization[%zu]: %s\n",n,winstr[encoder->protected_->apodizations[n].type]);}
1363#endif
1364#endif
1365 return true;
1366}
1367
Josh Coalson6afed9f2002-10-16 22:29:47 +00001368FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001369{
Josh Coalson92031602002-07-24 06:02:11 +00001370 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001371 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001372 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001373 encoder->protected_->max_lpc_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001374 return true;
1375}
1376
Josh Coalson6afed9f2002-10-16 22:29:47 +00001377FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001378{
Josh Coalson92031602002-07-24 06:02:11 +00001379 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001380 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001381 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001382 encoder->protected_->qlp_coeff_precision = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001383 return true;
1384}
1385
Josh Coalson6afed9f2002-10-16 22:29:47 +00001386FLAC_API FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001387{
Josh Coalson92031602002-07-24 06:02:11 +00001388 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001389 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001390 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001391 encoder->protected_->do_qlp_coeff_prec_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001392 return true;
1393}
1394
Josh Coalson6afed9f2002-10-16 22:29:47 +00001395FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson8395d022001-07-12 21:25:22 +00001396{
Josh Coalson92031602002-07-24 06:02:11 +00001397 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001398 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson8395d022001-07-12 21:25:22 +00001399 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001400#if 0
1401 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001402 encoder->protected_->do_escape_coding = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001403#else
1404 (void)value;
1405#endif
Josh Coalson8395d022001-07-12 21:25:22 +00001406 return true;
1407}
1408
Josh Coalson6afed9f2002-10-16 22:29:47 +00001409FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalson00e53872001-06-16 07:32:25 +00001410{
Josh Coalson92031602002-07-24 06:02:11 +00001411 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001412 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001413 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001414 encoder->protected_->do_exhaustive_model_search = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001415 return true;
1416}
1417
Josh Coalson6afed9f2002-10-16 22:29:47 +00001418FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001419{
Josh Coalson92031602002-07-24 06:02:11 +00001420 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001421 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001422 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001423 encoder->protected_->min_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001424 return true;
1425}
1426
Josh Coalson6afed9f2002-10-16 22:29:47 +00001427FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001428{
Josh Coalson92031602002-07-24 06:02:11 +00001429 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001430 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001431 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001432 encoder->protected_->max_residual_partition_order = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001433 return true;
1434}
1435
Josh Coalson6afed9f2002-10-16 22:29:47 +00001436FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value)
Josh Coalson00e53872001-06-16 07:32:25 +00001437{
Josh Coalson92031602002-07-24 06:02:11 +00001438 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001439 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001440 return false;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001441#if 0
1442 /*@@@ deprecated: */
Josh Coalsonfa697a92001-08-16 20:07:29 +00001443 encoder->protected_->rice_parameter_search_dist = value;
Josh Coalson680e3aa2002-08-01 07:32:17 +00001444#else
1445 (void)value;
1446#endif
Josh Coalson00e53872001-06-16 07:32:25 +00001447 return true;
1448}
1449
Josh Coalson6afed9f2002-10-16 22:29:47 +00001450FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)
Josh Coalson00e53872001-06-16 07:32:25 +00001451{
Josh Coalson92031602002-07-24 06:02:11 +00001452 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001453 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001454 return false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001455 encoder->protected_->total_samples_estimate = value;
Josh Coalson00e53872001-06-16 07:32:25 +00001456 return true;
1457}
1458
Josh Coalson6afed9f2002-10-16 22:29:47 +00001459FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
Josh Coalson00e53872001-06-16 07:32:25 +00001460{
Josh Coalson92031602002-07-24 06:02:11 +00001461 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001462 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalson00e53872001-06-16 07:32:25 +00001463 return false;
Josh Coalson66075c12002-06-01 05:39:38 +00001464 encoder->protected_->metadata = metadata;
1465 encoder->protected_->num_metadata_blocks = num_blocks;
Josh Coalson6b21f662006-09-13 01:42:27 +00001466 if(0 != metadata && num_blocks > 0) {
1467 unsigned i;
1468 for(i = 0; i < num_blocks; i++) {
1469 if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
1470 encoder->private_->seek_table = &metadata[i]->data.seek_table;
1471 break; /* take only the first one */
1472 }
1473 }
1474 }
Josh Coalson00e53872001-06-16 07:32:25 +00001475 return true;
1476}
1477
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001478/*
1479 * These three functions are not static, but not publically exposed in
1480 * include/FLAC/ either. They are used by the test suite.
1481 */
Josh Coalson6afed9f2002-10-16 22:29:47 +00001482FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001483{
1484 FLAC__ASSERT(0 != encoder);
1485 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1486 return false;
1487 encoder->private_->disable_constant_subframes = value;
1488 return true;
1489}
1490
Josh Coalson6afed9f2002-10-16 22:29:47 +00001491FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001492{
1493 FLAC__ASSERT(0 != encoder);
1494 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1495 return false;
1496 encoder->private_->disable_fixed_subframes = value;
1497 return true;
1498}
1499
Josh Coalson6afed9f2002-10-16 22:29:47 +00001500FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001501{
1502 FLAC__ASSERT(0 != encoder);
1503 if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
1504 return false;
1505 encoder->private_->disable_verbatim_subframes = value;
1506 return true;
1507}
1508
Josh Coalson6afed9f2002-10-16 22:29:47 +00001509FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001510{
Josh Coalson92031602002-07-24 06:02:11 +00001511 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001512 return encoder->protected_->state;
Josh Coalson0a15c142001-06-13 17:59:57 +00001513}
1514
Josh Coalson6afed9f2002-10-16 22:29:47 +00001515FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001516{
1517 FLAC__ASSERT(0 != encoder);
1518 if(encoder->protected_->verify)
1519 return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder);
1520 else
1521 return FLAC__STREAM_DECODER_UNINITIALIZED;
1522}
1523
Josh Coalson02954222002-11-08 06:16:31 +00001524FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder)
1525{
1526 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR)
1527 return FLAC__StreamEncoderStateString[encoder->protected_->state];
1528 else
Josh Coalson807140d2003-09-24 22:10:51 +00001529 return FLAC__stream_decoder_get_resolved_state_string(encoder->private_->verify.decoder);
Josh Coalson02954222002-11-08 06:16:31 +00001530}
1531
Josh Coalson6afed9f2002-10-16 22:29:47 +00001532FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
Josh Coalson589f8c72002-08-07 23:54:55 +00001533{
1534 FLAC__ASSERT(0 != encoder);
1535 if(0 != absolute_sample)
1536 *absolute_sample = encoder->private_->verify.error_stats.absolute_sample;
1537 if(0 != frame_number)
1538 *frame_number = encoder->private_->verify.error_stats.frame_number;
1539 if(0 != channel)
1540 *channel = encoder->private_->verify.error_stats.channel;
1541 if(0 != sample)
1542 *sample = encoder->private_->verify.error_stats.sample;
1543 if(0 != expected)
1544 *expected = encoder->private_->verify.error_stats.expected;
1545 if(0 != got)
1546 *got = encoder->private_->verify.error_stats.got;
1547}
1548
Josh Coalson6afed9f2002-10-16 22:29:47 +00001549FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder)
Josh Coalsond86e03b2002-08-03 21:56:15 +00001550{
1551 FLAC__ASSERT(0 != encoder);
1552 return encoder->protected_->verify;
1553}
1554
Josh Coalson6afed9f2002-10-16 22:29:47 +00001555FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001556{
Josh Coalson92031602002-07-24 06:02:11 +00001557 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001558 return encoder->protected_->streamable_subset;
Josh Coalson0a15c142001-06-13 17:59:57 +00001559}
1560
Josh Coalson6afed9f2002-10-16 22:29:47 +00001561FLAC_API FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001562{
Josh Coalson92031602002-07-24 06:02:11 +00001563 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001564 return encoder->protected_->do_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001565}
1566
Josh Coalson6afed9f2002-10-16 22:29:47 +00001567FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001568{
Josh Coalson92031602002-07-24 06:02:11 +00001569 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001570 return encoder->protected_->loose_mid_side_stereo;
Josh Coalson0a15c142001-06-13 17:59:57 +00001571}
1572
Josh Coalson6afed9f2002-10-16 22:29:47 +00001573FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001574{
Josh Coalson92031602002-07-24 06:02:11 +00001575 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001576 return encoder->protected_->channels;
Josh Coalson0a15c142001-06-13 17:59:57 +00001577}
1578
Josh Coalson6afed9f2002-10-16 22:29:47 +00001579FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001580{
Josh Coalson92031602002-07-24 06:02:11 +00001581 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001582 return encoder->protected_->bits_per_sample;
Josh Coalson0a15c142001-06-13 17:59:57 +00001583}
1584
Josh Coalson6afed9f2002-10-16 22:29:47 +00001585FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001586{
Josh Coalson92031602002-07-24 06:02:11 +00001587 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001588 return encoder->protected_->sample_rate;
Josh Coalson0a15c142001-06-13 17:59:57 +00001589}
1590
Josh Coalson6afed9f2002-10-16 22:29:47 +00001591FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001592{
Josh Coalson92031602002-07-24 06:02:11 +00001593 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001594 return encoder->protected_->blocksize;
Josh Coalson0a15c142001-06-13 17:59:57 +00001595}
1596
Josh Coalson6afed9f2002-10-16 22:29:47 +00001597FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001598{
Josh Coalson92031602002-07-24 06:02:11 +00001599 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001600 return encoder->protected_->max_lpc_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001601}
1602
Josh Coalson6afed9f2002-10-16 22:29:47 +00001603FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001604{
Josh Coalson92031602002-07-24 06:02:11 +00001605 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001606 return encoder->protected_->qlp_coeff_precision;
Josh Coalson0a15c142001-06-13 17:59:57 +00001607}
1608
Josh Coalson6afed9f2002-10-16 22:29:47 +00001609FLAC_API FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001610{
Josh Coalson92031602002-07-24 06:02:11 +00001611 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001612 return encoder->protected_->do_qlp_coeff_prec_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001613}
1614
Josh Coalson6afed9f2002-10-16 22:29:47 +00001615FLAC_API FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder)
Josh Coalson8395d022001-07-12 21:25:22 +00001616{
Josh Coalson92031602002-07-24 06:02:11 +00001617 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001618 return encoder->protected_->do_escape_coding;
Josh Coalson8395d022001-07-12 21:25:22 +00001619}
1620
Josh Coalson6afed9f2002-10-16 22:29:47 +00001621FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001622{
Josh Coalson92031602002-07-24 06:02:11 +00001623 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001624 return encoder->protected_->do_exhaustive_model_search;
Josh Coalson0a15c142001-06-13 17:59:57 +00001625}
1626
Josh Coalson6afed9f2002-10-16 22:29:47 +00001627FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001628{
Josh Coalson92031602002-07-24 06:02:11 +00001629 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001630 return encoder->protected_->min_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001631}
1632
Josh Coalson6afed9f2002-10-16 22:29:47 +00001633FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001634{
Josh Coalson92031602002-07-24 06:02:11 +00001635 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001636 return encoder->protected_->max_residual_partition_order;
Josh Coalson0a15c142001-06-13 17:59:57 +00001637}
1638
Josh Coalson6afed9f2002-10-16 22:29:47 +00001639FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
Josh Coalson0a15c142001-06-13 17:59:57 +00001640{
Josh Coalson92031602002-07-24 06:02:11 +00001641 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001642 return encoder->protected_->rice_parameter_search_dist;
Josh Coalson0a15c142001-06-13 17:59:57 +00001643}
1644
Josh Coalson6afed9f2002-10-16 22:29:47 +00001645FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder)
Josh Coalson3a7b2c92002-08-02 07:38:20 +00001646{
1647 FLAC__ASSERT(0 != encoder);
1648 return encoder->protected_->total_samples_estimate;
1649}
1650
Josh Coalson6afed9f2002-10-16 22:29:47 +00001651FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001652{
1653 unsigned i, j, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001654 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001655 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001656
Josh Coalsonf1eff452002-07-31 07:05:33 +00001657 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001658 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001659
1660 j = 0;
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001661 /*
1662 * we have several flavors of the same basic loop, optimized for
1663 * different conditions:
1664 */
1665 if(encoder->protected_->max_lpc_order > 0) {
1666 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
1667 /*
1668 * stereo coding: unroll channel loop
1669 * with LPC: calculate floating point version of signal
1670 */
1671 do {
1672 if(encoder->protected_->verify)
1673 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
Josh Coalsond86e03b2002-08-03 21:56:15 +00001674
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001675 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1676 x = mid = side = buffer[0][j];
1677 encoder->private_->integer_signal[0][i] = x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001678#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001679 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001680#endif
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001681 x = buffer[1][j];
1682 encoder->private_->integer_signal[1][i] = x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001683#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001684 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001685#endif
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001686 mid += x;
1687 side -= x;
1688 mid >>= 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */
1689 encoder->private_->integer_signal_mid_side[1][i] = side;
1690 encoder->private_->integer_signal_mid_side[0][i] = mid;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001691#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001692 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1693 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001694#endif
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001695 encoder->private_->current_sample_number++;
1696 }
1697 if(i == blocksize) {
1698 if(!process_frame_(encoder, false)) /* false => not last frame */
1699 return false;
1700 }
1701 } while(j < samples);
1702 }
1703 else {
1704 /*
1705 * independent channel coding: buffer each channel in inner loop
1706 * with LPC: calculate floating point version of signal
1707 */
1708 do {
1709 if(encoder->protected_->verify)
1710 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1711
1712 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1713 for(channel = 0; channel < channels; channel++) {
1714 x = buffer[channel][j];
1715 encoder->private_->integer_signal[channel][i] = x;
1716#ifndef FLAC__INTEGER_ONLY_LIBRARY
1717 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
1718#endif
1719 }
1720 encoder->private_->current_sample_number++;
1721 }
1722 if(i == blocksize) {
1723 if(!process_frame_(encoder, false)) /* false => not last frame */
1724 return false;
1725 }
1726 } while(j < samples);
1727 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001728 }
1729 else {
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001730 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
1731 /*
1732 * stereo coding: unroll channel loop
1733 * without LPC: no need to calculate floating point version of signal
1734 */
1735 do {
1736 if(encoder->protected_->verify)
1737 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
Josh Coalsond86e03b2002-08-03 21:56:15 +00001738
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001739 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1740 encoder->private_->integer_signal[0][i] = mid = side = buffer[0][j];
1741 x = buffer[1][j];
1742 encoder->private_->integer_signal[1][i] = x;
1743 mid += x;
1744 side -= x;
1745 mid >>= 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */
1746 encoder->private_->integer_signal_mid_side[1][i] = side;
1747 encoder->private_->integer_signal_mid_side[0][i] = mid;
1748 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001749 }
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001750 if(i == blocksize) {
1751 if(!process_frame_(encoder, false)) /* false => not last frame */
1752 return false;
1753 }
1754 } while(j < samples);
1755 }
1756 else {
1757 /*
1758 * independent channel coding: buffer each channel in inner loop
1759 * without LPC: no need to calculate floating point version of signal
1760 */
1761 do {
1762 if(encoder->protected_->verify)
1763 append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1764
1765 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1766 for(channel = 0; channel < channels; channel++)
1767 encoder->private_->integer_signal[channel][i] = buffer[channel][j];
1768 encoder->private_->current_sample_number++;
1769 }
1770 if(i == blocksize) {
1771 if(!process_frame_(encoder, false)) /* false => not last frame */
1772 return false;
1773 }
1774 } while(j < samples);
1775 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001776 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001777
1778 return true;
1779}
1780
Josh Coalson6afed9f2002-10-16 22:29:47 +00001781FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001782{
1783 unsigned i, j, k, channel;
Josh Coalson77e3f312001-06-23 03:03:24 +00001784 FLAC__int32 x, mid, side;
Josh Coalsonfa697a92001-08-16 20:07:29 +00001785 const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001786
Josh Coalsonf1eff452002-07-31 07:05:33 +00001787 FLAC__ASSERT(0 != encoder);
Josh Coalsonfa697a92001-08-16 20:07:29 +00001788 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001789
1790 j = k = 0;
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001791 /*
1792 * we have several flavors of the same basic loop, optimized for
1793 * different conditions:
1794 */
1795 if(encoder->protected_->max_lpc_order > 0) {
1796 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
1797 /*
1798 * stereo coding: unroll channel loop
1799 * with LPC: calculate floating point version of signal
1800 */
1801 do {
1802 if(encoder->protected_->verify)
1803 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
Josh Coalsond86e03b2002-08-03 21:56:15 +00001804
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001805 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1806 x = mid = side = buffer[k++];
1807 encoder->private_->integer_signal[0][i] = x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001808#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001809 encoder->private_->real_signal[0][i] = (FLAC__real)x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001810#endif
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001811 x = buffer[k++];
1812 encoder->private_->integer_signal[1][i] = x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001813#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001814 encoder->private_->real_signal[1][i] = (FLAC__real)x;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001815#endif
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001816 mid += x;
1817 side -= x;
1818 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
1819 encoder->private_->integer_signal_mid_side[1][i] = side;
1820 encoder->private_->integer_signal_mid_side[0][i] = mid;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001821#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001822 encoder->private_->real_signal_mid_side[1][i] = (FLAC__real)side;
1823 encoder->private_->real_signal_mid_side[0][i] = (FLAC__real)mid;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001824#endif
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001825 encoder->private_->current_sample_number++;
1826 }
1827 if(i == blocksize) {
1828 if(!process_frame_(encoder, false)) /* false => not last frame */
1829 return false;
1830 }
1831 } while(j < samples);
1832 }
1833 else {
1834 /*
1835 * independent channel coding: buffer each channel in inner loop
1836 * with LPC: calculate floating point version of signal
1837 */
1838 do {
1839 if(encoder->protected_->verify)
1840 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1841
1842 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1843 for(channel = 0; channel < channels; channel++) {
1844 x = buffer[k++];
1845 encoder->private_->integer_signal[channel][i] = x;
1846#ifndef FLAC__INTEGER_ONLY_LIBRARY
1847 encoder->private_->real_signal[channel][i] = (FLAC__real)x;
1848#endif
1849 }
1850 encoder->private_->current_sample_number++;
1851 }
1852 if(i == blocksize) {
1853 if(!process_frame_(encoder, false)) /* false => not last frame */
1854 return false;
1855 }
1856 } while(j < samples);
1857 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001858 }
1859 else {
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001860 if(encoder->protected_->do_mid_side_stereo && channels == 2) {
1861 /*
1862 * stereo coding: unroll channel loop
1863 * without LPC: no need to calculate floating point version of signal
1864 */
1865 do {
1866 if(encoder->protected_->verify)
1867 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
Josh Coalsond86e03b2002-08-03 21:56:15 +00001868
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001869 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1870 encoder->private_->integer_signal[0][i] = mid = side = buffer[k++];
Josh Coalson57ba6f42002-06-07 05:27:37 +00001871 x = buffer[k++];
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001872 encoder->private_->integer_signal[1][i] = x;
1873 mid += x;
1874 side -= x;
1875 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
1876 encoder->private_->integer_signal_mid_side[1][i] = side;
1877 encoder->private_->integer_signal_mid_side[0][i] = mid;
1878 encoder->private_->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +00001879 }
Josh Coalsonc549f0f2004-12-30 03:47:49 +00001880 if(i == blocksize) {
1881 if(!process_frame_(encoder, false)) /* false => not last frame */
1882 return false;
1883 }
1884 } while(j < samples);
1885 }
1886 else {
1887 /*
1888 * independent channel coding: buffer each channel in inner loop
1889 * without LPC: no need to calculate floating point version of signal
1890 */
1891 do {
1892 if(encoder->protected_->verify)
1893 append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j));
1894
1895 for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) {
1896 for(channel = 0; channel < channels; channel++)
1897 encoder->private_->integer_signal[channel][i] = buffer[k++];
1898 encoder->private_->current_sample_number++;
1899 }
1900 if(i == blocksize) {
1901 if(!process_frame_(encoder, false)) /* false => not last frame */
1902 return false;
1903 }
1904 } while(j < samples);
1905 }
Josh Coalsonaa255362001-05-31 06:17:41 +00001906 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00001907
1908 return true;
1909}
1910
Josh Coalsonf1eff452002-07-31 07:05:33 +00001911/***********************************************************************
1912 *
1913 * Private class methods
1914 *
1915 ***********************************************************************/
1916
1917void set_defaults_(FLAC__StreamEncoder *encoder)
Josh Coalson92031602002-07-24 06:02:11 +00001918{
1919 FLAC__ASSERT(0 != encoder);
1920
Josh Coalson47c7b142005-01-29 06:08:58 +00001921#ifdef FLAC__MANDATORY_VERIFY_WHILE_ENCODING
1922 encoder->protected_->verify = true;
1923#else
Josh Coalsond86e03b2002-08-03 21:56:15 +00001924 encoder->protected_->verify = false;
Josh Coalson47c7b142005-01-29 06:08:58 +00001925#endif
Josh Coalson92031602002-07-24 06:02:11 +00001926 encoder->protected_->streamable_subset = true;
1927 encoder->protected_->do_mid_side_stereo = false;
1928 encoder->protected_->loose_mid_side_stereo = false;
1929 encoder->protected_->channels = 2;
1930 encoder->protected_->bits_per_sample = 16;
1931 encoder->protected_->sample_rate = 44100;
1932 encoder->protected_->blocksize = 1152;
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00001933#ifndef FLAC__INTEGER_ONLY_LIBRARY
1934 encoder->protected_->num_apodizations = 1;
Josh Coalson82389362006-05-01 05:58:35 +00001935 encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY;
1936 encoder->protected_->apodizations[0].parameters.tukey.p = 0.5;
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00001937#endif
Josh Coalson92031602002-07-24 06:02:11 +00001938 encoder->protected_->max_lpc_order = 0;
1939 encoder->protected_->qlp_coeff_precision = 0;
1940 encoder->protected_->do_qlp_coeff_prec_search = false;
1941 encoder->protected_->do_exhaustive_model_search = false;
1942 encoder->protected_->do_escape_coding = false;
1943 encoder->protected_->min_residual_partition_order = 0;
1944 encoder->protected_->max_residual_partition_order = 0;
1945 encoder->protected_->rice_parameter_search_dist = 0;
1946 encoder->protected_->total_samples_estimate = 0;
1947 encoder->protected_->metadata = 0;
1948 encoder->protected_->num_metadata_blocks = 0;
1949
Josh Coalson6b21f662006-09-13 01:42:27 +00001950 encoder->private_->seek_table = 0;
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00001951 encoder->private_->disable_constant_subframes = false;
1952 encoder->private_->disable_fixed_subframes = false;
1953 encoder->private_->disable_verbatim_subframes = false;
Josh Coalson92031602002-07-24 06:02:11 +00001954 encoder->private_->write_callback = 0;
Josh Coalson6b21f662006-09-13 01:42:27 +00001955 encoder->private_->seek_callback = 0;
1956 encoder->private_->tell_callback = 0;
Josh Coalson92031602002-07-24 06:02:11 +00001957 encoder->private_->metadata_callback = 0;
Josh Coalson6b21f662006-09-13 01:42:27 +00001958 encoder->private_->progress_callback = 0;
Josh Coalson92031602002-07-24 06:02:11 +00001959 encoder->private_->client_data = 0;
1960}
1961
Josh Coalsonf1eff452002-07-31 07:05:33 +00001962void free_(FLAC__StreamEncoder *encoder)
Josh Coalson639aeb02002-07-25 05:38:23 +00001963{
1964 unsigned i, channel;
1965
Josh Coalsonf1eff452002-07-31 07:05:33 +00001966 FLAC__ASSERT(0 != encoder);
Josh Coalson639aeb02002-07-25 05:38:23 +00001967 for(i = 0; i < encoder->protected_->channels; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001968 if(0 != encoder->private_->integer_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001969 free(encoder->private_->integer_signal_unaligned[i]);
1970 encoder->private_->integer_signal_unaligned[i] = 0;
1971 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001972#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonf1eff452002-07-31 07:05:33 +00001973 if(0 != encoder->private_->real_signal_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001974 free(encoder->private_->real_signal_unaligned[i]);
1975 encoder->private_->real_signal_unaligned[i] = 0;
1976 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001977#endif
Josh Coalson639aeb02002-07-25 05:38:23 +00001978 }
1979 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00001980 if(0 != encoder->private_->integer_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001981 free(encoder->private_->integer_signal_mid_side_unaligned[i]);
1982 encoder->private_->integer_signal_mid_side_unaligned[i] = 0;
1983 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001984#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonf1eff452002-07-31 07:05:33 +00001985 if(0 != encoder->private_->real_signal_mid_side_unaligned[i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00001986 free(encoder->private_->real_signal_mid_side_unaligned[i]);
1987 encoder->private_->real_signal_mid_side_unaligned[i] = 0;
1988 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +00001989#endif
Josh Coalson639aeb02002-07-25 05:38:23 +00001990 }
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00001991#ifndef FLAC__INTEGER_ONLY_LIBRARY
1992 for(i = 0; i < encoder->protected_->num_apodizations; i++) {
1993 if(0 != encoder->private_->window_unaligned[i]) {
1994 free(encoder->private_->window_unaligned[i]);
1995 encoder->private_->window_unaligned[i] = 0;
1996 }
1997 }
1998 if(0 != encoder->private_->windowed_signal_unaligned) {
1999 free(encoder->private_->windowed_signal_unaligned);
2000 encoder->private_->windowed_signal_unaligned = 0;
2001 }
2002#endif
Josh Coalson639aeb02002-07-25 05:38:23 +00002003 for(channel = 0; channel < encoder->protected_->channels; channel++) {
2004 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00002005 if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00002006 free(encoder->private_->residual_workspace_unaligned[channel][i]);
2007 encoder->private_->residual_workspace_unaligned[channel][i] = 0;
2008 }
2009 }
2010 }
2011 for(channel = 0; channel < 2; channel++) {
2012 for(i = 0; i < 2; i++) {
Josh Coalsonf1eff452002-07-31 07:05:33 +00002013 if(0 != encoder->private_->residual_workspace_mid_side_unaligned[channel][i]) {
Josh Coalson639aeb02002-07-25 05:38:23 +00002014 free(encoder->private_->residual_workspace_mid_side_unaligned[channel][i]);
2015 encoder->private_->residual_workspace_mid_side_unaligned[channel][i] = 0;
2016 }
2017 }
2018 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00002019 if(0 != encoder->private_->abs_residual_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00002020 free(encoder->private_->abs_residual_unaligned);
2021 encoder->private_->abs_residual_unaligned = 0;
2022 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00002023 if(0 != encoder->private_->abs_residual_partition_sums_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00002024 free(encoder->private_->abs_residual_partition_sums_unaligned);
2025 encoder->private_->abs_residual_partition_sums_unaligned = 0;
2026 }
Josh Coalsonf1eff452002-07-31 07:05:33 +00002027 if(0 != encoder->private_->raw_bits_per_partition_unaligned) {
Josh Coalson639aeb02002-07-25 05:38:23 +00002028 free(encoder->private_->raw_bits_per_partition_unaligned);
2029 encoder->private_->raw_bits_per_partition_unaligned = 0;
2030 }
Josh Coalsond86e03b2002-08-03 21:56:15 +00002031 if(encoder->protected_->verify) {
2032 for(i = 0; i < encoder->protected_->channels; i++) {
2033 if(0 != encoder->private_->verify.input_fifo.data[i]) {
2034 free(encoder->private_->verify.input_fifo.data[i]);
2035 encoder->private_->verify.input_fifo.data[i] = 0;
2036 }
2037 }
2038 }
Josh Coalson639aeb02002-07-25 05:38:23 +00002039 FLAC__bitbuffer_free(encoder->private_->frame);
2040}
2041
Josh Coalsonf1eff452002-07-31 07:05:33 +00002042FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002043{
Josh Coalson77e3f312001-06-23 03:03:24 +00002044 FLAC__bool ok;
Josh Coalson0a15c142001-06-13 17:59:57 +00002045 unsigned i, channel;
2046
2047 FLAC__ASSERT(new_size > 0);
Josh Coalsonfa697a92001-08-16 20:07:29 +00002048 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
2049 FLAC__ASSERT(encoder->private_->current_sample_number == 0);
Josh Coalson0a15c142001-06-13 17:59:57 +00002050
2051 /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002052 if(new_size <= encoder->private_->input_capacity)
Josh Coalson0a15c142001-06-13 17:59:57 +00002053 return true;
2054
2055 ok = true;
Josh Coalson8395d022001-07-12 21:25:22 +00002056
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002057 /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx()
2058 * requires that the input arrays (in our case the integer signals)
2059 * have a buffer of up to 3 zeroes in front (at negative indices) for
2060 * alignment purposes; we use 4 to keep the data well-aligned.
2061 */
Josh Coalson8395d022001-07-12 21:25:22 +00002062
Josh Coalsonfa697a92001-08-16 20:07:29 +00002063 for(i = 0; ok && i < encoder->protected_->channels; i++) {
2064 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size+4, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]);
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002065#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00002066 if(encoder->protected_->max_lpc_order > 0)
2067 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]);
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002068#endif
Josh Coalsonfa697a92001-08-16 20:07:29 +00002069 memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4);
2070 encoder->private_->integer_signal[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00002071 }
2072 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002073 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]);
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002074#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalsonc549f0f2004-12-30 03:47:49 +00002075 if(encoder->protected_->max_lpc_order > 0)
2076 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]);
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002077#endif
Josh Coalsonfa697a92001-08-16 20:07:29 +00002078 memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4);
2079 encoder->private_->integer_signal_mid_side[i] += 4;
Josh Coalson0a15c142001-06-13 17:59:57 +00002080 }
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002081#ifndef FLAC__INTEGER_ONLY_LIBRARY
2082 if(ok && encoder->protected_->max_lpc_order > 0) {
2083 for(i = 0; ok && i < encoder->protected_->num_apodizations; i++)
2084 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->window_unaligned[i], &encoder->private_->window[i]);
2085 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->windowed_signal_unaligned, &encoder->private_->windowed_signal);
2086 }
2087#endif
Josh Coalsonfa697a92001-08-16 20:07:29 +00002088 for(channel = 0; ok && channel < encoder->protected_->channels; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00002089 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002090 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 +00002091 }
2092 }
2093 for(channel = 0; ok && channel < 2; channel++) {
2094 for(i = 0; ok && i < 2; i++) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002095 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 +00002096 }
2097 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00002098 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->private_->abs_residual_unaligned, &encoder->private_->abs_residual);
2099 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 */
2100 ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_size * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums);
2101 if(encoder->protected_->do_escape_coding)
2102 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 +00002103
2104 if(ok)
Josh Coalsonfa697a92001-08-16 20:07:29 +00002105 encoder->private_->input_capacity = new_size;
Josh Coalson0a15c142001-06-13 17:59:57 +00002106 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00002107 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson0a15c142001-06-13 17:59:57 +00002108
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002109#ifndef FLAC__INTEGER_ONLY_LIBRARY
2110 if(ok && encoder->protected_->max_lpc_order > 0) {
2111 for(i = 0; ok && i < encoder->protected_->num_apodizations; i++) {
2112 switch(encoder->protected_->apodizations[i].type) {
2113 case FLAC__APODIZATION_BARTLETT:
2114 FLAC__window_bartlett(encoder->private_->window[i], new_size);
2115 break;
2116 case FLAC__APODIZATION_BARTLETT_HANN:
2117 FLAC__window_bartlett_hann(encoder->private_->window[i], new_size);
2118 break;
2119 case FLAC__APODIZATION_BLACKMAN:
2120 FLAC__window_blackman(encoder->private_->window[i], new_size);
2121 break;
2122 case FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE:
2123 FLAC__window_blackman_harris_4term_92db_sidelobe(encoder->private_->window[i], new_size);
2124 break;
2125 case FLAC__APODIZATION_CONNES:
2126 FLAC__window_connes(encoder->private_->window[i], new_size);
2127 break;
2128 case FLAC__APODIZATION_FLATTOP:
2129 FLAC__window_flattop(encoder->private_->window[i], new_size);
2130 break;
2131 case FLAC__APODIZATION_GAUSS:
2132 FLAC__window_gauss(encoder->private_->window[i], new_size, encoder->protected_->apodizations[i].parameters.gauss.stddev);
2133 break;
2134 case FLAC__APODIZATION_HAMMING:
2135 FLAC__window_hamming(encoder->private_->window[i], new_size);
2136 break;
2137 case FLAC__APODIZATION_HANN:
2138 FLAC__window_hann(encoder->private_->window[i], new_size);
2139 break;
2140 case FLAC__APODIZATION_KAISER_BESSEL:
2141 FLAC__window_kaiser_bessel(encoder->private_->window[i], new_size);
2142 break;
2143 case FLAC__APODIZATION_NUTTALL:
2144 FLAC__window_nuttall(encoder->private_->window[i], new_size);
2145 break;
2146 case FLAC__APODIZATION_RECTANGLE:
2147 FLAC__window_rectangle(encoder->private_->window[i], new_size);
2148 break;
2149 case FLAC__APODIZATION_TRIANGLE:
2150 FLAC__window_triangle(encoder->private_->window[i], new_size);
2151 break;
2152 case FLAC__APODIZATION_TUKEY:
2153 FLAC__window_tukey(encoder->private_->window[i], new_size, encoder->protected_->apodizations[i].parameters.tukey.p);
2154 break;
2155 case FLAC__APODIZATION_WELCH:
2156 FLAC__window_welch(encoder->private_->window[i], new_size);
2157 break;
2158 default:
2159 FLAC__ASSERT(0);
2160 /* double protection */
Josh Coalsondf598452006-04-28 00:13:34 +00002161 FLAC__window_hann(encoder->private_->window[i], new_size);
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002162 break;
2163 }
2164 }
2165 }
2166#endif
2167
Josh Coalson0a15c142001-06-13 17:59:57 +00002168 return ok;
2169}
2170
Josh Coalsond86e03b2002-08-03 21:56:15 +00002171FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
Josh Coalson5c491a12002-08-01 06:39:40 +00002172{
2173 const FLAC__byte *buffer;
2174 unsigned bytes;
2175
2176 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
2177
2178 FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
2179
Josh Coalsond86e03b2002-08-03 21:56:15 +00002180 if(encoder->protected_->verify) {
2181 encoder->private_->verify.output.data = buffer;
2182 encoder->private_->verify.output.bytes = bytes;
2183 if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) {
2184 encoder->private_->verify.needs_magic_hack = true;
2185 }
2186 else {
2187 if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) {
2188 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
2189 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
2190 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
2191 return false;
2192 }
2193 }
2194 }
2195
Josh Coalson6b21f662006-09-13 01:42:27 +00002196 if(write_frame_(encoder, buffer, bytes, samples) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
Josh Coalsondd190232002-12-29 09:30:23 +00002197 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
Josh Coalson6b21f662006-09-13 01:42:27 +00002198 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
Josh Coalson5c491a12002-08-01 06:39:40 +00002199 return false;
Josh Coalsond86e03b2002-08-03 21:56:15 +00002200 }
Josh Coalson5c491a12002-08-01 06:39:40 +00002201
2202 FLAC__bitbuffer_release_buffer(encoder->private_->frame);
2203
Josh Coalsond86e03b2002-08-03 21:56:15 +00002204 if(samples > 0) {
Josh Coalson6b21f662006-09-13 01:42:27 +00002205 encoder->private_->streaminfo.data.stream_info.min_framesize = min(bytes, encoder->private_->streaminfo.data.stream_info.min_framesize);
2206 encoder->private_->streaminfo.data.stream_info.max_framesize = max(bytes, encoder->private_->streaminfo.data.stream_info.max_framesize);
Josh Coalsond86e03b2002-08-03 21:56:15 +00002207 }
2208
Josh Coalson5c491a12002-08-01 06:39:40 +00002209 return true;
2210}
2211
Josh Coalson6b21f662006-09-13 01:42:27 +00002212FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples)
2213{
2214 FLAC__StreamEncoderWriteStatus status;
2215 FLAC__uint64 output_position = 0;
2216
2217 /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */
2218 if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) {
2219 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2220 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
2221 }
2222
2223 /*
2224 * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets.
2225 */
2226 if(samples == 0) {
2227 FLAC__MetadataType type = (buffer[0] & 0x7f);
2228 if(type == FLAC__METADATA_TYPE_STREAMINFO)
2229 encoder->protected_->streaminfo_offset = output_position;
2230 else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0)
2231 encoder->protected_->seektable_offset = output_position;
2232 }
2233
2234 /*
2235 * Mark the current seek point if hit (if audio_offset == 0 that
2236 * means we're still writing metadata and haven't hit the first
2237 * frame yet)
2238 */
2239 if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) {
2240 const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder);
2241 const FLAC__uint64 frame_first_sample = encoder->private_->samples_written;
2242 const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
2243 FLAC__uint64 test_sample;
2244 unsigned i;
2245 for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) {
2246 test_sample = encoder->private_->seek_table->points[i].sample_number;
2247 if(test_sample > frame_last_sample) {
2248 break;
2249 }
2250 else if(test_sample >= frame_first_sample) {
2251 encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
2252 encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset;
2253 encoder->private_->seek_table->points[i].frame_samples = blocksize;
2254 encoder->private_->first_seekpoint_to_check++;
2255 /* DO NOT: "break;" and here's why:
2256 * The seektable template may contain more than one target
2257 * sample for any given frame; we will keep looping, generating
2258 * duplicate seekpoints for them, and we'll clean it up later,
2259 * just before writing the seektable back to the metadata.
2260 */
2261 }
2262 else {
2263 encoder->private_->first_seekpoint_to_check++;
2264 }
2265 }
2266 }
2267
2268 status = encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data);
2269
2270 if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
2271 encoder->private_->bytes_written += bytes;
2272 encoder->private_->samples_written += samples;
2273 /* we keep a high watermark on the number of frames written because
2274 * when the encoder goes back to write metadata, 'current_frame'
2275 * will drop back to 0.
2276 */
2277 encoder->private_->frames_written = max(encoder->private_->frames_written, encoder->private_->current_frame_number+1);
2278 }
2279 else
2280 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2281
2282 return status;
2283}
2284
2285/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks. */
2286void update_metadata_(const FLAC__StreamEncoder *encoder)
2287{
2288 FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
2289 const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo;
2290 const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
2291 const unsigned min_framesize = metadata->data.stream_info.min_framesize;
2292 const unsigned max_framesize = metadata->data.stream_info.max_framesize;
2293 const unsigned bps = metadata->data.stream_info.bits_per_sample;
2294 FLAC__StreamEncoderSeekStatus seek_status;
2295
2296 FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
2297
2298 /* All this is based on intimate knowledge of the stream header
2299 * layout, but a change to the header format that would break this
2300 * would also break all streams encoded in the previous format.
2301 */
2302
2303 /*
2304 * Write MD5 signature
2305 */
2306 {
2307 const unsigned md5_offset =
2308 FLAC__STREAM_METADATA_HEADER_LENGTH +
2309 (
2310 FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
2311 FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
2312 FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
2313 FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
2314 FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
2315 FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
2316 FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
2317 FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
2318 ) / 8;
2319
2320 if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + md5_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
2321 if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
2322 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2323 return;
2324 }
2325 if(encoder->private_->write_callback(encoder, metadata->data.stream_info.md5sum, 16, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
2326 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2327 return;
2328 }
2329 }
2330
2331 /*
2332 * Write total samples
2333 */
2334 {
2335 const unsigned total_samples_byte_offset =
2336 FLAC__STREAM_METADATA_HEADER_LENGTH +
2337 (
2338 FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
2339 FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
2340 FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
2341 FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
2342 FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
2343 FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
2344 FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
2345 - 4
2346 ) / 8;
2347
2348 b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F);
2349 b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
2350 b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
2351 b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
2352 b[4] = (FLAC__byte)(samples & 0xFF);
2353 if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + total_samples_byte_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
2354 if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
2355 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2356 return;
2357 }
2358 if(encoder->private_->write_callback(encoder, b, 5, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
2359 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2360 return;
2361 }
2362 }
2363
2364 /*
2365 * Write min/max framesize
2366 */
2367 {
2368 const unsigned min_framesize_offset =
2369 FLAC__STREAM_METADATA_HEADER_LENGTH +
2370 (
2371 FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
2372 FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
2373 ) / 8;
2374
2375 b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
2376 b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
2377 b[2] = (FLAC__byte)(min_framesize & 0xFF);
2378 b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
2379 b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
2380 b[5] = (FLAC__byte)(max_framesize & 0xFF);
2381 if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + min_framesize_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
2382 if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
2383 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2384 return;
2385 }
2386 if(encoder->private_->write_callback(encoder, b, 6, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
2387 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2388 return;
2389 }
2390 }
2391
2392 /*
2393 * Write seektable
2394 */
2395 if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
2396 unsigned i;
2397
2398 FLAC__format_seektable_sort(encoder->private_->seek_table);
2399
2400 FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
2401
2402 if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->seektable_offset + FLAC__STREAM_METADATA_HEADER_LENGTH, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
2403 if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
2404 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2405 return;
2406 }
2407
2408 for(i = 0; i < encoder->private_->seek_table->num_points; i++) {
2409 FLAC__uint64 xx;
2410 unsigned x;
2411 xx = encoder->private_->seek_table->points[i].sample_number;
2412 b[7] = (FLAC__byte)xx; xx >>= 8;
2413 b[6] = (FLAC__byte)xx; xx >>= 8;
2414 b[5] = (FLAC__byte)xx; xx >>= 8;
2415 b[4] = (FLAC__byte)xx; xx >>= 8;
2416 b[3] = (FLAC__byte)xx; xx >>= 8;
2417 b[2] = (FLAC__byte)xx; xx >>= 8;
2418 b[1] = (FLAC__byte)xx; xx >>= 8;
2419 b[0] = (FLAC__byte)xx; xx >>= 8;
2420 xx = encoder->private_->seek_table->points[i].stream_offset;
2421 b[15] = (FLAC__byte)xx; xx >>= 8;
2422 b[14] = (FLAC__byte)xx; xx >>= 8;
2423 b[13] = (FLAC__byte)xx; xx >>= 8;
2424 b[12] = (FLAC__byte)xx; xx >>= 8;
2425 b[11] = (FLAC__byte)xx; xx >>= 8;
2426 b[10] = (FLAC__byte)xx; xx >>= 8;
2427 b[9] = (FLAC__byte)xx; xx >>= 8;
2428 b[8] = (FLAC__byte)xx; xx >>= 8;
2429 x = encoder->private_->seek_table->points[i].frame_samples;
2430 b[17] = (FLAC__byte)x; x >>= 8;
2431 b[16] = (FLAC__byte)x; x >>= 8;
2432 if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
2433 encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
2434 return;
2435 }
2436 }
2437 }
2438}
2439
Josh Coalsonf1eff452002-07-31 07:05:33 +00002440FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson0a15c142001-06-13 17:59:57 +00002441{
Josh Coalsonfa697a92001-08-16 20:07:29 +00002442 FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002443
2444 /*
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00002445 * Accumulate raw signal to the MD5 signature
2446 */
Josh Coalson57ba6f42002-06-07 05:27:37 +00002447 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 +00002448 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +00002449 return false;
2450 }
2451
2452 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00002453 * Process the frame header and subframes into the frame bitbuffer
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002454 */
Josh Coalsonf1eff452002-07-31 07:05:33 +00002455 if(!process_subframes_(encoder, is_last_frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002456 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002457 return false;
2458 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002459
2460 /*
2461 * Zero-pad the frame to a byte_boundary
2462 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00002463 if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002464 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002465 return false;
2466 }
2467
2468 /*
Josh Coalson215af572001-03-27 01:15:58 +00002469 * CRC-16 the whole thing
2470 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00002471 FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
2472 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 +00002473
2474 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002475 * Write it
2476 */
Josh Coalsond86e03b2002-08-03 21:56:15 +00002477 if(!write_bitbuffer_(encoder, encoder->protected_->blocksize)) {
2478 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002479 return false;
2480 }
2481
2482 /*
2483 * Get ready for the next frame
2484 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002485 encoder->private_->current_sample_number = 0;
2486 encoder->private_->current_frame_number++;
Josh Coalson6b21f662006-09-13 01:42:27 +00002487 encoder->private_->streaminfo.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00002488
2489 return true;
2490}
2491
Josh Coalsonf1eff452002-07-31 07:05:33 +00002492FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002493{
2494 FLAC__FrameHeader frame_header;
Josh Coalsonfa697a92001-08-16 20:07:29 +00002495 unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00002496 FLAC__bool do_independent, do_mid_side, precompute_partition_sums;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002497
2498 /*
Josh Coalson60f77d72001-04-25 02:16:36 +00002499 * Calculate the min,max Rice partition orders
Josh Coalson94e02cd2001-01-25 10:41:06 +00002500 */
2501 if(is_last_frame) {
2502 max_partition_order = 0;
2503 }
2504 else {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002505 max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize);
2506 max_partition_order = min(max_partition_order, encoder->protected_->max_residual_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002507 }
Josh Coalson60f77d72001-04-25 02:16:36 +00002508 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002509
Josh Coalsonfa697a92001-08-16 20:07:29 +00002510 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 +00002511
Josh Coalson94e02cd2001-01-25 10:41:06 +00002512 /*
2513 * Setup the frame
2514 */
Josh Coalsonaec256b2002-03-12 16:19:54 +00002515 if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002516 encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002517 return false;
2518 }
Josh Coalsonfa697a92001-08-16 20:07:29 +00002519 frame_header.blocksize = encoder->protected_->blocksize;
2520 frame_header.sample_rate = encoder->protected_->sample_rate;
2521 frame_header.channels = encoder->protected_->channels;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002522 frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002523 frame_header.bits_per_sample = encoder->protected_->bits_per_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00002524 frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER;
Josh Coalsonfa697a92001-08-16 20:07:29 +00002525 frame_header.number.frame_number = encoder->private_->current_frame_number;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002526
2527 /*
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002528 * Figure out what channel assignments to try
2529 */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002530 if(encoder->protected_->do_mid_side_stereo) {
2531 if(encoder->protected_->loose_mid_side_stereo) {
2532 if(encoder->private_->loose_mid_side_stereo_frame_count == 0) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002533 do_independent = true;
2534 do_mid_side = true;
2535 }
2536 else {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002537 do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002538 do_mid_side = !do_independent;
2539 }
2540 }
2541 else {
2542 do_independent = true;
2543 do_mid_side = true;
2544 }
2545 }
2546 else {
2547 do_independent = true;
2548 do_mid_side = false;
2549 }
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002550
Josh Coalson1b689822001-05-31 20:11:02 +00002551 FLAC__ASSERT(do_independent || do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002552
2553 /*
Josh Coalson82b73242001-03-28 22:17:05 +00002554 * Check for wasted bits; set effective bps for each subframe
Josh Coalson859bc542001-03-27 22:22:27 +00002555 */
2556 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002557 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002558 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00002559 encoder->private_->subframe_workspace[channel][0].wasted_bits = encoder->private_->subframe_workspace[channel][1].wasted_bits = w;
2560 encoder->private_->subframe_bps[channel] = encoder->protected_->bits_per_sample - w;
Josh Coalson82b73242001-03-28 22:17:05 +00002561 }
Josh Coalson859bc542001-03-27 22:22:27 +00002562 }
2563 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002564 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson82b73242001-03-28 22:17:05 +00002565 for(channel = 0; channel < 2; channel++) {
Josh Coalsonb7023aa2002-08-17 15:23:43 +00002566 const unsigned w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize);
Josh Coalsonfa697a92001-08-16 20:07:29 +00002567 encoder->private_->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private_->subframe_workspace_mid_side[channel][1].wasted_bits = w;
2568 encoder->private_->subframe_bps_mid_side[channel] = encoder->protected_->bits_per_sample - w + (channel==0? 0:1);
Josh Coalson82b73242001-03-28 22:17:05 +00002569 }
Josh Coalson859bc542001-03-27 22:22:27 +00002570 }
2571
2572 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +00002573 * First do a normal encoding pass of each independent channel
2574 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002575 if(do_independent) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002576 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00002577 if(!
2578 process_subframe_(
2579 encoder,
2580 min_partition_order,
2581 max_partition_order,
2582 precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00002583 &frame_header,
2584 encoder->private_->subframe_bps[channel],
2585 encoder->private_->integer_signal[channel],
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002586#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson6fe72f72002-08-20 04:01:59 +00002587 encoder->private_->real_signal[channel],
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002588#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00002589 encoder->private_->subframe_workspace_ptr[channel],
2590 encoder->private_->partitioned_rice_contents_workspace_ptr[channel],
2591 encoder->private_->residual_workspace[channel],
2592 encoder->private_->best_subframe+channel,
2593 encoder->private_->best_subframe_bits+channel
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002594#ifdef WINDOW_DEBUG_OUTPUT
2595 ,channel
2596#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00002597 )
2598 )
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002599 return false;
2600 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002601 }
2602
2603 /*
2604 * Now do mid and side channels if requested
2605 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002606 if(do_mid_side) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002607 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002608
2609 for(channel = 0; channel < 2; channel++) {
Josh Coalson6fe72f72002-08-20 04:01:59 +00002610 if(!
2611 process_subframe_(
2612 encoder,
2613 min_partition_order,
2614 max_partition_order,
2615 precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00002616 &frame_header,
2617 encoder->private_->subframe_bps_mid_side[channel],
2618 encoder->private_->integer_signal_mid_side[channel],
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002619#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson6fe72f72002-08-20 04:01:59 +00002620 encoder->private_->real_signal_mid_side[channel],
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002621#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00002622 encoder->private_->subframe_workspace_ptr_mid_side[channel],
2623 encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel],
2624 encoder->private_->residual_workspace_mid_side[channel],
2625 encoder->private_->best_subframe_mid_side+channel,
2626 encoder->private_->best_subframe_bits_mid_side+channel
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002627#ifdef WINDOW_DEBUG_OUTPUT
2628 ,channel
2629#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00002630 )
2631 )
Josh Coalson94e02cd2001-01-25 10:41:06 +00002632 return false;
2633 }
2634 }
2635
2636 /*
2637 * Compose the frame bitbuffer
2638 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002639 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +00002640 unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
2641 FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002642 FLAC__ChannelAssignment channel_assignment;
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002643#ifdef WINDOW_DEBUG_OUTPUT
2644 unsigned left_bits = 0, right_bits = 0;
2645#endif
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002646
Josh Coalsonfa697a92001-08-16 20:07:29 +00002647 FLAC__ASSERT(encoder->protected_->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002648
Josh Coalsonfa697a92001-08-16 20:07:29 +00002649 if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) {
2650 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 +00002651 }
2652 else {
2653 unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
2654 unsigned min_bits;
2655 FLAC__ChannelAssignment ca;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002656
Josh Coalson1b689822001-05-31 20:11:02 +00002657 FLAC__ASSERT(do_independent && do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002658
2659 /* We have to figure out which channel assignent results in the smallest frame */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002660 bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1];
2661 bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1];
2662 bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1];
2663 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 +00002664
Josh Coalson7424d2f2002-11-06 07:10:38 +00002665 for(channel_assignment = (FLAC__ChannelAssignment)0, min_bits = bits[0], ca = (FLAC__ChannelAssignment)1; (int)ca <= 3; ca = (FLAC__ChannelAssignment)((int)ca + 1)) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002666 if(bits[ca] < min_bits) {
2667 min_bits = bits[ca];
2668 channel_assignment = ca;
2669 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002670 }
2671 }
2672
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002673 frame_header.channel_assignment = channel_assignment;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002674
Josh Coalsond0edb972006-10-07 06:50:08 +00002675 if(!FLAC__frame_add_header(&frame_header, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002676 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002677 return false;
2678 }
2679
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002680 switch(channel_assignment) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002681 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002682 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
2683 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002684#ifdef WINDOW_DEBUG_OUTPUT
2685 left_bits = encoder->private_->best_subframe_bits [0];
2686 right_bits = encoder->private_->best_subframe_bits [1];
2687#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002688 break;
2689 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002690 left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]];
2691 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002692#ifdef WINDOW_DEBUG_OUTPUT
2693 left_bits = encoder->private_->best_subframe_bits [0];
2694 right_bits = encoder->private_->best_subframe_bits_mid_side [1];
2695#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002696 break;
2697 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002698 left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
2699 right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]];
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002700#ifdef WINDOW_DEBUG_OUTPUT
2701 left_bits = encoder->private_->best_subframe_bits_mid_side [1];
2702 right_bits = encoder->private_->best_subframe_bits [1];
2703#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002704 break;
2705 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002706 left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]];
2707 right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002708#ifdef WINDOW_DEBUG_OUTPUT
2709 left_bits = encoder->private_->best_subframe_bits_mid_side [0];
2710 right_bits = encoder->private_->best_subframe_bits_mid_side [1];
2711#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002712 break;
2713 default:
Josh Coalson1b689822001-05-31 20:11:02 +00002714 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002715 }
Josh Coalson82b73242001-03-28 22:17:05 +00002716
2717 switch(channel_assignment) {
2718 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002719 left_bps = encoder->private_->subframe_bps [0];
2720 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00002721 break;
2722 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002723 left_bps = encoder->private_->subframe_bps [0];
2724 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00002725 break;
2726 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002727 left_bps = encoder->private_->subframe_bps_mid_side[1];
2728 right_bps = encoder->private_->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00002729 break;
2730 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalsonfa697a92001-08-16 20:07:29 +00002731 left_bps = encoder->private_->subframe_bps_mid_side[0];
2732 right_bps = encoder->private_->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00002733 break;
2734 default:
Josh Coalson1b689822001-05-31 20:11:02 +00002735 FLAC__ASSERT(0);
Josh Coalson82b73242001-03-28 22:17:05 +00002736 }
2737
2738 /* note that encoder_add_subframe_ sets the state for us in case of an error */
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002739#ifdef WINDOW_DEBUG_OUTPUT
2740 if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame, left_bits))
2741 return false;
2742 if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame, right_bits))
2743 return false;
2744#else
Josh Coalsonf1eff452002-07-31 07:05:33 +00002745 if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00002746 return false;
Josh Coalsonf1eff452002-07-31 07:05:33 +00002747 if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00002748 return false;
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002749#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00002750 }
2751 else {
Josh Coalsond0edb972006-10-07 06:50:08 +00002752 if(!FLAC__frame_add_header(&frame_header, encoder->private_->frame)) {
Josh Coalsonfa697a92001-08-16 20:07:29 +00002753 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002754 return false;
2755 }
2756
Josh Coalsonfa697a92001-08-16 20:07:29 +00002757 for(channel = 0; channel < encoder->protected_->channels; channel++) {
Josh Coalson0abc7352006-05-03 00:13:25 +00002758#ifdef WINDOW_DEBUG_OUTPUT
2759 if(!add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame, encoder->private_->best_subframe_bits[channel]))
2760#else
2761 if(!add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame))
2762#endif
2763 {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002764 /* the above function sets the state for us in case of an error */
2765 return false;
2766 }
2767 }
2768 }
2769
Josh Coalsonfa697a92001-08-16 20:07:29 +00002770 if(encoder->protected_->loose_mid_side_stereo) {
2771 encoder->private_->loose_mid_side_stereo_frame_count++;
2772 if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames)
2773 encoder->private_->loose_mid_side_stereo_frame_count = 0;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002774 }
2775
Josh Coalsonfa697a92001-08-16 20:07:29 +00002776 encoder->private_->last_channel_assignment = frame_header.channel_assignment;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00002777
Josh Coalson94e02cd2001-01-25 10:41:06 +00002778 return true;
2779}
2780
Josh Coalson6fe72f72002-08-20 04:01:59 +00002781FLAC__bool process_subframe_(
2782 FLAC__StreamEncoder *encoder,
2783 unsigned min_partition_order,
2784 unsigned max_partition_order,
2785 FLAC__bool precompute_partition_sums,
Josh Coalson6fe72f72002-08-20 04:01:59 +00002786 const FLAC__FrameHeader *frame_header,
2787 unsigned subframe_bps,
2788 const FLAC__int32 integer_signal[],
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002789#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson6fe72f72002-08-20 04:01:59 +00002790 const FLAC__real real_signal[],
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002791#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00002792 FLAC__Subframe *subframe[2],
2793 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
2794 FLAC__int32 *residual[2],
2795 unsigned *best_subframe,
2796 unsigned *best_bits
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002797#ifdef WINDOW_DEBUG_OUTPUT
2798 ,unsigned subframe_number
2799#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00002800)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002801{
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002802#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson09758432004-10-20 00:21:50 +00002803 FLAC__float fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002804#else
2805 FLAC__fixedpoint fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
2806#endif
2807#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson09758432004-10-20 00:21:50 +00002808 FLAC__double lpc_residual_bits_per_sample;
Josh Coalsonfa697a92001-08-16 20:07:29 +00002809 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 Coalson09758432004-10-20 00:21:50 +00002810 FLAC__double lpc_error[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00002811 unsigned min_lpc_order, max_lpc_order, lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002812 unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002813#endif
2814 unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002815 unsigned rice_parameter;
2816 unsigned _candidate_bits, _best_bits;
2817 unsigned _best_subframe;
2818
2819 /* verbatim subframe is the baseline against which we measure other compressed subframes */
2820 _best_subframe = 0;
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002821 if(encoder->private_->disable_verbatim_subframes && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER)
2822 _best_bits = UINT_MAX;
2823 else
2824 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00002825
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002826 if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
2827 unsigned signal_is_constant = false;
Josh Coalsonfa697a92001-08-16 20:07:29 +00002828 guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample);
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002829 /* check for constant subframe */
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002830 if(
2831 !encoder->private_->disable_constant_subframes &&
2832#ifndef FLAC__INTEGER_ONLY_LIBRARY
2833 fixed_residual_bits_per_sample[1] == 0.0
2834#else
2835 fixed_residual_bits_per_sample[1] == FLAC__FP_ZERO
2836#endif
2837 ) {
2838 /* the above means it's possible all samples are the same value; now double-check it: */
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002839 unsigned i;
2840 signal_is_constant = true;
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002841 for(i = 1; i < frame_header->blocksize; i++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00002842 if(integer_signal[0] != integer_signal[i]) {
2843 signal_is_constant = false;
2844 break;
2845 }
2846 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002847 }
2848 if(signal_is_constant) {
2849 _candidate_bits = evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
2850 if(_candidate_bits < _best_bits) {
2851 _best_subframe = !_best_subframe;
2852 _best_bits = _candidate_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002853 }
2854 }
2855 else {
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002856 if(!encoder->private_->disable_fixed_subframes || (encoder->protected_->max_lpc_order == 0 && _best_bits == UINT_MAX)) {
2857 /* encode fixed */
2858 if(encoder->protected_->do_exhaustive_model_search) {
2859 min_fixed_order = 0;
2860 max_fixed_order = FLAC__MAX_FIXED_ORDER;
Josh Coalson8395d022001-07-12 21:25:22 +00002861 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002862 else {
2863 min_fixed_order = max_fixed_order = guess_fixed_order;
2864 }
2865 for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002866#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson09758432004-10-20 00:21:50 +00002867 if(fixed_residual_bits_per_sample[fixed_order] >= (FLAC__float)subframe_bps)
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002868 continue; /* don't even try */
2869 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 Coalson5f2b46d2004-11-09 01:34:01 +00002870#else
2871 if(FLAC__fixedpoint_trunc(fixed_residual_bits_per_sample[fixed_order]) >= (int)subframe_bps)
2872 continue; /* don't even try */
2873 rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > FLAC__FP_ZERO)? (unsigned)FLAC__fixedpoint_trunc(fixed_residual_bits_per_sample[fixed_order]+FLAC__FP_ONE_HALF) : 0; /* 0.5 is for rounding */
2874#endif
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002875 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00002876 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
2877#ifdef DEBUG_VERBOSE
2878 fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
2879#endif
2880 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2881 }
2882 _candidate_bits =
2883 evaluate_fixed_subframe_(
2884 encoder,
2885 integer_signal,
2886 residual[!_best_subframe],
2887 encoder->private_->abs_residual,
2888 encoder->private_->abs_residual_partition_sums,
2889 encoder->private_->raw_bits_per_partition,
2890 frame_header->blocksize,
2891 subframe_bps,
2892 fixed_order,
2893 rice_parameter,
2894 min_partition_order,
2895 max_partition_order,
2896 precompute_partition_sums,
2897 encoder->protected_->do_escape_coding,
2898 encoder->protected_->rice_parameter_search_dist,
2899 subframe[!_best_subframe],
2900 partitioned_rice_contents[!_best_subframe]
2901 );
2902 if(_candidate_bits < _best_bits) {
2903 _best_subframe = !_best_subframe;
2904 _best_bits = _candidate_bits;
2905 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00002906 }
2907 }
2908
Josh Coalson5f2b46d2004-11-09 01:34:01 +00002909#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson94e02cd2001-01-25 10:41:06 +00002910 /* encode lpc */
Josh Coalsonfa697a92001-08-16 20:07:29 +00002911 if(encoder->protected_->max_lpc_order > 0) {
2912 if(encoder->protected_->max_lpc_order >= frame_header->blocksize)
Josh Coalson94e02cd2001-01-25 10:41:06 +00002913 max_lpc_order = frame_header->blocksize-1;
2914 else
Josh Coalsonfa697a92001-08-16 20:07:29 +00002915 max_lpc_order = encoder->protected_->max_lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00002916 if(max_lpc_order > 0) {
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002917 unsigned a;
2918 for (a = 0; a < encoder->protected_->num_apodizations; a++) {
Josh Coalson0abc7352006-05-03 00:13:25 +00002919 FLAC__lpc_window_data(real_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize);
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002920 encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize, max_lpc_order+1, autoc);
2921 /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
2922 if(autoc[0] != 0.0) {
2923 FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
2924 if(encoder->protected_->do_exhaustive_model_search) {
2925 min_lpc_order = 1;
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002926 }
2927 else {
Josh Coalsondf598452006-04-28 00:13:34 +00002928 const unsigned guess_lpc_order =
2929 FLAC__lpc_compute_best_order(
2930 lpc_error,
2931 max_lpc_order,
2932 frame_header->blocksize,
2933 subframe_bps + (
2934 encoder->protected_->do_qlp_coeff_prec_search?
2935 FLAC__MIN_QLP_COEFF_PRECISION : /* have to guess; use the min possible size to avoid accidentally favoring lower orders */
2936 encoder->protected_->qlp_coeff_precision
2937 )
2938 );
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002939 min_lpc_order = max_lpc_order = guess_lpc_order;
Josh Coalsonc9c0d132002-10-04 05:29:05 +00002940 }
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002941 for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
2942 lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order);
2943 if(lpc_residual_bits_per_sample >= (FLAC__double)subframe_bps)
2944 continue; /* don't even try */
2945 rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */
2946 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
2947 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalsondf598452006-04-28 00:13:34 +00002948#ifdef DEBUG_VERBOSE
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002949 fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
Josh Coalsondf598452006-04-28 00:13:34 +00002950#endif
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002951 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
2952 }
2953 if(encoder->protected_->do_qlp_coeff_prec_search) {
2954 min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
Josh Coalsondf598452006-04-28 00:13:34 +00002955 /* try to ensure a 32-bit datapath throughout for 16bps(+1bps for side channel) or less */
2956 if(subframe_bps <= 17) {
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002957 max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalsondf598452006-04-28 00:13:34 +00002958 max_qlp_coeff_precision = max(max_qlp_coeff_precision, min_qlp_coeff_precision);
2959 }
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00002960 else
2961 max_qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
2962 }
2963 else {
2964 min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
2965 }
2966 for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
2967 _candidate_bits =
2968 evaluate_lpc_subframe_(
2969 encoder,
2970 integer_signal,
2971 residual[!_best_subframe],
2972 encoder->private_->abs_residual,
2973 encoder->private_->abs_residual_partition_sums,
2974 encoder->private_->raw_bits_per_partition,
2975 encoder->private_->lp_coeff[lpc_order-1],
2976 frame_header->blocksize,
2977 subframe_bps,
2978 lpc_order,
2979 qlp_coeff_precision,
2980 rice_parameter,
2981 min_partition_order,
2982 max_partition_order,
2983 precompute_partition_sums,
2984 encoder->protected_->do_escape_coding,
2985 encoder->protected_->rice_parameter_search_dist,
2986 subframe[!_best_subframe],
2987 partitioned_rice_contents[!_best_subframe]
2988#ifdef WINDOW_DEBUG_OUTPUT
2989 ,frame_header->number.frame_number
2990 ,subframe_number
2991 ,encoder->protected_->apodizations[a]
2992#endif
2993 );
2994 if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
2995 if(_candidate_bits < _best_bits) {
2996 _best_subframe = !_best_subframe;
2997 _best_bits = _candidate_bits;
2998 }
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00002999 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00003000 }
3001 }
3002 }
3003 }
3004 }
3005 }
Josh Coalson5f2b46d2004-11-09 01:34:01 +00003006#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
Josh Coalson94e02cd2001-01-25 10:41:06 +00003007 }
3008 }
3009
Josh Coalson72695802002-10-11 06:25:16 +00003010 /* under rare circumstances this can happen when all but lpc subframe types are disabled: */
3011 if(_best_bits == UINT_MAX) {
3012 FLAC__ASSERT(_best_subframe == 0);
3013 _best_bits = evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
3014 }
Josh Coalsone6b3bbe2002-10-08 06:03:25 +00003015
Josh Coalson94e02cd2001-01-25 10:41:06 +00003016 *best_subframe = _best_subframe;
3017 *best_bits = _best_bits;
3018
3019 return true;
3020}
3021
Josh Coalson6fe72f72002-08-20 04:01:59 +00003022FLAC__bool add_subframe_(
3023 FLAC__StreamEncoder *encoder,
3024 const FLAC__FrameHeader *frame_header,
3025 unsigned subframe_bps,
3026 const FLAC__Subframe *subframe,
3027 FLAC__BitBuffer *frame
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00003028#ifdef WINDOW_DEBUG_OUTPUT
3029,unsigned subframe_bits
3030#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00003031)
Josh Coalson94e02cd2001-01-25 10:41:06 +00003032{
3033 switch(subframe->type) {
3034 case FLAC__SUBFRAME_TYPE_CONSTANT:
Josh Coalson82b73242001-03-28 22:17:05 +00003035 if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson6b21f662006-09-13 01:42:27 +00003036 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003037 return false;
3038 }
3039 break;
3040 case FLAC__SUBFRAME_TYPE_FIXED:
Josh Coalson82b73242001-03-28 22:17:05 +00003041 if(!FLAC__subframe_add_fixed(&(subframe->data.fixed), frame_header->blocksize - subframe->data.fixed.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson6b21f662006-09-13 01:42:27 +00003042 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003043 return false;
3044 }
3045 break;
3046 case FLAC__SUBFRAME_TYPE_LPC:
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00003047#ifdef WINDOW_DEBUG_OUTPUT
3048 fprintf(stderr, "WIN:\tframe=%u\tsubframe=?\torder=%u\twindow=%s\tbits=%u\n", frame_header->number.frame_number, subframe->data.lpc.order, subframe->data.lpc.window_type, subframe_bits);
3049#endif
Josh Coalson82b73242001-03-28 22:17:05 +00003050 if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), frame_header->blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson6b21f662006-09-13 01:42:27 +00003051 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003052 return false;
3053 }
3054 break;
3055 case FLAC__SUBFRAME_TYPE_VERBATIM:
Josh Coalson82b73242001-03-28 22:17:05 +00003056 if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson6b21f662006-09-13 01:42:27 +00003057 encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003058 return false;
3059 }
3060 break;
3061 default:
Josh Coalson1b689822001-05-31 20:11:02 +00003062 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00003063 }
3064
3065 return true;
3066}
3067
Josh Coalson6fe72f72002-08-20 04:01:59 +00003068unsigned evaluate_constant_subframe_(
3069 const FLAC__int32 signal,
3070 unsigned subframe_bps,
3071 FLAC__Subframe *subframe
3072)
Josh Coalson94e02cd2001-01-25 10:41:06 +00003073{
3074 subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
3075 subframe->data.constant.value = signal;
3076
Josh Coalson82b73242001-03-28 22:17:05 +00003077 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 +00003078}
3079
Josh Coalson6fe72f72002-08-20 04:01:59 +00003080unsigned evaluate_fixed_subframe_(
3081 FLAC__StreamEncoder *encoder,
3082 const FLAC__int32 signal[],
3083 FLAC__int32 residual[],
3084 FLAC__uint32 abs_residual[],
3085 FLAC__uint64 abs_residual_partition_sums[],
3086 unsigned raw_bits_per_partition[],
3087 unsigned blocksize,
3088 unsigned subframe_bps,
3089 unsigned order,
3090 unsigned rice_parameter,
3091 unsigned min_partition_order,
3092 unsigned max_partition_order,
3093 FLAC__bool precompute_partition_sums,
3094 FLAC__bool do_escape_coding,
3095 unsigned rice_parameter_search_dist,
3096 FLAC__Subframe *subframe,
3097 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
3098)
Josh Coalson94e02cd2001-01-25 10:41:06 +00003099{
3100 unsigned i, residual_bits;
3101 const unsigned residual_samples = blocksize - order;
3102
3103 FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
3104
3105 subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
3106
3107 subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00003108 subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003109 subframe->data.fixed.residual = residual;
3110
Josh Coalson6fe72f72002-08-20 04:01:59 +00003111 residual_bits =
3112 find_best_partition_order_(
3113 encoder->private_,
3114 residual,
3115 abs_residual,
3116 abs_residual_partition_sums,
3117 raw_bits_per_partition,
3118 residual_samples,
3119 order,
3120 rice_parameter,
3121 min_partition_order,
3122 max_partition_order,
3123 precompute_partition_sums,
3124 do_escape_coding,
3125 rice_parameter_search_dist,
3126 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
3127 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00003128
3129 subframe->data.fixed.order = order;
3130 for(i = 0; i < order; i++)
3131 subframe->data.fixed.warmup[i] = signal[i];
3132
Josh Coalson82b73242001-03-28 22:17:05 +00003133 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 +00003134}
3135
Josh Coalson5f2b46d2004-11-09 01:34:01 +00003136#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson6fe72f72002-08-20 04:01:59 +00003137unsigned evaluate_lpc_subframe_(
3138 FLAC__StreamEncoder *encoder,
3139 const FLAC__int32 signal[],
3140 FLAC__int32 residual[],
3141 FLAC__uint32 abs_residual[],
3142 FLAC__uint64 abs_residual_partition_sums[],
3143 unsigned raw_bits_per_partition[],
3144 const FLAC__real lp_coeff[],
3145 unsigned blocksize,
3146 unsigned subframe_bps,
3147 unsigned order,
3148 unsigned qlp_coeff_precision,
3149 unsigned rice_parameter,
3150 unsigned min_partition_order,
3151 unsigned max_partition_order,
3152 FLAC__bool precompute_partition_sums,
3153 FLAC__bool do_escape_coding,
3154 unsigned rice_parameter_search_dist,
3155 FLAC__Subframe *subframe,
3156 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00003157#ifdef WINDOW_DEBUG_OUTPUT
3158 ,unsigned frame_number
3159 ,unsigned subframe_number
3160 ,FLAC__ApodizationSpecification aspec
3161#endif
Josh Coalson6fe72f72002-08-20 04:01:59 +00003162)
Josh Coalson94e02cd2001-01-25 10:41:06 +00003163{
Josh Coalson77e3f312001-06-23 03:03:24 +00003164 FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00003165 unsigned i, residual_bits;
3166 int quantization, ret;
3167 const unsigned residual_samples = blocksize - order;
3168
Josh Coalson20ac2c12002-08-30 05:47:14 +00003169 /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */
3170 if(subframe_bps <= 16) {
3171 FLAC__ASSERT(order > 0);
3172 FLAC__ASSERT(order <= FLAC__MAX_LPC_ORDER);
3173 qlp_coeff_precision = min(qlp_coeff_precision, 32 - subframe_bps - FLAC__bitmath_ilog2(order));
3174 }
3175
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00003176#ifdef WINDOW_DEBUG_OUTPUT
3177 if (aspec.type == FLAC__APODIZATION_GAUSS)
3178 snprintf(subframe->data.lpc.window_type, sizeof subframe->data.lpc.window_type, "%s(%0.5f)", winstr[aspec.type], aspec.parameters.gauss.stddev);
3179 else if (aspec.type == FLAC__APODIZATION_TUKEY)
3180 snprintf(subframe->data.lpc.window_type, sizeof subframe->data.lpc.window_type, "%s(%0.5f)", winstr[aspec.type], aspec.parameters.tukey.p);
3181 else
3182 strncpy(subframe->data.lpc.window_type, winstr[aspec.type], sizeof subframe->data.lpc.window_type);
3183#endif
3184
Josh Coalsonc9c0d132002-10-04 05:29:05 +00003185 ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, qlp_coeff, &quantization);
Josh Coalson94e02cd2001-01-25 10:41:06 +00003186 if(ret != 0)
3187 return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
3188
Josh Coalsonfb9d18f2002-10-21 07:04:07 +00003189 if(subframe_bps + qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32)
3190 if(subframe_bps <= 16 && qlp_coeff_precision <= 16)
3191 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
3192 else
3193 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalsonc9c0d132002-10-04 05:29:05 +00003194 else
3195 encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalson94e02cd2001-01-25 10:41:06 +00003196
3197 subframe->type = FLAC__SUBFRAME_TYPE_LPC;
3198
3199 subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalsona37ba462002-08-19 21:36:39 +00003200 subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003201 subframe->data.lpc.residual = residual;
3202
Josh Coalson6fe72f72002-08-20 04:01:59 +00003203 residual_bits =
3204 find_best_partition_order_(
3205 encoder->private_,
3206 residual,
3207 abs_residual,
3208 abs_residual_partition_sums,
3209 raw_bits_per_partition,
3210 residual_samples,
3211 order,
3212 rice_parameter,
3213 min_partition_order,
3214 max_partition_order,
3215 precompute_partition_sums,
3216 do_escape_coding,
3217 rice_parameter_search_dist,
3218 &subframe->data.fixed.entropy_coding_method.data.partitioned_rice
3219 );
Josh Coalson94e02cd2001-01-25 10:41:06 +00003220
3221 subframe->data.lpc.order = order;
3222 subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
3223 subframe->data.lpc.quantization_level = quantization;
Josh Coalson77e3f312001-06-23 03:03:24 +00003224 memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER);
Josh Coalson94e02cd2001-01-25 10:41:06 +00003225 for(i = 0; i < order; i++)
3226 subframe->data.lpc.warmup[i] = signal[i];
3227
Josh Coalsonbf0f52c2006-04-25 06:38:43 +00003228#ifdef WINDOW_DEBUG_OUTPUT
3229 fprintf(stderr, "SWIN:\tframe=%u\tsubframe=%u\torder=%u\twindow=%s\tbits=%u\n", frame_number, subframe_number, order, subframe->data.lpc.window_type, 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);
3230#endif
Josh Coalson82b73242001-03-28 22:17:05 +00003231 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 +00003232}
Josh Coalson5f2b46d2004-11-09 01:34:01 +00003233#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00003234
Josh Coalson6fe72f72002-08-20 04:01:59 +00003235unsigned evaluate_verbatim_subframe_(
3236 const FLAC__int32 signal[],
3237 unsigned blocksize,
3238 unsigned subframe_bps,
3239 FLAC__Subframe *subframe
3240)
Josh Coalson94e02cd2001-01-25 10:41:06 +00003241{
3242 subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
3243
3244 subframe->data.verbatim.data = signal;
3245
Josh Coalson82b73242001-03-28 22:17:05 +00003246 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 +00003247}
3248
Josh Coalson6fe72f72002-08-20 04:01:59 +00003249unsigned find_best_partition_order_(
3250 FLAC__StreamEncoderPrivate *private_,
3251 const FLAC__int32 residual[],
3252 FLAC__uint32 abs_residual[],
3253 FLAC__uint64 abs_residual_partition_sums[],
3254 unsigned raw_bits_per_partition[],
3255 unsigned residual_samples,
3256 unsigned predictor_order,
3257 unsigned rice_parameter,
3258 unsigned min_partition_order,
3259 unsigned max_partition_order,
3260 FLAC__bool precompute_partition_sums,
3261 FLAC__bool do_escape_coding,
3262 unsigned rice_parameter_search_dist,
3263 FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
3264)
Josh Coalson94e02cd2001-01-25 10:41:06 +00003265{
Josh Coalson77e3f312001-06-23 03:03:24 +00003266 FLAC__int32 r;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003267 unsigned residual_bits, best_residual_bits = 0;
Josh Coalsonafcd8772001-04-18 22:59:25 +00003268 unsigned residual_sample;
Josh Coalson8084b052001-11-01 00:27:29 +00003269 unsigned best_parameters_index = 0;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003270 const unsigned blocksize = residual_samples + predictor_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003271
Josh Coalson2051dd42001-04-12 22:22:34 +00003272 /* compute abs(residual) for use later */
3273 for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
3274 r = residual[residual_sample];
Josh Coalson77e3f312001-06-23 03:03:24 +00003275 abs_residual[residual_sample] = (FLAC__uint32)(r<0? -r : r);
Josh Coalson2051dd42001-04-12 22:22:34 +00003276 }
3277
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003278 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 +00003279 min_partition_order = min(min_partition_order, max_partition_order);
3280
Josh Coalson8395d022001-07-12 21:25:22 +00003281 if(precompute_partition_sums) {
3282 int partition_order;
3283 unsigned sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003284
Josh Coalsonf1eff452002-07-31 07:05:33 +00003285 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 +00003286
3287 if(do_escape_coding)
Josh Coalsonf1eff452002-07-31 07:05:33 +00003288 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 +00003289
3290 for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
3291#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00003292 if(!
3293 set_partitioned_rice_with_precompute_(
3294 residual,
3295 abs_residual_partition_sums+sum,
3296 raw_bits_per_partition+sum,
3297 residual_samples,
3298 predictor_order,
3299 rice_parameter,
3300 rice_parameter_search_dist,
3301 (unsigned)partition_order,
3302 do_escape_coding,
3303 &private_->partitioned_rice_contents_extra[!best_parameters_index],
3304 &residual_bits
3305 )
3306 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00003307#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00003308 if(!
3309 set_partitioned_rice_with_precompute_(
3310 abs_residual,
3311 abs_residual_partition_sums+sum,
3312 raw_bits_per_partition+sum,
3313 residual_samples,
3314 predictor_order,
3315 rice_parameter,
3316 rice_parameter_search_dist,
3317 (unsigned)partition_order,
3318 do_escape_coding,
3319 &private_->partitioned_rice_contents_extra[!best_parameters_index],
3320 &residual_bits
3321 )
3322 )
Josh Coalson8395d022001-07-12 21:25:22 +00003323#endif
3324 {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003325 FLAC__ASSERT(best_residual_bits != 0);
3326 break;
Josh Coalson8395d022001-07-12 21:25:22 +00003327 }
3328 sum += 1u << partition_order;
3329 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
3330 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00003331 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003332 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00003333 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00003334 }
3335 }
Josh Coalson8395d022001-07-12 21:25:22 +00003336 else {
3337 unsigned partition_order;
3338 for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
3339#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00003340 if(!
3341 set_partitioned_rice_(
3342 abs_residual,
3343 residual,
3344 residual_samples,
3345 predictor_order,
3346 rice_parameter,
3347 rice_parameter_search_dist,
3348 partition_order,
3349 &private_->partitioned_rice_contents_extra[!best_parameters_index],
3350 &residual_bits
3351 )
3352 )
Josh Coalson8395d022001-07-12 21:25:22 +00003353#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00003354 if(!
3355 set_partitioned_rice_(
3356 abs_residual,
3357 residual_samples,
3358 predictor_order,
3359 rice_parameter,
3360 rice_parameter_search_dist,
3361 partition_order,
3362 &private_->partitioned_rice_contents_extra[!best_parameters_index],
3363 &residual_bits
3364 )
3365 )
Josh Coalsonafcd8772001-04-18 22:59:25 +00003366#endif
Josh Coalson8395d022001-07-12 21:25:22 +00003367 {
3368 FLAC__ASSERT(best_residual_bits != 0);
3369 break;
3370 }
3371 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
3372 best_residual_bits = residual_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00003373 best_parameters_index = !best_parameters_index;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003374 best_partitioned_rice->order = partition_order;
Josh Coalson8395d022001-07-12 21:25:22 +00003375 }
3376 }
3377 }
3378
Josh Coalsona37ba462002-08-19 21:36:39 +00003379 /*
Josh Coalson20ac2c12002-08-30 05:47:14 +00003380 * We are allowed to de-const the pointer based on our special knowledge;
Josh Coalsona37ba462002-08-19 21:36:39 +00003381 * it is const to the outside world.
3382 */
3383 {
3384 FLAC__EntropyCodingMethod_PartitionedRiceContents* best_partitioned_rice_contents = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_partitioned_rice->contents;
3385 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(best_partitioned_rice_contents, max(6, best_partitioned_rice->order));
3386 memcpy(best_partitioned_rice_contents->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
3387 memcpy(best_partitioned_rice_contents->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partitioned_rice->order)));
3388 }
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003389
3390 return best_residual_bits;
3391}
3392
Josh Coalson6fe72f72002-08-20 04:01:59 +00003393void precompute_partition_info_sums_(
3394 const FLAC__uint32 abs_residual[],
3395 FLAC__uint64 abs_residual_partition_sums[],
3396 unsigned residual_samples,
3397 unsigned predictor_order,
3398 unsigned min_partition_order,
3399 unsigned max_partition_order
3400)
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003401{
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003402 int partition_order;
Josh Coalsonaef013c2001-04-24 01:25:42 +00003403 unsigned from_partition, to_partition = 0;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003404 const unsigned blocksize = residual_samples + predictor_order;
3405
Josh Coalsonaef013c2001-04-24 01:25:42 +00003406 /* first do max_partition_order */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003407 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003408 FLAC__uint64 abs_residual_partition_sum;
Josh Coalson77e3f312001-06-23 03:03:24 +00003409 FLAC__uint32 abs_r;
Josh Coalsonaef013c2001-04-24 01:25:42 +00003410 unsigned partition, partition_sample, partition_samples, residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003411 const unsigned partitions = 1u << partition_order;
3412 const unsigned default_partition_samples = blocksize >> partition_order;
3413
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003414 FLAC__ASSERT(default_partition_samples > predictor_order);
3415
3416 for(partition = residual_sample = 0; partition < partitions; partition++) {
3417 partition_samples = default_partition_samples;
3418 if(partition == 0)
3419 partition_samples -= predictor_order;
3420 abs_residual_partition_sum = 0;
3421 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
3422 abs_r = abs_residual[residual_sample];
3423 abs_residual_partition_sum += abs_r;
3424 residual_sample++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003425 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003426 abs_residual_partition_sums[partition] = abs_residual_partition_sum;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003427 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003428 to_partition = partitions;
3429 break;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003430 }
Josh Coalsonf76a3612001-04-18 02:28:11 +00003431
Josh Coalson8395d022001-07-12 21:25:22 +00003432 /* now merge partitions for lower orders */
Josh Coalson6bd17572001-05-25 19:02:01 +00003433 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003434 FLAC__uint64 s;
Josh Coalsonaef013c2001-04-24 01:25:42 +00003435 unsigned i;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003436 const unsigned partitions = 1u << partition_order;
3437 for(i = 0; i < partitions; i++) {
Josh Coalsonaef013c2001-04-24 01:25:42 +00003438 s = abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00003439 from_partition++;
Josh Coalsonaef013c2001-04-24 01:25:42 +00003440 abs_residual_partition_sums[to_partition] = s + abs_residual_partition_sums[from_partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00003441 from_partition++;
3442 to_partition++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003443 }
3444 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00003445}
Josh Coalson8395d022001-07-12 21:25:22 +00003446
Josh Coalson6fe72f72002-08-20 04:01:59 +00003447void precompute_partition_info_escapes_(
3448 const FLAC__int32 residual[],
3449 unsigned raw_bits_per_partition[],
3450 unsigned residual_samples,
3451 unsigned predictor_order,
3452 unsigned min_partition_order,
3453 unsigned max_partition_order
3454)
Josh Coalson8395d022001-07-12 21:25:22 +00003455{
3456 int partition_order;
3457 unsigned from_partition, to_partition = 0;
3458 const unsigned blocksize = residual_samples + predictor_order;
3459
3460 /* first do max_partition_order */
3461 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
3462 FLAC__int32 r, residual_partition_min, residual_partition_max;
3463 unsigned silog2_min, silog2_max;
3464 unsigned partition, partition_sample, partition_samples, residual_sample;
3465 const unsigned partitions = 1u << partition_order;
3466 const unsigned default_partition_samples = blocksize >> partition_order;
3467
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003468 FLAC__ASSERT(default_partition_samples > predictor_order);
3469
3470 for(partition = residual_sample = 0; partition < partitions; partition++) {
3471 partition_samples = default_partition_samples;
3472 if(partition == 0)
3473 partition_samples -= predictor_order;
3474 residual_partition_min = residual_partition_max = 0;
3475 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
3476 r = residual[residual_sample];
3477 if(r < residual_partition_min)
3478 residual_partition_min = r;
3479 else if(r > residual_partition_max)
3480 residual_partition_max = r;
3481 residual_sample++;
Josh Coalson8395d022001-07-12 21:25:22 +00003482 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003483 silog2_min = FLAC__bitmath_silog2(residual_partition_min);
3484 silog2_max = FLAC__bitmath_silog2(residual_partition_max);
3485 raw_bits_per_partition[partition] = max(silog2_min, silog2_max);
Josh Coalson8395d022001-07-12 21:25:22 +00003486 }
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003487 to_partition = partitions;
Josh Coalson03f54be2006-05-18 00:04:14 +00003488 break; /*@@@@@@ yuck, should remove the 'for' loop instead */
Josh Coalson8395d022001-07-12 21:25:22 +00003489 }
3490
3491 /* now merge partitions for lower orders */
3492 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
3493 unsigned m;
3494 unsigned i;
3495 const unsigned partitions = 1u << partition_order;
3496 for(i = 0; i < partitions; i++) {
3497 m = raw_bits_per_partition[from_partition];
3498 from_partition++;
3499 raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]);
3500 from_partition++;
3501 to_partition++;
3502 }
3503 }
3504}
Josh Coalson94e02cd2001-01-25 10:41:06 +00003505
Josh Coalson352e0f62001-03-20 22:55:50 +00003506#ifdef VARIABLE_RICE_BITS
3507#undef VARIABLE_RICE_BITS
3508#endif
Josh Coalson8395d022001-07-12 21:25:22 +00003509#ifndef DONT_ESTIMATE_RICE_BITS
Josh Coalson352e0f62001-03-20 22:55:50 +00003510#define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
Josh Coalson8395d022001-07-12 21:25:22 +00003511#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00003512
Josh Coalson8395d022001-07-12 21:25:22 +00003513#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00003514FLAC__bool set_partitioned_rice_(
3515 const FLAC__uint32 abs_residual[],
3516 const FLAC__int32 residual[],
3517 const unsigned residual_samples,
3518 const unsigned predictor_order,
3519 const unsigned suggested_rice_parameter,
3520 const unsigned rice_parameter_search_dist,
3521 const unsigned partition_order,
3522 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
3523 unsigned *bits
3524)
Josh Coalson8395d022001-07-12 21:25:22 +00003525#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00003526FLAC__bool set_partitioned_rice_(
3527 const FLAC__uint32 abs_residual[],
3528 const unsigned residual_samples,
3529 const unsigned predictor_order,
3530 const unsigned suggested_rice_parameter,
3531 const unsigned rice_parameter_search_dist,
3532 const unsigned partition_order,
3533 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
3534 unsigned *bits
3535)
Josh Coalson8395d022001-07-12 21:25:22 +00003536#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00003537{
Josh Coalson034dfab2001-04-27 19:10:23 +00003538 unsigned rice_parameter, partition_bits;
3539#ifndef NO_RICE_SEARCH
3540 unsigned best_partition_bits;
3541 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
3542#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00003543 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003544 unsigned *parameters;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003545
Josh Coalson1b689822001-05-31 20:11:02 +00003546 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
Josh Coalson2051dd42001-04-12 22:22:34 +00003547
Josh Coalsona37ba462002-08-19 21:36:39 +00003548 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
3549 parameters = partitioned_rice_contents->parameters;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003550
Josh Coalson94e02cd2001-01-25 10:41:06 +00003551 if(partition_order == 0) {
3552 unsigned i;
Josh Coalson352e0f62001-03-20 22:55:50 +00003553
Josh Coalson034dfab2001-04-27 19:10:23 +00003554#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00003555 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00003556 if(suggested_rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00003557 min_rice_parameter = 0;
3558 else
Josh Coalson034dfab2001-04-27 19:10:23 +00003559 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
3560 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00003561 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00003562#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00003563 fprintf(stderr, "clipping rice_parameter (%u -> %u) @2\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
3564#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00003565 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00003566 }
3567 }
3568 else
3569 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
3570
3571 best_partition_bits = 0xffffffff;
3572 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
3573#endif
3574#ifdef VARIABLE_RICE_BITS
Josh Coalson8395d022001-07-12 21:25:22 +00003575 const unsigned rice_parameter_estimate = rice_parameter-1;
3576 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalson8395d022001-07-12 21:25:22 +00003577#else
3578 partition_bits = 0;
3579#endif
3580 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
3581 for(i = 0; i < residual_samples; i++) {
3582#ifdef VARIABLE_RICE_BITS
Josh Coalson8395d022001-07-12 21:25:22 +00003583 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalson8395d022001-07-12 21:25:22 +00003584#else
3585 partition_bits += FLAC__bitbuffer_rice_bits(residual[i], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
3586#endif
3587 }
3588#ifndef NO_RICE_SEARCH
3589 if(partition_bits < best_partition_bits) {
3590 best_rice_parameter = rice_parameter;
3591 best_partition_bits = partition_bits;
3592 }
3593 }
3594#endif
3595 parameters[0] = best_rice_parameter;
3596 bits_ += best_partition_bits;
3597 }
3598 else {
3599 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003600 unsigned partition_samples;
3601 FLAC__uint64 mean, k;
Josh Coalson8395d022001-07-12 21:25:22 +00003602 const unsigned partitions = 1u << partition_order;
3603 for(partition = residual_sample = 0; partition < partitions; partition++) {
3604 partition_samples = (residual_samples+predictor_order) >> partition_order;
3605 if(partition == 0) {
3606 if(partition_samples <= predictor_order)
3607 return false;
3608 else
3609 partition_samples -= predictor_order;
3610 }
3611 mean = 0;
3612 save_residual_sample = residual_sample;
3613 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++)
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003614 mean += abs_residual[residual_sample];
Josh Coalson8395d022001-07-12 21:25:22 +00003615 residual_sample = save_residual_sample;
Josh Coalsonf81b6df2005-02-04 01:34:35 +00003616 /* we are basically calculating the size in bits of the
3617 * average residual magnitude in the partition:
3618 * rice_parameter = floor(log2(mean/partition_samples))
3619 * 'mean' is not a good name for the variable, it is
3620 * actually the sum of magnitudes of all residual values
3621 * in the partition, so the actual mean is
3622 * mean/partition_samples
3623 */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003624 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson8395d022001-07-12 21:25:22 +00003625 ;
Josh Coalson8395d022001-07-12 21:25:22 +00003626 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00003627#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00003628 fprintf(stderr, "clipping rice_parameter (%u -> %u) @3\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
3629#endif
3630 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
3631 }
3632
3633#ifndef NO_RICE_SEARCH
3634 if(rice_parameter_search_dist) {
3635 if(rice_parameter < rice_parameter_search_dist)
3636 min_rice_parameter = 0;
3637 else
3638 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
3639 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
3640 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00003641#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00003642 fprintf(stderr, "clipping rice_parameter (%u -> %u) @4\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
3643#endif
3644 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
3645 }
3646 }
3647 else
3648 min_rice_parameter = max_rice_parameter = rice_parameter;
3649
3650 best_partition_bits = 0xffffffff;
3651 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
3652#endif
3653#ifdef VARIABLE_RICE_BITS
Josh Coalson8395d022001-07-12 21:25:22 +00003654 const unsigned rice_parameter_estimate = rice_parameter-1;
3655 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalson8395d022001-07-12 21:25:22 +00003656#else
3657 partition_bits = 0;
3658#endif
3659 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
3660 save_residual_sample = residual_sample;
3661 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
3662#ifdef VARIABLE_RICE_BITS
Josh Coalson8395d022001-07-12 21:25:22 +00003663 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalson8395d022001-07-12 21:25:22 +00003664#else
3665 partition_bits += FLAC__bitbuffer_rice_bits(residual[residual_sample], rice_parameter); /* NOTE: we will need to pass in residual[] in addition to abs_residual[] */
3666#endif
3667 }
3668#ifndef NO_RICE_SEARCH
3669 if(rice_parameter != max_rice_parameter)
3670 residual_sample = save_residual_sample;
3671 if(partition_bits < best_partition_bits) {
3672 best_rice_parameter = rice_parameter;
3673 best_partition_bits = partition_bits;
3674 }
3675 }
3676#endif
3677 parameters[partition] = best_rice_parameter;
3678 bits_ += best_partition_bits;
3679 }
3680 }
3681
3682 *bits = bits_;
3683 return true;
3684}
3685
3686#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson6fe72f72002-08-20 04:01:59 +00003687FLAC__bool set_partitioned_rice_with_precompute_(
3688 const FLAC__int32 residual[],
3689 const FLAC__uint64 abs_residual_partition_sums[],
3690 const unsigned raw_bits_per_partition[],
3691 const unsigned residual_samples,
3692 const unsigned predictor_order,
3693 const unsigned suggested_rice_parameter,
3694 const unsigned rice_parameter_search_dist,
3695 const unsigned partition_order,
3696 const FLAC__bool search_for_escapes,
3697 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
3698 unsigned *bits
3699)
Josh Coalson8395d022001-07-12 21:25:22 +00003700#else
Josh Coalson6fe72f72002-08-20 04:01:59 +00003701FLAC__bool set_partitioned_rice_with_precompute_(
3702 const FLAC__uint32 abs_residual[],
3703 const FLAC__uint64 abs_residual_partition_sums[],
3704 const unsigned raw_bits_per_partition[],
3705 const unsigned residual_samples,
3706 const unsigned predictor_order,
3707 const unsigned suggested_rice_parameter,
3708 const unsigned rice_parameter_search_dist,
3709 const unsigned partition_order,
3710 const FLAC__bool search_for_escapes,
3711 FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
3712 unsigned *bits
3713)
Josh Coalson8395d022001-07-12 21:25:22 +00003714#endif
3715{
3716 unsigned rice_parameter, partition_bits;
3717#ifndef NO_RICE_SEARCH
3718 unsigned best_partition_bits;
3719 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
3720#endif
3721 unsigned flat_bits;
3722 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003723 unsigned *parameters, *raw_bits;
Josh Coalson8395d022001-07-12 21:25:22 +00003724
3725 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
3726
Josh Coalsona37ba462002-08-19 21:36:39 +00003727 FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order));
3728 parameters = partitioned_rice_contents->parameters;
3729 raw_bits = partitioned_rice_contents->raw_bits;
Josh Coalsonb7023aa2002-08-17 15:23:43 +00003730
Josh Coalson8395d022001-07-12 21:25:22 +00003731 if(partition_order == 0) {
3732 unsigned i;
3733
3734#ifndef NO_RICE_SEARCH
3735 if(rice_parameter_search_dist) {
3736 if(suggested_rice_parameter < rice_parameter_search_dist)
3737 min_rice_parameter = 0;
3738 else
3739 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
3740 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
3741 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00003742#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00003743 fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
3744#endif
3745 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
3746 }
Josh Coalson60f77d72001-04-25 02:16:36 +00003747 }
3748 else
Josh Coalson034dfab2001-04-27 19:10:23 +00003749 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
Josh Coalson2051dd42001-04-12 22:22:34 +00003750
Josh Coalson034dfab2001-04-27 19:10:23 +00003751 best_partition_bits = 0xffffffff;
3752 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
3753#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00003754#ifdef VARIABLE_RICE_BITS
Josh Coalson352e0f62001-03-20 22:55:50 +00003755 const unsigned rice_parameter_estimate = rice_parameter-1;
Josh Coalson034dfab2001-04-27 19:10:23 +00003756 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalson034dfab2001-04-27 19:10:23 +00003757#else
3758 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003759#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00003760 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson352e0f62001-03-20 22:55:50 +00003761 for(i = 0; i < residual_samples; i++) {
3762#ifdef VARIABLE_RICE_BITS
Josh Coalson2051dd42001-04-12 22:22:34 +00003763 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00003764#else
Josh Coalson2051dd42001-04-12 22:22:34 +00003765 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 +00003766#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00003767 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003768#ifndef NO_RICE_SEARCH
3769 if(partition_bits < best_partition_bits) {
3770 best_rice_parameter = rice_parameter;
3771 best_partition_bits = partition_bits;
Josh Coalson352e0f62001-03-20 22:55:50 +00003772 }
3773 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003774#endif
Josh Coalson8395d022001-07-12 21:25:22 +00003775 if(search_for_escapes) {
3776 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;
3777 if(flat_bits <= best_partition_bits) {
3778 raw_bits[0] = raw_bits_per_partition[0];
3779 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
3780 best_partition_bits = flat_bits;
3781 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003782 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003783 parameters[0] = best_rice_parameter;
3784 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003785 }
3786 else {
Josh Coalson4dacd192001-06-06 21:11:44 +00003787 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003788 unsigned partition_samples;
3789 FLAC__uint64 mean, k;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00003790 const unsigned partitions = 1u << partition_order;
Josh Coalson4dacd192001-06-06 21:11:44 +00003791 for(partition = residual_sample = 0; partition < partitions; partition++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00003792 partition_samples = (residual_samples+predictor_order) >> partition_order;
Josh Coalson034dfab2001-04-27 19:10:23 +00003793 if(partition == 0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00003794 if(partition_samples <= predictor_order)
3795 return false;
3796 else
3797 partition_samples -= predictor_order;
3798 }
Josh Coalson05d20792001-06-29 23:12:26 +00003799 mean = abs_residual_partition_sums[partition];
Josh Coalsonf81b6df2005-02-04 01:34:35 +00003800 /* we are basically calculating the size in bits of the
3801 * average residual magnitude in the partition:
3802 * rice_parameter = floor(log2(mean/partition_samples))
3803 * 'mean' is not a good name for the variable, it is
3804 * actually the sum of magnitudes of all residual values
3805 * in the partition, so the actual mean is
3806 * mean/partition_samples
3807 */
Josh Coalsonb3347bd2001-07-16 18:06:41 +00003808 for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1)
Josh Coalson05d20792001-06-29 23:12:26 +00003809 ;
Josh Coalson8395d022001-07-12 21:25:22 +00003810 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00003811#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00003812 fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
3813#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00003814 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00003815 }
Josh Coalson60f77d72001-04-25 02:16:36 +00003816
Josh Coalson034dfab2001-04-27 19:10:23 +00003817#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00003818 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00003819 if(rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00003820 min_rice_parameter = 0;
3821 else
Josh Coalson034dfab2001-04-27 19:10:23 +00003822 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
3823 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
Josh Coalson8395d022001-07-12 21:25:22 +00003824 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
Josh Coalson31209492001-07-18 23:43:01 +00003825#ifdef DEBUG_VERBOSE
Josh Coalson8395d022001-07-12 21:25:22 +00003826 fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
3827#endif
Josh Coalson60f77d72001-04-25 02:16:36 +00003828 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson8395d022001-07-12 21:25:22 +00003829 }
Josh Coalson60f77d72001-04-25 02:16:36 +00003830 }
3831 else
3832 min_rice_parameter = max_rice_parameter = rice_parameter;
Josh Coalson60f77d72001-04-25 02:16:36 +00003833
Josh Coalson034dfab2001-04-27 19:10:23 +00003834 best_partition_bits = 0xffffffff;
3835 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
3836#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00003837#ifdef VARIABLE_RICE_BITS
Josh Coalson034dfab2001-04-27 19:10:23 +00003838 const unsigned rice_parameter_estimate = rice_parameter-1;
3839 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalson034dfab2001-04-27 19:10:23 +00003840#else
3841 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003842#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00003843 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson4dacd192001-06-06 21:11:44 +00003844 save_residual_sample = residual_sample;
3845 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
Josh Coalson352e0f62001-03-20 22:55:50 +00003846#ifdef VARIABLE_RICE_BITS
Josh Coalson4dacd192001-06-06 21:11:44 +00003847 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00003848#else
Josh Coalson4dacd192001-06-06 21:11:44 +00003849 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 +00003850#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00003851 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003852#ifndef NO_RICE_SEARCH
Josh Coalson4dacd192001-06-06 21:11:44 +00003853 if(rice_parameter != max_rice_parameter)
3854 residual_sample = save_residual_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00003855 if(partition_bits < best_partition_bits) {
3856 best_rice_parameter = rice_parameter;
3857 best_partition_bits = partition_bits;
3858 }
Josh Coalson2051dd42001-04-12 22:22:34 +00003859 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003860#endif
Josh Coalson8395d022001-07-12 21:25:22 +00003861 if(search_for_escapes) {
3862 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;
3863 if(flat_bits <= best_partition_bits) {
3864 raw_bits[partition] = raw_bits_per_partition[partition];
3865 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
3866 best_partition_bits = flat_bits;
3867 }
Josh Coalson2051dd42001-04-12 22:22:34 +00003868 }
Josh Coalson034dfab2001-04-27 19:10:23 +00003869 parameters[partition] = best_rice_parameter;
3870 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00003871 }
3872 }
3873
3874 *bits = bits_;
3875 return true;
3876}
Josh Coalson859bc542001-03-27 22:22:27 +00003877
Josh Coalsonf1eff452002-07-31 07:05:33 +00003878unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples)
Josh Coalson859bc542001-03-27 22:22:27 +00003879{
3880 unsigned i, shift;
Josh Coalson77e3f312001-06-23 03:03:24 +00003881 FLAC__int32 x = 0;
Josh Coalson859bc542001-03-27 22:22:27 +00003882
3883 for(i = 0; i < samples && !(x&1); i++)
3884 x |= signal[i];
3885
3886 if(x == 0) {
3887 shift = 0;
3888 }
3889 else {
3890 for(shift = 0; !(x&1); shift++)
3891 x >>= 1;
3892 }
3893
3894 if(shift > 0) {
3895 for(i = 0; i < samples; i++)
3896 signal[i] >>= shift;
3897 }
3898
3899 return shift;
3900}
Josh Coalsond86e03b2002-08-03 21:56:15 +00003901
3902void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
3903{
3904 unsigned channel;
3905
3906 for(channel = 0; channel < channels; channel++)
3907 memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples);
3908
3909 fifo->tail += wide_samples;
3910
3911 FLAC__ASSERT(fifo->tail <= fifo->size);
3912}
3913
3914void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples)
3915{
3916 unsigned channel;
3917 unsigned sample, wide_sample;
3918 unsigned tail = fifo->tail;
3919
3920 sample = input_offset * channels;
3921 for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
3922 for(channel = 0; channel < channels; channel++)
3923 fifo->data[channel][tail] = input[sample++];
3924 tail++;
3925 }
3926 fifo->tail = tail;
3927
3928 FLAC__ASSERT(fifo->tail <= fifo->size);
3929}
3930
3931FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
3932{
3933 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
3934 const unsigned encoded_bytes = encoder->private_->verify.output.bytes;
3935 (void)decoder;
3936
3937 if(encoder->private_->verify.needs_magic_hack) {
3938 FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH);
3939 *bytes = FLAC__STREAM_SYNC_LENGTH;
3940 memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes);
3941 encoder->private_->verify.needs_magic_hack = false;
3942 }
3943 else {
3944 if(encoded_bytes == 0) {
Josh Coalsonfc2b7372002-08-16 05:39:34 +00003945 /*
3946 * If we get here, a FIFO underflow has occurred,
3947 * which means there is a bug somewhere.
3948 */
3949 FLAC__ASSERT(0);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003950 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
3951 }
3952 else if(encoded_bytes < *bytes)
3953 *bytes = encoded_bytes;
3954 memcpy(buffer, encoder->private_->verify.output.data, *bytes);
3955 encoder->private_->verify.output.data += *bytes;
3956 encoder->private_->verify.output.bytes -= *bytes;
3957 }
3958
3959 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
3960}
3961
3962FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
3963{
3964 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data;
3965 unsigned channel;
3966 const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
3967 const unsigned blocksize = frame->header.blocksize;
3968 const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize;
3969
3970 for(channel = 0; channel < channels; channel++) {
3971 if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) {
3972 unsigned i, sample = 0;
3973 FLAC__int32 expect = 0, got = 0;
3974
3975 for(i = 0; i < blocksize; i++) {
3976 if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) {
3977 sample = i;
3978 expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i];
3979 got = (FLAC__int32)buffer[channel][i];
3980 break;
3981 }
3982 }
3983 FLAC__ASSERT(i < blocksize);
3984 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
3985 encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample;
Josh Coalson5f39e9f2002-08-21 05:27:01 +00003986 encoder->private_->verify.error_stats.frame_number = (unsigned)(frame->header.number.sample_number / blocksize);
Josh Coalsond86e03b2002-08-03 21:56:15 +00003987 encoder->private_->verify.error_stats.channel = channel;
3988 encoder->private_->verify.error_stats.sample = sample;
3989 encoder->private_->verify.error_stats.expected = expect;
3990 encoder->private_->verify.error_stats.got = got;
3991 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA;
3992 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
3993 }
3994 }
3995 /* dequeue the frame from the fifo */
3996 for(channel = 0; channel < channels; channel++) {
3997 memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail - blocksize);
3998 }
3999 encoder->private_->verify.input_fifo.tail -= blocksize;
4000 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
4001}
4002
4003void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
4004{
4005 (void)decoder, (void)metadata, (void)client_data;
4006}
4007
4008void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
4009{
4010 FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data;
4011 (void)decoder, (void)status;
4012 encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
4013}
Josh Coalson6b21f662006-09-13 01:42:27 +00004014
4015FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
4016{
4017 (void)client_data;
4018
4019 if(fseeko(encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
4020 return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
4021 else
4022 return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
4023}
4024
4025FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
4026{
4027 off_t offset;
4028
4029 (void)client_data;
4030
4031 offset = ftello(encoder->private_->file);
4032
4033 if(offset < 0) {
4034 return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
4035 }
4036 else {
4037 *absolute_byte_offset = (FLAC__uint64)offset;
4038 return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
4039 }
4040}
4041
4042#ifdef FLAC__VALGRIND_TESTING
4043static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
4044{
4045 size_t ret = fwrite(ptr, size, nmemb, stream);
4046 if(!ferror(stream))
4047 fflush(stream);
4048 return ret;
4049}
4050#else
4051#define local__fwrite fwrite
4052#endif
4053
4054FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
4055{
4056 (void)client_data, (void)samples, (void)current_frame;
4057
4058 if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) {
4059 if(0 != encoder->private_->progress_callback && samples > 0)
4060 encoder->private_->progress_callback(encoder, encoder->private_->bytes_written, encoder->private_->samples_written, encoder->private_->frames_written, encoder->private_->total_frames_estimate, encoder->private_->client_data);
4061 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
4062 }
4063 else
4064 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
4065}
4066
4067/*
4068 * This will forcibly set stdout to binary mode (for OSes that require it)
4069 */
4070FILE *get_binary_stdout_()
4071{
4072 /* if something breaks here it is probably due to the presence or
4073 * absence of an underscore before the identifiers 'setmode',
4074 * 'fileno', and/or 'O_BINARY'; check your system header files.
4075 */
4076#if defined _MSC_VER || defined __MINGW32__
4077 _setmode(_fileno(stdout), _O_BINARY);
4078#elif defined __CYGWIN__
4079 /* almost certainly not needed for any modern Cygwin, but let's be safe... */
4080 setmode(_fileno(stdout), _O_BINARY);
4081#elif defined __EMX__
4082 setmode(fileno(stdout), O_BINARY);
4083#endif
4084
4085 return stdout;
4086}