aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2017-02-25 13:08:53 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2017-02-25 13:08:53 +0000
commit6bb25ee7ef5962dd599a6f27e466bb0eea83c207 (patch)
treeddb38b145bab38f8e777383a7f94f5b048580044 /src/plugins/Input
parent53ac1b9923438a7b53e5a27c28cf48bb2b91af5d (diff)
downloadqmmp-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/plugins/Input')
-rw-r--r--src/plugins/Input/mad/decoder_mad.cpp154
-rw-r--r--src/plugins/Input/mad/decoder_mad.h34
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;
+
};