aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2015-12-27 17:44:16 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2015-12-27 17:44:16 +0000
commitd55e5c3b1bd791f0f579315c30bf14064eff5824 (patch)
tree212315e4157bcf4accd64994a083599151c8bc40 /src
parent78b5e1b27f7952bad19b53cdb6d0f371acb22ef2 (diff)
downloadqmmp-d55e5c3b1bd791f0f579315c30bf14064eff5824.tar.gz
qmmp-d55e5c3b1bd791f0f579315c30bf14064eff5824.tar.bz2
qmmp-d55e5c3b1bd791f0f579315c30bf14064eff5824.zip
using float output in the mpeg and vorbis plugins
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@5917 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src')
-rw-r--r--src/plugins/Input/mad/decoder_mad.cpp148
-rw-r--r--src/plugins/Input/mad/decoder_mad.h21
-rw-r--r--src/plugins/Input/vorbis/decoder_vorbis.cpp39
-rw-r--r--src/plugins/Input/vorbis/decoder_vorbis.h5
-rw-r--r--src/qmmp/decoder.cpp8
-rw-r--r--src/qmmp/decoder.h10
6 files changed, 18 insertions, 213 deletions
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp
index c17f14f42..69a4ef859 100644
--- a/src/plugins/Input/mad/decoder_mad.cpp
+++ b/src/plugins/Input/mad/decoder_mad.cpp
@@ -30,7 +30,6 @@
#define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
#define INPUT_BUFFER_SIZE (32*1024)
-#define USE_DITHERING
DecoderMAD::DecoderMAD(QIODevice *i) : Decoder(i)
{
@@ -42,20 +41,8 @@ DecoderMAD::DecoderMAD(QIODevice *i) : Decoder(i)
m_len = 0;
m_input_buf = 0;
m_input_bytes = 0;
- m_output_bytes = 0;
- m_output_at = 0;
m_skip_frames = 0;
m_eof = false;
-
- m_left_dither.random = 0;
- m_left_dither.error[0] = 0;
- m_left_dither.error[1] = 0;
- m_left_dither.error[2] = 0;
-
- m_right_dither.random = 0;
- m_right_dither.error[0] = 0;
- m_right_dither.error[1] = 0;
- m_right_dither.error[2] = 0;
}
DecoderMAD::~DecoderMAD()
@@ -78,8 +65,6 @@ bool DecoderMAD::initialize()
m_freq = 0;
m_len = 0;
m_input_bytes = 0;
- m_output_bytes = 0;
- m_output_at = 0;
if (!input())
{
@@ -125,12 +110,11 @@ bool DecoderMAD::initialize()
map << Qmmp::CHAN_FRONT_LEFT;
else
map << Qmmp::CHAN_FRONT_LEFT << Qmmp::CHAN_FRONT_RIGHT;
- configure(m_freq, map, Qmmp::PCM_S16LE);
+ configure(m_freq, map, Qmmp::PCM_FLOAT);
m_inited = true;
return true;
}
-
void DecoderMAD::deinit()
{
if (!m_inited)
@@ -147,8 +131,6 @@ void DecoderMAD::deinit()
m_freq = 0;
m_len = 0;
m_input_bytes = 0;
- m_output_bytes = 0;
- m_output_at = 0;
m_skip_frames = 0;
m_eof = false;
}
@@ -346,14 +328,7 @@ int DecoderMAD::bitrate()
qint64 DecoderMAD::read(unsigned char *data, qint64 size)
{
if(decodeFrame())
- return madOutput(data, size);
- return 0;
-}
-
-qint64 DecoderMAD::read(float *data, qint64 samples)
-{
- if(decodeFrame())
- return madOutputFloat(data, samples);
+ return madOutputFloat((float*)data, size / sizeof(float)) * sizeof(float);
return 0;
}
@@ -413,77 +388,6 @@ uint DecoderMAD::findID3v2(uchar *data, ulong size) //retuns ID3v2 tag size
return 0;
}
-unsigned long DecoderMAD::prng(unsigned long state) // 32-bit pseudo-random number generator
-{
- return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
-}
-
-long DecoderMAD::audio_linear_dither(unsigned int bits, mad_fixed_t sample,
- struct audio_dither *dither)
-{
- unsigned int scalebits;
- mad_fixed_t output, mask, random;
-
- /* noise shape */
- sample += dither->error[0] - dither->error[1] + dither->error[2];
-
- dither->error[2] = dither->error[1];
- dither->error[1] = dither->error[0] / 2;
-
- /* bias */
- output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1));
-
- scalebits = MAD_F_FRACBITS + 1 - bits;
- mask = (1L << scalebits) - 1;
-
- /* dither */
- random = prng(dither->random);
- output += (random & mask) - (dither->random & mask);
-
- dither->random = random;
-
- /* clip */
- if (output > CLIP_MAX)
- {
- output = CLIP_MAX;
-
- if (sample > CLIP_MAX)
- sample = CLIP_MAX;
- }
- else if (output < CLIP_MIN)
- {
- output = CLIP_MIN;
-
- if (sample < CLIP_MIN)
- sample = CLIP_MIN;
- }
-
- /* quantize */
- output &= ~mask;
-
- /* error feedback */
- dither->error[0] = sample - output;
-
- /* scale */
- return output >> scalebits;
-}
-
-//generic linear sample quantize routine
-long DecoderMAD::audio_linear_round(unsigned int bits, mad_fixed_t sample)
-{
- /* round */
- sample += (1L << (MAD_F_FRACBITS - bits));
-
- /* clip */
- if (sample > CLIP_MAX)
- sample = CLIP_MAX;
- else if (sample < CLIP_MIN)
- sample = CLIP_MIN;
-
- /* quantize and scale */
- return sample >> (MAD_F_FRACBITS + 1 - bits);
-}
-
bool DecoderMAD::decodeFrame()
{
forever
@@ -530,52 +434,6 @@ bool DecoderMAD::decodeFrame()
return true;
}
-qint64 DecoderMAD::madOutput(unsigned char *data, qint64 size)
-{
- 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;
-
- if(samples_per_channel * channels * 2 > size)
- {
- qWarning("DecoderMad: input buffer is too small");
- samples_per_channel = size / channels / 2;
- }
-
- while (samples_per_channel--)
- {
- signed int sample;
-#ifdef USE_DITHERING
- sample = audio_linear_dither(16, *left++, &m_left_dither);
-#else
- sample = audio_linear_round(16, *left++);
-#endif
- *(data + m_output_at++) = ((sample >> 0) & 0xff);
- *(data + m_output_at++) = ((sample >> 8) & 0xff);
- m_output_bytes += 2;
-
- if (channels == 2)
- {
-#ifdef USE_DITHERING
- sample = audio_linear_dither(16, *right++, &m_right_dither);
-#else
- sample = audio_linear_round(16, *right++);
-#endif
- *(data + m_output_at++) = ((sample >> 0) & 0xff);
- *(data + m_output_at++) = ((sample >> 8) & 0xff);
- m_output_bytes += 2;
- }
- }
- return m_output_bytes;
-}
-
qint64 DecoderMAD::madOutputFloat(float *data, qint64 samples)
{
float *data_it = data;
@@ -587,8 +445,6 @@ qint64 DecoderMAD::madOutputFloat(float *data, qint64 samples)
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)
diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h
index a846a96ed..73dc43f3b 100644
--- a/src/plugins/Input/mad/decoder_mad.h
+++ b/src/plugins/Input/mad/decoder_mad.h
@@ -46,13 +46,11 @@ public:
qint64 totalTime();
int bitrate();
qint64 read(unsigned char *data, qint64 size);
- qint64 read(float *data, qint64 samples);
void seek(qint64);
private:
// helper functions
bool decodeFrame();
- qint64 madOutput(unsigned char *data, qint64 size);
qint64 madOutputFloat(float *data, qint64 samples);
bool fillBuffer();
void deinit();
@@ -64,7 +62,6 @@ private:
int m_channels, m_skip_frames;
uint m_bitrate;
long m_freq, m_len;
- qint64 m_output_bytes, m_output_at;
// file input buffer
char *m_input_buf;
@@ -88,27 +85,9 @@ private:
XING_SCALE = 0x0008
};
- struct audio_dither
- {
- mad_fixed_t error[3];
- mad_fixed_t random;
- };
-
struct mad_stream m_stream;
struct mad_frame m_frame;
struct mad_synth m_synth;
- struct audio_dither m_left_dither, m_right_dither;
-
- enum
- {
- CLIP_MIN = -MAD_F_ONE,
- CLIP_MAX = MAD_F_ONE - 1
- };
-
- //converter functions
- unsigned long prng(unsigned long state);
- long audio_linear_dither(unsigned int bits, mad_fixed_t sample, struct audio_dither *dither);
- long audio_linear_round(unsigned int bits, mad_fixed_t sample);
};
diff --git a/src/plugins/Input/vorbis/decoder_vorbis.cpp b/src/plugins/Input/vorbis/decoder_vorbis.cpp
index 7f77d485f..765572c91 100644
--- a/src/plugins/Input/vorbis/decoder_vorbis.cpp
+++ b/src/plugins/Input/vorbis/decoder_vorbis.cpp
@@ -71,9 +71,8 @@ static long oggtell(void *src)
DecoderVorbis::DecoderVorbis(const QString &url, QIODevice *i)
: Decoder(i)
{
- inited = false;
+ m_inited = false;
m_totalTime = 0;
- m_section = 0;
m_last_section = -1;
m_bitrate = 0;
m_url = url;
@@ -88,7 +87,7 @@ DecoderVorbis::~DecoderVorbis()
bool DecoderVorbis::initialize()
{
qDebug("DecoderVorbis: initialize");
- inited = false;
+ m_inited = false;
m_totalTime = 0;
if (!input())
{
@@ -140,15 +139,15 @@ bool DecoderVorbis::initialize()
qWarning("DecoderVorbis: unsupported number of channels: %d", chan);
return false;
}
- configure(freq, chmap, Qmmp::PCM_S16LE);
- inited = true;
+ configure(freq, chmap, Qmmp::PCM_FLOAT);
+ m_inited = true;
return true;
}
qint64 DecoderVorbis::totalTime()
{
- if (!inited)
+ if (!m_inited)
return 0;
return m_totalTime;
}
@@ -161,7 +160,7 @@ int DecoderVorbis::bitrate()
void DecoderVorbis::deinit()
{
- if (inited)
+ if (m_inited)
ov_clear(&oggfile);
len = 0;
}
@@ -296,23 +295,10 @@ void DecoderVorbis::seek(qint64 time)
qint64 DecoderVorbis::read(unsigned char *data, qint64 maxSize)
{
len = -1;
- while (len < 0)
- len = ov_read(&oggfile, (char *)data, maxSize, 0, 2, 1, &m_section);
-
- if (m_section != m_last_section)
- updateTags();
- m_last_section = m_section;
- if(len > 0)
- m_bitrate = ov_bitrate_instant(&oggfile) / 1000;
- return len;
-}
-
-qint64 DecoderVorbis::read(float *data, qint64 samples)
-{
- len = -1;
float **pcm = 0;
+ int section = 0;
while (len < 0)
- len = ov_read_float(&oggfile, &pcm, samples, &m_section);
+ len = ov_read_float(&oggfile, &pcm, maxSize/sizeof(float), &section);
if(len == 0)
return 0;
@@ -321,7 +307,7 @@ qint64 DecoderVorbis::read(float *data, qint64 samples)
for(int i = 0; i < channels; ++i)
{
- float *ptr = &data[i];
+ float *ptr = (float *) (data + i*sizeof(float));
for(int j = 0; j < len; ++j)
{
*ptr = pcm[i][j];
@@ -329,9 +315,12 @@ qint64 DecoderVorbis::read(float *data, qint64 samples)
}
}
- if (m_section != m_last_section)
+ if (section != m_last_section)
+ {
updateTags();
+ m_last_section = section;
+ }
m_bitrate = ov_bitrate_instant(&oggfile) / 1000;
- return len*channels;
+ return len*sizeof(float)*channels;
}
diff --git a/src/plugins/Input/vorbis/decoder_vorbis.h b/src/plugins/Input/vorbis/decoder_vorbis.h
index f48fe763a..b7cbfdea3 100644
--- a/src/plugins/Input/vorbis/decoder_vorbis.h
+++ b/src/plugins/Input/vorbis/decoder_vorbis.h
@@ -25,7 +25,6 @@ public:
private:
virtual qint64 read(unsigned char *data, qint64 maxSize);
- virtual qint64 read(float *data, qint64 samples);
virtual void seek(qint64 time);
// helper functions
@@ -37,9 +36,9 @@ private:
OggVorbis_File oggfile;
qint64 m_totalTime;
long len;
- int m_section, m_last_section;
+ int m_last_section;
int m_bitrate;
- bool inited;
+ bool m_inited;
QString m_url;
};
diff --git a/src/qmmp/decoder.cpp b/src/qmmp/decoder.cpp
index 702031551..89327edc2 100644
--- a/src/qmmp/decoder.cpp
+++ b/src/qmmp/decoder.cpp
@@ -42,14 +42,6 @@ void Decoder::configure(quint32 srate, int channels, Qmmp::AudioFormat f)
m_parameters = AudioParameters(srate, ChannelMap(channels), f);
}
-qint64 Decoder::read(float *data, qint64 samples)
-{
- Q_UNUSED(data);
- Q_UNUSED(samples);
- qFatal("Decoder: peak overflow is enabled but does not implemented");
- return -1;
-}
-
void Decoder::next()
{}
diff --git a/src/qmmp/decoder.h b/src/qmmp/decoder.h
index 799c8d2da..4585ee65a 100644
--- a/src/qmmp/decoder.h
+++ b/src/qmmp/decoder.h
@@ -57,16 +57,6 @@ public:
*/
virtual qint64 read(unsigned char *data, qint64 maxSize) = 0;
/*!
- * Reads up of decoded audio using float audio format.
- * Reimplement this function if a decoder supports peak overflow (i.e. has headroom).
- * Audio engine uses this function to prevent clipping.
- * Default implementation doesn nothing and returns -1.
- * @param data output audio data
- * @param samples maximum samples count
- * @return the number of samples read, or -1 if an error occurred.
- */
- virtual qint64 read(float *data, qint64 samples);
- /*!
* Returns current bitrate (in kbps).
* Subclass should reimplement this function.
*/