stream_encoder.c 179 KB
Newer Older
1
/* libFLAC - Free Lossless Audio Codec library
Josh Coalson's avatar
Josh Coalson committed
2
 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
Josh Coalson's avatar
Josh Coalson committed
3
 *
4
5
6
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
Josh Coalson's avatar
Josh Coalson committed
7
 *
8
9
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
Josh Coalson's avatar
Josh Coalson committed
10
 *
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the Xiph.org Foundation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Josh Coalson's avatar
Josh Coalson committed
30
31
 */

Josh Coalson's avatar
Josh Coalson committed
32
33
34
35
#if HAVE_CONFIG_H
#  include <config.h>
#endif

36
37
38
39
40
41
42
43
#if defined _MSC_VER || defined __MINGW32__
#include <io.h> /* for _setmode() */
#include <fcntl.h> /* for _O_BINARY */
#endif
#if defined __CYGWIN__ || defined __EMX__
#include <io.h> /* for setmode(), O_BINARY */
#include <fcntl.h> /* for _O_BINARY */
#endif
44
#include <limits.h>
Josh Coalson's avatar
Josh Coalson committed
45
46
47
#include <stdio.h>
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for memcpy() */
48
#include <sys/types.h> /* for off_t */
49
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
50
#if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */
51
52
53
#define fseeko fseek
#define ftello ftell
#endif
54
#endif
55
#include "FLAC/assert.h"
Josh Coalson's avatar
Josh Coalson committed
56
#include "FLAC/stream_decoder.h"
57
#include "protected/stream_encoder.h"
58
#include "private/bitwriter.h"
59
#include "private/bitmath.h"
60
#include "private/crc.h"
61
#include "private/cpu.h"
Josh Coalson's avatar
Josh Coalson committed
62
#include "private/fixed.h"
63
#include "private/format.h"
Josh Coalson's avatar
Josh Coalson committed
64
#include "private/lpc.h"
Josh Coalson's avatar
Josh Coalson committed
65
#include "private/md5.h"
66
#include "private/memory.h"
67
#if FLAC__HAS_OGG
68
#include "private/ogg_helper.h"
69
#include "private/ogg_mapping.h"
70
#endif
71
#include "private/stream_encoder_framing.h"
72
#include "private/window.h"
Josh Coalson's avatar
Josh Coalson committed
73
74
75
76
77
78
79
80
81
82
83

#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))

84
85
86
87
88
89
90
91
92
93
94
95
/* Exact Rice codeword length calculation is off by default.  The simple
 * (and fast) estimation (of how many bits a residual value will be
 * encoded with) in this encoder is very good, almost always yielding
 * compression within 0.1% of exact calculation.
 */
#undef EXACT_RICE_BITS_CALCULATION
/* Rice parameter searching is off by default.  The simple (and fast)
 * parameter estimation in this encoder is very good, almost always
 * yielding compression within 0.1% of the optimal parameters.
 */
#undef ENABLE_RICE_PARAMETER_SEARCH 

Josh Coalson's avatar
Josh Coalson committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
typedef struct {
	FLAC__int32 *data[FLAC__MAX_CHANNELS];
	unsigned size; /* of each data[] in samples */
	unsigned tail;
} verify_input_fifo;

typedef struct {
	const FLAC__byte *data;
	unsigned capacity;
	unsigned bytes;
} verify_output;

typedef enum {
	ENCODER_IN_MAGIC = 0,
	ENCODER_IN_METADATA = 1,
	ENCODER_IN_AUDIO = 2
} EncoderStateHint;

114
115
116
117
118
119
120
121
122
123
124
125
static struct CompressionLevels {
	FLAC__bool do_mid_side_stereo;
	FLAC__bool loose_mid_side_stereo;
	unsigned max_lpc_order;
	unsigned qlp_coeff_precision;
	FLAC__bool do_qlp_coeff_prec_search;
	FLAC__bool do_escape_coding;
	FLAC__bool do_exhaustive_model_search;
	unsigned min_residual_partition_order;
	unsigned max_residual_partition_order;
	unsigned rice_parameter_search_dist;
} compression_levels_[] = {
126
127
128
129
130
131
132
133
134
	{ false, false,  0, 0, false, false, false, 2, 2, 0 },
	{ true , true ,  0, 0, false, false, false, 2, 2, 0 },
	{ true , false,  0, 0, false, false, false, 0, 3, 0 },
	{ false, false,  6, 0, false, false, false, 3, 3, 0 },
	{ true , true ,  8, 0, false, false, false, 3, 3, 0 },
	{ true , false,  8, 0, false, false, false, 3, 3, 0 },
	{ true , false,  8, 0, false, false, false, 0, 4, 0 },
	{ true , false,  8, 0, false, false, true , 0, 6, 0 },
	{ true , false, 12, 0, false, false, true , 0, 6, 0 }
135
136
137
};


138
139
140
141
142
143
/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

144
145
static void set_defaults_(FLAC__StreamEncoder *encoder);
static void free_(FLAC__StreamEncoder *encoder);
146
static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize);
147
148
static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples, FLAC__bool is_last_block);
static FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, FLAC__bool is_last_block);
149
static void update_metadata_(const FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
150
#if FLAC__HAS_OGG
151
static void update_ogg_metadata_(FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
152
#endif
153
static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block);
154
static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block);
Josh Coalson's avatar
Josh Coalson committed
155
156
157
158
159
160
161
162

static FLAC__bool process_subframe_(
	FLAC__StreamEncoder *encoder,
	unsigned min_partition_order,
	unsigned max_partition_order,
	const FLAC__FrameHeader *frame_header,
	unsigned subframe_bps,
	const FLAC__int32 integer_signal[],
163
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
164
	const FLAC__real real_signal[],
165
#endif
Josh Coalson's avatar
Josh Coalson committed
166
167
168
169
170
171
172
173
174
	FLAC__Subframe *subframe[2],
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
	FLAC__int32 *residual[2],
	unsigned *best_subframe,
	unsigned *best_bits
);

static FLAC__bool add_subframe_(
	FLAC__StreamEncoder *encoder,
175
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
176
177
	unsigned subframe_bps,
	const FLAC__Subframe *subframe,
178
	FLAC__BitWriter *frame
Josh Coalson's avatar
Josh Coalson committed
179
180
181
);

static unsigned evaluate_constant_subframe_(
182
	FLAC__StreamEncoder *encoder,
Josh Coalson's avatar
Josh Coalson committed
183
	const FLAC__int32 signal,
184
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
	unsigned subframe_bps,
	FLAC__Subframe *subframe
);

static unsigned evaluate_fixed_subframe_(
	FLAC__StreamEncoder *encoder,
	const FLAC__int32 signal[],
	FLAC__int32 residual[],
	FLAC__uint64 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,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__Subframe *subframe,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
);

207
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
static unsigned evaluate_lpc_subframe_(
	FLAC__StreamEncoder *encoder,
	const FLAC__int32 signal[],
	FLAC__int32 residual[],
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned raw_bits_per_partition[],
	const FLAC__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,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__Subframe *subframe,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
);
227
#endif
Josh Coalson's avatar
Josh Coalson committed
228
229

static unsigned evaluate_verbatim_subframe_(
230
	FLAC__StreamEncoder *encoder, 
Josh Coalson's avatar
Josh Coalson committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
	const FLAC__int32 signal[],
	unsigned blocksize,
	unsigned subframe_bps,
	FLAC__Subframe *subframe
);

static unsigned find_best_partition_order_(
	struct FLAC__StreamEncoderPrivate *private_,
	const FLAC__int32 residual[],
	FLAC__uint64 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,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
);

static void precompute_partition_info_sums_(
253
	const FLAC__int32 residual[],
Josh Coalson's avatar
Josh Coalson committed
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned residual_samples,
	unsigned predictor_order,
	unsigned min_partition_order,
	unsigned max_partition_order
);

static void precompute_partition_info_escapes_(
	const FLAC__int32 residual[],
	unsigned raw_bits_per_partition[],
	unsigned residual_samples,
	unsigned predictor_order,
	unsigned min_partition_order,
	unsigned max_partition_order
);

static FLAC__bool set_partitioned_rice_(
271
#ifdef EXACT_RICE_BITS_CALCULATION
Josh Coalson's avatar
Josh Coalson committed
272
	const FLAC__int32 residual[],
273
#endif
Josh Coalson's avatar
Josh Coalson committed
274
275
276
277
278
279
280
281
282
283
284
285
	const FLAC__uint64 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,
	const FLAC__bool search_for_escapes,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
	unsigned *bits
);

286
static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples);
Josh Coalson's avatar
Josh Coalson committed
287

Josh Coalson's avatar
Josh Coalson committed
288
/* verify-related routines: */
Josh Coalson's avatar
Josh Coalson committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
static void append_to_verify_fifo_(
	verify_input_fifo *fifo,
	const FLAC__int32 * const input[],
	unsigned input_offset,
	unsigned channels,
	unsigned wide_samples
);

