X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fmp3decoder.cpp;h=cc3235683db098cc5782ef11ba2b7094678f9bb1;hb=1e7141871d33e3e184456ba063fcf3448a8cc12a;hp=a717cf4b3b4dde400cac7b234d4cecf6db822c1d;hpb=0e266d73f9aab89410c736e969eaa51ef914acf1;p=libs%2Fal.git diff --git a/source/mp3decoder.cpp b/source/mp3decoder.cpp index a717cf4..cc32356 100644 --- a/source/mp3decoder.cpp +++ b/source/mp3decoder.cpp @@ -54,8 +54,10 @@ Mp3Decoder::Mp3Decoder(IO::Seekable &io): try { - decode_frame(); - format = (priv->frame.header.mode==MAD_MODE_SINGLE_CHANNEL ? MONO16 : STEREO16); + if(!fill_input() || !decode(false)) + throw runtime_error("no mp3 data"); + + format = create_format(2, MAD_NCHANNELS(&priv->frame.header)); freq = priv->frame.header.samplerate; } catch(...) @@ -71,6 +73,7 @@ Mp3Decoder::~Mp3Decoder() mad_synth_finish(&priv->synth); mad_frame_finish(&priv->frame); mad_stream_finish(&priv->stream); + delete priv; } bool Mp3Decoder::detect(const string &sig) @@ -81,27 +84,47 @@ bool Mp3Decoder::detect(const string &sig) static const char id3_sig[] = { 'I', 'D', '3' }; if(sig.size()stream, 0, 0); + fill_input(); + if(!pos) + { + priv->synth.pcm.length = 0; + return; + } + + while(decode(false)) + { + unsigned frame_len = 32*MAD_NSBSAMPLES(&priv->frame.header); + if(frame_len>pos) + { + decode(true); + read_pos = pos; + break; + } + + pos -= frame_len; + } } unsigned Mp3Decoder::read(char *buf, unsigned len) { - unsigned nchan = (format==STEREO16 ? 2 : 1); + unsigned nchan = get_n_channels(format); mad_pcm &pcm = priv->synth.pcm; unsigned pos = 0; while(pos+2*nchan<=len) { - if(read_pos>=pcm.length) - { - if(!decode_frame()) - break; - } + if(read_pos>=pcm.length && !decode(true)) + break; for(unsigned i=0; iframe, &priv->stream); + else + return !mad_header_decode(&priv->frame.header, &priv->stream); +} + +bool Mp3Decoder::decode(bool full) { - while(1) + while(!try_decode(full)) { - if(!priv->stream.buffer || priv->stream.error==MAD_ERROR_BUFLEN) + if(priv->stream.error==MAD_ERROR_BUFLEN) + { if(!fill_input()) return false; - - if(!mad_frame_decode(&priv->frame, &priv->stream)) - { - mad_synth_frame(&priv->synth, &priv->frame); - read_pos = 0; - return true; } - - if(priv->stream.error==MAD_ERROR_BUFLEN) - continue; else if(!MAD_RECOVERABLE(priv->stream.error)) throw mp3_error("mad_frame_decode", priv->stream.error); } + + if(full) + { + read_pos = 0; + mad_synth_frame(&priv->synth, &priv->frame); + } + + return true; } } // namespace AL