Skip to content

Instantly share code, notes, and snippets.

@prisonerjohn
Last active October 27, 2019 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prisonerjohn/350c1d31315fb84c6024a938c190acc7 to your computer and use it in GitHub Desktop.
Save prisonerjohn/350c1d31315fb84c6024a938c190acc7 to your computer and use it in GitHub Desktop.
Sensing Machines Sound Out
#include "ofApp.h"
void ofApp::setup()
{
ofBackground(0);
// Setup sound output.
ofSoundStreamSettings settings;
settings.setOutListener(this);
//settings.sampleRate = 44100;
settings.bufferSize = 256;
settings.numOutputChannels = 2;
settings.numInputChannels = 0;
soundStream.setup(settings);
phaseVal = 0;
phaseStep = 0.0f;
leftSamples.assign(settings.bufferSize, 0.0);
rightSamples.assign(settings.bufferSize, 0.0);
// Setup MIDI input.
midiIn.listInPorts();
midiIn.openPort(0);
midiIn.ignoreTypes(true, true, true);
midiIn.addListener(this);
// Build note to frequency table.
// http://subsynth.sourceforge.net/midinote2freq.html
midiFreqs.resize(127);
int a = 440; // a is 440 hz...
for (int i = 0; i < midiFreqs.size(); i++)
{
midiFreqs[i] = (a / 32.0f) * powf(2, (i - 9) / 12.0f);
}
volume.set("Volume", 0.1, 0.0, 1.0);
pan.set("Pan", 0.1, 0.0, 1.0);
resolution.set("Resolution", 32, 3, 64);
resolution.addListener(this, &ofApp::updateWaveform);
freqSpeed.set("Freq Speed", 0.2, 0.0, 1.0);
frequency.set("Frequency", 0.0, 0.0, 12544.0);
guiPanel.setup("Audio Out", "settings.json");
guiPanel.add(volume);
guiPanel.add(pan);
guiPanel.add(resolution);
guiPanel.add(freqSpeed);
guiPanel.add(frequency);
// Set initial params.
int res = resolution;
updateWaveform(res);
}
void ofApp::update()
{
pan = ofMap(ofGetMouseX(), 0, ofGetWidth(), 0, 1, true);
frequency = ofLerp(frequency, freqTarget, freqSpeed);
}
void ofApp::draw()
{
ofSetLineWidth(2.0);
// Draw the left channel history.
ofSetColor(200, 0, 0);
ofBeginShape();
for (int i = 0; i < leftSamples.size(); i++)
{
float x = ofMap(i, 0, leftSamples.size(), 0, ofGetWidth());
float y = ofMap(leftSamples[i], -1.0, 1.0, 0, 200);
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, 0, ofGetWidth(), 200);
// Draw the right channel history.
ofSetColor(200, 0, 0);
ofBeginShape();
for (int i = 0; i < rightSamples.size(); i++)
{
float x = ofMap(i, 0, rightSamples.size(), 0, ofGetWidth());
float y = ofMap(rightSamples[i], -1.0, 1.0, 200, 400);
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, 200, ofGetWidth(), 200);
// Draw the waveform.
ofSetColor(0, 200, 0);
ofBeginShape();
for (int i = 0; i < waveform.size(); i++)
{
float x = ofMap(i, 0, waveform.size() - 1, 0, ofGetWidth());
float y = ofMap(waveform[i], -1.0, 1.0, ofGetHeight() - 120, ofGetHeight());
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, ofGetHeight() - 120, ofGetWidth(), 120);
guiPanel.draw();
}
// https://openframeworks.cc/ofBook/chapters/sound.html
void ofApp::updateWaveform(int& resolution)
{
waveform.resize(resolution);
// "waveformStep" maps a full oscillation of sin() to the size
// of the waveform lookup table
float waveformStep = TWO_PI / (float)waveform.size();
for (int i = 0; i < waveform.size(); i++)
{
waveform[i] = sin(i * waveformStep);
}
}
void ofApp::audioOut(ofSoundBuffer& buffer)
{
float leftScale = 1 - pan;
float rightScale = pan;
// sin(n) seems to have trouble when n is very large.
// Keep phase in the range of 0-TWO_PI.
while (phaseVal > TWO_PI)
{
phaseVal -= TWO_PI;
}
float sampleRate = buffer.getSampleRate();
phaseStep = frequency / sampleRate;
for (int i = 0; i < buffer.getNumFrames(); i++)
{
phaseVal += phaseStep;
int idx = (int)(phaseVal * waveform.size()) % waveform.size();
float sample = waveform[idx];
leftSamples[i] = buffer[i * 2 + 0] = sample * volume * leftScale;
rightSamples[i] = buffer[i * 2 + 1] = sample * volume * rightScale;
}
}
void ofApp::newMidiMessage(ofxMidiMessage& msg)
{
ofLogNotice(__FUNCTION__) << msg.getStatusString(msg.status) << " Pitch: " << msg.pitch << " Velocity: " << msg.velocity << " Control: " << msg.control << " Value: " << msg.value;
if (msg.status == MidiStatus::MIDI_NOTE_ON)
{
freqTarget = midiFreqs[msg.pitch];
}
else if (msg.status == MidiStatus::MIDI_NOTE_OFF)
{
freqTarget = 0;
}
}
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
#include "ofxMidi.h"
class ofApp : public ofBaseApp, public ofxMidiListener
{
public:
void setup();
void update();
void draw();
void updateWaveform(int& resolution);
void audioOut(ofSoundBuffer& buffer);
void newMidiMessage(ofxMidiMessage& msg);
ofSoundStream soundStream;
std::vector<float> leftSamples;
std::vector<float> rightSamples;
ofxMidiIn midiIn;
std::vector<float> midiFreqs;
float freqTarget;
std::vector<float> waveform;
float phaseVal;
float phaseStep;
ofParameter<float> volume;
ofParameter<float> pan;
ofParameter<int> resolution;
ofParameter<float> freqSpeed;
ofParameter<float> frequency;
ofxPanel guiPanel;
};
#include "ofApp.h"
void ofApp::setup()
{
ofBackground(0);
ofSoundStreamSettings settings;
settings.setOutListener(this);
//settings.sampleRate = 44100;
settings.bufferSize = 256;
settings.numOutputChannels = 2;
settings.numInputChannels = 0;
soundStream.setup(settings);
phaseVal = 0;
phaseStep = 0.0f;
leftSamples.assign(settings.bufferSize, 0.0);
rightSamples.assign(settings.bufferSize, 0.0);
volume.set("Volume", 0.1, 0.0, 1.0);
pan.set("Pan", 0.1, 0.0, 1.0);
phaseSpeed.set("Phase Speed", 0.15, 0.0, 1.0);
doNoise.set("Do Noise", false);
guiPanel.setup("Audio Out", "settings.json");
guiPanel.add(volume);
guiPanel.add(pan);
guiPanel.add(phaseSpeed);
guiPanel.add(doNoise);
}
void ofApp::update()
{
pan = ofMap(ofGetMouseX(), 0, ofGetWidth(), 0, 1, true);
float phaseStepTarget = ofMap(ofGetMouseY(), 0, ofGetHeight(), phaseSpeed, 0, true);
phaseStep = ofLerp(phaseStep, phaseStepTarget, 0.95);
}
void ofApp::draw()
{
ofSetLineWidth(2.0);
// Draw the left channel history.
ofSetColor(200, 0, 0);
ofBeginShape();
for (int i = 0; i < leftSamples.size(); i++)
{
float x = ofMap(i, 0, leftSamples.size(), 0, ofGetWidth());
float y = ofMap(leftSamples[i], -1.0, 1.0, 0, 200);
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, 0, ofGetWidth(), 200);
// Draw the right channel history.
ofSetColor(200, 0, 0);
ofBeginShape();
for (int i = 0; i < rightSamples.size(); i++)
{
float x = ofMap(i, 0, rightSamples.size(), 0, ofGetWidth());
float y = ofMap(rightSamples[i], -1.0, 1.0, 200, 400);
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, 200, ofGetWidth(), 200);
guiPanel.draw();
}
void ofApp::audioOut(ofSoundBuffer& buffer)
{
float leftScale = 1 - pan;
float rightScale = pan;
// sin(n) seems to have trouble when n is very large.
// Keep phase in the range of 0-TWO_PI.
while (phaseVal > TWO_PI)
{
phaseVal -= TWO_PI;
}
if (doNoise)
{
for (int i = 0; i < buffer.getNumFrames(); i++)
{
phaseVal += phaseStep;
float sample = ofSignedNoise(phaseVal);
leftSamples[i] = buffer[i * 2 + 0] = sample * volume * leftScale;
rightSamples[i] = buffer[i * 2 + 1] = sample * volume * rightScale;
}
}
else
{
for (int i = 0; i < buffer.getNumFrames(); i++)
{
phaseVal += phaseStep;
float sample = sin(phaseVal);
leftSamples[i] = buffer[i * 2 + 0] = sample * volume * leftScale;
rightSamples[i] = buffer[i * 2 + 1] = sample * volume * rightScale;
}
}
}
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
class ofApp : public ofBaseApp
{
public:
void setup();
void update();
void draw();
void audioOut(ofSoundBuffer& buffer);
ofSoundStream soundStream;
std::vector<float> leftSamples;
std::vector<float> rightSamples;
float phaseVal;
float phaseStep;
ofParameter<float> volume;
ofParameter<float> pan;
ofParameter<float> phaseSpeed;
ofParameter<bool> doNoise;
ofxPanel guiPanel;
};
#include "ofApp.h"
void ofApp::setup()
{
ofBackground(0);
ofSoundStreamSettings settings;
settings.setOutListener(this);
//settings.sampleRate = 44100;
settings.bufferSize = 256;
settings.numOutputChannels = 2;
settings.numInputChannels = 0;
soundStream.setup(settings);
guiPanel.setup("Audio Out", "settings.json");
}
void ofApp::update()
{
}
void ofApp::draw()
{
guiPanel.draw();
}
void ofApp::audioOut(ofSoundBuffer& buffer)
{
}
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
class ofApp : public ofBaseApp
{
public:
void setup();
void update();
void draw();
void audioOut(ofSoundBuffer& buffer);
ofSoundStream soundStream;
ofxPanel guiPanel;
};
#include "ofApp.h"
void ofApp::setup()
{
ofBackground(0);
ofSoundStreamSettings settings;
settings.setOutListener(this);
//settings.sampleRate = 44100;
settings.bufferSize = 256;
settings.numOutputChannels = 2;
settings.numInputChannels = 0;
soundStream.setup(settings);
phaseVal = 0;
phaseStep = 0.0f;
leftSamples.assign(settings.bufferSize, 0.0);
rightSamples.assign(settings.bufferSize, 0.0);
volume.set("Volume", 0.1, 0.0, 1.0);
pan.set("Pan", 0.1, 0.0, 1.0);
phaseSpeed.set("Phase Speed", 0.15, 0.0, 1.0);
guiPanel.setup("Audio Out", "settings.json");
guiPanel.add(volume);
guiPanel.add(pan);
guiPanel.add(phaseSpeed);
}
void ofApp::update()
{
pan = ofMap(ofGetMouseX(), 0, ofGetWidth(), 0, 1, true);
float phaseStepTarget = ofMap(ofGetMouseY(), 0, ofGetHeight(), phaseSpeed, 0, true);
phaseStep = ofLerp(phaseStep, phaseStepTarget, 0.95);
}
void ofApp::draw()
{
ofSetLineWidth(2.0);
// Draw the left channel history.
ofSetColor(200, 0, 0);
ofBeginShape();
for (int i = 0; i < leftSamples.size(); i++)
{
float x = ofMap(i, 0, leftSamples.size(), 0, ofGetWidth());
float y = ofMap(leftSamples[i], -1.0, 1.0, 0, 200);
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, 0, ofGetWidth(), 200);
// Draw the right channel history.
ofSetColor(200, 0, 0);
ofBeginShape();
for (int i = 0; i < rightSamples.size(); i++)
{
float x = ofMap(i, 0, rightSamples.size(), 0, ofGetWidth());
float y = ofMap(rightSamples[i], -1.0, 1.0, 200, 400);
ofVertex(x, y);
}
ofEndShape(false);
ofSetColor(225);
ofNoFill();
ofDrawRectangle(0, 200, ofGetWidth(), 200);
guiPanel.draw();
}
void ofApp::audioOut(ofSoundBuffer& buffer)
{
float leftScale = 1 - pan;
float rightScale = pan;
// sin(n) seems to have trouble when n is very large.
// Keep phase in the range of 0-TWO_PI.
while (phaseVal > TWO_PI)
{
phaseVal -= TWO_PI;
}
for (int i = 0; i < buffer.getNumFrames(); i++)
{
phaseVal += phaseStep;
float sample = sin(phaseVal);
leftSamples[i] = buffer[i * 2 + 0] = sample * volume * leftScale;
rightSamples[i] = buffer[i * 2 + 1] = sample * volume * rightScale;
}
}
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
class ofApp : public ofBaseApp
{
public:
void setup();
void update();
void draw();
void audioOut(ofSoundBuffer& buffer);
ofSoundStream soundStream;
std::vector<float> leftSamples;
std::vector<float> rightSamples;
float phaseVal;
float phaseStep;
ofParameter<float> volume;
ofParameter<float> pan;
ofParameter<float> phaseSpeed;
ofxPanel guiPanel;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment