mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-01 21:56:43 +08:00
Ref T730, code style, adding namespaces
This commit is contained in:
committed by
Mat Sutcliffe
parent
329b1e8c9a
commit
99edc9cb13
@@ -8,8 +8,8 @@
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKSOUND_OPUSDECODER_H
|
||||
#define BLACKSOUND_OPUSDECODER_H
|
||||
#ifndef BLACKSOUND_CODECS_OPUSDECODER_H
|
||||
#define BLACKSOUND_CODECS_OPUSDECODER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "opus/opus.h"
|
||||
|
||||
@@ -2,33 +2,39 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
BufferedWaveProvider::BufferedWaveProvider(const QAudioFormat &format, QObject *parent) :
|
||||
ISampleProvider(parent)
|
||||
namespace BlackSound
|
||||
{
|
||||
// Set buffer size to 10 secs
|
||||
m_maxBufferSize = format.bytesForDuration(10 * 1000 * 1000);
|
||||
}
|
||||
|
||||
void BufferedWaveProvider::addSamples(const QVector<qint16> &samples)
|
||||
{
|
||||
int delta = m_audioBuffer.size() + samples.size() - m_maxBufferSize;
|
||||
if(delta > 0)
|
||||
namespace SampleProvider
|
||||
{
|
||||
m_audioBuffer.remove(0, delta);
|
||||
}
|
||||
m_audioBuffer.append(samples);
|
||||
}
|
||||
CBufferedWaveProvider::CBufferedWaveProvider(const QAudioFormat &format, QObject *parent) :
|
||||
ISampleProvider(parent)
|
||||
{
|
||||
// Set buffer size to 10 secs
|
||||
m_maxBufferSize = format.bytesForDuration(10 * 1000 * 1000);
|
||||
}
|
||||
|
||||
int BufferedWaveProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
qint64 len = qMin(count, static_cast<qint64>(m_audioBuffer.size()));
|
||||
samples = m_audioBuffer.mid(0, len);
|
||||
// if (len != 0) qDebug() << "Reading" << count << "samples." << m_audioBuffer.size() << "currently in the buffer.";
|
||||
m_audioBuffer.remove(0, len);
|
||||
return len;
|
||||
}
|
||||
void CBufferedWaveProvider::addSamples(const QVector<qint16> &samples)
|
||||
{
|
||||
int delta = m_audioBuffer.size() + samples.size() - m_maxBufferSize;
|
||||
if (delta > 0)
|
||||
{
|
||||
m_audioBuffer.remove(0, delta);
|
||||
}
|
||||
m_audioBuffer.append(samples);
|
||||
}
|
||||
|
||||
void BufferedWaveProvider::clearBuffer()
|
||||
{
|
||||
m_audioBuffer.clear();
|
||||
}
|
||||
int CBufferedWaveProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
qint64 len = qMin(count, static_cast<qint64>(m_audioBuffer.size()));
|
||||
samples = m_audioBuffer.mid(0, len);
|
||||
// if (len != 0) qDebug() << "Reading" << count << "samples." << m_audioBuffer.size() << "currently in the buffer.";
|
||||
m_audioBuffer.remove(0, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
void CBufferedWaveProvider::clearBuffer()
|
||||
{
|
||||
m_audioBuffer.clear();
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKSOUND_BUFFEREDWAVEPROVIDER_H
|
||||
#define BLACKSOUND_BUFFEREDWAVEPROVIDER_H
|
||||
|
||||
@@ -8,23 +18,31 @@
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
class BLACKSOUND_EXPORT BufferedWaveProvider : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! Buffered wave generator
|
||||
class BLACKSOUND_EXPORT CBufferedWaveProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BufferedWaveProvider(const QAudioFormat &format, QObject *parent = nullptr);
|
||||
public:
|
||||
//! Ctor
|
||||
CBufferedWaveProvider(const QAudioFormat &format, QObject *parent = nullptr);
|
||||
|
||||
void addSamples(const QVector<qint16> &samples);
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
void addSamples(const QVector<qint16> &samples);
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
int getBufferedBytes() const { return m_audioBuffer.size(); }
|
||||
int getBufferedBytes() const { return m_audioBuffer.size(); }
|
||||
|
||||
void clearBuffer();
|
||||
void clearBuffer();
|
||||
|
||||
private:
|
||||
QVector<qint16> m_audioBuffer;
|
||||
qint32 m_maxBufferSize;
|
||||
};
|
||||
private:
|
||||
QVector<qint16> m_audioBuffer;
|
||||
qint32 m_maxBufferSize;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BUFFEREDWAVEPROVIDER_H
|
||||
#endif // guard
|
||||
|
||||
@@ -1,51 +1,57 @@
|
||||
#include "equalizersampleprovider.h"
|
||||
|
||||
EqualizerSampleProvider::EqualizerSampleProvider(ISampleProvider *sourceProvider, EqualizerPresets preset, QObject *parent) :
|
||||
ISampleProvider(parent)
|
||||
namespace BlackSound
|
||||
{
|
||||
m_sourceProvider = sourceProvider;
|
||||
setupPreset(preset);
|
||||
}
|
||||
|
||||
int EqualizerSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
int samplesRead = m_sourceProvider->readSamples(samples, count);
|
||||
if (m_bypass) return samplesRead;
|
||||
|
||||
for (int n = 0; n < samplesRead; n++)
|
||||
namespace SampleProvider
|
||||
{
|
||||
// TODO stereo implementation
|
||||
|
||||
for (int band = 0; band < m_filters.size(); band++)
|
||||
CEqualizerSampleProvider::CEqualizerSampleProvider(ISampleProvider *sourceProvider, EqualizerPresets preset, QObject *parent) :
|
||||
ISampleProvider(parent)
|
||||
{
|
||||
float s = samples[n] / 32768.0f;
|
||||
s = m_filters[band].process(s);
|
||||
samples[n] = s * 32768;
|
||||
m_sourceProvider = sourceProvider;
|
||||
setupPreset(preset);
|
||||
}
|
||||
|
||||
samples[n] *= m_outputGain;
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
int CEqualizerSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
int samplesRead = m_sourceProvider->readSamples(samples, count);
|
||||
if (m_bypass) return samplesRead;
|
||||
|
||||
void EqualizerSampleProvider::setupPreset(EqualizerPresets preset)
|
||||
{
|
||||
switch (preset)
|
||||
{
|
||||
case VHFEmulation:
|
||||
m_filters.push_back(BiQuadFilter(BiQuadFilterType::HighPass, 44100, 450, 1.0f));
|
||||
m_filters.push_back(BiQuadFilter(BiQuadFilterType::Peak, 44100, 2200, 0.25, 13.0f));
|
||||
m_filters.push_back(BiQuadFilter(BiQuadFilterType::LowPass, 44100, 3000, 1.0f));
|
||||
break;
|
||||
for (int n = 0; n < samplesRead; n++)
|
||||
{
|
||||
// TODO stereo implementation
|
||||
|
||||
for (int band = 0; band < m_filters.size(); band++)
|
||||
{
|
||||
float s = samples[n] / 32768.0f;
|
||||
s = m_filters[band].process(s);
|
||||
samples[n] = s * 32768;
|
||||
}
|
||||
|
||||
samples[n] *= m_outputGain;
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
|
||||
void CEqualizerSampleProvider::setupPreset(EqualizerPresets preset)
|
||||
{
|
||||
switch (preset)
|
||||
{
|
||||
case VHFEmulation:
|
||||
m_filters.push_back(BiQuadFilter(BiQuadFilterType::HighPass, 44100, 450, 1.0f));
|
||||
m_filters.push_back(BiQuadFilter(BiQuadFilterType::Peak, 44100, 2200, 0.25, 13.0f));
|
||||
m_filters.push_back(BiQuadFilter(BiQuadFilterType::LowPass, 44100, 3000, 1.0f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double CEqualizerSampleProvider::outputGain() const
|
||||
{
|
||||
return m_outputGain;
|
||||
}
|
||||
|
||||
void CEqualizerSampleProvider::setOutputGain(double outputGain)
|
||||
{
|
||||
m_outputGain = outputGain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double EqualizerSampleProvider::outputGain() const
|
||||
{
|
||||
return m_outputGain;
|
||||
}
|
||||
|
||||
void EqualizerSampleProvider::setOutputGain(double outputGain)
|
||||
{
|
||||
m_outputGain = outputGain;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
#ifndef EQUALIZERSAMPLEPROVIDER_H
|
||||
#define EQUALIZERSAMPLEPROVIDER_H
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKSOUND_SAMPLEPROVIDER_EQUALIZERSAMPLEPROVIDER_H
|
||||
#define BLACKSOUND_SAMPLEPROVIDER_EQUALIZERSAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
@@ -8,34 +18,41 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
|
||||
enum EqualizerPresets
|
||||
namespace BlackSound
|
||||
{
|
||||
VHFEmulation = 1
|
||||
};
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! Equalizer
|
||||
enum EqualizerPresets
|
||||
{
|
||||
VHFEmulation = 1
|
||||
};
|
||||
|
||||
class BLACKSOUND_EXPORT EqualizerSampleProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
class BLACKSOUND_EXPORT CEqualizerSampleProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EqualizerSampleProvider(ISampleProvider *sourceProvider, EqualizerPresets preset, QObject *parent = nullptr);
|
||||
public:
|
||||
CEqualizerSampleProvider(ISampleProvider *sourceProvider, EqualizerPresets preset, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setBypassEffects(bool value) { m_bypass = value; }
|
||||
void setBypassEffects(bool value) { m_bypass = value; }
|
||||
|
||||
double outputGain() const;
|
||||
void setOutputGain(double outputGain);
|
||||
double outputGain() const;
|
||||
void setOutputGain(double outputGain);
|
||||
|
||||
private:
|
||||
void setupPreset(EqualizerPresets preset);
|
||||
private:
|
||||
void setupPreset(EqualizerPresets preset);
|
||||
|
||||
ISampleProvider *m_sourceProvider;
|
||||
ISampleProvider *m_sourceProvider;
|
||||
|
||||
int m_channels = 1;
|
||||
bool m_bypass = false;
|
||||
double m_outputGain = 1.0;
|
||||
QVector<BiQuadFilter> m_filters;
|
||||
};
|
||||
int m_channels = 1;
|
||||
bool m_bypass = false;
|
||||
double m_outputGain = 1.0;
|
||||
QVector<BiQuadFilter> m_filters;
|
||||
};
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
#endif // EQUALIZERSAMPLEPROVIDER_H
|
||||
#endif // guard
|
||||
|
||||
@@ -1,36 +1,50 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "mixingsampleprovider.h"
|
||||
|
||||
int MixingSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
namespace BlackSound
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
int outputLen = 0;
|
||||
|
||||
QVector<ISampleProvider*> finishedProviders;
|
||||
for (int i = 0; i < m_sources.size(); i++)
|
||||
namespace SampleProvider
|
||||
{
|
||||
ISampleProvider *sampleProvider = m_sources.at(i);
|
||||
QVector<qint16> sourceBuffer;
|
||||
int len = sampleProvider->readSamples(sourceBuffer, count);
|
||||
|
||||
for (int n = 0; n < len; n++)
|
||||
int CMixingSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
samples[n] += sourceBuffer[n];
|
||||
}
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
int outputLen = 0;
|
||||
|
||||
outputLen = qMax(len, outputLen);
|
||||
QVector<ISampleProvider *> finishedProviders;
|
||||
for (int i = 0; i < m_sources.size(); i++)
|
||||
{
|
||||
ISampleProvider *sampleProvider = m_sources.at(i);
|
||||
QVector<qint16> sourceBuffer;
|
||||
int len = sampleProvider->readSamples(sourceBuffer, count);
|
||||
|
||||
if (sampleProvider->isFinished())
|
||||
{
|
||||
finishedProviders.push_back(sampleProvider);
|
||||
for (int n = 0; n < len; n++)
|
||||
{
|
||||
samples[n] += sourceBuffer[n];
|
||||
}
|
||||
|
||||
outputLen = qMax(len, outputLen);
|
||||
|
||||
if (sampleProvider->isFinished())
|
||||
{
|
||||
finishedProviders.push_back(sampleProvider);
|
||||
}
|
||||
}
|
||||
|
||||
for (ISampleProvider *sampleProvider : finishedProviders)
|
||||
{
|
||||
sampleProvider->deleteLater();
|
||||
m_sources.removeAll(sampleProvider);
|
||||
}
|
||||
|
||||
return outputLen;
|
||||
}
|
||||
}
|
||||
|
||||
for (ISampleProvider *sampleProvider : finishedProviders)
|
||||
{
|
||||
sampleProvider->deleteLater();
|
||||
m_sources.removeAll(sampleProvider);
|
||||
}
|
||||
|
||||
return outputLen;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef MIXINGSAMPLEPROVIDER_H
|
||||
#define MIXINGSAMPLEPROVIDER_H
|
||||
|
||||
@@ -6,16 +16,22 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
|
||||
class BLACKSOUND_EXPORT MixingSampleProvider : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
public:
|
||||
MixingSampleProvider(QObject * parent = nullptr) : ISampleProvider(parent) {}
|
||||
namespace SampleProvider
|
||||
{
|
||||
class BLACKSOUND_EXPORT CMixingSampleProvider : public ISampleProvider
|
||||
{
|
||||
public:
|
||||
CMixingSampleProvider(QObject *parent = nullptr) : ISampleProvider(parent) {}
|
||||
|
||||
void addMixerInput(ISampleProvider *provider) { m_sources.append(provider); }
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
void addMixerInput(ISampleProvider *provider) { m_sources.append(provider); }
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
private:
|
||||
QVector<ISampleProvider*> m_sources;
|
||||
};
|
||||
private:
|
||||
QVector<ISampleProvider *> m_sources;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MIXINGSAMPLEPROVIDER_H
|
||||
#endif // guard
|
||||
|
||||
@@ -10,25 +10,31 @@
|
||||
|
||||
#include "pinknoisegenerator.h"
|
||||
|
||||
int PinkNoiseGenerator::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
namespace BlackSound
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
|
||||
for (int sampleCount = 0; sampleCount < count; sampleCount++)
|
||||
namespace SampleProvider
|
||||
{
|
||||
double white = 2 * random.generateDouble() - 1;
|
||||
int CPinkNoiseGenerator::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
|
||||
pinkNoiseBuffer[0] = 0.99886*pinkNoiseBuffer[0] + white*0.0555179;
|
||||
pinkNoiseBuffer[1] = 0.99332*pinkNoiseBuffer[1] + white*0.0750759;
|
||||
pinkNoiseBuffer[2] = 0.96900*pinkNoiseBuffer[2] + white*0.1538520;
|
||||
pinkNoiseBuffer[3] = 0.86650*pinkNoiseBuffer[3] + white*0.3104856;
|
||||
pinkNoiseBuffer[4] = 0.55000*pinkNoiseBuffer[4] + white*0.5329522;
|
||||
pinkNoiseBuffer[5] = -0.7616*pinkNoiseBuffer[5] - white*0.0168980;
|
||||
double pink = pinkNoiseBuffer[0] + pinkNoiseBuffer[1] + pinkNoiseBuffer[2] + pinkNoiseBuffer[3] + pinkNoiseBuffer[4] + pinkNoiseBuffer[5] + pinkNoiseBuffer[6] + white*0.5362;
|
||||
pinkNoiseBuffer[6] = white*0.115926;
|
||||
double sampleValue = (m_gain*(pink/5));
|
||||
samples[sampleCount] = sampleValue * 32768;
|
||||
for (int sampleCount = 0; sampleCount < count; sampleCount++)
|
||||
{
|
||||
double white = 2 * random.generateDouble() - 1;
|
||||
|
||||
pinkNoiseBuffer[0] = 0.99886 * pinkNoiseBuffer[0] + white * 0.0555179;
|
||||
pinkNoiseBuffer[1] = 0.99332 * pinkNoiseBuffer[1] + white * 0.0750759;
|
||||
pinkNoiseBuffer[2] = 0.96900 * pinkNoiseBuffer[2] + white * 0.1538520;
|
||||
pinkNoiseBuffer[3] = 0.86650 * pinkNoiseBuffer[3] + white * 0.3104856;
|
||||
pinkNoiseBuffer[4] = 0.55000 * pinkNoiseBuffer[4] + white * 0.5329522;
|
||||
pinkNoiseBuffer[5] = -0.7616 * pinkNoiseBuffer[5] - white * 0.0168980;
|
||||
double pink = pinkNoiseBuffer[0] + pinkNoiseBuffer[1] + pinkNoiseBuffer[2] + pinkNoiseBuffer[3] + pinkNoiseBuffer[4] + pinkNoiseBuffer[5] + pinkNoiseBuffer[6] + white * 0.5362;
|
||||
pinkNoiseBuffer[6] = white * 0.115926;
|
||||
double sampleValue = (m_gain * (pink / 5));
|
||||
samples[sampleCount] = sampleValue * 32768;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -19,23 +19,29 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
//! Pink noise generator
|
||||
class BLACKSOUND_EXPORT PinkNoiseGenerator : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! Pink noise generator
|
||||
class BLACKSOUND_EXPORT CPinkNoiseGenerator : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Noise generator
|
||||
PinkNoiseGenerator(QObject *parent = nullptr) : ISampleProvider(parent) {}
|
||||
public:
|
||||
//! Noise generator
|
||||
CPinkNoiseGenerator(QObject *parent = nullptr) : ISampleProvider(parent) {}
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setGain(double gain) { m_gain = gain; }
|
||||
void setGain(double gain) { m_gain = gain; }
|
||||
|
||||
private:
|
||||
QRandomGenerator random;
|
||||
std::array<double, 7> pinkNoiseBuffer = {0};
|
||||
double m_gain = 0.0;
|
||||
};
|
||||
private:
|
||||
QRandomGenerator random;
|
||||
std::array<double, 7> pinkNoiseBuffer = {0};
|
||||
double m_gain = 0.0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#include "resourcesound.h"
|
||||
#include "audioutilities.h"
|
||||
|
||||
ResourceSound::ResourceSound(const QString &audioFileName)
|
||||
{
|
||||
m_wavFile = new WavFile;
|
||||
m_wavFile->open(audioFileName);
|
||||
if (m_wavFile->fileFormat().sampleType() == QAudioFormat::Float)
|
||||
{
|
||||
m_samples = convertFloatBytesTo16BitPCM(m_wavFile->audioData());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_samples = convertBytesTo16BitPCM(m_wavFile->audioData());
|
||||
}
|
||||
using namespace BlackSound::Wav;
|
||||
|
||||
}
|
||||
|
||||
const QVector<qint16>& ResourceSound::audioData()
|
||||
namespace BlackSound
|
||||
{
|
||||
return m_samples;
|
||||
namespace SampleProvider
|
||||
{
|
||||
CResourceSound::CResourceSound(const QString &audioFileName)
|
||||
{
|
||||
m_wavFile = new WavFile;
|
||||
m_wavFile->open(audioFileName);
|
||||
if (m_wavFile->fileFormat().sampleType() == QAudioFormat::Float)
|
||||
{
|
||||
m_samples = convertFloatBytesTo16BitPCM(m_wavFile->audioData());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_samples = convertBytesTo16BitPCM(m_wavFile->audioData());
|
||||
}
|
||||
}
|
||||
|
||||
const QVector<qint16> &CResourceSound::audioData()
|
||||
{
|
||||
return m_samples;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
#ifndef RESOURCESOUND_H
|
||||
#define RESOURCESOUND_H
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKSOUND_SAMPLEPROVIDER_RESOURCESOUND_H
|
||||
#define BLACKSOUND_SAMPLEPROVIDER_RESOURCESOUND_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/wav/wavfile.h"
|
||||
@@ -7,16 +17,24 @@
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class ResourceSound
|
||||
namespace BlackSound
|
||||
{
|
||||
public:
|
||||
ResourceSound(const QString &audioFileName);
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! File from resources
|
||||
class CResourceSound
|
||||
{
|
||||
public:
|
||||
//! Sound of audio file
|
||||
CResourceSound(const QString &audioFileName);
|
||||
|
||||
const QVector<qint16> &audioData();
|
||||
const QVector<qint16> &audioData();
|
||||
|
||||
private:
|
||||
WavFile *m_wavFile;
|
||||
QVector<qint16> m_samples;
|
||||
};
|
||||
private:
|
||||
Wav::WavFile *m_wavFile = nullptr;
|
||||
QVector<qint16> m_samples;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RESOURCESOUND_H
|
||||
#endif // guard
|
||||
|
||||
@@ -1,76 +1,82 @@
|
||||
#include "resourcesoundsampleprovider.h"
|
||||
#include <QDebug>
|
||||
|
||||
ResourceSoundSampleProvider::ResourceSoundSampleProvider(const ResourceSound &resourceSound, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_resourceSound(resourceSound)
|
||||
namespace BlackSound
|
||||
{
|
||||
tempBuffer.resize(tempBufferSize);
|
||||
}
|
||||
|
||||
int ResourceSoundSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
if (count > tempBufferSize)
|
||||
namespace SampleProvider
|
||||
{
|
||||
qDebug() << "Count too large for temp buffer";
|
||||
return 0;
|
||||
}
|
||||
qint64 availableSamples = m_resourceSound.audioData().size() - position;
|
||||
|
||||
qint64 samplesToCopy = qMin(availableSamples, count);
|
||||
samples.clear();
|
||||
samples.fill(0, samplesToCopy);
|
||||
|
||||
for (qint64 i = 0; i < samplesToCopy; i++)
|
||||
{
|
||||
tempBuffer[i] = m_resourceSound.audioData().at(position + i);
|
||||
}
|
||||
|
||||
if (m_gain != 1.0f)
|
||||
{
|
||||
for (int i = 0; i < samplesToCopy; i++)
|
||||
CResourceSoundSampleProvider::CResourceSoundSampleProvider(const CResourceSound &resourceSound, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_resourceSound(resourceSound)
|
||||
{
|
||||
tempBuffer[i] *= m_gain;
|
||||
tempBuffer.resize(tempBufferSize);
|
||||
}
|
||||
|
||||
int CResourceSoundSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
if (count > tempBufferSize)
|
||||
{
|
||||
qDebug() << "Count too large for temp buffer";
|
||||
return 0;
|
||||
}
|
||||
qint64 availableSamples = m_resourceSound.audioData().size() - position;
|
||||
|
||||
qint64 samplesToCopy = qMin(availableSamples, count);
|
||||
samples.clear();
|
||||
samples.fill(0, samplesToCopy);
|
||||
|
||||
for (qint64 i = 0; i < samplesToCopy; i++)
|
||||
{
|
||||
tempBuffer[i] = m_resourceSound.audioData().at(position + i);
|
||||
}
|
||||
|
||||
if (m_gain != 1.0f)
|
||||
{
|
||||
for (int i = 0; i < samplesToCopy; i++)
|
||||
{
|
||||
tempBuffer[i] *= m_gain;
|
||||
}
|
||||
}
|
||||
|
||||
for (qint64 i = 0; i < samplesToCopy; i++)
|
||||
{
|
||||
samples[i] = tempBuffer.at(i);
|
||||
}
|
||||
|
||||
position += samplesToCopy;
|
||||
|
||||
if (position > availableSamples - 1)
|
||||
{
|
||||
if (m_looping) { position = 0; }
|
||||
else { m_isFinished = true; }
|
||||
}
|
||||
|
||||
return (int)samplesToCopy;
|
||||
}
|
||||
|
||||
bool CResourceSoundSampleProvider::isFinished()
|
||||
{
|
||||
return m_isFinished;
|
||||
}
|
||||
|
||||
bool CResourceSoundSampleProvider::looping() const
|
||||
{
|
||||
return m_looping;
|
||||
}
|
||||
|
||||
void CResourceSoundSampleProvider::setLooping(bool looping)
|
||||
{
|
||||
m_looping = looping;
|
||||
}
|
||||
|
||||
float CResourceSoundSampleProvider::gain() const
|
||||
{
|
||||
return m_gain;
|
||||
}
|
||||
|
||||
void CResourceSoundSampleProvider::setGain(float gain)
|
||||
{
|
||||
m_gain = gain;
|
||||
}
|
||||
}
|
||||
|
||||
for (qint64 i = 0; i < samplesToCopy; i++)
|
||||
{
|
||||
samples[i] = tempBuffer.at(i);
|
||||
}
|
||||
|
||||
position += samplesToCopy;
|
||||
|
||||
if (position > availableSamples - 1)
|
||||
{
|
||||
if (m_looping) { position = 0; }
|
||||
else { m_isFinished = true; }
|
||||
}
|
||||
|
||||
return (int)samplesToCopy;
|
||||
}
|
||||
|
||||
bool ResourceSoundSampleProvider::isFinished()
|
||||
{
|
||||
return m_isFinished;
|
||||
}
|
||||
|
||||
bool ResourceSoundSampleProvider::looping() const
|
||||
{
|
||||
return m_looping;
|
||||
}
|
||||
|
||||
void ResourceSoundSampleProvider::setLooping(bool looping)
|
||||
{
|
||||
m_looping = looping;
|
||||
}
|
||||
|
||||
float ResourceSoundSampleProvider::gain() const
|
||||
{
|
||||
return m_gain;
|
||||
}
|
||||
|
||||
void ResourceSoundSampleProvider::setGain(float gain)
|
||||
{
|
||||
m_gain = gain;
|
||||
}
|
||||
|
||||
@@ -1,37 +1,51 @@
|
||||
#ifndef RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
#define RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef BLACKSOUND_SAMPLEPROVIDER_RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
#define BLACKSOUND_SAMPLEPROVIDER_RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "sampleprovider.h"
|
||||
#include "resourcesound.h"
|
||||
|
||||
//! A sample provider
|
||||
class BLACKSOUND_EXPORT ResourceSoundSampleProvider : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! A sample provider
|
||||
class BLACKSOUND_EXPORT CResourceSoundSampleProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Ctor
|
||||
ResourceSoundSampleProvider(const ResourceSound &resourceSound, QObject *parent = nullptr);
|
||||
public:
|
||||
//! Ctor
|
||||
CResourceSoundSampleProvider(const CResourceSound &resourceSound, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual bool isFinished() override;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual bool isFinished() override;
|
||||
|
||||
bool looping() const;
|
||||
void setLooping(bool looping);
|
||||
bool looping() const;
|
||||
void setLooping(bool looping);
|
||||
|
||||
float gain() const;
|
||||
void setGain(float gain);
|
||||
float gain() const;
|
||||
void setGain(float gain);
|
||||
|
||||
private:
|
||||
float m_gain = 1.0f;
|
||||
bool m_looping = false;
|
||||
private:
|
||||
float m_gain = 1.0f;
|
||||
bool m_looping = false;
|
||||
|
||||
ResourceSound m_resourceSound;
|
||||
qint64 position = 0;
|
||||
const int tempBufferSize = 9600; //9600 = 200ms
|
||||
QVector<qint16> tempBuffer;
|
||||
bool m_isFinished = false;
|
||||
};
|
||||
CResourceSound m_resourceSound;
|
||||
qint64 position = 0;
|
||||
const int tempBufferSize = 9600; //9600 = 200ms
|
||||
QVector<qint16> tempBuffer;
|
||||
bool m_isFinished = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
#endif // guard
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef SAMPLEPROVIDER_H
|
||||
#define SAMPLEPROVIDER_H
|
||||
|
||||
@@ -5,17 +15,24 @@
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
class BLACKSOUND_EXPORT ISampleProvider : public QObject
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! Sample provider interface
|
||||
class BLACKSOUND_EXPORT ISampleProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ISampleProvider(QObject *parent = nullptr) : QObject(parent) {}
|
||||
virtual ~ISampleProvider() {}
|
||||
public:
|
||||
ISampleProvider(QObject *parent = nullptr) : QObject(parent) {}
|
||||
virtual ~ISampleProvider() override {}
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) = 0;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) = 0;
|
||||
|
||||
virtual bool isFinished() { return false; }
|
||||
};
|
||||
virtual bool isFinished() { return false; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SAMPLEPROVIDER_H
|
||||
#endif // guard
|
||||
|
||||
@@ -1,29 +1,43 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "samples.h"
|
||||
#include "blackmisc/directoryutils.h"
|
||||
|
||||
Samples &Samples::instance()
|
||||
namespace BlackSound
|
||||
{
|
||||
static Samples samples;
|
||||
return samples;
|
||||
}
|
||||
namespace SampleProvider
|
||||
{
|
||||
Samples &Samples::instance()
|
||||
{
|
||||
static Samples samples;
|
||||
return samples;
|
||||
}
|
||||
|
||||
Samples::Samples() :
|
||||
m_crackle(BlackMisc::CDirectoryUtils::soundFilesDirectory() + "/Crackle_f32.wav"),
|
||||
m_click(BlackMisc::CDirectoryUtils::soundFilesDirectory() + "/Click_f32.wav"),
|
||||
m_whiteNoise(BlackMisc::CDirectoryUtils::soundFilesDirectory() + "/WhiteNoise_f32.wav")
|
||||
{ }
|
||||
Samples::Samples() :
|
||||
m_crackle(BlackMisc::CDirectoryUtils::soundFilesDirectory() + "/Crackle_f32.wav"),
|
||||
m_click(BlackMisc::CDirectoryUtils::soundFilesDirectory() + "/Click_f32.wav"),
|
||||
m_whiteNoise(BlackMisc::CDirectoryUtils::soundFilesDirectory() + "/WhiteNoise_f32.wav")
|
||||
{ }
|
||||
|
||||
ResourceSound Samples::click() const
|
||||
{
|
||||
return m_click;
|
||||
}
|
||||
CResourceSound Samples::click() const
|
||||
{
|
||||
return m_click;
|
||||
}
|
||||
|
||||
ResourceSound Samples::crackle() const
|
||||
{
|
||||
return m_crackle;
|
||||
}
|
||||
CResourceSound Samples::crackle() const
|
||||
{
|
||||
return m_crackle;
|
||||
}
|
||||
|
||||
ResourceSound Samples::whiteNoise() const
|
||||
{
|
||||
return m_whiteNoise;
|
||||
CResourceSound Samples::whiteNoise() const
|
||||
{
|
||||
return m_whiteNoise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,40 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef SAMPLES_H
|
||||
#define SAMPLES_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "resourcesound.h"
|
||||
|
||||
class BLACKSOUND_EXPORT Samples
|
||||
namespace BlackSound
|
||||
{
|
||||
public:
|
||||
static Samples &instance();
|
||||
namespace SampleProvider
|
||||
{
|
||||
class BLACKSOUND_EXPORT Samples
|
||||
{
|
||||
public:
|
||||
static Samples &instance();
|
||||
|
||||
ResourceSound crackle() const;
|
||||
ResourceSound click() const;
|
||||
ResourceSound whiteNoise() const;
|
||||
CResourceSound crackle() const;
|
||||
CResourceSound click() const;
|
||||
CResourceSound whiteNoise() const;
|
||||
|
||||
private:
|
||||
Samples();
|
||||
private:
|
||||
Samples();
|
||||
|
||||
ResourceSound m_crackle;
|
||||
ResourceSound m_click;
|
||||
ResourceSound m_whiteNoise;
|
||||
};
|
||||
CResourceSound m_crackle;
|
||||
CResourceSound m_click;
|
||||
CResourceSound m_whiteNoise;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SAMPLES_H
|
||||
|
||||
@@ -1,23 +1,37 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "sawtoothgenerator.h"
|
||||
#include <cmath>
|
||||
|
||||
SawToothGenerator::SawToothGenerator(double frequency, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_frequency(frequency)
|
||||
{}
|
||||
|
||||
int SawToothGenerator::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
namespace BlackSound
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
|
||||
for (int sampleCount = 0; sampleCount < count; sampleCount++)
|
||||
namespace SampleProvider
|
||||
{
|
||||
double multiple = 2 * m_frequency / m_sampleRate;
|
||||
double sampleSaw = std::fmod((m_nSample * multiple), 2) - 1;
|
||||
double sampleValue = m_gain * sampleSaw;
|
||||
samples[sampleCount] = sampleValue * 32768;
|
||||
m_nSample++;
|
||||
CSawToothGenerator::CSawToothGenerator(double frequency, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_frequency(frequency)
|
||||
{}
|
||||
|
||||
int CSawToothGenerator::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
|
||||
for (int sampleCount = 0; sampleCount < count; sampleCount++)
|
||||
{
|
||||
double multiple = 2 * m_frequency / m_sampleRate;
|
||||
double sampleSaw = std::fmod((m_nSample * multiple), 2) - 1;
|
||||
double sampleValue = m_gain * sampleSaw;
|
||||
samples[sampleCount] = sampleValue * 32768;
|
||||
m_nSample++;
|
||||
}
|
||||
return static_cast<int>(count);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -1,30 +1,45 @@
|
||||
#ifndef SAWTOOTHGENERATOR_H
|
||||
#define SAWTOOTHGENERATOR_H
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKSOUND_SAMPLEPROVIDER_SAWTOOTHGENERATOR_H
|
||||
#define BLACKSOUND_SAMPLEPROVIDER_SAWTOOTHGENERATOR_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
#include <QVector>
|
||||
|
||||
#include <array>
|
||||
|
||||
class BLACKSOUND_EXPORT SawToothGenerator : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! Saw tooth generator
|
||||
class BLACKSOUND_EXPORT CSawToothGenerator : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SawToothGenerator(double frequency, QObject *parent = nullptr);
|
||||
public:
|
||||
CSawToothGenerator(double frequency, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setGain(double gain) { m_gain = gain; }
|
||||
void setGain(double gain) { m_gain = gain; }
|
||||
|
||||
private:
|
||||
double m_gain = 0.0;
|
||||
double m_frequency = 0.0;
|
||||
double m_sampleRate = 48000;
|
||||
int m_nSample = 0;
|
||||
};
|
||||
private:
|
||||
double m_gain = 0.0;
|
||||
double m_frequency = 0.0;
|
||||
double m_sampleRate = 48000;
|
||||
int m_nSample = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SAWTOOTHGENERATOR_H
|
||||
#endif // guard
|
||||
|
||||
@@ -1,45 +1,59 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "simplecompressoreffect.h"
|
||||
#include <QDebug>
|
||||
|
||||
SimpleCompressorEffect::SimpleCompressorEffect(ISampleProvider *source, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_sourceStream(source)
|
||||
namespace BlackSound
|
||||
{
|
||||
m_simpleCompressor.setAttack(5.0);
|
||||
m_simpleCompressor.setRelease(10.0);
|
||||
m_simpleCompressor.setSampleRate(48000.0);
|
||||
m_simpleCompressor.setThresh(16.0);
|
||||
m_simpleCompressor.setRatio(6.0);
|
||||
m_simpleCompressor.setMakeUpGain(16.0);
|
||||
|
||||
m_timer.start(3000);
|
||||
}
|
||||
|
||||
int SimpleCompressorEffect::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
int samplesRead = m_sourceStream->readSamples(samples, count);
|
||||
|
||||
if (m_enabled)
|
||||
namespace SampleProvider
|
||||
{
|
||||
for (int sample = 0; sample < samplesRead; sample+=channels)
|
||||
CSimpleCompressorEffect::CSimpleCompressorEffect(ISampleProvider *source, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_sourceStream(source)
|
||||
{
|
||||
double in1 = samples.at(sample) / 32768.0;
|
||||
double in2 = (channels == 1) ? 0 : samples.at(sample+1);
|
||||
m_simpleCompressor.process(in1, in2);
|
||||
samples[sample] = in1 * 32768.0;
|
||||
if (channels > 1)
|
||||
samples[sample + 1] = in2 * 32768.0f;
|
||||
m_simpleCompressor.setAttack(5.0);
|
||||
m_simpleCompressor.setRelease(10.0);
|
||||
m_simpleCompressor.setSampleRate(48000.0);
|
||||
m_simpleCompressor.setThresh(16.0);
|
||||
m_simpleCompressor.setRatio(6.0);
|
||||
m_simpleCompressor.setMakeUpGain(16.0);
|
||||
|
||||
m_timer.start(3000);
|
||||
}
|
||||
|
||||
int CSimpleCompressorEffect::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
int samplesRead = m_sourceStream->readSamples(samples, count);
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
for (int sample = 0; sample < samplesRead; sample += channels)
|
||||
{
|
||||
double in1 = samples.at(sample) / 32768.0;
|
||||
double in2 = (channels == 1) ? 0 : samples.at(sample + 1);
|
||||
m_simpleCompressor.process(in1, in2);
|
||||
samples[sample] = in1 * 32768.0;
|
||||
if (channels > 1)
|
||||
samples[sample + 1] = in2 * 32768.0f;
|
||||
}
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
|
||||
void CSimpleCompressorEffect::setEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void CSimpleCompressorEffect::setMakeUpGain(double gain)
|
||||
{
|
||||
m_simpleCompressor.setMakeUpGain(gain);
|
||||
}
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
|
||||
void SimpleCompressorEffect::setEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void SimpleCompressorEffect::setMakeUpGain(double gain)
|
||||
{
|
||||
m_simpleCompressor.setMakeUpGain(gain);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
#ifndef SIMPLECOMPRESSOREFFECT_H
|
||||
#define SIMPLECOMPRESSOREFFECT_H
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKSOUND_SAMPLEPROVIDER_SIMPLECOMPRESSOREFFECT_H
|
||||
#define BLACKSOUND_SAMPLEPROVIDER_SIMPLECOMPRESSOREFFECT_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "sampleprovider.h"
|
||||
@@ -8,25 +18,31 @@
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class BLACKSOUND_EXPORT SimpleCompressorEffect : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
class BLACKSOUND_EXPORT CSimpleCompressorEffect : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SimpleCompressorEffect(ISampleProvider *source, QObject *parent = nullptr);
|
||||
public:
|
||||
CSimpleCompressorEffect(ISampleProvider *source, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setMakeUpGain(double gain);
|
||||
void setEnabled(bool enabled);
|
||||
void setMakeUpGain(double gain);
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
QTimer m_timer;
|
||||
ISampleProvider *m_sourceStream;
|
||||
bool m_enabled = true;
|
||||
chunkware_simple::SimpleComp m_simpleCompressor;
|
||||
const int channels = 1;
|
||||
};
|
||||
QTimer m_timer;
|
||||
ISampleProvider *m_sourceStream;
|
||||
bool m_enabled = true;
|
||||
chunkware_simple::SimpleComp m_simpleCompressor;
|
||||
const int channels = 1;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SIMPLECOMPRESSOREFFECT_H
|
||||
#endif // guard
|
||||
|
||||
@@ -8,33 +8,30 @@
|
||||
|
||||
//! \file
|
||||
|
||||
#include "volumesampleprovider.h"
|
||||
#include "volumesampleprovider.h"
|
||||
|
||||
VolumeSampleProvider::VolumeSampleProvider(ISampleProvider *sourceProvider, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_sourceProvider(sourceProvider)
|
||||
{ }
|
||||
|
||||
int VolumeSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
namespace BlackSound
|
||||
{
|
||||
int samplesRead = m_sourceProvider->readSamples(samples, count);
|
||||
|
||||
if (! qFuzzyCompare(m_volume, 1.0))
|
||||
namespace SampleProvider
|
||||
{
|
||||
for (int n = 0; n < samplesRead; n++)
|
||||
CVolumeSampleProvider::CVolumeSampleProvider(ISampleProvider *sourceProvider, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_sourceProvider(sourceProvider)
|
||||
{ }
|
||||
|
||||
int CVolumeSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
samples[n] *= m_volume;
|
||||
int samplesRead = m_sourceProvider->readSamples(samples, count);
|
||||
|
||||
if (! qFuzzyCompare(m_volume, 1.0))
|
||||
{
|
||||
for (int n = 0; n < samplesRead; n++)
|
||||
{
|
||||
samples[n] *= m_volume;
|
||||
}
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
}
|
||||
return samplesRead;
|
||||
}
|
||||
|
||||
double VolumeSampleProvider::volume() const
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
void VolumeSampleProvider::setVolume(double volume)
|
||||
{
|
||||
m_volume = volume;
|
||||
}
|
||||
|
||||
@@ -8,29 +8,35 @@
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef VOLUMESAMPLEPROVIDER_H
|
||||
#define VOLUMESAMPLEPROVIDER_H
|
||||
#ifndef BLACKSOUND_SAMPLEPROVIDER_VOLUMESAMPLEPROVIDER_H
|
||||
#define BLACKSOUND_SAMPLEPROVIDER_VOLUMESAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
|
||||
//! Pink noise generator
|
||||
class BLACKSOUND_EXPORT VolumeSampleProvider : public ISampleProvider
|
||||
namespace BlackSound
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace SampleProvider
|
||||
{
|
||||
//! Pink noise generator
|
||||
class BLACKSOUND_EXPORT CVolumeSampleProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Noise generator
|
||||
VolumeSampleProvider(ISampleProvider *sourceProvider, QObject *parent = nullptr);
|
||||
public:
|
||||
//! Noise generator
|
||||
CVolumeSampleProvider(ISampleProvider *sourceProvider, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
double volume() const;
|
||||
void setVolume(double volume);
|
||||
double volume() const { return m_volume; }
|
||||
void setVolume(double volume) { m_volume = volume; }
|
||||
|
||||
private:
|
||||
ISampleProvider *m_sourceProvider;
|
||||
double m_volume = 1.0;
|
||||
};
|
||||
private:
|
||||
ISampleProvider *m_sourceProvider = nullptr;
|
||||
double m_volume = 1.0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -1,133 +1,147 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <qendian.h>
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
// #include "utils.h"
|
||||
#include "wavfile.h"
|
||||
|
||||
struct chunk
|
||||
namespace BlackSound
|
||||
{
|
||||
char id[4];
|
||||
quint32 size;
|
||||
};
|
||||
|
||||
struct RIFFHeader
|
||||
{
|
||||
chunk descriptor; // "RIFF"
|
||||
char type[4]; // "WAVE"
|
||||
};
|
||||
|
||||
struct WAVEHeader
|
||||
{
|
||||
chunk descriptor;
|
||||
quint16 audioFormat;
|
||||
quint16 numChannels;
|
||||
quint32 sampleRate;
|
||||
quint32 byteRate;
|
||||
quint16 blockAlign;
|
||||
quint16 bitsPerSample;
|
||||
};
|
||||
|
||||
struct DATAHeader
|
||||
{
|
||||
chunk descriptor;
|
||||
};
|
||||
|
||||
struct CombinedHeader
|
||||
{
|
||||
RIFFHeader riff;
|
||||
WAVEHeader wave;
|
||||
};
|
||||
|
||||
WavFile::WavFile(QObject *parent) :
|
||||
QFile(parent),
|
||||
m_headerLength(0)
|
||||
{ }
|
||||
|
||||
bool WavFile::open(const QString &fileName)
|
||||
{
|
||||
close();
|
||||
setFileName(fileName);
|
||||
return QFile::open(QIODevice::ReadOnly) && readHeader();
|
||||
}
|
||||
|
||||
const QAudioFormat &WavFile::fileFormat() const
|
||||
{
|
||||
return m_fileFormat;
|
||||
}
|
||||
|
||||
qint64 WavFile::headerLength() const
|
||||
{
|
||||
return m_headerLength;
|
||||
}
|
||||
|
||||
bool WavFile::readHeader()
|
||||
{
|
||||
seek(0);
|
||||
CombinedHeader header;
|
||||
DATAHeader dataHeader;
|
||||
bool result = read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader);
|
||||
if (result)
|
||||
namespace Wav
|
||||
{
|
||||
if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
|
||||
|| memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
|
||||
&& memcmp(&header.riff.type, "WAVE", 4) == 0
|
||||
&& memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
|
||||
&& (header.wave.audioFormat == 1 || header.wave.audioFormat == 0 || header.wave.audioFormat == 3))
|
||||
struct chunk
|
||||
{
|
||||
// Read off remaining header information
|
||||
if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader))
|
||||
char id[4];
|
||||
quint32 size;
|
||||
};
|
||||
|
||||
struct RIFFHeader
|
||||
{
|
||||
chunk descriptor; // "RIFF"
|
||||
char type[4]; // "WAVE"
|
||||
};
|
||||
|
||||
struct WAVEHeader
|
||||
{
|
||||
chunk descriptor;
|
||||
quint16 audioFormat;
|
||||
quint16 numChannels;
|
||||
quint32 sampleRate;
|
||||
quint32 byteRate;
|
||||
quint16 blockAlign;
|
||||
quint16 bitsPerSample;
|
||||
};
|
||||
|
||||
struct DATAHeader
|
||||
{
|
||||
chunk descriptor;
|
||||
};
|
||||
|
||||
struct CombinedHeader
|
||||
{
|
||||
RIFFHeader riff;
|
||||
WAVEHeader wave;
|
||||
};
|
||||
|
||||
WavFile::WavFile(QObject *parent) :
|
||||
QFile(parent),
|
||||
m_headerLength(0)
|
||||
{ }
|
||||
|
||||
bool WavFile::open(const QString &fileName)
|
||||
{
|
||||
close();
|
||||
setFileName(fileName);
|
||||
return QFile::open(QIODevice::ReadOnly) && readHeader();
|
||||
}
|
||||
|
||||
const QAudioFormat &WavFile::fileFormat() const
|
||||
{
|
||||
return m_fileFormat;
|
||||
}
|
||||
|
||||
qint64 WavFile::headerLength() const
|
||||
{
|
||||
return m_headerLength;
|
||||
}
|
||||
|
||||
bool WavFile::readHeader()
|
||||
{
|
||||
seek(0);
|
||||
CombinedHeader header;
|
||||
DATAHeader dataHeader;
|
||||
bool result = read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader);
|
||||
if (result)
|
||||
{
|
||||
// Extended data available
|
||||
quint16 extraFormatBytes;
|
||||
if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16))
|
||||
return false;
|
||||
const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes);
|
||||
if (read(throwAwayBytes).size() != throwAwayBytes)
|
||||
if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
|
||||
|| memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
|
||||
&& memcmp(&header.riff.type, "WAVE", 4) == 0
|
||||
&& memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
|
||||
&& (header.wave.audioFormat == 1 || header.wave.audioFormat == 0 || header.wave.audioFormat == 3))
|
||||
{
|
||||
// Read off remaining header information
|
||||
if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader))
|
||||
{
|
||||
// Extended data available
|
||||
quint16 extraFormatBytes;
|
||||
if (peek((char *)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16))
|
||||
return false;
|
||||
const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes);
|
||||
if (read(throwAwayBytes).size() != throwAwayBytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (read((char *)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader))
|
||||
return false;
|
||||
|
||||
// Establish format
|
||||
if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
|
||||
m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
else
|
||||
m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
|
||||
|
||||
int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
|
||||
m_fileFormat.setChannelCount(qFromLittleEndian<quint16>(header.wave.numChannels));
|
||||
m_fileFormat.setCodec("audio/pcm");
|
||||
m_fileFormat.setSampleRate(qFromLittleEndian<quint32>(header.wave.sampleRate));
|
||||
m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
|
||||
|
||||
if (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)
|
||||
{
|
||||
m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fileFormat.setSampleType(QAudioFormat::Float);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
m_headerLength = pos();
|
||||
|
||||
if (memcmp(&dataHeader.descriptor.id, "data", 4) == 0)
|
||||
{
|
||||
qint32 dataLength = qFromLittleEndian<qint32>(dataHeader.descriptor.size);
|
||||
m_audioData = read(dataLength);
|
||||
if (m_audioData.size() != dataLength)
|
||||
{
|
||||
return false;
|
||||
m_audioData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader))
|
||||
return false;
|
||||
|
||||
// Establish format
|
||||
if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
|
||||
m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
else
|
||||
m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
|
||||
|
||||
int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
|
||||
m_fileFormat.setChannelCount(qFromLittleEndian<quint16>(header.wave.numChannels));
|
||||
m_fileFormat.setCodec("audio/pcm");
|
||||
m_fileFormat.setSampleRate(qFromLittleEndian<quint32>(header.wave.sampleRate));
|
||||
m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
|
||||
|
||||
if (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)
|
||||
{
|
||||
m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fileFormat.setSampleType(QAudioFormat::Float);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
m_headerLength = pos();
|
||||
|
||||
if (memcmp(&dataHeader.descriptor.id, "data", 4) == 0)
|
||||
{
|
||||
qint32 dataLength = qFromLittleEndian<qint32>(dataHeader.descriptor.size);
|
||||
m_audioData = read(dataLength);
|
||||
if (m_audioData.size() != dataLength)
|
||||
{
|
||||
return false;
|
||||
m_audioData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/* Copyright (C) 2019
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
||||
* or distributed except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef WAVFILE_H
|
||||
#define WAVFILE_H
|
||||
|
||||
@@ -5,24 +15,32 @@
|
||||
#include <QFile>
|
||||
#include <QAudioFormat>
|
||||
|
||||
class WavFile : public QFile
|
||||
namespace BlackSound
|
||||
{
|
||||
public:
|
||||
WavFile(QObject *parent = 0);
|
||||
namespace Wav
|
||||
{
|
||||
//! * WAV file
|
||||
class WavFile : public QFile
|
||||
{
|
||||
public:
|
||||
//! Ctor
|
||||
WavFile(QObject *parent = nullptr);
|
||||
|
||||
using QFile::open;
|
||||
bool open(const QString &fileName);
|
||||
const QAudioFormat &fileFormat() const;
|
||||
qint64 headerLength() const;
|
||||
QByteArray audioData() { return m_audioData; }
|
||||
using QFile::open;
|
||||
bool open(const QString &fileName);
|
||||
const QAudioFormat &fileFormat() const;
|
||||
qint64 headerLength() const;
|
||||
QByteArray audioData() { return m_audioData; }
|
||||
|
||||
private:
|
||||
bool readHeader();
|
||||
private:
|
||||
bool readHeader();
|
||||
|
||||
private:
|
||||
QAudioFormat m_fileFormat;
|
||||
qint64 m_headerLength;
|
||||
QByteArray m_audioData;
|
||||
};
|
||||
private:
|
||||
QAudioFormat m_fileFormat;
|
||||
qint64 m_headerLength;
|
||||
QByteArray m_audioData;
|
||||
};
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
#endif // WAVFILE_H
|
||||
#endif // guard
|
||||
|
||||
Reference in New Issue
Block a user