aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2013-10-07 12:18:16 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2013-10-07 12:18:16 +0000
commit6a8185ef6679cc329a5fde14bfe97eadca0d2f91 (patch)
treeb3a862160efc964f10ca3690523b47a55b054c2f /src/plugins/Input
parent803d0ca7c17bfddde8d74ab914ebc519f66bb50d (diff)
downloadqmmp-6a8185ef6679cc329a5fde14bfe97eadca0d2f91.tar.gz
qmmp-6a8185ef6679cc329a5fde14bfe97eadca0d2f91.tar.bz2
qmmp-6a8185ef6679cc329a5fde14bfe97eadca0d2f91.zip
prepare for new replaygain implementation
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@3753 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Input')
-rw-r--r--src/plugins/Input/mad/decoder_mad.cpp140
-rw-r--r--src/plugins/Input/mad/decoder_mad.h3
2 files changed, 98 insertions, 45 deletions
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp
index 331453362..b4087c06b 100644
--- a/src/plugins/Input/mad/decoder_mad.cpp
+++ b/src/plugins/Input/mad/decoder_mad.cpp
@@ -340,48 +340,18 @@ int DecoderMAD::bitrate()
qint64 DecoderMAD::read(char *data, qint64 size)
{
- forever
- {
- if(((m_stream.error == MAD_ERROR_BUFLEN) || !m_stream.buffer) && !m_eof)
- {
- m_eof = !fillBuffer();
- }
- if(mad_frame_decode(&m_frame, &m_stream) < 0)
- {
- switch((int) m_stream.error)
- {
- case MAD_ERROR_LOSTSYNC:
- {
- //skip ID3v2 tag
- uint tagSize = findID3v2((uchar *)m_stream.this_frame,
- (ulong) (m_stream.bufend - m_stream.this_frame));
- if (tagSize > 0)
- {
- mad_stream_skip(&m_stream, tagSize);
- qDebug("DecoderMAD: %d bytes skipped", tagSize);
- }
- continue;
- }
- case MAD_ERROR_BUFLEN:
- if(m_eof)
- return 0;
- continue;
- default:
- if (!MAD_RECOVERABLE(m_stream.error))
- return 0;
- else
- continue;
- }
- }
- if(m_skip_frames)
- {
- m_skip_frames--;
- continue;
- }
- mad_synth_frame(&m_synth, &m_frame);
+ if(decodeFrame())
return madOutput(data, size);
- }
+ return 0;
}
+
+qint64 DecoderMAD::read(float *data, qint64 samples)
+{
+ if(decodeFrame())
+ return madOutputFloat(data, samples);
+ return 0;
+}
+
void DecoderMAD::seek(qint64 pos)
{
if(m_totalTime > 0)
@@ -508,12 +478,58 @@ long DecoderMAD::audio_linear_round(unsigned int bits, mad_fixed_t sample)
return sample >> (MAD_F_FRACBITS + 1 - bits);
}
+bool DecoderMAD::decodeFrame()
+{
+ forever
+ {
+ if(((m_stream.error == MAD_ERROR_BUFLEN) || !m_stream.buffer) && !m_eof)
+ {
+ m_eof = !fillBuffer();
+ }
+ if(mad_frame_decode(&m_frame, &m_stream) < 0)
+ {
+ switch((int) m_stream.error)
+ {
+ case MAD_ERROR_LOSTSYNC:
+ {
+ //skip ID3v2 tag
+ uint tagSize = findID3v2((uchar *)m_stream.this_frame,
+ (ulong) (m_stream.bufend - m_stream.this_frame));
+ if (tagSize > 0)
+ {
+ mad_stream_skip(&m_stream, tagSize);
+ qDebug("DecoderMAD: %d bytes skipped", tagSize);
+ }
+ continue;
+ }
+ case MAD_ERROR_BUFLEN:
+ if(m_eof)
+ return false;
+ continue;
+ default:
+ if (!MAD_RECOVERABLE(m_stream.error))
+ return false;
+ else
+ continue;
+ }
+ }
+ if(m_skip_frames)
+ {
+ m_skip_frames--;
+ continue;
+ }
+ mad_synth_frame(&m_synth, &m_frame);
+ break;
+ }
+ return true;
+}
+
qint64 DecoderMAD::madOutput(char *data, qint64 size)
{
- unsigned int samples, channels;
+ unsigned int samples_per_channel, channels;
mad_fixed_t const *left, *right;
- samples = m_synth.pcm.length;
+ samples_per_channel = m_synth.pcm.length;
channels = m_synth.pcm.channels;
left = m_synth.pcm.samples[0];
right = m_synth.pcm.samples[1];
@@ -521,13 +537,13 @@ qint64 DecoderMAD::madOutput(char *data, qint64 size)
m_output_at = 0;
m_output_bytes = 0;
- if(samples * channels * 2 > size)
+ if(samples_per_channel * channels * 2 > size)
{
qWarning("DecoderMad: input buffer is too small");
- samples = size / channels / 2;
+ samples_per_channel = size / channels / 2;
}
- while (samples--)
+ while (samples_per_channel--)
{
signed int sample;
#ifdef USE_DITHERING
@@ -553,3 +569,37 @@ qint64 DecoderMAD::madOutput(char *data, qint64 size)
}
return m_output_bytes;
}
+
+qint64 DecoderMAD::madOutputFloat(float *data, qint64 samples)
+{
+ float *data_it = data;
+ unsigned int samples_per_channel, channels;
+ mad_fixed_t const *left, *right;
+
+ samples_per_channel = m_synth.pcm.length;
+ channels = m_synth.pcm.channels;
+ left = m_synth.pcm.samples[0];
+ right = m_synth.pcm.samples[1];
+ m_bitrate = m_frame.header.bitrate / 1000;
+ m_output_at = 0;
+ m_output_bytes = 0;
+ qint64 output_samples = 0;
+
+ if(samples_per_channel * channels > samples)
+ {
+ qWarning("DecoderMad: input buffer is too small");
+ samples_per_channel = samples / channels;
+ }
+
+ while (samples_per_channel--)
+ {
+ *data_it++ = mad_f_todouble(*left++);
+ output_samples++;
+ if (channels == 2)
+ {
+ *data_it++ = mad_f_todouble(*right++);
+ output_samples++;
+ }
+ }
+ return output_samples;
+}
diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h
index 002caa53d..d15508848 100644
--- a/src/plugins/Input/mad/decoder_mad.h
+++ b/src/plugins/Input/mad/decoder_mad.h
@@ -46,11 +46,14 @@ public:
qint64 totalTime();
int bitrate();
qint64 read(char *data, qint64 size);
+ qint64 read(float *data, qint64 samples);
void seek(qint64);
private:
// helper functions
+ bool decodeFrame();
qint64 madOutput(char *data, qint64 size);
+ qint64 madOutputFloat(float *data, qint64 samples);
bool fillBuffer();
void deinit();
bool findHeader();