static void append_to_verify_fifo_interleaved_(
	verify_input_fifo *fifo,
	const FLAC__int32 input[],
	unsigned input_offset,
	unsigned channels,
	unsigned wide_samples
);

305
static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
306
307
308
static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
Josh Coalson's avatar
Josh Coalson committed
309

310
static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
311
312
static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
313
static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
314
static FILE *get_binary_stdout_(void);
Josh Coalson's avatar
Josh Coalson committed
315

316
317
318
319
320
321
322
323

/***********************************************************************
 *
 * Private class data
 *
 ***********************************************************************/

typedef struct FLAC__StreamEncoderPrivate {
324
	unsigned input_capacity;                          /* current size (in samples) of the signal and residual buffers */
Josh Coalson's avatar
Josh Coalson committed
325
326
	FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS];  /* the integer version of the input signal */
	FLAC__int32 *integer_signal_mid_side[2];          /* the integer version of the mid-side input signal (stereo only) */
327
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
328
329
	FLAC__real *real_signal[FLAC__MAX_CHANNELS];      /* the floating-point version of the input signal */
	FLAC__real *real_signal_mid_side[2];              /* the floating-point version of the mid-side input signal (stereo only) */
330
331
	FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
	FLAC__real *windowed_signal;                      /* the real_signal[] * current window[] */
332
#endif
333
334
	unsigned subframe_bps[FLAC__MAX_CHANNELS];        /* the effective bits per sample of the input signal (stream bps - wasted bits) */
	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
335
336
	FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
	FLAC__int32 *residual_workspace_mid_side[2][2];
Josh Coalson's avatar
Josh Coalson committed
337
338
339
340
	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];
341
342
343
344
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2];
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2];
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2];
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2];
345
	unsigned best_subframe[FLAC__MAX_CHANNELS];       /* index (0 or 1) into 2nd dimension of the above workspaces */
Josh Coalson's avatar
Josh Coalson committed
346
	unsigned best_subframe_mid_side[2];
347
	unsigned best_subframe_bits[FLAC__MAX_CHANNELS];  /* size in bits of the best subframe for each channel */
Josh Coalson's avatar
Josh Coalson committed
348
	unsigned best_subframe_bits_mid_side[2];
349
	FLAC__uint64 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
350
	unsigned *raw_bits_per_partition;                 /* workspace where the sum of silog2(candidate residual) for each partition is stored */
351
	FLAC__BitWriter *frame;                           /* the current frame being worked on */
352
353
	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 */
354
	FLAC__ChannelAssignment last_channel_assignment;
355
356
	FLAC__StreamMetadata streaminfo;                  /* scratchpad for STREAMINFO as it is built */
	FLAC__StreamMetadata_SeekTable *seek_table;       /* pointer into encoder->protected_->metadata_ where the seek table is */
Josh Coalson's avatar
Josh Coalson committed
357
358
	unsigned current_sample_number;
	unsigned current_frame_number;
359
	struct FLAC__MD5Context md5context;
360
	FLAC__CPUInfo cpuinfo;
361
#ifndef FLAC__INTEGER_ONLY_LIBRARY
362
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
363
364
365
366
#else
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
#endif
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
367
	void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
368
369
370
	void (*local_lpc_compute_residual_from_qlp_coefficients)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
	void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
	void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
371
#endif
372
373
374
	FLAC__bool use_wide_by_block;          /* use slow 64-bit versions of some functions because of the block size */
	FLAC__bool use_wide_by_partition;      /* use slow 64-bit versions of some functions because of the min partition order and blocksize */
	FLAC__bool use_wide_by_order;          /* use slow 64-bit versions of some functions because of the lpc order */
375
376
377
	FLAC__bool disable_constant_subframes;
	FLAC__bool disable_fixed_subframes;
	FLAC__bool disable_verbatim_subframes;
378
379
380
381
#if FLAC__HAS_OGG
	FLAC__bool is_ogg;
#endif
	FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */
382
383
	FLAC__StreamEncoderSeekCallback seek_callback;
	FLAC__StreamEncoderTellCallback tell_callback;
Josh Coalson's avatar
Josh Coalson committed
384
385
	FLAC__StreamEncoderWriteCallback write_callback;
	FLAC__StreamEncoderMetadataCallback metadata_callback;
386
	FLAC__StreamEncoderProgressCallback progress_callback;
Josh Coalson's avatar
Josh Coalson committed
387
	void *client_data;
388
389
390
391
392
393
	unsigned first_seekpoint_to_check;
	FILE *file;                            /* only used when encoding to a file */
	FLAC__uint64 bytes_written;
	FLAC__uint64 samples_written;
	unsigned frames_written;
	unsigned total_frames_estimate;
394
	/* unaligned (original) pointers to allocated data */
Josh Coalson's avatar
Josh Coalson committed
395
396
	FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__int32 *integer_signal_mid_side_unaligned[2];
397
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
398
399
	FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__real *real_signal_mid_side_unaligned[2];
400
401
	FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
	FLAC__real *windowed_signal_unaligned;
402
#endif
Josh Coalson's avatar
Josh Coalson committed
403
404
	FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
	FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
405
	FLAC__uint64 *abs_residual_partition_sums_unaligned;
406
	unsigned *raw_bits_per_partition_unaligned;
407
408
409
410
	/*
	 * These fields have been moved here from private function local
	 * declarations merely to save stack space during encoding.
	 */
411
#ifndef FLAC__INTEGER_ONLY_LIBRARY
412
	FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
413
#endif
414
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalson's avatar
Josh Coalson committed
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
	/*
	 * The data for the verify section
	 */
	struct {
		FLAC__StreamDecoder *decoder;
		EncoderStateHint state_hint;
		FLAC__bool needs_magic_hack;
		verify_input_fifo input_fifo;
		verify_output output;
		struct {
			FLAC__uint64 absolute_sample;
			unsigned frame_number;
			unsigned channel;
			unsigned sample;
			FLAC__int32 expected;
			FLAC__int32 got;
		} error_stats;
	} verify;
433
	FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
434
} FLAC__StreamEncoderPrivate;
Josh Coalson's avatar
Josh Coalson committed
435

436
437
438
439
440
441
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/

442
FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
443
	"FLAC__STREAM_ENCODER_OK",
444
	"FLAC__STREAM_ENCODER_UNINITIALIZED",
445
	"FLAC__STREAM_ENCODER_OGG_ERROR",
Josh Coalson's avatar
Josh Coalson committed
446
447
	"FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
	"FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
448
449
	"FLAC__STREAM_ENCODER_CLIENT_ERROR",
	"FLAC__STREAM_ENCODER_IO_ERROR",
450
	"FLAC__STREAM_ENCODER_FRAMING_ERROR",
451
452
453
454
455
456
	"FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR"
};

FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = {
	"FLAC__STREAM_ENCODER_INIT_STATUS_OK",
	"FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR",
457
	"FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
458
459
460
461
462
463
464
465
466
467
468
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION",
	"FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
	"FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA",
	"FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED"
Josh Coalson's avatar
Josh Coalson committed
469
470
};

471
472
473
474
475
476
477
FLAC_API const char * const FLAC__treamEncoderReadStatusString[] = {
	"FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE",
	"FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
	"FLAC__STREAM_ENCODER_READ_STATUS_ABORT",
	"FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED"
};

478
FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
479
480
	"FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
	"FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalson's avatar
Josh Coalson committed
481
482
};

483
484
485
486
487
488
489
490
491
492
493
494
FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = {
	"FLAC__STREAM_ENCODER_SEEK_STATUS_OK",
	"FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR",
	"FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED"
};

FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = {
	"FLAC__STREAM_ENCODER_TELL_STATUS_OK",
	"FLAC__STREAM_ENCODER_TELL_STATUS_ERROR",
	"FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED"
};

495
496
497
498
499
500
501
502
503
504
505
506
507
/* Number of samples that will be overread to watch for end of stream.  By
 * 'overread', we mean that the FLAC__stream_encoder_process*() calls will
 * always try to read blocksize+1 samples before encoding a block, so that
 * even if the stream has a total sample count that is an integral multiple
 * of the blocksize, we will still notice when we are encoding the last
 * block.  This is needed, for example, to correctly set the end-of-stream
 * marker in Ogg FLAC.
 *
 * WATCHOUT: some parts of the code assert that OVERREAD_ == 1 and there's
 * not really any reason to change it.
 */
static const unsigned OVERREAD_ = 1;

508
509
510
511
/***********************************************************************
 *
 * Class constructor/destructor
 *
Josh Coalson's avatar
Josh Coalson committed
512
 */
513
FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void)
Josh Coalson's avatar
Josh Coalson committed
514
{
515
	FLAC__StreamEncoder *encoder;
516
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
517

518
	FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalson's avatar
Josh Coalson committed
519

520
	encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder));
521
522
	if(encoder == 0) {
		return 0;
523
	}
Josh Coalson's avatar
Josh Coalson committed
524

