mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-14 16:55:36 +08:00
AFV initial commit
This commit is contained in:
committed by
Mat Sutcliffe
parent
7030302e73
commit
b5a2f2ad13
34
src/blacksound/sampleprovider/bufferedwaveprovider.cpp
Normal file
34
src/blacksound/sampleprovider/bufferedwaveprovider.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "bufferedwaveprovider.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
BufferedWaveProvider::BufferedWaveProvider(const QAudioFormat &format, QObject *parent) :
|
||||
ISampleProvider(parent)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
m_audioBuffer.remove(0, delta);
|
||||
}
|
||||
m_audioBuffer.append(samples);
|
||||
}
|
||||
|
||||
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 BufferedWaveProvider::clearBuffer()
|
||||
{
|
||||
m_audioBuffer.clear();
|
||||
}
|
||||
30
src/blacksound/sampleprovider/bufferedwaveprovider.h
Normal file
30
src/blacksound/sampleprovider/bufferedwaveprovider.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef BLACKSOUND_BUFFEREDWAVEPROVIDER_H
|
||||
#define BLACKSOUND_BUFFEREDWAVEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
|
||||
#include <QAudioFormat>
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
class BLACKSOUND_EXPORT BufferedWaveProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BufferedWaveProvider(const QAudioFormat &format, QObject *parent = nullptr);
|
||||
|
||||
void addSamples(const QVector<qint16> &samples);
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
int getBufferedBytes() const { return m_audioBuffer.size(); }
|
||||
|
||||
void clearBuffer();
|
||||
|
||||
private:
|
||||
QVector<qint16> m_audioBuffer;
|
||||
qint32 m_maxBufferSize;
|
||||
};
|
||||
|
||||
#endif // BUFFEREDWAVEPROVIDER_H
|
||||
51
src/blacksound/sampleprovider/equalizersampleprovider.cpp
Normal file
51
src/blacksound/sampleprovider/equalizersampleprovider.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "equalizersampleprovider.h"
|
||||
|
||||
EqualizerSampleProvider::EqualizerSampleProvider(ISampleProvider *sourceProvider, EqualizerPresets preset, QObject *parent) :
|
||||
ISampleProvider(parent)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
// 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 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;
|
||||
}
|
||||
}
|
||||
|
||||
double EqualizerSampleProvider::outputGain() const
|
||||
{
|
||||
return m_outputGain;
|
||||
}
|
||||
|
||||
void EqualizerSampleProvider::setOutputGain(double outputGain)
|
||||
{
|
||||
m_outputGain = outputGain;
|
||||
}
|
||||
41
src/blacksound/sampleprovider/equalizersampleprovider.h
Normal file
41
src/blacksound/sampleprovider/equalizersampleprovider.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef EQUALIZERSAMPLEPROVIDER_H
|
||||
#define EQUALIZERSAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
#include "blacksound/dsp/biquadfilter.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
|
||||
enum EqualizerPresets
|
||||
{
|
||||
VHFEmulation = 1
|
||||
};
|
||||
|
||||
class BLACKSOUND_EXPORT EqualizerSampleProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EqualizerSampleProvider(ISampleProvider *sourceProvider, EqualizerPresets preset, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setBypassEffects(bool value) { m_bypass = value; }
|
||||
|
||||
double outputGain() const;
|
||||
void setOutputGain(double outputGain);
|
||||
|
||||
private:
|
||||
void setupPreset(EqualizerPresets preset);
|
||||
|
||||
ISampleProvider *m_sourceProvider;
|
||||
|
||||
int m_channels = 1;
|
||||
bool m_bypass = false;
|
||||
double m_outputGain = 1.0;
|
||||
QVector<BiQuadFilter> m_filters;
|
||||
};
|
||||
|
||||
#endif // EQUALIZERSAMPLEPROVIDER_H
|
||||
36
src/blacksound/sampleprovider/mixingsampleprovider.cpp
Normal file
36
src/blacksound/sampleprovider/mixingsampleprovider.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "mixingsampleprovider.h"
|
||||
|
||||
int MixingSampleProvider::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
int outputLen = 0;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
21
src/blacksound/sampleprovider/mixingsampleprovider.h
Normal file
21
src/blacksound/sampleprovider/mixingsampleprovider.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef MIXINGSAMPLEPROVIDER_H
|
||||
#define MIXINGSAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
|
||||
class BLACKSOUND_EXPORT MixingSampleProvider : public ISampleProvider
|
||||
{
|
||||
public:
|
||||
MixingSampleProvider(QObject * parent = nullptr) : ISampleProvider(parent) {}
|
||||
|
||||
void addMixerInput(ISampleProvider *provider) { m_sources.append(provider); }
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
private:
|
||||
QVector<ISampleProvider*> m_sources;
|
||||
};
|
||||
|
||||
#endif // MIXINGSAMPLEPROVIDER_H
|
||||
24
src/blacksound/sampleprovider/pinknoisegenerator.cpp
Normal file
24
src/blacksound/sampleprovider/pinknoisegenerator.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "pinknoisegenerator.h"
|
||||
|
||||
int PinkNoiseGenerator::readSamples(QVector<qint16> &samples, qint64 count)
|
||||
{
|
||||
samples.clear();
|
||||
samples.fill(0, count);
|
||||
|
||||
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;
|
||||
}
|
||||
29
src/blacksound/sampleprovider/pinknoisegenerator.h
Normal file
29
src/blacksound/sampleprovider/pinknoisegenerator.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef PINKNOISEGENERATOR_H
|
||||
#define PINKNOISEGENERATOR_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
#include <QVector>
|
||||
|
||||
#include <array>
|
||||
|
||||
class BLACKSOUND_EXPORT PinkNoiseGenerator : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PinkNoiseGenerator(QObject *parent = nullptr) : ISampleProvider(parent) {}
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setGain(double gain) { m_gain = gain; }
|
||||
|
||||
private:
|
||||
QRandomGenerator random;
|
||||
std::array<double, 7> pinkNoiseBuffer = {0};
|
||||
double m_gain = 0.0;
|
||||
};
|
||||
|
||||
#endif // PINKNOISEGENERATOR_H
|
||||
22
src/blacksound/sampleprovider/resourcesound.cpp
Normal file
22
src/blacksound/sampleprovider/resourcesound.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const QVector<qint16>& ResourceSound::audioData()
|
||||
{
|
||||
return m_samples;
|
||||
}
|
||||
22
src/blacksound/sampleprovider/resourcesound.h
Normal file
22
src/blacksound/sampleprovider/resourcesound.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef RESOURCESOUND_H
|
||||
#define RESOURCESOUND_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/wav/wavfile.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class ResourceSound
|
||||
{
|
||||
public:
|
||||
ResourceSound(const QString &audioFileName);
|
||||
|
||||
const QVector<qint16> &audioData();
|
||||
|
||||
private:
|
||||
WavFile *m_wavFile;
|
||||
QVector<qint16> m_samples;
|
||||
};
|
||||
|
||||
#endif // RESOURCESOUND_H
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "resourcesoundsampleprovider.h"
|
||||
#include <QDebug>
|
||||
|
||||
ResourceSoundSampleProvider::ResourceSoundSampleProvider(const ResourceSound &resourceSound, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_resourceSound(resourceSound)
|
||||
{
|
||||
tempBuffer.resize(tempBufferSize);
|
||||
}
|
||||
|
||||
int ResourceSoundSampleProvider::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 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;
|
||||
}
|
||||
35
src/blacksound/sampleprovider/resourcesoundsampleprovider.h
Normal file
35
src/blacksound/sampleprovider/resourcesoundsampleprovider.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
#define RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "sampleprovider.h"
|
||||
#include "resourcesound.h"
|
||||
|
||||
class BLACKSOUND_EXPORT ResourceSoundSampleProvider : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ResourceSoundSampleProvider(const ResourceSound &resourceSound, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
virtual bool isFinished() override;
|
||||
|
||||
bool looping() const;
|
||||
void setLooping(bool looping);
|
||||
|
||||
float gain() const;
|
||||
void setGain(float gain);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#endif // RESOURCESOUNDSAMPLEPROVIDER_H
|
||||
21
src/blacksound/sampleprovider/sampleprovider.h
Normal file
21
src/blacksound/sampleprovider/sampleprovider.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef SAMPLEPROVIDER_H
|
||||
#define SAMPLEPROVIDER_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
class BLACKSOUND_EXPORT ISampleProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ISampleProvider(QObject *parent = nullptr) : QObject(parent) {}
|
||||
virtual ~ISampleProvider() {}
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) = 0;
|
||||
|
||||
virtual bool isFinished() { return false; }
|
||||
};
|
||||
|
||||
#endif // SAMPLEPROVIDER_H
|
||||
22
src/blacksound/sampleprovider/sampleprovider.pri
Normal file
22
src/blacksound/sampleprovider/sampleprovider.pri
Normal file
@@ -0,0 +1,22 @@
|
||||
SOURCES += \
|
||||
$$PWD/bufferedwaveprovider.cpp \
|
||||
$$PWD/mixingsampleprovider.cpp \
|
||||
$$PWD/equalizersampleprovider.cpp \
|
||||
$$PWD/pinknoisegenerator.cpp \
|
||||
$$PWD/resourcesound.cpp \
|
||||
$$PWD/resourcesoundsampleprovider.cpp \
|
||||
$$PWD/samples.cpp \
|
||||
$$PWD/sawtoothgenerator.cpp \
|
||||
$$PWD/simplecompressoreffect.cpp \
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/bufferedwaveprovider.h \
|
||||
$$PWD/mixingsampleprovider.h \
|
||||
$$PWD/resourcesound.h \
|
||||
$$PWD/resourcesoundsampleprovider.h \
|
||||
$$PWD/sampleprovider.h \
|
||||
$$PWD/equalizersampleprovider.h \
|
||||
$$PWD/pinknoisegenerator.h \
|
||||
$$PWD/samples.h \
|
||||
$$PWD/sawtoothgenerator.h \
|
||||
$$PWD/simplecompressoreffect.h \
|
||||
29
src/blacksound/sampleprovider/samples.cpp
Normal file
29
src/blacksound/sampleprovider/samples.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "samples.h"
|
||||
#include "blackmisc/directoryutils.h"
|
||||
|
||||
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")
|
||||
{ }
|
||||
|
||||
ResourceSound Samples::click() const
|
||||
{
|
||||
return m_click;
|
||||
}
|
||||
|
||||
ResourceSound Samples::crackle() const
|
||||
{
|
||||
return m_crackle;
|
||||
}
|
||||
|
||||
ResourceSound Samples::whiteNoise() const
|
||||
{
|
||||
return m_whiteNoise;
|
||||
}
|
||||
24
src/blacksound/sampleprovider/samples.h
Normal file
24
src/blacksound/sampleprovider/samples.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef SAMPLES_H
|
||||
#define SAMPLES_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "resourcesound.h"
|
||||
|
||||
class BLACKSOUND_EXPORT Samples
|
||||
{
|
||||
public:
|
||||
static Samples &instance();
|
||||
|
||||
ResourceSound crackle() const;
|
||||
ResourceSound click() const;
|
||||
ResourceSound whiteNoise() const;
|
||||
|
||||
private:
|
||||
Samples();
|
||||
|
||||
ResourceSound m_crackle;
|
||||
ResourceSound m_click;
|
||||
ResourceSound m_whiteNoise;
|
||||
};
|
||||
|
||||
#endif // SAMPLES_H
|
||||
23
src/blacksound/sampleprovider/sawtoothgenerator.cpp
Normal file
23
src/blacksound/sampleprovider/sawtoothgenerator.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "sawtoothgenerator.h"
|
||||
#include <cmath>
|
||||
|
||||
SawToothGenerator::SawToothGenerator(double frequency, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_frequency(frequency)
|
||||
{}
|
||||
|
||||
int SawToothGenerator::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 count;
|
||||
}
|
||||
30
src/blacksound/sampleprovider/sawtoothgenerator.h
Normal file
30
src/blacksound/sampleprovider/sawtoothgenerator.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef SAWTOOTHGENERATOR_H
|
||||
#define SAWTOOTHGENERATOR_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "blacksound/sampleprovider/sampleprovider.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
#include <QVector>
|
||||
|
||||
#include <array>
|
||||
|
||||
class BLACKSOUND_EXPORT SawToothGenerator : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SawToothGenerator(double frequency, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#endif // SAWTOOTHGENERATOR_H
|
||||
45
src/blacksound/sampleprovider/simplecompressoreffect.cpp
Normal file
45
src/blacksound/sampleprovider/simplecompressoreffect.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "simplecompressoreffect.h"
|
||||
#include <QDebug>
|
||||
|
||||
SimpleCompressorEffect::SimpleCompressorEffect(ISampleProvider *source, QObject *parent) :
|
||||
ISampleProvider(parent),
|
||||
m_sourceStream(source)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 SimpleCompressorEffect::setEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void SimpleCompressorEffect::setMakeUpGain(double gain)
|
||||
{
|
||||
m_simpleCompressor.setMakeUpGain(gain);
|
||||
}
|
||||
32
src/blacksound/sampleprovider/simplecompressoreffect.h
Normal file
32
src/blacksound/sampleprovider/simplecompressoreffect.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef SIMPLECOMPRESSOREFFECT_H
|
||||
#define SIMPLECOMPRESSOREFFECT_H
|
||||
|
||||
#include "blacksound/blacksoundexport.h"
|
||||
#include "sampleprovider.h"
|
||||
#include "blacksound/dsp/SimpleComp.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class BLACKSOUND_EXPORT SimpleCompressorEffect : public ISampleProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SimpleCompressorEffect(ISampleProvider *source, QObject *parent = nullptr);
|
||||
|
||||
virtual int readSamples(QVector<qint16> &samples, qint64 count) override;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setMakeUpGain(double gain);
|
||||
|
||||
private:
|
||||
|
||||
QTimer m_timer;
|
||||
ISampleProvider *m_sourceStream;
|
||||
bool m_enabled = true;
|
||||
chunkware_simple::SimpleComp m_simpleCompressor;
|
||||
const int channels = 1;
|
||||
};
|
||||
|
||||
#endif // SIMPLECOMPRESSOREFFECT_H
|
||||
Reference in New Issue
Block a user