From 66f4a9b45fef95d3c65fc86247dc73be8b56974d Mon Sep 17 00:00:00 2001 From: trialuser02 Date: Mon, 11 Jan 2016 15:42:53 +0000 Subject: prepare for dither implementation git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@5985 90c681e8-e032-0410-971d-27865f9a5e38 --- src/qmmp/dithering.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++ src/qmmp/dithering_p.h | 56 ++++++++++++++++++++++ src/qmmp/qmmp.pro | 6 ++- src/qmmp/qmmpaudioengine.cpp | 5 +- src/qmmp/qmmpaudioengine_p.h | 2 +- 5 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 src/qmmp/dithering.cpp create mode 100644 src/qmmp/dithering_p.h (limited to 'src') diff --git a/src/qmmp/dithering.cpp b/src/qmmp/dithering.cpp new file mode 100644 index 000000000..dd5513b47 --- /dev/null +++ b/src/qmmp/dithering.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + * Based on madplay project * + * * + * Copyright (C) 2000-2004 Robert Leslie * + * Copyright (C) 2015 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "dithering_p.h" + +Dithering::Dithering() : Effect() +{ + qDebug("========================="); + + float output, random; + + for(int i = 0; i < 9; ++i) + { + m_dither[i].error[0] = 0.0f; + m_dither[i].error[1] = 0.0f; + m_dither[i].error[2] = 0.0f; + m_dither[i].random = 0.0f; + } + + //for(int i = 0; i < 500; ++i) + // audioLinearDither(0, &m_dither[0]); + + qDebug("=%x=", 1<< 8); +} + +void Dithering::configure(quint32 srate, ChannelMap map) +{ + m_chan = map.count(); + for(int i = 0; i < 9; ++i) + { + m_dither[i].error[0] = 0.0f; + m_dither[i].error[1] = 0.0f; + m_dither[i].error[2] = 0.0f; + m_dither[i].random = 0.0f; + } + Effect::configure(srate, map); +} + +void Dithering::applyEffect(Buffer *b) +{ + for(size_t i = 0; i < b->samples; ++i) + { + b->data[i] = audioLinearDither(b->data[i], &m_dither[i % m_chan]); + } +} + +quint32 Dithering::prng(quint32 state) // 32-bit pseudo-random number generator +{ + return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; +} + +float Dithering::audioLinearDither(float sample, AudioDither *dither) +{ + float output; quint32 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; + + output = sample; + + /* dither */ + random = prng(dither->random); + output += ((float) (random & 0x0000ffffL) - (dither->random & 0x0000ffffL)) / 0xffffffffL; + dither->random = random; + + /* clip */ + if (output > 1.0f) + { + output = 1.0f; + + if (sample > 1.0f) + sample = 1.0f; + } + else if (output < 1.0f) + { + output = 1.0f; + + if (sample < 1.0f) + sample = 1.0f; + } + + /* error feedback */ + dither->error[0] = sample - output; + + return output; +} diff --git a/src/qmmp/dithering_p.h b/src/qmmp/dithering_p.h new file mode 100644 index 000000000..db25c00d2 --- /dev/null +++ b/src/qmmp/dithering_p.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Based on madplay project * + * * + * Copyright (C) 2000-2004 Robert Leslie * + * Copyright (C) 2015 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#ifndef DITHERING_P_H +#define DITHERING_P_H + +#include "effect.h" + +/** @internal + @author Ilya Kotov +*/ +class Dithering : public Effect +{ +public: + Dithering(); + + void configure(quint32 srate, ChannelMap map); + void applyEffect(Buffer *b); + +private: + int m_chan; + + typedef struct + { + float error[3]; + quint32 random; + + } AudioDither; + + AudioDither m_dither[9]; + + quint32 prng(quint32 state); + float audioLinearDither(float sample, AudioDither *dither); +}; + +#endif // DITHERING_P_H diff --git a/src/qmmp/qmmp.pro b/src/qmmp/qmmp.pro index 3351a1096..0bf127f95 100644 --- a/src/qmmp/qmmp.pro +++ b/src/qmmp/qmmp.pro @@ -39,7 +39,8 @@ HEADERS += \ qmmpplugincache_p.h \ channelmap.h \ channelconverter_p.h \ - audioconverter.h + audioconverter.h \ + dithering_p.h SOURCES += recycler.cpp \ decoder.cpp \ output.cpp \ @@ -71,7 +72,8 @@ SOURCES += recycler.cpp \ qmmpplugincache.cpp \ channelmap.cpp \ channelconverter.cpp \ - volume.cpp + volume.cpp \ + dithering.cpp FORMS += unix:TARGET = ../../lib/qmmp win32:TARGET = ../../../bin/qmmp diff --git a/src/qmmp/qmmpaudioengine.cpp b/src/qmmp/qmmpaudioengine.cpp index dd8e57c25..b736db2e8 100644 --- a/src/qmmp/qmmpaudioengine.cpp +++ b/src/qmmp/qmmpaudioengine.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2009-2015 by Ilya Kotov * + * Copyright (C) 2009-2016 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -33,6 +33,7 @@ #include "audioconverter.h" #include "qmmpaudioengine_p.h" #include "channelconverter_p.h" +#include "dithering_p.h" #include "metadatamanager.h" #define TRANSPORT_TIMEOUT 5000 //ms @@ -54,6 +55,8 @@ QmmpAudioEngine::QmmpAudioEngine(QObject *parent) connect(m_settings, SIGNAL(eqSettingsChanged()), SLOT(updateEqSettings())); reset(); m_instance = this; + + Dithering d; } QmmpAudioEngine::~QmmpAudioEngine() diff --git a/src/qmmp/qmmpaudioengine_p.h b/src/qmmp/qmmpaudioengine_p.h index 14446e802..92c39fc6e 100644 --- a/src/qmmp/qmmpaudioengine_p.h +++ b/src/qmmp/qmmpaudioengine_p.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2009-2013 by Ilya Kotov * + * Copyright (C) 2009-2016 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * -- cgit v1.2.3-13-gbd6f