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