stop that
parent
0f96a959d3
commit
33ea8d7496
148
source/snd_mp3.c
148
source/snd_mp3.c
|
@ -56,12 +56,12 @@ static mad_timer_t const mad_timer_zero_stub = {0, 0};
|
|||
typedef struct _mp3_priv_t
|
||||
{
|
||||
uint8_t mp3_buffer[MP3_BUFFER_SIZE];
|
||||
struct mad_stream Stream;
|
||||
struct mad_frame Frame;
|
||||
struct mad_synth Synth;
|
||||
mad_timer_t Timer;
|
||||
struct mad_stream stream;
|
||||
struct mad_frame frame;
|
||||
struct mad_synth synth;
|
||||
mad_timer_t timer;
|
||||
ptrdiff_t cursamp;
|
||||
size_t FrameCount;
|
||||
size_t frame_count;
|
||||
} mp3_priv_t;
|
||||
|
||||
/* This function merges the functions tagtype() and id3_tag_query()
|
||||
|
@ -148,21 +148,21 @@ static int mp3_inputtag(snd_stream_t *stream)
|
|||
size_t tagsize;
|
||||
|
||||
/* FIXME: This needs some more work if we are to ever
|
||||
* look at the ID3 frame. This is because the Stream
|
||||
* look at the ID3 frame. This is because the stream
|
||||
* may not be able to hold the complete ID3 frame.
|
||||
* We should consume the whole frame inside tagtype()
|
||||
* instead of outside of tagframe(). That would support
|
||||
* recovering when Stream contains less then 8-bytes (header)
|
||||
* and also when ID3v2 is bigger then Stream buffer size.
|
||||
* recovering when stream contains less then 8-bytes (header)
|
||||
* and also when ID3v2 is bigger then stream buffer size.
|
||||
* Need to pass in stream so that buffer can be
|
||||
* consumed as well as letting additional data to be
|
||||
* read in.
|
||||
*/
|
||||
remaining = p->Stream.bufend - p->Stream.next_frame;
|
||||
tagsize = mp3_tagsize(p->Stream.this_frame, remaining);
|
||||
remaining = p->stream.bufend - p->stream.next_frame;
|
||||
tagsize = mp3_tagsize(p->stream.this_frame, remaining);
|
||||
if (tagsize != 0)
|
||||
{
|
||||
mad_stream_skip(&p->Stream, tagsize);
|
||||
mad_stream_skip(&p->stream, tagsize);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ static int mp3_inputtag(snd_stream_t *stream)
|
|||
* so help libmad out and go back into frame seek mode.
|
||||
* This is true whether an ID3 tag was found or not.
|
||||
*/
|
||||
mad_stream_sync(&p->Stream);
|
||||
mad_stream_sync(&p->stream);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ static int mp3_inputdata(snd_stream_t *stream)
|
|||
size_t bytes_read;
|
||||
size_t remaining;
|
||||
|
||||
remaining = p->Stream.bufend - p->Stream.next_frame;
|
||||
remaining = p->stream.bufend - p->stream.next_frame;
|
||||
|
||||
/* libmad does not consume all the buffer it's given. Some
|
||||
* data, part of a truncated frame, is left unused at the
|
||||
|
@ -196,15 +196,15 @@ static int mp3_inputdata(snd_stream_t *stream)
|
|||
* TODO: Is 2016 bytes the size of the largest frame?
|
||||
* (448000*(1152/32000))/8
|
||||
*/
|
||||
memmove(p->mp3_buffer, p->Stream.next_frame, remaining);
|
||||
memmove(p->mp3_buffer, p->stream.next_frame, remaining);
|
||||
|
||||
bytes_read = FS_fread(p->mp3_buffer + remaining, 1,
|
||||
MP3_BUFFER_SIZE - remaining, &stream->fh);
|
||||
if (bytes_read == 0)
|
||||
return -1;
|
||||
|
||||
mad_stream_buffer(&p->Stream, p->mp3_buffer, bytes_read+remaining);
|
||||
p->Stream.error = MAD_ERROR_NONE;
|
||||
mad_stream_buffer(&p->stream, p->mp3_buffer, bytes_read+remaining);
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -214,10 +214,10 @@ static int mp3_startread(snd_stream_t *stream)
|
|||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
size_t ReadSize;
|
||||
|
||||
mad_stream_init(&p->Stream);
|
||||
mad_frame_init(&p->Frame);
|
||||
mad_synth_init(&p->Synth);
|
||||
mad_timer_reset(&p->Timer);
|
||||
mad_stream_init(&p->stream);
|
||||
mad_frame_init(&p->frame);
|
||||
mad_synth_init(&p->synth);
|
||||
mad_timer_reset(&p->timer);
|
||||
|
||||
/* Decode at least one valid frame to find out the input
|
||||
* format. The decoded frame will be saved off so that it
|
||||
|
@ -227,17 +227,17 @@ static int mp3_startread(snd_stream_t *stream)
|
|||
if (!ReadSize || FS_ferror(&stream->fh))
|
||||
return -1;
|
||||
|
||||
mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);
|
||||
mad_stream_buffer(&p->stream, p->mp3_buffer, ReadSize);
|
||||
|
||||
/* Find a valid frame before starting up. This makes sure
|
||||
* that we have a valid MP3 and also skips past ID3v2 tags
|
||||
* at the beginning of the audio file.
|
||||
*/
|
||||
p->Stream.error = MAD_ERROR_NONE;
|
||||
while (mad_frame_decode(&p->Frame,&p->Stream))
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
while (mad_frame_decode(&p->frame,&p->stream))
|
||||
{
|
||||
/* check whether input buffer needs a refill */
|
||||
if (p->Stream.error == MAD_ERROR_BUFLEN)
|
||||
if (p->stream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
if (mp3_inputdata(stream) == -1)
|
||||
return -1;/* EOF with no valid data */
|
||||
|
@ -253,33 +253,33 @@ static int mp3_startread(snd_stream_t *stream)
|
|||
* frame. In that case we can abort early without
|
||||
* scanning the whole file.
|
||||
*/
|
||||
p->Stream.error = MAD_ERROR_NONE;
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
}
|
||||
|
||||
if (p->Stream.error)
|
||||
if (p->stream.error)
|
||||
{
|
||||
Con_Printf("MP3: No valid MP3 frame found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(p->Frame.header.mode)
|
||||
switch(p->frame.header.mode)
|
||||
{
|
||||
case MAD_MODE_SINGLE_CHANNEL:
|
||||
case MAD_MODE_DUAL_CHANNEL:
|
||||
case MAD_MODE_JOINT_STEREO:
|
||||
case MAD_MODE_STEREO:
|
||||
stream->info.channels = MAD_NCHANNELS(&p->Frame.header);
|
||||
stream->info.channels = MAD_NCHANNELS(&p->frame.header);
|
||||
break;
|
||||
default:
|
||||
Con_Printf("MP3: Cannot determine number of channels\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->FrameCount = 1;
|
||||
p->frame_count = 1;
|
||||
|
||||
mad_timer_add(&p->Timer,p->Frame.header.duration);
|
||||
mad_synth_frame(&p->Synth,&p->Frame);
|
||||
stream->info.rate = p->Synth.pcm.samplerate;
|
||||
mad_timer_add(&p->timer,p->frame.header.duration);
|
||||
mad_synth_frame(&p->synth,&p->frame);
|
||||
stream->info.rate = p->synth.pcm.samplerate;
|
||||
stream->info.bits = MP3_MAD_SAMPLEBITS;
|
||||
stream->info.width = MP3_MAD_SAMPLEWIDTH;
|
||||
|
||||
|
@ -288,7 +288,7 @@ static int mp3_startread(snd_stream_t *stream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Read up to len samples from p->Synth
|
||||
/* Read up to len samples from p->synth
|
||||
* If needed, read some more MP3 data, decode them and synth them
|
||||
* Place in buf[].
|
||||
* Return number of samples read. */
|
||||
|
@ -301,14 +301,14 @@ static int mp3_decode(snd_stream_t *stream, byte *buf, int len)
|
|||
|
||||
do
|
||||
{
|
||||
x = (p->Synth.pcm.length - p->cursamp) * stream->info.channels;
|
||||
x = (p->synth.pcm.length - p->cursamp) * stream->info.channels;
|
||||
donow = q_min(len, x);
|
||||
i = 0;
|
||||
while (i < donow)
|
||||
{
|
||||
for (chan = 0; chan < stream->info.channels; chan++)
|
||||
{
|
||||
sample = p->Synth.pcm.samples[chan][p->cursamp];
|
||||
sample = p->synth.pcm.samples[chan][p->cursamp];
|
||||
/* convert from fixed to int16_t,
|
||||
* write in host-endian format. */
|
||||
if (sample <= -MAD_F_ONE)
|
||||
|
@ -339,7 +339,7 @@ static int mp3_decode(snd_stream_t *stream, byte *buf, int len)
|
|||
break;
|
||||
|
||||
/* check whether input buffer needs a refill */
|
||||
if (p->Stream.error == MAD_ERROR_BUFLEN)
|
||||
if (p->stream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
if (mp3_inputdata(stream) == -1)
|
||||
{
|
||||
|
@ -349,28 +349,28 @@ static int mp3_decode(snd_stream_t *stream, byte *buf, int len)
|
|||
}
|
||||
}
|
||||
|
||||
if (mad_frame_decode(&p->Frame, &p->Stream))
|
||||
if (mad_frame_decode(&p->frame, &p->stream))
|
||||
{
|
||||
if (MAD_RECOVERABLE(p->Stream.error))
|
||||
if (MAD_RECOVERABLE(p->stream.error))
|
||||
{
|
||||
mp3_inputtag(stream);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->Stream.error == MAD_ERROR_BUFLEN)
|
||||
if (p->stream.error == MAD_ERROR_BUFLEN)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
Con_Printf("MP3: unrecoverable frame level error (%s)\n",
|
||||
mad_stream_errorstr(&p->Stream));
|
||||
mad_stream_errorstr(&p->stream));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->FrameCount++;
|
||||
mad_timer_add(&p->Timer, p->Frame.header.duration);
|
||||
mad_synth_frame(&p->Synth, &p->Frame);
|
||||
p->frame_count++;
|
||||
mad_timer_add(&p->timer, p->frame.header.duration);
|
||||
mad_synth_frame(&p->synth, &p->frame);
|
||||
p->cursamp = 0;
|
||||
} while (1);
|
||||
|
||||
|
@ -381,9 +381,9 @@ static int mp3_stopread(snd_stream_t *stream)
|
|||
{
|
||||
mp3_priv_t *p = (mp3_priv_t*) stream->priv;
|
||||
|
||||
mad_synth_finish(&p->Synth);
|
||||
mad_frame_finish(&p->Frame);
|
||||
mad_stream_finish(&p->Stream);
|
||||
mad_synth_finish(&p->synth);
|
||||
mad_frame_finish(&p->frame);
|
||||
mad_stream_finish(&p->stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -441,63 +441,63 @@ static void S_MP3_CodecCloseStream (snd_stream_t *stream)
|
|||
static int S_MP3_CodecRewindStream (snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
size_t initial_bitrate = p->Frame.header.bitrate;
|
||||
size_t initial_bitrate = p->frame.header.bitrate;
|
||||
size_t tagsize = 0, consumed = 0;
|
||||
int vbr = 0; /* Variable Bit Rate, bool */
|
||||
bool depadded = false;
|
||||
|
||||
/* Reset all */
|
||||
FS_rewind(&stream->fh);
|
||||
mad_timer_reset(&p->Timer);
|
||||
p->FrameCount = 0;
|
||||
mad_timer_reset(&p->timer);
|
||||
p->frame_count = 0;
|
||||
|
||||
/* They where opened in startread */
|
||||
mad_synth_finish(&p->Synth);
|
||||
mad_frame_finish(&p->Frame);
|
||||
mad_stream_finish(&p->Stream);
|
||||
mad_synth_finish(&p->synth);
|
||||
mad_frame_finish(&p->frame);
|
||||
mad_stream_finish(&p->stream);
|
||||
|
||||
mad_stream_init(&p->Stream);
|
||||
mad_frame_init(&p->Frame);
|
||||
mad_synth_init(&p->Synth);
|
||||
mad_stream_init(&p->stream);
|
||||
mad_frame_init(&p->frame);
|
||||
mad_synth_init(&p->synth);
|
||||
|
||||
while (1) /* Read data from the MP3 file */
|
||||
{
|
||||
int bytes_read, padding = 0;
|
||||
size_t leftover = p->Stream.bufend - p->Stream.next_frame;
|
||||
size_t leftover = p->stream.bufend - p->stream.next_frame;
|
||||
|
||||
memcpy(p->mp3_buffer, p->Stream.this_frame, leftover);
|
||||
memcpy(p->mp3_buffer, p->stream.this_frame, leftover);
|
||||
bytes_read = FS_fread(p->mp3_buffer + leftover, (size_t) 1,
|
||||
MP3_BUFFER_SIZE - leftover, &stream->fh);
|
||||
if (bytes_read <= 0)
|
||||
{
|
||||
Con_DPrintf("seek failure. unexpected EOF (frames=%u leftover=%u)\n",
|
||||
p->FrameCount, leftover);
|
||||
p->frame_count, leftover);
|
||||
break;
|
||||
}
|
||||
for ( ; !depadded && padding < bytes_read && !p->mp3_buffer[padding]; ++padding)
|
||||
;
|
||||
depadded = true;
|
||||
mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + bytes_read - padding);
|
||||
mad_stream_buffer(&p->stream, p->mp3_buffer + padding, leftover + bytes_read - padding);
|
||||
|
||||
while (1) /* Decode frame headers */
|
||||
{
|
||||
static uint16_t samples;
|
||||
p->Stream.error = MAD_ERROR_NONE;
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
|
||||
/* Not an audio frame */
|
||||
if (mad_header_decode(&p->Frame.header, &p->Stream) == -1)
|
||||
if (mad_header_decode(&p->frame.header, &p->stream) == -1)
|
||||
{
|
||||
if (p->Stream.error == MAD_ERROR_BUFLEN)
|
||||
if (p->stream.error == MAD_ERROR_BUFLEN)
|
||||
break; /* Normal behaviour; get some more data from the file */
|
||||
if (!MAD_RECOVERABLE(p->Stream.error))
|
||||
if (!MAD_RECOVERABLE(p->stream.error))
|
||||
{
|
||||
Con_DPrintf("unrecoverable MAD error\n");
|
||||
break;
|
||||
}
|
||||
if (p->Stream.error == MAD_ERROR_LOSTSYNC)
|
||||
if (p->stream.error == MAD_ERROR_LOSTSYNC)
|
||||
{
|
||||
size_t available = (p->Stream.bufend - p->Stream.this_frame);
|
||||
tagsize = mp3_tagsize(p->Stream.this_frame, (size_t) available);
|
||||
size_t available = (p->stream.bufend - p->stream.this_frame);
|
||||
tagsize = mp3_tagsize(p->stream.this_frame, (size_t) available);
|
||||
if (tagsize)
|
||||
{ /* It's some ID3 tags, so just skip */
|
||||
if (tagsize >= available)
|
||||
|
@ -507,7 +507,7 @@ static int S_MP3_CodecRewindStream (snd_stream_t *stream)
|
|||
SEEK_CUR);
|
||||
depadded = false;
|
||||
}
|
||||
mad_stream_skip(&p->Stream, q_min(tagsize, available));
|
||||
mad_stream_skip(&p->stream, q_min(tagsize, available));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -521,16 +521,16 @@ static int S_MP3_CodecRewindStream (snd_stream_t *stream)
|
|||
continue;
|
||||
}
|
||||
|
||||
consumed += p->Stream.next_frame - p->Stream.this_frame;
|
||||
vbr |= (p->Frame.header.bitrate != initial_bitrate);
|
||||
consumed += p->stream.next_frame - p->stream.this_frame;
|
||||
vbr |= (p->frame.header.bitrate != initial_bitrate);
|
||||
|
||||
samples = 32 * MAD_NSBSAMPLES(&p->Frame.header);
|
||||
samples = 32 * MAD_NSBSAMPLES(&p->frame.header);
|
||||
|
||||
p->FrameCount++;
|
||||
mad_timer_add(&p->Timer, p->Frame.header.duration);
|
||||
p->frame_count++;
|
||||
mad_timer_add(&p->timer, p->frame.header.duration);
|
||||
|
||||
mad_frame_decode(&p->Frame,&p->Stream);
|
||||
mad_synth_frame(&p->Synth, &p->Frame);
|
||||
mad_frame_decode(&p->frame,&p->stream);
|
||||
mad_synth_frame(&p->synth, &p->frame);
|
||||
p->cursamp = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue