stream_encoder.c 170 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,2008,2009  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 "share/alloc.h"
58
#include "protected/stream_encoder.h"
59
#include "private/bitwriter.h"
60
#include "private/bitmath.h"
61
#include "private/crc.h"
62
#include "private/cpu.h"
Josh Coalson's avatar
Josh Coalson committed
63
#include "private/fixed.h"
64
#include "private/format.h"
Josh Coalson's avatar
Josh Coalson committed
65
#include "private/lpc.h"
Josh Coalson's avatar
Josh Coalson committed
66
#include "private/md5.h"
67
#include "private/memory.h"
68
#if FLAC__HAS_OGG
69
#include "private/ogg_helper.h"
70
#include "private/ogg_mapping.h"
71
#endif
72
#include "private/stream_encoder_framing.h"
73
#include "private/window.h"
Josh Coalson's avatar
Josh Coalson committed
74

75
76
77
78
#ifndef FLaC__INLINE
#define FLaC__INLINE
#endif

Josh Coalson's avatar
Josh Coalson committed
79
80
81
82
83
84
85
86
87
88
#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))

89
90
91
92
93
94
95
96
97
98
99
100
/* 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 

101

Josh Coalson's avatar
Josh Coalson committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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;

120
121
122
123
124
125
126
127
128
129
130
131
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_[] = {
132
133
	{ false, false,  0, 0, false, false, false, 0, 3, 0 },
	{ true , true ,  0, 0, false, false, false, 0, 3, 0 },
134
	{ true , false,  0, 0, false, false, false, 0, 3, 0 },
135
136
137
138
	{ false, false,  6, 0, false, false, false, 0, 4, 0 },
	{ true , true ,  8, 0, false, false, false, 0, 4, 0 },
	{ true , false,  8, 0, false, false, false, 0, 5, 0 },
	{ true , false,  8, 0, false, false, false, 0, 6, 0 },
139
140
	{ true , false,  8, 0, false, false, true , 0, 6, 0 },
	{ true , false, 12, 0, false, false, true , 0, 6, 0 }
141
142
143
};


144
145
146
147
148
149
/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

150
151
static void set_defaults_(FLAC__StreamEncoder *encoder);
static void free_(FLAC__StreamEncoder *encoder);
152
static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize);
153
154
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);
155
static void update_metadata_(const FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
156
#if FLAC__HAS_OGG
157
static void update_ogg_metadata_(FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
158
#endif
159
static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block);
160
static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block);
Josh Coalson's avatar
Josh Coalson committed
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

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[],
	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,
178
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
179
180
	unsigned subframe_bps,
	const FLAC__Subframe *subframe,
181
	FLAC__BitWriter *frame
Josh Coalson's avatar
Josh Coalson committed
182
183
184
);

static unsigned evaluate_constant_subframe_(
185
	FLAC__StreamEncoder *encoder,
Josh Coalson's avatar
Josh Coalson committed
186
	const FLAC__int32 signal,
187
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
	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,
202
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
203
204
205
206
207
208
209
210
	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
);

211
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
212
213
214
215
216
217
218
219
220
221
222
223
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,
224
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
225
226
227
228
229
230
231
	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
);
232
#endif
Josh Coalson's avatar
Josh Coalson committed
233
234

static unsigned evaluate_verbatim_subframe_(
235
	FLAC__StreamEncoder *encoder, 
Josh Coalson's avatar
Josh Coalson committed
236
237
238
239
240
241
242
243
244
245
246
247
248
249
	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,
250
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
251
252
	unsigned min_partition_order,
	unsigned max_partition_order,
253
	unsigned bps,
Josh Coalson's avatar
Josh Coalson committed
254
255
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
256
	FLAC__EntropyCodingMethod *best_ecm
Josh Coalson's avatar
Josh Coalson committed
257
258
259
);

static void precompute_partition_info_sums_(
260
	const FLAC__int32 residual[],
Josh Coalson's avatar
Josh Coalson committed
261
262
263
264
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned residual_samples,
	unsigned predictor_order,
	unsigned min_partition_order,
265
266
	unsigned max_partition_order,
	unsigned bps
Josh Coalson's avatar
Josh Coalson committed
267
268
269
270
271
272
273
274
275
276
277
278
);

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_(
279
#ifdef EXACT_RICE_BITS_CALCULATION
Josh Coalson's avatar
Josh Coalson committed
280
	const FLAC__int32 residual[],
281
#endif
Josh Coalson's avatar
Josh Coalson committed
282
283
284
285
286
	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,
287
	const unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
288
289
290
291
292
293
294
	const unsigned rice_parameter_search_dist,
	const unsigned partition_order,
	const FLAC__bool search_for_escapes,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
	unsigned *bits
);

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

Josh Coalson's avatar
Josh Coalson committed
297
/* verify-related routines: */
Josh Coalson's avatar
Josh Coalson committed
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
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
);

314
static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
315
316
317
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
318

319
static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
320
321
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);
322
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);
323
static FILE *get_binary_stdout_(void);
Josh Coalson's avatar
Josh Coalson committed
324

325
326
327
328
329
330
331
332

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

typedef struct FLAC__StreamEncoderPrivate {
333
	unsigned input_capacity;                          /* current size (in samples) of the signal and residual buffers */
Josh Coalson's avatar
Josh Coalson committed
334
335
	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) */
336
#ifndef FLAC__INTEGER_ONLY_LIBRARY
337
338
	FLAC__real *real_signal[FLAC__MAX_CHANNELS];      /* (@@@ currently unused) the floating-point version of the input signal */
	FLAC__real *real_signal_mid_side[2];              /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */
339
	FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
340
	FLAC__real *windowed_signal;                      /* the integer_signal[] * current window[] */
341
#endif
342
343
	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
344
345
	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
346
347
348
349
	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];
350
351
352
353
	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];
354
	unsigned best_subframe[FLAC__MAX_CHANNELS];       /* index (0 or 1) into 2nd dimension of the above workspaces */
Josh Coalson's avatar
Josh Coalson committed
355
	unsigned best_subframe_mid_side[2];
356
	unsigned best_subframe_bits[FLAC__MAX_CHANNELS];  /* size in bits of the best subframe for each channel */
Josh Coalson's avatar
Josh Coalson committed
357
	unsigned best_subframe_bits_mid_side[2];
358
	FLAC__uint64 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
359
	unsigned *raw_bits_per_partition;                 /* workspace where the sum of silog2(candidate residual) for each partition is stored */
360
	FLAC__BitWriter *frame;                           /* the current frame being worked on */
361
362
	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 */
363
	FLAC__ChannelAssignment last_channel_assignment;
364
365
	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
366
367
	unsigned current_sample_number;
	unsigned current_frame_number;
368
	FLAC__MD5Context md5context;
369
	FLAC__CPUInfo cpuinfo;
370
#ifndef FLAC__INTEGER_ONLY_LIBRARY
371
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
372
373
374
375
#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
376
	void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
377
378
379
	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[]);
380
#endif
381
382
383
	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 */
384
385
386
	FLAC__bool disable_constant_subframes;
	FLAC__bool disable_fixed_subframes;
	FLAC__bool disable_verbatim_subframes;
387
388
389
390
#if FLAC__HAS_OGG
	FLAC__bool is_ogg;
#endif
	FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */
391
392
	FLAC__StreamEncoderSeekCallback seek_callback;
	FLAC__StreamEncoderTellCallback tell_callback;
Josh Coalson's avatar
Josh Coalson committed
393
394
	FLAC__StreamEncoderWriteCallback write_callback;
	FLAC__StreamEncoderMetadataCallback metadata_callback;
395
	FLAC__StreamEncoderProgressCallback progress_callback;
Josh Coalson's avatar
Josh Coalson committed
396
	void *client_data;
397
398
399
400
401
402
	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;
403
	/* unaligned (original) pointers to allocated data */
Josh Coalson's avatar
Josh Coalson committed
404
405
	FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__int32 *integer_signal_mid_side_unaligned[2];
406
#ifndef FLAC__INTEGER_ONLY_LIBRARY
407
408
	FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) */
	FLAC__real *real_signal_mid_side_unaligned[2]; /* (@@@ currently unused) */
409
410
	FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
	FLAC__real *windowed_signal_unaligned;
411
#endif
Josh Coalson's avatar
Josh Coalson committed
412
413
	FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
	FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
414
	FLAC__uint64 *abs_residual_partition_sums_unaligned;
415
	unsigned *raw_bits_per_partition_unaligned;
416
417
418
419
	/*
	 * These fields have been moved here from private function local
	 * declarations merely to save stack space during encoding.
	 */
420
#ifndef FLAC__INTEGER_ONLY_LIBRARY
421
	FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
422
#endif
423
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalson's avatar
Josh Coalson committed
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
	/*
	 * 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;
442
	FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
443
} FLAC__StreamEncoderPrivate;
Josh Coalson's avatar
Josh Coalson committed
444

445
446
447
448
449
450
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/

451
FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
452
	"FLAC__STREAM_ENCODER_OK",
453
	"FLAC__STREAM_ENCODER_UNINITIALIZED",
454
	"FLAC__STREAM_ENCODER_OGG_ERROR",
Josh Coalson's avatar
Josh Coalson committed
455
456
	"FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
	"FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
457
458
	"FLAC__STREAM_ENCODER_CLIENT_ERROR",
	"FLAC__STREAM_ENCODER_IO_ERROR",
459
	"FLAC__STREAM_ENCODER_FRAMING_ERROR",
460
461
462
463
464
465
	"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",
466
	"FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
467
468
469
470
471
472
473
474
475
476
477
	"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
478
479
};

480
481
482
483
484
485
486
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"
};

487
FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
488
489
	"FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
	"FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalson's avatar
Josh Coalson committed
490
491
};

492
493
494
495
496
497
498
499
500
501
502
503
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"
};

504
505
506
507
508
509
510
511
512
513
514
515
516
/* 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;

517
518
519
520
/***********************************************************************
 *
 * Class constructor/destructor
 *
Josh Coalson's avatar
Josh Coalson committed
521
 */
522
FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void)
Josh Coalson's avatar
Josh Coalson committed
523
{
524
	FLAC__StreamEncoder *encoder;
525
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
526

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

529
	encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder));
530
531
	if(encoder == 0) {
		return 0;
532
	}
Josh Coalson's avatar
Josh Coalson committed
533

534
	encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected));
535
	if(encoder->protected_ == 0) {
536
537
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
538
	}
Josh Coalson's avatar
Josh Coalson committed
539

540
	encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
541
542
	if(encoder->private_ == 0) {
		free(encoder->protected_);
543
544
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
545
	}
Josh Coalson's avatar
Josh Coalson committed
546

547
	encoder->private_->frame = FLAC__bitwriter_new();
548
549
550
551
552
553
	if(encoder->private_->frame == 0) {
		free(encoder->private_);
		free(encoder->protected_);
		free(encoder);
		return 0;
	}
554

555
556
	encoder->private_->file = 0;

557
	set_defaults_(encoder);
558

559
	encoder->private_->is_being_deleted = false;
560
561
562
563
564
565
566
567
568
569

	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++) {
570
571
		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];
572
573
	}
	for(i = 0; i < 2; i++) {
574
575
		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];
576
577
578
	}

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
579
580
		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]);
581
582
	}
	for(i = 0; i < 2; i++) {
583
584
		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]);
585
586
	}
	for(i = 0; i < 2; i++)
587
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
588

589
	encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
590

Josh Coalson's avatar
Josh Coalson committed
591
592
593
	return encoder;
}

594
FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalson's avatar
Josh Coalson committed
595
{
596
597
	unsigned i;

598
599
600
601
	FLAC__ASSERT(0 != encoder);
	FLAC__ASSERT(0 != encoder->protected_);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->private_->frame);
602

603
604
	encoder->private_->is_being_deleted = true;

605
	(void)FLAC__stream_encoder_finish(encoder);
606

607
	if(0 != encoder->private_->verify.decoder)
Josh Coalson's avatar
Josh Coalson committed
608
		FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
609
610

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
611
612
		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]);
613
614
	}
	for(i = 0; i < 2; i++) {
615
616
		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]);
617
618
	}
	for(i = 0; i < 2; i++)
619
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
620

621
	FLAC__bitwriter_delete(encoder->private_->frame);
622
623
	free(encoder->private_);
	free(encoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
624
625
626
	free(encoder);
}

627
628
629
630
631
632
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

633
634
635
636
637
638
639
640
641
642
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
643
644
{
	unsigned i;
645
	FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
Josh Coalson's avatar
Josh Coalson committed
646

647
	FLAC__ASSERT(0 != encoder);
Josh Coalson's avatar
Josh Coalson committed
648

649
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
650
		return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
651

652
#if !FLAC__HAS_OGG
653
654
655
656
	if(is_ogg)
		return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
#endif

657
658
	if(0 == write_callback || (seek_callback && 0 == tell_callback))
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
Josh Coalson's avatar
Josh Coalson committed
659

660
	if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
661
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson's avatar
Josh Coalson committed
662

663
664
665
666
667
668
	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;
669

670
	if(encoder->protected_->bits_per_sample >= 32)
671
		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
672

673
	if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
674
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
Josh Coalson's avatar
Josh Coalson committed
675

676
	if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
677
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
Josh Coalson's avatar
Josh Coalson committed
678

679
680
681
682
	if(encoder->protected_->blocksize == 0) {
		if(encoder->protected_->max_lpc_order == 0)
			encoder->protected_->blocksize = 1152;
		else
683
			encoder->protected_->blocksize = 4096;
684
685
	}

686
	if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
687
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
Josh Coalson's avatar
Josh Coalson committed
688

689
	if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
690
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
691

692
	if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
693
		return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
694

695
696
	if(encoder->protected_->qlp_coeff_precision == 0) {
		if(encoder->protected_->bits_per_sample < 16) {
Josh Coalson's avatar
Josh Coalson committed
697
698
			/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
			/* @@@ until then we'll make a guess */
699
			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
700
		}
701
702
703
704
705
706
707
708
709
710
711
712
713
		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
714
			else
715
				encoder->protected_->qlp_coeff_precision = 13;
Josh Coalson's avatar
Josh Coalson committed
716
717
		}
		else {
718
719
720
721
722
723
			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
724
		}
725
		FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalson's avatar
Josh Coalson committed
726
	}
727
	else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
728
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
729

730
	if(encoder->protected_->streamable_subset) {
731
		if(!FLAC__format_blocksize_is_subset(encoder->protected_->blocksize, encoder->protected_->sample_rate))
732
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
733
		if(!FLAC__format_sample_rate_is_subset(encoder->protected_->sample_rate))
734
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
735
736
737
738
739
740
741
		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
		)
742
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
743
		if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
744
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
745
746
747
748
749
750
751
752
753
		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
754
755
	}

756
757
758
759
	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
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
#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 */
			}
		}
	}

787
788
	/* validate metadata */
	if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
789
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
790
791
	metadata_has_seektable = false;
	metadata_has_vorbis_comment = false;
792
793
	metadata_picture_has_type1 = false;
	metadata_picture_has_type2 = false;
794
	for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
795
796
		const FLAC__StreamMetadata *m = encoder->protected_->metadata[i];
		if(m->type == FLAC__METADATA_TYPE_STREAMINFO)
797
			return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
798
		else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
799
			if(metadata_has_seektable) /* only one is allowed */
800
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
801
			metadata_has_seektable = true;
802
			if(!FLAC__format_seektable_is_legal(&m->data.seek_table))
803
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
804
		}
805
		else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
Josh Coalson's avatar
Josh Coalson committed
806
			if(metadata_has_vorbis_comment) /* only one is allowed */
807
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
808
809
			metadata_has_vorbis_comment = true;
		}
