1 /*
2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3 ** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 **
19 ** Any non-GPL usage of this software or parts of this software is strictly
20 ** forbidden.
21 **
22 ** The "appropriate copyright message" mentioned in section 2c of the GPLv2
23 ** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
24 **
25 ** Commercial non-GPL licensing of this software is possible.
26 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
27 **
28 ** $Id: main.c,v 1.89 2015/01/19 09:46:12 knik Exp $
29 **/
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #ifdef _WIN32
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #include <io.h>
39 #ifndef __MINGW32__
40 #define off_t __int64
41 #endif
42 #else
43 #include <time.h>
44 #endif
45 
46 #include <fcntl.h>
47 #include <stdio.h>
48 #include <stdarg.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <getopt.h>
52 
53 #include <neaacdec.h>
54 
55 #include "unicode_support.h"
56 #include "audio.h"
57 #include "mp4read.h"
58 
59 #ifdef HAVE_GETOPT_H
60 # include <getopt.h>
61 #else
62 # include "getopt.h"
63 # include "getopt.c"
64 #endif
65 
66 #ifndef min
67 #define min(a,b) ( (a) < (b) ? (a) : (b) )
68 #endif
69 
70 #define MAX_CHANNELS 6 /* make this higher to support files with
71                           more channels */
72 
73 #define MAX_PERCENTS 384
74 
75 static int quiet = 0;
76 
faad_fprintf(FILE * stream,const char * fmt,...)77 static void faad_fprintf(FILE *stream, const char *fmt, ...)
78 {
79     va_list ap;
80 
81     if (!quiet)
82     {
83         va_start(ap, fmt);
84         vfprintf(stream, fmt, ap);
85         va_end(ap);
86     }
87 
88 #ifdef _WIN32
89     if (!_isatty(_fileno(stream)))
90     {
91         fflush(stream); /*ensure real-time progress output on Win32*/
92     }
93 #endif
94 }
95 
96 /* FAAD file buffering routines */
97 typedef struct {
98     long bytes_into_buffer;
99     long bytes_consumed;
100     long file_offset;
101     unsigned char *buffer;
102     int at_eof;
103     FILE *infile;
104 } aac_buffer;
105 
106 
fill_buffer(aac_buffer * b)107 static int fill_buffer(aac_buffer *b)
108 {
109     int bread;
110 
111     if (b->bytes_consumed > 0)
112     {
113         if (b->bytes_into_buffer)
114         {
115             memmove((void*)b->buffer, (void*)(b->buffer + b->bytes_consumed),
116                 b->bytes_into_buffer*sizeof(unsigned char));
117         }
118 
119         if (!b->at_eof)
120         {
121             bread = fread((void*)(b->buffer + b->bytes_into_buffer), 1,
122                 b->bytes_consumed, b->infile);
123 
124             if (bread != b->bytes_consumed)
125                 b->at_eof = 1;
126 
127             b->bytes_into_buffer += bread;
128         }
129 
130         b->bytes_consumed = 0;
131 
132         if (b->bytes_into_buffer > 3)
133         {
134             if (memcmp(b->buffer, "TAG", 3) == 0)
135                 b->bytes_into_buffer = 0;
136         }
137         if (b->bytes_into_buffer > 11)
138         {
139             if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0)
140                 b->bytes_into_buffer = 0;
141         }
142         if (b->bytes_into_buffer > 8)
143         {
144             if (memcmp(b->buffer, "APETAGEX", 8) == 0)
145                 b->bytes_into_buffer = 0;
146         }
147     }
148 
149     return 1;
150 }
151 
advance_buffer(aac_buffer * b,int bytes)152 static void advance_buffer(aac_buffer *b, int bytes)
153 {
154     while ((b->bytes_into_buffer > 0) && (bytes > 0))
155     {
156         int chunk = min(bytes, b->bytes_into_buffer);
157 
158         bytes -= chunk;
159         b->file_offset += chunk;
160         b->bytes_consumed = chunk;
161         b->bytes_into_buffer -= chunk;
162 
163         if (b->bytes_into_buffer == 0)
164             fill_buffer(b);
165     }
166 }
167 
lookforheader(aac_buffer * b)168 static void lookforheader(aac_buffer *b)
169 {
170     int i = 0;
171     while (!b->at_eof )
172     {
173         if (b->bytes_into_buffer > 4)
174         {
175             if( ((b->buffer[0+i] == 0xff) && ((b->buffer[1+i] & 0xf6) == 0xf0)) ||
176                 (b->buffer[0+i] == 'A'    && b->buffer[1+i] == 'D' && b->buffer[2+i] == 'I' && b->buffer[3+i] == 'F'))
177             {
178                 fill_buffer(b);
179                 break;
180             } else {
181                 i++;
182                 b->file_offset       += 1;
183                 b->bytes_consumed    += 1;
184                 b->bytes_into_buffer -= 1;
185             }
186         }
187         else
188         {
189             fill_buffer(b);
190             i = 0;
191         }
192     }
193 }
194 
195 static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0};
196 
adts_parse(aac_buffer * b,int * bitrate,float * length)197 static int adts_parse(aac_buffer *b, int *bitrate, float *length)
198 {
199     int frames, frame_length;
200     int t_framelength = 0;
201     int samplerate;
202     float frames_per_sec, bytes_per_frame;
203 
204     /* Read all frames to ensure correct time and bitrate */
205     for (frames = 0; /* */; frames++)
206     {
207         fill_buffer(b);
208 
209         if (b->bytes_into_buffer > 7)
210         {
211             /* check syncword */
212             if (!((b->buffer[0] == 0xFF)&&((b->buffer[1] & 0xF6) == 0xF0)))
213                 break;
214 
215             if (frames == 0)
216                 samplerate = adts_sample_rates[(b->buffer[2]&0x3c)>>2];
217 
218             frame_length = ((((unsigned int)b->buffer[3] & 0x3)) << 11)
219                 | (((unsigned int)b->buffer[4]) << 3) | (b->buffer[5] >> 5);
220             if (frame_length == 0)
221                 break;
222 
223             t_framelength += frame_length;
224 
225             if (frame_length > b->bytes_into_buffer)
226                 break;
227 
228             advance_buffer(b, frame_length);
229         } else {
230             break;
231         }
232     }
233 
234     frames_per_sec = (float)samplerate/1024.0f;
235     if (frames != 0)
236         bytes_per_frame = (float)t_framelength/(float)(frames*1000);
237     else
238         bytes_per_frame = 0;
239     *bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5);
240     if (frames_per_sec != 0)
241         *length = (float)frames/frames_per_sec;
242     else
243         *length = 1;
244 
245     return 1;
246 }
247 
248 
249 
read_callback(void * user_data,void * buffer,uint32_t length)250 uint32_t read_callback(void *user_data, void *buffer, uint32_t length)
251 {
252     return fread(buffer, 1, length, (FILE*)user_data);
253 }
254 
seek_callback(void * user_data,uint64_t position)255 uint32_t seek_callback(void *user_data, uint64_t position)
256 {
257     return fseek((FILE*)user_data, position, SEEK_SET);
258 }
259 
260 /* MicroSoft channel definitions */
261 #define SPEAKER_FRONT_LEFT             0x1
262 #define SPEAKER_FRONT_RIGHT            0x2
263 #define SPEAKER_FRONT_CENTER           0x4
264 #define SPEAKER_LOW_FREQUENCY          0x8
265 #define SPEAKER_BACK_LEFT              0x10
266 #define SPEAKER_BACK_RIGHT             0x20
267 #define SPEAKER_FRONT_LEFT_OF_CENTER   0x40
268 #define SPEAKER_FRONT_RIGHT_OF_CENTER  0x80
269 #define SPEAKER_BACK_CENTER            0x100
270 #define SPEAKER_SIDE_LEFT              0x200
271 #define SPEAKER_SIDE_RIGHT             0x400
272 #define SPEAKER_TOP_CENTER             0x800
273 #define SPEAKER_TOP_FRONT_LEFT         0x1000
274 #define SPEAKER_TOP_FRONT_CENTER       0x2000
275 #define SPEAKER_TOP_FRONT_RIGHT        0x4000
276 #define SPEAKER_TOP_BACK_LEFT          0x8000
277 #define SPEAKER_TOP_BACK_CENTER        0x10000
278 #define SPEAKER_TOP_BACK_RIGHT         0x20000
279 #define SPEAKER_RESERVED               0x80000000
280 
aacChannelConfig2wavexChannelMask(NeAACDecFrameInfo * hInfo)281 static long aacChannelConfig2wavexChannelMask(NeAACDecFrameInfo *hInfo)
282 {
283     if (hInfo->channels == 6 && hInfo->num_lfe_channels)
284     {
285         return SPEAKER_FRONT_LEFT + SPEAKER_FRONT_RIGHT +
286             SPEAKER_FRONT_CENTER + SPEAKER_LOW_FREQUENCY +
287             SPEAKER_BACK_LEFT + SPEAKER_BACK_RIGHT;
288     } else {
289         return 0;
290     }
291 }
292 
position2string(int position)293 static char *position2string(int position)
294 {
295     switch (position)
296     {
297     case FRONT_CHANNEL_CENTER: return "Center front";
298     case FRONT_CHANNEL_LEFT:   return "Left front";
299     case FRONT_CHANNEL_RIGHT:  return "Right front";
300     case SIDE_CHANNEL_LEFT:    return "Left side";
301     case SIDE_CHANNEL_RIGHT:   return "Right side";
302     case BACK_CHANNEL_LEFT:    return "Left back";
303     case BACK_CHANNEL_RIGHT:   return "Right back";
304     case BACK_CHANNEL_CENTER:  return "Center back";
305     case LFE_CHANNEL:          return "LFE";
306     case UNKNOWN_CHANNEL:      return "Unknown";
307     default: return "";
308     }
309 
310     return "";
311 }
312 
print_channel_info(NeAACDecFrameInfo * frameInfo)313 static void print_channel_info(NeAACDecFrameInfo *frameInfo)
314 {
315     /* print some channel info */
316     int i;
317     long channelMask = aacChannelConfig2wavexChannelMask(frameInfo);
318 
319     faad_fprintf(stderr, "  ---------------------\n");
320     if (frameInfo->num_lfe_channels > 0)
321     {
322         faad_fprintf(stderr, " | Config: %2d.%d Ch     |", frameInfo->channels-frameInfo->num_lfe_channels, frameInfo->num_lfe_channels);
323     } else {
324         faad_fprintf(stderr, " | Config: %2d Ch       |", frameInfo->channels);
325     }
326     if (channelMask)
327         faad_fprintf(stderr, " WARNING: channels are reordered according to\n");
328     else
329         faad_fprintf(stderr, "\n");
330     faad_fprintf(stderr, "  ---------------------");
331     if (channelMask)
332         faad_fprintf(stderr, "  MS defaults defined in WAVE_FORMAT_EXTENSIBLE\n");
333     else
334         faad_fprintf(stderr, "\n");
335     faad_fprintf(stderr, " | Ch |    Position    |\n");
336     faad_fprintf(stderr, "  ---------------------\n");
337     for (i = 0; i < frameInfo->channels; i++)
338     {
339         faad_fprintf(stderr, " | %.2d | %-14s |\n", i, position2string((int)frameInfo->channel_position[i]));
340     }
341     faad_fprintf(stderr, "  ---------------------\n");
342     faad_fprintf(stderr, "\n");
343 }
344 
FindAdtsSRIndex(int sr)345 static int FindAdtsSRIndex(int sr)
346 {
347     int i;
348 
349     for (i = 0; i < 16; i++)
350     {
351         if (sr == adts_sample_rates[i])
352             return i;
353     }
354     return 16 - 1;
355 }
356 
MakeAdtsHeader(int * dataSize,NeAACDecFrameInfo * hInfo,int old_format)357 static unsigned char *MakeAdtsHeader(int *dataSize, NeAACDecFrameInfo *hInfo, int old_format)
358 {
359     unsigned char *data;
360     int profile = (hInfo->object_type - 1) & 0x3;
361     int sr_index = ((hInfo->sbr == SBR_UPSAMPLED) || (hInfo->sbr == NO_SBR_UPSAMPLED)) ?
362         FindAdtsSRIndex(hInfo->samplerate / 2) : FindAdtsSRIndex(hInfo->samplerate);
363     int skip = (old_format) ? 8 : 7;
364     int framesize = skip + hInfo->bytesconsumed;
365 
366     if (hInfo->header_type == ADTS)
367         framesize -= skip;
368 
369     *dataSize = 7;
370 
371     data = malloc(*dataSize * sizeof(unsigned char));
372     memset(data, 0, *dataSize * sizeof(unsigned char));
373 
374     data[0] += 0xFF; /* 8b: syncword */
375 
376     data[1] += 0xF0; /* 4b: syncword */
377     /* 1b: mpeg id = 0 */
378     /* 2b: layer = 0 */
379     data[1] += 1; /* 1b: protection absent */
380 
381     data[2] += ((profile << 6) & 0xC0); /* 2b: profile */
382     data[2] += ((sr_index << 2) & 0x3C); /* 4b: sampling_frequency_index */
383     /* 1b: private = 0 */
384     data[2] += ((hInfo->channels >> 2) & 0x1); /* 1b: channel_configuration */
385 
386     data[3] += ((hInfo->channels << 6) & 0xC0); /* 2b: channel_configuration */
387     /* 1b: original */
388     /* 1b: home */
389     /* 1b: copyright_id */
390     /* 1b: copyright_id_start */
391     data[3] += ((framesize >> 11) & 0x3); /* 2b: aac_frame_length */
392 
393     data[4] += ((framesize >> 3) & 0xFF); /* 8b: aac_frame_length */
394 
395     data[5] += ((framesize << 5) & 0xE0); /* 3b: aac_frame_length */
396     data[5] += ((0x7FF >> 6) & 0x1F); /* 5b: adts_buffer_fullness */
397 
398     data[6] += ((0x7FF << 2) & 0x3F); /* 6b: adts_buffer_fullness */
399     /* 2b: num_raw_data_blocks */
400 
401     return data;
402 }
403 
404 /* globals */
405 char *progName;
406 
407 static const char *file_ext[] =
408 {
409     NULL,
410     ".wav",
411     ".aif",
412     ".au",
413     ".au",
414     ".pcm",
415     NULL
416 };
417 
usage(void)418 static void usage(void)
419 {
420     faad_fprintf(stdout, "\nUsage:\n");
421     faad_fprintf(stdout, "%s [options] infile.aac\n", progName);
422     faad_fprintf(stdout, "Options:\n");
423     faad_fprintf(stdout, " -h    Shows this help screen.\n");
424     faad_fprintf(stdout, " -i    Shows info about the input file.\n");
425     faad_fprintf(stdout, " -a X  Write MPEG-4 AAC ADTS output file.\n");
426     faad_fprintf(stdout, " -t    Assume old ADTS format.\n");
427     faad_fprintf(stdout, " -o X  Set output filename.\n");
428     faad_fprintf(stdout, " -f X  Set output format. Valid values for X are:\n");
429     faad_fprintf(stdout, "        1:  Microsoft WAV format (default).\n");
430     faad_fprintf(stdout, "        2:  RAW PCM data.\n");
431     faad_fprintf(stdout, " -b X  Set output sample format. Valid values for X are:\n");
432     faad_fprintf(stdout, "        1:  16 bit PCM data (default).\n");
433     faad_fprintf(stdout, "        2:  24 bit PCM data.\n");
434     faad_fprintf(stdout, "        3:  32 bit PCM data.\n");
435     faad_fprintf(stdout, "        4:  32 bit floating point data.\n");
436     faad_fprintf(stdout, "        5:  64 bit floating point data.\n");
437     faad_fprintf(stdout, " -s X  Force the samplerate to X (for RAW files).\n");
438     faad_fprintf(stdout, " -l X  Set object type. Supported object types:\n");
439     faad_fprintf(stdout, "        1:  Main object type.\n");
440     faad_fprintf(stdout, "        2:  LC (Low Complexity) object type.\n");
441     faad_fprintf(stdout, "        4:  LTP (Long Term Prediction) object type.\n");
442     faad_fprintf(stdout, "        23: LD (Low Delay) object type.\n");
443     faad_fprintf(stdout, " -d    Down matrix 5.1 to 2 channels\n");
444     faad_fprintf(stdout, " -w    Write output to stdio instead of a file.\n");
445     faad_fprintf(stdout, " -g    Disable gapless decoding.\n");
446     faad_fprintf(stdout, " -q    Quiet - suppresses status messages.\n");
447     faad_fprintf(stdout, " -j X  Jump - start output X seconds into track (MP4 files only).\n");
448     faad_fprintf(stdout, "Example:\n");
449     faad_fprintf(stdout, "       %s infile.aac\n", progName);
450     faad_fprintf(stdout, "       %s infile.mp4\n", progName);
451     faad_fprintf(stdout, "       %s -o outfile.wav infile.aac\n", progName);
452     faad_fprintf(stdout, "       %s -w infile.aac > outfile.wav\n", progName);
453     faad_fprintf(stdout, "       %s -a outfile.aac infile.aac\n", progName);
454     return;
455 }
456 
decodeAACfile(char * aacfile,char * sndfile,char * adts_fn,int to_stdout,int def_srate,int object_type,int outputFormat,int fileType,int downMatrix,int infoOnly,int adts_out,int old_format,float * song_length)457 static int decodeAACfile(char *aacfile, char *sndfile, char *adts_fn, int to_stdout,
458                   int def_srate, int object_type, int outputFormat, int fileType,
459                   int downMatrix, int infoOnly, int adts_out, int old_format,
460                   float *song_length)
461 {
462     int tagsize;
463     unsigned long samplerate;
464     unsigned char channels;
465     void *sample_buffer;
466 
467     audio_file *aufile = NULL;
468 
469     FILE *adtsFile = NULL;
470     unsigned char *adtsData;
471     int adtsDataSize;
472 
473     NeAACDecHandle hDecoder;
474     NeAACDecFrameInfo frameInfo;
475     NeAACDecConfigurationPtr config;
476 
477     char percents[MAX_PERCENTS];
478     int percent, old_percent = -1;
479     int bread, fileread;
480     int header_type = 0;
481     int bitrate = 0;
482     float length = 0;
483 
484     int first_time = 1;
485     int retval;
486     int streaminput = 0;
487 
488     aac_buffer b;
489 
490     memset(&b, 0, sizeof(aac_buffer));
491 
492     if (adts_out)
493     {
494         adtsFile = faad_fopen(adts_fn, "wb");
495         if (adtsFile == NULL)
496         {
497             faad_fprintf(stderr, "Error opening file: %s\n", adts_fn);
498             return 1;
499         }
500     }
501 
502     if (0 == strcmp(aacfile, "-"))
503     {
504         b.infile = stdin;
505 #ifdef _WIN32
506         _setmode(_fileno(stdin), O_BINARY);
507 #endif
508 
509     }
510     else
511     {
512         b.infile = faad_fopen(aacfile, "rb");
513         if (b.infile == NULL)
514         {
515             /* unable to open file */
516             faad_fprintf(stderr, "Error opening file: %s\n", aacfile);
517             return 1;
518         }
519     }
520 
521     retval = fseek(b.infile, 0, SEEK_END);
522 #ifdef _WIN32
523     if (0 == strcmp(aacfile, "-")) {
524         retval = -1;
525     }
526 #endif
527     if (retval )
528     {
529         faad_fprintf(stderr, "Input not seekable %s\n", aacfile);
530         fileread = -1;
531         streaminput = 1;
532     } else {
533         fileread = ftell(b.infile);
534         fseek(b.infile, 0, SEEK_SET);
535     };
536 
537     if (!(b.buffer = (unsigned char*)malloc(FAAD_MIN_STREAMSIZE*MAX_CHANNELS)))
538     {
539         faad_fprintf(stderr, "Memory allocation error\n");
540         return 0;
541     }
542     memset(b.buffer, 0, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
543 
544     bread = fread(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, b.infile);
545     b.bytes_into_buffer = bread;
546     b.bytes_consumed = 0;
547     b.file_offset = 0;
548 
549     if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS)
550         b.at_eof = 1;
551 
552     tagsize = 0;
553     if (!memcmp(b.buffer, "ID3", 3))
554     {
555         /* high bit is not used */
556         tagsize = (b.buffer[6] << 21) | (b.buffer[7] << 14) |
557             (b.buffer[8] <<  7) | (b.buffer[9] <<  0);
558 
559         tagsize += 10;
560         advance_buffer(&b, tagsize);
561         fill_buffer(&b);
562     }
563 
564     hDecoder = NeAACDecOpen();
565 
566     /* Set the default object type and samplerate */
567     /* This is useful for RAW AAC files */
568     config = NeAACDecGetCurrentConfiguration(hDecoder);
569     if (def_srate)
570         config->defSampleRate = def_srate;
571     config->defObjectType = object_type;
572     config->outputFormat = outputFormat;
573     config->downMatrix = downMatrix;
574     config->useOldADTSFormat = old_format;
575     //config->dontUpSampleImplicitSBR = 1;
576     NeAACDecSetConfiguration(hDecoder, config);
577 
578     /* get AAC infos for printing */
579     header_type = 0;
580     if (streaminput == 1)
581         lookforheader(&b);
582 
583     if ((b.buffer[0] == 0xFF) && ((b.buffer[1] & 0xF6) == 0xF0))
584     {
585         if (streaminput == 1)
586         {
587             int /*frames,*/ frame_length;
588             int samplerate;
589             float frames_per_sec, bytes_per_frame;
590             channels = 2;
591             samplerate = adts_sample_rates[(b.buffer[2]&0x3c)>>2];
592             frame_length = ((((unsigned int)b.buffer[3] & 0x3)) << 11)
593                 | (((unsigned int)b.buffer[4]) << 3) | (b.buffer[5] >> 5);
594             frames_per_sec = (float)samplerate/1024.0f;
595             bytes_per_frame = (float)frame_length/(float)(1000);
596             bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5);
597             length = 1;
598             faad_fprintf(stderr, "Streamed input format  samplerate %d channels %d.\n", samplerate, channels);
599         } else {
600             adts_parse(&b, &bitrate, &length);
601             fseek(b.infile, tagsize, SEEK_SET);
602 
603             bread = fread(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, b.infile);
604             if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS)
605                 b.at_eof = 1;
606             else
607                 b.at_eof = 0;
608             b.bytes_into_buffer = bread;
609             b.bytes_consumed = 0;
610             b.file_offset = tagsize;
611         }
612 
613         header_type = 1;
614     }
615     else if (memcmp(b.buffer, "ADIF", 4) == 0)
616     {
617         int skip_size = (b.buffer[4] & 0x80) ? 9 : 0;
618         bitrate = ((unsigned int)(b.buffer[4 + skip_size] & 0x0F)<<19) |
619             ((unsigned int)b.buffer[5 + skip_size]<<11) |
620             ((unsigned int)b.buffer[6 + skip_size]<<3) |
621             ((unsigned int)b.buffer[7 + skip_size] & 0xE0);
622 
623         length = (float)fileread;
624         if (length != 0)
625         {
626             length = ((float)length*8.f)/((float)bitrate) + 0.5f;
627         }
628 
629         bitrate = (int)((float)bitrate/1000.0f + 0.5f);
630 
631         header_type = 2;
632     }
633 
634     *song_length = length;
635 
636     fill_buffer(&b);
637     if ((bread = NeAACDecInit(hDecoder, b.buffer,
638         b.bytes_into_buffer, &samplerate, &channels)) < 0)
639     {
640         /* If some error initializing occured, skip the file */
641         faad_fprintf(stderr, "Error initializing decoder library.\n");
642         if (b.buffer)
643             free(b.buffer);
644         NeAACDecClose(hDecoder);
645         if (b.infile != stdin)
646             fclose(b.infile);
647         return 1;
648     }
649     advance_buffer(&b, bread);
650     fill_buffer(&b);
651 
652     /* print AAC file info */
653     faad_fprintf(stderr, "%s file info:\n", aacfile);
654     switch (header_type)
655     {
656     case 0:
657         faad_fprintf(stderr, "RAW\n\n");
658         break;
659     case 1:
660         faad_fprintf(stderr, "ADTS, %.3f sec, %d kbps, %d Hz\n\n",
661             length, bitrate, samplerate);
662         break;
663     case 2:
664         faad_fprintf(stderr, "ADIF, %.3f sec, %d kbps, %d Hz\n\n",
665             length, bitrate, samplerate);
666         break;
667     }
668 
669     if (infoOnly)
670     {
671         NeAACDecClose(hDecoder);
672         if (b.infile != stdin)
673             fclose(b.infile);
674         if (b.buffer)
675             free(b.buffer);
676         return 0;
677     }
678 
679     do
680     {
681         sample_buffer = NeAACDecDecode(hDecoder, &frameInfo,
682             b.buffer, b.bytes_into_buffer);
683 
684         if (adts_out == 1)
685         {
686             int skip = (old_format) ? 8 : 7;
687             adtsData = MakeAdtsHeader(&adtsDataSize, &frameInfo, old_format);
688 
689             /* write the adts header */
690             fwrite(adtsData, 1, adtsDataSize, adtsFile);
691 
692             /* write the frame data */
693             if (frameInfo.header_type == ADTS)
694                 fwrite(b.buffer + skip, 1, frameInfo.bytesconsumed - skip, adtsFile);
695             else
696                 fwrite(b.buffer, 1, frameInfo.bytesconsumed, adtsFile);
697         }
698 
699         /* update buffer indices */
700         advance_buffer(&b, frameInfo.bytesconsumed);
701 
702         /* check if the inconsistent number of channels */
703         if (aufile != NULL && frameInfo.channels != aufile->channels)
704             frameInfo.error = 12;
705 
706         if (frameInfo.error > 0)
707         {
708             faad_fprintf(stderr, "Error: %s\n",
709                 NeAACDecGetErrorMessage(frameInfo.error));
710         }
711 
712         /* open the sound file now that the number of channels are known */
713         if (first_time && !frameInfo.error)
714         {
715             /* print some channel info */
716             print_channel_info(&frameInfo);
717 
718             if (!adts_out)
719             {
720                 /* open output file */
721                 if (!to_stdout)
722                 {
723                     aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
724                         outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
725                 } else {
726                     aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
727                         outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
728                 }
729                 if (aufile == NULL)
730                 {
731                     if (b.buffer)
732                         free(b.buffer);
733                     NeAACDecClose(hDecoder);
734                     if (b.infile != stdin)
735                         fclose(b.infile);
736                     return 0;
737                 }
738             } else {
739                 faad_fprintf(stderr, "Writing output MPEG-4 AAC ADTS file.\n\n");
740             }
741             first_time = 0;
742         }
743 
744         percent = min((int)(b.file_offset*100)/fileread, 100);
745         if (percent > old_percent)
746         {
747             old_percent = percent;
748             snprintf(percents, MAX_PERCENTS, "%d%% decoding %s.", percent, aacfile);
749             faad_fprintf(stderr, "%s\r", percents);
750 #ifdef _WIN32
751             SetConsoleTitle(percents);
752 #endif
753         }
754 
755         if ((frameInfo.error == 0) && (frameInfo.samples > 0) && (!adts_out))
756         {
757             if (write_audio_file(aufile, sample_buffer, frameInfo.samples, 0) == 0)
758                 break;
759         }
760 
761         /* fill buffer */
762         fill_buffer(&b);
763 
764         if (b.bytes_into_buffer == 0)
765             sample_buffer = NULL; /* to make sure it stops now */
766 
767     } while (sample_buffer != NULL);
768 
769     NeAACDecClose(hDecoder);
770 
771     if (adts_out == 1)
772     {
773         fclose(adtsFile);
774     }
775 
776     if (b.infile != stdin)
777         fclose(b.infile);
778 
779     if (!first_time && !adts_out)
780         close_audio_file(aufile);
781 
782     if (b.buffer)
783         free(b.buffer);
784 
785     return frameInfo.error;
786 }
787 
788 static const unsigned long srates[] =
789 {
790     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
791     12000, 11025, 8000
792 };
793 
decodeMP4file(char * mp4file,char * sndfile,char * adts_fn,int to_stdout,int outputFormat,int fileType,int downMatrix,int noGapless,int infoOnly,int adts_out,float * song_length,float seek_to)794 static int decodeMP4file(char *mp4file, char *sndfile, char *adts_fn, int to_stdout,
795                   int outputFormat, int fileType, int downMatrix, int noGapless,
796                   int infoOnly, int adts_out, float *song_length, float seek_to)
797 {
798     /*int track;*/
799     unsigned long samplerate;
800     unsigned char channels;
801     void *sample_buffer;
802 
803     long sampleId, startSampleId;
804 
805     audio_file *aufile = NULL;
806 
807     FILE *adtsFile = NULL;
808     unsigned char *adtsData;
809     int adtsDataSize;
810 
811     NeAACDecHandle hDecoder;
812     NeAACDecConfigurationPtr config;
813     NeAACDecFrameInfo frameInfo;
814     mp4AudioSpecificConfig mp4ASC;
815 
816     char percents[MAX_PERCENTS];
817     int percent, old_percent = -1;
818 
819     int first_time = 1;
820 
821     /* for gapless decoding */
822     unsigned int useAacLength = 1;
823     unsigned int framesize;
824     unsigned decoded;
825 
826     if (strcmp(mp4file, "-") == 0 ) {
827         faad_fprintf(stderr, "Cannot open stdin for MP4 input \n");
828         return 1;
829     }
830 
831     if (!quiet)
832     {
833         mp4config.verbose.header = 1;
834         mp4config.verbose.tags = 1;
835     }
836     if (mp4read_open(mp4file))
837     {
838         /* unable to open file */
839         faad_fprintf(stderr, "Error opening file: %s\n", mp4file);
840         return 1;
841     }
842 
843     hDecoder = NeAACDecOpen();
844 
845     /* Set configuration */
846     config = NeAACDecGetCurrentConfiguration(hDecoder);
847     config->outputFormat = outputFormat;
848     config->downMatrix = downMatrix;
849     //config->dontUpSampleImplicitSBR = 1;
850     NeAACDecSetConfiguration(hDecoder, config);
851 
852     if (adts_out)
853     {
854         adtsFile = faad_fopen(adts_fn, "wb");
855         if (adtsFile == NULL)
856         {
857             faad_fprintf(stderr, "Error opening file: %s\n", adts_fn);
858             return 1;
859         }
860     }
861 
862     if(NeAACDecInit2(hDecoder, mp4config.asc.buf, mp4config.asc.size,
863                     &samplerate, &channels) < 0)
864     {
865         /* If some error initializing occured, skip the file */
866         faad_fprintf(stderr, "Error initializing decoder library.\n");
867         NeAACDecClose(hDecoder);
868         mp4read_close();
869         return 1;
870     }
871 
872     framesize = 1024;
873     useAacLength = 0;
874     decoded = 0;
875 
876     if (mp4config.asc.size)
877     {
878         if (NeAACDecAudioSpecificConfig(mp4config.asc.buf, mp4config.asc.size, &mp4ASC) >= 0)
879         {
880             if (mp4ASC.frameLengthFlag == 1) framesize = 960;
881             if (mp4ASC.sbr_present_flag == 1 || mp4ASC.forceUpSampling) framesize *= 2;
882         }
883     }
884 
885     /* print some mp4 file info */
886     faad_fprintf(stderr, "%s file info:\n\n", mp4file);
887     {
888         char *tag = NULL, *item = NULL;
889         /*int k, j;*/
890         char *ot[6] = { "NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC" };
891         float seconds;
892         seconds = (float)mp4config.samples/(float)mp4ASC.samplingFrequency;
893 
894         *song_length = seconds;
895 
896         faad_fprintf(stderr, "%s\t%.3f secs, %d ch, %d Hz\n\n", ot[(mp4ASC.objectTypeIndex > 5)?0:mp4ASC.objectTypeIndex],
897             seconds, mp4ASC.channelsConfiguration, mp4ASC.samplingFrequency);
898     }
899 
900     if (infoOnly)
901     {
902         NeAACDecClose(hDecoder);
903         mp4read_close();
904         return 0;
905     }
906 
907     startSampleId = 0;
908     if (seek_to > 0.1)
909         startSampleId = (int64_t)(seek_to * mp4config.samplerate / framesize);
910 
911     mp4read_seek(startSampleId);
912     for (sampleId = startSampleId; sampleId < mp4config.frame.ents; sampleId++)
913     {
914         /*int rc;*/
915         long dur;
916         unsigned int sample_count;
917         unsigned int delay = 0;
918 
919         if (mp4read_frame())
920             break;
921 
922         sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, mp4config.bitbuf.data, mp4config.bitbuf.size);
923 
924         if (!sample_buffer) {
925             /* unable to decode file, abort */
926             break;
927         }
928 
929         if (adts_out == 1)
930         {
931             adtsData = MakeAdtsHeader(&adtsDataSize, &frameInfo, 0);
932 
933             /* write the adts header */
934             fwrite(adtsData, 1, adtsDataSize, adtsFile);
935 
936             fwrite(mp4config.bitbuf.data, 1, frameInfo.bytesconsumed, adtsFile);
937         }
938 
939         dur = frameInfo.samples / frameInfo.channels;
940         decoded += dur;
941 
942         if (decoded > mp4config.samples)
943             dur += mp4config.samples - decoded;
944 
945         if (dur > framesize)
946         {
947             faad_fprintf(stderr, "Warning: excess frame detected in MP4 file.\n");
948             dur = framesize;
949         }
950 
951         if (!noGapless)
952         {
953             if (useAacLength || (mp4config.samplerate != samplerate)) {
954                 sample_count = frameInfo.samples;
955             } else {
956                 sample_count = (unsigned int)(dur * frameInfo.channels);
957                 if (sample_count > frameInfo.samples)
958                     sample_count = frameInfo.samples;
959             }
960         } else {
961             sample_count = frameInfo.samples;
962         }
963 
964         /* open the sound file now that the number of channels are known */
965         if (first_time && !frameInfo.error)
966         {
967             /* print some channel info */
968             print_channel_info(&frameInfo);
969 
970             if (!adts_out)
971             {
972                 /* open output file */
973                 if(!to_stdout)
974                 {
975                     aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
976                         outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
977                 } else {
978 #ifdef _WIN32
979                     _setmode(_fileno(stdout), O_BINARY);
980 #endif
981                     aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
982                         outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
983                 }
984                 if (aufile == NULL)
985                 {
986                     NeAACDecClose(hDecoder);
987                     mp4read_close();
988                     return 0;
989                 }
990             }
991             first_time = 0;
992         }
993 
994         percent = min((int)(sampleId*100)/mp4config.frame.ents, 100);
995         if (percent > old_percent)
996         {
997             old_percent = percent;
998             snprintf(percents, MAX_PERCENTS, "%d%% decoding %s.", percent, mp4file);
999             faad_fprintf(stderr, "%s\r", percents);
1000 #ifdef _WIN32
1001             SetConsoleTitle(percents);
1002 #endif
1003         }
1004 
1005         if ((frameInfo.error == 0) && (sample_count > 0) && (!adts_out))
1006         {
1007             if (write_audio_file(aufile, sample_buffer, sample_count, delay) == 0)
1008                 break;
1009         }
1010 
1011         if (frameInfo.error > 0)
1012         {
1013             faad_fprintf(stderr, "Warning: %s\n",
1014                 NeAACDecGetErrorMessage(frameInfo.error));
1015         }
1016     }
1017 
1018     NeAACDecClose(hDecoder);
1019 
1020     if (adts_out == 1)
1021     {
1022         fclose(adtsFile);
1023     }
1024 
1025     mp4read_close();
1026 
1027     if (!first_time && !adts_out)
1028         close_audio_file(aufile);
1029 
1030     return frameInfo.error;
1031 }
1032 
faad_main(int argc,char * argv[])1033 static int faad_main(int argc, char *argv[])
1034 {
1035     int result;
1036     int infoOnly = 0;
1037     int writeToStdio = 0;
1038     int readFromStdin = 0;
1039     int object_type = LC;
1040     int def_srate = 0;
1041     int downMatrix = 0;
1042     int format = 1;
1043     int outputFormat = FAAD_FMT_16BIT;
1044     int outfile_set = 0;
1045     int adts_out = 0;
1046     int old_format = 0;
1047     int showHelp = 0;
1048     int mp4file = 0;
1049     int noGapless = 0;
1050     char *fnp;
1051     char *aacFileName = NULL;
1052     char *audioFileName = NULL;
1053     char *adtsFileName = NULL;
1054     float seekTo = 0;
1055     unsigned char header[8];
1056     int bread;
1057     float length = 0;
1058     FILE *hMP4File;
1059     char *faad_id_string;
1060     char *faad_copyright_string;
1061 
1062 /* System dependant types */
1063 #ifdef _WIN32
1064     long begin;
1065 #else
1066     clock_t begin;
1067 #endif
1068 
1069     unsigned long cap = NeAACDecGetCapabilities();
1070 
1071 
1072     /* begin process command line */
1073     progName = argv[0];
1074     while (1) {
1075         int c = -1;
1076         int option_index = 0;
1077         static struct option long_options[] = {
1078             { "quiet",      0, 0, 'q' },
1079             { "outfile",    0, 0, 'o' },
1080             { "adtsout",    0, 0, 'a' },
1081             { "oldformat",  0, 0, 't' },
1082             { "format",     0, 0, 'f' },
1083             { "bits",       0, 0, 'b' },
1084             { "samplerate", 0, 0, 's' },
1085             { "objecttype", 0, 0, 'l' },
1086             { "downmix",    0, 0, 'd' },
1087             { "info",       0, 0, 'i' },
1088             { "stdio",      0, 0, 'w' },
1089             { "stdio",      0, 0, 'g' },
1090             { "seek",       1, 0, 'j' },
1091             { "help",       0, 0, 'h' },
1092             { 0, 0, 0, 0 }
1093         };
1094 
1095         c = getopt_long(argc, argv, "o:a:s:f:b:l:j:wgdhitq",
1096             long_options, &option_index);
1097 
1098         if (c == -1)
1099             break;
1100 
1101         switch (c) {
1102         case 'o':
1103             if (optarg)
1104             {
1105                 outfile_set = 1;
1106                 audioFileName = (char *) malloc(sizeof(char) * (strlen(optarg) + 1));
1107                 if (audioFileName == NULL)
1108                 {
1109                     faad_fprintf(stderr, "Error allocating memory for audioFileName.\n");
1110                     return 1;
1111                 }
1112                 strcpy(audioFileName, optarg);
1113             }
1114             break;
1115         case 'a':
1116             if (optarg)
1117             {
1118                 adts_out = 1;
1119                 adtsFileName = (char *) malloc(sizeof(char) * (strlen(optarg) + 1));
1120                 if (adtsFileName == NULL)
1121                 {
1122                     faad_fprintf(stderr, "Error allocating memory for adtsFileName.\n");
1123                     return 1;
1124                 }
1125                 strcpy(adtsFileName, optarg);
1126             }
1127             break;
1128         case 's':
1129             if (optarg)
1130             {
1131                 char dr[10];
1132                 if (sscanf(optarg, "%s", dr) < 1) {
1133                     def_srate = 0;
1134                 } else {
1135                     def_srate = atoi(dr);
1136                 }
1137             }
1138             break;
1139         case 'f':
1140             if (optarg)
1141             {
1142                 char dr[10];
1143                 if (sscanf(optarg, "%s", dr) < 1)
1144                 {
1145                     format = 1;
1146                 } else {
1147                     format = atoi(dr);
1148                     if ((format < 1) || (format > 2))
1149                         showHelp = 1;
1150                 }
1151             }
1152             break;
1153         case 'b':
1154             if (optarg)
1155             {
1156                 char dr[10];
1157                 if (sscanf(optarg, "%s", dr) < 1)
1158                 {
1159                     outputFormat = FAAD_FMT_16BIT; /* just use default */
1160                 } else {
1161                     outputFormat = atoi(dr);
1162                     if ((outputFormat < 1) || (outputFormat > 5))
1163                         showHelp = 1;
1164                 }
1165             }
1166             break;
1167         case 'l':
1168             if (optarg)
1169             {
1170                 char dr[10];
1171                 if (sscanf(optarg, "%s", dr) < 1)
1172                 {
1173                     object_type = LC; /* default */
1174                 } else {
1175                     object_type = atoi(dr);
1176                     if ((object_type != LC) &&
1177                         (object_type != MAIN) &&
1178                         (object_type != LTP) &&
1179                         (object_type != LD))
1180                     {
1181                         showHelp = 1;
1182                     }
1183                 }
1184             }
1185             break;
1186         case 'j':
1187             if (optarg)
1188             {
1189                 seekTo = atof(optarg);
1190             }
1191             break;
1192         case 't':
1193             old_format = 1;
1194             break;
1195         case 'd':
1196             downMatrix = 1;
1197             break;
1198         case 'w':
1199             writeToStdio = 1;
1200             break;
1201         case 'g':
1202             noGapless = 1;
1203             break;
1204         case 'i':
1205             infoOnly = 1;
1206             break;
1207         case 'h':
1208             showHelp = 1;
1209             break;
1210         case 'q':
1211             quiet = 1;
1212             break;
1213         default:
1214             break;
1215         }
1216     }
1217 
1218     NeAACDecGetVersion(&faad_id_string, &faad_copyright_string);
1219 
1220     faad_fprintf(stderr, " *********** Ahead Software MPEG-4 AAC Decoder V%s ******************\n\n", faad_id_string);
1221 #ifndef BUILD_DATE
1222 #define BUILD_DATE __DATE__
1223 #endif
1224     faad_fprintf(stderr, " Build: %s\n", BUILD_DATE);
1225 #undef BUILD_DATE
1226     faad_fprintf(stderr, "%s", faad_copyright_string);
1227     if (cap & FIXED_POINT_CAP)
1228         faad_fprintf(stderr, " Fixed point version\n");
1229     else
1230         faad_fprintf(stderr, " Floating point version\n");
1231     faad_fprintf(stderr, "\n");
1232     faad_fprintf(stderr, " This program is free software; you can redistribute it and/or modify\n");
1233     faad_fprintf(stderr, " it under the terms of the GNU General Public License.\n");
1234     faad_fprintf(stderr, "\n");
1235     faad_fprintf(stderr, " **************************************************************************\n\n");
1236 
1237 
1238     /* check that we have at least two non-option arguments */
1239     /* Print help if requested */
1240     if (((argc - optind) < 1) || showHelp)
1241     {
1242         usage();
1243         return 1;
1244     }
1245 
1246 #if 0
1247     /* only allow raw data on stdio */
1248     if (writeToStdio == 1)
1249     {
1250         format = 2;
1251     }
1252 #endif
1253 
1254     /* point to the specified file name */
1255     aacFileName = (char *) malloc(sizeof(char) * (strlen(argv[optind]) + 1));
1256     if (aacFileName == NULL)
1257     {
1258         faad_fprintf(stderr, "Error allocating memory for aacFileName.\n");
1259         return 1;
1260     }
1261     strcpy(aacFileName, argv[optind]);
1262 
1263 #ifdef _WIN32
1264     begin = GetTickCount();
1265 #else
1266     begin = clock();
1267 #endif
1268 
1269     /* Only calculate the path and open the file for writing if
1270        we are not writing to stdout.
1271      */
1272     if(!writeToStdio && !outfile_set)
1273     {
1274         audioFileName = (char *) malloc(sizeof(char) * (strlen(aacFileName) + strlen(file_ext[format]) + 1));
1275         if (audioFileName == NULL)
1276         {
1277             faad_fprintf(stderr, "Error allocating memory for audioFileName.\n");
1278             return 1;
1279         }
1280         strcpy(audioFileName, aacFileName);
1281 
1282         fnp = (char *)strrchr(audioFileName,'.');
1283 
1284         if (fnp)
1285             fnp[0] = '\0';
1286 
1287         strcat(audioFileName, file_ext[format]);
1288     }
1289 
1290     /* check for mp4 file */
1291     if (0 == strcmp(aacFileName, "-")) {
1292         faad_fprintf(stderr, "Reading from stdin: %s\n", aacFileName);
1293         readFromStdin = 1;
1294         hMP4File  = stdin;
1295 #ifdef _WIN32
1296         _setmode(_fileno(stdin), O_BINARY);
1297 #endif
1298 
1299     } else {
1300 
1301         mp4file = 0;
1302         hMP4File = faad_fopen(aacFileName, "rb");
1303         if (!hMP4File)
1304         {
1305             faad_fprintf(stderr, "Error opening file: %s\n", aacFileName);
1306             return 1;
1307         }
1308     }
1309 
1310     bread = fread(header, 1, 8, hMP4File);
1311 
1312     if (! readFromStdin )
1313       fclose(hMP4File);
1314 
1315     if (bread != 8) {
1316         faad_fprintf(stderr, "Error reading file.\n");
1317         return 1;
1318     }
1319 
1320     if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
1321         mp4file = 1;
1322 
1323     if (!mp4file && seekTo != 0) {
1324         faad_fprintf(stderr, "Warning: can only seek in MP4 files\n");
1325     }
1326 
1327     if (mp4file)
1328     {
1329         result = decodeMP4file(aacFileName, audioFileName, adtsFileName, writeToStdio,
1330             outputFormat, format, downMatrix, noGapless, infoOnly, adts_out, &length, seekTo);
1331     } else {
1332 
1333     if (readFromStdin == 1) {
1334         ungetc(header[7],hMP4File);
1335         ungetc(header[6],hMP4File);
1336         ungetc(header[5],hMP4File);
1337         ungetc(header[4],hMP4File);
1338         ungetc(header[3],hMP4File);
1339         ungetc(header[2],hMP4File);
1340         ungetc(header[1],hMP4File);
1341         ungetc(header[0],hMP4File);
1342     }
1343 
1344         result = decodeAACfile(aacFileName, audioFileName, adtsFileName, writeToStdio,
1345             def_srate, object_type, outputFormat, format, downMatrix, infoOnly, adts_out,
1346             old_format, &length);
1347     }
1348 
1349     if (audioFileName != NULL)
1350       free (audioFileName);
1351     if (adtsFileName != NULL)
1352       free (adtsFileName);
1353 
1354     if (!result && !infoOnly)
1355     {
1356 #ifdef _WIN32
1357         float dec_length = (float)(GetTickCount()-begin)/1000.0;
1358         SetConsoleTitle("FAAD");
1359 #else
1360         /* clock() grabs time since the start of the app but when we decode
1361            multiple files, each file has its own starttime (begin).
1362          */
1363         float dec_length = (float)(clock() - begin)/(float)CLOCKS_PER_SEC;
1364 #endif
1365         faad_fprintf(stderr, "Decoding %s took: %5.2f sec. %5.2fx real-time.\n", aacFileName,
1366             dec_length, (dec_length > 0.01) ? (length/dec_length) : 0.);
1367     }
1368 
1369     if (aacFileName != NULL)
1370       free (aacFileName);
1371 
1372     return 0;
1373 }
1374 
main(int argc,char * argv[])1375 int main(int argc, char *argv[])
1376 {
1377 #if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
1378     int argc_utf8, exit_code;
1379     char **argv_utf8;
1380     init_console_utf8(stderr);
1381     init_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
1382     exit_code = faad_main(argc_utf8, argv_utf8);
1383     free_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
1384     uninit_console_utf8();
1385     return exit_code;
1386 #else
1387     return faad_main(argc, argv);
1388 #endif
1389 }
1390