encoder.c 63.9 KB
Newer Older
1
/* libFLAC - Free Lossless Audio Codec library
Josh Coalson's avatar
Josh Coalson committed
2
 * Copyright (C) 2000,2001  Josh Coalson
Josh Coalson's avatar
Josh Coalson committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for memcpy() */
24
#include "FLAC/config.h"
Josh Coalson's avatar
Josh Coalson committed
25
#include "FLAC/encoder.h"
26
#include "FLAC/seek_table.h"
Josh Coalson's avatar
Josh Coalson committed
27
#include "private/bitbuffer.h"
28
#include "private/bitmath.h"
29
#include "private/crc.h"
30
#include "private/cpu.h"
Josh Coalson's avatar
Josh Coalson committed
31
32
33
#include "private/encoder_framing.h"
#include "private/fixed.h"
#include "private/lpc.h"
Josh Coalson's avatar
Josh Coalson committed
34
#include "private/md5.h"
35
#include "private/memory.h"
Josh Coalson's avatar
Josh Coalson committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#ifdef min
#undef min
#endif
#define min(x,y) ((x)<(y)?(x):(y))

#ifdef max
#undef max
#endif
#define max(x,y) ((x)>(y)?(x):(y))

typedef struct FLAC__EncoderPrivate {
	unsigned input_capacity;                    /* current size (in samples) of the signal and residual buffers */
	int32 *integer_signal[FLAC__MAX_CHANNELS];  /* the integer version of the input signal */
	int32 *integer_signal_mid_side[2];          /* the integer version of the mid-side input signal (stereo only) */
	real *real_signal[FLAC__MAX_CHANNELS];      /* the floating-point version of the input signal */
	real *real_signal_mid_side[2];              /* the floating-point version of the mid-side input signal (stereo only) */
53
	unsigned subframe_bps[FLAC__MAX_CHANNELS];  /* the effective bits per sample of the input signal (stream bps - wasted bits) */
Josh Coalson's avatar
Josh Coalson committed
54
	unsigned subframe_bps_mid_side[2];          /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */
Josh Coalson's avatar
Josh Coalson committed
55
56
57
58
59
60
61
62
63
64
	int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
	int32 *residual_workspace_mid_side[2][2];
	FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
	FLAC__Subframe subframe_workspace_mid_side[2][2];
	FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
	FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
	unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index into the above workspaces */
	unsigned best_subframe_mid_side[2];
	unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */
	unsigned best_subframe_bits_mid_side[2];
65
	uint32 *abs_residual;                       /* workspace where abs(candidate residual) is stored */
66
	uint32 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
67
	unsigned *raw_bits_per_partition;           /* workspace where the sum of silog2(candidate residual) for each partition is stored */
Josh Coalson's avatar
Josh Coalson committed
68
69
	FLAC__BitBuffer frame;                      /* the current frame being worked on */
	bool current_frame_can_do_mid_side;         /* encoder sets this false when any given sample of a frame's side channel exceeds 16 bits */
70
71
72
73
	double loose_mid_side_stereo_frames_exact;  /* exact number of frames the encoder will use before trying both independent and mid/side frames again */
	unsigned loose_mid_side_stereo_frames;      /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
	unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
	FLAC__ChannelAssignment last_channel_assignment;
Josh Coalson's avatar
Josh Coalson committed
74
75
76
	FLAC__StreamMetaData metadata;
	unsigned current_sample_number;
	unsigned current_frame_number;
Josh Coalson's avatar
Josh Coalson committed
77
	struct MD5Context md5context;
78
79
80
	FLAC__CPUInfo cpuinfo;
	unsigned (*local_fixed_compute_best_predictor)(const int32 data[], unsigned data_len, real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
	void (*local_lpc_compute_autocorrelation)(const real data[], unsigned data_len, unsigned lag, real autoc[]);
81
	bool use_slow;                              /* use slow 64-bit versions of some functions */
Josh Coalson's avatar
Josh Coalson committed
82
83
84
	FLAC__EncoderWriteStatus (*write_callback)(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
	void (*metadata_callback)(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data);
	void *client_data;
85
86
87
88
89
90
91
92
93
94
	/* unaligned (original) pointers to allocated data */
	int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
	int32 *integer_signal_mid_side_unaligned[2];
	real *real_signal_unaligned[FLAC__MAX_CHANNELS];
	real *real_signal_mid_side_unaligned[2];
	int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
	int32 *residual_workspace_mid_side_unaligned[2][2];
	uint32 *abs_residual_unaligned;
	uint32 *abs_residual_partition_sums_unaligned;
	unsigned *raw_bits_per_partition_unaligned;
Josh Coalson's avatar
Josh Coalson committed
95
96
97
98
} FLAC__EncoderPrivate;

static bool encoder_resize_buffers_(FLAC__Encoder *encoder, unsigned new_size);
static bool encoder_process_frame_(FLAC__Encoder *encoder, bool is_last_frame);
Josh Coalson's avatar
Josh Coalson committed
99
static bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame);
100
static bool encoder_process_subframe_(FLAC__Encoder *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);
101
102
static bool encoder_add_subframe_(FLAC__Encoder *encoder, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const FLAC__Subframe *subframe, FLAC__BitBuffer *frame);
static unsigned encoder_evaluate_constant_subframe_(const int32 signal, unsigned subframe_bps, FLAC__Subframe *subframe);
103
104
static unsigned 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);
static unsigned encoder_evaluate_lpc_subframe_(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);
105
static unsigned encoder_evaluate_verbatim_subframe_(const int32 signal[], unsigned blocksize, unsigned subframe_bps, FLAC__Subframe *subframe);
106
static unsigned 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 Coalson's avatar
Josh Coalson committed
107
#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
108
static unsigned 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);
109
#endif
110
static bool 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);
111
static unsigned encoder_get_wasted_bits_(int32 signal[], unsigned samples);
Josh Coalson's avatar
Josh Coalson committed
112

Josh Coalson's avatar
Josh Coalson committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const char *FLAC__EncoderWriteStatusString[] = {
	"FLAC__ENCODER_WRITE_OK",
	"FLAC__ENCODER_WRITE_FATAL_ERROR"
};

const char *FLAC__EncoderStateString[] = {
	"FLAC__ENCODER_OK",
	"FLAC__ENCODER_UNINITIALIZED",
	"FLAC__ENCODER_INVALID_NUMBER_OF_CHANNELS",
	"FLAC__ENCODER_INVALID_BITS_PER_SAMPLE",
	"FLAC__ENCODER_INVALID_SAMPLE_RATE",
	"FLAC__ENCODER_INVALID_BLOCK_SIZE",
	"FLAC__ENCODER_INVALID_QLP_COEFF_PRECISION",
	"FLAC__ENCODER_MID_SIDE_CHANNELS_MISMATCH",
	"FLAC__ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
128
	"FLAC__ENCODER_ILLEGAL_MID_SIDE_FORCE",
Josh Coalson's avatar
Josh Coalson committed
129
130
131
132
133
134
135
136
	"FLAC__ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
	"FLAC__ENCODER_NOT_STREAMABLE",
	"FLAC__ENCODER_FRAMING_ERROR",
	"FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING",
	"FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING",
	"FLAC__ENCODER_MEMORY_ALLOCATION_ERROR"
};

Josh Coalson's avatar
Josh Coalson committed
137
138
139
140

