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"
31 #include "wav_reader.h"
37 #define PROGNAME "fdkaac"
40 int read_callback(void *cookie
, void *data
, uint32_t size
)
42 size_t rc
= fread(data
, 1, size
, (FILE*)cookie
);
43 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
47 int write_callback(void *cookie
, const void *data
, uint32_t size
)
49 size_t rc
= fwrite(data
, 1, size
, (FILE*)cookie
);
50 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
54 int seek_callback(void *cookie
, int64_t off
, int whence
)
56 return fseeko((FILE*)cookie
, off
, whence
);
60 int64_t tell_callback(void *cookie
)
62 return ftello((FILE*)cookie
);
70 "Usage: " PROGNAME
" [options] input_file\n"
72 " -h, --help Print this help message\n"
73 " -p, --profile <n> Profile (audio object type)\n"
74 " 2: MPEG-4 AAC LC (default)\n"
75 " 5: MPEG-4 HE-AAC (SBR)\n"
76 " 29: MPEG-4 HE-AAC v2 (SBR+PS)\n"
77 " 23: MPEG-4 AAC LD\n"
78 " 39: MPEG-4 AAC ELD\n"
79 " 129: MPEG-2 AAC LC\n"
80 " 132: MPEG-2 HE-AAC (SBR)\n"
81 " 156: MPEG-2 HE-AAC v2 (SBR+PS)\n"
82 " -b, --bitrate <n> Bitrate in bits per seconds (for CBR)\n"
83 " -m, --bitrate-mode <n> Bitrate configuration\n"
86 " (VBR mode is not officially supported, and\n"
87 " works only on a certain combination of\n"
88 " parameter settings, sample rate, and\n"
89 " channel configuration)\n"
90 " -w, --bandwidth <n> Frequency bandwidth in Hz (AAC LC only)\n"
91 " -a, --afterburner <n> Afterburner\n"
94 " -L, --lowdelay-sbr Enable ELD-SBR (AAC ELD only)\n"
95 " -s, --sbr-signaling <n> SBR signaling mode\n"
96 " 0: Implicit, backward compatible(default)\n"
97 " 1: Explicit SBR and implicit PS\n"
98 " 2: Explicit hierarchical signaling\n"
99 " -f, --transport-format <n> Transport format\n"
100 " 0: RAW (default, muxed into M4A)\n"
105 " 10: LOAS/LATM (LATM within LOAS)\n"
106 " -C, --adts-crc-check Add CRC protection on ADTS header\n"
107 " -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
110 " -o <filename> Output filename\n"
111 " --ignore-length Ignore length of WAV header\n"
113 "Options for raw (headerless) input:\n"
114 " -R, --raw Treat input as raw (by default WAV is\n"
116 " --raw-channels <n> Number of channels (default: 2)\n"
117 " --raw-rate <n> Sample rate (default: 44100)\n"
118 " --raw-format <spec> Sample format, default is \"S16L\".\n"
119 " Spec is as follows:\n"
120 " 1st char: S(igned)|U(nsigned)|F(loat)\n"
121 " 2nd part: bits per channel\n"
122 " Last char: L(ittle)|B(ig)\n"
123 " Last char can be omitted, in which case L is\n"
124 " assumed. Spec is case insensitive, therefore\n"
125 " \"u16b\" is same as \"U16B\".\n"
128 " --title <string>\n"
129 " --artist <string>\n"
130 " --album <string>\n"
131 " --genre <string>\n"
133 " --composer <string>\n"
134 " --grouping <string>\n"
135 " --comment <string>\n"
136 " --album-artist <string>\n"
137 " --track <number[/total]>\n"
138 " --disk <number[/total]>\n"
140 " --tag <fcc>:<value> Set iTunes predefined tag with four char code.\n"
141 " --long-tag <name>:<value> Set arbitrary tag as iTunes custom metadata.\n"
145 typedef struct aacenc_tag_entry_t
{
150 } aacenc_tag_entry_t
;
152 typedef struct aacenc_param_ex_t
{
155 char *input_filename
;
156 char *output_filename
;
157 unsigned ignore_length
;
160 unsigned raw_channels
;
162 const char *raw_format
;
164 aacenc_tag_entry_t
*tag_table
;
166 unsigned tag_table_capacity
;
170 void param_add_itmf_entry(aacenc_param_ex_t
*params
, uint32_t tag
,
171 const char *key
, const char *value
, uint32_t size
)
173 aacenc_tag_entry_t
*entry
;
174 if (params
->tag_count
== params
->tag_table_capacity
) {
175 unsigned newsize
= params
->tag_table_capacity
;
176 newsize
= newsize
? newsize
* 2 : 1;
178 realloc(params
->tag_table
, newsize
* sizeof(aacenc_tag_entry_t
));
179 params
->tag_table_capacity
= newsize
;
181 entry
= params
->tag_table
+ params
->tag_count
;
183 if (tag
== M4AF_FOURCC('-','-','-','-'))
186 entry
->data_size
= size
;
191 int parse_options(int argc
, char **argv
, aacenc_param_ex_t
*params
)
196 #define OPT_RAW_CHANNELS M4AF_FOURCC('r','c','h','n')
197 #define OPT_RAW_RATE M4AF_FOURCC('r','r','a','t')
198 #define OPT_RAW_FORMAT M4AF_FOURCC('r','f','m','t')
199 #define OPT_SHORT_TAG M4AF_FOURCC('s','t','a','g')
200 #define OPT_LONG_TAG M4AF_FOURCC('l','t','a','g')
202 static struct option long_options
[] = {
203 { "help", no_argument
, 0, 'h' },
204 { "profile", required_argument
, 0, 'p' },
205 { "bitrate", required_argument
, 0, 'b' },
206 { "bitrate-mode", required_argument
, 0, 'm' },
207 { "bandwidth", required_argument
, 0, 'w' },
208 { "afterburner", required_argument
, 0, 'a' },
209 { "lowdelay-sbr", no_argument
, 0, 'L' },
210 { "sbr-signaling", required_argument
, 0, 's' },
211 { "transport-format", required_argument
, 0, 'f' },
212 { "adts-crc-check", no_argument
, 0, 'C' },
213 { "header-period", required_argument
, 0, 'P' },
215 { "ignore-length", no_argument
, 0, 'I' },
217 { "raw", no_argument
, 0, 'R' },
218 { "raw-channels", required_argument
, 0, OPT_RAW_CHANNELS
},
219 { "raw-rate", required_argument
, 0, OPT_RAW_RATE
},
220 { "raw-format", required_argument
, 0, OPT_RAW_FORMAT
},
222 { "title", required_argument
, 0, M4AF_TAG_TITLE
},
223 { "artist", required_argument
, 0, M4AF_TAG_ARTIST
},
224 { "album", required_argument
, 0, M4AF_TAG_ALBUM
},
225 { "genre", required_argument
, 0, M4AF_TAG_GENRE
},
226 { "date", required_argument
, 0, M4AF_TAG_DATE
},
227 { "composer", required_argument
, 0, M4AF_TAG_COMPOSER
},
228 { "grouping", required_argument
, 0, M4AF_TAG_GROUPING
},
229 { "comment", required_argument
, 0, M4AF_TAG_COMMENT
},
230 { "album-artist", required_argument
, 0, M4AF_TAG_ALBUM_ARTIST
},
231 { "track", required_argument
, 0, M4AF_TAG_TRACK
},
232 { "disk", required_argument
, 0, M4AF_TAG_DISK
},
233 { "tempo", required_argument
, 0, M4AF_TAG_TEMPO
},
234 { "tag", required_argument
, 0, OPT_SHORT_TAG
},
235 { "long-tag", required_argument
, 0, OPT_LONG_TAG
},
237 params
->afterburner
= 1;
239 aacenc_getmainargs(&argc
, &argv
);
240 while ((ch
= getopt_long(argc
, argv
, "hp:b:m:w:a:Ls:f:CP:Io:R",
241 long_options
, 0)) != EOF
) {
246 if (sscanf(optarg
, "%u", &n
) != 1) {
247 fprintf(stderr
, "invalid arg for profile\n");
253 if (sscanf(optarg
, "%u", &n
) != 1) {
254 fprintf(stderr
, "invalid arg for bitrate\n");
260 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 5) {
261 fprintf(stderr
, "invalid arg for bitrate-mode\n");
264 params
->bitrate_mode
= n
;
267 if (sscanf(optarg
, "%u", &n
) != 1) {
268 fprintf(stderr
, "invalid arg for bandwidth\n");
271 params
->bandwidth
= n
;
274 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 1) {
275 fprintf(stderr
, "invalid arg for afterburner\n");
278 params
->afterburner
= n
;
281 params
->lowdelay_sbr
= 1;
284 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 2) {
285 fprintf(stderr
, "invalid arg for sbr-signaling\n");
288 params
->sbr_signaling
= n
;
291 if (sscanf(optarg
, "%u", &n
) != 1) {
292 fprintf(stderr
, "invalid arg for transport-format\n");
295 params
->transport_format
= n
;
298 params
->adts_crc_check
= 1;
301 if (sscanf(optarg
, "%u", &n
) != 1) {
302 fprintf(stderr
, "invalid arg for header-period\n");
305 params
->header_period
= n
;
308 params
->output_filename
= optarg
;
311 params
->ignore_length
= 1;
316 case OPT_RAW_CHANNELS
:
317 if (sscanf(optarg
, "%u", &n
) != 1) {
318 fprintf(stderr
, "invalid arg for raw-channels\n");
321 params
->raw_channels
= n
;
324 if (sscanf(optarg
, "%u", &n
) != 1) {
325 fprintf(stderr
, "invalid arg for raw-rate\n");
328 params
->raw_rate
= n
;
331 params
->raw_format
= optarg
;
334 case M4AF_TAG_ARTIST
:
338 case M4AF_TAG_COMPOSER
:
339 case M4AF_TAG_GROUPING
:
340 case M4AF_TAG_COMMENT
:
341 case M4AF_TAG_ALBUM_ARTIST
:
345 param_add_itmf_entry(params
, ch
, 0, optarg
, strlen(optarg
));
352 unsigned fcc
= M4AF_FOURCC('-','-','-','-');
354 if ((val
= strchr(optarg
, ':')) == 0) {
355 fprintf(stderr
, "invalid arg for tag\n");
359 if (ch
== OPT_SHORT_TAG
) {
360 if ((klen
= strlen(optarg
))== 3)
362 else if (klen
!= 4) {
363 fprintf(stderr
, "invalid arg for tag\n");
366 for (; *optarg
; ++optarg
)
367 fcc
= ((fcc
<< 8) | (*optarg
& 0xff));
369 param_add_itmf_entry(params
, fcc
, optarg
, val
, strlen(val
));
379 if (!params
->bitrate
&& !params
->bitrate_mode
) {
380 fprintf(stderr
, "bitrate or bitrate-mode is mandatory\n");
383 if (params
->output_filename
&& !strcmp(params
->output_filename
, "-") &&
384 !params
->transport_format
) {
385 fprintf(stderr
, "stdout streaming is not available on M4A output\n");
388 if (params
->bitrate
&& params
->bitrate
< 10000)
389 params
->bitrate
*= 1000;
391 if (params
->is_raw
) {
392 if (!params
->raw_channels
)
393 params
->raw_channels
= 2;
394 if (!params
->raw_rate
)
395 params
->raw_rate
= 44100;
396 if (!params
->raw_format
)
397 params
->raw_format
= "S16L";
399 params
->input_filename
= argv
[optind
];
404 int write_sample(FILE *ofp
, m4af_writer_t
*m4af
,
405 const void *data
, uint32_t size
, uint32_t duration
)
408 fwrite(data
, 1, size
, ofp
);
410 fprintf(stderr
, "ERROR: fwrite(): %s\n", strerror(errno
));
413 } else if (m4af_write_sample(m4af
, 0, data
, size
, duration
) < 0) {
414 fprintf(stderr
, "ERROR: failed to write m4a sample\n");
421 int encode(wav_reader_t
*wavf
, HANDLE_AACENCODER encoder
,
422 uint32_t frame_length
, FILE *ofp
, m4af_writer_t
*m4af
)
426 uint32_t pcmsize
= 0;
433 int frames_written
= 0;
434 aacenc_progress_t progress
= { 0 };
435 const pcm_sample_description_t
*format
= wav_get_format(wavf
);
437 ibuf
= malloc(frame_length
* format
->bytes_per_frame
);
438 aacenc_progress_init(&progress
, wav_get_length(wavf
), format
->sample_rate
);
441 if ((nread
= wav_read_frames(wavf
, ibuf
, frame_length
)) < 0) {
442 fprintf(stderr
, "ERROR: read failed\n");
444 } else if (nread
> 0) {
445 if (pcm_convert_to_native_sint16(format
, ibuf
, nread
,
446 &pcmbuf
, &pcmsize
) < 0) {
447 fprintf(stderr
, "ERROR: unsupported sample format\n");
451 aacenc_progress_update(&progress
, wav_get_position(wavf
),
452 format
->sample_rate
* 2);
454 if ((consumed
= aac_encode_frame(encoder
, format
, pcmbuf
, nread
,
455 &obuf
, &olen
, &osize
)) < 0)
458 if (write_sample(ofp
, m4af
, obuf
, olen
, frame_length
) < 0)
462 } while (nread
> 0 || olen
> 0);
463 aacenc_progress_finish(&progress
, wav_get_position(wavf
));
466 if (ibuf
) free(ibuf
);
467 if (pcmbuf
) free(pcmbuf
);
468 if (obuf
) free(obuf
);
473 int put_tag_entry(m4af_writer_t
*m4af
, const aacenc_tag_entry_t
*tag
)
479 if (sscanf(tag
->data
, "%u/%u", &m
, &n
) >= 1)
480 m4af_add_itmf_track_tag(m4af
, m
, n
);
483 if (sscanf(tag
->data
, "%u/%u", &m
, &n
) >= 1)
484 m4af_add_itmf_disk_tag(m4af
, m
, n
);
486 case M4AF_TAG_GENRE_ID3
:
487 if (sscanf(tag
->data
, "%u", &n
) == 1)
488 m4af_add_itmf_genre_tag(m4af
, n
);
491 if (sscanf(tag
->data
, "%u", &n
) == 1)
492 m4af_add_itmf_int16_tag(m4af
, tag
->tag
, n
);
494 case M4AF_TAG_COMPILATION
:
495 case M4AF_FOURCC('a','k','I','D'):
496 case M4AF_FOURCC('h','d','v','d'):
497 case M4AF_FOURCC('p','c','s','t'):
498 case M4AF_FOURCC('p','g','a','p'):
499 case M4AF_FOURCC('r','t','n','g'):
500 case M4AF_FOURCC('s','t','i','k'):
501 if (sscanf(tag
->data
, "%u", &n
) == 1)
502 m4af_add_itmf_int8_tag(m4af
, tag
->tag
, n
);
504 case M4AF_FOURCC('a','t','I','D'):
505 case M4AF_FOURCC('c','m','I','D'):
506 case M4AF_FOURCC('c','n','I','D'):
507 case M4AF_FOURCC('g','e','I','D'):
508 case M4AF_FOURCC('s','f','I','D'):
509 case M4AF_FOURCC('t','v','s','n'):
510 case M4AF_FOURCC('t','v','s','s'):
511 if (sscanf(tag
->data
, "%u", &n
) == 1)
512 m4af_add_itmf_int32_tag(m4af
, tag
->tag
, n
);
514 case M4AF_FOURCC('p','l','I','D'):
517 if (sscanf(tag
->data
, "%" SCNd64
, &qn
) == 1)
518 m4af_add_itmf_int64_tag(m4af
, tag
->tag
, qn
);
521 case M4AF_TAG_ARTWORK
:
524 if (!memcmp(tag
->data
, "GIF", 3))
525 data_type
= M4AF_GIF
;
526 else if (!memcmp(tag
->data
, "\xff\xd8\xff", 3))
527 data_type
= M4AF_JPEG
;
528 else if (!memcmp(tag
->data
, "\x89PNG", 4))
529 data_type
= M4AF_PNG
;
531 m4af_add_itmf_short_tag(m4af
, tag
->tag
, data_type
,
532 tag
->data
, tag
->data_size
);
535 case M4AF_FOURCC('-','-','-','-'):
537 char *u8
= aacenc_to_utf8(tag
->data
);
538 m4af_add_itmf_long_tag(m4af
, tag
->name
, u8
);
543 case M4AF_TAG_ARTIST
:
547 case M4AF_TAG_COMPOSER
:
548 case M4AF_TAG_GROUPING
:
549 case M4AF_TAG_COMMENT
:
550 case M4AF_TAG_LYRICS
:
552 case M4AF_TAG_ALBUM_ARTIST
:
553 case M4AF_TAG_DESCRIPTION
:
554 case M4AF_TAG_LONG_DESCRIPTION
:
555 case M4AF_TAG_COPYRIGHT
:
556 case M4AF_FOURCC('a','p','I','D'):
557 case M4AF_FOURCC('c','a','t','g'):
558 case M4AF_FOURCC('k','e','y','w'):
559 case M4AF_FOURCC('p','u','r','d'):
560 case M4AF_FOURCC('p','u','r','l'):
561 case M4AF_FOURCC('s','o','a','a'):
562 case M4AF_FOURCC('s','o','a','l'):
563 case M4AF_FOURCC('s','o','a','r'):
564 case M4AF_FOURCC('s','o','c','o'):
565 case M4AF_FOURCC('s','o','n','m'):
566 case M4AF_FOURCC('s','o','s','n'):
567 case M4AF_FOURCC('t','v','e','n'):
568 case M4AF_FOURCC('t','v','n','n'):
569 case M4AF_FOURCC('t','v','s','h'):
570 case M4AF_FOURCC('\xa9','e','n','c'):
571 case M4AF_FOURCC('\xa9','s','t','3'):
573 char *u8
= aacenc_to_utf8(tag
->data
);
574 m4af_add_itmf_string_tag(m4af
, tag
->tag
, u8
);
579 fprintf(stderr
, "WARNING: unknown/unsupported tag: %c%c%c%c\n",
580 tag
->tag
>> 24, (tag
->tag
>> 16) & 0xff,
581 (tag
->tag
>> 8) & 0xff, tag
->tag
& 0xff);
586 void put_tool_tag(m4af_writer_t
*m4af
, const aacenc_param_ex_t
*params
,
587 HANDLE_AACENCODER encoder
)
591 LIB_INFO
*lib_info
= 0;
593 p
+= sprintf(p
, PROGNAME
" %s, ", fdkaac_version
);
595 lib_info
= calloc(FDK_MODULE_LAST
, sizeof(LIB_INFO
));
596 if (aacEncGetLibInfo(lib_info
) == AACENC_OK
) {
598 for (i
= 0; i
< FDK_MODULE_LAST
; ++i
)
599 if (lib_info
[i
].module_id
== FDK_AACENC
)
601 p
+= sprintf(p
, "libfdk-aac %s, ", lib_info
[i
].versionStr
);
604 if (params
->bitrate_mode
)
605 sprintf(p
, "VBR mode %d", params
->bitrate_mode
);
607 sprintf(p
, "CBR %dkbps",
608 aacEncoder_GetParam(encoder
, AACENC_BITRATE
) / 1000);
610 m4af_add_itmf_string_tag(m4af
, M4AF_TAG_TOOL
, tool_info
);
614 int finalize_m4a(m4af_writer_t
*m4af
, const aacenc_param_ex_t
*params
,
615 HANDLE_AACENCODER encoder
)
618 aacenc_tag_entry_t
*tag
= params
->tag_table
;
619 for (i
= 0; i
< params
->tag_count
; ++i
, ++tag
)
620 put_tag_entry(m4af
, tag
);
622 put_tool_tag(m4af
, params
, encoder
);
624 if (m4af_finalize(m4af
) < 0) {
625 fprintf(stderr
, "ERROR: failed to finalize m4a\n");
632 const char *basename(const char *filename
)
634 char *p
= strrchr(filename
, '/');
636 char *q
= strrchr(filename
, '\\');
639 return p
? p
+ 1 : filename
;
643 char *generate_output_filename(const char *filename
, const char *ext
)
646 size_t ext_len
= strlen(ext
);
648 if (strcmp(filename
, "-") == 0) {
649 p
= malloc(ext_len
+ 6);
650 sprintf(p
, "stdin%s", ext
);
652 const char *base
= basename(filename
);
653 size_t ilen
= strlen(base
);
654 const char *ext_org
= strrchr(base
, '.');
655 if (ext_org
) ilen
= ext_org
- base
;
656 p
= malloc(ilen
+ ext_len
+ 1);
657 sprintf(p
, "%.*s%s", ilen
, base
, ext
);
663 int parse_raw_spec(const char *spec
, pcm_sample_description_t
*desc
)
666 unsigned char c_type
, c_endian
= 'L';
669 if (sscanf(spec
, "%c%u%c", &c_type
, &bits
, &c_endian
) < 2)
671 c_type
= toupper(c_type
);
672 c_endian
= toupper(c_endian
);
676 else if (c_type
== 'U')
678 else if (c_type
== 'F')
685 else if (c_endian
!= 'L')
688 if (c_type
== 'F' && bits
!= 32 && bits
!= 64)
690 if (c_type
!= 'F' && (bits
< 8 || bits
> 32))
693 desc
->sample_type
= type
;
694 desc
->bits_per_channel
= bits
;
698 int main(int argc
, char **argv
)
700 wav_io_context_t wav_io
= { read_callback
, seek_callback
, tell_callback
};
701 m4af_io_callbacks_t m4af_io
= {
702 write_callback
, seek_callback
, tell_callback
};
703 aacenc_param_ex_t params
= { 0 };
708 char *output_filename
= 0;
709 wav_reader_t
*wavf
= 0;
710 HANDLE_AACENCODER encoder
= 0;
711 AACENC_InfoStruct aacinfo
= { 0 };
712 m4af_writer_t
*m4af
= 0;
713 const pcm_sample_description_t
*sample_format
;
714 int downsampled_timescale
= 0;
716 struct stat stb
= { 0 };
718 setlocale(LC_CTYPE
, "");
721 if (parse_options(argc
, argv
, ¶ms
) < 0)
724 if ((ifp
= aacenc_fopen(params
.input_filename
, "rb")) == 0) {
725 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.input_filename
,
729 if (fstat(fileno(ifp
), &stb
) == 0 && (stb
.st_mode
& S_IFMT
) != S_IFREG
) {
733 if (!params
.is_raw
) {
734 if ((wavf
= wav_open(&wav_io
, ifp
, params
.ignore_length
)) == 0) {
735 fprintf(stderr
, "ERROR: broken / unsupported input file\n");
739 int bytes_per_channel
;
740 pcm_sample_description_t desc
= { 0 };
741 if (parse_raw_spec(params
.raw_format
, &desc
) < 0) {
742 fprintf(stderr
, "ERROR: invalid raw-format spec\n");
745 desc
.sample_rate
= params
.raw_rate
;
746 desc
.channels_per_frame
= params
.raw_channels
;
747 bytes_per_channel
= (desc
.bits_per_channel
+ 7) / 8;
748 desc
.bytes_per_frame
= params
.raw_channels
* bytes_per_channel
;
749 if ((wavf
= raw_open(&wav_io
, ifp
, &desc
)) == 0) {
750 fprintf(stderr
, "ERROR: failed to open raw input\n");
754 sample_format
= wav_get_format(wavf
);
756 if (aacenc_init(&encoder
, (aacenc_param_t
*)¶ms
, sample_format
,
760 if (!params
.output_filename
) {
761 const char *ext
= params
.transport_format
? ".aac" : ".m4a";
762 output_filename
= generate_output_filename(params
.input_filename
, ext
);
763 params
.output_filename
= output_filename
;
766 if ((ofp
= aacenc_fopen(params
.output_filename
, "wb")) == 0) {
767 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.output_filename
,
771 if (!params
.transport_format
) {
773 unsigned framelen
= aacinfo
.frameLength
;
774 int sbr_mode
= aacenc_is_sbr_active((aacenc_param_t
*)¶ms
);
775 int sig_mode
= aacEncoder_GetParam(encoder
, AACENC_SIGNALING_MODE
);
776 if (sbr_mode
&& !sig_mode
)
777 downsampled_timescale
= 1;
778 scale
= sample_format
->sample_rate
>> downsampled_timescale
;
779 if ((m4af
= m4af_create(M4AF_CODEC_MP4A
, scale
, &m4af_io
, ofp
)) < 0)
781 m4af_decoder_specific_info(m4af
, 0, aacinfo
.confBuf
, aacinfo
.confSize
);
782 m4af_set_fixed_frame_duration(m4af
, 0,
783 framelen
>> downsampled_timescale
);
784 m4af_begin_write(m4af
);
786 frame_count
= encode(wavf
, encoder
, aacinfo
.frameLength
, ofp
, m4af
);
790 uint32_t delay
= aacinfo
.encoderDelay
;
791 int64_t frames_read
= wav_get_position(wavf
);
792 uint32_t padding
= frame_count
* aacinfo
.frameLength
793 - frames_read
- aacinfo
.encoderDelay
;
794 m4af_set_priming(m4af
, 0, delay
>> downsampled_timescale
,
795 padding
>> downsampled_timescale
);
796 if (finalize_m4a(m4af
, ¶ms
, encoder
) < 0)
801 if (wavf
) wav_teardown(&wavf
);
802 if (ifp
) fclose(ifp
);
803 if (m4af
) m4af_teardown(&m4af
);
804 if (ofp
) fclose(ofp
);
805 if (encoder
) aacEncClose(&encoder
);
806 if (output_filename
) free(output_filename
);
807 if (params
.tag_table
) free(params
.tag_table
);