Sorry, didn't wanna blast you with my code and say please fix it
..
the stream / main
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Signals.h"
#include "Waveforms.h"
#include "Wavetable.h"
#include <array>
#include <cmath>
#include "DspMath.h"
#include <iostream>
#include "Synth.h"
#include "SynthFactory.h"
#include "Spectrometer.h"
#include <functional>
#include <queue>
using namespace std;
using namespace synth;
#include <concurrent_queue.h>
class SynthStream : public sf::SoundStream
{
public:
SynthStream(synth::Synth& synth, Spectrometer& spectrometer) :
_synth((synth)),
_spectrometer(spectrometer)
{
this->setLoop(false);
this->initialize(1, 44100);
}
private:
//queue<Signal> _results;
Synth& _synth;
Spectrometer& _spectrometer;
virtual bool onGetData(Chunk& data)
{
Signal signal = _synth.getSignal(4096);
const SignalVector& signalVector = signal.getSignalVector();
unsigned int length = signalVector.size();
sf::Int16* samples = new sf::Int16[length];
for (int sample = 0; sample < length; sample++)
{
double value = signalVector[sample];
samples[sample] = 10000* value;
if (sample % 10 == 0)
_spectrometer.addValue(value);
}
data.samples = samples;
data.sampleCount = length;
return true;
}
virtual void onSeek(sf::Time timeOffset)
{
}
};
int main()
{
const int width = 800;
const int height = 200;
sf::RenderWindow window(sf::VideoMode(width, height), "StubbzDSP.CPP.Visualization");
unsigned int sampleRate = 44100;
const synth::Wavetable wavetable = synth::wavetable::getWavetable();
const synth::filters::FilterTable filterTable = synth::filters::getFilterTable();
synth::DefaultSynthFactory synthFactory;
synth::Synth synth = synthFactory.createSynth(sampleRate, wavetable, filterTable);
unsigned int rootNote = 69 - 24;
synth.enableNote(rootNote, 1);
synth.enableNote(rootNote + 7, 1);
//synth.enableNote(rootNote - 5, 1);
double scale = (height) / 4;
sf::View view(sf::FloatRect(0, 0, width, height));
view.move(0, -scale * 2);
window.setView(view);
window.setVerticalSyncEnabled(true);
Spectrometer spectrometer(width, height, 5);
SynthStream stream(synth, spectrometer);
stream.play();
std::queue<Signal> signals;
unsigned int c = 72 - 12;
unordered_map<sf::Keyboard::Key, unsigned int> keyMap {
{ sf::Keyboard::A, c }, //c
{ sf::Keyboard::W, c + 1 }, //c#
{ sf::Keyboard::S, c + 2 }, //d
{ sf::Keyboard::E, c + 3 }, //d#
{ sf::Keyboard::D, c + 4 }, //e
{ sf::Keyboard::F, c + 5 }, //f
{ sf::Keyboard::T, c + 6 }, //f#
{ sf::Keyboard::G, c + 7 }, //g
{ sf::Keyboard::Y, c + 8 }, //g#
{ sf::Keyboard::H, c + 9 }, //a
{ sf::Keyboard::U, c + 10 }, //a#
{ sf::Keyboard::J, c + 11 }, //b
{ sf::Keyboard::K, c + 12 }, //c
{ sf::Keyboard::O, c + 13 }, //c#
{ sf::Keyboard::L, c + 14 }, //d
{ sf::Keyboard::P, c + 14 }, //d#
};
double value = 0;
while (stream.getStatus() == SynthStream::Playing && window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::KeyPressed)
{
auto key = event.key.code;
auto mapping = keyMap.find(key);
if (mapping != keyMap.end()){
//synth.disableNote(mapping->second);
synth.enableNote(mapping->second, 1);
} else
{
if (key == sf::Keyboard::Up)
{
value += .2;
if (value > 1)
value = 1;
synthFactory._lfo1Freq.setValue(value);
} else if (key == sf::Keyboard::Down)
{
value -= .2;
if (value < 0)
value = 0;
synthFactory._lfo1Freq.setValue(value);
}
}
}
if (event.type == sf::Event::KeyReleased)
{
auto key = event.key.code;
auto mapping = keyMap.find(key);
if (mapping != keyMap.end()){
synth.disableNote(mapping->second);
}
}
}
window.clear(sf::Color::White);
spectrometer.draw(window);
spectrometer.draw(window);
window.display();
}
return 0;
}
Synth
#pragma once
#include "SignalGenerator.h"
#include <unordered_map>
#include "Note.h"
#include <mutex>
namespace synth{
class Synth
{
public:
Synth(unique_ptr<SignalGenerator> signalGeneratorFactory, unsigned int sampleRate);
Synth(Synth&& other);
Synth& operator=(Synth&& other) = delete;
Synth(const Synth& other) = delete;
Synth& operator= (const Synth& other) = delete;
~Synth();
void Synth::enableNote(char midiNoteId, double velocity);
void Synth::disableNote(char midiNoteId);
Signal getSignal(unsigned int signalLength);
private:
unique_ptr<SignalGenerator> _signalGenerator;
unordered_multimap<char, Note*> _notes;
unsigned int _sampleRate;
mutex _noteLock;
};
}
#include "Synth.h"
#include "DspMath.h"
#include "SignalFunctions.h"
#include <algorithm>
#include <iostream>
using namespace synth;
Synth::Synth(unique_ptr<SignalGenerator> signalGenerator, unsigned int sampleRate)
: _signalGenerator(move(signalGenerator)), _sampleRate(sampleRate){}
Synth::Synth(Synth&& other)
: _signalGenerator(move(other._signalGenerator)), _sampleRate(other._sampleRate), _notes(move(_notes)){}
Synth::~Synth(){
//TODO make sure that all the _notes are being deleted from "this->_notes"
}
void Synth::enableNote(char midiNoteId, double velocity){
_noteLock.lock();
auto existingNotes = _notes.equal_range(midiNoteId);
//TODO update velocity
for (auto it = existingNotes.first; it != existingNotes.second; ++it){
}
//TODO this current logic only allows one note of an id
if (existingNotes.first == existingNotes.second){
double frequency = dspMath::convertMidiNoteToFrequency(midiNoteId);
_notes.emplace(std::pair<char, Note*>(midiNoteId, new Note(midiNoteId, frequency, velocity)));
}
_noteLock.unlock();
}
void Synth::disableNote(char midiNoteId){
//TODO instead of erasing _notes, mark their statuses as being completed
//auto existingNotes = _notes.equal_range(midiNoteId);
_noteLock.lock();
_notes.erase(midiNoteId);
_noteLock.unlock();
}
Signal Synth::getSignal(unsigned int signalLength){
_noteLock.lock();
vector<const shared_ptr<Signal>> signals;
for (auto it = _notes.begin(); it != _notes.end(); ++it){
Note& note = *it->second;
SignalConfiguration& configuration = note.getConfiguration(signalLength, _sampleRate);
unique_ptr<SignalConfiguration> nextConfiguration = unique_ptr<SignalConfiguration>(new SignalConfiguration(note.getFrequency(), signalLength, _sampleRate, note.isNoteOff()));
SignalCache signalCache;
shared_ptr<Signal> signal = _signalGenerator->getSignal(configuration, *nextConfiguration, signalCache);
note.setConfiguration(move(nextConfiguration));
signals.push_back(signal);
if (signal->isComplete()){
this->_notes.erase(it);
}
}
_noteLock.unlock();
return signals::mixSignals(signals, signalLength);
}
spectrometer
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Thread.hpp>
#include <mutex>
class Spectrometer //: public sf::Drawable
{
public:
Spectrometer(unsigned int width, unsigned int height, double thickness);
~Spectrometer();
Spectrometer(Spectrometer&& other);
Spectrometer& operator=(Spectrometer&& other) = delete;
Spectrometer(const Spectrometer& other) = delete;
Spectrometer& operator= (const Spectrometer& other) = delete;
void addValue(double value);
sf::VertexArray _wave;
void draw(sf::RenderWindow& window) ;
private:
void setValue(unsigned x, double value);
unsigned int _width;
unsigned int _height;
double _yScale;
double _thickness;
unsigned int _currentX;
std::mutex _lock;
};
Spectrometer::~Spectrometer()
{
}
Spectrometer::Spectrometer(Spectrometer&& other)
: _width(other._width),
_height(other._height),
_yScale(other._yScale),
_wave(std::move(other._wave)),
_thickness(other._thickness),
_currentX(other._currentX)
{
}
Spectrometer::Spectrometer(unsigned width, unsigned height, double thickness)
: _width(width),
_height(height),
_yScale(height / 2),
_wave(sf::VertexArray(sf::TrianglesStrip, width * 2)),
_thickness(thickness/2),
_currentX(0)
{
for (unsigned int x = 0; x < width; x++)
{
this->setValue(x, 0);
}
}
void Spectrometer::draw(sf::RenderWindow& window)
{
_lock.lock();
window.draw(_wave);
sf::RectangleShape line(sf::Vector2f(_thickness * 2, _height));
line.setPosition(_currentX, -_yScale);
line.setFillColor(sf::Color::Black);
window.draw(line);
_lock.unlock();
}
void Spectrometer::addValue(double value)
{
_lock.lock();
if (_currentX * 2 + 1 > _wave.getVertexCount() - 1)
{
_currentX = 0;
}
this->setValue(_currentX, value);
_currentX++;
_lock.unlock();
}
void Spectrometer::setValue(unsigned int x, double value)
{
auto color = sf::Color::Black;
if (x + 1 <= _wave.getVertexCount() - 1)
{
double scaledValue = value * _yScale * .5;
_wave[2 * x] = sf::Vertex(sf::Vector2f(x, scaledValue + _thickness), color);
_wave[2 * x + 1] = sf::Vertex(sf::Vector2f(x, scaledValue - _thickness), color);
}
}