bool encoder_resize_buffers_(FLAC__Encoder *encoder, unsigned new_size)
{
	bool ok;
Josh Coalson's avatar
Josh Coalson committed
141
	unsigned i, channel;
Josh Coalson's avatar
Josh Coalson committed
142
143
144
145
146
147
148
149
150

	assert(new_size > 0);
	assert(encoder->state == FLAC__ENCODER_OK);
	assert(encoder->guts->current_sample_number == 0);

	/* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
	if(new_size <= encoder->guts->input_capacity)
		return true;

151
152
153
154
155
156
157
158
	ok = true;
	for(i = 0; ok && i < encoder->channels; i++) {
		ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->guts->integer_signal_unaligned[i], &encoder->guts->integer_signal[i]);
		ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->guts->real_signal_unaligned[i], &encoder->guts->real_signal[i]);
	}
	for(i = 0; ok && i < 2; i++) {
		ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->guts->integer_signal_mid_side_unaligned[i], &encoder->guts->integer_signal_mid_side[i]);
		ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->guts->real_signal_mid_side_unaligned[i], &encoder->guts->real_signal_mid_side[i]);
Josh Coalson's avatar
Josh Coalson committed
159
	}
160
	for(channel = 0; ok && channel < encoder->channels; channel++) {
Josh Coalson's avatar
Josh Coalson committed
161
		for(i = 0; ok && i < 2; i++) {
162
			ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->guts->residual_workspace_unaligned[channel][i], &encoder->guts->residual_workspace[channel][i]);
Josh Coalson's avatar
Josh Coalson committed
163
164
		}
	}
165
166
167
	for(channel = 0; ok && channel < 2; channel++) {
		for(i = 0; ok && i < 2; i++) {
			ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->guts->residual_workspace_mid_side_unaligned[channel][i], &encoder->guts->residual_workspace_mid_side[channel][i]);
Josh Coalson's avatar
Josh Coalson committed
168
		}
169
170
	}
	ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size, &encoder->guts->abs_residual_unaligned, &encoder->guts->abs_residual);
Josh Coalson's avatar
Josh Coalson committed
171
#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
172
	ok = ok && FLAC__memory_alloc_aligned_uint32_array(new_size * 2, &encoder->guts->abs_residual_partition_sums_unaligned, &encoder->guts->abs_residual_partition_sums);
173
#endif
Josh Coalson's avatar
Josh Coalson committed
174
#ifdef FLAC__SEARCH_FOR_ESCAPES
175
	ok = ok && FLAC__memory_alloc_aligned_unsigned_array(new_size * 2, &encoder->guts->raw_bits_per_partition_unaligned, &encoder->guts->raw_bits_per_partition);
176
#endif
177

Josh Coalson's avatar
Josh Coalson committed
178
179
	if(ok)
		encoder->guts->input_capacity = new_size;
180
181
	else
		encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

	return ok;
}

FLAC__Encoder *FLAC__encoder_get_new_instance()
{
	FLAC__Encoder *encoder = (FLAC__Encoder*)malloc(sizeof(FLAC__Encoder));
	if(encoder != 0) {
		encoder->state = FLAC__ENCODER_UNINITIALIZED;
		encoder->guts = 0;
	}
	return encoder;
}

void FLAC__encoder_free_instance(FLAC__Encoder *encoder)
{
	assert(encoder != 0);
	free(encoder);
}

FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWriteStatus (*write_callback)(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data), void (*metadata_callback)(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data), void *client_data)
{
	unsigned i;
205
	FLAC__StreamMetaData padding;
206
	FLAC__StreamMetaData seek_table;
Josh Coalson's avatar
Josh Coalson committed
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

	assert(sizeof(int) >= 4); /* we want to die right away if this is not true */
	assert(encoder != 0);
	assert(write_callback != 0);
	assert(metadata_callback != 0);
	assert(encoder->state == FLAC__ENCODER_UNINITIALIZED);
	assert(encoder->guts == 0);

	encoder->state = FLAC__ENCODER_OK;

	if(encoder->channels == 0 || encoder->channels > FLAC__MAX_CHANNELS)
		return encoder->state = FLAC__ENCODER_INVALID_NUMBER_OF_CHANNELS;

	if(encoder->do_mid_side_stereo && encoder->channels != 2)
		return encoder->state = FLAC__ENCODER_MID_SIDE_CHANNELS_MISMATCH;

223
	if(encoder->loose_mid_side_stereo && !encoder->do_mid_side_stereo)
224
225
		return encoder->state = FLAC__ENCODER_ILLEGAL_MID_SIDE_FORCE;

226
	if(encoder->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->bits_per_sample > FLAC__MAX_BITS_PER_SAMPLE)
Josh Coalson's avatar
Josh Coalson committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
		return encoder->state = FLAC__ENCODER_INVALID_BITS_PER_SAMPLE;

	if(encoder->sample_rate == 0 || encoder->sample_rate > FLAC__MAX_SAMPLE_RATE)
		return encoder->state = FLAC__ENCODER_INVALID_SAMPLE_RATE;

	if(encoder->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->blocksize > FLAC__MAX_BLOCK_SIZE)
		return encoder->state = FLAC__ENCODER_INVALID_BLOCK_SIZE;

	if(encoder->blocksize < encoder->max_lpc_order)
		return encoder->state = FLAC__ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;

	if(encoder->qlp_coeff_precision == 0) {
		if(encoder->bits_per_sample < 16) {
			/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
			/* @@@ until then we'll make a guess */
			encoder->qlp_coeff_precision = max(5, 2 + encoder->bits_per_sample / 2);
		}
		else if(encoder->bits_per_sample == 16) {
			if(encoder->blocksize <= 192)
				encoder->qlp_coeff_precision = 7;
			else if(encoder->blocksize <= 384)
				encoder->qlp_coeff_precision = 8;
			else if(encoder->blocksize <= 576)
				encoder->qlp_coeff_precision = 9;
			else if(encoder->blocksize <= 1152)
				encoder->qlp_coeff_precision = 10;
			else if(encoder->blocksize <= 2304)
				encoder->qlp_coeff_precision = 11;
			else if(encoder->blocksize <= 4608)
				encoder->qlp_coeff_precision = 12;
			else
				encoder->qlp_coeff_precision = 13;
		}
		else {
			encoder->qlp_coeff_precision = min(13, 8*sizeof(int32) - encoder->bits_per_sample - 1);
		}
	}
264
	else if(encoder->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->qlp_coeff_precision + encoder->bits_per_sample >= 8*sizeof(uint32) || encoder->qlp_coeff_precision >= (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
Josh Coalson's avatar
Josh Coalson committed
265
266
267
		return encoder->state = FLAC__ENCODER_INVALID_QLP_COEFF_PRECISION;

	if(encoder->streamable_subset) {
268
		//@@@ add check for blocksize here
Josh Coalson's avatar
Josh Coalson committed
269
270
271
272
273
274
		if(encoder->bits_per_sample != 8 && encoder->bits_per_sample != 12 && encoder->bits_per_sample != 16 && encoder->bits_per_sample != 20 && encoder->bits_per_sample != 24)
			return encoder->state = FLAC__ENCODER_NOT_STREAMABLE;
		if(encoder->sample_rate > 655350)
			return encoder->state = FLAC__ENCODER_NOT_STREAMABLE;
	}

275
276
277
278
	if(encoder->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
		encoder->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
	if(encoder->min_residual_partition_order >= encoder->max_residual_partition_order)
		encoder->min_residual_partition_order = encoder->max_residual_partition_order;
Josh Coalson's avatar
Josh Coalson committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292

	encoder->guts = (FLAC__EncoderPrivate*)malloc(sizeof(FLAC__EncoderPrivate));
	if(encoder->guts == 0)
		return encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;

	encoder->guts->input_capacity = 0;
	for(i = 0; i < encoder->channels; i++) {
		encoder->guts->integer_signal[i] = 0;
		encoder->guts->real_signal[i] = 0;
	}
	for(i = 0; i < 2; i++) {
		encoder->guts->integer_signal_mid_side[i] = 0;
		encoder->guts->real_signal_mid_side[i] = 0;
	}
Josh Coalson's avatar
Josh Coalson committed
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
	for(i = 0; i < encoder->channels; i++) {
		encoder->guts->residual_workspace[i][0] = encoder->guts->residual_workspace[i][1] = 0;
		encoder->guts->best_subframe[i] = 0;
	}
	for(i = 0; i < 2; i++) {
		encoder->guts->residual_workspace_mid_side[i][0] = encoder->guts->residual_workspace_mid_side[i][1] = 0;
		encoder->guts->best_subframe_mid_side[i] = 0;
	}
	for(i = 0; i < encoder->channels; i++) {
		encoder->guts->subframe_workspace_ptr[i][0] = &encoder->guts->subframe_workspace[i][0];
		encoder->guts->subframe_workspace_ptr[i][1] = &encoder->guts->subframe_workspace[i][1];
	}
	for(i = 0; i < 2; i++) {
		encoder->guts->subframe_workspace_ptr_mid_side[i][0] = &encoder->guts->subframe_workspace_mid_side[i][0];
		encoder->guts->subframe_workspace_ptr_mid_side[i][1] = &encoder->guts->subframe_workspace_mid_side[i][1];
	}
Josh Coalson's avatar
Josh Coalson committed
309
	encoder->guts->abs_residual = 0;
310
	encoder->guts->abs_residual_partition_sums = 0;
311
	encoder->guts->raw_bits_per_partition = 0;
Josh Coalson's avatar
Josh Coalson committed
312
	encoder->guts->current_frame_can_do_mid_side = true;
313
314
315
316
317
	encoder->guts->loose_mid_side_stereo_frames_exact = (double)encoder->sample_rate * 0.4 / (double)encoder->blocksize;
	encoder->guts->loose_mid_side_stereo_frames = (unsigned)(encoder->guts->loose_mid_side_stereo_frames_exact + 0.5);
	if(encoder->guts->loose_mid_side_stereo_frames == 0)
		encoder->guts->loose_mid_side_stereo_frames = 1;
	encoder->guts->loose_mid_side_stereo_frame_count = 0;
Josh Coalson's avatar
Josh Coalson committed
318
319
320
	encoder->guts->current_sample_number = 0;
	encoder->guts->current_frame_number = 0;

321
322
323
324
325
326
327
328
329
330
331
	/*
	 * get the CPU info and set the function pointers
	 */
	FLAC__cpu_info(&encoder->guts->cpuinfo);
	/* first default to the non-asm routines */
	encoder->guts->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
	encoder->guts->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
	/* now override with asm where appropriate */
	if(encoder->guts->cpuinfo.use_asm) {
#ifdef FLAC__CPU_IA32
		assert(encoder->guts->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
332
#ifdef FLAC__HAS_NASM
333
334
335
336
337
338
339
340
341
342
343
344
#if 0
		/* @@@ SSE version not working yet */
		if(encoder->guts->cpuinfo.data.ia32.sse)
			encoder->guts->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386_sse;
		else
#endif
fprintf(stderr,"@@@ got _asm_i386 of lpc_compute_autocorrelation()\n");
			encoder->guts->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_i386;
		if(encoder->guts->cpuinfo.data.ia32.mmx && encoder->guts->cpuinfo.data.ia32.cmov)
{
			encoder->guts->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_i386_mmx_cmov;
fprintf(stderr,"@@@ got _asm_i386_mmx_cmov of fixed_compute_best_predictor()\n");}
345
#endif
346
347
348
#endif
	}

349
350
351
352
353
	if(encoder->bits_per_sample + FLAC__bitmath_ilog2(encoder->blocksize)+1 > 30)
		encoder->guts->use_slow = true;
	else
		encoder->guts->use_slow = false;

Josh Coalson's avatar
Josh Coalson committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
	if(!encoder_resize_buffers_(encoder, encoder->blocksize)) {
		/* the above function sets the state for us in case of an error */
		return encoder->state;
	}
	FLAC__bitbuffer_init(&encoder->guts->frame);
	encoder->guts->write_callback = write_callback;
	encoder->guts->metadata_callback = metadata_callback;
	encoder->guts->client_data = client_data;

	/*
	 * write the stream header
	 */
	if(!FLAC__bitbuffer_clear(&encoder->guts->frame))
		return encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;

	if(!FLAC__bitbuffer_write_raw_uint32(&encoder->guts->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
		return encoder->state = FLAC__ENCODER_FRAMING_ERROR;

372
	encoder->guts->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
373
	encoder->guts->metadata.is_last = (encoder->seek_table == 0 && encoder->padding == 0);
374
375
376
377
378
379
380
381
382
383
	encoder->guts->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
	encoder->guts->metadata.data.stream_info.min_blocksize = encoder->blocksize; /* this encoder uses the same blocksize for the whole stream */
	encoder->guts->metadata.data.stream_info.max_blocksize = encoder->blocksize;
	encoder->guts->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
	encoder->guts->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
	encoder->guts->metadata.data.stream_info.sample_rate = encoder->sample_rate;
	encoder->guts->metadata.data.stream_info.channels = encoder->channels;
	encoder->guts->metadata.data.stream_info.bits_per_sample = encoder->bits_per_sample;
	encoder->guts->metadata.data.stream_info.total_samples = encoder->total_samples_estimate; /* we will replace this later with the real total */
	memset(encoder->guts->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
Josh Coalson's avatar
Josh Coalson committed
384
	MD5Init(&encoder->guts->md5context);
Josh Coalson's avatar
Josh Coalson committed
385
386
387
	if(!FLAC__add_metadata_block(&encoder->guts->metadata, &encoder->guts->frame))
		return encoder->state = FLAC__ENCODER_FRAMING_ERROR;

388
389
390
391
392
393
394
395
396
397
398
	if(0 != encoder->seek_table) {
		if(!FLAC__seek_table_is_valid(encoder->seek_table))
			return encoder->state = FLAC__ENCODER_INVALID_SEEK_TABLE;
		seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE;
		seek_table.is_last = (encoder->padding == 0);
		seek_table.length = encoder->seek_table->num_points * FLAC__STREAM_METADATA_SEEKPOINT_LEN;
		seek_table.data.seek_table = *encoder->seek_table;
		if(!FLAC__add_metadata_block(&seek_table, &encoder->guts->frame))
			return encoder->state = FLAC__ENCODER_FRAMING_ERROR;
	}

399
400
401
402
403
404
405
406
407
	/* add a PADDING block if requested */
	if(encoder->padding > 0) {
		padding.type = FLAC__METADATA_TYPE_PADDING;
		padding.is_last = true;
		padding.length = encoder->padding;
		if(!FLAC__add_metadata_block(&padding, &encoder->guts->frame))
			return encoder->state = FLAC__ENCODER_FRAMING_ERROR;
	}

Josh Coalson's avatar
Josh Coalson committed
408
409
410
411
412
	assert(encoder->guts->frame.bits == 0); /* assert that we're byte-aligned before writing */
	assert(encoder->guts->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
	if(encoder->guts->write_callback(encoder, encoder->guts->frame.buffer, encoder->guts->frame.bytes, 0, encoder->guts->current_frame_number, encoder->guts->client_data) != FLAC__ENCODER_WRITE_OK)
		return encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING;

Josh Coalson's avatar
Josh Coalson committed
413
	/* now that the metadata block is written, we can init this to an absurdly-high value... */
414
	encoder->guts->metadata.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
Josh Coalson's avatar
Josh Coalson committed
415
	/* ... and clear this to 0 */
416
	encoder->guts->metadata.data.stream_info.total_samples = 0;
Josh Coalson's avatar
Josh Coalson committed
417
418
419
420
421
422

	return encoder->state;
}

void FLAC__encoder_finish(FLAC__Encoder *encoder)
{
Josh Coalson's avatar
Josh Coalson committed
423
	unsigned i, channel;
Josh Coalson's avatar
Josh Coalson committed
424
425
426
427
428
429
430
431

	assert(encoder != 0);
	if(encoder->state == FLAC__ENCODER_UNINITIALIZED)
		return;
	if(encoder->guts->current_sample_number != 0) {
		encoder->blocksize = encoder->guts->current_sample_number;
		encoder_process_frame_(encoder, true); /* true => is last frame */
	}
432
	MD5Final(encoder->guts->metadata.data.stream_info.md5sum, &encoder->guts->md5context);
Josh Coalson's avatar
Josh Coalson committed
433
434
435
	encoder->guts->metadata_callback(encoder, &encoder->guts->metadata, encoder->guts->client_data);
	if(encoder->guts != 0) {
		for(i = 0; i < encoder->channels; i++) {
Josh Coalson's avatar
Josh Coalson committed
436
437
438
			if(encoder->guts->integer_signal_unaligned[i] != 0) {
				free(encoder->guts->integer_signal_unaligned[i]);
				encoder->guts->integer_signal_unaligned[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
439
			}
Josh Coalson's avatar
Josh Coalson committed
440
441
442
			if(encoder->guts->real_signal_unaligned[i] != 0) {
				free(encoder->guts->real_signal_unaligned[i]);
				encoder->guts->real_signal_unaligned[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
443
444
445
			}
		}
		for(i = 0; i < 2; i++) {
Josh Coalson's avatar
Josh Coalson committed
446
447
448
			if(encoder->guts->integer_signal_mid_side_unaligned[i] != 0) {
				free(encoder->guts->integer_signal_mid_side_unaligned[i]);
				encoder->guts->integer_signal_mid_side_unaligned[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
449
			}
Josh Coalson's avatar
Josh Coalson committed
450
451
452
			if(encoder->guts->real_signal_mid_side_unaligned[i] != 0) {
				free(encoder->guts->real_signal_mid_side_unaligned[i]);
				encoder->guts->real_signal_mid_side_unaligned[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
453
454
			}
		}
Josh Coalson's avatar
Josh Coalson committed
455
456
		for(channel = 0; channel < encoder->channels; channel++) {
			for(i = 0; i < 2; i++) {
Josh Coalson's avatar
Josh Coalson committed
457
458
459
				if(encoder->guts->residual_workspace_unaligned[channel][i] != 0) {
					free(encoder->guts->residual_workspace_unaligned[channel][i]);
					encoder->guts->residual_workspace_unaligned[channel][i] = 0;
Josh Coalson's avatar
Josh Coalson committed
460
461
462
463
464
				}
			}
		}
		for(channel = 0; channel < 2; channel++) {
			for(i = 0; i < 2; i++) {
Josh Coalson's avatar
Josh Coalson committed
465
466
467
				if(encoder->guts->residual_workspace_mid_side_unaligned[channel][i] != 0) {
					free(encoder->guts->residual_workspace_mid_side_unaligned[channel][i]);
					encoder->guts->residual_workspace_mid_side_unaligned[channel][i] = 0;
Josh Coalson's avatar
Josh Coalson committed
468
				}
Josh Coalson's avatar
Josh Coalson committed
469
470
			}
		}
Josh Coalson's avatar
Josh Coalson committed
471
472
473
		if(encoder->guts->abs_residual_unaligned != 0) {
			free(encoder->guts->abs_residual_unaligned);
			encoder->guts->abs_residual_unaligned = 0;
Josh Coalson's avatar
Josh Coalson committed
474
		}
Josh Coalson's avatar
Josh Coalson committed
475
476
477
		if(encoder->guts->abs_residual_partition_sums_unaligned != 0) {
			free(encoder->guts->abs_residual_partition_sums_unaligned);
			encoder->guts->abs_residual_partition_sums_unaligned = 0;
478
		}
Josh Coalson's avatar
Josh Coalson committed
479
480
481
		if(encoder->guts->raw_bits_per_partition_unaligned != 0) {
			free(encoder->guts->raw_bits_per_partition_unaligned);
			encoder->guts->raw_bits_per_partition_unaligned = 0;
482
		}
Josh Coalson's avatar
Josh Coalson committed
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
		FLAC__bitbuffer_free(&encoder->guts->frame);
		free(encoder->guts);
		encoder->guts = 0;
	}
	encoder->state = FLAC__ENCODER_UNINITIALIZED;
}

bool FLAC__encoder_process(FLAC__Encoder *encoder, const int32 *buf[], unsigned samples)
{
	unsigned i, j, channel;
	int32 x, mid, side;
	const bool ms = encoder->do_mid_side_stereo && encoder->channels == 2;
	const int32 min_side = -((int64)1 << (encoder->bits_per_sample-1));
	const int32 max_side =  ((int64)1 << (encoder->bits_per_sample-1)) - 1;

	assert(encoder != 0);
	assert(encoder->state == FLAC__ENCODER_OK);

	j = 0;
	do {
		for(i = encoder->guts->current_sample_number; i < encoder->blocksize && j < samples; i++, j++) {
			for(channel = 0; channel < encoder->channels; channel++) {
				x = buf[channel][j];
				encoder->guts->integer_signal[channel][i] = x;
				encoder->guts->real_signal[channel][i] = (real)x;
			}
			if(ms && encoder->guts->current_frame_can_do_mid_side) {
				side = buf[0][j] - buf[1][j];
				if(side < min_side || side > max_side) {
					encoder->guts->current_frame_can_do_mid_side = false;
				}
				else {
515
					mid = (buf[0][j] + buf[1][j]) >> 1; /* NOTE: not the same as 'mid = (buf[0][j] + buf[1][j]) / 2' ! */
Josh Coalson's avatar
Josh Coalson committed
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
					encoder->guts->integer_signal_mid_side[0][i] = mid;
					encoder->guts->integer_signal_mid_side[1][i] = side;
					encoder->guts->real_signal_mid_side[0][i] = (real)mid;
					encoder->guts->real_signal_mid_side[1][i] = (real)side;
				}
			}
			encoder->guts->current_sample_number++;
		}
		if(i == encoder->blocksize) {
			if(!encoder_process_frame_(encoder, false)) /* false => not last frame */
				return false;
		}
	} while(j < samples);

	return true;
}

/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
bool FLAC__encoder_process_interleaved(FLAC__Encoder *encoder, const int32 buf[], unsigned samples)
{
	unsigned i, j, k, channel;
	int32 x, left = 0, mid, side;
	const bool ms = encoder->do_mid_side_stereo && encoder->channels == 2;
	const int32 min_side = -((int64)1 << (encoder->bits_per_sample-1));
	const int32 max_side =  ((int64)1 << (encoder->bits_per_sample-1)) - 1;

	assert(encoder != 0);
	assert(encoder->state == FLAC__ENCODER_OK);

	j = k = 0;
	do {
		for(i = encoder->guts->current_sample_number; i < encoder->blocksize && j < samples; i++, j++, k++) {
			for(channel = 0; channel < encoder->channels; channel++, k++) {
				x = buf[k];
				encoder->guts->integer_signal[channel][i] = x;
				encoder->guts->real_signal[channel][i] = (real)x;
				if(ms && encoder->guts->current_frame_can_do_mid_side) {
					if(channel == 0) {
						left = x;
					}
					else {
						side = left - x;
						if(side < min_side || side > max_side) {
							encoder->guts->current_frame_can_do_mid_side = false;
						}
						else {
562
							mid = (left + x) >> 1; /* NOTE: not the same as 'mid = (left + x) / 2' ! */
Josh Coalson's avatar
Josh Coalson committed
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
							encoder->guts->integer_signal_mid_side[0][i] = mid;
							encoder->guts->integer_signal_mid_side[1][i] = side;
							encoder->guts->real_signal_mid_side[0][i] = (real)mid;
							encoder->guts->real_signal_mid_side[1][i] = (real)side;
						}
					}
				}
			}
			encoder->guts->current_sample_number++;
		}
		if(i == encoder->blocksize) {
			if(!encoder_process_frame_(encoder, false)) /* false => not last frame */
				return false;
		}
	} while(j < samples);

	return true;
}

bool encoder_process_frame_(FLAC__Encoder *encoder, bool is_last_frame)
{
	assert(encoder->state == FLAC__ENCODER_OK);

Josh Coalson's avatar
Josh Coalson committed
586
587
588
	/*
	 * Accumulate raw signal to the MD5 signature
	 */
589
	/* 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 Coalson's avatar
Josh Coalson committed
590
591
592
593
594
	if(!FLAC__MD5Accumulate(&encoder->guts->md5context, encoder->guts->integer_signal, encoder->channels, encoder->blocksize, (encoder->bits_per_sample+7) / 8)) {
		encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
		return false;
	}

Josh Coalson's avatar
Josh Coalson committed
595
	/*
Josh Coalson's avatar
Josh Coalson committed
596
	 * Process the frame header and subframes into the frame bitbuffer
Josh Coalson's avatar
Josh Coalson committed
597
	 */
Josh Coalson's avatar
Josh Coalson committed
598
599
	if(!encoder_process_subframes_(encoder, is_last_frame)) {
		/* the above function sets the state for us in case of an error */
Josh Coalson's avatar
Josh Coalson committed
600
601
602
603
604
605
		return false;
	}

	/*
	 * Zero-pad the frame to a byte_boundary
	 */
Josh Coalson's avatar
Josh Coalson committed
606
	if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(&encoder->guts->frame)) {
Josh Coalson's avatar
Josh Coalson committed
607
608
609
610
611
		encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
		return false;
	}

	/*
612
	 * CRC-16 the whole thing
Josh Coalson's avatar
Josh Coalson committed
613
	 */
614
	assert(encoder->guts->frame.bits == 0); /* assert that we're byte-aligned */
Josh Coalson's avatar
Josh Coalson committed
615
	assert(encoder->guts->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
616
617
618
619
620
	FLAC__bitbuffer_write_raw_uint32(&encoder->guts->frame, FLAC__crc16(encoder->guts->frame.buffer, encoder->guts->frame.bytes), FLAC__FRAME_FOOTER_CRC_LEN);

	/*
	 * Write it
	 */
Josh Coalson's avatar
Josh Coalson committed
621
	if(encoder->guts->write_callback(encoder, encoder->guts->frame.buffer, encoder->guts->frame.bytes, encoder->blocksize, encoder->guts->current_frame_number, encoder->guts->client_data) != FLAC__ENCODER_WRITE_OK) {
Josh Coalson's avatar
Josh Coalson committed
622
623
624
625
626
627
628
629
630
631
		encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING;
		return false;
	}

	/*
	 * Get ready for the next frame
	 */
	encoder->guts->current_frame_can_do_mid_side = true;
	encoder->guts->current_sample_number = 0;
	encoder->guts->current_frame_number++;
632
633
634
	encoder->guts->metadata.data.stream_info.total_samples += (uint64)encoder->blocksize;
	encoder->guts->metadata.data.stream_info.min_framesize = min(encoder->guts->frame.bytes, encoder->guts->metadata.data.stream_info.min_framesize);
	encoder->guts->metadata.data.stream_info.max_framesize = max(encoder->guts->frame.bytes, encoder->guts->metadata.data.stream_info.max_framesize);
Josh Coalson's avatar
Josh Coalson committed
635
636
637
638

	return true;
}

Josh Coalson's avatar
Josh Coalson committed
639
bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame)
Josh Coalson's avatar
Josh Coalson committed
640
{
Josh Coalson's avatar
Josh Coalson committed
641
	FLAC__FrameHeader frame_header;
642
	unsigned channel, min_partition_order = encoder->min_residual_partition_order, max_partition_order;
643
	bool do_independent, do_mid_side;
Josh Coalson's avatar
Josh Coalson committed
644

Josh Coalson's avatar
Josh Coalson committed
645
	/*
646
	 * Calculate the min,max Rice partition orders
Josh Coalson's avatar
Josh Coalson committed
647
	 */
Josh Coalson's avatar
Josh Coalson committed
648
649
650
651
652
653
654
655
656
	if(is_last_frame) {
		max_partition_order = 0;
	}
	else {
		unsigned limit = 0, b = encoder->blocksize;
		while(!(b & 1)) {
			limit++;
			b >>= 1;
		}
657
		max_partition_order = min(encoder->max_residual_partition_order, limit);
Josh Coalson's avatar
Josh Coalson committed
658
	}
659
	min_partition_order = min(min_partition_order, max_partition_order);
Josh Coalson's avatar
Josh Coalson committed
660

Josh Coalson's avatar
Josh Coalson committed
661
662
663
664
665
666
667
668
669
670
671
672
673
	/*
	 * Setup the frame
	 */
	if(!FLAC__bitbuffer_clear(&encoder->guts->frame)) {
		encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
		return false;
	}
	frame_header.blocksize = encoder->blocksize;
	frame_header.sample_rate = encoder->sample_rate;
	frame_header.channels = encoder->channels;
	frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
	frame_header.bits_per_sample = encoder->bits_per_sample;
	frame_header.number.frame_number = encoder->guts->current_frame_number;
Josh Coalson's avatar
Josh Coalson committed
674

675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
	/*
	 * Figure out what channel assignments to try
	 */
	if(encoder->do_mid_side_stereo) {
		if(encoder->loose_mid_side_stereo) {
			if(encoder->guts->loose_mid_side_stereo_frame_count == 0) {
				do_independent = true;
				do_mid_side = true;
			}
			else {
				do_independent = (encoder->guts->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
				do_mid_side = !do_independent;
			}
		}
		else {
			do_independent = true;
			do_mid_side = true;
		}
	}
	else {
		do_independent = true;
		do_mid_side = false;
	}
	if(do_mid_side && !encoder->guts->current_frame_can_do_mid_side) {
		do_independent = true;
		do_mid_side = false;
	}

	assert(do_independent || do_mid_side);

705
	/*
706
	 * Check for wasted bits; set effective bps for each subframe
707
708
	 */
	if(do_independent) {
709
710
711
712
713
714
		unsigned w;
		for(channel = 0; channel < encoder->channels; channel++) {
			w = encoder_get_wasted_bits_(encoder->guts->integer_signal[channel], encoder->blocksize);
			encoder->guts->subframe_workspace[channel][0].wasted_bits = encoder->guts->subframe_workspace[channel][1].wasted_bits = w;
			encoder->guts->subframe_bps[channel] = encoder->bits_per_sample - w;
		}
715
716
	}
	if(do_mid_side) {
717
		unsigned w;
718
		assert(encoder->channels == 2);
719
720
721
722
723
		for(channel = 0; channel < 2; channel++) {
			w = encoder_get_wasted_bits_(encoder->guts->integer_signal_mid_side[channel], encoder->blocksize);
			encoder->guts->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->guts->subframe_workspace_mid_side[channel][1].wasted_bits = w;
			encoder->guts->subframe_bps_mid_side[channel] = encoder->bits_per_sample - w + (channel==0? 0:1);
		}
724
725
	}

Josh Coalson's avatar
Josh Coalson committed
726
727
728
	/*
	 * First do a normal encoding pass of each independent channel
	 */
729
730
	if(do_independent) {
		for(channel = 0; channel < encoder->channels; channel++) {
731
			if(!encoder_process_subframe_(encoder, min_partition_order, max_partition_order, false, &frame_header, encoder->guts->subframe_bps[channel], encoder->guts->integer_signal[channel], encoder->guts->real_signal[channel], encoder->guts->subframe_workspace_ptr[channel], encoder->guts->residual_workspace[channel], encoder->guts->best_subframe+channel, encoder->guts->best_subframe_bits+channel))
732
733
				return false;
		}
Josh Coalson's avatar
Josh Coalson committed
734
735
736
737
738
	}

	/*
	 * Now do mid and side channels if requested
	 */
739
	if(do_mid_side) {
Josh Coalson's avatar
Josh Coalson committed
740
741
742
		assert(encoder->channels == 2);

		for(channel = 0; channel < 2; channel++) {
743
			if(!encoder_process_subframe_(encoder, min_partition_order, max_partition_order, false, &frame_header, encoder->guts->subframe_bps_mid_side[channel], encoder->guts->integer_signal_mid_side[channel], encoder->guts->real_signal_mid_side[channel], encoder->guts->subframe_workspace_ptr_mid_side[channel], encoder->guts->residual_workspace_mid_side[channel], encoder->guts->best_subframe_mid_side+channel, encoder->guts->best_subframe_bits_mid_side+channel))
Josh Coalson's avatar
Josh Coalson committed
744
745
746
747
748
749
750
				return false;
		}
	}

	/*
	 * Compose the frame bitbuffer
	 */
751
	if(do_mid_side) {
752
753
		unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
		FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
754
		FLAC__ChannelAssignment channel_assignment;
Josh Coalson's avatar
Josh Coalson committed
755

756
		assert(encoder->channels == 2);
Josh Coalson's avatar
Josh Coalson committed
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
		if(encoder->loose_mid_side_stereo && encoder->guts->loose_mid_side_stereo_frame_count > 0) {
			channel_assignment = (encoder->guts->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT? FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT : FLAC__CHANNEL_ASSIGNMENT_MID_SIDE);
		}
		else {
			unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
			unsigned min_bits;
			FLAC__ChannelAssignment ca;

			assert(do_independent && do_mid_side);

			/* We have to figure out which channel assignent results in the smallest frame */
			bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->guts->best_subframe_bits         [0] + encoder->guts->best_subframe_bits         [1];
			bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE  ] = encoder->guts->best_subframe_bits         [0] + encoder->guts->best_subframe_bits_mid_side[1];
			bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->guts->best_subframe_bits         [1] + encoder->guts->best_subframe_bits_mid_side[1];
			bits[FLAC__CHANNEL_ASSIGNMENT_MID_SIDE   ] = encoder->guts->best_subframe_bits_mid_side[0] + encoder->guts->best_subframe_bits_mid_side[1];

			for(channel_assignment = 0, min_bits = bits[0], ca = 1; ca <= 3; ca++) {
				if(bits[ca] < min_bits) {
					min_bits = bits[ca];
					channel_assignment = ca;
				}
Josh Coalson's avatar
Josh Coalson committed
779
780
781
			}
		}

782
		frame_header.channel_assignment = channel_assignment;
Josh Coalson's avatar
Josh Coalson committed
783
784
785
786
787
788

		if(!FLAC__frame_add_header(&frame_header, encoder->streamable_subset, is_last_frame, &encoder->guts->frame)) {
			encoder->state = FLAC__ENCODER_FRAMING_ERROR;
			return false;
		}

789
		switch(channel_assignment) {
Josh Coalson's avatar
Josh Coalson committed
790
			case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
791
792
				left_subframe  = &encoder->guts->subframe_workspace         [0][encoder->guts->best_subframe         [0]];
				right_subframe = &encoder->guts->subframe_workspace         [1][encoder->guts->best_subframe         [1]];
Josh Coalson's avatar
Josh Coalson committed
793
794
				break;
			case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
795
796
				left_subframe  = &encoder->guts->subframe_workspace         [0][encoder->guts->best_subframe         [0]];
				right_subframe = &encoder->guts->subframe_workspace_mid_side[1][encoder->guts->best_subframe_mid_side[1]];
Josh Coalson's avatar
Josh Coalson committed
797
798
				break;
			case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
799
800
				left_subframe  = &encoder->guts->subframe_workspace_mid_side[1][encoder->guts->best_subframe_mid_side[1]];
				right_subframe = &encoder->guts->subframe_workspace         [1][encoder->guts->best_subframe         [1]];
Josh Coalson's avatar
Josh Coalson committed
801
802
				break;
			case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
803
804
				left_subframe  = &encoder->guts->subframe_workspace_mid_side[0][encoder->guts->best_subframe_mid_side[0]];
				right_subframe = &encoder->guts->subframe_workspace_mid_side[1][encoder->guts->best_subframe_mid_side[1]];
Josh Coalson's avatar
Josh Coalson committed
805
806
807
808
				break;
			default:
				assert(0);
		}
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835

		switch(channel_assignment) {
			case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
				left_bps  = encoder->guts->subframe_bps         [0];
				right_bps = encoder->guts->subframe_bps         [1];
				break;
			case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
				left_bps  = encoder->guts->subframe_bps         [0];
				right_bps = encoder->guts->subframe_bps_mid_side[1];
				break;
			case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
				left_bps  = encoder->guts->subframe_bps_mid_side[1];
				right_bps = encoder->guts->subframe_bps         [1];
				break;
			case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
				left_bps  = encoder->guts->subframe_bps_mid_side[0];
				right_bps = encoder->guts->subframe_bps_mid_side[1];
				break;
			default:
				assert(0);
		}

		/* note that encoder_add_subframe_ sets the state for us in case of an error */
		if(!encoder_add_subframe_(encoder, &frame_header, left_bps , left_subframe , &encoder->guts->frame))
			return false;
		if(!encoder_add_subframe_(encoder, &frame_header, right_bps, right_subframe, &encoder->guts->frame))
			return false;
Josh Coalson's avatar
Josh Coalson committed
836
837
838
839
840
841
842
843
	}
	else {
		if(!FLAC__frame_add_header(&frame_header, encoder->streamable_subset, is_last_frame, &encoder->guts->frame)) {
			encoder->state = FLAC__ENCODER_FRAMING_ERROR;
			return false;
		}

		for(channel = 0; channel < encoder->channels; channel++) {
844
			if(!encoder_add_subframe_(encoder, &frame_header, encoder->guts->subframe_bps[channel], &encoder->guts->subframe_workspace[channel][encoder->guts->best_subframe[channel]], &encoder->guts->frame)) {
Josh Coalson's avatar
Josh Coalson committed
845
846
847
848
849
850
				/* the above function sets the state for us in case of an error */
				return false;
			}
		}
	}

851
852
853
854
855
856
857
858
	if(encoder->loose_mid_side_stereo) {
		encoder->guts->loose_mid_side_stereo_frame_count++;
		if(encoder->guts->loose_mid_side_stereo_frame_count >= encoder->guts->loose_mid_side_stereo_frames)
			encoder->guts->loose_mid_side_stereo_frame_count = 0;
	}

	encoder->guts->last_channel_assignment = frame_header.channel_assignment;

Josh Coalson's avatar
Josh Coalson committed
859
860
861
	return true;
}

862
bool encoder_process_subframe_(FLAC__Encoder *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 Coalson's avatar
Josh Coalson committed
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
{
	real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
	real lpc_residual_bits_per_sample;
	real autoc[FLAC__MAX_LPC_ORDER+1];
	real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER];
	real lpc_error[FLAC__MAX_LPC_ORDER];
	unsigned min_lpc_order, max_lpc_order, lpc_order;
	unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
	unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
	unsigned rice_parameter;
	unsigned _candidate_bits, _best_bits;
	unsigned _best_subframe;

	/* verbatim subframe is the baseline against which we measure other compressed subframes */
	_best_subframe = 0;
878
	_best_bits = encoder_evaluate_verbatim_subframe_(integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]);
Josh Coalson's avatar
Josh Coalson committed
879
880
881

	if(!verbatim_only && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
		/* check for constant subframe */
882
883
884
		if(encoder->guts->use_slow)
			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);
		else
885
			guess_fixed_order = encoder->guts->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample);
Josh Coalson's avatar
Josh Coalson committed
886
887
888
889
890
891
892
		if(fixed_residual_bits_per_sample[1] == 0.0) {
			/* the above means integer_signal+FLAC__MAX_FIXED_ORDER is constant, now we just have to check the warmup samples */
			unsigned i, signal_is_constant = true;
			for(i = 1; i <= FLAC__MAX_FIXED_ORDER; i++) {
				if(integer_signal[0] != integer_signal[i]) {
					signal_is_constant = false;
					break;
893
				}
Josh Coalson's avatar
Josh Coalson committed
894
895
			}
			if(signal_is_constant) {
896
				_candidate_bits = encoder_evaluate_constant_subframe_(integer_signal[0], subframe_bps, subframe[!_best_subframe]);
Josh Coalson's avatar
Josh Coalson committed
897
898
899
				if(_candidate_bits < _best_bits) {
					_best_subframe = !_best_subframe;
					_best_bits = _candidate_bits;
Josh Coalson's avatar
Josh Coalson committed
900
901
				}
			}
Josh Coalson's avatar
Josh Coalson committed
902
903
904
905
906
907
908
		}
		else {
			/* encode fixed */
			if(encoder->do_exhaustive_model_search) {
				min_fixed_order = 0;
				max_fixed_order = FLAC__MAX_FIXED_ORDER;
			}
Josh Coalson's avatar
Josh Coalson committed
909
			else {
Josh Coalson's avatar
Josh Coalson committed
910
911
912
				min_fixed_order = max_fixed_order = guess_fixed_order;
			}
			for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
913
				if(fixed_residual_bits_per_sample[fixed_order] >= (real)subframe_bps)
Josh Coalson's avatar
Josh Coalson committed
914
					continue; /* don't even try */
915
				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 Coalson's avatar
Josh Coalson committed
916
#ifndef FLAC__SYMMETRIC_RICE
917
				rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
918
#endif
919
920
				if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
					rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
921
				_candidate_bits = encoder_evaluate_fixed_subframe_(integer_signal, residual[!_best_subframe], encoder->guts->abs_residual, encoder->guts->abs_residual_partition_sums, encoder->guts->raw_bits_per_partition, frame_header->blocksize, subframe_bps, fixed_order, rice_parameter, min_partition_order, max_partition_order, encoder->rice_parameter_search_dist, subframe[!_best_subframe]);
Josh Coalson's avatar
Josh Coalson committed
922
923
924
				if(_candidate_bits < _best_bits) {
					_best_subframe = !_best_subframe;
					_best_bits = _candidate_bits;
Josh Coalson's avatar
Josh Coalson committed
925
				}
Josh Coalson's avatar
Josh Coalson committed
926
			}
Josh Coalson's avatar
Josh Coalson committed
927

Josh Coalson's avatar
Josh Coalson committed
928
929
930
931
932
933
934
			/* encode lpc */
			if(encoder->max_lpc_order > 0) {
				if(encoder->max_lpc_order >= frame_header->blocksize)
					max_lpc_order = frame_header->blocksize-1;
				else
					max_lpc_order = encoder->max_lpc_order;
				if(max_lpc_order > 0) {
935
					encoder->guts->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
936
937
938
939
940
941
942
					/* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
					if(autoc[0] != 0.0) {
						FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, lp_coeff, lpc_error);
						if(encoder->do_exhaustive_model_search) {
							min_lpc_order = 1;
						}
						else {
943
							unsigned guess_lpc_order = FLAC__lpc_compute_best_order(lpc_error, max_lpc_order, frame_header->blocksize, subframe_bps);
944
945
946
947
							min_lpc_order = max_lpc_order = guess_lpc_order;
						}
						if(encoder->do_qlp_coeff_prec_search) {
							min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
948
							max_qlp_coeff_precision = min(32 - subframe_bps - 1, (1u<<FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)-1);
949
950
951
952
953
954
						}
						else {
							min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->qlp_coeff_precision;
						}
						for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
							lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order);
955
							if(lpc_residual_bits_per_sample >= (real)subframe_bps)
956
957
								continue; /* don't even try */
							rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */
Josh Coalson's avatar
Josh Coalson committed
958
#ifndef FLAC__SYMMETRIC_RICE
959
							rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
960
#endif
961
962
							if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
								rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
963
							for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
964
								_candidate_bits = encoder_evaluate_lpc_subframe_(integer_signal, residual[!_best_subframe], encoder->guts->abs_residual, encoder->guts->abs_residual_partition_sums, encoder->guts->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->rice_parameter_search_dist, subframe[!_best_subframe]);
965
966
967
968
969
								if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
									if(_candidate_bits < _best_bits) {
										_best_subframe = !_best_subframe;
										_best_bits = _candidate_bits;
									}
Josh Coalson's avatar
Josh Coalson committed
970
971
972
973
974
975
976
								}
							}
						}
					}
				}
			}
		}
Josh Coalson's avatar
Josh Coalson committed
977
	}
Josh Coalson's avatar
Josh Coalson committed
978

Josh Coalson's avatar
Josh Coalson committed
979
980
981
982
983
984
	*best_subframe = _best_subframe;
	*best_bits = _best_bits;

	return true;
}

985
bool encoder_add_subframe_(FLAC__Encoder *encoder, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const FLAC__Subframe *subframe, FLAC__BitBuffer *frame)
Josh Coalson's avatar
Josh Coalson committed
986
987
988
{
	switch(subframe->type) {
		case FLAC__SUBFRAME_TYPE_CONSTANT:
989
			if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson's avatar
Josh Coalson committed
990
991
992
993
994
				encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
				return false;
			}
			break;
		case FLAC__SUBFRAME_TYPE_FIXED:
995
			if(!FLAC__subframe_add_fixed(&(subframe->data.fixed), frame_header->blocksize - subframe->data.fixed.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson's avatar
Josh Coalson committed
996
997
998
999
1000
				encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
				return false;
			}
			break;
		case FLAC__SUBFRAME_TYPE_LPC:
1001
			if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), frame_header->blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson's avatar
Josh Coalson committed
1002
1003
1004
1005
1006
				encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
				return false;
			}
			break;
		case FLAC__SUBFRAME_TYPE_VERBATIM:
1007
			if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
Josh Coalson's avatar
Josh Coalson committed
1008
1009
1010
1011
1012
1013
				encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
				return false;
			}
			break;
		default:
			assert(0);
Josh Coalson's avatar
Josh Coalson committed
1014
1015
1016
1017
1018
	}

	return true;
}

1019
unsigned encoder_evaluate_constant_subframe_(const int32 signal, unsigned subframe_bps, FLAC__Subframe *subframe)
Josh Coalson's avatar
Josh Coalson committed
1020
1021
1022
1023
{
	subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
	subframe->data.constant.value = signal;

1024
	return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe_bps;
Josh Coalson's avatar
Josh Coalson committed
1025
1026
}

1027
unsigned 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 Coalson's avatar
Josh Coalson committed
1028
1029
1030
1031
1032
1033
1034
1035
1036
{
	unsigned i, residual_bits;
	const unsigned residual_samples = blocksize - order;

	FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);

	subframe->type = FLAC__SUBFRAME_TYPE_FIXED;

	subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalson's avatar
Josh Coalson committed
1037
	subframe->data.fixed.residual = residual;
Josh Coalson's avatar
Josh Coalson committed
1038

1039
	residual_bits = 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 Coalson's avatar
Josh Coalson committed
1040
1041
1042
1043
1044

	subframe->data.fixed.order = order;
	for(i = 0; i < order; i++)
		subframe->data.fixed.warmup[i] = signal[i];

1045
	return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (order * subframe_bps) + residual_bits;
Josh Coalson's avatar
Josh Coalson committed
1046
1047
}

1048
unsigned encoder_evaluate_lpc_subframe_(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 Coalson's avatar
Josh Coalson committed
1049
1050
1051
1052
1053
1054
{
	int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
	unsigned i, residual_bits;
	int quantization, ret;
	const unsigned residual_samples = blocksize - order;

1055
	ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, subframe_bps, qlp_coeff, &quantization);
Josh Coalson's avatar
Josh Coalson committed
1056
1057
1058
1059
1060
1061
1062
1063
	if(ret != 0)
		return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */

	FLAC__lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual);

	subframe->type = FLAC__SUBFRAME_TYPE_LPC;

	subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
Josh Coalson's avatar
Josh Coalson committed
1064
	subframe->data.lpc.residual = residual;
Josh Coalson's avatar
Josh Coalson committed
1065

1066
	residual_bits = 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 Coalson's avatar
Josh Coalson committed
1067
1068
1069
1070
1071
1072
1073
1074

	subframe->data.lpc.order = order;
	subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
	subframe->data.lpc.quantization_level = quantization;
	memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(int32)*FLAC__MAX_LPC_ORDER);
	for(i = 0; i < order; i++)
		subframe->data.lpc.warmup[i] = signal[i];

1075
	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 Coalson's avatar
Josh Coalson committed
1076
1077
}

1078
unsigned encoder_evaluate_verbatim_subframe_(const int32 signal[], unsigned blocksize, unsigned subframe_bps, FLAC__Subframe *subframe)
Josh Coalson's avatar
Josh Coalson committed
1079
1080
1081
{
	subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;

Josh Coalson's avatar
Josh Coalson committed
1082
1083
	subframe->data.verbatim.data = signal;

1084
	return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (blocksize * subframe_bps);
Josh Coalson's avatar
Josh Coalson committed
1085
1086
}

1087
unsigned 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 Coalson's avatar
Josh Coalson committed
1088
{
1089
	int32 r;
Josh Coalson's avatar
Josh Coalson committed
1090
#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
1091
	unsigned sum;
1092
	int partition_order;
1093
1094
1095
#else
	unsigned partition_order;
#endif
Josh Coalson's avatar
Josh Coalson committed
1096
	unsigned residual_bits, best_residual_bits = 0;
1097
	unsigned residual_sample;
1098
	unsigned best_parameters_index = 0, parameters[2][1 << FLAC__MAX_RICE_PARTITION_ORDER], raw_bits[2][1 << FLAC__MAX_RICE_PARTITION_ORDER];
1099
1100
1101
1102
1103
1104
1105

	/* compute abs(residual) for use later */
	for(residual_sample = 0; residual_sample < residual_samples; residual_sample++) {
		r = residual[residual_sample];
		abs_residual[residual_sample] = (uint32)(r<0? -r : r);
	}

Josh Coalson's avatar
Josh Coalson committed
1106
#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
1107
1108
	max_partition_order = 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);
	min_partition_order = min(min_partition_order, max_partition_order);
