diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2017-02-25 13:08:53 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2017-02-25 13:08:53 +0000 |
| commit | 6bb25ee7ef5962dd599a6f27e466bb0eea83c207 (patch) | |
| tree | ddb38b145bab38f8e777383a7f94f5b048580044 /src | |
| parent | 53ac1b9923438a7b53e5a27c28cf48bb2b91af5d (diff) | |
| download | qmmp-6bb25ee7ef5962dd599a6f27e466bb0eea83c207.tar.gz qmmp-6bb25ee7ef5962dd599a6f27e466bb0eea83c207.tar.bz2 qmmp-6bb25ee7ef5962dd599a6f27e466bb0eea83c207.zip | |
mad: added lame header support (#138)
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@7054 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src')
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.cpp | 154 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.h | 34 |
2 files changed, 153 insertions, 35 deletions
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp index 7c1339ece..5e1f392ca 100644 --- a/src/plugins/Input/mad/decoder_mad.cpp +++ b/src/plugins/Input/mad/decoder_mad.cpp @@ -3,7 +3,7 @@ * * * Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com> * * Copyright (C) 2000-2004 Robert Leslie <rob@mars.org> * - * Copyright (C) 2009-2013 Ilya Kotov forkotov02@hotmail.ru * + * Copyright (C) 2009-2017 Ilya Kotov forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -29,6 +29,8 @@ #include "decoder_mad.h" #define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g') +#define XING_MAGIC2 (('I' << 24) | ('n' << 16) | ('f' << 8) | 'o') +#define LAME_MAGIC (('L' << 24) | ('A' << 16) | ('M' << 8) | 'E') #define INPUT_BUFFER_SIZE (32*1024) DecoderMAD::DecoderMAD(QIODevice *i) : Decoder(i) @@ -43,6 +45,8 @@ DecoderMAD::DecoderMAD(QIODevice *i) : Decoder(i) m_input_bytes = 0; m_skip_frames = 0; m_eof = false; + m_skip_bytes = 0; + m_play_bytes = -1; } DecoderMAD::~DecoderMAD() @@ -124,64 +128,104 @@ void DecoderMAD::deinit() m_input_bytes = 0; m_skip_frames = 0; m_eof = false; + if(m_xing.lame) + { + delete m_xing.lame; + m_xing.lame = 0; + } } bool DecoderMAD::findXingHeader(struct mad_bitptr ptr, unsigned int bitlen) { - if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC) - goto fail; + if (bitlen < 64) + return false; + + quint32 xing_magic = mad_bit_read(&ptr, 32); + if(xing_magic != XING_MAGIC && xing_magic != XING_MAGIC2) + return false; - xing.flags = mad_bit_read(&ptr, 32); + m_xing.flags = mad_bit_read(&ptr, 32); bitlen -= 64; - if (xing.flags & XING_FRAMES) + if (m_xing.flags & XING_FRAMES) { if (bitlen < 32) - goto fail; + return false; - xing.frames = mad_bit_read(&ptr, 32); + m_xing.frames = mad_bit_read(&ptr, 32); bitlen -= 32; + + if(!m_xing.frames) + { + qDebug("DecoderMAD: invalid xing header (zero number of frames)"); + return false; + } } - if (xing.flags & XING_BYTES) + if (m_xing.flags & XING_BYTES) { if (bitlen < 32) - goto fail; + return false; - xing.bytes = mad_bit_read(&ptr, 32); + m_xing.bytes = mad_bit_read(&ptr, 32); bitlen -= 32; + + if(!m_xing.bytes) + { + qDebug("DecoderMAD: invalid xing header (zero number of bytes)"); + return false; + } } - if (xing.flags & XING_TOC) + if (m_xing.flags & XING_TOC) { - int i; - if (bitlen < 800) - goto fail; + return false; - for (i = 0; i < 100; ++i) - xing.toc[i] = mad_bit_read(&ptr, 8); + for (int i = 0; i < 100; ++i) + m_xing.toc[i] = mad_bit_read(&ptr, 8); bitlen -= 800; } - if (xing.flags & XING_SCALE) + if (m_xing.flags & XING_SCALE) { if (bitlen < 32) - goto fail; + return false; - xing.scale = mad_bit_read(&ptr, 32); + m_xing.scale = mad_bit_read(&ptr, 32); bitlen -= 32; } + m_xing.lame = findLameHeader(ptr, bitlen); return true; +} + +DecoderMAD::LameHeader* DecoderMAD::findLameHeader(mad_bitptr ptr, unsigned int bitlen) +{ + if(bitlen < 272) + return 0; + + if(mad_bit_read (&ptr, 32) != LAME_MAGIC) + return 0; + + LameHeader header; + mad_bit_skip (&ptr, 40); //version + + header.revision = mad_bit_read (&ptr, 4); + if (header.revision == 15) + return 0; -fail: - xing.flags = 0; - xing.frames = 0; - xing.bytes = 0; - xing.scale = 0; - return false; + mad_bit_skip(&ptr, 12); //VBR,Lowpass filter value + header.peak = mad_bit_read(&ptr, 32) << 5; //Peak amplitude + mad_bit_skip(&ptr, 32); //Replay Gain + mad_bit_skip(&ptr, 16); //Encoding flags, ATH Type, bitrate + header.start_delay = mad_bit_read (&ptr, 12); //Start delay + header.end_padding = mad_bit_read (&ptr, 12); //End padding + mad_bit_skip (&ptr, 8); //Misc + header.gain = mad_bit_read (&ptr, 8); //MP3 Gain + mad_bit_skip (&ptr, 64); //Preset and surroud info, MusicLength, Music CRC + return new LameHeader(header); } bool DecoderMAD::findHeader() @@ -253,12 +297,22 @@ bool DecoderMAD::findHeader() { is_vbr = true; - qDebug ("DecoderMAD: Xing header detected"); + qDebug("DecoderMAD: Xing header found"); - if (xing.flags & XING_FRAMES) + if (m_xing.flags & XING_FRAMES) { has_xing = true; - count = xing.frames; + count = m_xing.frames; + + if(m_xing.lame) + { + qDebug("DecoderMAD: LAME header found"); + m_skip_bytes = m_xing.lame->start_delay * sizeof(float) * MAD_NCHANNELS(&header); + m_play_bytes = (m_xing.frames * 1152 - m_xing.lame->start_delay - m_xing.lame->end_padding) * + sizeof(float) * MAD_NCHANNELS(&header); + qDebug("DecoderMAD: samples to skip: %d, padding: %d", + m_xing.lame->start_delay, m_xing.lame->end_padding); + } break; } } @@ -322,9 +376,45 @@ int DecoderMAD::bitrate() const qint64 DecoderMAD::read(unsigned char *data, qint64 size) { - if(decodeFrame()) - return madOutputFloat((float*)data, size / sizeof(float)) * sizeof(float); - return 0; + while(m_skip_bytes > 0) + { + if(!decodeFrame()) + return 0; + + qint64 l = madOutputFloat((float*)data, size / sizeof(float)) * sizeof(float); + + if(m_skip_bytes > l) + { + m_skip_bytes -= l; + continue; + } + else if(m_skip_bytes < l) + { + l -= m_skip_bytes; + memmove(data, data + m_skip_bytes, l); + m_skip_bytes = 0; + m_play_bytes -= l; + return l; + } + } + + if(!decodeFrame()) + return 0; + + qint64 l = madOutputFloat((float*)data, size / sizeof(float)) * sizeof(float); + + if(m_play_bytes > 0) + { + if(m_play_bytes > l) + m_play_bytes -= l; + else + { + l -= m_play_bytes; + m_play_bytes = 0; + } + + } + return l; } void DecoderMAD::seek(qint64 pos) @@ -340,6 +430,8 @@ void DecoderMAD::seek(qint64 pos) m_input_bytes = 0; m_stream.next_frame = 0; m_skip_frames = 2; + m_skip_bytes = 0; + m_play_bytes = -1; } } diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h index d74754a38..c1dcd84c9 100644 --- a/src/plugins/Input/mad/decoder_mad.h +++ b/src/plugins/Input/mad/decoder_mad.h @@ -3,7 +3,7 @@ * * * Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com> * * Copyright (C) 2000-2004 Robert Leslie <rob@mars.org> * - * Copyright (C) 2009-2012 Ilya Kotov forkotov02@hotmail.ru * + * Copyright (C) 2009-2017 Ilya Kotov forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -49,13 +49,24 @@ public: void seek(qint64); private: + //LAME header + struct LameHeader + { + unsigned char revision; + unsigned char flags; + mad_fixed_t peak; + unsigned short start_delay; + unsigned short end_padding; + qint8 gain; + }; // helper functions bool decodeFrame(); qint64 madOutputFloat(float *data, qint64 samples); bool fillBuffer(); void deinit(); bool findHeader(); - bool findXingHeader(struct mad_bitptr, unsigned int); + bool findXingHeader(struct mad_bitptr, unsigned int bitlen); + LameHeader *findLameHeader(struct mad_bitptr ptr, unsigned int bitlen); uint findID3v2(uchar *data, ulong size); bool m_inited, m_eof; qint64 m_totalTime; @@ -68,14 +79,27 @@ private: qint64 m_input_bytes; // MAD decoder - struct + + //xing header + struct XingHeader { int flags; unsigned long frames; unsigned long bytes; unsigned char toc[100]; long scale; - } xing; + LameHeader *lame; + + XingHeader() + { + flags = 0; + frames = 0; + bytes = 0; + scale = 0; + lame = 0; + } + }; + XingHeader m_xing; enum { @@ -88,6 +112,8 @@ private: struct mad_stream m_stream; struct mad_frame m_frame; struct mad_synth m_synth; + qint64 m_skip_bytes, m_play_bytes; + }; |
