stream_encoder.c 186 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  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
50
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
#if _MSC_VER <= 1200 || 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"
Josh Coalson's avatar
Josh Coalson committed
58
#include "private/bitbuffer.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))

Josh Coalson's avatar
Josh Coalson committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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;

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
static struct CompressionLevels {
	FLAC__bool do_mid_side_stereo;
	FLAC__bool loose_mid_side_stereo;
	const char *apodization;
	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_[] = {
	{ false, false, "tukey(0.5)",  0, 0, false, false, false, 2, 2, 0 },
	{ true , true , "tukey(0.5)",  0, 0, false, false, false, 2, 2, 0 },
	{ true , false, "tukey(0.5)",  0, 0, false, false, false, 0, 3, 0 },
	{ false, false, "tukey(0.5)",  6, 0, false, false, false, 3, 3, 0 },
	{ true , true , "tukey(0.5)",  8, 0, false, false, false, 3, 3, 0 },
	{ true , false, "tukey(0.5)",  8, 0, false, false, false, 3, 3, 0 },
	{ true , false, "tukey(0.5)",  8, 0, false, false, false, 0, 4, 0 },
	{ true , false, "tukey(0.5)",  8, 0, false, false, true , 0, 6, 0 },
	{ true , false, "tukey(0.5)", 12, 0, false, false, true , 0, 6, 0 }
};


127
128
129
130
131
132
/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

133
134
static void set_defaults_(FLAC__StreamEncoder *encoder);
static void free_(FLAC__StreamEncoder *encoder);
135
static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize);
136
137
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);
138
static void update_metadata_(const FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
139
#if FLAC__HAS_OGG
140
static void update_ogg_metadata_(FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
141
#endif
142
static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block);
143
static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block);
Josh Coalson's avatar
Josh Coalson committed
144
145
146
147
148
149
150
151
152

static FLAC__bool process_subframe_(
	FLAC__StreamEncoder *encoder,
	unsigned min_partition_order,
	unsigned max_partition_order,
	FLAC__bool precompute_partition_sums,
	const FLAC__FrameHeader *frame_header,
	unsigned subframe_bps,
	const FLAC__int32 integer_signal[],
153
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
154
	const FLAC__real real_signal[],
155
#endif
Josh Coalson's avatar
Josh Coalson committed
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	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,
	const FLAC__FrameHeader *frame_header,
	unsigned subframe_bps,
	const FLAC__Subframe *subframe,
	FLAC__BitBuffer *frame
);

static unsigned evaluate_constant_subframe_(
	const FLAC__int32 signal,
	unsigned subframe_bps,
	FLAC__Subframe *subframe
);

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

197
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
static unsigned evaluate_lpc_subframe_(
	FLAC__StreamEncoder *encoder,
	const FLAC__int32 signal[],
	FLAC__int32 residual[],
	FLAC__uint32 abs_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 precompute_partition_sums,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__Subframe *subframe,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
);
219
#endif
Josh Coalson's avatar
Josh Coalson committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

static unsigned evaluate_verbatim_subframe_(
	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__uint32 abs_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 precompute_partition_sums,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__EntropyCodingMethod_PartitionedRice *best_partitioned_rice
);

static void precompute_partition_info_sums_(
	const FLAC__uint32 abs_residual[],
	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
);

263
#ifdef DONT_ESTIMATE_RICE_BITS
Josh Coalson's avatar
Josh Coalson committed
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
static FLAC__bool set_partitioned_rice_(
	const FLAC__uint32 abs_residual[],
	const FLAC__int32 residual[],
	const unsigned residual_samples,
	const unsigned predictor_order,
	const unsigned suggested_rice_parameter,
	const unsigned rice_parameter_search_dist,
	const unsigned partition_order,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
	unsigned *bits
);

static FLAC__bool set_partitioned_rice_with_precompute_(
	const FLAC__int32 residual[],
	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
);
289
#else
Josh Coalson's avatar
Josh Coalson committed
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
static FLAC__bool set_partitioned_rice_(
	const FLAC__uint32 abs_residual[],
	const unsigned residual_samples,
	const unsigned predictor_order,
	const unsigned suggested_rice_parameter,
	const unsigned rice_parameter_search_dist,
	const unsigned partition_order,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
	unsigned *bits
);

static FLAC__bool set_partitioned_rice_with_precompute_(
	const FLAC__uint32 abs_residual[],
	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
);
314
#endif
Josh Coalson's avatar
Josh Coalson committed
315

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

Josh Coalson's avatar
Josh Coalson committed
318
/* verify-related routines: */
Josh Coalson's avatar
Josh Coalson committed
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
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
);

335
static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
336
337
338
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
339

340
static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
341
342
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);
343
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);
344
static FILE *get_binary_stdout_();
Josh Coalson's avatar
Josh Coalson committed
345

346
347
348
349
350
351
352
353

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

typedef struct FLAC__StreamEncoderPrivate {
354
	unsigned input_capacity;                          /* current size (in samples) of the signal and residual buffers */
Josh Coalson's avatar
Josh Coalson committed
355
356
	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) */
357
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
358
359
	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) */
360
361
	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[] */
362
#endif
363
364
	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
365
366
	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
367
368
369
370
	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];
371
372
373
374
	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];
375
	unsigned best_subframe[FLAC__MAX_CHANNELS];       /* index into the above workspaces */
Josh Coalson's avatar
Josh Coalson committed
376
	unsigned best_subframe_mid_side[2];
377
	unsigned best_subframe_bits[FLAC__MAX_CHANNELS];  /* size in bits of the best subframe for each channel */
Josh Coalson's avatar
Josh Coalson committed
378
	unsigned best_subframe_bits_mid_side[2];
Josh Coalson's avatar
Josh Coalson committed
379
	FLAC__uint32 *abs_residual;                       /* workspace where abs(candidate residual) is stored */
380
	FLAC__uint64 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
381
	unsigned *raw_bits_per_partition;                 /* workspace where the sum of silog2(candidate residual) for each partition is stored */
382
	FLAC__BitBuffer *frame;                           /* the current frame being worked on */
383
384
	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 */
385
	FLAC__ChannelAssignment last_channel_assignment;
386
387
	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
388
389
	unsigned current_sample_number;
	unsigned current_frame_number;
390
	struct FLAC__MD5Context md5context;
391
	FLAC__CPUInfo cpuinfo;
392
#ifndef FLAC__INTEGER_ONLY_LIBRARY
393
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
394
395
396
397
#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
398
	void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
399
400
401
	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[]);
402
#endif
403
404
405
406
	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 */
	FLAC__bool precompute_partition_sums;  /* our initial guess as to whether precomputing the partitions sums will be a speed improvement */
407
408
409
	FLAC__bool disable_constant_subframes;
	FLAC__bool disable_fixed_subframes;
	FLAC__bool disable_verbatim_subframes;
410
411
412
413
#if FLAC__HAS_OGG
	FLAC__bool is_ogg;
#endif
	FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */
414
415
	FLAC__StreamEncoderSeekCallback seek_callback;
	FLAC__StreamEncoderTellCallback tell_callback;
Josh Coalson's avatar
Josh Coalson committed
416
417
	FLAC__StreamEncoderWriteCallback write_callback;
	FLAC__StreamEncoderMetadataCallback metadata_callback;
418
	FLAC__StreamEncoderProgressCallback progress_callback;
Josh Coalson's avatar
Josh Coalson committed
419
	void *client_data;
420
421
422
423
424
425
	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;
426
	/* unaligned (original) pointers to allocated data */
Josh Coalson's avatar
Josh Coalson committed
427
428
	FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__int32 *integer_signal_mid_side_unaligned[2];
429
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
430
431
	FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__real *real_signal_mid_side_unaligned[2];
432
433
	FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
	FLAC__real *windowed_signal_unaligned;
434
#endif
Josh Coalson's avatar
Josh Coalson committed
435
436
437
	FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
	FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
	FLAC__uint32 *abs_residual_unaligned;
