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"
43 #define PROGNAME "fdkaac"
45 static volatile int g_interrupted
= 0;
48 static void signal_handler(int signum
)
52 static void handle_signals(void)
54 int i
, sigs
[] = { SIGINT
, SIGHUP
, SIGTERM
};
55 for (i
= 0; i
< sizeof(sigs
)/sizeof(sigs
[0]); ++i
) {
56 struct sigaction sa
= { 0 };
57 sa
.sa_handler
= signal_handler
;
58 sa
.sa_flags
|= SA_RESTART
;
59 sigaction(sigs
[i
], &sa
, 0);
63 static BOOL WINAPI
signal_handler(DWORD type
)
69 static void handle_signals(void)
71 SetConsoleCtrlHandler(signal_handler
, TRUE
);
74 static void handle_signals(void)
80 int read_callback(void *cookie
, void *data
, uint32_t size
)
82 size_t rc
= fread(data
, 1, size
, (FILE*)cookie
);
83 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
87 int write_callback(void *cookie
, const void *data
, uint32_t size
)
89 size_t rc
= fwrite(data
, 1, size
, (FILE*)cookie
);
90 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
94 int seek_callback(void *cookie
, int64_t off
, int whence
)
96 return fseeko((FILE*)cookie
, off
, whence
);
100 int64_t tell_callback(void *cookie
)
102 return ftello((FILE*)cookie
);
110 "Usage: " PROGNAME
" [options] input_file\n"
112 " -h, --help Print this help message\n"
113 " -p, --profile <n> Profile (audio object type)\n"
114 " 2: MPEG-4 AAC LC (default)\n"
115 " 5: MPEG-4 HE-AAC (SBR)\n"
116 " 29: MPEG-4 HE-AAC v2 (SBR+PS)\n"
117 " 23: MPEG-4 AAC LD\n"
118 " 39: MPEG-4 AAC ELD\n"
119 " 129: MPEG-2 AAC LC\n"
120 " 132: MPEG-2 HE-AAC (SBR)\n"
121 " 156: MPEG-2 HE-AAC v2 (SBR+PS)\n"
122 " -b, --bitrate <n> Bitrate in bits per seconds (for CBR)\n"
123 " -m, --bitrate-mode <n> Bitrate configuration\n"
124 " 0: CBR (default)\n"
126 " (VBR mode is not officially supported, and\n"
127 " works only on a certain combination of\n"
128 " parameter settings, sample rate, and\n"
129 " channel configuration)\n"
130 " -w, --bandwidth <n> Frequency bandwidth in Hz (AAC LC only)\n"
131 " -a, --afterburner <n> Afterburner\n"
134 " -L, --lowdelay-sbr Enable ELD-SBR (AAC ELD only)\n"
135 " -s, --sbr-signaling <n> SBR signaling mode\n"
136 " 0: Implicit, backward compatible(default)\n"
137 " 1: Explicit SBR and implicit PS\n"
138 " 2: Explicit hierarchical signaling\n"
139 " -f, --transport-format <n> Transport format\n"
140 " 0: RAW (default, muxed into M4A)\n"
145 " 10: LOAS/LATM (LATM within LOAS)\n"
146 " -C, --adts-crc-check Add CRC protection on ADTS header\n"
147 " -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
150 " -o <filename> Output filename\n"
151 " -G, --gapless-mode <n> Encoder delay signaling for gapless playback\n"
152 " 0: iTunSMPB (default)\n"
153 " 1: ISO standard (edts + sgpd)\n"
155 " --ignorelength Ignore length of WAV header\n"
156 " -S, --silent Don't print progress messages\n"
158 "Options for raw (headerless) input:\n"
159 " -R, --raw Treat input as raw (by default WAV is\n"
161 " --raw-channels <n> Number of channels (default: 2)\n"
162 " --raw-rate <n> Sample rate (default: 44100)\n"
163 " --raw-format <spec> Sample format, default is \"S16L\".\n"
164 " Spec is as follows:\n"
165 " 1st char: S(igned)|U(nsigned)|F(loat)\n"
166 " 2nd part: bits per channel\n"
167 " Last char: L(ittle)|B(ig)\n"
168 " Last char can be omitted, in which case L is\n"
169 " assumed. Spec is case insensitive, therefore\n"
170 " \"u16b\" is same as \"U16B\".\n"
173 " --title <string>\n"
174 " --artist <string>\n"
175 " --album <string>\n"
176 " --genre <string>\n"
178 " --composer <string>\n"
179 " --grouping <string>\n"
180 " --comment <string>\n"
181 " --album-artist <string>\n"
182 " --track <number[/total]>\n"
183 " --disk <number[/total]>\n"
185 " --tag <fcc>:<value> Set iTunes predefined tag with four char code.\n"
186 " --tag-from-file <fcc>:<filename>\n"
187 " Same as above, but value is read from file.\n"
188 " --long-tag <name>:<value> Set arbitrary tag as iTunes custom metadata.\n"
189 " --tag-from-json <filename[?dot_notation]>\n"
190 " Read tags from JSON. By default, tags are\n"
191 " assumed to be direct children of the root\n"
192 " object(dictionary).\n"
193 " Optionally, position of the dictionary\n"
194 " that contains tags can be specified with\n"
195 " dotted notation.\n"
197 " --tag-from-json /path/to/json?format.tags\n"
201 typedef struct aacenc_param_ex_t
{
204 char *input_filename
;
205 char *output_filename
;
206 unsigned gapless_mode
;
207 unsigned ignore_length
;
211 unsigned raw_channels
;
213 const char *raw_format
;
215 aacenc_tag_param_t tags
;
221 int parse_options(int argc
, char **argv
, aacenc_param_ex_t
*params
)
226 #define OPT_RAW_CHANNELS M4AF_FOURCC('r','c','h','n')
227 #define OPT_RAW_RATE M4AF_FOURCC('r','r','a','t')
228 #define OPT_RAW_FORMAT M4AF_FOURCC('r','f','m','t')
229 #define OPT_SHORT_TAG M4AF_FOURCC('s','t','a','g')
230 #define OPT_SHORT_TAG_FILE M4AF_FOURCC('s','t','g','f')
231 #define OPT_LONG_TAG M4AF_FOURCC('l','t','a','g')
232 #define OPT_TAG_FROM_JSON M4AF_FOURCC('t','f','j','s')
234 static struct option long_options
[] = {
235 { "help", no_argument
, 0, 'h' },
236 { "profile", required_argument
, 0, 'p' },
237 { "bitrate", required_argument
, 0, 'b' },
238 { "bitrate-mode", required_argument
, 0, 'm' },
239 { "bandwidth", required_argument
, 0, 'w' },
240 { "afterburner", required_argument
, 0, 'a' },
241 { "lowdelay-sbr", no_argument
, 0, 'L' },
242 { "sbr-signaling", required_argument
, 0, 's' },
243 { "transport-format", required_argument
, 0, 'f' },
244 { "adts-crc-check", no_argument
, 0, 'C' },
245 { "header-period", required_argument
, 0, 'P' },
247 { "gapless-mode", required_argument
, 0, 'G' },
248 { "ignorelength", no_argument
, 0, 'I' },
249 { "silent", no_argument
, 0, 'S' },
251 { "raw", no_argument
, 0, 'R' },
252 { "raw-channels", required_argument
, 0, OPT_RAW_CHANNELS
},
253 { "raw-rate", required_argument
, 0, OPT_RAW_RATE
},
254 { "raw-format", required_argument
, 0, OPT_RAW_FORMAT
},
256 { "title", required_argument
, 0, M4AF_TAG_TITLE
},
257 { "artist", required_argument
, 0, M4AF_TAG_ARTIST
},
258 { "album", required_argument
, 0, M4AF_TAG_ALBUM
},
259 { "genre", required_argument
, 0, M4AF_TAG_GENRE
},
260 { "date", required_argument
, 0, M4AF_TAG_DATE
},
261 { "composer", required_argument
, 0, M4AF_TAG_COMPOSER
},
262 { "grouping", required_argument
, 0, M4AF_TAG_GROUPING
},
263 { "comment", required_argument
, 0, M4AF_TAG_COMMENT
},
264 { "album-artist", required_argument
, 0, M4AF_TAG_ALBUM_ARTIST
},
265 { "track", required_argument
, 0, M4AF_TAG_TRACK
},
266 { "disk", required_argument
, 0, M4AF_TAG_DISK
},
267 { "tempo", required_argument
, 0, M4AF_TAG_TEMPO
},
268 { "tag", required_argument
, 0, OPT_SHORT_TAG
},
269 { "tag-from-file", required_argument
, 0, OPT_SHORT_TAG_FILE
},
270 { "long-tag", required_argument
, 0, OPT_LONG_TAG
},
271 { "tag-from-json", required_argument
, 0, OPT_TAG_FROM_JSON
},
274 params
->afterburner
= 1;
276 aacenc_getmainargs(&argc
, &argv
);
277 while ((ch
= getopt_long(argc
, argv
, "hp:b:m:w:a:Ls:f:CP:G:Io:SR",
278 long_options
, 0)) != EOF
) {
283 if (sscanf(optarg
, "%u", &n
) != 1) {
284 fprintf(stderr
, "invalid arg for profile\n");
290 if (sscanf(optarg
, "%u", &n
) != 1) {
291 fprintf(stderr
, "invalid arg for bitrate\n");
297 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 5) {
298 fprintf(stderr
, "invalid arg for bitrate-mode\n");
301 params
->bitrate_mode
= n
;
304 if (sscanf(optarg
, "%u", &n
) != 1) {
305 fprintf(stderr
, "invalid arg for bandwidth\n");
308 params
->bandwidth
= n
;
311 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 1) {
312 fprintf(stderr
, "invalid arg for afterburner\n");
315 params
->afterburner
= n
;
318 params
->lowdelay_sbr
= 1;
321 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 2) {
322 fprintf(stderr
, "invalid arg for sbr-signaling\n");
325 params
->sbr_signaling
= n
;
328 if (sscanf(optarg
, "%u", &n
) != 1) {
329 fprintf(stderr
, "invalid arg for transport-format\n");
332 params
->transport_format
= n
;
335 params
->adts_crc_check
= 1;
338 if (sscanf(optarg
, "%u", &n
) != 1) {
339 fprintf(stderr
, "invalid arg for header-period\n");
342 params
->header_period
= n
;
345 params
->output_filename
= optarg
;
348 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 2) {
349 fprintf(stderr
, "invalid arg for gapless-mode\n");
352 params
->gapless_mode
= n
;
355 params
->ignore_length
= 1;
363 case OPT_RAW_CHANNELS
:
364 if (sscanf(optarg
, "%u", &n
) != 1) {
365 fprintf(stderr
, "invalid arg for raw-channels\n");
368 params
->raw_channels
= n
;
371 if (sscanf(optarg
, "%u", &n
) != 1) {
372 fprintf(stderr
, "invalid arg for raw-rate\n");
375 params
->raw_rate
= n
;
378 params
->raw_format
= optarg
;
381 case M4AF_TAG_ARTIST
:
385 case M4AF_TAG_COMPOSER
:
386 case M4AF_TAG_GROUPING
:
387 case M4AF_TAG_COMMENT
:
388 case M4AF_TAG_ALBUM_ARTIST
:
392 aacenc_param_add_itmf_entry(¶ms
->tags
, ch
, 0, optarg
,
396 case OPT_SHORT_TAG_FILE
:
401 unsigned fcc
= M4AF_FOURCC('-','-','-','-');
403 if ((val
= strchr(optarg
, ':')) == 0) {
404 fprintf(stderr
, "invalid arg for tag\n");
408 if (ch
== OPT_SHORT_TAG
|| ch
== OPT_SHORT_TAG_FILE
) {
410 * take care of U+00A9(COPYRIGHT SIGN).
411 * 1) if length of fcc is 3, we prepend '\xa9'.
412 * 2) U+00A9 becomes "\xc2\xa9" in UTF-8. Therefore
413 * we remove first '\xc2'.
415 if (optarg
[0] == '\xc2')
417 if ((klen
= strlen(optarg
))== 3)
419 else if (klen
!= 4) {
420 fprintf(stderr
, "invalid arg for tag\n");
423 for (; *optarg
; ++optarg
)
424 fcc
= ((fcc
<< 8) | (*optarg
& 0xff));
426 aacenc_param_add_itmf_entry(¶ms
->tags
, fcc
, optarg
,
428 ch
== OPT_SHORT_TAG_FILE
);
431 case OPT_TAG_FROM_JSON
:
432 params
->json_filename
= optarg
;
441 if (!params
->bitrate
&& !params
->bitrate_mode
) {
442 fprintf(stderr
, "bitrate or bitrate-mode is mandatory\n");
445 if (params
->output_filename
&& !strcmp(params
->output_filename
, "-") &&
446 !params
->transport_format
) {
447 fprintf(stderr
, "stdout streaming is not available on M4A output\n");
450 if (params
->bitrate
&& params
->bitrate
< 10000)
451 params
->bitrate
*= 1000;
453 if (params
->is_raw
) {
454 if (!params
->raw_channels
)
455 params
->raw_channels
= 2;
456 if (!params
->raw_rate
)
457 params
->raw_rate
= 44100;
458 if (!params
->raw_format
)
459 params
->raw_format
= "S16L";
461 params
->input_filename
= argv
[optind
];
466 int write_sample(FILE *ofp
, m4af_ctx_t
*m4af
,
467 const void *data
, uint32_t size
, uint32_t duration
)
470 fwrite(data
, 1, size
, ofp
);
472 fprintf(stderr
, "ERROR: fwrite(): %s\n", strerror(errno
));
475 } else if (m4af_write_sample(m4af
, 0, data
, size
, duration
) < 0) {
476 fprintf(stderr
, "ERROR: failed to write m4a sample\n");
483 int encode(wav_reader_t
*wavf
, HANDLE_AACENCODER encoder
,
484 uint32_t frame_length
, FILE *ofp
, m4af_ctx_t
*m4af
,
489 uint32_t pcmsize
= 0;
496 int frames_written
= 0;
497 aacenc_progress_t progress
= { 0 };
498 const pcm_sample_description_t
*format
= wav_get_format(wavf
);
500 ibuf
= malloc(frame_length
* format
->bytes_per_frame
);
501 aacenc_progress_init(&progress
, wav_get_length(wavf
), format
->sample_rate
);
506 if ((nread
= wav_read_frames(wavf
, ibuf
, frame_length
)) < 0) {
507 fprintf(stderr
, "ERROR: read failed\n");
509 } else if (nread
> 0) {
510 if (pcm_convert_to_native_sint16(format
, ibuf
, nread
,
511 &pcmbuf
, &pcmsize
) < 0) {
512 fprintf(stderr
, "ERROR: unsupported sample format\n");
517 aacenc_progress_update(&progress
, wav_get_position(wavf
),
518 format
->sample_rate
* 2);
520 if ((consumed
= aac_encode_frame(encoder
, format
, pcmbuf
, nread
,
521 &obuf
, &olen
, &osize
)) < 0)
524 if (write_sample(ofp
, m4af
, obuf
, olen
, frame_length
) < 0)
528 } while (nread
> 0 || olen
> 0);
531 aacenc_progress_finish(&progress
, wav_get_position(wavf
));
534 if (ibuf
) free(ibuf
);
535 if (pcmbuf
) free(pcmbuf
);
536 if (obuf
) free(obuf
);
541 void put_tool_tag(m4af_ctx_t
*m4af
, const aacenc_param_ex_t
*params
,
542 HANDLE_AACENCODER encoder
)
546 LIB_INFO
*lib_info
= 0;
548 p
+= sprintf(p
, PROGNAME
" %s, ", fdkaac_version
);
550 lib_info
= calloc(FDK_MODULE_LAST
, sizeof(LIB_INFO
));
551 if (aacEncGetLibInfo(lib_info
) == AACENC_OK
) {
553 for (i
= 0; i
< FDK_MODULE_LAST
; ++i
)
554 if (lib_info
[i
].module_id
== FDK_AACENC
)
556 p
+= sprintf(p
, "libfdk-aac %s, ", lib_info
[i
].versionStr
);
559 if (params
->bitrate_mode
)
560 sprintf(p
, "VBR mode %d", params
->bitrate_mode
);
562 sprintf(p
, "CBR %dkbps",
563 aacEncoder_GetParam(encoder
, AACENC_BITRATE
) / 1000);
565 m4af_add_itmf_string_tag(m4af
, M4AF_TAG_TOOL
, tool_info
);
569 int finalize_m4a(m4af_ctx_t
*m4af
, const aacenc_param_ex_t
*params
,
570 HANDLE_AACENCODER encoder
)
573 aacenc_tag_entry_t
*tag
= params
->tags
.tag_table
;
575 if (params
->json_filename
)
576 aacenc_put_tags_from_json(m4af
, params
->json_filename
);
578 for (i
= 0; i
< params
->tags
.tag_count
; ++i
, ++tag
)
579 aacenc_put_tag_entry(m4af
, tag
);
581 put_tool_tag(m4af
, params
, encoder
);
583 if (m4af_finalize(m4af
) < 0) {
584 fprintf(stderr
, "ERROR: failed to finalize m4a\n");
591 char *generate_output_filename(const char *filename
, const char *ext
)
594 size_t ext_len
= strlen(ext
);
596 if (strcmp(filename
, "-") == 0) {
597 p
= malloc(ext_len
+ 6);
598 sprintf(p
, "stdin%s", ext
);
600 const char *base
= aacenc_basename(filename
);
601 size_t ilen
= strlen(base
);
602 const char *ext_org
= strrchr(base
, '.');
603 if (ext_org
) ilen
= ext_org
- base
;
604 p
= malloc(ilen
+ ext_len
+ 1);
605 sprintf(p
, "%.*s%s", ilen
, base
, ext
);
611 int parse_raw_spec(const char *spec
, pcm_sample_description_t
*desc
)
614 unsigned char c_type
, c_endian
= 'L';
617 if (sscanf(spec
, "%c%u%c", &c_type
, &bits
, &c_endian
) < 2)
619 c_type
= toupper(c_type
);
620 c_endian
= toupper(c_endian
);
624 else if (c_type
== 'U')
626 else if (c_type
== 'F')
633 else if (c_endian
!= 'L')
636 if (c_type
== 'F' && bits
!= 32 && bits
!= 64)
638 if (c_type
!= 'F' && (bits
< 8 || bits
> 32))
641 desc
->sample_type
= type
;
642 desc
->bits_per_channel
= bits
;
646 int main(int argc
, char **argv
)
648 wav_io_context_t wav_io
= { read_callback
, seek_callback
, tell_callback
};
650 m4af_io
= { 0, write_callback
, seek_callback
, tell_callback
};
651 aacenc_param_ex_t params
= { 0 };
656 char *output_filename
= 0;
657 wav_reader_t
*wavf
= 0;
658 HANDLE_AACENCODER encoder
= 0;
659 AACENC_InfoStruct aacinfo
= { 0 };
660 m4af_ctx_t
*m4af
= 0;
661 const pcm_sample_description_t
*sample_format
;
662 int downsampled_timescale
= 0;
664 struct stat stb
= { 0 };
666 setlocale(LC_CTYPE
, "");
669 if (parse_options(argc
, argv
, ¶ms
) < 0)
672 if ((ifp
= aacenc_fopen(params
.input_filename
, "rb")) == 0) {
673 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.input_filename
,
677 if (fstat(fileno(ifp
), &stb
) == 0 && (stb
.st_mode
& S_IFMT
) != S_IFREG
) {
681 if (!params
.is_raw
) {
682 if ((wavf
= wav_open(&wav_io
, ifp
, params
.ignore_length
)) == 0) {
683 fprintf(stderr
, "ERROR: broken / unsupported input file\n");
687 int bytes_per_channel
;
688 pcm_sample_description_t desc
= { 0 };
689 if (parse_raw_spec(params
.raw_format
, &desc
) < 0) {
690 fprintf(stderr
, "ERROR: invalid raw-format spec\n");
693 desc
.sample_rate
= params
.raw_rate
;
694 desc
.channels_per_frame
= params
.raw_channels
;
695 bytes_per_channel
= (desc
.bits_per_channel
+ 7) / 8;
696 desc
.bytes_per_frame
= params
.raw_channels
* bytes_per_channel
;
697 if ((wavf
= raw_open(&wav_io
, ifp
, &desc
)) == 0) {
698 fprintf(stderr
, "ERROR: failed to open raw input\n");
702 sample_format
= wav_get_format(wavf
);
704 if (aacenc_init(&encoder
, (aacenc_param_t
*)¶ms
, sample_format
,
708 if (!params
.output_filename
) {
709 const char *ext
= params
.transport_format
? ".aac" : ".m4a";
710 output_filename
= generate_output_filename(params
.input_filename
, ext
);
711 params
.output_filename
= output_filename
;
714 if ((ofp
= aacenc_fopen(params
.output_filename
, "wb")) == 0) {
715 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.output_filename
,
720 if (!params
.transport_format
) {
722 unsigned framelen
= aacinfo
.frameLength
;
723 int sbr_mode
= aacenc_is_sbr_active((aacenc_param_t
*)¶ms
);
724 int sig_mode
= aacEncoder_GetParam(encoder
, AACENC_SIGNALING_MODE
);
725 if (sbr_mode
&& !sig_mode
)
726 downsampled_timescale
= 1;
727 scale
= sample_format
->sample_rate
>> downsampled_timescale
;
728 if ((m4af
= m4af_create(M4AF_CODEC_MP4A
, scale
, &m4af_io
, ofp
)) < 0)
730 m4af_set_decoder_specific_info(m4af
, 0, aacinfo
.confBuf
,
732 m4af_set_fixed_frame_duration(m4af
, 0,
733 framelen
>> downsampled_timescale
);
734 m4af_set_priming_mode(m4af
, params
.gapless_mode
+ 1);
735 m4af_begin_write(m4af
);
737 frame_count
= encode(wavf
, encoder
, aacinfo
.frameLength
, ofp
, m4af
,
742 uint32_t delay
= aacinfo
.encoderDelay
;
743 int64_t frames_read
= wav_get_position(wavf
);
744 uint32_t padding
= frame_count
* aacinfo
.frameLength
745 - frames_read
- aacinfo
.encoderDelay
;
746 m4af_set_priming(m4af
, 0, delay
>> downsampled_timescale
,
747 padding
>> downsampled_timescale
);
748 if (finalize_m4a(m4af
, ¶ms
, encoder
) < 0)
753 if (wavf
) wav_teardown(&wavf
);
754 if (ifp
) fclose(ifp
);
755 if (m4af
) m4af_teardown(&m4af
);
756 if (ofp
) fclose(ofp
);
757 if (encoder
) aacEncClose(&encoder
);
758 if (output_filename
) free(output_filename
);
759 if (params
.tags
.tag_table
) free(params
.tags
.tag_table
);