Skip to content

Commit

Permalink
music_mad.c: Tag detection fixes, updates and cleanups:
Browse files Browse the repository at this point in the history
- Fix APE header presence detection: APEv2 doesn't guarantee a header.
  We rely on bit31 of the flags field of the header/footer, instead.
- Add a note that the 'Extended ID3v1' thingy is non-standard: we must
  not assume any additional tags before it. (should we drop support??)
- The 'APE before ID3v1' is duplicated code (because we just return if
  we detect a TAG+ thingy): removed it.
- Add a FIXME note about handling possible double-ID3v1 tags.
- possibly a few minor tidy-ups.
  • Loading branch information
sezero committed Dec 7, 2019
1 parent f8f9ca0 commit f179e83
Showing 1 changed file with 24 additions and 48 deletions.
72 changes: 24 additions & 48 deletions music_mad.c
Expand Up @@ -170,7 +170,7 @@ static __inline__ SDL_bool is_id3v2(const unsigned char *data, int length)
}
return SDL_TRUE;
}
static __inline__ int get_id3v2_len(const unsigned char *data, long length)
static __inline__ int get_id3v2_len(const unsigned char *data, int length)
{
/* size is a 'synchsafe' integer (see above) */
int size = (int)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
Expand Down Expand Up @@ -207,11 +207,14 @@ static __inline__ SDL_bool is_apetag(const unsigned char *data, int length)
}
return SDL_TRUE;
}
static __inline__ int get_ape_len(const unsigned char *data, int datalen, Uint32 *version)
static __inline__ int get_ape_len(const unsigned char *data)
{
Uint32 flags, version;
int size = (int)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
*version = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
return size; /* caller will handle the additional v2 header length */
version = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
flags = (data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20];
if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
return size;
}

static int skip_tags(mad_data *music)
Expand All @@ -229,11 +232,10 @@ static int skip_tags(mad_data *music)
music->length -= len;
MAD_RWseek(music, 0, RW_SEEK_SET);
}
/* APE tag _might_ be at the start: read the header */
/* APE tag _might_ be at the start (discouraged
* but not forbidden, either.) read the header. */
else if (is_apetag(music->input_buffer, readsize)) {
Uint32 v;
len = get_ape_len(music->input_buffer, readsize, &v);
len += 32; /* we're at top: have a header. */
len = get_ape_len(music->input_buffer);
if (len >= music->length) return -1;
music->start += len;
music->length -= len;
Expand All @@ -249,29 +251,10 @@ static int skip_tags(mad_data *music)
if (is_id3v1(music->input_buffer, 128)) {
music->length -= 128;

/* APE tag may be before the ID3v1: read the footer */
if (music->length < 32) goto end;
MAD_RWseek(music, -32, RW_SEEK_END);
readsize = MAD_RWread(music, music->input_buffer, 1, 32);
MAD_RWseek(music, 0, RW_SEEK_SET);
if (readsize != 32) return -1;
if (is_apetag(music->input_buffer, 32)) {
Uint32 v;
len = get_ape_len(music->input_buffer, readsize, &v);
if (v == 2000U) len += 32; /* header */
if (len >= music->length) return -1;
if (v == 2000U) { /* verify header : */
MAD_RWseek(music, -len, RW_SEEK_END);
readsize = MAD_RWread(music, music->input_buffer, 1, 32);
MAD_RWseek(music, 0, RW_SEEK_SET);
if (readsize != 32) return -1;
if (!is_apetag(music->input_buffer, 32)) return -1;
}
music->length -= len;
goto end;
}
/* extended ID3v1 just before the ID3v1 tag? (unlikely) */
if (music->length < 227) goto end;
/* extended ID3v1 just before the ID3v1 tag? (unlikely)
* if found, assume no additional tags: this stupidity
* is non-standard.. */
if (music->length < 227) goto ape;
MAD_RWseek(music, -227, RW_SEEK_END);
readsize = MAD_RWread(music, music->input_buffer, 1, 227);
MAD_RWseek(music, 0, RW_SEEK_SET);
Expand All @@ -280,25 +263,19 @@ static int skip_tags(mad_data *music)
music->length -= 227;
goto end;
}

/* FIXME: handle possible double-ID3v1 tags? */
}

ape: /* APE tag may be at the end: read the footer */
if (music->length >= 32) {
MAD_RWseek(music, -32, RW_SEEK_END);
readsize = MAD_RWread(music, music->input_buffer, 1, 32);
MAD_RWseek(music, 0, RW_SEEK_SET);
if (readsize != 32) return -1;
if (is_apetag(music->input_buffer, 32)) {
Uint32 v;
len = get_ape_len(music->input_buffer, readsize, &v);
if (v == 2000U) len += 32; /* header */
len = get_ape_len(music->input_buffer);
if (len >= music->length) return -1;
if (v == 2000U) { /* verify header : */
MAD_RWseek(music, -len, RW_SEEK_END);
readsize = MAD_RWread(music, music->input_buffer, 1, 32);
MAD_RWseek(music, 0, RW_SEEK_SET);
if (readsize != 32) return -1;
if (!is_apetag(music->input_buffer, 32)) return -1;
}
music->length -= len;
}
}
Expand All @@ -325,7 +302,7 @@ read_next_frame(mad_data *mp3_mad) {
memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
read_start = mp3_mad->input_buffer + remaining;
read_size = MAD_INPUT_BUFFER_SIZE - remaining;

} else {
read_size = MAD_INPUT_BUFFER_SIZE;
read_start = mp3_mad->input_buffer;
Expand All @@ -334,22 +311,22 @@ read_next_frame(mad_data *mp3_mad) {

/* Now read additional bytes from the input file. */
read_size = MAD_RWread(mp3_mad, read_start, 1, read_size);

if (read_size <= 0) {
if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
if (read_size == 0) {
mp3_mad->status |= MS_input_eof;
} else {
mp3_mad->status |= MS_input_error;
}

/* At the end of the file, we must stuff MAD_BUFFER_GUARD
number of 0 bytes. */
memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
read_size += MAD_BUFFER_GUARD;
}
}

/* Now feed those bytes into the libmad stream. */
mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
read_size + remaining);
Expand All @@ -362,10 +339,10 @@ read_next_frame(mad_data *mp3_mad) {
if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
mad_stream_sync(&mp3_mad->stream); /* to frame seek mode */
return 0;

} else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
return 0;

} else {
mp3_mad->status |= MS_decode_error;
return 0;
Expand Down Expand Up @@ -402,7 +379,6 @@ decode_frame(mad_data *mp3_mad) {
unsigned int nchannels, nsamples;
mad_fixed_t const *left_ch, *right_ch;
unsigned char *out;
int ret;

mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
pcm = &mp3_mad->synth.pcm;
Expand Down

0 comments on commit f179e83

Please sign in to comment.