438
	FLAC__uint64 *abs_residual_partition_sums_unaligned;
439
	unsigned *raw_bits_per_partition_unaligned;
440
441
442
443
	/*
	 * These fields have been moved here from private function local
	 * declarations merely to save stack space during encoding.
	 */
444
#ifndef FLAC__INTEGER_ONLY_LIBRARY
445
	FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
446
#endif
447
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalson's avatar
Josh Coalson committed
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
	/*
	 * 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;
466
	FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
467
} FLAC__StreamEncoderPrivate;
Josh Coalson's avatar
Josh Coalson committed
468

469
470
471
472
473
474
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/

475
FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
476
	"FLAC__STREAM_ENCODER_OK",
477
	"FLAC__STREAM_ENCODER_UNINITIALIZED",
478
	"FLAC__STREAM_ENCODER_OGG_ERROR",
Josh Coalson's avatar
Josh Coalson committed
479
480
	"FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
	"FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
481
482
	"FLAC__STREAM_ENCODER_CLIENT_ERROR",
	"FLAC__STREAM_ENCODER_IO_ERROR",
483
	"FLAC__STREAM_ENCODER_FRAMING_ERROR",
484
485
486
487
488
489
	"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",
490
	"FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
491
492
493
494
495
496
497
498
499
500
501
	"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
502
503
};

504
505
506
507
508
509
510
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"
};

511
FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
512
513
	"FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
	"FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalson's avatar
Josh Coalson committed
514
515
};

516
517
518
519
520
521
522
523
524
525
526
527
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"
};

528
529
530
531
532
533
534
535
536
537
538
539
540
/* 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;

541
542
543
544
/***********************************************************************
 *
 * Class constructor/destructor
 *
Josh Coalson's avatar
Josh Coalson committed
545
 */
546
FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new()
Josh Coalson's avatar
Josh Coalson committed
547
{
548
	FLAC__StreamEncoder *encoder;
549
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
550

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

553
	encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder));
554
555
	if(encoder == 0) {
		return 0;
556
	}
Josh Coalson's avatar
Josh Coalson committed
557

558
	encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected));
559
	if(encoder->protected_ == 0) {
560
561
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
562
	}
Josh Coalson's avatar
Josh Coalson committed
563

564
	encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
565
566
	if(encoder->private_ == 0) {
		free(encoder->protected_);
567
568
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
569
	}
Josh Coalson's avatar
Josh Coalson committed
570

571
572
573
574
575
576
577
	encoder->private_->frame = FLAC__bitbuffer_new();
	if(encoder->private_->frame == 0) {
		free(encoder->private_);
		free(encoder->protected_);
		free(encoder);
		return 0;
	}
578

579
580
	encoder->private_->file = 0;

581
	set_defaults_(encoder);
582

583
	encoder->private_->is_being_deleted = false;
584
585
586
587
588
589
590
591
592
593

	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++) {
594
595
		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];
596
597
	}
	for(i = 0; i < 2; i++) {
598
599
		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];
600
601
602
	}

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
603
604
		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]);
605
606
	}
	for(i = 0; i < 2; i++) {
607
608
		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]);
609
610
	}
	for(i = 0; i < 2; i++)
611
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
612

613
	encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
614

Josh Coalson's avatar
Josh Coalson committed
615
616
617
	return encoder;
}

618
FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalson's avatar
Josh Coalson committed
619
{
620
621
	unsigned i;

622
623
624
625
	FLAC__ASSERT(0 != encoder);
	FLAC__ASSERT(0 != encoder->protected_);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->private_->frame);
626

627
628
	encoder->private_->is_being_deleted = true;

629
	(void)FLAC__stream_encoder_finish(encoder);
630

631
	if(0 != encoder->private_->verify.decoder)
Josh Coalson's avatar
Josh Coalson committed
632
		FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
633
634

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
635
636
		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]);
637
638
	}
	for(i = 0; i < 2; i++) {
639
640
		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]);