810
811
		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))
812
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
813
		}
814
815
		else if(m->type == FLAC__METADATA_TYPE_PICTURE) {
			if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0))
816
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
			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;
			}
837
		}
838
839
	}

840
841
842
	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;
843
#ifndef FLAC__INTEGER_ONLY_LIBRARY
844
		encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
845
#endif
Josh Coalson's avatar
Josh Coalson committed
846
847
	}
	for(i = 0; i < 2; i++) {
848
		encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
849
#ifndef FLAC__INTEGER_ONLY_LIBRARY
850
		encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
851
#endif
Josh Coalson's avatar
Josh Coalson committed
852
	}
853
854
855
856
857
#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
858
859
860
861
	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
862
863
	}
	for(i = 0; i < 2; i++) {
864
865
866
		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
867
	}
868
869
	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;
870
871
872
873
874
875
876
877
878
879
880
#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
881
882
883
884
885
886
887
888
889
	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 */
890

891
892
893
	/*
	 * get the CPU info and set the function pointers
	 */
894
	FLAC__cpu_info(&encoder->private_->cpuinfo);
895
	/* first default to the non-asm routines */
896
#ifndef FLAC__INTEGER_ONLY_LIBRARY
897
	encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
898
#endif
899
	encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
900
#ifndef FLAC__INTEGER_ONLY_LIBRARY
901
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
902
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
903
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
904
#endif
905
	/* now override with asm where appropriate */
906
907
#ifndef FLAC__INTEGER_ONLY_LIBRARY
# ifndef FLAC__NO_ASM
908
	if(encoder->private_->cpuinfo.use_asm) {
909
#  ifdef FLAC__CPU_IA32
910
		FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
911
#   ifdef FLAC__HAS_NASM
912
		if(encoder->private_->cpuinfo.data.ia32.sse) {
913
914
915
916
917
918
			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;
919
			else
920
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
921
		}
922
		else if(encoder->private_->cpuinfo.data.ia32._3dnow)
923
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
924
		else
925
926
927
928
			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;
929
930
		}
		else {
931
932
			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;
933
		}
934
935
936
937
		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 */
938
	}
939
940
# endif /* !FLAC__NO_ASM */
#endif /* !FLAC__INTEGER_ONLY_LIBRARY */
941
	/* finally override based on wide-ness if necessary */
942
943
	if(encoder->private_->use_wide_by_block) {
		encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
944
	}
945

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

949
950
951
952
953
954
955
956
957
#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;
958
959
960
961
962
963
	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;

964
	if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalson's avatar
Josh Coalson committed
965
		/* the above function sets the state for us in case of an error */
966
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalson's avatar
Josh Coalson committed
967
	}
968

969
	if(!FLAC__bitwriter_init(encoder->private_->frame)) {
970
971
972
		encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
	}
Josh Coalson's avatar
Josh Coalson committed
973

Josh Coalson's avatar
Josh Coalson committed
974
975
976
977
978
979
980
981
	/*
	 * 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
		 */
982
		encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize+OVERREAD_;
Josh Coalson's avatar
Josh Coalson committed
983
		for(i = 0; i < encoder->protected_->channels; i++) {
984
			if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)safe_malloc_mul_2op_(sizeof(FLAC__int32), /*times*/encoder->private_->verify.input_fifo.size))) {
985
986
987
				encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
				return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
			}
Josh Coalson's avatar
Josh Coalson committed
988
989
990
991
992
993
		}
		encoder->private_->verify.input_fifo.tail = 0;

		/*
		 * Now set up a stream decoder for verification
		 */
994
		if(0 == encoder->private_->verify.decoder) {
995
996
997
998
999
			encoder->private_->verify.decoder = FLAC__stream_decoder_new();
			if(0 == encoder->private_->verify.decoder) {
				encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
				return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
			}
1000
		}
Josh Coalson's avatar
Josh Coalson committed
1001

1002
1003
1004
1005
		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;
		}
Josh Coalson's avatar
Josh Coalson committed
1006
	}
1007
1008