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