641
642
	}
	for(i = 0; i < 2; i++)
643
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
644

645
	FLAC__bitbuffer_delete(encoder->private_->frame);
646
647
	free(encoder->private_);
	free(encoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
648
649
650
	free(encoder);
}

651
652
653
654
655
656
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

657
658
659
660
661
662
663
664
665
666
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
667
668
{
	unsigned i;
669
	FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
Josh Coalson's avatar
Josh Coalson committed
670

671
	FLAC__ASSERT(0 != encoder);
Josh Coalson's avatar
Josh Coalson committed
672

673
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
674
		return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
675

676
#if !FLAC__HAS_OGG
677
678
679
680
	if(is_ogg)
		return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
#endif

681
682
	if(0 == write_callback || (seek_callback && 0 == tell_callback))
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
Josh Coalson's avatar
Josh Coalson committed
683

684
	if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
685
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson's avatar
Josh Coalson committed
686

687
688
689
690
691
692
	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;
693

694
	if(encoder->protected_->bits_per_sample >= 32)
695
		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
696

697
	if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
698
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
Josh Coalson's avatar
Josh Coalson committed
699

700
	if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
701
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
Josh Coalson's avatar
Josh Coalson committed
702

703
704
705
706
707
708
709
	if(encoder->protected_->blocksize == 0) {
		if(encoder->protected_->max_lpc_order == 0)
			encoder->protected_->blocksize = 1152;
		else
			encoder->protected_->blocksize = 4608;
	}

710
	if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
711
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
Josh Coalson's avatar
Josh Coalson committed
712

713
	if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
714
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
715

716
	if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
717
		return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
718

719
720
	if(encoder->protected_->qlp_coeff_precision == 0) {
		if(encoder->protected_->bits_per_sample < 16) {
Josh Coalson's avatar
Josh Coalson committed
721
722
			/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
			/* @@@ until then we'll make a guess */
723
			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
724
		}
725
726
727
728
729
730
731
732
733
734
735
736
737
		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
738
			else
739
				encoder->protected_->qlp_coeff_precision = 13;
Josh Coalson's avatar
Josh Coalson committed
740
741
		}
		else {
742
743
744
745
746
747
			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
748
		}
749
		FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalson's avatar
Josh Coalson committed
750
	}
751
	else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
752
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
753

754
	if(encoder->protected_->streamable_subset) {
755
756
757
758
759
760
761
762
763
764
765
766
767
768
		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
		)
769
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
770
771
772
773
774
775
776
777
778
779
		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
		)
780
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
781
782
783
784
785
786
787
		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
		)
788
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
789
		if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
790
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
791
792
793
794
795
796
797
798
799
		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
800
801
	}

802
803
804
805
	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
806

807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
#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 */
			}
		}
	}

833
834
	/* validate metadata */
	if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
835
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
836
837
	metadata_has_seektable = false;
	metadata_has_vorbis_comment = false;
838
839
	metadata_picture_has_type1 = false;
	metadata_picture_has_type2 = false;
840
	for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
841
842
		const FLAC__StreamMetadata *m = encoder->protected_->metadata[i];
		if(m->type == FLAC__METADATA_TYPE_STREAMINFO)
843
			return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
844
		else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
845
			if(metadata_has_seektable) /* only one is allowed */
846
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
847
			metadata_has_seektable = true;
848
			if(!FLAC__format_seektable_is_legal(&m->data.seek_table))
849
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
850
		}
851
		else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
Josh Coalson's avatar
Josh Coalson committed
852
			if(metadata_has_vorbis_comment) /* only one is allowed */
853
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
854
855
			metadata_has_vorbis_comment = true;
		}
856
857
		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))
858
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
859
		}
860
861
		else if(m->type == FLAC__METADATA_TYPE_PICTURE) {
			if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0))
862
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
			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;
			}
883
		}
884
885
	}

886
887
888
	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;
889
#ifndef FLAC__INTEGER_ONLY_LIBRARY
890
		encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