525
	encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected));
526
	if(encoder->protected_ == 0) {
527
528
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
529
	}
Josh Coalson's avatar
Josh Coalson committed
530

531
	encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
532
533
	if(encoder->private_ == 0) {
		free(encoder->protected_);
534
535
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
536
	}
Josh Coalson's avatar
Josh Coalson committed
537

538
	encoder->private_->frame = FLAC__bitwriter_new();
539
540
541
542
543
544
	if(encoder->private_->frame == 0) {
		free(encoder->private_);
		free(encoder->protected_);
		free(encoder);
		return 0;
	}
545

546
547
	encoder->private_->file = 0;

548
	set_defaults_(encoder);
549

550
	encoder->private_->is_being_deleted = false;
551
552
553
554
555
556
557
558
559
560

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
		encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
		encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
	}
	for(i = 0; i < 2; i++) {
		encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
		encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
	}
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
561
562
		encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
		encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
563
564
	}
	for(i = 0; i < 2; i++) {
565
566
		encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
		encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][1] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1];
567
568
569
	}

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
570
571
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
572
573
	}
	for(i = 0; i < 2; i++) {
574
575
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]);
576
577
	}
	for(i = 0; i < 2; i++)
578
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
579

580
	encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
581

Josh Coalson's avatar
Josh Coalson committed
582
583
584
	return encoder;
}

585
FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalson's avatar
Josh Coalson committed
586
{
587
588
	unsigned i;

589
590
591
592
	FLAC__ASSERT(0 != encoder);
	FLAC__ASSERT(0 != encoder->protected_);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->private_->frame);
593

594
595
	encoder->private_->is_being_deleted = true;

596
	(void)FLAC__stream_encoder_finish(encoder);
597

598
	if(0 != encoder->private_->verify.decoder)
Josh Coalson's avatar
Josh Coalson committed
599
		FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
600
601

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
602
603
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
604
605
	}
	for(i = 0; i < 2; i++) {
606
607
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]);
608
609
	}
	for(i = 0; i < 2; i++)
610
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
611

612
	FLAC__bitwriter_delete(encoder->private_->frame);
613
614
	free(encoder->private_);
	free(encoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
615
616
617
	free(encoder);
}

618
619
620
621
622
623
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

624
625
626
627
628
629
630
631
632
633
static FLAC__StreamEncoderInitStatus init_stream_internal_(
	FLAC__StreamEncoder *encoder,
	FLAC__StreamEncoderReadCallback read_callback,
	FLAC__StreamEncoderWriteCallback write_callback,
	FLAC__StreamEncoderSeekCallback seek_callback,
	FLAC__StreamEncoderTellCallback tell_callback,
	FLAC__StreamEncoderMetadataCallback metadata_callback,
	void *client_data,
	FLAC__bool is_ogg
)
Josh Coalson's avatar
Josh Coalson committed
634
635
{
	unsigned i;
636
	FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
Josh Coalson's avatar
Josh Coalson committed
637

638
	FLAC__ASSERT(0 != encoder);
Josh Coalson's avatar
Josh Coalson committed
639

640
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
641
		return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
642

643
#if !FLAC__HAS_OGG
644
645
646
647
	if(is_ogg)
		return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
#endif

648
649
	if(0 == write_callback || (seek_callback && 0 == tell_callback))
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
Josh Coalson's avatar
Josh Coalson committed
650

651
	if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
652
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson's avatar
Josh Coalson committed
653

654
655
656
657
658
659
	if(encoder->protected_->channels != 2) {
		encoder->protected_->do_mid_side_stereo = false;
		encoder->protected_->loose_mid_side_stereo = false;
	}
	else if(!encoder->protected_->do_mid_side_stereo)
		encoder->protected_->loose_mid_side_stereo = false;
660

661
	if(encoder->protected_->bits_per_sample >= 32)
662
		encoder->protected_->do_mid_side_stereo = false; /* since we currenty do 32-bit math, the side channel would have 33 bps and overflow */
Josh Coalson's avatar
Josh Coalson committed
663

664
	if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
665
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
Josh Coalson's avatar
Josh Coalson committed
666

667
	if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
668
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
Josh Coalson's avatar
Josh Coalson committed
669

670
671
672
673
674
675
676
	if(encoder->protected_->blocksize == 0) {
		if(encoder->protected_->max_lpc_order == 0)
			encoder->protected_->blocksize = 1152;
		else
			encoder->protected_->blocksize = 4608;
	}

677
	if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
678
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
Josh Coalson's avatar
Josh Coalson committed
679

680
	if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
681
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
682

683
	if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
684
		return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
685

686
687
	if(encoder->protected_->qlp_coeff_precision == 0) {
		if(encoder->protected_->bits_per_sample < 16) {
Josh Coalson's avatar
Josh Coalson committed
688
689
			/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
			/* @@@ until then we'll make a guess */
690
			encoder->protected_->qlp_coeff_precision = max(FLAC__MIN_QLP_COEFF_PRECISION, 2 + encoder->protected_->bits_per_sample / 2);
Josh Coalson's avatar
Josh Coalson committed
691
		}
692
693
694
695
696
697
698
699
700
701
702
703
704
		else if(encoder->protected_->bits_per_sample == 16) {
			if(encoder->protected_->blocksize <= 192)
				encoder->protected_->qlp_coeff_precision = 7;
			else if(encoder->protected_->blocksize <= 384)
				encoder->protected_->qlp_coeff_precision = 8;
			else if(encoder->protected_->blocksize <= 576)
				encoder->protected_->qlp_coeff_precision = 9;
			else if(encoder->protected_->blocksize <= 1152)
				encoder->protected_->qlp_coeff_precision = 10;
			else if(encoder->protected_->blocksize <= 2304)
				encoder->protected_->qlp_coeff_precision = 11;
			else if(encoder->protected_->blocksize <= 4608)
				encoder->protected_->qlp_coeff_precision = 12;
Josh Coalson's avatar
Josh Coalson committed
705
			else
706
				encoder->protected_->qlp_coeff_precision = 13;
Josh Coalson's avatar
Josh Coalson committed
707
708
		}
		else {
709
710
711
712
713
714
			if(encoder->protected_->blocksize <= 384)
				encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-2;
			else if(encoder->protected_->blocksize <= 1152)
				encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-1;
			else
				encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
715
		}
716
		FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalson's avatar
Josh Coalson committed
717
	}
718
	else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
719
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
720

721
	if(encoder->protected_->streamable_subset) {
722
723
724
725
726
727
728
729
730
731
732
733
734
735
		if(
			encoder->protected_->blocksize != 192 &&
			encoder->protected_->blocksize != 576 &&
			encoder->protected_->blocksize != 1152 &&
			encoder->protected_->blocksize != 2304 &&
			encoder->protected_->blocksize != 4608 &&
			encoder->protected_->blocksize != 256 &&
			encoder->protected_->blocksize != 512 &&
			encoder->protected_->blocksize != 1024 &&
			encoder->protected_->blocksize != 2048 &&
			encoder->protected_->blocksize != 4096 &&
			encoder->protected_->blocksize != 8192 &&
			encoder->protected_->blocksize != 16384
		)
736
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
737
738
739
740
741
742
743
744
745
746
		if(
			encoder->protected_->sample_rate != 8000 &&
			encoder->protected_->sample_rate != 16000 &&
			encoder->protected_->sample_rate != 22050 &&
			encoder->protected_->sample_rate != 24000 &&
			encoder->protected_->sample_rate != 32000 &&
			encoder->protected_->sample_rate != 44100 &&
			encoder->protected_->sample_rate != 48000 &&
			encoder->protected_->sample_rate != 96000
		)
747
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
748
749
750
751
752
753
754
		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
		)
755
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
756
		if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
757
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
758
759
760
761
762
763
764
765
766
		if(
			encoder->protected_->sample_rate <= 48000 &&
			(
				encoder->protected_->blocksize > FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ ||
				encoder->protected_->max_lpc_order > FLAC__SUBSET_MAX_LPC_ORDER_48000HZ
			)
		) {
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
		}
Josh Coalson's avatar
Josh Coalson committed
767
768
	}

769
770
771
772
	if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
		encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
	if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
		encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalson's avatar
Josh Coalson committed
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
#if FLAC__HAS_OGG
	/* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
	if(is_ogg && 0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 1) {
		unsigned i;
		for(i = 1; i < encoder->protected_->num_metadata_blocks; i++) {
			if(0 != encoder->protected_->metadata[i] && encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
				FLAC__StreamMetadata *vc = encoder->protected_->metadata[i];
				for( ; i > 0; i--)
					encoder->protected_->metadata[i] = encoder->protected_->metadata[i-1];
				encoder->protected_->metadata[0] = vc;
				break;
			}
		}
	}
#endif
	/* keep track of any SEEKTABLE block */
	if(0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) {
		unsigned i;
		for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
			if(0 != encoder->protected_->metadata[i] && encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
				encoder->private_->seek_table = &encoder->protected_->metadata[i]->data.seek_table;
				break; /* take only the first one */
			}
		}
	}

