fixes based on Windows testing
[flac.git] / src / flac / encode.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000,2001,2002  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #if defined _WIN32 && !defined __CYGWIN__
20 /* where MSVC puts unlink() */
21 # include <io.h>
22 #else
23 # include <unistd.h>
24 #endif
25 #include <limits.h> /* for LONG_MAX */
26 #include <math.h> /* for floor() */
27 #include <stdarg.h>
28 #include <stdio.h> /* for FILE etc. */
29 #include <stdlib.h> /* for malloc */
30 #include <string.h> /* for strcmp() */
31 #include "FLAC/all.h"
32 #include "encode.h"
33 #include "file.h"
34 #ifdef FLAC__HAS_OGG
35 #include "OggFLAC/stream_encoder.h"
36 #endif
37
38 #ifdef min
39 #undef min
40 #endif
41 #define min(x,y) ((x)<(y)?(x):(y))
42
43 /* this MUST be >= 588 so that sector aligning can take place with one read */
44 #define CHUNK_OF_SAMPLES 2048
45
46 typedef struct {
47 #ifdef FLAC__HAS_OGG
48         FLAC__bool use_ogg;
49 #endif
50         FLAC__bool verify;
51         FLAC__bool verbose;
52         FLAC__bool is_stdout;
53         const char *inbasefilename;
54         const char *outfilename;
55
56         FLAC__uint64 unencoded_size;
57         FLAC__uint64 total_samples_to_encode;
58         FLAC__uint64 bytes_written;
59         FLAC__uint64 samples_written;
60         unsigned blocksize;
61         unsigned stats_mask;
62
63         /*
64          * We use flac.stream for encoding native FLAC to stdout
65          * We use flac.file for encoding native FLAC to a regular file
66          * We use ogg.stream for encoding Ogg FLAC to either stdout or a regular file
67          */
68         union {
69                 union {
70                         FLAC__StreamEncoder *stream;
71                         FLAC__FileEncoder *file;
72                 } flac;
73 #ifdef FLAC__HAS_OGG
74                 union {
75                         OggFLAC__StreamEncoder *stream;
76                 } ogg;
77 #endif
78         } encoder;
79
80         FILE *fin;
81         FILE *fout;
82         FLAC__StreamMetadata *seek_table_template;
83 } EncoderSession;
84
85
86 static FLAC__bool is_big_endian_host_;
87
88 static unsigned char ucbuffer_[CHUNK_OF_SAMPLES*FLAC__MAX_CHANNELS*((FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE+7)/8)];
89 static signed char *scbuffer_ = (signed char *)ucbuffer_;
90 static FLAC__uint16 *usbuffer_ = (FLAC__uint16 *)ucbuffer_;
91 static FLAC__int16 *ssbuffer_ = (FLAC__int16 *)ucbuffer_;
92
93 static FLAC__int32 in_[FLAC__MAX_CHANNELS][CHUNK_OF_SAMPLES];
94 static FLAC__int32 *input_[FLAC__MAX_CHANNELS];
95
96
97 /*
98  * local routines
99  */
100 static FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool verbose, FILE *infile, const char *infilename, const char *outfilename);
101 static void EncoderSession_destroy(EncoderSession *e);
102 static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero);
103 static int EncoderSession_finish_error(EncoderSession *e);
104 static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate);
105 static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples);
106 static FLAC__bool convert_to_seek_table_template(char *requested_seek_points, int num_requested_seek_points, EncoderSession *e);
107 static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps);
108 #ifdef FLAC__HAS_OGG
109 static FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
110 #endif
111 static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
112 static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
113 static void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
114 static void print_stats(const EncoderSession *encoder_session);
115 static void print_error_with_state(const EncoderSession *e, const char *message);
116 static void print_verify_error(EncoderSession *e);
117 static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn);
118 static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn);
119 static FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn);
120 static FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn);
121 static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn);
122
123 /*
124  * public routines
125  */
126 int
127 flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const char *outfilename,
128         const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options)
129 {
130         EncoderSession encoder_session;
131         FLAC__uint16 x;
132         FLAC__uint32 xx;
133         unsigned int channels= 0U, bps= 0U, sample_rate= 0U, sample_frames= 0U;
134         FLAC__bool got_comm_chunk= false, got_ssnd_chunk= false;
135         int info_align_carry= -1, info_align_zero= -1;
136
137         FLAC__ASSERT(!options.common.sector_align || options.common.skip == 0);
138
139         (void)infilesize; /* silence compiler warning about unused parameter */
140         (void)lookahead; /* silence compiler warning about unused parameter */
141         (void)lookahead_length; /* silence compiler warning about unused parameter */
142
143         if(!EncoderSession_construct(&encoder_session, options.common.use_ogg, options.common.verify, options.common.verbose, infile, infilename, outfilename))
144                 return 1;
145
146         /* lookahead[] already has "FORMxxxxAIFF", do sub-chunks */
147
148         while(1) {
149                 size_t c= 0U;
150                 char chunk_id[4];
151
152                 /* chunk identifier; really conservative about behavior of fread() and feof() */
153                 if(feof(infile) || ((c= fread(chunk_id, 1U, 4U, infile)), c==0U && feof(infile)))
154                         break;
155                 else if(c<4U || feof(infile)) {
156                         fprintf(stderr, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename);
157                         return EncoderSession_finish_error(&encoder_session);
158                 }
159
160                 if(got_comm_chunk==false && !strncmp(chunk_id, "COMM", 4)) { /* common chunk */
161                         unsigned long skip;
162
163                         /* COMM chunk size */
164                         if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
165                                 return EncoderSession_finish_error(&encoder_session);
166                         else if(xx<18U) {
167                                 fprintf(stderr, "%s: ERROR: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx);
168                                 return EncoderSession_finish_error(&encoder_session);
169                         }
170                         else if(xx!=18U)
171                                 fprintf(stderr, "%s: WARNING: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx);
172                         skip= (xx-18U)+(xx & 1U);
173
174                         /* number of channels */
175                         if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename))
176                                 return EncoderSession_finish_error(&encoder_session);
177                         else if(x==0U || x>FLAC__MAX_CHANNELS) {
178                                 fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned int)x);
179                                 return EncoderSession_finish_error(&encoder_session);
180                         }
181                         else if(options.common.sector_align && x!=2U) {
182                                 fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x);
183                                 return EncoderSession_finish_error(&encoder_session);
184                         }
185                         channels= x;
186
187                         /* number of sample frames */
188                         if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
189                                 return EncoderSession_finish_error(&encoder_session);
190                         sample_frames= xx;
191
192                         /* bits per sample */
193                         if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename))
194                                 return EncoderSession_finish_error(&encoder_session);
195                         else if(x!=8U && x!=16U && x!=24U) {
196                                 fprintf(stderr, "%s: ERROR: unsupported bits per sample %u\n", encoder_session.inbasefilename, (unsigned int)x);
197                                 return EncoderSession_finish_error(&encoder_session);
198                         }
199                         else if(options.common.sector_align && x!=16U) {
200                                 fprintf(stderr, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x);
201                                 return EncoderSession_finish_error(&encoder_session);
202                         }
203                         bps= x;
204
205                         /* sample rate */
206                         if(!read_sane_extended(infile, &xx, false, encoder_session.inbasefilename))
207                                 return EncoderSession_finish_error(&encoder_session);
208                         else if(!FLAC__format_sample_rate_is_valid(xx)) {
209                                 fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned int)xx);
210                                 return EncoderSession_finish_error(&encoder_session);
211                         }
212                         else if(options.common.sector_align && xx!=44100U) {
213                                 fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)xx);
214                                 return EncoderSession_finish_error(&encoder_session);
215                         }
216                         sample_rate= xx;
217
218                         /* skip any extra data in the COMM chunk */
219                         FLAC__ASSERT(skip<=LONG_MAX);
220                         while(skip>0U && fseek(infile, skip, SEEK_CUR)<0) {
221                                 unsigned int need= min(skip, sizeof ucbuffer_);
222                                 if(fread(ucbuffer_, 1U, need, infile)<need) {
223                                         fprintf(stderr, "%s: ERROR during read while skipping extra COMM data\n", encoder_session.inbasefilename);
224                                         return EncoderSession_finish_error(&encoder_session);
225                                 }
226                                 skip-= need;
227                         }
228
229                         got_comm_chunk= true;
230                 }
231                 else if(got_ssnd_chunk==false && !strncmp(chunk_id, "SSND", 4)) { /* sound data chunk */
232                         unsigned int offset= 0U, block_size= 0U, align_remainder= 0U, data_bytes;
233                         size_t bytes_per_frame= channels*(bps>>3);
234                         FLAC__bool pad= false;
235
236                         if(got_comm_chunk==false) {
237                                 fprintf(stderr, "%s: ERROR: got 'SSND' chunk before 'COMM' chunk\n", encoder_session.inbasefilename);
238                                 return EncoderSession_finish_error(&encoder_session);
239                         }
240
241                         /* SSND chunk size */
242                         if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
243                                 return EncoderSession_finish_error(&encoder_session);
244                         else if(xx!=(sample_frames*bytes_per_frame + 8U)) {
245                                 fprintf(stderr, "%s: ERROR: SSND chunk size inconsistent with sample frame count\n", encoder_session.inbasefilename);
246                                 return EncoderSession_finish_error(&encoder_session);
247                         }
248                         data_bytes= xx;
249                         pad= (data_bytes & 1U) ? true : false;
250
251                         /* offset */
252                         if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
253                                 return EncoderSession_finish_error(&encoder_session);
254                         else if(xx!=0U) {
255                                 fprintf(stderr, "%s: ERROR: offset is %u; must be 0\n", encoder_session.inbasefilename, (unsigned int)xx);
256                                 return EncoderSession_finish_error(&encoder_session);
257                         }
258                         offset= xx;
259
260                         /* block size */
261                         if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
262                                 return EncoderSession_finish_error(&encoder_session);
263                         else if(xx!=0U) {
264                                 fprintf(stderr, "%s: ERROR: block size is %u; must be 0\n", encoder_session.inbasefilename, (unsigned int)xx);
265                                 return EncoderSession_finish_error(&encoder_session);
266                         }
267                         block_size= xx;
268
269                         if(options.common.skip>0U) {
270                                 FLAC__uint64 remaining= options.common.skip*bytes_per_frame;
271
272                                 /* do 1<<30 bytes at a time, since 1<<30 is a nice round number, and */
273                                 /* is guaranteed to be less than LONG_MAX */
274                                 for(; remaining>0U; remaining-= remaining>(1U<<30) ? remaining : (1U<<30))
275                                 {
276                                         unsigned long skip= (unsigned long)(remaining % (1U<<30));
277
278                                         FLAC__ASSERT(skip<=LONG_MAX);
279                                         while(skip>0 && fseek(infile, skip, SEEK_CUR)<0) {
280                                                 unsigned int need= min(skip, sizeof ucbuffer_);
281                                                 if(fread(ucbuffer_, 1U, need, infile)<need) {
282                                                         fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename);
283                                                         return EncoderSession_finish_error(&encoder_session);
284                                                 }
285                                                 skip-= need;
286                                         }
287                                 }
288                         }
289
290                         data_bytes-= (8U + (unsigned int)options.common.skip*bytes_per_frame); /*@@@ WATCHOUT: 4GB limit */
291                         encoder_session.total_samples_to_encode= data_bytes/bytes_per_frame + *options.common.align_reservoir_samples;
292                         if(options.common.sector_align) {
293                                 align_remainder= (unsigned int)(encoder_session.total_samples_to_encode % 588U);
294                                 if(options.common.is_last_file)
295                                         encoder_session.total_samples_to_encode+= (588U-align_remainder); /* will pad with zeroes */
296                                 else
297                                         encoder_session.total_samples_to_encode-= align_remainder; /* will stop short and carry over to next file */
298                         }
299
300                         /* +54 for the size of the AIFF headers; this is just an estimate for the progress indicator and doesn't need to be exact */
301                         encoder_session.unencoded_size= encoder_session.total_samples_to_encode*bytes_per_frame+54;
302
303                         if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate))
304                                 return EncoderSession_finish_error(&encoder_session);
305
306                         /* first do any samples in the reservoir */
307                         if(options.common.sector_align && *options.common.align_reservoir_samples>0U) {
308
309                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) {
310                                         print_error_with_state(&encoder_session, "ERROR during encoding");
311                                         return EncoderSession_finish_error(&encoder_session);
312                                 }
313                         }
314
315                         /* decrement the data_bytes counter if we need to align the file */
316                         if(options.common.sector_align) {
317                                 if(options.common.is_last_file)
318                                         *options.common.align_reservoir_samples= 0U;
319                                 else {
320                                         *options.common.align_reservoir_samples= align_remainder;
321                                         data_bytes-= (*options.common.align_reservoir_samples)*bytes_per_frame;
322                                 }
323                         }
324
325                         /* now do from the file */
326                         while(data_bytes>0) {
327                                 size_t bytes_read= fread(ucbuffer_, 1U, min(data_bytes, CHUNK_OF_SAMPLES*bytes_per_frame), infile);
328
329                                 if(bytes_read==0U) {
330                                         if(ferror(infile)) {
331                                                 fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
332                                                 return EncoderSession_finish_error(&encoder_session);
333                                         }
334                                         else if(feof(infile)) {
335                                                 fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written);
336                                                 data_bytes= 0;
337                                         }
338                                 }
339                                 else {
340                                         if(bytes_read % bytes_per_frame != 0U) {
341                                                 fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename);
342                                                 return EncoderSession_finish_error(&encoder_session);
343                                         }
344                                         else {
345                                                 unsigned int frames= bytes_read/bytes_per_frame;
346                                                 format_input(input_, frames, true, false, channels, bps);
347
348                                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)input_, frames)) {
349                                                         print_error_with_state(&encoder_session, "ERROR during encoding");
350                                                         return EncoderSession_finish_error(&encoder_session);
351                                                 }
352                                                 else
353                                                         data_bytes-= bytes_read;
354                                         }
355                                 }
356                         }
357
358                         /* now read unaligned samples into reservoir or pad with zeroes if necessary */
359                         if(options.common.sector_align) {
360                                 if(options.common.is_last_file) {
361                                         unsigned int pad_frames= 588U-align_remainder;
362
363                                         if(pad_frames<588U) {
364                                                 unsigned int i;
365
366                                                 info_align_zero= pad_frames;
367                                                 for(i= 0U; i<channels; ++i)
368                                                         memset(input_[i], 0, pad_frames*(bps>>3));
369
370                                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)input_, pad_frames)) {
371                                                         print_error_with_state(&encoder_session, "ERROR during encoding");
372                                                         return EncoderSession_finish_error(&encoder_session);
373                                                 }
374                                         }
375                                 }
376                                 else {
377                                         if(*options.common.align_reservoir_samples > 0) {
378                                                 size_t bytes_read= fread(ucbuffer_, 1U, (*options.common.align_reservoir_samples)*bytes_per_frame, infile);
379
380                                                 FLAC__ASSERT(CHUNK_OF_SAMPLES>=588U);
381                                                 if(bytes_read==0U && ferror(infile)) {
382                                                         fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
383                                                         return EncoderSession_finish_error(&encoder_session);
384                                                 }
385                                                 else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_frame)
386                                                         fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written);
387                                                 else {
388                                                         info_align_carry= *options.common.align_reservoir_samples;
389                                                         format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, true, false, channels, bps);
390                                                 }
391                                         }
392                                 }
393                         }
394
395                         if(pad==true) {
396                                 unsigned char tmp;
397
398                                 if(fread(&tmp, 1U, 1U, infile)<1U) {
399                                         fprintf(stderr, "%s: ERROR during read of SSND pad byte\n", encoder_session.inbasefilename);
400                                         return EncoderSession_finish_error(&encoder_session);
401                                 }
402                         }
403
404                         got_ssnd_chunk= true;
405                 }
406                 else { /* other chunk */
407                         if(!strncmp(chunk_id, "COMM", 4))
408                                 fprintf(stderr, "%s: WARNING: skipping extra 'COMM' chunk\n", encoder_session.inbasefilename);
409                         else if(!strncmp(chunk_id, "SSND", 4))
410                                 fprintf(stderr, "%s: WARNING: skipping extra 'SSND' chunk\n", encoder_session.inbasefilename);
411                         else
412                                 fprintf(stderr, "%s: WARNING: skipping unknown chunk '%s'\n", encoder_session.inbasefilename, chunk_id);
413
414                         /* chunk size */
415                         if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
416                                 return EncoderSession_finish_error(&encoder_session);
417                         else {
418                                 unsigned long skip= xx+(xx & 1U);
419
420                                 FLAC__ASSERT(skip<=LONG_MAX);
421                                 while(skip>0U && fseek(infile, skip, SEEK_CUR)<0) {
422                                         unsigned int need= min(skip, sizeof ucbuffer_);
423                                         if(fread(ucbuffer_, 1U, need, infile)<need) {
424                                                 fprintf(stderr, "%s: ERROR during read while skipping unknown chunk\n", encoder_session.inbasefilename);
425                                                 return EncoderSession_finish_error(&encoder_session);
426                                         }
427                                         skip-= need;
428                                 }
429                         }
430                 }
431         }
432
433         if(got_ssnd_chunk==false && sample_frames!=0U) {
434                 fprintf(stderr, "%s: ERROR: missing SSND chunk\n", encoder_session.inbasefilename);
435                 return EncoderSession_finish_error(&encoder_session);
436         }
437
438         return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero);
439 }
440
441 int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options)
442 {
443         EncoderSession encoder_session;
444         FLAC__bool is_unsigned_samples = false;
445         unsigned channels = 0, bps = 0, sample_rate = 0, data_bytes;
446         size_t bytes_per_wide_sample, bytes_read;
447         FLAC__uint16 x;
448         FLAC__uint32 xx;
449         FLAC__bool got_fmt_chunk = false, got_data_chunk = false;
450         unsigned align_remainder = 0;
451         int info_align_carry = -1, info_align_zero = -1;
452
453         FLAC__ASSERT(!options.common.sector_align || options.common.skip == 0);
454
455         (void)infilesize;
456         (void)lookahead;
457         (void)lookahead_length;
458
459         if(!EncoderSession_construct(&encoder_session, options.common.use_ogg, options.common.verify, options.common.verbose, infile, infilename, outfilename))
460                 return 1;
461
462         /*
463          * lookahead[] already has "RIFFxxxxWAVE", do sub-chunks
464          */
465         while(!feof(infile)) {
466                 if(!read_little_endian_uint32(infile, &xx, true, encoder_session.inbasefilename))
467                         return EncoderSession_finish_error(&encoder_session);
468                 if(feof(infile))
469                         break;
470                 if(xx == 0x20746d66 && !got_fmt_chunk) { /* "fmt " */
471                         /* fmt sub-chunk size */
472                         if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
473                                 return EncoderSession_finish_error(&encoder_session);
474                         if(xx < 16) {
475                                 fprintf(stderr, "%s: ERROR: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx);
476                                 return EncoderSession_finish_error(&encoder_session);
477                         }
478                         else if(xx != 16 && xx != 18) {
479                                 fprintf(stderr, "%s: WARNING: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx);
480                         }
481                         data_bytes = xx;
482                         /* compression code */
483                         if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename))
484                                 return EncoderSession_finish_error(&encoder_session);
485                         if(x != 1) {
486                                 fprintf(stderr, "%s: ERROR: unsupported compression type %u\n", encoder_session.inbasefilename, (unsigned)x);
487                                 return EncoderSession_finish_error(&encoder_session);
488                         }
489                         /* number of channels */
490                         if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename))
491                                 return EncoderSession_finish_error(&encoder_session);
492                         if(x == 0 || x > FLAC__MAX_CHANNELS) {
493                                 fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned)x);
494                                 return EncoderSession_finish_error(&encoder_session);
495                         }
496                         else if(options.common.sector_align && x != 2) {
497                                 fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x);
498                                 return EncoderSession_finish_error(&encoder_session);
499                         }
500                         channels = x;
501                         /* sample rate */
502                         if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
503                                 return EncoderSession_finish_error(&encoder_session);
504                         if(!FLAC__format_sample_rate_is_valid(xx)) {
505                                 fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned)xx);
506                                 return EncoderSession_finish_error(&encoder_session);
507                         }
508                         else if(options.common.sector_align && xx != 44100) {
509                                 fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned)xx);
510                                 return EncoderSession_finish_error(&encoder_session);
511                         }
512                         sample_rate = xx;
513                         /* avg bytes per second (ignored) */
514                         if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
515                                 return EncoderSession_finish_error(&encoder_session);
516                         /* block align (ignored) */
517                         if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename))
518                                 return EncoderSession_finish_error(&encoder_session);
519                         /* bits per sample */
520                         if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename))
521                                 return EncoderSession_finish_error(&encoder_session);
522                         if(x != 8 && x != 16 && x != 24) {
523                                 fprintf(stderr, "%s: ERROR: unsupported bits per sample %u\n", encoder_session.inbasefilename, (unsigned)x);
524                                 return EncoderSession_finish_error(&encoder_session);
525                         }
526                         else if(options.common.sector_align && x != 16) {
527                                 fprintf(stderr, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x);
528                                 return EncoderSession_finish_error(&encoder_session);
529                         }
530                         bps = x;
531                         is_unsigned_samples = (x == 8);
532
533                         /* skip any extra data in the fmt sub-chunk */
534                         data_bytes -= 16;
535                         if(data_bytes > 0) {
536                                 unsigned left, need;
537                                 for(left = data_bytes; left > 0; ) {
538                                         need = min(left, CHUNK_OF_SAMPLES);
539                                         if(fread(ucbuffer_, 1U, need, infile) < need) {
540                                                 fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename);
541                                                 return EncoderSession_finish_error(&encoder_session);
542                                         }
543                                         left -= need;
544                                 }
545                         }
546
547                         got_fmt_chunk = true;
548                 }
549                 else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */
550                         /* data size */
551                         if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
552                                 return EncoderSession_finish_error(&encoder_session);
553                         data_bytes = xx;
554
555                         bytes_per_wide_sample = channels * (bps >> 3);
556
557                         if(options.common.skip > 0) {
558                                 if(fseek(infile, bytes_per_wide_sample * (unsigned)options.common.skip, SEEK_CUR) < 0) {
559                                         /* can't seek input, read ahead manually... */
560                                         unsigned left, need;
561                                         for(left = (unsigned)options.common.skip; left > 0; ) { /*@@@ WATCHOUT: 4GB limit */
562                                                 need = min(left, CHUNK_OF_SAMPLES);
563                                                 if(fread(ucbuffer_, bytes_per_wide_sample, need, infile) < need) {
564                                                         fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename);
565                                                         return EncoderSession_finish_error(&encoder_session);
566                                                 }
567                                                 left -= need;
568                                         }
569                                 }
570                         }
571
572                         data_bytes -= (unsigned)options.common.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */
573                         encoder_session.total_samples_to_encode = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples;
574                         if(options.common.sector_align) {
575                                 align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588);
576                                 if(options.common.is_last_file)
577                                         encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */
578                                 else
579                                         encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */
580                         }
581
582                         /* +44 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */
583                         encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample + 44;
584
585                         if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate))
586                                 return EncoderSession_finish_error(&encoder_session);
587
588                         /*
589                          * first do any samples in the reservoir
590                          */
591                         if(options.common.sector_align && *options.common.align_reservoir_samples > 0) {
592                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) {
593                                         print_error_with_state(&encoder_session, "ERROR during encoding");
594                                         return EncoderSession_finish_error(&encoder_session);
595                                 }
596                         }
597
598                         /*
599                          * decrement the data_bytes counter if we need to align the file
600                          */
601                         if(options.common.sector_align) {
602                                 if(options.common.is_last_file) {
603                                         *options.common.align_reservoir_samples = 0;
604                                 }
605                                 else {
606                                         *options.common.align_reservoir_samples = align_remainder;
607                                         data_bytes -= (*options.common.align_reservoir_samples) * bytes_per_wide_sample;
608                                 }
609                         }
610
611                         /*
612                          * now do from the file
613                          */
614                         while(data_bytes > 0) {
615                                 bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile);
616                                 if(bytes_read == 0) {
617                                         if(ferror(infile)) {
618                                                 fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
619                                                 return EncoderSession_finish_error(&encoder_session);
620                                         }
621                                         else if(feof(infile)) {
622                                                 fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
623                                                 data_bytes = 0;
624                                         }
625                                 }
626                                 else {
627                                         if(bytes_read % bytes_per_wide_sample != 0) {
628                                                 fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename);
629                                                 return EncoderSession_finish_error(&encoder_session);
630                                         }
631                                         else {
632                                                 unsigned wide_samples = bytes_read / bytes_per_wide_sample;
633                                                 format_input(input_, wide_samples, false, is_unsigned_samples, channels, bps);
634
635                                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) {
636                                                         print_error_with_state(&encoder_session, "ERROR during encoding");
637                                                         return EncoderSession_finish_error(&encoder_session);
638                                                 }
639                                                 data_bytes -= bytes_read;
640                                         }
641                                 }
642                         }
643
644                         /*
645                          * now read unaligned samples into reservoir or pad with zeroes if necessary
646                          */
647                         if(options.common.sector_align) {
648                                 if(options.common.is_last_file) {
649                                         unsigned wide_samples = 588 - align_remainder;
650                                         if(wide_samples < 588) {
651                                                 unsigned channel;
652
653                                                 info_align_zero = wide_samples;
654                                                 data_bytes = wide_samples * (bps >> 3);
655                                                 for(channel = 0; channel < channels; channel++)
656                                                         memset(input_[channel], 0, data_bytes);
657
658                                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) {
659                                                         print_error_with_state(&encoder_session, "ERROR during encoding");
660                                                         return EncoderSession_finish_error(&encoder_session);
661                                                 }
662                                         }
663                                 }
664                                 else {
665                                         if(*options.common.align_reservoir_samples > 0) {
666                                                 FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588);
667                                                 bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile);
668                                                 if(bytes_read == 0 && ferror(infile)) {
669                                                         fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
670                                                         return EncoderSession_finish_error(&encoder_session);
671                                                 }
672                                                 else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) {
673                                                         fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
674                                                         data_bytes = 0;
675                                                 }
676                                                 else {
677                                                         info_align_carry = *options.common.align_reservoir_samples;
678                                                         format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, is_unsigned_samples, channels, bps);
679                                                 }
680                                         }
681                                 }
682                         }
683
684                         got_data_chunk = true;
685                 }
686                 else {
687                         if(xx == 0x20746d66 && got_fmt_chunk) { /* "fmt " */
688                                 fprintf(stderr, "%s: WARNING: skipping extra 'fmt ' sub-chunk\n", encoder_session.inbasefilename);
689                         }
690                         else if(xx == 0x61746164) { /* "data" */
691                                 if(got_data_chunk) {
692                                         fprintf(stderr, "%s: WARNING: skipping extra 'data' sub-chunk\n", encoder_session.inbasefilename);
693                                 }
694                                 else if(!got_fmt_chunk) {
695                                         fprintf(stderr, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename);
696                                         return EncoderSession_finish_error(&encoder_session);
697                                 }
698                                 else {
699                                         FLAC__ASSERT(0);
700                                 }
701                         }
702                         else {
703                                 fprintf(stderr, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c'\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24));
704                         }
705                         /* sub-chunk size */
706                         if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
707                                 return EncoderSession_finish_error(&encoder_session);
708                         if(fseek(infile, xx, SEEK_CUR) < 0) {
709                                 /* can't seek input, read ahead manually... */
710                                 unsigned left, need;
711                                 const unsigned chunk = sizeof(ucbuffer_);
712                                 for(left = xx; left > 0; ) {
713                                         need = min(left, chunk);
714                                         if(fread(ucbuffer_, 1, need, infile) < need) {
715                                                 fprintf(stderr, "%s: ERROR during read while skipping unsupported sub-chunk\n", encoder_session.inbasefilename);
716                                                 return EncoderSession_finish_error(&encoder_session);
717                                         }
718                                         left -= need;
719                                 }
720                         }
721                 }
722         }
723
724         return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero);
725 }
726
727 int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options)
728 {
729         EncoderSession encoder_session;
730         size_t bytes_read;
731         const size_t bytes_per_wide_sample = options.channels * (options.bps >> 3);
732         unsigned align_remainder = 0;
733         int info_align_carry = -1, info_align_zero = -1;
734
735         FLAC__ASSERT(!options.common.sector_align || options.common.skip == 0);
736         FLAC__ASSERT(!options.common.sector_align || options.channels == 2);
737         FLAC__ASSERT(!options.common.sector_align || options.bps == 16);
738         FLAC__ASSERT(!options.common.sector_align || options.sample_rate == 44100);
739         FLAC__ASSERT(!options.common.sector_align || infilesize >= 0);
740
741         if(!EncoderSession_construct(&encoder_session, options.common.use_ogg, options.common.verify, options.common.verbose, infile, infilename, outfilename))
742                 return 1;
743
744         /* get the file length */
745         if(infilesize < 0) {
746                 encoder_session.total_samples_to_encode = encoder_session.unencoded_size = 0;
747         }
748         else {
749                 if(options.common.sector_align) {
750                         FLAC__ASSERT(options.common.skip == 0);
751                         encoder_session.total_samples_to_encode = (unsigned)infilesize / bytes_per_wide_sample + *options.common.align_reservoir_samples;
752                         align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588);
753                         if(options.common.is_last_file)
754                                 encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */
755                         else
756                                 encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */
757                 }
758                 else {
759                         encoder_session.total_samples_to_encode = (unsigned)infilesize / bytes_per_wide_sample - options.common.skip;
760                 }
761
762                 encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample;
763         }
764
765         if(encoder_session.verbose && encoder_session.total_samples_to_encode <= 0)
766                 fprintf(stderr, "(No runtime statistics possible; please wait for encoding to finish...)\n");
767
768         if(options.common.skip > 0) {
769                 unsigned skip_bytes = bytes_per_wide_sample * (unsigned)options.common.skip;
770                 if(skip_bytes > lookahead_length) {
771                         skip_bytes -= lookahead_length;
772                         lookahead_length = 0;
773                         if(fseek(infile, (long)skip_bytes, SEEK_CUR) < 0) {
774                                 /* can't seek input, read ahead manually... */
775                                 unsigned left, need;
776                                 const unsigned chunk = sizeof(ucbuffer_);
777                                 for(left = skip_bytes; left > 0; ) {
778                                         need = min(left, chunk);
779                                         if(fread(ucbuffer_, 1, need, infile) < need) {
780                                                 fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename);
781                                                 return EncoderSession_finish_error(&encoder_session);
782                                         }
783                                         left -= need;
784                                 }
785                         }
786                 }
787                 else {
788                         lookahead += skip_bytes;
789                         lookahead_length -= skip_bytes;
790                 }
791         }
792
793         if(!EncoderSession_init_encoder(&encoder_session, options.common, options.channels, options.bps, options.sample_rate))
794                 return EncoderSession_finish_error(&encoder_session);
795
796         /*
797          * first do any samples in the reservoir
798          */
799         if(options.common.sector_align && *options.common.align_reservoir_samples > 0) {
800                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) {
801                         print_error_with_state(&encoder_session, "ERROR during encoding");
802                         return EncoderSession_finish_error(&encoder_session);
803                 }
804         }
805
806         /*
807          * decrement infilesize if we need to align the file
808          */
809         if(options.common.sector_align) {
810                 FLAC__ASSERT(infilesize >= 0);
811                 if(options.common.is_last_file) {
812                         *options.common.align_reservoir_samples = 0;
813                 }
814                 else {
815                         *options.common.align_reservoir_samples = align_remainder;
816                         infilesize -= (long)((*options.common.align_reservoir_samples) * bytes_per_wide_sample);
817                 }
818         }
819
820         /*
821          * now do from the file
822          */
823         while(!feof(infile)) {
824                 if(lookahead_length > 0) {
825                         FLAC__ASSERT(lookahead_length < CHUNK_OF_SAMPLES * bytes_per_wide_sample);
826                         memcpy(ucbuffer_, lookahead, lookahead_length);
827                         bytes_read = fread(ucbuffer_+lookahead_length, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample - lookahead_length, infile) + lookahead_length;
828                         if(ferror(infile)) {
829                                 fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
830                                 return EncoderSession_finish_error(&encoder_session);
831                         }
832                         lookahead_length = 0;
833                 }
834                 else
835                         bytes_read = fread(ucbuffer_, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, infile);
836
837                 if(bytes_read == 0) {
838                         if(ferror(infile)) {
839                                 fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
840                                 return EncoderSession_finish_error(&encoder_session);
841                         }
842                 }
843                 else if(bytes_read % bytes_per_wide_sample != 0) {
844                         fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename);
845                         return EncoderSession_finish_error(&encoder_session);
846                 }
847                 else {
848                         unsigned wide_samples = bytes_read / bytes_per_wide_sample;
849                         format_input(input_, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps);
850
851                         if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) {
852                                 print_error_with_state(&encoder_session, "ERROR during encoding");
853                                 return EncoderSession_finish_error(&encoder_session);
854                         }
855                 }
856         }
857
858         /*
859          * now read unaligned samples into reservoir or pad with zeroes if necessary
860          */
861         if(options.common.sector_align) {
862                 if(options.common.is_last_file) {
863                         unsigned wide_samples = 588 - align_remainder;
864                         if(wide_samples < 588) {
865                                 unsigned channel, data_bytes;
866
867                                 info_align_zero = wide_samples;
868                                 data_bytes = wide_samples * (options.bps >> 3);
869                                 for(channel = 0; channel < options.channels; channel++)
870                                         memset(input_[channel], 0, data_bytes);
871
872                                 if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) {
873                                         print_error_with_state(&encoder_session, "ERROR during encoding");
874                                         return EncoderSession_finish_error(&encoder_session);
875                                 }
876                         }
877                 }
878                 else {
879                         if(*options.common.align_reservoir_samples > 0) {
880                                 FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588);
881                                 bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile);
882                                 if(bytes_read == 0 && ferror(infile)) {
883                                         fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename);
884                                         return EncoderSession_finish_error(&encoder_session);
885                                 }
886                                 else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) {
887                                         fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
888                                 }
889                                 else {
890                                         info_align_carry = *options.common.align_reservoir_samples;
891                                         format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, options.is_unsigned_samples, options.channels, options.bps);
892                                 }
893                         }
894                 }
895         }
896
897         return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero);
898 }
899
900 FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool verbose, FILE *infile, const char *infilename, const char *outfilename)
901 {
902         unsigned i;
903         FLAC__uint32 test = 1;
904
905         /*
906          * initialize globals
907          */
908
909         is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
910
911         for(i = 0; i < FLAC__MAX_CHANNELS; i++)
912                 input_[i] = &(in_[i][0]);
913
914
915         /*
916          * initialize instance
917          */
918
919 #ifdef FLAC__HAS_OGG
920         e->use_ogg = use_ogg;
921 #endif
922         e->verify = verify;
923         e->verbose = verbose;
924
925         e->is_stdout = (0 == strcmp(outfilename, "-"));
926
927         e->inbasefilename = flac__file_get_basename(infilename);
928         e->outfilename = outfilename;
929
930         e->unencoded_size = 0;
931         e->total_samples_to_encode = 0;
932         e->bytes_written = 0;
933         e->samples_written = 0;
934         e->blocksize = 0;
935         e->stats_mask = 0;
936
937         e->encoder.flac.stream = 0;
938         e->encoder.flac.file = 0;
939 #ifdef FLAC__HAS_OGG
940         e->encoder.ogg.stream = 0;
941 #endif
942
943         e->fin = infile;
944         e->fout = 0;
945         e->seek_table_template = 0;
946
947         if(e->is_stdout) {
948                 e->fout = file__get_binary_stdout();
949         }
950 #ifdef FLAC__HAS_OGG
951         else {
952                 if(e->use_ogg) {
953                         if(0 == (e->fout = fopen(outfilename, "wb"))) {
954                                 fprintf(stderr, "%s: ERROR: can't open output file %s\n", e->inbasefilename, outfilename);
955                                 EncoderSession_destroy(e);
956                                 return false;
957                         }
958                 }
959         }
960 #endif
961
962         if(0 == (e->seek_table_template = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE))) {
963                 fprintf(stderr, "%s: ERROR allocating memory for seek table\n", e->inbasefilename);
964                 return false;
965         }
966
967 #ifdef FLAC__HAS_OGG
968         if(e->use_ogg) {
969                 e->encoder.ogg.stream = OggFLAC__stream_encoder_new();
970                 if(0 == e->encoder.ogg.stream) {
971                         fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
972                         EncoderSession_destroy(e);
973                         return false;
974                 }
975         }
976         else
977 #endif
978         if(e->is_stdout) {
979                 e->encoder.flac.stream = FLAC__stream_encoder_new();
980                 if(0 == e->encoder.flac.stream) {
981                         fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
982                         EncoderSession_destroy(e);
983                         return false;
984                 }
985         }
986         else {
987                 e->encoder.flac.file = FLAC__file_encoder_new();
988                 if(0 == e->encoder.flac.file) {
989                         fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
990                         EncoderSession_destroy(e);
991                         return false;
992                 }
993         }
994
995         return true;
996 }
997
998 void EncoderSession_destroy(EncoderSession *e)
999 {
1000         if(e->fin != stdin)
1001                 fclose(e->fin);
1002
1003 #ifdef FLAC__HAS_OGG
1004         if(e->use_ogg) {
1005                 if(0 != e->encoder.ogg.stream) {
1006                         OggFLAC__stream_encoder_delete(e->encoder.ogg.stream);
1007                         e->encoder.ogg.stream = 0;
1008                 }
1009         }
1010         else
1011 #endif
1012         if(e->is_stdout) {
1013                 if(0 != e->encoder.flac.stream) {
1014                         FLAC__stream_encoder_delete(e->encoder.flac.stream);
1015                         e->encoder.flac.stream = 0;
1016                 }
1017         }
1018         else {
1019                 if(0 != e->encoder.flac.file) {
1020                         FLAC__file_encoder_delete(e->encoder.flac.file);
1021                         e->encoder.flac.file = 0;
1022                 }
1023         }
1024
1025         if(0 != e->seek_table_template) {
1026                 FLAC__metadata_object_delete(e->seek_table_template);
1027                 e->seek_table_template = 0;
1028         }
1029 }
1030
1031 int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero)
1032 {
1033         FLAC__StreamEncoderState fse_state = FLAC__STREAM_ENCODER_OK;
1034         int ret = 0;
1035
1036 #ifdef FLAC__HAS_OGG
1037         if(e->use_ogg) {
1038                 if(e->encoder.ogg.stream) {
1039                         fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream);
1040                         OggFLAC__stream_encoder_finish(e->encoder.ogg.stream);
1041                 }
1042         }
1043         else
1044 #endif
1045         if(e->is_stdout) {
1046                 if(e->encoder.flac.stream) {
1047                         fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream);
1048                         FLAC__stream_encoder_finish(e->encoder.flac.stream);
1049                 }
1050         }
1051         else {
1052                 if(e->encoder.flac.file) {
1053                         fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file);
1054                         FLAC__file_encoder_finish(e->encoder.flac.file);
1055                 }
1056         }
1057
1058         if(e->verbose && e->total_samples_to_encode > 0) {
1059                 print_stats(e);
1060                 fprintf(stderr, "\n");
1061         }
1062
1063         if(fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) {
1064                 print_verify_error(e);
1065                 ret = 1;
1066         }
1067         else {
1068                 if(info_align_carry >= 0)
1069                         fprintf(stderr, "%s: INFO: sector alignment causing %d samples to be carried over\n", e->inbasefilename, info_align_carry);
1070                 if(info_align_zero >= 0)
1071                         fprintf(stderr, "%s: INFO: sector alignment causing %d zero samples to be appended\n", e->inbasefilename, info_align_zero);
1072         }
1073
1074         EncoderSession_destroy(e);
1075
1076         return ret;
1077 }
1078
1079 int EncoderSession_finish_error(EncoderSession *e)
1080 {
1081         FLAC__StreamEncoderState fse_state;
1082
1083         if(e->verbose && e->total_samples_to_encode > 0)
1084                 fprintf(stderr, "\n");
1085
1086 #ifdef FLAC__HAS_OGG
1087         if(e->use_ogg) {
1088                 fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream);
1089         }
1090         else
1091 #endif
1092         if(e->is_stdout) {
1093                 fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream);
1094         }
1095         else {
1096                 fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file);
1097         }
1098
1099         if(fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
1100                 print_verify_error(e);
1101         else
1102                 unlink(e->outfilename);
1103
1104         EncoderSession_destroy(e);
1105
1106         return 1;
1107 }
1108
1109 FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate)
1110 {
1111         unsigned num_metadata;
1112         FLAC__StreamMetadata padding;
1113         FLAC__StreamMetadata *metadata[2];
1114
1115         if(channels != 2)
1116                 options.do_mid_side = options.loose_mid_side = false;
1117
1118         if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, e)) {
1119                 fprintf(stderr, "%s: ERROR allocating memory for seek table\n", e->inbasefilename);
1120                 return false;
1121         }
1122
1123         num_metadata = 0;
1124         if(e->seek_table_template->data.seek_table.num_points > 0) {
1125                 e->seek_table_template->is_last = false; /* the encoder will set this for us */
1126                 metadata[num_metadata++] = e->seek_table_template;
1127         }
1128         if(options.padding > 0) {
1129                 padding.is_last = false; /* the encoder will set this for us */
1130                 padding.type = FLAC__METADATA_TYPE_PADDING;
1131                 padding.length = (unsigned)options.padding;
1132                 metadata[num_metadata++] = &padding;
1133         }
1134
1135         e->blocksize = options.blocksize;
1136         e->stats_mask = (options.do_exhaustive_model_search || options.do_qlp_coeff_prec_search)? 0x0f : 0x3f;
1137
1138 #ifdef FLAC__HAS_OGG
1139         if(e->use_ogg) {
1140                 OggFLAC__stream_encoder_set_verify(e->encoder.ogg.stream, options.verify);
1141                 OggFLAC__stream_encoder_set_streamable_subset(e->encoder.ogg.stream, !options.lax);
1142                 OggFLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.ogg.stream, options.do_mid_side);
1143                 OggFLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.ogg.stream, options.loose_mid_side);
1144                 OggFLAC__stream_encoder_set_channels(e->encoder.ogg.stream, channels);
1145                 OggFLAC__stream_encoder_set_bits_per_sample(e->encoder.ogg.stream, bps);
1146                 OggFLAC__stream_encoder_set_sample_rate(e->encoder.ogg.stream, sample_rate);
1147                 OggFLAC__stream_encoder_set_blocksize(e->encoder.ogg.stream, options.blocksize);
1148                 OggFLAC__stream_encoder_set_max_lpc_order(e->encoder.ogg.stream, options.max_lpc_order);
1149                 OggFLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.ogg.stream, options.qlp_coeff_precision);
1150                 OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.stream, options.do_qlp_coeff_prec_search);
1151                 OggFLAC__stream_encoder_set_do_escape_coding(e->encoder.ogg.stream, options.do_escape_coding);
1152                 OggFLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.ogg.stream, options.do_exhaustive_model_search);
1153                 OggFLAC__stream_encoder_set_min_residual_partition_order(e->encoder.ogg.stream, options.min_residual_partition_order);
1154                 OggFLAC__stream_encoder_set_max_residual_partition_order(e->encoder.ogg.stream, options.max_residual_partition_order);
1155                 OggFLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.ogg.stream, options.rice_parameter_search_dist);
1156                 OggFLAC__stream_encoder_set_total_samples_estimate(e->encoder.ogg.stream, e->total_samples_to_encode);
1157                 OggFLAC__stream_encoder_set_metadata(e->encoder.ogg.stream, (num_metadata > 0)? metadata : 0, num_metadata);
1158                 OggFLAC__stream_encoder_set_write_callback(e->encoder.ogg.stream, ogg_stream_encoder_write_callback);
1159                 OggFLAC__stream_encoder_set_client_data(e->encoder.ogg.stream, e);
1160
1161                 if(OggFLAC__stream_encoder_init(e->encoder.ogg.stream) != FLAC__STREAM_ENCODER_OK) {
1162                         print_error_with_state(e, "ERROR initializing encoder");
1163                         return false;
1164                 }
1165         }
1166         else
1167 #endif
1168         if(e->is_stdout) {
1169                 FLAC__stream_encoder_set_verify(e->encoder.flac.stream, options.verify);
1170                 FLAC__stream_encoder_set_streamable_subset(e->encoder.flac.stream, !options.lax);
1171                 FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.flac.stream, options.do_mid_side);
1172                 FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.flac.stream, options.loose_mid_side);
1173                 FLAC__stream_encoder_set_channels(e->encoder.flac.stream, channels);
1174                 FLAC__stream_encoder_set_bits_per_sample(e->encoder.flac.stream, bps);
1175                 FLAC__stream_encoder_set_sample_rate(e->encoder.flac.stream, sample_rate);
1176                 FLAC__stream_encoder_set_blocksize(e->encoder.flac.stream, options.blocksize);
1177                 FLAC__stream_encoder_set_max_lpc_order(e->encoder.flac.stream, options.max_lpc_order);
1178                 FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.flac.stream, options.qlp_coeff_precision);
1179                 FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.stream, options.do_qlp_coeff_prec_search);
1180                 FLAC__stream_encoder_set_do_escape_coding(e->encoder.flac.stream, options.do_escape_coding);
1181                 FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.flac.stream, options.do_exhaustive_model_search);
1182                 FLAC__stream_encoder_set_min_residual_partition_order(e->encoder.flac.stream, options.min_residual_partition_order);
1183                 FLAC__stream_encoder_set_max_residual_partition_order(e->encoder.flac.stream, options.max_residual_partition_order);
1184                 FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.flac.stream, options.rice_parameter_search_dist);
1185                 FLAC__stream_encoder_set_total_samples_estimate(e->encoder.flac.stream, e->total_samples_to_encode);
1186                 FLAC__stream_encoder_set_metadata(e->encoder.flac.stream, (num_metadata > 0)? metadata : 0, num_metadata);
1187                 FLAC__stream_encoder_set_write_callback(e->encoder.flac.stream, flac_stream_encoder_write_callback);
1188                 FLAC__stream_encoder_set_metadata_callback(e->encoder.flac.stream, flac_stream_encoder_metadata_callback);
1189                 FLAC__stream_encoder_set_client_data(e->encoder.flac.stream, e);
1190
1191                 if(FLAC__stream_encoder_init(e->encoder.flac.stream) != FLAC__STREAM_ENCODER_OK) {
1192                         print_error_with_state(e, "ERROR initializing encoder");
1193                         return false;
1194                 }
1195         }
1196         else {
1197                 FLAC__file_encoder_set_filename(e->encoder.flac.file, e->outfilename);
1198                 FLAC__file_encoder_set_verify(e->encoder.flac.file, options.verify);
1199                 FLAC__file_encoder_set_streamable_subset(e->encoder.flac.file, !options.lax);
1200                 FLAC__file_encoder_set_do_mid_side_stereo(e->encoder.flac.file, options.do_mid_side);
1201                 FLAC__file_encoder_set_loose_mid_side_stereo(e->encoder.flac.file, options.loose_mid_side);
1202                 FLAC__file_encoder_set_channels(e->encoder.flac.file, channels);
1203                 FLAC__file_encoder_set_bits_per_sample(e->encoder.flac.file, bps);
1204                 FLAC__file_encoder_set_sample_rate(e->encoder.flac.file, sample_rate);
1205                 FLAC__file_encoder_set_blocksize(e->encoder.flac.file, options.blocksize);
1206                 FLAC__file_encoder_set_max_lpc_order(e->encoder.flac.file, options.max_lpc_order);
1207                 FLAC__file_encoder_set_qlp_coeff_precision(e->encoder.flac.file, options.qlp_coeff_precision);
1208                 FLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.file, options.do_qlp_coeff_prec_search);
1209                 FLAC__file_encoder_set_do_escape_coding(e->encoder.flac.file, options.do_escape_coding);
1210                 FLAC__file_encoder_set_do_exhaustive_model_search(e->encoder.flac.file, options.do_exhaustive_model_search);
1211                 FLAC__file_encoder_set_min_residual_partition_order(e->encoder.flac.file, options.min_residual_partition_order);
1212                 FLAC__file_encoder_set_max_residual_partition_order(e->encoder.flac.file, options.max_residual_partition_order);
1213                 FLAC__file_encoder_set_rice_parameter_search_dist(e->encoder.flac.file, options.rice_parameter_search_dist);
1214                 FLAC__file_encoder_set_total_samples_estimate(e->encoder.flac.file, e->total_samples_to_encode);
1215                 FLAC__file_encoder_set_metadata(e->encoder.flac.file, (num_metadata > 0)? metadata : 0, num_metadata);
1216                 FLAC__file_encoder_set_progress_callback(e->encoder.flac.file, flac_file_encoder_progress_callback);
1217                 FLAC__file_encoder_set_client_data(e->encoder.flac.file, e);
1218
1219                 if(FLAC__file_encoder_init(e->encoder.flac.file) != FLAC__FILE_ENCODER_OK) {
1220                         print_error_with_state(e, "ERROR initializing encoder");
1221                         return false;
1222                 }
1223         }
1224
1225         return true;
1226 }
1227
1228 FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples)
1229 {
1230 #ifdef FLAC__HAS_OGG
1231         if(e->use_ogg) {
1232                 return OggFLAC__stream_encoder_process(e->encoder.ogg.stream, buffer, samples);
1233         }
1234         else
1235 #endif
1236         if(e->is_stdout) {
1237                 return FLAC__stream_encoder_process(e->encoder.flac.stream, buffer, samples);
1238         }
1239         else {
1240                 return FLAC__file_encoder_process(e->encoder.flac.file, buffer, samples);
1241         }
1242 }
1243
1244 FLAC__bool convert_to_seek_table_template(char *requested_seek_points, int num_requested_seek_points, EncoderSession *e)
1245 {
1246         unsigned i;
1247         char *pt = requested_seek_points, *q;
1248         FLAC__bool only_placeholders = false;
1249         FLAC__bool needs_warning = false;
1250
1251         if(num_requested_seek_points == 0)
1252                 return true;
1253
1254         if(num_requested_seek_points < 0) {
1255                 strcpy(requested_seek_points, "100x<");
1256                 num_requested_seek_points = 1;
1257         }
1258
1259         if(e->is_stdout) {
1260                 only_placeholders = true;
1261         }
1262 #ifdef HAS_OGG
1263         else if(e->is_ogg) {
1264                 only_placeholders = true;
1265         }
1266 #endif
1267
1268         for(i = 0; i < (unsigned)num_requested_seek_points; i++) {
1269                 q = strchr(pt, '<');
1270                 FLAC__ASSERT(0 != q);
1271                 *q++ = '\0';
1272
1273                 if(0 == strcmp(pt, "X")) { /* -S X */
1274                         if(!FLAC__metadata_object_seektable_template_append_placeholders(e->seek_table_template, 1))
1275                                 return false;
1276                 }
1277                 else if(!only_placeholders) {
1278                         if(pt[strlen(pt)-1] == 'x') { /* -S #x */
1279                                 if(e->total_samples_to_encode > 0) { /* we can only do these if we know the number of samples to encode up front */
1280                                         if(!FLAC__metadata_object_seektable_template_append_spaced_points(e->seek_table_template, atoi(pt), e->total_samples_to_encode))
1281                                                 return false;
1282                                 }
1283                         }
1284                         else { /* -S # */
1285                                 FLAC__uint64 n = (unsigned)atoi(pt);
1286                                 if(!FLAC__metadata_object_seektable_template_append_point(e->seek_table_template, n))
1287                                         return false;
1288                         }
1289                 }
1290                 else
1291                         needs_warning = true;
1292
1293                 pt = q;
1294         }
1295
1296         if(!FLAC__metadata_object_seektable_template_sort(e->seek_table_template, /*compact=*/true))
1297                 return false;
1298
1299         if(needs_warning) {
1300                 if(e->is_stdout) {
1301                         fprintf(stderr, "%s: WARNING, cannot write back seektable when encoding to stdout\n", e->inbasefilename);
1302                 }
1303 #ifdef HAS_OGG
1304                 else if(e->is_ogg) {
1305                         fprintf(stderr, "%s: WARNING, cannot write back seektable when encoding to Ogg\n", e->inbasefilename);
1306                 }
1307 #endif
1308                 else
1309                         FLAC__ASSERT(0);
1310         }
1311
1312         return true;
1313 }
1314
1315 void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps)
1316 {
1317         unsigned wide_sample, sample, channel, byte;
1318
1319         if(bps == 8) {
1320                 if(is_unsigned_samples) {
1321                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
1322                                 for(channel = 0; channel < channels; channel++, sample++)
1323                                         dest[channel][wide_sample] = (FLAC__int32)ucbuffer_[sample] - 0x80;
1324                 }
1325                 else {
1326                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
1327                                 for(channel = 0; channel < channels; channel++, sample++)
1328                                         dest[channel][wide_sample] = (FLAC__int32)scbuffer_[sample];
1329                 }
1330         }
1331         else if(bps == 16) {
1332                 if(is_big_endian != is_big_endian_host_) {
1333                         unsigned char tmp;
1334                         const unsigned bytes = wide_samples * channels * (bps >> 3);
1335                         for(byte = 0; byte < bytes; byte += 2) {
1336                                 tmp = ucbuffer_[byte];
1337                                 ucbuffer_[byte] = ucbuffer_[byte+1];
1338                                 ucbuffer_[byte+1] = tmp;
1339                         }
1340                 }
1341                 if(is_unsigned_samples) {
1342                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
1343                                 for(channel = 0; channel < channels; channel++, sample++)
1344                                         dest[channel][wide_sample] = (FLAC__int32)usbuffer_[sample] - 0x8000;
1345                 }
1346                 else {
1347                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
1348                                 for(channel = 0; channel < channels; channel++, sample++)
1349                                         dest[channel][wide_sample] = (FLAC__int32)ssbuffer_[sample];
1350                 }
1351         }
1352         else if(bps == 24) {
1353                 if(!is_big_endian) {
1354                         unsigned char tmp;
1355                         const unsigned bytes = wide_samples * channels * (bps >> 3);
1356                         for(byte = 0; byte < bytes; byte += 3) {
1357                                 tmp = ucbuffer_[byte];
1358                                 ucbuffer_[byte] = ucbuffer_[byte+2];
1359                                 ucbuffer_[byte+2] = tmp;
1360                         }
1361                 }
1362                 if(is_unsigned_samples) {
1363                         for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
1364                                 for(channel = 0; channel < channels; channel++, sample++) {
1365                                         dest[channel][wide_sample]  = ucbuffer_[byte++]; dest[channel][wide_sample] <<= 8;
1366                                         dest[channel][wide_sample] |= ucbuffer_[byte++]; dest[channel][wide_sample] <<= 8;
1367                                         dest[channel][wide_sample] |= ucbuffer_[byte++];
1368                                         dest[channel][wide_sample] -= 0x800000;
1369                                 }
1370                 }
1371                 else {
1372                         for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
1373                                 for(channel = 0; channel < channels; channel++, sample++) {
1374                                         dest[channel][wide_sample]  = scbuffer_[byte++]; dest[channel][wide_sample] <<= 8;
1375                                         dest[channel][wide_sample] |= ucbuffer_[byte++]; dest[channel][wide_sample] <<= 8;
1376                                         dest[channel][wide_sample] |= ucbuffer_[byte++];
1377                                 }
1378                 }
1379         }
1380         else {
1381                 FLAC__ASSERT(0);
1382         }
1383 }
1384
1385 #ifdef FLAC__HAS_OGG
1386 FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
1387 {
1388         EncoderSession *encoder_session = (EncoderSession*)client_data;
1389
1390         (void)encoder;
1391
1392         encoder_session->bytes_written += bytes;
1393         /*
1394          * With Ogg FLAC we don't get one write callback per frame and
1395          * we don't have good number for 'samples', so we estimate based
1396          * on the frame number and the knowledge that all blocks (except
1397          * the last) are the same size.
1398          */
1399         (void)samples;
1400         encoder_session->samples_written = (current_frame+1) * encoder_session->blocksize;
1401
1402         if(encoder_session->verbose && encoder_session->total_samples_to_encode > 0 && !(current_frame & encoder_session->stats_mask))
1403                 print_stats(encoder_session);
1404
1405         if(fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_session->fout) == bytes)
1406                 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
1407         else
1408                 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
1409 }
1410 #endif
1411
1412 FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
1413 {
1414         EncoderSession *encoder_session = (EncoderSession*)client_data;
1415
1416         (void)encoder;
1417
1418         encoder_session->bytes_written += bytes;
1419         encoder_session->samples_written += samples;
1420
1421         if(samples && encoder_session->verbose && encoder_session->total_samples_to_encode > 0 && !(current_frame & encoder_session->stats_mask))
1422                 print_stats(encoder_session);
1423
1424         if(fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_session->fout) == bytes)
1425                 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
1426         else
1427                 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
1428 }
1429
1430 void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
1431 {
1432         /*
1433          * Nothing to do; if we get here, we're decoding to stdout, in
1434          * which case we can't seek backwards to write new metadata.
1435          */
1436         (void)encoder, (void)metadata, (void)client_data;
1437 }
1438
1439 void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
1440 {
1441         EncoderSession *encoder_session = (EncoderSession*)client_data;
1442
1443         (void)encoder, (void)total_frames_estimate;
1444
1445         encoder_session->bytes_written = bytes_written;
1446         encoder_session->samples_written = samples_written;
1447
1448         if(encoder_session->verbose && encoder_session->total_samples_to_encode > 0 && !((frames_written-1) & encoder_session->stats_mask))
1449                 print_stats(encoder_session);
1450 }
1451
1452 void print_stats(const EncoderSession *encoder_session)
1453 {
1454         const FLAC__uint64 samples_written = min(encoder_session->total_samples_to_encode, encoder_session->samples_written);
1455 #if defined _MSC_VER || defined __MINGW32__
1456         /* with VC++ you have to spoon feed it the casting */
1457         const double progress = (double)(FLAC__int64)samples_written / (double)(FLAC__int64)encoder_session->total_samples_to_encode;
1458         const double ratio = (double)(FLAC__int64)encoder_session->bytes_written / ((double)(FLAC__int64)encoder_session->unencoded_size * progress);
1459 #else
1460         const double progress = (double)samples_written / (double)encoder_session->total_samples_to_encode;
1461         const double ratio = (double)encoder_session->bytes_written / ((double)encoder_session->unencoded_size * progress);
1462 #endif
1463
1464         if(samples_written == encoder_session->total_samples_to_encode) {
1465                 fprintf(stderr, "\r%s:%s wrote %u bytes, ratio=%0.3f",
1466                         encoder_session->inbasefilename,
1467                         encoder_session->verify? " Verify OK," : "",
1468                         (unsigned)encoder_session->bytes_written,
1469                         ratio
1470                 );
1471         }
1472         else {
1473                 fprintf(stderr, "\r%s: %u%% complete, ratio=%0.3f", encoder_session->inbasefilename, (unsigned)floor(progress * 100.0 + 0.5), ratio);
1474         }
1475 }
1476
1477 void print_error_with_state(const EncoderSession *e, const char *message)
1478 {
1479         const int ilen = strlen(e->inbasefilename) + 1;
1480
1481         fprintf(stderr, "\n%s: %s\n", e->inbasefilename, message);
1482
1483 #ifdef FLAC__HAS_OGG
1484         if(e->use_ogg) {
1485                 const OggFLAC__StreamEncoderState ose_state = OggFLAC__stream_encoder_get_state(e->encoder.ogg.stream);
1486                 if(ose_state != OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
1487                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)ose_state, OggFLAC__StreamEncoderStateString[ose_state]);
1488                 }
1489                 else {
1490                         const FLAC__StreamEncoderState fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream);
1491                         if(fse_state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
1492                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fse_state, FLAC__StreamEncoderStateString[fse_state]);
1493                         }
1494                         else {
1495                                 const FLAC__StreamDecoderState fsd_state = OggFLAC__stream_encoder_get_verify_decoder_state(e->encoder.ogg.stream);
1496                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1497                         }
1498                 }
1499         }
1500         else
1501 #endif
1502         if(e->is_stdout) {
1503                 const FLAC__StreamEncoderState fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream);
1504                 if(fse_state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
1505                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fse_state, FLAC__StreamEncoderStateString[fse_state]);
1506                 }
1507                 else {
1508                         const FLAC__StreamDecoderState fsd_state = FLAC__stream_encoder_get_verify_decoder_state(e->encoder.flac.stream);
1509                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1510                 }
1511         }
1512         else {
1513                 const FLAC__FileEncoderState ffe_state = FLAC__file_encoder_get_state(e->encoder.flac.file);
1514                 if(ffe_state != FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) {
1515                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)ffe_state, FLAC__FileEncoderStateString[ffe_state]);
1516                 }
1517                 else {
1518                         const FLAC__SeekableStreamEncoderState fsse_state = FLAC__file_encoder_get_seekable_stream_encoder_state(e->encoder.flac.file);
1519                         if(fsse_state != FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) {
1520                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsse_state, FLAC__SeekableStreamEncoderStateString[fsse_state]);
1521                         }
1522                         else {
1523                                 const FLAC__StreamEncoderState fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file);
1524                                 if(fse_state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
1525                                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fse_state, FLAC__StreamEncoderStateString[fse_state]);
1526                                 }
1527                                 else {
1528                                         const FLAC__StreamDecoderState fsd_state = FLAC__file_encoder_get_verify_decoder_state(e->encoder.flac.file);
1529                                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1530                                 }
1531                         }
1532                 }
1533         }
1534 }
1535
1536 void print_verify_error(EncoderSession *e)
1537 {
1538         FLAC__uint64 absolute_sample;
1539         unsigned frame_number;
1540         unsigned channel;
1541         unsigned sample;
1542         FLAC__int32 expected;
1543         FLAC__int32 got;
1544
1545 #ifdef FLAC__HAS_OGG
1546         if(e->use_ogg) {
1547                 OggFLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.ogg.stream, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
1548         }
1549         else
1550 #endif
1551         if(e->is_stdout) {
1552                 FLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.flac.stream, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
1553         }
1554         else {
1555                 FLAC__file_encoder_get_verify_decoder_error_stats(e->encoder.flac.file, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
1556         }
1557
1558         fprintf(stderr, "%s: ERROR: mismatch in decoded data, verify FAILED!\n", e->inbasefilename);
1559         fprintf(stderr, "       Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)absolute_sample, frame_number, channel, sample, expected, got);
1560         fprintf(stderr, "       Please submit a bug report to\n");
1561         fprintf(stderr, "           http://sourceforge.net/bugs/?func=addbug&group_id=13478\n");
1562         fprintf(stderr, "       Make sure to include an email contact in the comment and/or use the\n");
1563         fprintf(stderr, "       \"Monitor\" feature to monitor the bug status.\n");
1564         fprintf(stderr, "Verify FAILED!  Do not trust %s\n", e->outfilename);
1565 }
1566
1567 FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn)
1568 {
1569         size_t bytes_read = fread(val, 1, 2, f);
1570
1571         if(bytes_read == 0) {
1572                 if(!eof_ok) {
1573                         fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1574                         return false;
1575                 }
1576                 else
1577                         return true;
1578         }
1579         else if(bytes_read < 2) {
1580                 fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1581                 return false;
1582         }
1583         else {
1584                 if(is_big_endian_host_) {
1585                         FLAC__byte tmp, *b = (FLAC__byte*)val;
1586                         tmp = b[1]; b[1] = b[0]; b[0] = tmp;
1587                 }
1588                 return true;
1589         }
1590 }
1591
1592 FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn)
1593 {
1594         size_t bytes_read = fread(val, 1, 4, f);
1595
1596         if(bytes_read == 0) {
1597                 if(!eof_ok) {
1598                         fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1599                         return false;
1600                 }
1601                 else
1602                         return true;
1603         }
1604         else if(bytes_read < 4) {
1605                 fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1606                 return false;
1607         }
1608         else {
1609                 if(is_big_endian_host_) {
1610                         FLAC__byte tmp, *b = (FLAC__byte*)val;
1611                         tmp = b[3]; b[3] = b[0]; b[0] = tmp;
1612                         tmp = b[2]; b[2] = b[1]; b[1] = tmp;
1613                 }
1614                 return true;
1615         }
1616 }
1617
1618 FLAC__bool
1619 read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn)
1620 {
1621         unsigned char buf[4];
1622         size_t bytes_read= fread(buf, 1, 2, f);
1623
1624         if(bytes_read==0U && eof_ok)
1625                 return true;
1626         else if(bytes_read<2U) {
1627                 fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1628                 return false;
1629         }
1630
1631         /* this is independent of host endianness */
1632         *val= (FLAC__uint16)(buf[0])<<8 | buf[1];
1633
1634         return true;
1635 }
1636
1637 FLAC__bool
1638 read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn)
1639 {
1640         unsigned char buf[4];
1641         size_t bytes_read= fread(buf, 1, 4, f);
1642
1643         if(bytes_read==0U && eof_ok)
1644                 return true;
1645         else if(bytes_read<4U) {
1646                 fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1647                 return false;
1648         }
1649
1650         /* this is independent of host endianness */
1651         *val= (FLAC__uint32)(buf[0])<<24 | (FLAC__uint32)(buf[1])<<16 |
1652                 (FLAC__uint32)(buf[2])<<8 | buf[3];
1653
1654         return true;
1655 }
1656
1657 FLAC__bool
1658 read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn)
1659         /* Read an IEEE 754 80-bit (aka SANE) extended floating point value from 'f',
1660          * convert it into an integral value and store in 'val'.  Return false if only
1661          * between 1 and 9 bytes remain in 'f', if 0 bytes remain in 'f' and 'eof_ok' is
1662          * false, or if the value is negative, between zero and one, or too large to be
1663          * represented by 'val'; return true otherwise.
1664          */
1665 {
1666         unsigned int i;
1667         unsigned char buf[10];
1668         size_t bytes_read= fread(buf, 1U, 10U, f);
1669         FLAC__int16 e= ((FLAC__uint16)(buf[0])<<8 | (FLAC__uint16)(buf[1]))-0x3FFF;
1670         FLAC__int16 shift= 63-e;
1671         FLAC__uint64 p= 0U;
1672
1673         if(bytes_read==0U && eof_ok)
1674                 return true;
1675         else if(bytes_read<10U) {
1676                 fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn);
1677                 return false;
1678         }
1679         else if((buf[0]>>7)==1U || e<0 || e>63) {
1680                 fprintf(stderr, "%s: ERROR: invalid floating-point value\n", fn);
1681                 return false;
1682         }
1683
1684         for(i= 0U; i<8U; ++i)
1685                 p|= (FLAC__uint64)(buf[i+2])<<(56U-i*8);
1686         *val= (FLAC__uint32)((p>>shift)+(p>>(shift-1) & 0x1));
1687
1688         return true;
1689 }