diff options
| -rw-r--r-- | apps/codecs/aac.c | 29 | ||||
| -rw-r--r-- | apps/metadata/mp4.c | 27 |
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; |