/**************************************************************************
Copyright (C) 2019 Arnaud Champenois arthelion@free.fr
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 3 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, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "WaveGenerator.h"
#include "../JuceLibraryCode/JuceHeader.h"
#include <array>
constexpr std::array<double, 11> harmonics({ 500, 200, 150, 100, 75, 50, 30, 20, 10, 5, 2 });
std::vector<double> SineGenerator::sSineTable;
void SineGenerator::init(double samplingFreq) {
mTableSize = int(samplingFreq);
if (sSineTable.size() != mTableSize) {
sSineTable.clear();
sSineTable.reserve(mTableSize);
double locPhase = 0;
double incr = double(2.0* M_PI / samplingFreq);
for (size_t i = 0; i < mTableSize; i++, locPhase += incr) {
double value = std::sin(locPhase);
sSineTable.push_back(value);
}
}
mTableData = sSineTable.data();
}
void SquareGenerator::initSquareTable(std::vector<double>&table, double samplingFreq, double harmonicsIn) {
size_t tableSize = size_t(samplingFreq);
if (table.size() != tableSize) {
table.clear();
table.reserve(tableSize);
double locPhase = 0;
double incr = double(2.0* M_PI / samplingFreq);
for (size_t i = 0; i < tableSize; i++, locPhase += incr) {
double value = 0;
for (double factor = 1.0; factor <= harmonicsIn; factor += 2.0) {
value += std::sin(locPhase*factor) / factor;
}
value *= double(4.0 / M_PI);
table.push_back(value);
}
}
}
void SawToothGenerator::initSawTable(std::vector<double>&table, double samplingFreq, double harmonicsIn) {
size_t tableSize = size_t(samplingFreq);
if (table.size() != tableSize) {
table.clear();
table.reserve(tableSize);
double locPhase = 0;
double incr = double(2.0* M_PI / samplingFreq);
for (size_t i = 0; i < tableSize; i++, locPhase += incr) {
double value = 0;
double sign = -1;
for (double factor = 1.0; factor < harmonicsIn; factor += 1.0) {
value += sign * sin(locPhase*factor) / factor;
sign *= -1;
}
value = double(- (2.0 / M_PI)*value);
table.push_back(value);
}
}
}
std::vector < MultiTableGenerator::TableDescriptor > SawToothGenerator::sSawTables;
void SawToothGenerator::init(double samplingFreq)
{
mTableSize = int(samplingFreq);
mPhaseMax = double(mTableSize - 1);
if (!sSawTables.empty() && sSawTables.front().getTable().size() == size_t(samplingFreq))
return;
sSawTables.clear();
for (double h : harmonics) {
TableDescriptor t(0.5*samplingFreq / h);
initSawTable(t.getTable(), samplingFreq, h);
sSawTables.push_back(t);
}
}
std::vector<MultiTableGenerator::TableDescriptor> SquareGenerator::sSquareTables;
void SquareGenerator::init(double samplingFreq)
{
mTableSize = int(samplingFreq);
mPhaseMax = double(mTableSize - 1);
if (!sSquareTables.empty() && sSquareTables.front().getTable().size() == size_t(samplingFreq))
return;
sSquareTables.clear();
for (double h : harmonics) {
TableDescriptor t(0.5*samplingFreq / h);
initSquareTable(t.getTable(), samplingFreq, h);
sSquareTables.push_back(t);
}
}
void RevertSawToothGenerator::initRSawTable(std::vector<double>& table, double samplingFreq, double harmonicsIn, double deltaPhase)
{
size_t tableSize = size_t(samplingFreq);
if (table.size() != tableSize) {
table.clear();
table.reserve(tableSize);
double locPhase = deltaPhase;
double incr = double(2.0* M_PI / samplingFreq);
for (size_t i = 0; i < tableSize; i++, locPhase += incr) {
double value = 0;
double sign = -1;
for (double factor = 1.0; factor < harmonicsIn; factor += 1.0) {
value += sign * sin(locPhase*factor) / factor;
sign *= -1;
}
value = double((2.0 / M_PI)*value-0.5);
table.push_back(value);
}
}
}
std::vector < MultiTableGenerator::TableDescriptor > RevertSawToothGenerator::sRSawTables;
void RevertSawToothGenerator::init(double samplingFreq)
{
mTableSize = int(samplingFreq);
mPhaseMax = double(mTableSize - 1);
if (!sRSawTables.empty() && sRSawTables.front().getTable().size() == size_t(samplingFreq))
return;
sRSawTables.clear();
for (double h : harmonics) {
TableDescriptor t(0.5*samplingFreq / h);
initRSawTable(t.getTable(), samplingFreq, h);
sRSawTables.push_back(t);
}
}
void PWMGenerator::init(double samplingFreq)
{
mSawGenerator.init(samplingFreq);
mRSawGenerator.init(samplingFreq);
}
std::vector<MultiTableGenerator::TableDescriptor> OddHarmonicsGenerator::sHarmonicsTables;
void OddHarmonicsGenerator::init(double samplingFreq)
{
mTableSize = int(samplingFreq);
mPhaseMax = double(mTableSize - 1);
if (!sHarmonicsTables.empty() && sHarmonicsTables.front().getTable().size() == size_t(samplingFreq))
return;
sHarmonicsTables.clear();
for (double h : harmonics) {
TableDescriptor t(0.5*samplingFreq / h);
initHarmonicsTable(t.getTable(), samplingFreq,h);
sHarmonicsTables.push_back(t);
}
}
void OddHarmonicsGenerator::initHarmonicsTable(std::vector<double>& table, double samplingFreq, double harmonicsIn) {
size_t tableSize = size_t(samplingFreq);
if (table.size() != tableSize) {
table.clear();
table.reserve(tableSize);
double locPhase = 0;
double incr = 2.0* double(M_PI) / samplingFreq;
for (size_t i = 0; i < tableSize; i++, locPhase += incr) {
double value = 0;
for (double factor = 2.0; factor < harmonicsIn; factor += 2.0) {
value += sin(locPhase*factor) / factor;
}
table.push_back(value*2.0);
}
}
}
std::vector<MultiTableGenerator::TableDescriptor> EvenHarmonicsGenerator::sHarmonicsTables;
void EvenHarmonicsGenerator::init(double samplingFreq)
{
mTableSize = int(samplingFreq);
mPhaseMax = double(mTableSize - 1);
if (!sHarmonicsTables.empty() && sHarmonicsTables.front().getTable().size() == size_t(samplingFreq))
return;
sHarmonicsTables.clear();
for (double h : harmonics) {
TableDescriptor t(0.5*samplingFreq / h);
initHarmonicsTable(t.getTable(), samplingFreq, h);
sHarmonicsTables.push_back(t);
}
}
void EvenHarmonicsGenerator::initHarmonicsTable(std::vector<double>& table, double samplingFreq, double harmonicsIn) {
size_t tableSize = size_t(samplingFreq);
if (table.size() != tableSize) {
table.clear();
table.reserve(tableSize);
double locPhase = 0;
double incr = 2.0* double(M_PI) / samplingFreq;
for (size_t i = 0; i < tableSize; i++, locPhase += incr) {
double value = 0;
for (double factor = 3.0; factor < harmonicsIn; factor += 2.0) {
value += sin(locPhase*factor) / factor;
}
table.push_back(value*3.0);
}
}
}
std::vector<double> NoiseGenerator::sNoiseTable;
void NoiseGenerator::init(double samplingFreq)
{
mTableSize = int(samplingFreq);
if (sNoiseTable.size() != size_t(mTableSize)) {
sNoiseTable.clear();
sNoiseTable.reserve(mTableSize);
juce::Random random;
for (int i = 0; i < mTableSize; i++) {
sNoiseTable.push_back(random.nextDouble()-0.5);
}
}
mTableData = sNoiseTable.data();
juce::Random random;
phase = random.nextInt(mTableSize);
}
void DelayLine::init(double samplingFreq) {
mSamplingFreq = samplingFreq;
mDelayTable.resize(int(ceil(samplingFreq*mMaxDelay)), 0.0);
mTableData = mDelayTable.data();
mTableSize = mDelayTable.size();
}