891
#endif
Josh Coalson's avatar
Josh Coalson committed
892
893
	}
	for(i = 0; i < 2; i++) {
894
		encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
895
#ifndef FLAC__INTEGER_ONLY_LIBRARY
896
		encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
897
#endif
Josh Coalson's avatar
Josh Coalson committed
898
	}
899
900
901
902
903
#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
904
905
906
907
	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
908
909
	}
	for(i = 0; i < 2; i++) {
910
911
912
		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
913
	}
914
915
916
	encoder->private_->abs_residual_unaligned = encoder->private_->abs_residual = 0;
	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;
917
918
919
920
921
922
923
924
925
926
927
#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
928
929
930
931
932
933
934
935
936
	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 */
937

938
939
940
	/*
	 * get the CPU info and set the function pointers
	 */
941
	FLAC__cpu_info(&encoder->private_->cpuinfo);
942
	/* first default to the non-asm routines */
943
#ifndef FLAC__INTEGER_ONLY_LIBRARY
944
	encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
945
#endif
946
	encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
947
#ifndef FLAC__INTEGER_ONLY_LIBRARY
948
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
949
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
950
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
951
#endif
952
	/* now override with asm where appropriate */
953
954
#ifndef FLAC__INTEGER_ONLY_LIBRARY
# ifndef FLAC__NO_ASM
955
	if(encoder->private_->cpuinfo.use_asm) {
956
#  ifdef FLAC__CPU_IA32
957
		FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
958
959
#   ifdef FLAC__HAS_NASM
#    ifdef FLAC__SSE_OS
960
		if(encoder->private_->cpuinfo.data.ia32.sse) {
961
962
963
964
965
966
			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;
967
			else
968
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
969
		}
970
		else
971
#    endif /* FLAC__SSE_OS */
972
		if(encoder->private_->cpuinfo.data.ia32._3dnow)
973
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
974
		else
975
976
977
978
			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;
979
980
		}
		else {
981
982
			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;
983
		}
984
985
986
987
		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 */
988
	}
989
990
# endif /* !FLAC__NO_ASM */
#endif /* !FLAC__INTEGER_ONLY_LIBRARY */
991
	/* finally override based on wide-ness if necessary */
992
993
	if(encoder->private_->use_wide_by_block) {
		encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
994
	}
995

996
	/* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
997
	encoder->private_->precompute_partition_sums = (encoder->protected_->max_residual_partition_order > encoder->protected_->min_residual_partition_order) || encoder->protected_->do_escape_coding;
998

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

1002
1003
1004
1005
1006
1007
1008
1009
1010
#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;
1011
1012
1013
1014
1015
1016
	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;

1017
	if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalson's avatar
Josh Coalson committed
1018
		/* the above function sets the state for us in case of an error */
1019
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalson's avatar
Josh Coalson committed
1020
	}
1021

1022
1023
1024
1025
	if(!FLAC__bitbuffer_init(encoder->private_->frame)) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
	}
Josh Coalson's avatar
Josh Coalson committed
1026

Josh Coalson's avatar
Josh Coalson committed
1027
1028
1029
1030
1031
1032
1033
1034
	/*
	 * 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
		 */
1035
		encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize+OVERREAD_;
Josh Coalson's avatar
Josh Coalson committed
1036
		for(i = 0; i < encoder->protected_->channels; i++) {
1037
1038
1039
1040
			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
1041
1042
1043
1044
1045
1046
1047
		}
		encoder->private_->verify.input_fifo.tail = 0;

		/*
		 * Now set up a stream decoder for verification
		 */
		encoder->private_->verify.decoder = FLAC__stream_decoder_new();
1048
1049
1050
1051
		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
1052

1053
1054
1055
1056
		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
1057
	}
1058
1059
1060
1061
1062
1063
	encoder->private_->verify.error_stats.absolute_sample = 0;
	encoder->private_->verify.error_stats.frame_number = 0;
	encoder->private_->verify.error_stats.channel = 0;
	encoder->private_->verify.error_stats.sample = 0;
	encoder->private_->