1109

1110
1111
	for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
		if(!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)) {
1112
			assert(0); /* encoder_precompute_partition_info_ should keep this from ever happening */
1113
1114
1115
1116
1117
1118
1119
1120
		}
		sum += 1u << partition_order;
		if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
			best_residual_bits = residual_bits;
			*best_partition_order = partition_order;
			best_parameters_index = !best_parameters_index;
		}
	}
1121
#else
1122
1123
	for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
		if(!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)) {
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
			assert(best_residual_bits != 0);
			break;
		}
		if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
			best_residual_bits = residual_bits;
			*best_partition_order = partition_order;
			best_parameters_index = !best_parameters_index;
		}
	}
#endif
1134
1135
1136
1137
1138
1139
	memcpy(best_parameters, parameters[best_parameters_index], sizeof(unsigned)*(1<<(*best_partition_order)));
	memcpy(best_raw_bits, raw_bits[best_parameters_index], sizeof(unsigned)*(1<<(*best_partition_order)));

	return best_residual_bits;
}

Josh Coalson's avatar
Josh Coalson committed
1140
#if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
1141
unsigned 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)
1142
1143
{
	int partition_order;
1144
	unsigned from_partition, to_partition = 0;
1145
	const unsigned blocksize = residual_samples + predictor_order;
Josh Coalson's avatar
Josh Coalson committed
1146

1147
	/* first do max_partition_order */
1148
	for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
Josh Coalson's avatar
Josh Coalson committed
1149
#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
1150
		uint32 abs_residual_partition_sum;
1151
#endif
Josh Coalson's avatar
Josh Coalson committed
1152
#ifdef FLAC__SEARCH_FOR_ESCAPES
1153
1154
1155
1156
1157
		uint32 abs_residual_partition_max;
		unsigned abs_residual_partition_max_index = 0; /* initialized to silence superfluous compiler warning */
#endif
		uint32 abs_r;
		unsigned partition, partition_sample, partition_samples, residual_sample;
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
		const unsigned partitions = 1u << partition_order;
		const unsigned default_partition_samples = blocksize >> partition_order;

		if(default_partition_samples <= predictor_order) {
			assert(max_partition_order > 0);
			max_partition_order--;
		}
		else {
			for(partition = residual_sample = 0; partition < partitions; partition++) {
				partition_samples = default_partition_samples;
				if(partition == 0)
					partition_samples -= predictor_order;
Josh Coalson's avatar
Josh Coalson committed
1170
#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
1171
				abs_residual_partition_sum = 0;
1172
#endif
Josh Coalson's avatar
Josh Coalson committed
1173
#ifdef FLAC__SEARCH_FOR_ESCAPES
1174
1175
1176
1177
				abs_residual_partition_max = 0;
#endif
				for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
					abs_r = abs_residual[residual_sample];
Josh Coalson's avatar
Josh Coalson committed
1178
#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
1179
1180
					abs_residual_partition_sum += abs_r; /* @@@ this can overflow with small max_partition_order and (large blocksizes or bits-per-sample), FIX! */
#endif
Josh Coalson's avatar
Josh Coalson committed
1181
#ifdef FLAC__SEARCH_FOR_ESCAPES
1182
1183
1184
1185
1186
1187
1188
					if(abs_r > abs_residual_partition_max) {
						abs_residual_partition_max = abs_r;
						abs_residual_partition_max_index = residual_sample;
					}
#endif
					residual_sample++;
				}
Josh Coalson's avatar
Josh Coalson committed
1189
#ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
1190
				abs_residual_partition_sums[partition] = abs_residual_partition_sum;
1191
#endif
Josh Coalson's avatar
Josh Coalson committed
1192
#ifdef FLAC__SEARCH_FOR_ESCAPES
1193
1194
1195
1196
1197
				if(</