2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
12 # include <inttypes.h>
13 #elif defined(_MSC_VER)
14 # define SCNd64 "I64d"
32 #define WIN32_LEAN_AND_MEAN
36 #include "wav_reader.h"
37 #include "caf_reader.h"
44 #define PROGNAME "fdkaac"
46 static volatile int g_interrupted
= 0;
49 static void signal_handler(int signum
)
53 static void handle_signals(void)
55 int i
, sigs
[] = { SIGINT
, SIGHUP
, SIGTERM
};
56 for (i
= 0; i
< sizeof(sigs
)/sizeof(sigs
[0]); ++i
) {
58 memset(&sa
, 0, sizeof sa
);
59 sa
.sa_handler
= signal_handler
;
60 sa
.sa_flags
|= SA_RESTART
;
61 sigaction(sigs
[i
], &sa
, 0);
65 static BOOL WINAPI
signal_handler(DWORD type
)
71 static void handle_signals(void)
73 SetConsoleCtrlHandler(signal_handler
, TRUE
);
76 static void handle_signals(void)
82 int read_callback(void *cookie
, void *data
, uint32_t size
)
84 size_t rc
= fread(data
, 1, size
, (FILE*)cookie
);
85 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
89 int write_callback(void *cookie
, const void *data
, uint32_t size
)
91 size_t rc
= fwrite(data
, 1, size
, (FILE*)cookie
);
92 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
96 int seek_callback(void *cookie
, int64_t off
, int whence
)
98 return fseeko((FILE*)cookie
, off
, whence
);
102 int64_t tell_callback(void *cookie
)
104 return ftello((FILE*)cookie
);
112 "Usage: " PROGNAME
" [options] input_file\n"
114 " -h, --help Print this help message\n"
115 " -p, --profile <n> Profile (audio object type)\n"
116 " 2: MPEG-4 AAC LC (default)\n"
117 " 5: MPEG-4 HE-AAC (SBR)\n"
118 " 29: MPEG-4 HE-AAC v2 (SBR+PS)\n"
119 " 23: MPEG-4 AAC LD\n"
120 " 39: MPEG-4 AAC ELD\n"
121 " 129: MPEG-2 AAC LC\n"
122 " 132: MPEG-2 HE-AAC (SBR)\n"
123 " 156: MPEG-2 HE-AAC v2 (SBR+PS)\n"
124 " -b, --bitrate <n> Bitrate in bits per seconds (for CBR)\n"
125 " -m, --bitrate-mode <n> Bitrate configuration\n"
126 " 0: CBR (default)\n"
128 " (VBR mode is not officially supported, and\n"
129 " works only on a certain combination of\n"
130 " parameter settings, sample rate, and\n"
131 " channel configuration)\n"
132 " -w, --bandwidth <n> Frequency bandwidth in Hz (AAC LC only)\n"
133 " -a, --afterburner <n> Afterburner\n"
136 " -L, --lowdelay-sbr <-1|0|1> Configure SBR activity on AAC ELD\n"
137 " -1: Use ELD SBR auto configurator\n"
138 " 0: Disable SBR on ELD (default)\n"
139 " 1: Enable SBR on ELD\n"
140 " -s, --sbr-ratio <0|1|2> Controls activation of downsampled SBR\n"
141 " 0: Use lib default (default)\n"
142 " 1: downsampled SBR (default for ELD+SBR)\n"
143 " 2: dual-rate SBR (default for HE-AAC)\n"
144 " -f, --transport-format <n> Transport format\n"
145 " 0: RAW (default, muxed into M4A)\n"
150 " 10: LOAS/LATM (LATM within LOAS)\n"
151 " -C, --adts-crc-check Add CRC protection on ADTS header\n"
152 " -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
155 " -o <filename> Output filename\n"
156 " -G, --gapless-mode <n> Encoder delay signaling for gapless playback\n"
157 " 0: iTunSMPB (default)\n"
158 " 1: ISO standard (edts + sgpd)\n"
160 " --include-sbr-delay Count SBR decoder delay in encoder delay\n"
161 " This is not iTunes compatible, but is default\n"
162 " behavior of FDK library.\n"
163 " -I, --ignorelength Ignore length of WAV header\n"
164 " -S, --silent Don't print progress messages\n"
165 " --moov-before-mdat Place moov box before mdat box on m4a output\n"
167 "Options for raw (headerless) input:\n"
168 " -R, --raw Treat input as raw (by default WAV is\n"
170 " --raw-channels <n> Number of channels (default: 2)\n"
171 " --raw-rate <n> Sample rate (default: 44100)\n"
172 " --raw-format <spec> Sample format, default is \"S16L\".\n"
173 " Spec is as follows:\n"
174 " 1st char: S(igned)|U(nsigned)|F(loat)\n"
175 " 2nd part: bits per channel\n"
176 " Last char: L(ittle)|B(ig)\n"
177 " Last char can be omitted, in which case L is\n"
178 " assumed. Spec is case insensitive, therefore\n"
179 " \"u16b\" is same as \"U16B\".\n"
182 " --title <string>\n"
183 " --artist <string>\n"
184 " --album <string>\n"
185 " --genre <string>\n"
187 " --composer <string>\n"
188 " --grouping <string>\n"
189 " --comment <string>\n"
190 " --album-artist <string>\n"
191 " --track <number[/total]>\n"
192 " --disk <number[/total]>\n"
194 " --tag <fcc>:<value> Set iTunes predefined tag with four char code.\n"
195 " --tag-from-file <fcc>:<filename>\n"
196 " Same as above, but value is read from file.\n"
197 " --long-tag <name>:<value> Set arbitrary tag as iTunes custom metadata.\n"
198 " --tag-from-json <filename[?dot_notation]>\n"
199 " Read tags from JSON. By default, tags are\n"
200 " assumed to be direct children of the root\n"
201 " object(dictionary).\n"
202 " Optionally, position of the dictionary\n"
203 " that contains tags can be specified with\n"
204 " dotted notation.\n"
206 " --tag-from-json /path/to/json?format.tags\n"
210 typedef struct aacenc_param_ex_t
{
213 char *input_filename
;
215 char *output_filename
;
217 unsigned gapless_mode
;
218 unsigned include_sbr_delay
;
219 unsigned ignore_length
;
221 int moov_before_mdat
;
224 unsigned raw_channels
;
226 const char *raw_format
;
228 aacenc_tag_store_t tags
;
229 aacenc_tag_store_t source_tags
;
230 aacenc_translate_generic_text_tag_ctx_t source_tag_ctx
;
236 int parse_options(int argc
, char **argv
, aacenc_param_ex_t
*params
)
241 #define OPT_INCLUDE_SBR_DELAY M4AF_FOURCC('s','d','l','y')
242 #define OPT_MOOV_BEFORE_MDAT M4AF_FOURCC('m','o','o','v')
243 #define OPT_RAW_CHANNELS M4AF_FOURCC('r','c','h','n')
244 #define OPT_RAW_RATE M4AF_FOURCC('r','r','a','t')
245 #define OPT_RAW_FORMAT M4AF_FOURCC('r','f','m','t')
246 #define OPT_SHORT_TAG M4AF_FOURCC('s','t','a','g')
247 #define OPT_SHORT_TAG_FILE M4AF_FOURCC('s','t','g','f')
248 #define OPT_LONG_TAG M4AF_FOURCC('l','t','a','g')
249 #define OPT_TAG_FROM_JSON M4AF_FOURCC('t','f','j','s')
251 static struct option long_options
[] = {
252 { "help", no_argument
, 0, 'h' },
253 { "profile", required_argument
, 0, 'p' },
254 { "bitrate", required_argument
, 0, 'b' },
255 { "bitrate-mode", required_argument
, 0, 'm' },
256 { "bandwidth", required_argument
, 0, 'w' },
257 { "afterburner", required_argument
, 0, 'a' },
258 { "lowdelay-sbr", required_argument
, 0, 'L' },
259 { "sbr-ratio", required_argument
, 0, 's' },
260 { "transport-format", required_argument
, 0, 'f' },
261 { "adts-crc-check", no_argument
, 0, 'C' },
262 { "header-period", required_argument
, 0, 'P' },
264 { "gapless-mode", required_argument
, 0, 'G' },
265 { "include-sbr-delay", no_argument
, 0, OPT_INCLUDE_SBR_DELAY
},
266 { "ignorelength", no_argument
, 0, 'I' },
267 { "silent", no_argument
, 0, 'S' },
268 { "moov-before-mdat", no_argument
, 0, OPT_MOOV_BEFORE_MDAT
},
270 { "raw", no_argument
, 0, 'R' },
271 { "raw-channels", required_argument
, 0, OPT_RAW_CHANNELS
},
272 { "raw-rate", required_argument
, 0, OPT_RAW_RATE
},
273 { "raw-format", required_argument
, 0, OPT_RAW_FORMAT
},
275 { "title", required_argument
, 0, M4AF_TAG_TITLE
},
276 { "artist", required_argument
, 0, M4AF_TAG_ARTIST
},
277 { "album", required_argument
, 0, M4AF_TAG_ALBUM
},
278 { "genre", required_argument
, 0, M4AF_TAG_GENRE
},
279 { "date", required_argument
, 0, M4AF_TAG_DATE
},
280 { "composer", required_argument
, 0, M4AF_TAG_COMPOSER
},
281 { "grouping", required_argument
, 0, M4AF_TAG_GROUPING
},
282 { "comment", required_argument
, 0, M4AF_TAG_COMMENT
},
283 { "album-artist", required_argument
, 0, M4AF_TAG_ALBUM_ARTIST
},
284 { "track", required_argument
, 0, M4AF_TAG_TRACK
},
285 { "disk", required_argument
, 0, M4AF_TAG_DISK
},
286 { "tempo", required_argument
, 0, M4AF_TAG_TEMPO
},
287 { "tag", required_argument
, 0, OPT_SHORT_TAG
},
288 { "tag-from-file", required_argument
, 0, OPT_SHORT_TAG_FILE
},
289 { "long-tag", required_argument
, 0, OPT_LONG_TAG
},
290 { "tag-from-json", required_argument
, 0, OPT_TAG_FROM_JSON
},
293 params
->afterburner
= 1;
295 aacenc_getmainargs(&argc
, &argv
);
296 while ((ch
= getopt_long(argc
, argv
, "hp:b:m:w:a:Ls:f:CP:G:Io:SR",
297 long_options
, 0)) != EOF
) {
302 if (sscanf(optarg
, "%u", &n
) != 1) {
303 fprintf(stderr
, "invalid arg for profile\n");
309 if (sscanf(optarg
, "%u", &n
) != 1) {
310 fprintf(stderr
, "invalid arg for bitrate\n");
316 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 5) {
317 fprintf(stderr
, "invalid arg for bitrate-mode\n");
320 params
->bitrate_mode
= n
;
323 if (sscanf(optarg
, "%u", &n
) != 1) {
324 fprintf(stderr
, "invalid arg for bandwidth\n");
327 params
->bandwidth
= n
;
330 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 1) {
331 fprintf(stderr
, "invalid arg for afterburner\n");
334 params
->afterburner
= n
;
337 if (sscanf(optarg
, "%d", &n
) != 1 || n
< -1 || n
> 1) {
338 fprintf(stderr
, "invalid arg for lowdelay-sbr\n");
341 params
->lowdelay_sbr
= n
;
344 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 2) {
345 fprintf(stderr
, "invalid arg for sbr-ratio\n");
348 params
->sbr_ratio
= n
;
351 if (sscanf(optarg
, "%u", &n
) != 1) {
352 fprintf(stderr
, "invalid arg for transport-format\n");
355 params
->transport_format
= n
;
358 params
->adts_crc_check
= 1;
361 if (sscanf(optarg
, "%u", &n
) != 1) {
362 fprintf(stderr
, "invalid arg for header-period\n");
365 params
->header_period
= n
;
368 params
->output_filename
= optarg
;
371 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 2) {
372 fprintf(stderr
, "invalid arg for gapless-mode\n");
375 params
->gapless_mode
= n
;
377 case OPT_INCLUDE_SBR_DELAY
:
378 params
->include_sbr_delay
= 1;
381 params
->ignore_length
= 1;
386 case OPT_MOOV_BEFORE_MDAT
:
387 params
->moov_before_mdat
= 1;
392 case OPT_RAW_CHANNELS
:
393 if (sscanf(optarg
, "%u", &n
) != 1) {
394 fprintf(stderr
, "invalid arg for raw-channels\n");
397 params
->raw_channels
= n
;
400 if (sscanf(optarg
, "%u", &n
) != 1) {
401 fprintf(stderr
, "invalid arg for raw-rate\n");
404 params
->raw_rate
= n
;
407 params
->raw_format
= optarg
;
410 case M4AF_TAG_ARTIST
:
414 case M4AF_TAG_COMPOSER
:
415 case M4AF_TAG_GROUPING
:
416 case M4AF_TAG_COMMENT
:
417 case M4AF_TAG_ALBUM_ARTIST
:
421 aacenc_add_tag_to_store(¶ms
->tags
, ch
, 0, optarg
,
425 case OPT_SHORT_TAG_FILE
:
430 unsigned fcc
= M4AF_FOURCC('-','-','-','-');
432 if ((val
= strchr(optarg
, ':')) == 0) {
433 fprintf(stderr
, "invalid arg for tag\n");
437 if (ch
== OPT_SHORT_TAG
|| ch
== OPT_SHORT_TAG_FILE
) {
439 * take care of U+00A9(COPYRIGHT SIGN).
440 * 1) if length of fcc is 3, we prepend '\xa9'.
441 * 2) U+00A9 becomes "\xc2\xa9" in UTF-8. Therefore
442 * we remove first '\xc2'.
444 if (optarg
[0] == '\xc2')
446 if ((klen
= strlen(optarg
))== 3)
448 else if (klen
!= 4) {
449 fprintf(stderr
, "invalid arg for tag\n");
452 for (; *optarg
; ++optarg
)
453 fcc
= ((fcc
<< 8) | (*optarg
& 0xff));
455 aacenc_add_tag_to_store(¶ms
->tags
, fcc
, optarg
,
457 ch
== OPT_SHORT_TAG_FILE
);
460 case OPT_TAG_FROM_JSON
:
461 params
->json_filename
= optarg
;
470 if (!params
->bitrate
&& !params
->bitrate_mode
) {
471 fprintf(stderr
, "bitrate or bitrate-mode is mandatory\n");
474 if (params
->output_filename
&& !strcmp(params
->output_filename
, "-") &&
475 !params
->transport_format
) {
476 fprintf(stderr
, "stdout streaming is not available on M4A output\n");
479 if (params
->bitrate
&& params
->bitrate
< 10000)
480 params
->bitrate
*= 1000;
482 if (params
->is_raw
) {
483 if (!params
->raw_channels
)
484 params
->raw_channels
= 2;
485 if (!params
->raw_rate
)
486 params
->raw_rate
= 44100;
487 if (!params
->raw_format
)
488 params
->raw_format
= "S16L";
490 params
->input_filename
= argv
[optind
];
495 int write_sample(FILE *ofp
, m4af_ctx_t
*m4af
, aacenc_frame_t
*frame
)
498 fwrite(frame
->data
, 1, frame
->size
, ofp
);
500 fprintf(stderr
, "ERROR: fwrite(): %s\n", strerror(errno
));
503 } else if (m4af_write_sample(m4af
, 0, frame
->data
, frame
->size
, 0) < 0) {
504 fprintf(stderr
, "ERROR: failed to write m4a sample\n");
511 int encode(aacenc_param_ex_t
*params
, pcm_reader_t
*reader
,
512 HANDLE_AACENCODER encoder
, uint32_t frame_length
,
515 int16_t *ibuf
= 0, *ip
;
516 aacenc_frame_t obuf
[2] = {{ 0 }}, *obp
;
520 int remaining
, consumed
;
521 int frames_written
= 0, encoded
= 0;
522 aacenc_progress_t progress
= { 0 };
523 const pcm_sample_description_t
*fmt
= pcm_get_format(reader
);
525 ibuf
= malloc(frame_length
* fmt
->bytes_per_frame
);
526 aacenc_progress_init(&progress
, pcm_get_length(reader
), fmt
->sample_rate
);
530 * Since we delay the write, we cannot just exit loop when interrupted.
531 * Instead, we regard it as EOF.
536 if ((nread
= pcm_read_frames(reader
, ibuf
, frame_length
)) < 0) {
537 fprintf(stderr
, "ERROR: read failed\n");
541 aacenc_progress_update(&progress
, pcm_get_position(reader
),
542 fmt
->sample_rate
* 2);
548 consumed
= aac_encode_frame(encoder
, fmt
, ip
, remaining
, obp
);
549 if (consumed
< 0) goto END
;
550 if (consumed
== 0 && obp
->size
== 0) goto DONE
;
551 if (obp
->size
== 0) break;
553 remaining
-= consumed
;
554 ip
+= consumed
* fmt
->channels_per_frame
;
557 * As we pad 1 frame at beginning and ending by our extrapolator,
558 * we want to drop them.
559 * We delay output by 1 frame by double buffering, and discard
560 * second frame and final frame from the encoder.
561 * Since sbr_header is included in the first frame (in case of
562 * SBR), we cannot discard first frame. So we pick second instead.
565 if (encoded
== 1 || encoded
== 3)
568 if (write_sample(params
->output_fp
, m4af
, obp
) < 0)
571 } while (remaining
> 0);
575 aacenc_progress_finish(&progress
, pcm_get_position(reader
));
578 if (ibuf
) free(ibuf
);
579 if (obuf
[0].data
) free(obuf
[0].data
);
580 if (obuf
[1].data
) free(obuf
[1].data
);
585 void put_tool_tag(m4af_ctx_t
*m4af
, const aacenc_param_ex_t
*params
,
586 HANDLE_AACENCODER encoder
)
592 p
+= sprintf(p
, PROGNAME
" %s, ", fdkaac_version
);
593 aacenc_get_lib_info(&lib_info
);
594 p
+= sprintf(p
, "libfdk-aac %s, ", lib_info
.versionStr
);
595 if (params
->bitrate_mode
)
596 sprintf(p
, "VBR mode %d", params
->bitrate_mode
);
598 sprintf(p
, "CBR %dkbps",
599 aacEncoder_GetParam(encoder
, AACENC_BITRATE
) / 1000);
601 m4af_add_itmf_string_tag(m4af
, M4AF_TAG_TOOL
, tool_info
);
605 int finalize_m4a(m4af_ctx_t
*m4af
, const aacenc_param_ex_t
*params
,
606 HANDLE_AACENCODER encoder
)
609 aacenc_tag_entry_t
*tag
;
611 tag
= params
->source_tags
.tag_table
;
612 for (i
= 0; i
< params
->source_tags
.tag_count
; ++i
, ++tag
)
613 aacenc_write_tag_entry(m4af
, tag
);
615 if (params
->json_filename
)
616 aacenc_write_tags_from_json(m4af
, params
->json_filename
);
618 tag
= params
->tags
.tag_table
;
619 for (i
= 0; i
< params
->tags
.tag_count
; ++i
, ++tag
)
620 aacenc_write_tag_entry(m4af
, tag
);
622 put_tool_tag(m4af
, params
, encoder
);
624 if (m4af_finalize(m4af
, params
->moov_before_mdat
) < 0) {
625 fprintf(stderr
, "ERROR: failed to finalize m4a\n");
632 char *generate_output_filename(const char *filename
, const char *ext
)
635 size_t ext_len
= strlen(ext
);
637 if (strcmp(filename
, "-") == 0) {
638 p
= malloc(ext_len
+ 6);
639 sprintf(p
, "stdin%s", ext
);
641 const char *base
= aacenc_basename(filename
);
642 size_t ilen
= strlen(base
);
643 const char *ext_org
= strrchr(base
, '.');
644 if (ext_org
) ilen
= ext_org
- base
;
645 p
= malloc(ilen
+ ext_len
+ 1);
646 sprintf(p
, "%.*s%s", (int)ilen
, base
, ext
);
652 int parse_raw_spec(const char *spec
, pcm_sample_description_t
*desc
)
655 unsigned char c_type
, c_endian
= 'L';
658 if (sscanf(spec
, "%c%u%c", &c_type
, &bits
, &c_endian
) < 2)
660 c_type
= toupper(c_type
);
661 c_endian
= toupper(c_endian
);
665 else if (c_type
== 'U')
667 else if (c_type
== 'F')
674 else if (c_endian
!= 'L')
677 if (c_type
== 'F' && bits
!= 32 && bits
!= 64)
679 if (c_type
!= 'F' && (bits
< 8 || bits
> 32))
682 desc
->sample_type
= type
;
683 desc
->bits_per_channel
= bits
;
687 static pcm_io_vtbl_t pcm_io_vtbl
= {
688 read_callback
, seek_callback
, tell_callback
690 static pcm_io_vtbl_t pcm_io_vtbl_noseek
= { read_callback
, 0, tell_callback
};
693 pcm_reader_t
*open_input(aacenc_param_ex_t
*params
)
695 pcm_io_context_t io
= { 0 };
696 pcm_reader_t
*reader
= 0;
697 struct stat stb
= { 0 };
699 if ((params
->input_fp
= aacenc_fopen(params
->input_filename
, "rb")) == 0) {
700 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
->input_filename
,
704 io
.cookie
= params
->input_fp
;
705 if (fstat(fileno(params
->input_fp
), &stb
) == 0
706 && (stb
.st_mode
& S_IFMT
) == S_IFREG
)
707 io
.vtbl
= &pcm_io_vtbl
;
709 io
.vtbl
= &pcm_io_vtbl_noseek
;
711 if (params
->is_raw
) {
712 int bytes_per_channel
;
713 pcm_sample_description_t desc
= { 0 };
714 if (parse_raw_spec(params
->raw_format
, &desc
) < 0) {
715 fprintf(stderr
, "ERROR: invalid raw-format spec\n");
718 desc
.sample_rate
= params
->raw_rate
;
719 desc
.channels_per_frame
= params
->raw_channels
;
720 bytes_per_channel
= (desc
.bits_per_channel
+ 7) / 8;
721 desc
.bytes_per_frame
= params
->raw_channels
* bytes_per_channel
;
722 if ((reader
= raw_open(&io
, &desc
)) == 0) {
723 fprintf(stderr
, "ERROR: failed to open raw input\n");
728 ungetc(c
= getc(params
->input_fp
), params
->input_fp
);
732 if ((reader
= wav_open(&io
, params
->ignore_length
)) == 0) {
733 fprintf(stderr
, "ERROR: broken / unsupported input file\n");
738 params
->source_tag_ctx
.add
= aacenc_add_tag_entry_to_store
;
739 params
->source_tag_ctx
.add_ctx
= ¶ms
->source_tags
;
740 if ((reader
= caf_open(&io
,
741 aacenc_translate_generic_text_tag
,
742 ¶ms
->source_tag_ctx
)) == 0) {
743 fprintf(stderr
, "ERROR: broken / unsupported input file\n");
748 fprintf(stderr
, "ERROR: unsupported input file\n");
752 if ((reader
= pcm_open_sint16_converter(reader
)) != 0)
753 reader
= extrapolater_open(reader
);
759 int main(int argc
, char **argv
)
761 static m4af_io_callbacks_t m4af_io
= {
762 read_callback
, write_callback
, seek_callback
, tell_callback
764 aacenc_param_ex_t params
= { 0 };
767 char *output_filename
= 0;
768 pcm_reader_t
*reader
= 0;
769 HANDLE_AACENCODER encoder
= 0;
770 AACENC_InfoStruct aacinfo
= { 0 };
771 m4af_ctx_t
*m4af
= 0;
772 const pcm_sample_description_t
*sample_format
;
775 unsigned scale_shift
= 0;
777 setlocale(LC_CTYPE
, "");
780 if (parse_options(argc
, argv
, ¶ms
) < 0)
783 if ((reader
= open_input(¶ms
)) == 0)
786 sample_format
= pcm_get_format(reader
);
789 * We use explicit/hierarchical signaling for LOAS.
790 * Other than that, we request implicit signaling to FDK library, then
791 * append explicit/backward-compatible signaling to ASC in case of MP4FF.
793 * Explicit/backward-compatible signaling of SBR is the most recommended
794 * way in MPEG4 part3 spec, and seems the only way supported by iTunes.
795 * Since FDK library does not support it, we have to do it on our side.
797 sbr_mode
= aacenc_is_sbr_active((aacenc_param_t
*)¶ms
);
798 if (sbr_mode
&& !aacenc_is_sbr_ratio_available()) {
799 fprintf(stderr
, "WARNING: Only dual-rate SBR is available "
800 "for this version\n");
801 params
.sbr_ratio
= 2;
803 scale_shift
= aacenc_is_dual_rate_sbr((aacenc_param_t
*)¶ms
);
804 params
.sbr_signaling
= (params
.transport_format
== TT_MP4_LOAS
) ? 2 : 0;
805 if (sbr_mode
&& !scale_shift
)
806 params
.sbr_signaling
= 2;
808 if (aacenc_init(&encoder
, (aacenc_param_t
*)¶ms
, sample_format
,
812 if (!params
.output_filename
) {
813 const char *ext
= params
.transport_format
? ".aac" : ".m4a";
814 output_filename
= generate_output_filename(params
.input_filename
, ext
);
815 params
.output_filename
= output_filename
;
818 if ((params
.output_fp
= aacenc_fopen(params
.output_filename
, "wb+")) == 0) {
819 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.output_filename
,
825 if (!params
.transport_format
) {
828 uint32_t ascsize
= sizeof(mp4asc
);
829 unsigned framelen
= aacinfo
.frameLength
;
830 scale
= sample_format
->sample_rate
>> scale_shift
;
831 if ((m4af
= m4af_create(M4AF_CODEC_MP4A
, scale
, &m4af_io
,
832 params
.output_fp
)) < 0)
834 aacenc_mp4asc((aacenc_param_t
*)¶ms
, aacinfo
.confBuf
,
835 aacinfo
.confSize
, mp4asc
, &ascsize
);
836 m4af_set_decoder_specific_info(m4af
, 0, mp4asc
, ascsize
);
837 m4af_set_fixed_frame_duration(m4af
, 0,
838 framelen
>> scale_shift
);
839 m4af_set_vbr_mode(m4af
, 0, params
.bitrate_mode
);
840 m4af_set_priming_mode(m4af
, params
.gapless_mode
+ 1);
841 m4af_begin_write(m4af
);
843 if (scale_shift
&& (aacinfo
.encoderDelay
& 1)) {
845 * Since odd delay cannot be exactly expressed in downsampled scale,
846 * we push one zero frame to the encoder here, to make delay even
848 int16_t zero
[8] = { 0 };
849 aacenc_frame_t frame
= { 0 };
850 aac_encode_frame(encoder
, sample_format
, zero
, 1, &frame
);
853 frame_count
= encode(¶ms
, reader
, encoder
, aacinfo
.frameLength
, m4af
);
857 uint32_t delay
= aacinfo
.encoderDelay
;
859 int64_t frames_read
= pcm_get_position(reader
);
861 if (sbr_mode
&& params
.profile
!= AOT_ER_AAC_ELD
&&
862 !params
.include_sbr_delay
)
863 delay
-= 481 << scale_shift
;
864 if (scale_shift
&& (delay
& 1))
866 padding
= frame_count
* aacinfo
.frameLength
- frames_read
- delay
;
867 m4af_set_priming(m4af
, 0, delay
>> scale_shift
, padding
>> scale_shift
);
868 if (finalize_m4a(m4af
, ¶ms
, encoder
) < 0)
873 if (reader
) pcm_teardown(&reader
);
874 if (params
.input_fp
) fclose(params
.input_fp
);
875 if (m4af
) m4af_teardown(&m4af
);
876 if (params
.output_fp
) fclose(params
.output_fp
);
877 if (encoder
) aacEncClose(&encoder
);
878 if (output_filename
) free(output_filename
);
879 if (params
.tags
.tag_table
)
880 aacenc_free_tag_store(¶ms
.tags
);
881 if (params
.source_tags
.tag_table
)
882 aacenc_free_tag_store(¶ms
.source_tags
);