800
801
	/* validate metadata */
	if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
802
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
803
804
	metadata_has_seektable = false;
	metadata_has_vorbis_comment = false;
805
806
	metadata_picture_has_type1 = false;
	metadata_picture_has_type2 = false;
807
	for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
808
809
		const FLAC__StreamMetadata *m = encoder->protected_->metadata[i];
		if(m->type == FLAC__METADATA_TYPE_STREAMINFO)
810
			return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
811
		else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
812
			if(metadata_has_seektable) /* only one is allowed */
813
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
814
			metadata_has_seektable = true;
815
			if(!FLAC__format_seektable_is_legal(&m->data.seek_table))
816
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
817
		}
818
		else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
Josh Coalson's avatar
Josh Coalson committed
819
			if(metadata_has_vorbis_comment) /* only one is allowed */
820
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
821
822
			metadata_has_vorbis_comment = true;
		}
823
824
		else if(m->type == FLAC__METADATA_TYPE_CUESHEET) {
			if(!FLAC__format_cuesheet_is_legal(&m->data.cue_sheet, m->data.cue_sheet.is_cd, /*violation=*/0))
825
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
826
		}
827
828
		else if(m->type == FLAC__METADATA_TYPE_PICTURE) {
			if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0))
829
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
			if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) {
				if(metadata_picture_has_type1) /* there should only be 1 per stream */
					return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
				metadata_picture_has_type1 = true;
				/* standard icon must be 32x32 pixel PNG */
				if(
					m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD && 
					(
						(strcmp(m->data.picture.mime_type, "image/png") && strcmp(m->data.picture.mime_type, "-->")) ||
						m->data.picture.width != 32 ||
						m->data.picture.height != 32
					)
				)
					return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
			}
			else if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) {
				if(metadata_picture_has_type2) /* there should only be 1 per stream */
					return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
				metadata_picture_has_type2 = true;
			}
850
		}
851
852
	}

853
854
855
	encoder->private_->input_capacity = 0;
	for(i = 0; i < encoder->protected_->channels; i++) {
		encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
856
#ifndef FLAC__INTEGER_ONLY_LIBRARY
857
		encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
858
#endif
Josh Coalson's avatar
Josh Coalson committed
859
860
	}
	for(i = 0; i < 2; i++) {
861
		encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
862
#ifndef FLAC__INTEGER_ONLY_LIBRARY
863
		encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
864
#endif
Josh Coalson's avatar
Josh Coalson committed
865
	}
866
867
868
869
870
#ifndef FLAC__INTEGER_ONLY_LIBRARY
	for(i = 0; i < encoder->protected_->num_apodizations; i++)
		encoder->private_->window_unaligned[i] = encoder->private_->window[i] = 0;
	encoder->private_->windowed_signal_unaligned = encoder->private_->windowed_signal = 0;
#endif
871
872
873
874
	for(i = 0; i < encoder->protected_->channels; i++) {
		encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
		encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
		encoder->private_->best_subframe[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
875
876
	}
	for(i = 0; i < 2; i++) {
877
878
879
		encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
		encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
		encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
880
	}
881
882
	encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
	encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
883
884
885
886
887
888
889
890
891
892
893
#ifndef FLAC__INTEGER_ONLY_LIBRARY
	encoder->private_->loose_mid_side_stereo_frames = (unsigned)((FLAC__double)encoder->protected_->sample_rate * 0.4 / (FLAC__double)encoder->protected_->blocksize + 0.5);
#else
	/* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */
	/* sample rate can be up to 655350 Hz, and thus use 20 bits, so we do the multiply&divide by hand */
	FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 655350);
	FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535);
	FLAC__ASSERT(encoder->protected_->sample_rate <= 655350);
	FLAC__ASSERT(encoder->protected_->blocksize <= 65535);
	encoder->private_->loose_mid_side_stereo_frames = (unsigned)FLAC__fixedpoint_trunc((((FLAC__uint64)(encoder->protected_->sample_rate) * (FLAC__uint64)(26214)) << 16) / (encoder->protected_->blocksize<<16) + FLAC__FP_ONE_HALF);
#endif
894
895
896
897
898
899
900
901
902
	if(encoder->private_->loose_mid_side_stereo_frames == 0)
		encoder->private_->loose_mid_side_stereo_frames = 1;
	encoder->private_->loose_mid_side_stereo_frame_count = 0;
	encoder->private_->current_sample_number = 0;
	encoder->private_->current_frame_number = 0;

	encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
	encoder->private_->use_wide_by_order = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(max(encoder->protected_->max_lpc_order, FLAC__MAX_FIXED_ORDER))+1 > 30); /*@@@ need to use this? */
	encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
903

904
905
906
	/*
	 * get the CPU info and set the function pointers
	 */
907
	FLAC__cpu_info(&encoder->private_->cpuinfo);
908
	/* first default to the non-asm routines */
909
#ifndef FLAC__INTEGER_ONLY_LIBRARY
910
	encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
911
#endif
912
	encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
913
#ifndef FLAC__INTEGER_ONLY_LIBRARY
914
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
915
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
916
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
917
#endif
918
	/* now override with asm where appropriate */
919
920
#ifndef FLAC__INTEGER_ONLY_LIBRARY
# ifndef FLAC__NO_ASM
921
	if(encoder->private_->cpuinfo.use_asm) {
922
#  ifdef FLAC__CPU_IA32
923
		FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
924
925
#   ifdef FLAC__HAS_NASM
#    ifdef FLAC__SSE_OS
926
		if(encoder->private_->cpuinfo.data.ia32.sse) {
927
928
929
930
931
932
			if(encoder->protected_->max_lpc_order < 4)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
			else if(encoder->protected_->max_lpc_order < 8)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
			else if(encoder->protected_->max_lpc_order < 12)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
933
			else
934
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
935
		}
936
		else
937
#    endif /* FLAC__SSE_OS */
938
		if(encoder->private_->cpuinfo.data.ia32._3dnow)
939
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
940
		else
941
942
943
944
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
		if(encoder->private_->cpuinfo.data.ia32.mmx) {
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx;
945
946
		}
		else {
947
948
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
949
		}
950
951
952
953
		if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
			encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
#   endif /* FLAC__HAS_NASM */
#  endif /* FLAC__CPU_IA32 */
954
	}
955
956
# endif /* !FLAC__NO_ASM */
#endif /* !FLAC__INTEGER_ONLY_LIBRARY */
957
	/* finally override based on wide-ness if necessary */
958
959
	if(encoder->private_->use_wide_by_block) {
		encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
960
	}
961

962
963
964
	/* set state to OK; from here on, errors are fatal and we'll override the state then */
	encoder->protected_->state = FLAC__STREAM_ENCODER_OK;

965
966
967
968
969
970
971
972
973
#if FLAC__HAS_OGG
	encoder->private_->is_ogg = is_ogg;
	if(is_ogg && !FLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
	}
#endif

	encoder->private_->read_callback = read_callback;
974
975
976
977
978
979
	encoder->private_->write_callback = write_callback;
	encoder->private_->seek_callback = seek_callback;
	encoder->private_->tell_callback = tell_callback;
	encoder->private_->metadata_callback = metadata_callback;
	encoder->private_->client_data = client_data;

980
	if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalson's avatar
Josh Coalson committed
981
		/* the above function sets the state for us in case of an error */
982
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalson's avatar
Josh Coalson committed
983
	}
984

985
	if(!FLAC__bitwriter_init(encoder->private_->frame)) {
986
987
988
		encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
	}
Josh Coalson's avatar
Josh Coalson committed
989

Josh Coalson's avatar
Josh Coalson committed
990
991
992
993
994
995
996
997
	/*
	 * Set up the verify stuff if necessary
	 */
	if(encoder->protected_->verify) {
		/*
		 * First, set up the fifo which will hold the
		 * original signal to compare against
		 */
998
		encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize+OVERREAD_;
Josh Coalson's avatar
Josh Coalson committed
999
		for(i = 0; i < encoder->protected_->channels; i++) {
1000
1001
1002
1003
			if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size))) {
				encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
				return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
			}
Josh Coalson's avatar
Josh Coalson committed
1004
1005
1006
1007
1008
1009
1010
		}
		encoder->private_->verify.input_fifo.tail = 0;

		/*
		 * Now set up a stream decoder for verification
		 */
		encoder->private_->verify.decoder = FLAC__stream_decoder_new();
1011
1012
1013
1014
		if(0 == encoder->private_->verify.decoder) {
			encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
			return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
		}
Josh Coalson's avatar
Josh Coalson committed
1015

1016
1017
1018
1019
		if(FLAC__stream_decoder_init_stream(encoder->private_->verify.decoder, verify_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, verify_write_callback_, verify_metadata_callback_, verify_error_callback_, /*client_data=*/encoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
			encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
			return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
		}