diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2015-12-27 17:44:16 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2015-12-27 17:44:16 +0000 |
| commit | d55e5c3b1bd791f0f579315c30bf14064eff5824 (patch) | |
| tree | 212315e4157bcf4accd64994a083599151c8bc40 | |
| parent | 78b5e1b27f7952bad19b53cdb6d0f371acb22ef2 (diff) | |
| download | qmmp-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
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.cpp | 148 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.h | 21 | ||||
| -rw-r--r-- | src/plugins/Input/vorbis/decoder_vorbis.cpp | 39 | ||||
| -rw-r--r-- | src/plugins/Input/vorbis/decoder_vorbis.h | 5 | ||||
| -rw-r--r-- | src/qmmp/decoder.cpp | 8 | ||||
| -rw-r--r-- | src/qmmp/decoder.h | 10 |
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), §ion); 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. */ |
