summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/aac.c29
-rw-r--r--apps/metadata/mp4.c27
2 files changed, 51 insertions, 5 deletions
diff --git a/apps/codecs/aac.c b/apps/codecs/aac.c
index af40385..37e525e 100644
--- a/apps/codecs/aac.c
+++ b/apps/codecs/aac.c
@@ -59,6 +59,7 @@ enum codec_status codec_main(void)
NeAACDecHandle decoder;
int err;
uint32_t s = 0;
+ uint32_t sbr_fac = 1;
unsigned char c = 0;
void *ret;
@@ -143,13 +144,26 @@ next_track:
decoder->fb_intermed[1] = &gb_fb_intermed[1][0];
}
+#ifdef SBR_DEC
+ /* The file uses SBR. */
+ if (decoder->forceUpSampling) {
+ sbr_fac = 2;
+ } else {
+ sbr_fac = 1;
+ }
+#endif
+
ci->id3->frequency = s;
i = 0;
if (file_offset > 0) {
+ /* Resume the desired (byte) position. Important: When resuming SBR
+ * upsampling files the resulting sound_samples_done must be expanded
+ * by a factor of 2. This is done via using sbr_fac. */
if (alac_seek_raw(&demux_res, &input_stream, file_offset,
&sound_samples_done, (int*) &i)) {
+ sound_samples_done *= sbr_fac;
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
ci->set_elapsed(elapsed_time);
} else {
@@ -174,9 +188,14 @@ next_track:
/* Deal with any pending seek requests */
if (ci->seek_time) {
+ /* Seek to the desired time position. Important: When seeking in SBR
+ * upsampling files the seek_time must be divided by 2 when calling
+ * alac_seek and the resulting sound_samples_done must be expanded
+ * by a factor 2. This is done via using sbr_fac. */
if (alac_seek(&demux_res, &input_stream,
- ((ci->seek_time-1)/10)*(ci->id3->frequency/100),
+ ((ci->seek_time-1)/10/sbr_fac)*(ci->id3->frequency/100),
&sound_samples_done, (int*) &i)) {
+ sound_samples_done *= sbr_fac;
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
ci->set_elapsed(elapsed_time);
@@ -234,6 +253,10 @@ next_track:
/* Output the audio */
ci->yield();
+ /* Ensure correct sample_duration is used. For SBR upsampling files
+ * sample_duration is only half the size of real output frame size. */
+ sample_duration *= sbr_fac;
+
framelength = (frame_info.samples >> 1) - lead_trim;
if (i == demux_res.num_sample_byte_sizes - 1 && framelength > 0)
@@ -266,7 +289,7 @@ next_track:
{
/* frame_info.samples can be 0 for the first frame */
lead_trim -= (i > 0 || frame_info.samples)
- ? (frame_info.samples >> 1) : sample_duration;
+ ? (frame_info.samples >> 1) : (uint32_t)framelength;
if (lead_trim < 0 || ci->id3->lead_trim == 0)
{
@@ -275,7 +298,7 @@ next_track:
}
/* Update the elapsed-time indicator */
- sound_samples_done += sample_duration;
+ sound_samples_done += framelength;
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
ci->set_elapsed(elapsed_time);
i++;
diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c
index a59b3f9..c9c691f 100644
--- a/apps/metadata/mp4.c
+++ b/apps/metadata/mp4.c
@@ -73,6 +73,9 @@
#define MP4_udta FOURCC('u', 'd', 't', 'a')
#define MP4_extra FOURCC('-', '-', '-', '-')
+/* Used to correct id3->samples, if SBR upsampling was detected in esds atom. */
+static bool SBR_upsampling_used = false;
+
/* Read the tag data from an MP4 file, storing up to buffer_size bytes in
* buffer.
*/
@@ -272,7 +275,6 @@ static bool read_mp4_esds(int fd, struct mp3entry* id3, uint32_t* size)
if (type == 5)
{
- DEBUGF("MP4: SBR\n");
unsigned int old_index = index;
sbr = true;
@@ -342,6 +344,12 @@ static bool read_mp4_esds(int fd, struct mp3entry* id3, uint32_t* size)
* decoding (parts of) the file.
*/
id3->frequency *= 2;
+
+ /* Set this to true to be able to calculate the correct runtime
+ * and bitrate. */
+ SBR_upsampling_used = true;
+
+ sbr = true;
}
}
@@ -665,6 +673,7 @@ static bool read_mp4_container(int fd, struct mp3entry* id3,
{
uint32_t subsize;
uint32_t subtype;
+ bool sbr_used;
/* Get frequency from the decoder info tag, if possible. */
lseek(fd, 2, SEEK_CUR);
@@ -676,7 +685,14 @@ static bool read_mp4_container(int fd, struct mp3entry* id3,
if (subtype == MP4_esds)
{
- read_mp4_esds(fd, id3, &size);
+ sbr_used = read_mp4_esds(fd, id3, &size);
+ if (sbr_used)
+ {
+ if (SBR_upsampling_used)
+ DEBUGF("MP4: AAC-HE, SBR upsampling\n");
+ else
+ DEBUGF("MP4: AAC-HE, SBR\n");
+ }
}
}
}
@@ -730,6 +746,7 @@ static bool read_mp4_container(int fd, struct mp3entry* id3,
bool get_mp4_metadata(int fd, struct mp3entry* id3)
{
+ SBR_upsampling_used = false;
id3->codectype = AFMT_UNKNOWN;
id3->filesize = 0;
errno = 0;
@@ -743,6 +760,12 @@ bool get_mp4_metadata(int fd, struct mp3entry* id3)
logf("Not an ALAC or AAC file");
return false;
}
+
+ /* SBR upsampling will output double amount of samples per frame. */
+ if (SBR_upsampling_used)
+ {
+ id3->samples *= 2;
+ }
id3->length = ((int64_t) id3->samples * 1000) / id3->frequency;