summaryrefslogtreecommitdiff
path: root/lib/rbcodec/metadata
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2018-12-22 20:01:42 -0500
committerSolomon Peachy <pizza@shaftnet.org>2018-12-22 20:12:10 -0500
commit928557bb174fdc6ae44d784137e19a61b4f42693 (patch)
tree37b6a3effd923b839c8fb02b806c43ea7506be9f /lib/rbcodec/metadata
parent9b9b30bd547c829157f3f83c71378f0bbd43241d (diff)
downloadrockbox-928557bb174fdc6ae44d784137e19a61b4f42693.tar.gz
rockbox-928557bb174fdc6ae44d784137e19a61b4f42693.zip
AAC bitstream format files support
Files with extension "aac" in ADTS or ADIF format are now playable. Full credit goes to Igor Poretsky. Change-Id: I413b34e15e5242fea60d3461966ae0984080f530
Diffstat (limited to 'lib/rbcodec/metadata')
-rw-r--r--lib/rbcodec/metadata/aac.c122
-rw-r--r--lib/rbcodec/metadata/metadata.c3
-rw-r--r--lib/rbcodec/metadata/metadata.h1
-rw-r--r--lib/rbcodec/metadata/metadata_parsers.h1
4 files changed, 127 insertions, 0 deletions
diff --git a/lib/rbcodec/metadata/aac.c b/lib/rbcodec/metadata/aac.c
new file mode 100644
index 0000000000..82adeacbde
--- /dev/null
+++ b/lib/rbcodec/metadata/aac.c
@@ -0,0 +1,122 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Parsing ADTS and ADIF headers
11 *
12 * Written by Igor B. Poretsky
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include <stdlib.h>
25#include <stdbool.h>
26#include <string.h>
27
28#include "platform.h"
29
30#include "metadata.h"
31#include "metadata_common.h"
32#include "metadata_parsers.h"
33
34static const int sample_rates[] =
35{
36 96000, 88200, 64000, 48000,
37 44100, 32000, 24000, 22050,
38 16000, 12000, 11025, 8000,
39 7350, 0, 0, 0
40};
41
42static bool check_adts_syncword(int fd)
43{
44 uint16_t syncword;
45
46 read_uint16be(fd, &syncword);
47 return (syncword & 0xFFF6) == 0xFFF0;
48}
49
50bool get_aac_metadata(int fd, struct mp3entry *entry)
51{
52 unsigned char buf[5];
53
54 entry->title = NULL;
55 entry->tracknum = 0;
56 entry->discnum = 0;
57 entry->id3v1len = 0;
58 entry->id3v2len = getid3v2len(fd);
59 entry->first_frame_offset = entry->id3v2len;
60 entry->filesize = filesize(fd) - entry->first_frame_offset;
61 entry->needs_upsampling_correction = false;
62
63 if (entry->id3v2len)
64 setid3v2title(fd, entry);
65
66 if (-1 == lseek(fd, entry->first_frame_offset, SEEK_SET))
67 return false;
68
69 if (check_adts_syncword(fd))
70 {
71 int frames;
72 int stat_length;
73 uint64_t total;
74 if (read(fd, buf, 5) != 5)
75 return false;
76 entry->frequency = sample_rates[(buf[0] >> 2) & 0x0F];
77 entry->vbr = ((buf[3] & 0x1F) == 0x1F)
78 && ((buf[4] & 0xFC) == 0xFC);
79 stat_length = entry->frequency >> ((entry->vbr) ? 5 : 7);
80 for (frames = 1, total = 0; frames < stat_length; frames++)
81 {
82 unsigned int frame_length = (((unsigned int)buf[1] & 0x3) << 11)
83 | ((unsigned int)buf[2] << 3)
84 | ((unsigned int)buf[3] >> 5);
85 total += frame_length;
86 if (frame_length < 7)
87 break;
88 if (-1 == lseek(fd, frame_length - 7, SEEK_CUR))
89 break;
90 if (!check_adts_syncword(fd))
91 break;
92 if (read(fd, buf, 5) != 5)
93 break;
94 }
95 entry->bitrate = (unsigned int)((total * entry->frequency / frames + 64000) / 128000);
96 if (entry->frequency <= 24000)
97 {
98 entry->frequency <<= 1;
99 entry->needs_upsampling_correction = true;
100 }
101 }
102 else
103 {
104 uint32_t bitrate;
105 if (-1 == lseek(fd, entry->first_frame_offset, SEEK_SET))
106 return false;
107 if (read(fd, buf, 5) != 5)
108 return false;
109 if (memcmp(buf, "ADIF", 4))
110 return false;
111 if (-1 == lseek(fd, (buf[4] & 0x80) ? (entry->first_frame_offset + 9) : entry->first_frame_offset, SEEK_SET))
112 return false;
113 read_uint32be(fd, &bitrate);
114 entry->vbr = (bitrate & 0x10000000) != 0;
115 entry->bitrate = ((bitrate & 0xFFFFFE0) + 16000) / 32000;
116 read_uint32be(fd, (uint32_t*)(&(entry->frequency)));
117 entry->frequency = sample_rates[(entry->frequency >> (entry->vbr ? 23 : 3)) & 0x0F];
118 }
119 entry->length = (unsigned long)((entry->filesize * 8LL + (entry->bitrate >> 1)) / entry->bitrate);
120
121 return true;
122}
diff --git a/lib/rbcodec/metadata/metadata.c b/lib/rbcodec/metadata/metadata.c
index 7ca4b1afd2..c24a27df2b 100644
--- a/lib/rbcodec/metadata/metadata.c
+++ b/lib/rbcodec/metadata/metadata.c
@@ -235,6 +235,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
235 /* Opus */ 235 /* Opus */
236 [AFMT_OPUS] = 236 [AFMT_OPUS] =
237 AFMT_ENTRY("Opus", "opus", NULL, get_ogg_metadata, "opus\0"), 237 AFMT_ENTRY("Opus", "opus", NULL, get_ogg_metadata, "opus\0"),
238 /* AAC bitstream format */
239 [AFMT_AAC_BSF] =
240 AFMT_ENTRY("AAC", "aac_bsf", NULL, get_aac_metadata, "aac\0"),
238#endif 241#endif
239}; 242};
240 243
diff --git a/lib/rbcodec/metadata/metadata.h b/lib/rbcodec/metadata/metadata.h
index 18cfce7523..a7ebcf16e5 100644
--- a/lib/rbcodec/metadata/metadata.h
+++ b/lib/rbcodec/metadata/metadata.h
@@ -90,6 +90,7 @@ enum
90 AFMT_VGM, /* VGM (Video Game Music Format) */ 90 AFMT_VGM, /* VGM (Video Game Music Format) */
91 AFMT_KSS, /* KSS (MSX computer KSS Music File) */ 91 AFMT_KSS, /* KSS (MSX computer KSS Music File) */
92 AFMT_OPUS, /* Opus (see http://www.opus-codec.org ) */ 92 AFMT_OPUS, /* Opus (see http://www.opus-codec.org ) */
93 AFMT_AAC_BSF,
93#endif 94#endif
94 95
95 /* add new formats at any index above this line to have a sensible order - 96 /* add new formats at any index above this line to have a sensible order -
diff --git a/lib/rbcodec/metadata/metadata_parsers.h b/lib/rbcodec/metadata/metadata_parsers.h
index 304e393538..9f03c79bb5 100644
--- a/lib/rbcodec/metadata/metadata_parsers.h
+++ b/lib/rbcodec/metadata/metadata_parsers.h
@@ -56,4 +56,5 @@ bool get_hes_metadata(int fd, struct mp3entry* id3);
56bool get_sgc_metadata(int fd, struct mp3entry* id3); 56bool get_sgc_metadata(int fd, struct mp3entry* id3);
57bool get_vgm_metadata(int fd, struct mp3entry* id3); 57bool get_vgm_metadata(int fd, struct mp3entry* id3);
58bool get_kss_metadata(int fd, struct mp3entry* id3); 58bool get_kss_metadata(int fd, struct mp3entry* id3);
59bool get_aac_metadata(int fd, struct mp3entry* id3);
59#endif /* CONFIG_CODEC == SWCODEC */ 60#endif /* CONFIG_CODEC == SWCODEC */