blob: c24932ffa642e8de1c820299e9e7003b13041d98 [file] [log] [blame]
Josh Coalson26560dd2001-02-08 00:38:41 +00001/* libFLAC - Free Lossless Audio Codec library
Josh Coalson70118f62001-01-16 20:17:53 +00002 * Copyright (C) 2000,2001 Josh Coalson
Josh Coalsonbb7f6b92000-12-10 04:09:52 +00003 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000020#include <stdio.h>
21#include <stdlib.h> /* for malloc() */
22#include <string.h> /* for memcpy() */
Josh Coalson1b689822001-05-31 20:11:02 +000023#include "FLAC/assert.h"
Josh Coalson0a72e182001-04-13 19:17:16 +000024#include "FLAC/seek_table.h"
Josh Coalson0a15c142001-06-13 17:59:57 +000025#include "protected/stream_encoder.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000026#include "private/bitbuffer.h"
Josh Coalsoneef56702001-03-30 00:45:22 +000027#include "private/bitmath.h"
Josh Coalson215af572001-03-27 01:15:58 +000028#include "private/crc.h"
Josh Coalsoncf30f502001-05-23 20:57:44 +000029#include "private/cpu.h"
Josh Coalson0a15c142001-06-13 17:59:57 +000030#include "private/stream_encoder_framing.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000031#include "private/fixed.h"
32#include "private/lpc.h"
Josh Coalsonfa37f1c2001-01-12 23:55:11 +000033#include "private/md5.h"
Josh Coalsond98c43d2001-05-13 05:17:01 +000034#include "private/memory.h"
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000035
36#ifdef min
37#undef min
38#endif
39#define min(x,y) ((x)<(y)?(x):(y))
40
41#ifdef max
42#undef max
43#endif
44#define max(x,y) ((x)>(y)?(x):(y))
45
Josh Coalson0a15c142001-06-13 17:59:57 +000046/***********************************************************************
47 *
48 * Private class method prototypes
49 *
50 ***********************************************************************/
51
52static bool stream_encoder_resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
53static bool stream_encoder_process_frame_(FLAC__StreamEncoder *encoder, bool is_last_frame);
54static bool stream_encoder_process_subframes_(FLAC__StreamEncoder *encoder, bool is_last_frame);
55static bool stream_encoder_process_subframe_(FLAC__StreamEncoder *encoder, unsigned min_partition_order, unsigned max_partition_order, bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const int32 integer_signal[], const real real_signal[], FLAC__Subframe *subframe[2], int32 *residual[2], unsigned *best_subframe, unsigned *best_bits);
56static bool stream_encoder_add_subframe_(FLAC__StreamEncoder *encoder, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const FLAC__Subframe *subframe, FLAC__BitBuffer *frame);
57static unsigned stream_encoder_evaluate_constant_subframe_(const int32 signal, unsigned subframe_bps, FLAC__Subframe *subframe);
58static unsigned stream_encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe);
59static unsigned stream_encoder_evaluate_lpc_subframe_(FLAC__StreamEncoder *encoder, const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], const real lp_coeff[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe);
60static unsigned stream_encoder_evaluate_verbatim_subframe_(const int32 signal[], unsigned blocksize, unsigned subframe_bps, FLAC__Subframe *subframe);
61static unsigned stream_encoder_find_best_partition_order_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, unsigned *best_partition_order, unsigned best_parameters[], unsigned best_raw_bits[]);
62#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
63static unsigned stream_encoder_precompute_partition_info_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order);
64#endif
65static bool stream_encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, const unsigned suggested_rice_parameter, const unsigned rice_parameter_search_dist, const unsigned partition_order, unsigned parameters[], unsigned raw_bits[], unsigned *bits);
66static unsigned stream_encoder_get_wasted_bits_(int32 signal[], unsigned samples);
67
68/***********************************************************************
69 *
70 * Private class data
71 *
72 ***********************************************************************/
73
74typedef struct FLAC__StreamEncoderPrivate {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000075 unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */
76 int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */
77 int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */
78 real *real_signal[FLAC__MAX_CHANNELS]; /* the floating-point version of the input signal */
79 real *real_signal_mid_side[2]; /* the floating-point version of the mid-side input signal (stereo only) */
Josh Coalson82b73242001-03-28 22:17:05 +000080 unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */
Josh Coalsonac4c1582001-03-28 23:10:22 +000081 unsigned subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */
Josh Coalson94e02cd2001-01-25 10:41:06 +000082 int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
83 int32 *residual_workspace_mid_side[2][2];
84 FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
85 FLAC__Subframe subframe_workspace_mid_side[2][2];
86 FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
87 FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
88 unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index into the above workspaces */
89 unsigned best_subframe_mid_side[2];
90 unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */
91 unsigned best_subframe_bits_mid_side[2];
Josh Coalson2051dd42001-04-12 22:22:34 +000092 uint32 *abs_residual; /* workspace where abs(candidate residual) is stored */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +000093 uint32 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */
Josh Coalsonaef013c2001-04-24 01:25:42 +000094 unsigned *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +000095 FLAC__BitBuffer frame; /* the current frame being worked on */
Josh Coalsonb5e60e52001-01-28 09:27:27 +000096 double loose_mid_side_stereo_frames_exact; /* exact number of frames the encoder will use before trying both independent and mid/side frames again */
97 unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
98 unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
99 FLAC__ChannelAssignment last_channel_assignment;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000100 FLAC__StreamMetaData metadata;
101 unsigned current_sample_number;
102 unsigned current_frame_number;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +0000103 struct MD5Context md5context;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000104 FLAC__CPUInfo cpuinfo;
105 unsigned (*local_fixed_compute_best_predictor)(const int32 data[], unsigned data_len, real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
106 void (*local_lpc_compute_autocorrelation)(const real data[], unsigned data_len, unsigned lag, real autoc[]);
Josh Coalson8e833622001-05-29 20:49:51 +0000107 void (*local_lpc_compute_residual_from_qlp_coefficients)(const int32 data[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 residual[]);
Josh Coalson92d42402001-05-31 20:53:19 +0000108 void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const int32 data[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 residual[]);
Josh Coalsoneef56702001-03-30 00:45:22 +0000109 bool use_slow; /* use slow 64-bit versions of some functions */
Josh Coalson0a15c142001-06-13 17:59:57 +0000110 FLAC__StreamEncoderWriteStatus (*write_callback)(const FLAC__StreamEncoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
111 void (*metadata_callback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000112 void *client_data;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000113 /* unaligned (original) pointers to allocated data */
114 int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
115 int32 *integer_signal_mid_side_unaligned[2];
116 real *real_signal_unaligned[FLAC__MAX_CHANNELS];
117 real *real_signal_mid_side_unaligned[2];
118 int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
119 int32 *residual_workspace_mid_side_unaligned[2][2];
120 uint32 *abs_residual_unaligned;
121 uint32 *abs_residual_partition_sums_unaligned;
122 unsigned *raw_bits_per_partition_unaligned;
Josh Coalson0a15c142001-06-13 17:59:57 +0000123} FLAC__StreamEncoderPrivate;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000124
Josh Coalson0a15c142001-06-13 17:59:57 +0000125/***********************************************************************
126 *
127 * Public static class data
128 *
129 ***********************************************************************/
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000130
Josh Coalson0a15c142001-06-13 17:59:57 +0000131const char *FLAC__StreamEncoderStateString[] = {
132 "FLAC__STREAM_ENCODER_OK",
133 "FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS",
134 "FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE",
135 "FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE",
136 "FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE",
137 "FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION",
138 "FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH",
139 "FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
140 "FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE",
141 "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
142 "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
143 "FLAC__STREAM_ENCODER_FRAMING_ERROR",
144 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
145 "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
146 "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
147 "FLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
148 "FLAC__STREAM_ENCODER_UNINITIALIZED"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000149};
150
Josh Coalson0a15c142001-06-13 17:59:57 +0000151const char *FLAC__StreamEncoderWriteStatusString[] = {
152 "FLAC__STREAM_ENCODER_WRITE_OK",
153 "FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR"
Josh Coalsoncbf595f2000-12-22 22:35:33 +0000154};
155
Josh Coalson0a15c142001-06-13 17:59:57 +0000156/***********************************************************************
157 *
158 * Class constructor/destructor
159 *
160 ***********************************************************************/
161FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000162{
Josh Coalson0a15c142001-06-13 17:59:57 +0000163 FLAC__StreamEncoder *encoder;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000164
Josh Coalson0a15c142001-06-13 17:59:57 +0000165 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000166
Josh Coalson0a15c142001-06-13 17:59:57 +0000167 encoder = (FLAC__StreamEncoder*)malloc(sizeof(FLAC__StreamEncoder));
168 if(encoder == 0) {
169 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000170 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000171 encoder->protected = (FLAC__StreamEncoderProtected*)malloc(sizeof(FLAC__StreamEncoderProtected));
172 if(encoder->protected == 0) {
173 free(encoder);
174 return 0;
Josh Coalsond98c43d2001-05-13 05:17:01 +0000175 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000176 encoder->private = (FLAC__StreamEncoderPrivate*)malloc(sizeof(FLAC__StreamEncoderPrivate));
177 if(encoder->private == 0) {
178 free(encoder->protected);
179 free(encoder);
180 return 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000181 }
Josh Coalsond98c43d2001-05-13 05:17:01 +0000182
Josh Coalson0a15c142001-06-13 17:59:57 +0000183 encoder->protected->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000184
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000185 return encoder;
186}
187
Josh Coalson0a15c142001-06-13 17:59:57 +0000188void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000189{
Josh Coalson1b689822001-05-31 20:11:02 +0000190 FLAC__ASSERT(encoder != 0);
Josh Coalson0a15c142001-06-13 17:59:57 +0000191 FLAC__ASSERT(encoder->protected != 0);
192 FLAC__ASSERT(encoder->private != 0);
193
194 free(encoder->private);
195 free(encoder->protected);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000196 free(encoder);
197}
198
Josh Coalson0a15c142001-06-13 17:59:57 +0000199/***********************************************************************
200 *
201 * Public class methods
202 *
203 ***********************************************************************/
204
205FLAC__StreamEncoderState FLAC__stream_encoder_init(
206 FLAC__StreamEncoder *encoder,
207 bool streamable_subset,
208 bool do_mid_side_stereo,
209 bool loose_mid_side_stereo,
210 unsigned channels,
211 unsigned bits_per_sample,
212 unsigned sample_rate,
213 unsigned blocksize,
214 unsigned max_lpc_order,
215 unsigned qlp_coeff_precision,
216 bool do_qlp_coeff_prec_search,
217 bool do_exhaustive_model_search,
218 unsigned min_residual_partition_order,
219 unsigned max_residual_partition_order,
220 unsigned rice_parameter_search_dist,
221 uint64 total_samples_estimate,
222 const FLAC__StreamMetaData_SeekTable *seek_table,
223 unsigned padding,
224 FLAC__StreamEncoderWriteStatus (*write_callback)(const FLAC__StreamEncoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data),
225 void (*metadata_callback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data),
226 void *client_data)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000227{
228 unsigned i;
Josh Coalson0a15c142001-06-13 17:59:57 +0000229 FLAC__StreamMetaData padding_block;
230 FLAC__StreamMetaData seek_table_block;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000231
Josh Coalson1b689822001-05-31 20:11:02 +0000232 FLAC__ASSERT(encoder != 0);
233 FLAC__ASSERT(write_callback != 0);
234 FLAC__ASSERT(metadata_callback != 0);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000235
Josh Coalson0a15c142001-06-13 17:59:57 +0000236 if(encoder->protected->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
237 return encoder->protected->state = FLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000238
Josh Coalson0a15c142001-06-13 17:59:57 +0000239 encoder->protected->state = FLAC__STREAM_ENCODER_OK;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000240
Josh Coalson0a15c142001-06-13 17:59:57 +0000241 encoder->protected->streamable_subset = streamable_subset;
242 encoder->protected->do_mid_side_stereo = do_mid_side_stereo;
243 encoder->protected->loose_mid_side_stereo = loose_mid_side_stereo;
244 encoder->protected->channels = channels;
245 encoder->protected->bits_per_sample = bits_per_sample;
246 encoder->protected->sample_rate = sample_rate;
247 encoder->protected->blocksize = blocksize;
248 encoder->protected->max_lpc_order = max_lpc_order;
249 encoder->protected->qlp_coeff_precision = qlp_coeff_precision;
250 encoder->protected->do_qlp_coeff_prec_search = do_qlp_coeff_prec_search;
251 encoder->protected->do_exhaustive_model_search = do_exhaustive_model_search;
252 encoder->protected->min_residual_partition_order = min_residual_partition_order;
253 encoder->protected->max_residual_partition_order = max_residual_partition_order;
254 encoder->protected->rice_parameter_search_dist = rice_parameter_search_dist;
255 encoder->protected->total_samples_estimate = total_samples_estimate;
256 encoder->protected->seek_table = seek_table;
257 encoder->protected->padding = padding;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000258
Josh Coalson0a15c142001-06-13 17:59:57 +0000259 if(encoder->protected->channels == 0 || encoder->protected->channels > FLAC__MAX_CHANNELS)
260 return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson69f1ee02001-01-24 00:54:43 +0000261
Josh Coalson0a15c142001-06-13 17:59:57 +0000262 if(encoder->protected->do_mid_side_stereo && encoder->protected->channels != 2)
263 return encoder->protected->state = FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH;
Josh Coalsond37d1352001-05-30 23:09:31 +0000264
Josh Coalson0a15c142001-06-13 17:59:57 +0000265 if(encoder->protected->loose_mid_side_stereo && !encoder->protected->do_mid_side_stereo)
266 return encoder->protected->state = FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000267
Josh Coalson0a15c142001-06-13 17:59:57 +0000268 if(encoder->protected->bits_per_sample >= 32)
269 encoder->protected->do_mid_side_stereo = false; /* since we do 32-bit math, the side channel would have 33 bps and overflow */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000270
Josh Coalson0a15c142001-06-13 17:59:57 +0000271 if(encoder->protected->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected->bits_per_sample > FLAC__MAX_BITS_PER_SAMPLE)
272 return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000273
Josh Coalson0a15c142001-06-13 17:59:57 +0000274 if(encoder->protected->sample_rate == 0 || encoder->protected->sample_rate > FLAC__MAX_SAMPLE_RATE)
275 return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000276
Josh Coalson0a15c142001-06-13 17:59:57 +0000277 if(encoder->protected->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected->blocksize > FLAC__MAX_BLOCK_SIZE)
278 return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE;
279
280 if(encoder->protected->blocksize < encoder->protected->max_lpc_order)
281 return encoder->protected->state = FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
282
283 if(encoder->protected->qlp_coeff_precision == 0) {
284 if(encoder->protected->bits_per_sample < 16) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000285 /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
286 /* @@@ until then we'll make a guess */
Josh Coalson0a15c142001-06-13 17:59:57 +0000287 encoder->protected->qlp_coeff_precision = max(5, 2 + encoder->protected->bits_per_sample / 2);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000288 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000289 else if(encoder->protected->bits_per_sample == 16) {
290 if(encoder->protected->blocksize <= 192)
291 encoder->protected->qlp_coeff_precision = 7;
292 else if(encoder->protected->blocksize <= 384)
293 encoder->protected->qlp_coeff_precision = 8;
294 else if(encoder->protected->blocksize <= 576)
295 encoder->protected->qlp_coeff_precision = 9;
296 else if(encoder->protected->blocksize <= 1152)
297 encoder->protected->qlp_coeff_precision = 10;
298 else if(encoder->protected->blocksize <= 2304)
299 encoder->protected->qlp_coeff_precision = 11;
300 else if(encoder->protected->blocksize <= 4608)
301 encoder->protected->qlp_coeff_precision = 12;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000302 else
Josh Coalson0a15c142001-06-13 17:59:57 +0000303 encoder->protected->qlp_coeff_precision = 13;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000304 }
305 else {
Josh Coalson0a15c142001-06-13 17:59:57 +0000306 encoder->protected->qlp_coeff_precision = min(13, 8*sizeof(int32) - encoder->protected->bits_per_sample - 1);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000307 }
308 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000309 else if(encoder->protected->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected->qlp_coeff_precision + encoder->protected->bits_per_sample >= 8*sizeof(uint32) || encoder->protected->qlp_coeff_precision >= (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
310 return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000311
Josh Coalson0a15c142001-06-13 17:59:57 +0000312 if(encoder->protected->streamable_subset) {
Josh Coalsond4e0ddb2001-04-18 02:20:52 +0000313 //@@@ add check for blocksize here
Josh Coalson0a15c142001-06-13 17:59:57 +0000314 if(encoder->protected->bits_per_sample != 8 && encoder->protected->bits_per_sample != 12 && encoder->protected->bits_per_sample != 16 && encoder->protected->bits_per_sample != 20 && encoder->protected->bits_per_sample != 24)
315 return encoder->protected->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
316 if(encoder->protected->sample_rate > 655350)
317 return encoder->protected->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000318 }
319
Josh Coalson0a15c142001-06-13 17:59:57 +0000320 if(encoder->protected->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
321 encoder->protected->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
322 if(encoder->protected->min_residual_partition_order >= encoder->protected->max_residual_partition_order)
323 encoder->protected->min_residual_partition_order = encoder->protected->max_residual_partition_order;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000324
Josh Coalson0a15c142001-06-13 17:59:57 +0000325 encoder->private->input_capacity = 0;
326 for(i = 0; i < encoder->protected->channels; i++) {
327 encoder->private->integer_signal_unaligned[i] = encoder->private->integer_signal[i] = 0;
328 encoder->private->real_signal_unaligned[i] = encoder->private->real_signal[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000329 }
330 for(i = 0; i < 2; i++) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000331 encoder->private->integer_signal_mid_side_unaligned[i] = encoder->private->integer_signal_mid_side[i] = 0;
332 encoder->private->real_signal_mid_side_unaligned[i] = encoder->private->real_signal_mid_side[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000333 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000334 for(i = 0; i < encoder->protected->channels; i++) {
335 encoder->private->residual_workspace_unaligned[i][0] = encoder->private->residual_workspace[i][0] = 0;
336 encoder->private->residual_workspace_unaligned[i][1] = encoder->private->residual_workspace[i][1] = 0;
337 encoder->private->best_subframe[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000338 }
339 for(i = 0; i < 2; i++) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000340 encoder->private->residual_workspace_mid_side_unaligned[i][0] = encoder->private->residual_workspace_mid_side[i][0] = 0;
341 encoder->private->residual_workspace_mid_side_unaligned[i][1] = encoder->private->residual_workspace_mid_side[i][1] = 0;
342 encoder->private->best_subframe_mid_side[i] = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000343 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000344 for(i = 0; i < encoder->protected->channels; i++) {
345 encoder->private->subframe_workspace_ptr[i][0] = &encoder->private->subframe_workspace[i][0];
346 encoder->private->subframe_workspace_ptr[i][1] = &encoder->private->subframe_workspace[i][1];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000347 }
348 for(i = 0; i < 2; i++) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000349 encoder->private->subframe_workspace_ptr_mid_side[i][0] = &encoder->private->subframe_workspace_mid_side[i][0];
350 encoder->private->subframe_workspace_ptr_mid_side[i][1] = &encoder->private->subframe_workspace_mid_side[i][1];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000351 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000352 encoder->private->abs_residual_unaligned = encoder->private->abs_residual = 0;
353 encoder->private->abs_residual_partition_sums_unaligned = encoder->private->abs_residual_partition_sums = 0;
354 encoder->private->raw_bits_per_partition_unaligned = encoder->private->raw_bits_per_partition = 0;
355 encoder->private->loose_mid_side_stereo_frames_exact = (double)encoder->protected->sample_rate * 0.4 / (double)encoder->protected->blocksize;
356 encoder->private->loose_mid_side_stereo_frames = (unsigned)(encoder->private->loose_mid_side_stereo_frames_exact + 0.5);
357 if(encoder->private->loose_mid_side_stereo_frames == 0)
358 encoder->private->loose_mid_side_stereo_frames = 1;
359 encoder->private->loose_mid_side_stereo_frame_count = 0;
360 encoder->private->current_sample_number = 0;
361 encoder->private->current_frame_number = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000362
Josh Coalsoncf30f502001-05-23 20:57:44 +0000363 /*
364 * get the CPU info and set the function pointers
365 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000366 FLAC__cpu_info(&encoder->private->cpuinfo);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000367 /* first default to the non-asm routines */
Josh Coalson0a15c142001-06-13 17:59:57 +0000368 encoder->private->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
369 encoder->private->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
370 encoder->private->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
371 encoder->private->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
Josh Coalsoncf30f502001-05-23 20:57:44 +0000372 /* now override with asm where appropriate */
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000373#ifndef FLAC__NO_ASM
Josh Coalson0a15c142001-06-13 17:59:57 +0000374 FLAC__ASSERT(encoder->private->cpuinfo.use_asm);
Josh Coalsoncf30f502001-05-23 20:57:44 +0000375#ifdef FLAC__CPU_IA32
Josh Coalson0a15c142001-06-13 17:59:57 +0000376 FLAC__ASSERT(encoder->private->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
Josh Coalson034d38e2001-05-24 19:29:30 +0000377#ifdef FLAC__HAS_NASM
Josh Coalson0a15c142001-06-13 17:59:57 +0000378 if(0 && encoder->private->cpuinfo.data.ia32.sse) { /* SSE version lacks necessary resolution, plus SSE flag doesn't check for OS support */
379 if(encoder->protected->max_lpc_order < 4)
380 encoder->private->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386_sse_lag_4;
381 else if(encoder->protected->max_lpc_order < 8)
382 encoder->private->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386_sse_lag_8;
383 else if(encoder->protected->max_lpc_order < 12)
384 encoder->private->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386_sse_lag_12;
Josh Coalsonaa255362001-05-31 06:17:41 +0000385 else
Josh Coalson0a15c142001-06-13 17:59:57 +0000386 encoder->private->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386;
Josh Coalsonaa255362001-05-31 06:17:41 +0000387 }
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000388 else
Josh Coalson0a15c142001-06-13 17:59:57 +0000389 encoder->private->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386;
390 if(encoder->private->cpuinfo.data.ia32.mmx && encoder->private->cpuinfo.data.ia32.cmov)
391 encoder->private->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_i386_mmx_cmov;
392 if(encoder->private->cpuinfo.data.ia32.mmx) {
393 encoder->private->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_i386;
394 encoder->private->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_i386_mmx;
Josh Coalson92d42402001-05-31 20:53:19 +0000395 }
396 else {
Josh Coalson0a15c142001-06-13 17:59:57 +0000397 encoder->private->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_i386;
398 encoder->private->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_i386;
Josh Coalson92d42402001-05-31 20:53:19 +0000399 }
Josh Coalsoncf30f502001-05-23 20:57:44 +0000400#endif
Josh Coalson034d38e2001-05-24 19:29:30 +0000401#endif
Josh Coalsona3f7c2c2001-05-25 00:04:45 +0000402#endif
Josh Coalsoncf30f502001-05-23 20:57:44 +0000403
Josh Coalson0a15c142001-06-13 17:59:57 +0000404 if(encoder->protected->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected->blocksize)+1 > 30)
405 encoder->private->use_slow = true;
Josh Coalsoneef56702001-03-30 00:45:22 +0000406 else
Josh Coalson0a15c142001-06-13 17:59:57 +0000407 encoder->private->use_slow = false;
Josh Coalsoneef56702001-03-30 00:45:22 +0000408
Josh Coalson0a15c142001-06-13 17:59:57 +0000409 if(!stream_encoder_resize_buffers_(encoder, encoder->protected->blocksize)) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000410 /* the above function sets the state for us in case of an error */
Josh Coalson0a15c142001-06-13 17:59:57 +0000411 return encoder->protected->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000412 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000413 FLAC__bitbuffer_init(&encoder->private->frame);
414 encoder->private->write_callback = write_callback;
415 encoder->private->metadata_callback = metadata_callback;
416 encoder->private->client_data = client_data;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000417
418 /*
419 * write the stream header
420 */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000421
Josh Coalson0a15c142001-06-13 17:59:57 +0000422 if(!FLAC__bitbuffer_clear(&encoder->private->frame))
423 return encoder->protected->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
424 if(!FLAC__bitbuffer_write_raw_uint32(&encoder->private->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
425 return encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000426
Josh Coalson0a15c142001-06-13 17:59:57 +0000427 encoder->private->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
428 encoder->private->metadata.is_last = (encoder->protected->seek_table == 0 && encoder->protected->padding == 0);
429 encoder->private->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
430 encoder->private->metadata.data.stream_info.min_blocksize = encoder->protected->blocksize; /* this encoder uses the same blocksize for the whole stream */
431 encoder->private->metadata.data.stream_info.max_blocksize = encoder->protected->blocksize;
432 encoder->private->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
433 encoder->private->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
434 encoder->private->metadata.data.stream_info.sample_rate = encoder->protected->sample_rate;
435 encoder->private->metadata.data.stream_info.channels = encoder->protected->channels;
436 encoder->private->metadata.data.stream_info.bits_per_sample = encoder->protected->bits_per_sample;
437 encoder->private->metadata.data.stream_info.total_samples = encoder->protected->total_samples_estimate; /* we will replace this later with the real total */
438 memset(encoder->private->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
439 MD5Init(&encoder->private->md5context);
440 if(!FLAC__add_metadata_block(&encoder->private->metadata, &encoder->private->frame))
441 return encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000442
Josh Coalson0a15c142001-06-13 17:59:57 +0000443 if(0 != encoder->protected->seek_table) {
444 if(!FLAC__seek_table_is_valid(encoder->protected->seek_table))
445 return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_SEEK_TABLE;
446 seek_table_block.type = FLAC__METADATA_TYPE_SEEKTABLE;
447 seek_table_block.is_last = (encoder->protected->padding == 0);
448 seek_table_block.length = encoder->protected->seek_table->num_points * FLAC__STREAM_METADATA_SEEKPOINT_LEN;
449 seek_table_block.data.seek_table = *encoder->protected->seek_table;
450 if(!FLAC__add_metadata_block(&seek_table_block, &encoder->private->frame))
451 return encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson0a72e182001-04-13 19:17:16 +0000452 }
453
Josh Coalsonc692d382001-02-23 21:05:05 +0000454 /* add a PADDING block if requested */
Josh Coalson0a15c142001-06-13 17:59:57 +0000455 if(encoder->protected->padding > 0) {
456 padding_block.type = FLAC__METADATA_TYPE_PADDING;
457 padding_block.is_last = true;
458 padding_block.length = encoder->protected->padding;
459 if(!FLAC__add_metadata_block(&padding_block, &encoder->private->frame))
460 return encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalsonc692d382001-02-23 21:05:05 +0000461 }
462
Josh Coalson0a15c142001-06-13 17:59:57 +0000463 FLAC__ASSERT(encoder->private->frame.bits == 0); /* assert that we're byte-aligned before writing */
464 FLAC__ASSERT(encoder->private->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
465 if(encoder->private->write_callback(encoder, encoder->private->frame.buffer, encoder->private->frame.bytes, 0, encoder->private->current_frame_number, encoder->private->client_data) != FLAC__STREAM_ENCODER_WRITE_OK)
466 return encoder->protected->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000467
Josh Coalsoncbbbb5f2001-01-23 00:41:48 +0000468 /* now that the metadata block is written, we can init this to an absurdly-high value... */
Josh Coalson0a15c142001-06-13 17:59:57 +0000469 encoder->private->metadata.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
Josh Coalsoncbbbb5f2001-01-23 00:41:48 +0000470 /* ... and clear this to 0 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000471 encoder->private->metadata.data.stream_info.total_samples = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000472
Josh Coalson0a15c142001-06-13 17:59:57 +0000473 return encoder->protected->state;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000474}
475
Josh Coalson0a15c142001-06-13 17:59:57 +0000476void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000477{
Josh Coalson94e02cd2001-01-25 10:41:06 +0000478 unsigned i, channel;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000479
Josh Coalson1b689822001-05-31 20:11:02 +0000480 FLAC__ASSERT(encoder != 0);
Josh Coalson0a15c142001-06-13 17:59:57 +0000481 if(encoder->protected->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000482 return;
Josh Coalson0a15c142001-06-13 17:59:57 +0000483 if(encoder->private->current_sample_number != 0) {
484 encoder->protected->blocksize = encoder->private->current_sample_number;
485 stream_encoder_process_frame_(encoder, true); /* true => is last frame */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000486 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000487 MD5Final(encoder->private->metadata.data.stream_info.md5sum, &encoder->private->md5context);
488 encoder->private->metadata_callback(encoder, &encoder->private->metadata, encoder->private->client_data);
489 for(i = 0; i < encoder->protected->channels; i++) {
490 if(encoder->private->integer_signal_unaligned[i] != 0) {
491 free(encoder->private->integer_signal_unaligned[i]);
492 encoder->private->integer_signal_unaligned[i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000493 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000494 if(encoder->private->real_signal_unaligned[i] != 0) {
495 free(encoder->private->real_signal_unaligned[i]);
496 encoder->private->real_signal_unaligned[i] = 0;
497 }
498 }
499 for(i = 0; i < 2; i++) {
500 if(encoder->private->integer_signal_mid_side_unaligned[i] != 0) {
501 free(encoder->private->integer_signal_mid_side_unaligned[i]);
502 encoder->private->integer_signal_mid_side_unaligned[i] = 0;
503 }
504 if(encoder->private->real_signal_mid_side_unaligned[i] != 0) {
505 free(encoder->private->real_signal_mid_side_unaligned[i]);
506 encoder->private->real_signal_mid_side_unaligned[i] = 0;
507 }
508 }
509 for(channel = 0; channel < encoder->protected->channels; channel++) {
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000510 for(i = 0; i < 2; i++) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000511 if(encoder->private->residual_workspace_unaligned[channel][i] != 0) {
512 free(encoder->private->residual_workspace_unaligned[channel][i]);
513 encoder->private->residual_workspace_unaligned[channel][i] = 0;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000514 }
515 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000516 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000517 for(channel = 0; channel < 2; channel++) {
518 for(i = 0; i < 2; i++) {
519 if(encoder->private->residual_workspace_mid_side_unaligned[channel][i] != 0) {
520 free(encoder->private->residual_workspace_mid_side_unaligned[channel][i]);
521 encoder->private->residual_workspace_mid_side_unaligned[channel][i] = 0;
522 }
523 }
524 }
525 if(encoder->private->abs_residual_unaligned != 0) {
526 free(encoder->private->abs_residual_unaligned);
527 encoder->private->abs_residual_unaligned = 0;
528 }
529 if(encoder->private->abs_residual_partition_sums_unaligned != 0) {
530 free(encoder->private->abs_residual_partition_sums_unaligned);
531 encoder->private->abs_residual_partition_sums_unaligned = 0;
532 }
533 if(encoder->private->raw_bits_per_partition_unaligned != 0) {
534 free(encoder->private->raw_bits_per_partition_unaligned);
535 encoder->private->raw_bits_per_partition_unaligned = 0;
536 }
537 FLAC__bitbuffer_free(&encoder->private->frame);
538
539 encoder->protected->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000540}
541
Josh Coalson0a15c142001-06-13 17:59:57 +0000542FLAC__StreamEncoderState FLAC__stream_encoder_state(const FLAC__StreamEncoder *encoder)
543{
544 return encoder->protected->state;
545}
546
547bool FLAC__stream_encoder_streamable_subset(const FLAC__StreamEncoder *encoder)
548{
549 return encoder->protected->streamable_subset;
550}
551
552bool FLAC__stream_encoder_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
553{
554 return encoder->protected->do_mid_side_stereo;
555}
556
557bool FLAC__stream_encoder_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
558{
559 return encoder->protected->loose_mid_side_stereo;
560}
561
562unsigned FLAC__stream_encoder_channels(const FLAC__StreamEncoder *encoder)
563{
564 return encoder->protected->channels;
565}
566
567unsigned FLAC__stream_encoder_bits_per_sample(const FLAC__StreamEncoder *encoder)
568{
569 return encoder->protected->bits_per_sample;
570}
571
572unsigned FLAC__stream_encoder_sample_rate(const FLAC__StreamEncoder *encoder)
573{
574 return encoder->protected->sample_rate;
575}
576
577unsigned FLAC__stream_encoder_blocksize(const FLAC__StreamEncoder *encoder)
578{
579 return encoder->protected->blocksize;
580}
581
582unsigned FLAC__stream_encoder_max_lpc_order(const FLAC__StreamEncoder *encoder)
583{
584 return encoder->protected->max_lpc_order;
585}
586
587unsigned FLAC__stream_encoder_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
588{
589 return encoder->protected->qlp_coeff_precision;
590}
591
592bool FLAC__stream_encoder_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
593{
594 return encoder->protected->do_qlp_coeff_prec_search;
595}
596
597bool FLAC__stream_encoder_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
598{
599 return encoder->protected->do_exhaustive_model_search;
600}
601
602unsigned FLAC__stream_encoder_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
603{
604 return encoder->protected->min_residual_partition_order;
605}
606
607unsigned FLAC__stream_encoder_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
608{
609 return encoder->protected->max_residual_partition_order;
610}
611
612unsigned FLAC__stream_encoder_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
613{
614 return encoder->protected->rice_parameter_search_dist;
615}
616
617bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const int32 *buf[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000618{
619 unsigned i, j, channel;
620 int32 x, mid, side;
Josh Coalson0a15c142001-06-13 17:59:57 +0000621 const unsigned channels = encoder->protected->channels, blocksize = encoder->protected->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000622
Josh Coalson1b689822001-05-31 20:11:02 +0000623 FLAC__ASSERT(encoder != 0);
Josh Coalson0a15c142001-06-13 17:59:57 +0000624 FLAC__ASSERT(encoder->protected->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000625
626 j = 0;
Josh Coalson0a15c142001-06-13 17:59:57 +0000627 if(encoder->protected->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +0000628 do {
Josh Coalson0a15c142001-06-13 17:59:57 +0000629 for(i = encoder->private->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +0000630 x = mid = side = buf[0][j];
Josh Coalson0a15c142001-06-13 17:59:57 +0000631 encoder->private->integer_signal[0][i] = x;
632 encoder->private->real_signal[0][i] = (real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +0000633 x = buf[1][j];
Josh Coalson0a15c142001-06-13 17:59:57 +0000634 encoder->private->integer_signal[1][i] = x;
635 encoder->private->real_signal[1][i] = (real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +0000636 mid += x;
637 side -= x;
638 mid >>= 1; /* NOTE: not the same as 'mid = (buf[0][j] + buf[1][j]) / 2' ! */
Josh Coalson0a15c142001-06-13 17:59:57 +0000639 encoder->private->integer_signal_mid_side[1][i] = side;
640 encoder->private->integer_signal_mid_side[0][i] = mid;
641 encoder->private->real_signal_mid_side[1][i] = (real)side;
642 encoder->private->real_signal_mid_side[0][i] = (real)mid;
643 encoder->private->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000644 }
Josh Coalsonaa255362001-05-31 06:17:41 +0000645 if(i == blocksize) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000646 if(!stream_encoder_process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +0000647 return false;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000648 }
Josh Coalsonaa255362001-05-31 06:17:41 +0000649 } while(j < samples);
650 }
651 else {
652 do {
Josh Coalson0a15c142001-06-13 17:59:57 +0000653 for(i = encoder->private->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +0000654 for(channel = 0; channel < channels; channel++) {
655 x = buf[channel][j];
Josh Coalson0a15c142001-06-13 17:59:57 +0000656 encoder->private->integer_signal[channel][i] = x;
657 encoder->private->real_signal[channel][i] = (real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +0000658 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000659 encoder->private->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +0000660 }
661 if(i == blocksize) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000662 if(!stream_encoder_process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +0000663 return false;
664 }
665 } while(j < samples);
666 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000667
668 return true;
669}
670
671/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
Josh Coalson0a15c142001-06-13 17:59:57 +0000672bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const int32 buf[], unsigned samples)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000673{
674 unsigned i, j, k, channel;
Josh Coalsonaa255362001-05-31 06:17:41 +0000675 int32 x, mid, side;
Josh Coalson0a15c142001-06-13 17:59:57 +0000676 const unsigned channels = encoder->protected->channels, blocksize = encoder->protected->blocksize;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000677
Josh Coalson1b689822001-05-31 20:11:02 +0000678 FLAC__ASSERT(encoder != 0);
Josh Coalson0a15c142001-06-13 17:59:57 +0000679 FLAC__ASSERT(encoder->protected->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000680
681 j = k = 0;
Josh Coalson0a15c142001-06-13 17:59:57 +0000682 if(encoder->protected->do_mid_side_stereo && channels == 2) {
Josh Coalsonaa255362001-05-31 06:17:41 +0000683 do {
Josh Coalson0a15c142001-06-13 17:59:57 +0000684 for(i = encoder->private->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +0000685 x = mid = side = buf[k++];
Josh Coalson0a15c142001-06-13 17:59:57 +0000686 encoder->private->integer_signal[0][i] = x;
687 encoder->private->real_signal[0][i] = (real)x;
Josh Coalsond37d1352001-05-30 23:09:31 +0000688 x = buf[k++];
Josh Coalson0a15c142001-06-13 17:59:57 +0000689 encoder->private->integer_signal[1][i] = x;
690 encoder->private->real_signal[1][i] = (real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +0000691 mid += x;
692 side -= x;
693 mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */
Josh Coalson0a15c142001-06-13 17:59:57 +0000694 encoder->private->integer_signal_mid_side[1][i] = side;
695 encoder->private->integer_signal_mid_side[0][i] = mid;
696 encoder->private->real_signal_mid_side[1][i] = (real)side;
697 encoder->private->real_signal_mid_side[0][i] = (real)mid;
698 encoder->private->current_sample_number++;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000699 }
Josh Coalsonaa255362001-05-31 06:17:41 +0000700 if(i == blocksize) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000701 if(!stream_encoder_process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +0000702 return false;
703 }
704 } while(j < samples);
705 }
706 else {
707 do {
Josh Coalson0a15c142001-06-13 17:59:57 +0000708 for(i = encoder->private->current_sample_number; i < blocksize && j < samples; i++, j++) {
Josh Coalsonaa255362001-05-31 06:17:41 +0000709 for(channel = 0; channel < channels; channel++) {
710 x = buf[k++];
Josh Coalson0a15c142001-06-13 17:59:57 +0000711 encoder->private->integer_signal[channel][i] = x;
712 encoder->private->real_signal[channel][i] = (real)x;
Josh Coalsonaa255362001-05-31 06:17:41 +0000713 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000714 encoder->private->current_sample_number++;
Josh Coalsonaa255362001-05-31 06:17:41 +0000715 }
716 if(i == blocksize) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000717 if(!stream_encoder_process_frame_(encoder, false)) /* false => not last frame */
Josh Coalsonaa255362001-05-31 06:17:41 +0000718 return false;
719 }
720 } while(j < samples);
721 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000722
723 return true;
724}
725
Josh Coalson0a15c142001-06-13 17:59:57 +0000726bool stream_encoder_resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000727{
Josh Coalson0a15c142001-06-13 17:59:57 +0000728 bool ok;
729 unsigned i, channel;
730
731 FLAC__ASSERT(new_size > 0);
732 FLAC__ASSERT(encoder->protected->state == FLAC__STREAM_ENCODER_OK);
733 FLAC__ASSERT(encoder->private->current_sample_number == 0);
734
735 /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
736 if(new_size <= encoder->private->input_capacity)
737 return true;
738
739 ok = true;
740 for(i = 0; ok && i < encoder->protected->channels; i++) {
741 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->private->integer_signal_unaligned[i], &encoder->private->integer_signal[i]);
742 ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private->real_signal_unaligned[i], &encoder->private->real_signal[i]);
743 }
744 for(i = 0; ok && i < 2; i++) {
745 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->private->integer_signal_mid_side_unaligned[i], &encoder->private->integer_signal_mid_side[i]);
746 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]);
747 }
748 for(channel = 0; ok && channel < encoder->protected->channels; channel++) {
749 for(i = 0; ok && i < 2; i++) {
750 ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->private->residual_workspace_unaligned[channel][i], &encoder->private->residual_workspace[channel][i]);
751 }
752 }
753 for(channel = 0; ok && channel < 2; channel++) {
754 for(i = 0; ok && i < 2; i++) {
755 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]);
756 }
757 }
758 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->private->abs_residual_unaligned, &encoder->private->abs_residual);
759#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
760 ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size * 2, &encoder->private->abs_residual_partition_sums_unaligned, &encoder->private->abs_residual_partition_sums);
761#endif
762#ifdef FLAC__SEARCH_FOR_ESCAPES
763 ok = ok && FLAC__memory_alloc_aligned_unsigned_array(new_size * 2, &encoder->private->raw_bits_per_partition_unaligned, &encoder->private->raw_bits_per_partition);
764#endif
765
766 if(ok)
767 encoder->private->input_capacity = new_size;
768 else
769 encoder->protected->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
770
771 return ok;
772}
773
774/***********************************************************************
775 *
776 * Private class methods
777 *
778 ***********************************************************************/
779
780bool stream_encoder_process_frame_(FLAC__StreamEncoder *encoder, bool is_last_frame)
781{
782 FLAC__ASSERT(encoder->protected->state == FLAC__STREAM_ENCODER_OK);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000783
784 /*
Josh Coalsonfa37f1c2001-01-12 23:55:11 +0000785 * Accumulate raw signal to the MD5 signature
786 */
Josh Coalsoneae4dde2001-04-16 05:33:22 +0000787 /* NOTE: some versions of GCC can't figure out const-ness right and will give you an 'incompatible pointer type' warning on arg 2 here: */
Josh Coalson0a15c142001-06-13 17:59:57 +0000788 if(!FLAC__MD5Accumulate(&encoder->private->md5context, encoder->private->integer_signal, encoder->protected->channels, encoder->protected->blocksize, (encoder->protected->bits_per_sample+7) / 8)) {
789 encoder->protected->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonfa37f1c2001-01-12 23:55:11 +0000790 return false;
791 }
792
793 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +0000794 * Process the frame header and subframes into the frame bitbuffer
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000795 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000796 if(!stream_encoder_process_subframes_(encoder, is_last_frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +0000797 /* the above function sets the state for us in case of an error */
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000798 return false;
799 }
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000800
801 /*
802 * Zero-pad the frame to a byte_boundary
803 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000804 if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(&encoder->private->frame)) {
805 encoder->protected->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000806 return false;
807 }
808
809 /*
Josh Coalson215af572001-03-27 01:15:58 +0000810 * CRC-16 the whole thing
811 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000812 FLAC__ASSERT(encoder->private->frame.bits == 0); /* assert that we're byte-aligned */
813 FLAC__ASSERT(encoder->private->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
814 FLAC__bitbuffer_write_raw_uint32(&encoder->private->frame, FLAC__crc16(encoder->private->frame.buffer, encoder->private->frame.bytes), FLAC__FRAME_FOOTER_CRC_LEN);
Josh Coalson215af572001-03-27 01:15:58 +0000815
816 /*
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000817 * Write it
818 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000819 if(encoder->private->write_callback(encoder, encoder->private->frame.buffer, encoder->private->frame.bytes, encoder->protected->blocksize, encoder->private->current_frame_number, encoder->private->client_data) != FLAC__STREAM_ENCODER_WRITE_OK) {
820 encoder->protected->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000821 return false;
822 }
823
824 /*
825 * Get ready for the next frame
826 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000827 encoder->private->current_sample_number = 0;
828 encoder->private->current_frame_number++;
829 encoder->private->metadata.data.stream_info.total_samples += (uint64)encoder->protected->blocksize;
830 encoder->private->metadata.data.stream_info.min_framesize = min(encoder->private->frame.bytes, encoder->private->metadata.data.stream_info.min_framesize);
831 encoder->private->metadata.data.stream_info.max_framesize = max(encoder->private->frame.bytes, encoder->private->metadata.data.stream_info.max_framesize);
Josh Coalsonbb7f6b92000-12-10 04:09:52 +0000832
833 return true;
834}
835
Josh Coalson0a15c142001-06-13 17:59:57 +0000836bool stream_encoder_process_subframes_(FLAC__StreamEncoder *encoder, bool is_last_frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +0000837{
838 FLAC__FrameHeader frame_header;
Josh Coalson0a15c142001-06-13 17:59:57 +0000839 unsigned channel, min_partition_order = encoder->protected->min_residual_partition_order, max_partition_order;
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000840 bool do_independent, do_mid_side;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000841
842 /*
Josh Coalson60f77d72001-04-25 02:16:36 +0000843 * Calculate the min,max Rice partition orders
Josh Coalson94e02cd2001-01-25 10:41:06 +0000844 */
845 if(is_last_frame) {
846 max_partition_order = 0;
847 }
848 else {
Josh Coalson0a15c142001-06-13 17:59:57 +0000849 unsigned limit = 0, b = encoder->protected->blocksize;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000850 while(!(b & 1)) {
851 limit++;
852 b >>= 1;
853 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000854 max_partition_order = min(encoder->protected->max_residual_partition_order, limit);
Josh Coalson94e02cd2001-01-25 10:41:06 +0000855 }
Josh Coalson60f77d72001-04-25 02:16:36 +0000856 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson94e02cd2001-01-25 10:41:06 +0000857
858 /*
859 * Setup the frame
860 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000861 if(!FLAC__bitbuffer_clear(&encoder->private->frame)) {
862 encoder->protected->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000863 return false;
864 }
Josh Coalson0a15c142001-06-13 17:59:57 +0000865 frame_header.blocksize = encoder->protected->blocksize;
866 frame_header.sample_rate = encoder->protected->sample_rate;
867 frame_header.channels = encoder->protected->channels;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000868 frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
Josh Coalson0a15c142001-06-13 17:59:57 +0000869 frame_header.bits_per_sample = encoder->protected->bits_per_sample;
870 frame_header.number.frame_number = encoder->private->current_frame_number;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000871
872 /*
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000873 * Figure out what channel assignments to try
874 */
Josh Coalson0a15c142001-06-13 17:59:57 +0000875 if(encoder->protected->do_mid_side_stereo) {
876 if(encoder->protected->loose_mid_side_stereo) {
877 if(encoder->private->loose_mid_side_stereo_frame_count == 0) {
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000878 do_independent = true;
879 do_mid_side = true;
880 }
881 else {
Josh Coalson0a15c142001-06-13 17:59:57 +0000882 do_independent = (encoder->private->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000883 do_mid_side = !do_independent;
884 }
885 }
886 else {
887 do_independent = true;
888 do_mid_side = true;
889 }
890 }
891 else {
892 do_independent = true;
893 do_mid_side = false;
894 }
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000895
Josh Coalson1b689822001-05-31 20:11:02 +0000896 FLAC__ASSERT(do_independent || do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000897
898 /*
Josh Coalson82b73242001-03-28 22:17:05 +0000899 * Check for wasted bits; set effective bps for each subframe
Josh Coalson859bc542001-03-27 22:22:27 +0000900 */
901 if(do_independent) {
Josh Coalson82b73242001-03-28 22:17:05 +0000902 unsigned w;
Josh Coalson0a15c142001-06-13 17:59:57 +0000903 for(channel = 0; channel < encoder->protected->channels; channel++) {
904 w = stream_encoder_get_wasted_bits_(encoder->private->integer_signal[channel], encoder->protected->blocksize);
905 encoder->private->subframe_workspace[channel][0].wasted_bits = encoder->private->subframe_workspace[channel][1].wasted_bits = w;
906 encoder->private->subframe_bps[channel] = encoder->protected->bits_per_sample - w;
Josh Coalson82b73242001-03-28 22:17:05 +0000907 }
Josh Coalson859bc542001-03-27 22:22:27 +0000908 }
909 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +0000910 unsigned w;
Josh Coalson0a15c142001-06-13 17:59:57 +0000911 FLAC__ASSERT(encoder->protected->channels == 2);
Josh Coalson82b73242001-03-28 22:17:05 +0000912 for(channel = 0; channel < 2; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000913 w = stream_encoder_get_wasted_bits_(encoder->private->integer_signal_mid_side[channel], encoder->protected->blocksize);
914 encoder->private->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private->subframe_workspace_mid_side[channel][1].wasted_bits = w;
915 encoder->private->subframe_bps_mid_side[channel] = encoder->protected->bits_per_sample - w + (channel==0? 0:1);
Josh Coalson82b73242001-03-28 22:17:05 +0000916 }
Josh Coalson859bc542001-03-27 22:22:27 +0000917 }
918
919 /*
Josh Coalson94e02cd2001-01-25 10:41:06 +0000920 * First do a normal encoding pass of each independent channel
921 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000922 if(do_independent) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000923 for(channel = 0; channel < encoder->protected->channels; channel++) {
924 if(!stream_encoder_process_subframe_(encoder, min_partition_order, max_partition_order, false, &frame_header, encoder->private->subframe_bps[channel], encoder->private->integer_signal[channel], encoder->private->real_signal[channel], encoder->private->subframe_workspace_ptr[channel], encoder->private->residual_workspace[channel], encoder->private->best_subframe+channel, encoder->private->best_subframe_bits+channel))
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000925 return false;
926 }
Josh Coalson94e02cd2001-01-25 10:41:06 +0000927 }
928
929 /*
930 * Now do mid and side channels if requested
931 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000932 if(do_mid_side) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000933 FLAC__ASSERT(encoder->protected->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +0000934
935 for(channel = 0; channel < 2; channel++) {
Josh Coalson0a15c142001-06-13 17:59:57 +0000936 if(!stream_encoder_process_subframe_(encoder, min_partition_order, max_partition_order, false, &frame_header, encoder->private->subframe_bps_mid_side[channel], encoder->private->integer_signal_mid_side[channel], encoder->private->real_signal_mid_side[channel], encoder->private->subframe_workspace_ptr_mid_side[channel], encoder->private->residual_workspace_mid_side[channel], encoder->private->best_subframe_mid_side+channel, encoder->private->best_subframe_bits_mid_side+channel))
Josh Coalson94e02cd2001-01-25 10:41:06 +0000937 return false;
938 }
939 }
940
941 /*
942 * Compose the frame bitbuffer
943 */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000944 if(do_mid_side) {
Josh Coalson82b73242001-03-28 22:17:05 +0000945 unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
946 FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000947 FLAC__ChannelAssignment channel_assignment;
948
Josh Coalson0a15c142001-06-13 17:59:57 +0000949 FLAC__ASSERT(encoder->protected->channels == 2);
Josh Coalson94e02cd2001-01-25 10:41:06 +0000950
Josh Coalson0a15c142001-06-13 17:59:57 +0000951 if(encoder->protected->loose_mid_side_stereo && encoder->private->loose_mid_side_stereo_frame_count > 0) {
952 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 +0000953 }
954 else {
955 unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
956 unsigned min_bits;
957 FLAC__ChannelAssignment ca;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000958
Josh Coalson1b689822001-05-31 20:11:02 +0000959 FLAC__ASSERT(do_independent && do_mid_side);
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000960
961 /* We have to figure out which channel assignent results in the smallest frame */
Josh Coalson0a15c142001-06-13 17:59:57 +0000962 bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private->best_subframe_bits [0] + encoder->private->best_subframe_bits [1];
963 bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private->best_subframe_bits [0] + encoder->private->best_subframe_bits_mid_side[1];
964 bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private->best_subframe_bits [1] + encoder->private->best_subframe_bits_mid_side[1];
965 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 +0000966
967 for(channel_assignment = 0, min_bits = bits[0], ca = 1; ca <= 3; ca++) {
968 if(bits[ca] < min_bits) {
969 min_bits = bits[ca];
970 channel_assignment = ca;
971 }
Josh Coalson94e02cd2001-01-25 10:41:06 +0000972 }
973 }
974
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000975 frame_header.channel_assignment = channel_assignment;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000976
Josh Coalson0a15c142001-06-13 17:59:57 +0000977 if(!FLAC__frame_add_header(&frame_header, encoder->protected->streamable_subset, is_last_frame, &encoder->private->frame)) {
978 encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +0000979 return false;
980 }
981
Josh Coalsonb5e60e52001-01-28 09:27:27 +0000982 switch(channel_assignment) {
Josh Coalson94e02cd2001-01-25 10:41:06 +0000983 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalson0a15c142001-06-13 17:59:57 +0000984 left_subframe = &encoder->private->subframe_workspace [0][encoder->private->best_subframe [0]];
985 right_subframe = &encoder->private->subframe_workspace [1][encoder->private->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000986 break;
987 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalson0a15c142001-06-13 17:59:57 +0000988 left_subframe = &encoder->private->subframe_workspace [0][encoder->private->best_subframe [0]];
989 right_subframe = &encoder->private->subframe_workspace_mid_side[1][encoder->private->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000990 break;
991 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalson0a15c142001-06-13 17:59:57 +0000992 left_subframe = &encoder->private->subframe_workspace_mid_side[1][encoder->private->best_subframe_mid_side[1]];
993 right_subframe = &encoder->private->subframe_workspace [1][encoder->private->best_subframe [1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000994 break;
995 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalson0a15c142001-06-13 17:59:57 +0000996 left_subframe = &encoder->private->subframe_workspace_mid_side[0][encoder->private->best_subframe_mid_side[0]];
997 right_subframe = &encoder->private->subframe_workspace_mid_side[1][encoder->private->best_subframe_mid_side[1]];
Josh Coalson94e02cd2001-01-25 10:41:06 +0000998 break;
999 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001000 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001001 }
Josh Coalson82b73242001-03-28 22:17:05 +00001002
1003 switch(channel_assignment) {
1004 case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
Josh Coalson0a15c142001-06-13 17:59:57 +00001005 left_bps = encoder->private->subframe_bps [0];
1006 right_bps = encoder->private->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001007 break;
1008 case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
Josh Coalson0a15c142001-06-13 17:59:57 +00001009 left_bps = encoder->private->subframe_bps [0];
1010 right_bps = encoder->private->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001011 break;
1012 case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
Josh Coalson0a15c142001-06-13 17:59:57 +00001013 left_bps = encoder->private->subframe_bps_mid_side[1];
1014 right_bps = encoder->private->subframe_bps [1];
Josh Coalson82b73242001-03-28 22:17:05 +00001015 break;
1016 case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
Josh Coalson0a15c142001-06-13 17:59:57 +00001017 left_bps = encoder->private->subframe_bps_mid_side[0];
1018 right_bps = encoder->private->subframe_bps_mid_side[1];
Josh Coalson82b73242001-03-28 22:17:05 +00001019 break;
1020 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001021 FLAC__ASSERT(0);
Josh Coalson82b73242001-03-28 22:17:05 +00001022 }
1023
1024 /* note that encoder_add_subframe_ sets the state for us in case of an error */
Josh Coalson0a15c142001-06-13 17:59:57 +00001025 if(!stream_encoder_add_subframe_(encoder, &frame_header, left_bps , left_subframe , &encoder->private->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001026 return false;
Josh Coalson0a15c142001-06-13 17:59:57 +00001027 if(!stream_encoder_add_subframe_(encoder, &frame_header, right_bps, right_subframe, &encoder->private->frame))
Josh Coalson82b73242001-03-28 22:17:05 +00001028 return false;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001029 }
1030 else {
Josh Coalson0a15c142001-06-13 17:59:57 +00001031 if(!FLAC__frame_add_header(&frame_header, encoder->protected->streamable_subset, is_last_frame, &encoder->private->frame)) {
1032 encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001033 return false;
1034 }
1035
Josh Coalson0a15c142001-06-13 17:59:57 +00001036 for(channel = 0; channel < encoder->protected->channels; channel++) {
1037 if(!stream_encoder_add_subframe_(encoder, &frame_header, encoder->private->subframe_bps[channel], &encoder->private->subframe_workspace[channel][encoder->private->best_subframe[channel]], &encoder->private->frame)) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001038 /* the above function sets the state for us in case of an error */
1039 return false;
1040 }
1041 }
1042 }
1043
Josh Coalson0a15c142001-06-13 17:59:57 +00001044 if(encoder->protected->loose_mid_side_stereo) {
1045 encoder->private->loose_mid_side_stereo_frame_count++;
1046 if(encoder->private->loose_mid_side_stereo_frame_count >= encoder->private->loose_mid_side_stereo_frames)
1047 encoder->private->loose_mid_side_stereo_frame_count = 0;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001048 }
1049
Josh Coalson0a15c142001-06-13 17:59:57 +00001050 encoder->private->last_channel_assignment = frame_header.channel_assignment;
Josh Coalsonb5e60e52001-01-28 09:27:27 +00001051
Josh Coalson94e02cd2001-01-25 10:41:06 +00001052 return true;
1053}
1054
Josh Coalson0a15c142001-06-13 17:59:57 +00001055bool stream_encoder_process_subframe_(FLAC__StreamEncoder *encoder, unsigned min_partition_order, unsigned max_partition_order, bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const int32 integer_signal[], const real real_signal[], FLAC__Subframe *subframe[2], int32 *residual[2], unsigned *best_subframe, unsigned *best_bits)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001056{
1057 real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
1058 real lpc_residual_bits_per_sample;
Josh Coalson0a15c142001-06-13 17:59:57 +00001059 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 Coalson94e02cd2001-01-25 10:41:06 +00001060 real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER];
1061 real lpc_error[FLAC__MAX_LPC_ORDER];
1062 unsigned min_lpc_order, max_lpc_order, lpc_order;
1063 unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
1064 unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
1065 unsigned rice_parameter;
1066 unsigned _candidate_bits, _best_bits;
1067 unsigned _best_subframe;
1068
1069 /* verbatim subframe is the baseline against which we measure other compressed subframes */
1070 _best_subframe = 0;
Josh Coalson0a15c142001-06-13 17:59:57 +00001071 _best_bits = stream_encoder_evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001072
1073 if(!verbatim_only && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
1074 /* check for constant subframe */
Josh Coalson0a15c142001-06-13 17:59:57 +00001075 if(encoder->private->use_slow)
Josh Coalsoneef56702001-03-30 00:45:22 +00001076 guess_fixed_order = FLAC__fixed_compute_best_predictor_slow(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample);
1077 else
Josh Coalson0a15c142001-06-13 17:59:57 +00001078 guess_fixed_order = encoder->private->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001079 if(fixed_residual_bits_per_sample[1] == 0.0) {
1080 /* the above means integer_signal+FLAC__MAX_FIXED_ORDER is constant, now we just have to check the warmup samples */
1081 unsigned i, signal_is_constant = true;
1082 for(i = 1; i <= FLAC__MAX_FIXED_ORDER; i++) {
1083 if(integer_signal[0] != integer_signal[i]) {
1084 signal_is_constant = false;
1085 break;
1086 }
1087 }
1088 if(signal_is_constant) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001089 _candidate_bits = stream_encoder_evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001090 if(_candidate_bits < _best_bits) {
1091 _best_subframe = !_best_subframe;
1092 _best_bits = _candidate_bits;
1093 }
1094 }
1095 }
1096 else {
1097 /* encode fixed */
Josh Coalson0a15c142001-06-13 17:59:57 +00001098 if(encoder->protected->do_exhaustive_model_search) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001099 min_fixed_order = 0;
1100 max_fixed_order = FLAC__MAX_FIXED_ORDER;
1101 }
1102 else {
1103 min_fixed_order = max_fixed_order = guess_fixed_order;
1104 }
1105 for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
Josh Coalson82b73242001-03-28 22:17:05 +00001106 if(fixed_residual_bits_per_sample[fixed_order] >= (real)subframe_bps)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001107 continue; /* don't even try */
Josh Coalson46f2ae82001-02-08 00:27:21 +00001108 rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > 0.0)? (unsigned)(fixed_residual_bits_per_sample[fixed_order]+0.5) : 0; /* 0.5 is for rounding */
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001109#ifndef FLAC__SYMMETRIC_RICE
Josh Coalson46f2ae82001-02-08 00:27:21 +00001110 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00001111#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001112 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
1113 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson0a15c142001-06-13 17:59:57 +00001114 _candidate_bits = stream_encoder_evaluate_fixed_subframe_(integer_signal, residual[!_best_subframe], encoder->private->abs_residual, encoder->private->abs_residual_partition_sums, encoder->private->raw_bits_per_partition, frame_header->blocksize, subframe_bps, fixed_order, rice_parameter, min_partition_order, max_partition_order, encoder->protected->rice_parameter_search_dist, subframe[!_best_subframe]);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001115 if(_candidate_bits < _best_bits) {
1116 _best_subframe = !_best_subframe;
1117 _best_bits = _candidate_bits;
1118 }
1119 }
1120
1121 /* encode lpc */
Josh Coalson0a15c142001-06-13 17:59:57 +00001122 if(encoder->protected->max_lpc_order > 0) {
1123 if(encoder->protected->max_lpc_order >= frame_header->blocksize)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001124 max_lpc_order = frame_header->blocksize-1;
1125 else
Josh Coalson0a15c142001-06-13 17:59:57 +00001126 max_lpc_order = encoder->protected->max_lpc_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001127 if(max_lpc_order > 0) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001128 encoder->private->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001129 /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
1130 if(autoc[0] != 0.0) {
1131 FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, lp_coeff, lpc_error);
Josh Coalson0a15c142001-06-13 17:59:57 +00001132 if(encoder->protected->do_exhaustive_model_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001133 min_lpc_order = 1;
1134 }
1135 else {
Josh Coalson82b73242001-03-28 22:17:05 +00001136 unsigned guess_lpc_order = FLAC__lpc_compute_best_order(lpc_error, max_lpc_order, frame_header->blocksize, subframe_bps);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001137 min_lpc_order = max_lpc_order = guess_lpc_order;
1138 }
Josh Coalson0a15c142001-06-13 17:59:57 +00001139 if(encoder->protected->do_qlp_coeff_prec_search) {
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001140 min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
Josh Coalson82b73242001-03-28 22:17:05 +00001141 max_qlp_coeff_precision = min(32 - subframe_bps - 1, (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)-1);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001142 }
1143 else {
Josh Coalson0a15c142001-06-13 17:59:57 +00001144 min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected->qlp_coeff_precision;
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001145 }
1146 for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
1147 lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order);
Josh Coalson82b73242001-03-28 22:17:05 +00001148 if(lpc_residual_bits_per_sample >= (real)subframe_bps)
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001149 continue; /* don't even try */
1150 rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001151#ifndef FLAC__SYMMETRIC_RICE
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001152 rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
Josh Coalsonb9433f92001-03-17 01:07:00 +00001153#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001154 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
1155 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001156 for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001157 _candidate_bits = stream_encoder_evaluate_lpc_subframe_(encoder, integer_signal, residual[!_best_subframe], encoder->private->abs_residual, encoder->private->abs_residual_partition_sums, encoder->private->raw_bits_per_partition, lp_coeff[lpc_order-1], frame_header->blocksize, subframe_bps, lpc_order, qlp_coeff_precision, rice_parameter, min_partition_order, max_partition_order, encoder->protected->rice_parameter_search_dist, subframe[!_best_subframe]);
Josh Coalsonf4ce50b2001-02-28 23:45:15 +00001158 if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
1159 if(_candidate_bits < _best_bits) {
1160 _best_subframe = !_best_subframe;
1161 _best_bits = _candidate_bits;
1162 }
Josh Coalson94e02cd2001-01-25 10:41:06 +00001163 }
1164 }
1165 }
1166 }
1167 }
1168 }
1169 }
1170 }
1171
1172 *best_subframe = _best_subframe;
1173 *best_bits = _best_bits;
1174
1175 return true;
1176}
1177
Josh Coalson0a15c142001-06-13 17:59:57 +00001178bool stream_encoder_add_subframe_(FLAC__StreamEncoder *encoder, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const FLAC__Subframe *subframe, FLAC__BitBuffer *frame)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001179{
1180 switch(subframe->type) {
1181 case FLAC__SUBFRAME_TYPE_CONSTANT:
Josh Coalson82b73242001-03-28 22:17:05 +00001182 if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001183 encoder->protected->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001184 return false;
1185 }
1186 break;
1187 case FLAC__SUBFRAME_TYPE_FIXED:
Josh Coalson82b73242001-03-28 22:17:05 +00001188 if(!FLAC__subframe_add_fixed(&(subframe->data.fixed), frame_header->blocksize - subframe->data.fixed.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001189 encoder->protected->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001190 return false;
1191 }
1192 break;
1193 case FLAC__SUBFRAME_TYPE_LPC:
Josh Coalson82b73242001-03-28 22:17:05 +00001194 if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), frame_header->blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001195 encoder->protected->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001196 return false;
1197 }
1198 break;
1199 case FLAC__SUBFRAME_TYPE_VERBATIM:
Josh Coalson82b73242001-03-28 22:17:05 +00001200 if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001201 encoder->protected->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001202 return false;
1203 }
1204 break;
1205 default:
Josh Coalson1b689822001-05-31 20:11:02 +00001206 FLAC__ASSERT(0);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001207 }
1208
1209 return true;
1210}
1211
Josh Coalson0a15c142001-06-13 17:59:57 +00001212unsigned stream_encoder_evaluate_constant_subframe_(const int32 signal, unsigned subframe_bps, FLAC__Subframe *subframe)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001213{
1214 subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
1215 subframe->data.constant.value = signal;
1216
Josh Coalson82b73242001-03-28 22:17:05 +00001217 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 +00001218}
1219
Josh Coalson0a15c142001-06-13 17:59:57 +00001220unsigned stream_encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001221{
1222 unsigned i, residual_bits;
1223 const unsigned residual_samples = blocksize - order;
1224
1225 FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
1226
1227 subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
1228
1229 subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
1230 subframe->data.fixed.residual = residual;
1231
Josh Coalson0a15c142001-06-13 17:59:57 +00001232 residual_bits = stream_encoder_find_best_partition_order_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, order, rice_parameter, min_partition_order, max_partition_order, rice_parameter_search_dist, &subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.raw_bits);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001233
1234 subframe->data.fixed.order = order;
1235 for(i = 0; i < order; i++)
1236 subframe->data.fixed.warmup[i] = signal[i];
1237
Josh Coalson82b73242001-03-28 22:17:05 +00001238 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 +00001239}
1240
Josh Coalson0a15c142001-06-13 17:59:57 +00001241unsigned stream_encoder_evaluate_lpc_subframe_(FLAC__StreamEncoder *encoder, const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], const real lp_coeff[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001242{
1243 int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
1244 unsigned i, residual_bits;
1245 int quantization, ret;
1246 const unsigned residual_samples = blocksize - order;
1247
Josh Coalson82b73242001-03-28 22:17:05 +00001248 ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, subframe_bps, qlp_coeff, &quantization);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001249 if(ret != 0)
1250 return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
1251
Josh Coalson92d42402001-05-31 20:53:19 +00001252 if(subframe_bps <= 16 && qlp_coeff_precision <= 16)
Josh Coalson0a15c142001-06-13 17:59:57 +00001253 encoder->private->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalson92d42402001-05-31 20:53:19 +00001254 else
Josh Coalson0a15c142001-06-13 17:59:57 +00001255 encoder->private->local_lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001256
1257 subframe->type = FLAC__SUBFRAME_TYPE_LPC;
1258
1259 subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
1260 subframe->data.lpc.residual = residual;
1261
Josh Coalson0a15c142001-06-13 17:59:57 +00001262 residual_bits = stream_encoder_find_best_partition_order_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, order, rice_parameter, min_partition_order, max_partition_order, rice_parameter_search_dist, &subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.raw_bits);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001263
1264 subframe->data.lpc.order = order;
1265 subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
1266 subframe->data.lpc.quantization_level = quantization;
1267 memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(int32)*FLAC__MAX_LPC_ORDER);
1268 for(i = 0; i < order; i++)
1269 subframe->data.lpc.warmup[i] = signal[i];
1270
Josh Coalson82b73242001-03-28 22:17:05 +00001271 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 +00001272}
1273
Josh Coalson0a15c142001-06-13 17:59:57 +00001274unsigned stream_encoder_evaluate_verbatim_subframe_(const int32 signal[], unsigned blocksize, unsigned subframe_bps, FLAC__Subframe *subframe)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001275{
1276 subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
1277
1278 subframe->data.verbatim.data = signal;
1279
Josh Coalson82b73242001-03-28 22:17:05 +00001280 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 +00001281}
1282
Josh Coalson0a15c142001-06-13 17:59:57 +00001283unsigned stream_encoder_find_best_partition_order_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, unsigned *best_partition_order, unsigned best_parameters[], unsigned best_raw_bits[])
Josh Coalson94e02cd2001-01-25 10:41:06 +00001284{
Josh Coalson94e02cd2001-01-25 10:41:06 +00001285 int32 r;
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001286#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
Josh Coalsonafcd8772001-04-18 22:59:25 +00001287 unsigned sum;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001288 int partition_order;
Josh Coalsonafcd8772001-04-18 22:59:25 +00001289#else
1290 unsigned partition_order;
1291#endif
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001292 unsigned residual_bits, best_residual_bits = 0;
Josh Coalsonafcd8772001-04-18 22:59:25 +00001293 unsigned residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001294 unsigned best_parameters_index = 0, parameters[2][1 << FLAC__MAX_RICE_PARTITION_ORDER], raw_bits[2][1 << FLAC__MAX_RICE_PARTITION_ORDER];
Josh Coalson94e02cd2001-01-25 10:41:06 +00001295
Josh Coalson2051dd42001-04-12 22:22:34 +00001296 /* compute abs(residual) for use later */
1297 for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
1298 r = residual[residual_sample];
1299 abs_residual[residual_sample] = (uint32)(r<0? -r : r);
1300 }
1301
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001302#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
Josh Coalson0a15c142001-06-13 17:59:57 +00001303 max_partition_order = stream_encoder_precompute_partition_info_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, predictor_order, min_partition_order, max_partition_order);
Josh Coalson60f77d72001-04-25 02:16:36 +00001304 min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001305
Josh Coalson60f77d72001-04-25 02:16:36 +00001306 for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001307 if(!stream_encoder_set_partitioned_rice_(abs_residual, abs_residual_partition_sums+sum, raw_bits_per_partition+sum, residual_samples, predictor_order, rice_parameter, rice_parameter_search_dist, (unsigned)partition_order, parameters[!best_parameters_index], raw_bits[!best_parameters_index], &residual_bits)) {
1308 FLAC__ASSERT(0); /* stream_encoder_precompute_partition_info_ should keep this from ever happening */
Josh Coalson94e02cd2001-01-25 10:41:06 +00001309 }
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001310 sum += 1u << partition_order;
1311 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
1312 best_residual_bits = residual_bits;
1313 *best_partition_order = partition_order;
1314 best_parameters_index = !best_parameters_index;
1315 }
1316 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00001317#else
Josh Coalson60f77d72001-04-25 02:16:36 +00001318 for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
Josh Coalson0a15c142001-06-13 17:59:57 +00001319 if(!stream_encoder_set_partitioned_rice_(abs_residual, 0, 0, residual_samples, predictor_order, rice_parameter, rice_parameter_search_dist, partition_order, parameters[!best_parameters_index], raw_bits[!best_parameters_index], &residual_bits)) {
Josh Coalson1b689822001-05-31 20:11:02 +00001320 FLAC__ASSERT(best_residual_bits != 0);
Josh Coalsonafcd8772001-04-18 22:59:25 +00001321 break;
1322 }
1323 if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
1324 best_residual_bits = residual_bits;
1325 *best_partition_order = partition_order;
1326 best_parameters_index = !best_parameters_index;
1327 }
1328 }
1329#endif
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001330 memcpy(best_parameters, parameters[best_parameters_index], sizeof(unsigned)*(1<<(*best_partition_order)));
1331 memcpy(best_raw_bits, raw_bits[best_parameters_index], sizeof(unsigned)*(1<<(*best_partition_order)));
1332
1333 return best_residual_bits;
1334}
1335
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001336#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
Josh Coalson0a15c142001-06-13 17:59:57 +00001337unsigned stream_encoder_precompute_partition_info_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order)
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001338{
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001339 int partition_order;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001340 unsigned from_partition, to_partition = 0;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001341 const unsigned blocksize = residual_samples + predictor_order;
1342
Josh Coalsonaef013c2001-04-24 01:25:42 +00001343 /* first do max_partition_order */
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001344 for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001345#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001346 uint32 abs_residual_partition_sum;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001347#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001348#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001349 uint32 abs_residual_partition_max;
1350 unsigned abs_residual_partition_max_index = 0; /* initialized to silence superfluous compiler warning */
1351#endif
1352 uint32 abs_r;
1353 unsigned partition, partition_sample, partition_samples, residual_sample;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001354 const unsigned partitions = 1u << partition_order;
1355 const unsigned default_partition_samples = blocksize >> partition_order;
1356
1357 if(default_partition_samples <= predictor_order) {
Josh Coalson1b689822001-05-31 20:11:02 +00001358 FLAC__ASSERT(max_partition_order > 0);
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001359 max_partition_order--;
1360 }
1361 else {
1362 for(partition = residual_sample = 0; partition < partitions; partition++) {
1363 partition_samples = default_partition_samples;
1364 if(partition == 0)
1365 partition_samples -= predictor_order;
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001366#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001367 abs_residual_partition_sum = 0;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001368#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001369#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001370 abs_residual_partition_max = 0;
1371#endif
1372 for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
1373 abs_r = abs_residual[residual_sample];
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001374#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsonaef013c2001-04-24 01:25:42 +00001375 abs_residual_partition_sum += abs_r; /* @@@ this can overflow with small max_partition_order and (large blocksizes or bits-per-sample), FIX! */
1376#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001377#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001378 if(abs_r > abs_residual_partition_max) {
1379 abs_residual_partition_max = abs_r;
1380 abs_residual_partition_max_index = residual_sample;
1381 }
1382#endif
1383 residual_sample++;
1384 }
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001385#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001386 abs_residual_partition_sums[partition] = abs_residual_partition_sum;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001387#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001388#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001389 if(abs_residual_partition_max > 0)
1390 raw_bits_per_partition[partition] = FLAC__bitmath_silog2(residual[abs_residual_partition_max_index]);
1391 else
1392 raw_bits_per_partition[partition] = FLAC__bitmath_silog2(0);
1393#endif
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001394 }
Josh Coalsonaef013c2001-04-24 01:25:42 +00001395 to_partition = partitions;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001396 break;
1397 }
1398 }
Josh Coalsonf76a3612001-04-18 02:28:11 +00001399
Josh Coalsonaef013c2001-04-24 01:25:42 +00001400 /* now merge for lower orders */
Josh Coalson6bd17572001-05-25 19:02:01 +00001401 for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001402#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001403 uint32 s;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001404#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001405#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001406 unsigned m;
1407#endif
1408 unsigned i;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001409 const unsigned partitions = 1u << partition_order;
1410 for(i = 0; i < partitions; i++) {
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001411#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsonaef013c2001-04-24 01:25:42 +00001412 s = abs_residual_partition_sums[from_partition];
1413#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001414#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001415 m = raw_bits_per_partition[from_partition];
1416#endif
1417 from_partition++;
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001418#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalsonaef013c2001-04-24 01:25:42 +00001419 abs_residual_partition_sums[to_partition] = s + abs_residual_partition_sums[from_partition];
1420#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001421#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001422 raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]);
1423#endif
1424 from_partition++;
1425 to_partition++;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001426 }
1427 }
1428
Josh Coalsonf76a3612001-04-18 02:28:11 +00001429 return max_partition_order;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001430}
Josh Coalsonafcd8772001-04-18 22:59:25 +00001431#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00001432
Josh Coalson352e0f62001-03-20 22:55:50 +00001433#ifdef VARIABLE_RICE_BITS
1434#undef VARIABLE_RICE_BITS
1435#endif
1436#define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
1437
Josh Coalson0a15c142001-06-13 17:59:57 +00001438bool stream_encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, const unsigned suggested_rice_parameter, const unsigned rice_parameter_search_dist, const unsigned partition_order, unsigned parameters[], unsigned raw_bits[], unsigned *bits)
Josh Coalson94e02cd2001-01-25 10:41:06 +00001439{
Josh Coalson034dfab2001-04-27 19:10:23 +00001440 unsigned rice_parameter, partition_bits;
1441#ifndef NO_RICE_SEARCH
1442 unsigned best_partition_bits;
1443 unsigned min_rice_parameter, max_rice_parameter, best_rice_parameter = 0;
1444#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001445#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalsonaef013c2001-04-24 01:25:42 +00001446 unsigned flat_bits;
Josh Coalsonafcd8772001-04-18 22:59:25 +00001447#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00001448 unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN;
1449
Josh Coalson1b689822001-05-31 20:11:02 +00001450 FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER);
Josh Coalson2051dd42001-04-12 22:22:34 +00001451
Josh Coalson94e02cd2001-01-25 10:41:06 +00001452 if(partition_order == 0) {
1453 unsigned i;
Josh Coalson352e0f62001-03-20 22:55:50 +00001454
Josh Coalson034dfab2001-04-27 19:10:23 +00001455#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00001456 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00001457 if(suggested_rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00001458 min_rice_parameter = 0;
1459 else
Josh Coalson034dfab2001-04-27 19:10:23 +00001460 min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist;
1461 max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist;
Josh Coalson60f77d72001-04-25 02:16:36 +00001462 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
1463 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
1464 }
1465 else
Josh Coalson034dfab2001-04-27 19:10:23 +00001466 min_rice_parameter = max_rice_parameter = suggested_rice_parameter;
Josh Coalson2051dd42001-04-12 22:22:34 +00001467
Josh Coalson034dfab2001-04-27 19:10:23 +00001468 best_partition_bits = 0xffffffff;
1469 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
1470#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00001471#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001472#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00001473 partition_bits = (2+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00001474#else
Josh Coalson352e0f62001-03-20 22:55:50 +00001475 const unsigned rice_parameter_estimate = rice_parameter-1;
Josh Coalson034dfab2001-04-27 19:10:23 +00001476 partition_bits = (1+rice_parameter) * residual_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00001477#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001478#else
1479 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001480#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00001481 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson352e0f62001-03-20 22:55:50 +00001482 for(i = 0; i < residual_samples; i++) {
1483#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001484#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson2051dd42001-04-12 22:22:34 +00001485 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001486#else
Josh Coalson2051dd42001-04-12 22:22:34 +00001487 partition_bits += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00001488#endif
1489#else
Josh Coalson2051dd42001-04-12 22:22:34 +00001490 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 +00001491#endif
Josh Coalson2051dd42001-04-12 22:22:34 +00001492 }
Josh Coalson034dfab2001-04-27 19:10:23 +00001493#ifndef NO_RICE_SEARCH
1494 if(partition_bits < best_partition_bits) {
1495 best_rice_parameter = rice_parameter;
1496 best_partition_bits = partition_bits;
Josh Coalson352e0f62001-03-20 22:55:50 +00001497 }
1498 }
Josh Coalson034dfab2001-04-27 19:10:23 +00001499#endif
1500#ifdef FLAC__SEARCH_FOR_ESCAPES
1501 flat_bits = raw_bits_per_partition[0] * residual_samples;
1502 if(flat_bits <= best_partition_bits) {
1503 raw_bits[0] = raw_bits_per_partition[0];
1504 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
1505 best_partition_bits = flat_bits;
1506 }
1507#endif
1508 parameters[0] = best_rice_parameter;
1509 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001510 }
1511 else {
Josh Coalson4dacd192001-06-06 21:11:44 +00001512 unsigned partition, residual_sample, save_residual_sample, partition_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00001513 unsigned mean, partition_samples;
Josh Coalsond4e0ddb2001-04-18 02:20:52 +00001514 const unsigned partitions = 1u << partition_order;
Josh Coalson4dacd192001-06-06 21:11:44 +00001515 for(partition = residual_sample = 0; partition < partitions; partition++) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001516 partition_samples = (residual_samples+predictor_order) >> partition_order;
Josh Coalson034dfab2001-04-27 19:10:23 +00001517 if(partition == 0) {
Josh Coalson94e02cd2001-01-25 10:41:06 +00001518 if(partition_samples <= predictor_order)
1519 return false;
1520 else
1521 partition_samples -= predictor_order;
1522 }
1523 mean = partition_samples >> 1;
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001524#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
Josh Coalson034dfab2001-04-27 19:10:23 +00001525 mean += abs_residual_partition_sums[partition];
Josh Coalsonaef013c2001-04-24 01:25:42 +00001526#else
Josh Coalson4dacd192001-06-06 21:11:44 +00001527 save_residual_sample = residual_sample;
1528 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++)
1529 mean += abs_residual[residual_sample];
1530 residual_sample = save_residual_sample;
Josh Coalsonaef013c2001-04-24 01:25:42 +00001531#endif
Josh Coalson94e02cd2001-01-25 10:41:06 +00001532 mean /= partition_samples;
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001533#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00001534 /* calc rice_parameter = floor(log2(mean)) */
1535 rice_parameter = 0;
1536 mean>>=1;
Josh Coalsonb9433f92001-03-17 01:07:00 +00001537 while(mean) {
Josh Coalson034dfab2001-04-27 19:10:23 +00001538 rice_parameter++;
Josh Coalsonb9433f92001-03-17 01:07:00 +00001539 mean >>= 1;
1540 }
Josh Coalsonb9433f92001-03-17 01:07:00 +00001541#else
Josh Coalson034dfab2001-04-27 19:10:23 +00001542 /* calc rice_parameter = floor(log2(mean)) + 1 */
1543 rice_parameter = 0;
Josh Coalson352e0f62001-03-20 22:55:50 +00001544 while(mean) {
Josh Coalson034dfab2001-04-27 19:10:23 +00001545 rice_parameter++;
Josh Coalson352e0f62001-03-20 22:55:50 +00001546 mean >>= 1;
1547 }
Josh Coalsonb9433f92001-03-17 01:07:00 +00001548#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001549 if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
1550 rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
Josh Coalson60f77d72001-04-25 02:16:36 +00001551
Josh Coalson034dfab2001-04-27 19:10:23 +00001552#ifndef NO_RICE_SEARCH
Josh Coalson60f77d72001-04-25 02:16:36 +00001553 if(rice_parameter_search_dist) {
Josh Coalson034dfab2001-04-27 19:10:23 +00001554 if(rice_parameter < rice_parameter_search_dist)
Josh Coalson60f77d72001-04-25 02:16:36 +00001555 min_rice_parameter = 0;
1556 else
Josh Coalson034dfab2001-04-27 19:10:23 +00001557 min_rice_parameter = rice_parameter - rice_parameter_search_dist;
1558 max_rice_parameter = rice_parameter + rice_parameter_search_dist;
Josh Coalson60f77d72001-04-25 02:16:36 +00001559 if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
1560 max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
1561 }
1562 else
1563 min_rice_parameter = max_rice_parameter = rice_parameter;
Josh Coalson60f77d72001-04-25 02:16:36 +00001564
Josh Coalson034dfab2001-04-27 19:10:23 +00001565 best_partition_bits = 0xffffffff;
1566 for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) {
1567#endif
Josh Coalson352e0f62001-03-20 22:55:50 +00001568#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001569#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson034dfab2001-04-27 19:10:23 +00001570 partition_bits = (2+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00001571#else
Josh Coalson034dfab2001-04-27 19:10:23 +00001572 const unsigned rice_parameter_estimate = rice_parameter-1;
1573 partition_bits = (1+rice_parameter) * partition_samples;
Josh Coalsonb9433f92001-03-17 01:07:00 +00001574#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001575#else
1576 partition_bits = 0;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001577#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001578 partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
Josh Coalson4dacd192001-06-06 21:11:44 +00001579 save_residual_sample = residual_sample;
1580 for(partition_sample = 0; partition_sample < partition_samples; residual_sample++, partition_sample++) {
Josh Coalson352e0f62001-03-20 22:55:50 +00001581#ifdef VARIABLE_RICE_BITS
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001582#ifdef FLAC__SYMMETRIC_RICE
Josh Coalson4dacd192001-06-06 21:11:44 +00001583 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter);
Josh Coalson94e02cd2001-01-25 10:41:06 +00001584#else
Josh Coalson4dacd192001-06-06 21:11:44 +00001585 partition_bits += VARIABLE_RICE_BITS(abs_residual[residual_sample], rice_parameter_estimate);
Josh Coalsonb9433f92001-03-17 01:07:00 +00001586#endif
1587#else
Josh Coalson4dacd192001-06-06 21:11:44 +00001588 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 +00001589#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001590 }
Josh Coalson034dfab2001-04-27 19:10:23 +00001591#ifndef NO_RICE_SEARCH
Josh Coalson4dacd192001-06-06 21:11:44 +00001592 if(rice_parameter != max_rice_parameter)
1593 residual_sample = save_residual_sample;
Josh Coalson034dfab2001-04-27 19:10:23 +00001594 if(partition_bits < best_partition_bits) {
1595 best_rice_parameter = rice_parameter;
1596 best_partition_bits = partition_bits;
1597 }
Josh Coalson2051dd42001-04-12 22:22:34 +00001598 }
Josh Coalson034dfab2001-04-27 19:10:23 +00001599#endif
Josh Coalsonbb6712e2001-04-24 22:54:07 +00001600#ifdef FLAC__SEARCH_FOR_ESCAPES
Josh Coalson034dfab2001-04-27 19:10:23 +00001601 flat_bits = raw_bits_per_partition[partition] * partition_samples;
1602 if(flat_bits <= best_partition_bits) {
1603 raw_bits[partition] = raw_bits_per_partition[partition];
1604 best_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
1605 best_partition_bits = flat_bits;
Josh Coalson2051dd42001-04-12 22:22:34 +00001606 }
Josh Coalsonafcd8772001-04-18 22:59:25 +00001607#endif
Josh Coalson034dfab2001-04-27 19:10:23 +00001608 parameters[partition] = best_rice_parameter;
1609 bits_ += best_partition_bits;
Josh Coalson94e02cd2001-01-25 10:41:06 +00001610 }
1611 }
1612
1613 *bits = bits_;
1614 return true;
1615}
Josh Coalson859bc542001-03-27 22:22:27 +00001616
Josh Coalson0a15c142001-06-13 17:59:57 +00001617unsigned stream_encoder_get_wasted_bits_(int32 signal[], unsigned samples)
Josh Coalson859bc542001-03-27 22:22:27 +00001618{
1619 unsigned i, shift;
1620 int32 x = 0;
1621
1622 for(i = 0; i < samples && !(x&1); i++)
1623 x |= signal[i];
1624
1625 if(x == 0) {
1626 shift = 0;
1627 }
1628 else {
1629 for(shift = 0; !(x&1); shift++)
1630 x >>= 1;
1631 }
1632
1633 if(shift > 0) {
1634 for(i = 0; i < samples; i++)
1635 signal[i] >>= shift;
1636 }
1637
1638 return shift;
1639}
Josh Coalson0a15c142001-06-13 17:59:57 +00001640