forked from len0rd/rockbox
AAC: Add support for iTunes-style gapless playback.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13636 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
93af4feae9
commit
c3206a455a
2 changed files with 102 additions and 2 deletions
|
|
@ -42,6 +42,8 @@ enum codec_status codec_main(void)
|
||||||
uint32_t sample_duration;
|
uint32_t sample_duration;
|
||||||
uint32_t sample_byte_size;
|
uint32_t sample_byte_size;
|
||||||
int file_offset;
|
int file_offset;
|
||||||
|
int framelength;
|
||||||
|
int lead_trim = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned char* buffer;
|
unsigned char* buffer;
|
||||||
static NeAACDecFrameInfo frame_info;
|
static NeAACDecFrameInfo frame_info;
|
||||||
|
|
@ -117,6 +119,11 @@ next_track:
|
||||||
sound_samples_done = 0;
|
sound_samples_done = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
lead_trim = ci->id3->lead_trim;
|
||||||
|
}
|
||||||
|
|
||||||
/* The main decoding loop */
|
/* The main decoding loop */
|
||||||
while (i < demux_res.num_sample_byte_sizes) {
|
while (i < demux_res.num_sample_byte_sizes) {
|
||||||
|
|
@ -133,6 +140,11 @@ next_track:
|
||||||
&sound_samples_done, (int*) &i)) {
|
&sound_samples_done, (int*) &i)) {
|
||||||
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
|
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
|
||||||
ci->set_elapsed(elapsed_time);
|
ci->set_elapsed(elapsed_time);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
lead_trim = ci->id3->lead_trim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ci->seek_complete();
|
ci->seek_complete();
|
||||||
}
|
}
|
||||||
|
|
@ -183,8 +195,46 @@ next_track:
|
||||||
|
|
||||||
/* Output the audio */
|
/* Output the audio */
|
||||||
ci->yield();
|
ci->yield();
|
||||||
ci->pcmbuf_insert(decoder->time_out[0], decoder->time_out[1],
|
|
||||||
frame_info.samples >> 1);
|
framelength = (frame_info.samples >> 1) - lead_trim;
|
||||||
|
|
||||||
|
if (i == demux_res.num_sample_byte_sizes - 1 && framelength > 0)
|
||||||
|
{
|
||||||
|
/* Currently limited to at most one frame of tail_trim.
|
||||||
|
* Seems to be enough.
|
||||||
|
*/
|
||||||
|
if (ci->id3->tail_trim == 0
|
||||||
|
&& sample_duration < (frame_info.samples >> 1))
|
||||||
|
{
|
||||||
|
/* Subtract lead_trim just in case we decode a file with
|
||||||
|
* only one audio frame with actual data.
|
||||||
|
*/
|
||||||
|
framelength = sample_duration - lead_trim;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
framelength -= ci->id3->tail_trim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framelength > 0)
|
||||||
|
{
|
||||||
|
ci->pcmbuf_insert(&decoder->time_out[0][lead_trim],
|
||||||
|
&decoder->time_out[1][lead_trim],
|
||||||
|
framelength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lead_trim > 0)
|
||||||
|
{
|
||||||
|
/* frame_info.samples can be 0 for the first frame */
|
||||||
|
lead_trim -= (i > 0 || frame_info.samples)
|
||||||
|
? (frame_info.samples >> 1) : sample_duration;
|
||||||
|
|
||||||
|
if (lead_trim < 0 || ci->id3->lead_trim == 0)
|
||||||
|
{
|
||||||
|
lead_trim = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the elapsed-time indicator */
|
/* Update the elapsed-time indicator */
|
||||||
sound_samples_done += sample_duration;
|
sound_samples_done += sample_duration;
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,43 @@ static long get_slong(void* buf)
|
||||||
|
|
||||||
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
|
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char* skip_space(char* str)
|
||||||
|
{
|
||||||
|
while (isspace(*str))
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long get_itunes_int32(char* value, int count)
|
||||||
|
{
|
||||||
|
static const char hexdigits[] = "0123456789ABCDEF";
|
||||||
|
const char* c;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
while (count-- > 0)
|
||||||
|
{
|
||||||
|
value = skip_space(value);
|
||||||
|
|
||||||
|
while (*value && !isspace(*value))
|
||||||
|
{
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = skip_space(value);
|
||||||
|
|
||||||
|
while (*value && ((c = strchr(hexdigits, toupper(*value))) != NULL))
|
||||||
|
{
|
||||||
|
r = (r << 4) | (c - hexdigits);
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the tag (the name-value pair) and fill id3 and buffer accordingly.
|
/* Parse the tag (the name-value pair) and fill id3 and buffer accordingly.
|
||||||
* String values to keep are written to buf. Returns number of bytes written
|
* String values to keep are written to buf. Returns number of bytes written
|
||||||
|
|
@ -1520,6 +1557,19 @@ static bool read_mp4_tags(int fd, struct mp3entry* id3,
|
||||||
{
|
{
|
||||||
read_mp4_tag_string(fd, size, &buffer, &buffer_left,
|
read_mp4_tag_string(fd, size, &buffer, &buffer_left,
|
||||||
&id3->composer);
|
&id3->composer);
|
||||||
|
}
|
||||||
|
else if (strcasecmp(tag_name, "iTunSMPB") == 0)
|
||||||
|
{
|
||||||
|
char value[TAG_VALUE_LENGTH];
|
||||||
|
char* value_p = value;
|
||||||
|
char* any;
|
||||||
|
unsigned int length = sizeof(value);
|
||||||
|
|
||||||
|
read_mp4_tag_string(fd, size, &value_p, &length, &any);
|
||||||
|
id3->lead_trim = get_itunes_int32(value, 1);
|
||||||
|
id3->tail_trim = get_itunes_int32(value, 2);
|
||||||
|
DEBUGF("AAC: lead_trim %d, tail_trim %d\n",
|
||||||
|
id3->lead_trim, id3->tail_trim);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue