@@ -1,9 +1,7 @@ | |||||
ARCH ?= linux | ARCH ?= linux | ||||
CXXFLAGS = -MMD -fPIC -g -Wall -std=c++11 -O3 -ffast-math -DTEST \ | |||||
CXXFLAGS = -MMD -fPIC -g -Wall -std=c++11 -O3 -msse -mfpmath=sse -ffast-math -DTEST \ | |||||
-I./src -I../../include -I./eurorack \ | -I./src -I../../include -I./eurorack \ | ||||
-fasm \ | |||||
-finline \ | |||||
-fshort-enums | -fshort-enums | ||||
LDFLAGS = | LDFLAGS = | ||||
@@ -57,3 +57,51 @@ Percentages are progress amounts, X means won't port | |||||
#### [100%] Branches (Bernoulli Gate) | #### [100%] Branches (Bernoulli Gate) | ||||
#### [100%] Blinds (Quad VC-polarizer) | #### [100%] Blinds (Quad VC-polarizer) | ||||
#### [100%] Veils (Quad VCA) | #### [100%] Veils (Quad VCA) | ||||
### Sound sources | |||||
- [[Macro Oscillator]] (based on [Braids](http://mutable-instruments.net/modules/braids)) | |||||
- [[Modal Synthesizer]] (based on [Elements](http://mutable-instruments.net/modules/elements)) | |||||
### Modulation sources | |||||
- [[Tidal Modulator]] (based on [Tides](http://mutable-instruments.net/modules/tides)) | |||||
### Sound modifiers | |||||
- [[Texture Synthesizer]] (based on [Clouds](http://mutable-instruments.net/modules/clouds)) | |||||
- [[Meta Modulator]] (based on [Warps](http://mutable-instruments.net/modules/warps)) | |||||
- [[Resonator]] (based on [Rings](http://mutable-instruments.net/modules/rings)) | |||||
### Plumbing | |||||
- [[Multiples]] (based on [Links](http://mutable-instruments.net/modules/links)) | |||||
- [[Utilities]] (based on [Kinks](http://mutable-instruments.net/modules/kinks)) | |||||
- [[Mixer]] (based on [Shades](http://mutable-instruments.net/modules/shades)) | |||||
- [[Bernoulli Gate]] (based on [Branches](http://mutable-instruments.net/modules/branches)) | |||||
- [[Quad VC-polarizer]] (based on [Blinds](http://mutable-instruments.net/modules/blinds)) | |||||
- [[Quad VCA]] (based on [Veils](http://mutable-instruments.net/modules/veils)) | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 | |||||
 |
@@ -1,5 +1,6 @@ | |||||
#include "AudibleInstruments.hpp" | |||||
#include <string.h> | #include <string.h> | ||||
#include "AudibleInstruments.hpp" | |||||
#include "dsp.hpp" | |||||
#include "braids/macro_oscillator.h" | #include "braids/macro_oscillator.h" | ||||
@@ -28,8 +29,8 @@ struct Braids : Module { | |||||
}; | }; | ||||
braids::MacroOscillator *osc; | braids::MacroOscillator *osc; | ||||
int bufferFrame = 0; | |||||
int16_t buffer[24] = {}; | |||||
SampleRateConverter<1> src; | |||||
DoubleRingBuffer<float, 256> outputBuffer; | |||||
bool lastTrig = false; | bool lastTrig = false; | ||||
Braids(); | Braids(); | ||||
@@ -54,9 +55,6 @@ Braids::~Braids() { | |||||
} | } | ||||
void Braids::step() { | void Braids::step() { | ||||
// TODO Sample rate convert from 96000Hz | |||||
setf(outputs[OUT_OUTPUT], 5.0*(buffer[bufferFrame] / 32768.0)); | |||||
// Trigger | // Trigger | ||||
bool trig = getf(inputs[TRIG_INPUT]) >= 1.0; | bool trig = getf(inputs[TRIG_INPUT]) >= 1.0; | ||||
if (!lastTrig && trig) { | if (!lastTrig && trig) { | ||||
@@ -64,8 +62,8 @@ void Braids::step() { | |||||
} | } | ||||
lastTrig = trig; | lastTrig = trig; | ||||
if (++bufferFrame >= 24) { | |||||
bufferFrame = 0; | |||||
// Render frames | |||||
if (outputBuffer.empty()) { | |||||
// Set shape | // Set shape | ||||
int shape = roundf(params[SHAPE_PARAM]); | int shape = roundf(params[SHAPE_PARAM]); | ||||
osc->set_shape((braids::MacroOscillatorShape) shape); | osc->set_shape((braids::MacroOscillatorShape) shape); | ||||
@@ -82,8 +80,28 @@ void Braids::step() { | |||||
int16_t p = clampf((pitch * 12.0 + 60) * 128, 0, INT16_MAX); | int16_t p = clampf((pitch * 12.0 + 60) * 128, 0, INT16_MAX); | ||||
osc->set_pitch(p); | osc->set_pitch(p); | ||||
// TODO: add a sync input buffer (must be sample rate converted) | |||||
uint8_t sync_buffer[24] = {}; | uint8_t sync_buffer[24] = {}; | ||||
osc->Render(sync_buffer, buffer, 24); | |||||
int16_t render_buffer[24]; | |||||
osc->Render(sync_buffer, render_buffer, 24); | |||||
// Sample rate convert | |||||
float in[24]; | |||||
for (int i = 0; i < 24; i++) { | |||||
in[i] = render_buffer[i] / 32768.0; | |||||
} | |||||
src.setRatio(gRack->sampleRate / 96000.0); | |||||
int inLen = 24; | |||||
int outLen = outputBuffer.capacity(); | |||||
src.process(in, &inLen, outputBuffer.endData(), &outLen); | |||||
outputBuffer.endIncr(outLen); | |||||
} | |||||
// Output | |||||
if (!outputBuffer.empty()) { | |||||
setf(outputs[OUT_OUTPUT], 5.0 * outputBuffer.shift()); | |||||
} | } | ||||
} | } | ||||
@@ -45,8 +45,8 @@ static void computeChannel(const float *in, const float *p, float threshold, flo | |||||
bool gate = (out >= 1.0); | bool gate = (out >= 1.0); | ||||
if (gate && !*lastGate) { | if (gate && !*lastGate) { | ||||
// trigger | // trigger | ||||
std::uniform_real_distribution<float> dist(0.0, 1.0); | |||||
bool toss = (dist(rng) < threshold + getf(p)); | |||||
float r = randomf(); | |||||
bool toss = (r < threshold + getf(p)); | |||||
if (mode < 0.5) { | if (mode < 0.5) { | ||||
// direct mode | // direct mode | ||||
*outcome = toss; | *outcome = toss; | ||||
@@ -1,5 +1,6 @@ | |||||
#include "AudibleInstruments.hpp" | |||||
#include <string.h> | #include <string.h> | ||||
#include "AudibleInstruments.hpp" | |||||
#include "dsp.hpp" | |||||
#include "clouds/dsp/granular_processor.h" | #include "clouds/dsp/granular_processor.h" | ||||
@@ -33,14 +34,15 @@ struct Clouds : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
SampleRateConverter<2> inputSrc; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<2>, 256> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
uint8_t *block_mem; | uint8_t *block_mem; | ||||
uint8_t *block_ccm; | uint8_t *block_ccm; | ||||
clouds::GranularProcessor *processor; | clouds::GranularProcessor *processor; | ||||
int bufferFrame = 0; | |||||
float inL[32] = {}; | |||||
float inR[32] = {}; | |||||
float outL[32] = {}; | |||||
float outR[32] = {}; | |||||
bool triggered = false; | bool triggered = false; | ||||
Clouds(); | Clouds(); | ||||
@@ -56,10 +58,8 @@ Clouds::Clouds() { | |||||
const int memLen = 118784; | const int memLen = 118784; | ||||
const int ccmLen = 65536 - 128; | const int ccmLen = 65536 - 128; | ||||
block_mem = new uint8_t[memLen]; | |||||
memset(block_mem, 0, memLen); | |||||
block_ccm = new uint8_t[ccmLen]; | |||||
memset(block_ccm, 0, ccmLen); | |||||
block_mem = new uint8_t[memLen](); | |||||
block_ccm = new uint8_t[ccmLen](); | |||||
processor = new clouds::GranularProcessor(); | processor = new clouds::GranularProcessor(); | ||||
memset(processor, 0, sizeof(*processor)); | memset(processor, 0, sizeof(*processor)); | ||||
@@ -73,21 +73,42 @@ Clouds::~Clouds() { | |||||
} | } | ||||
void Clouds::step() { | void Clouds::step() { | ||||
// TODO Sample rate conversion from 32000 Hz | |||||
inL[bufferFrame] = getf(inputs[IN_L_INPUT]); | |||||
inR[bufferFrame] = getf(inputs[IN_R_INPUT]); | |||||
setf(outputs[OUT_L_OUTPUT], outL[bufferFrame]); | |||||
setf(outputs[OUT_R_OUTPUT], outR[bufferFrame]); | |||||
// Get input | |||||
if (!inputBuffer.full()) { | |||||
Frame<2> inputFrame; | |||||
inputFrame.samples[0] = getf(inputs[IN_L_INPUT]) * params[IN_GAIN_PARAM] / 5.0; | |||||
inputFrame.samples[1] = getf(inputs[IN_R_INPUT]) * params[IN_GAIN_PARAM] / 5.0; | |||||
inputBuffer.push(inputFrame); | |||||
} | |||||
// Trigger | // Trigger | ||||
if (getf(inputs[TRIG_INPUT]) >= 1.0) { | if (getf(inputs[TRIG_INPUT]) >= 1.0) { | ||||
triggered = true; | triggered = true; | ||||
} | } | ||||
if (++bufferFrame >= 32) { | |||||
bufferFrame = 0; | |||||
// Render frames | |||||
if (outputBuffer.empty()) { | |||||
clouds::ShortFrame input[32] = {}; | |||||
// Convert input buffer | |||||
{ | |||||
inputSrc.setRatio(32000.0 / gRack->sampleRate); | |||||
Frame<2> inputFrames[32]; | |||||
int inLen = inputBuffer.size(); | |||||
int outLen = 32; | |||||
inputSrc.process((const float*) inputBuffer.startData(), &inLen, (float*) inputFrames, &outLen); | |||||
inputBuffer.startIncr(inLen); | |||||
// We might not fill all of the input buffer if there is a deficiency, but this cannot be avoided due to imprecisions between the input and output SRC. | |||||
for (int i = 0; i < outLen; i++) { | |||||
input[i].l = clampf(inputFrames[i].samples[0] * 32767.0, -32768, 32767); | |||||
input[i].r = clampf(inputFrames[i].samples[1] * 32767.0, -32768, 32767); | |||||
} | |||||
} | |||||
// Set up processor | |||||
processor->set_num_channels(2); | processor->set_num_channels(2); | ||||
processor->set_low_fidelity(false); | processor->set_low_fidelity(false); | ||||
// TODO Support the other modes | |||||
processor->set_playback_mode(clouds::PLAYBACK_MODE_GRANULAR); | processor->set_playback_mode(clouds::PLAYBACK_MODE_GRANULAR); | ||||
processor->Prepare(); | processor->Prepare(); | ||||
@@ -105,22 +126,33 @@ void Clouds::step() { | |||||
p->feedback = 0.0f; | p->feedback = 0.0f; | ||||
p->reverb = 0.0f; | p->reverb = 0.0f; | ||||
clouds::ShortFrame input[32]; | |||||
clouds::ShortFrame output[32]; | clouds::ShortFrame output[32]; | ||||
for (int j = 0; j < 32; j++) { | |||||
input[j].l = clampf(inL[j] * params[IN_GAIN_PARAM] / 5.0, -1.0, 1.0) * 32767; | |||||
input[j].r = clampf(inR[j] * params[IN_GAIN_PARAM] / 5.0, -1.0, 1.0) * 32767; | |||||
} | |||||
processor->Process(input, output, 32); | processor->Process(input, output, 32); | ||||
for (int j = 0; j < 32; j++) { | |||||
outL[j] = (float)output[j].l / 32767 * 5.0; | |||||
outR[j] = (float)output[j].r / 32767 * 5.0; | |||||
// Convert output buffer | |||||
{ | |||||
Frame<2> outputFrames[32]; | |||||
for (int i = 0; i < 32; i++) { | |||||
outputFrames[i].samples[0] = output[i].l / 32768.0; | |||||
outputFrames[i].samples[1] = output[i].r / 32768.0; | |||||
} | |||||
outputSrc.setRatio(gRack->sampleRate / 32000.0); | |||||
int inLen = 32; | |||||
int outLen = outputBuffer.capacity(); | |||||
outputSrc.process((const float*) outputFrames, &inLen, (float*) outputBuffer.endData(), &outLen); | |||||
outputBuffer.endIncr(outLen); | |||||
} | } | ||||
triggered = false; | triggered = false; | ||||
} | } | ||||
// Set output | |||||
if (!outputBuffer.empty()) { | |||||
Frame<2> outputFrame = outputBuffer.shift(); | |||||
setf(outputs[OUT_L_OUTPUT], 5.0 * outputFrame.samples[0]); | |||||
setf(outputs[OUT_R_OUTPUT], 5.0 * outputFrame.samples[1]); | |||||
} | |||||
} | } | ||||
@@ -1,5 +1,6 @@ | |||||
#include "AudibleInstruments.hpp" | |||||
#include <string.h> | #include <string.h> | ||||
#include "AudibleInstruments.hpp" | |||||
#include "dsp.hpp" | |||||
#include "elements/dsp/part.h" | #include "elements/dsp/part.h" | ||||
@@ -65,13 +66,13 @@ struct Elements : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
SampleRateConverter<2> inputSrc; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<2>, 256> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
uint16_t reverb_buffer[32768] = {}; | uint16_t reverb_buffer[32768] = {}; | ||||
elements::Part *part; | elements::Part *part; | ||||
int bufferFrame = 0; | |||||
float blow[16] = {}; | |||||
float strike[16] = {}; | |||||
float main[16] = {}; | |||||
float aux[16] = {}; | |||||
float lights[2] = {}; | float lights[2] = {}; | ||||
Elements(); | Elements(); | ||||
@@ -99,14 +100,36 @@ Elements::~Elements() { | |||||
} | } | ||||
void Elements::step() { | void Elements::step() { | ||||
// TODO Sample rate convert from 32000Hz | |||||
blow[bufferFrame] = getf(inputs[BLOW_INPUT]); | |||||
strike[bufferFrame] = getf(inputs[STRIKE_INPUT]); | |||||
setf(outputs[AUX_OUTPUT], 5.0*aux[bufferFrame]); | |||||
setf(outputs[MAIN_OUTPUT], 5.0*main[bufferFrame]); | |||||
if (++bufferFrame >= 16) { | |||||
bufferFrame = 0; | |||||
// Get input | |||||
if (!inputBuffer.full()) { | |||||
Frame<2> inputFrame; | |||||
inputFrame.samples[0] = getf(inputs[BLOW_INPUT]) / 5.0; | |||||
inputFrame.samples[1] = getf(inputs[STRIKE_INPUT]) / 5.0; | |||||
inputBuffer.push(inputFrame); | |||||
} | |||||
// Render frames | |||||
if (outputBuffer.empty()) { | |||||
float blow[16] = {}; | |||||
float strike[16] = {}; | |||||
float main[16]; | |||||
float aux[16]; | |||||
// Convert input buffer | |||||
{ | |||||
inputSrc.setRatio(32000.0 / gRack->sampleRate); | |||||
Frame<2> inputFrames[16]; | |||||
int inLen = inputBuffer.size(); | |||||
int outLen = 16; | |||||
inputSrc.process((float*) inputBuffer.startData(), &inLen, (float*) inputFrames, &outLen); | |||||
inputBuffer.startIncr(inLen); | |||||
for (int i = 0; i < outLen; i++) { | |||||
blow[i] = inputFrames[i].samples[0]; | |||||
strike[i] = inputFrames[i].samples[1]; | |||||
} | |||||
} | |||||
// Set patch from parameters | // Set patch from parameters | ||||
elements::Patch* p = part->mutable_patch(); | elements::Patch* p = part->mutable_patch(); | ||||
p->exciter_envelope_shape = params[CONTOUR_PARAM]; | p->exciter_envelope_shape = params[CONTOUR_PARAM]; | ||||
@@ -114,7 +137,7 @@ void Elements::step() { | |||||
p->exciter_blow_level = params[BLOW_PARAM]; | p->exciter_blow_level = params[BLOW_PARAM]; | ||||
p->exciter_strike_level = params[STRIKE_PARAM]; | p->exciter_strike_level = params[STRIKE_PARAM]; | ||||
#define BIND(_p, _m, _i) clampf(params[_p] + 3.3*quadraticBipolar(params[_m])*getf(inputs[_i])/5.0, 0.0, 0.9995) | |||||
#define BIND(_p, _m, _i) clampf(params[_p] + 3.3*quadraticBipolar(params[_m])*getf(inputs[_i])/5.0, 0.0, 0.9995) | |||||
p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | ||||
p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | ||||
@@ -137,10 +160,32 @@ void Elements::step() { | |||||
// Generate audio | // Generate audio | ||||
part->Process(performance, blow, strike, main, aux, 16); | part->Process(performance, blow, strike, main, aux, 16); | ||||
// Convert output buffer | |||||
{ | |||||
Frame<2> outputFrames[16]; | |||||
for (int i = 0; i < 16; i++) { | |||||
outputFrames[i].samples[0] = main[i]; | |||||
outputFrames[i].samples[1] = aux[i]; | |||||
} | |||||
outputSrc.setRatio(gRack->sampleRate / 32000.0); | |||||
int inLen = 16; | |||||
int outLen = outputBuffer.capacity(); | |||||
outputSrc.process((float*) outputFrames, &inLen, (float*) outputBuffer.endData(), &outLen); | |||||
outputBuffer.endIncr(outLen); | |||||
} | |||||
// Set lights | // Set lights | ||||
lights[0] = part->exciter_level(); | lights[0] = part->exciter_level(); | ||||
lights[1] = part->resonator_level(); | lights[1] = part->resonator_level(); | ||||
} | } | ||||
// Set output | |||||
if (!outputBuffer.empty()) { | |||||
Frame<2> outputFrame = outputBuffer.shift(); | |||||
setf(outputs[AUX_OUTPUT], 5.0 * outputFrame.samples[0]); | |||||
setf(outputs[MAIN_OUTPUT], 5.0 * outputFrame.samples[1]); | |||||
} | |||||
} | } | ||||
@@ -28,7 +28,6 @@ struct Kinks : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
std::normal_distribution<float> dist; | |||||
float lastTrig = 0.0; | float lastTrig = 0.0; | ||||
float sample = 0.0; | float sample = 0.0; | ||||
float lights[3] = {}; | float lights[3] = {}; | ||||
@@ -38,7 +37,7 @@ struct Kinks : Module { | |||||
}; | }; | ||||
Kinks::Kinks() : dist(0.0, 1.0) { | |||||
Kinks::Kinks() { | |||||
params.resize(NUM_PARAMS); | params.resize(NUM_PARAMS); | ||||
inputs.resize(NUM_INPUTS); | inputs.resize(NUM_INPUTS); | ||||
outputs.resize(NUM_OUTPUTS); | outputs.resize(NUM_OUTPUTS); | ||||
@@ -46,11 +45,11 @@ Kinks::Kinks() : dist(0.0, 1.0) { | |||||
void Kinks::step() { | void Kinks::step() { | ||||
// Gaussian noise generator | // Gaussian noise generator | ||||
float noise = 2.0 * dist(rng); | |||||
float noise = 2.0 * randomNormal(); | |||||
// S&H | // S&H | ||||
float trig = getf(inputs[TRIG_INPUT]); | float trig = getf(inputs[TRIG_INPUT]); | ||||
float dtrig = (trig - lastTrig) * SAMPLE_RATE; | |||||
float dtrig = (trig - lastTrig) * gRack->sampleRate; | |||||
if (dtrig > DTRIG) { | if (dtrig > DTRIG) { | ||||
sample = getf(inputs[SH_INPUT], noise); | sample = getf(inputs[SH_INPUT], noise); | ||||
} | } | ||||
@@ -1,5 +1,6 @@ | |||||
#include "AudibleInstruments.hpp" | |||||
#include <string.h> | #include <string.h> | ||||
#include "AudibleInstruments.hpp" | |||||
#include "dsp.hpp" | |||||
#include "rings/dsp/part.h" | #include "rings/dsp/part.h" | ||||
#include "rings/dsp/strummer.h" | #include "rings/dsp/strummer.h" | ||||
#include "rings/dsp/string_synth_part.h" | #include "rings/dsp/string_synth_part.h" | ||||
@@ -41,11 +42,12 @@ struct Rings : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
SampleRateConverter<1> inputSrc; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<float, 256> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
uint16_t reverb_buffer[32768] = {}; | uint16_t reverb_buffer[32768] = {}; | ||||
int bufferFrame = 0; | |||||
float in[24] = {}; | |||||
float out[24] = {}; | |||||
float aux[24] = {}; | |||||
rings::Part part; | rings::Part part; | ||||
rings::StringSynthPart string_synth; | rings::StringSynthPart string_synth; | ||||
rings::Strummer strummer; | rings::Strummer strummer; | ||||
@@ -76,33 +78,36 @@ Rings::~Rings() { | |||||
} | } | ||||
void Rings::step() { | void Rings::step() { | ||||
// TODO Sample rate conversion from 48000 Hz | |||||
// TODO | // TODO | ||||
// "Normalized to a pulse/burst generator that reacts to note changes on the V/OCT input." | // "Normalized to a pulse/burst generator that reacts to note changes on the V/OCT input." | ||||
in[bufferFrame] = clampf(getf(inputs[IN_INPUT])/5.0, -1.0, 1.0); | |||||
// "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | |||||
if (outputs[ODD_OUTPUT] && outputs[EVEN_OUTPUT]) { | |||||
setf(outputs[ODD_OUTPUT], clampf(out[bufferFrame], -1.0, 1.0)*5.0); | |||||
setf(outputs[EVEN_OUTPUT], clampf(aux[bufferFrame], -1.0, 1.0)*5.0); | |||||
} | |||||
else { | |||||
float v = clampf(out[bufferFrame] + aux[bufferFrame], -1.0, 1.0)*5.0; | |||||
setf(outputs[ODD_OUTPUT], v); | |||||
setf(outputs[EVEN_OUTPUT], v); | |||||
// Get input | |||||
if (!inputBuffer.full()) { | |||||
float inputFrame = getf(inputs[IN_INPUT]) / 5.0; | |||||
inputBuffer.push(inputFrame); | |||||
} | } | ||||
if (!strum) { | if (!strum) { | ||||
strum = getf(inputs[STRUM_INPUT]) >= 1.0; | strum = getf(inputs[STRUM_INPUT]) >= 1.0; | ||||
} | } | ||||
if (++bufferFrame >= 24) { | |||||
bufferFrame = 0; | |||||
// Render frames | |||||
if (outputBuffer.empty()) { | |||||
float in[24] = {}; | |||||
// Convert input buffer | |||||
{ | |||||
inputSrc.setRatio(48000.0 / gRack->sampleRate); | |||||
int inLen = inputBuffer.size(); | |||||
int outLen = 24; | |||||
inputSrc.process(inputBuffer.startData(), &inLen, (float*) in, &outLen); | |||||
inputBuffer.startIncr(inLen); | |||||
} | |||||
// modes | // modes | ||||
int polyphony = 1; | |||||
int polyphony; | |||||
switch ((int) roundf(params[POLYPHONY_PARAM])) { | switch ((int) roundf(params[POLYPHONY_PARAM])) { | ||||
case 1: polyphony = 2; break; | case 1: polyphony = 2; break; | ||||
case 2: polyphony = 4; break; | case 2: polyphony = 4; break; | ||||
default: polyphony = 1; | |||||
} | } | ||||
if (polyphony != part.polyphony()) { | if (polyphony != part.polyphony()) { | ||||
part.set_polyphony(polyphony); | part.set_polyphony(polyphony); | ||||
@@ -145,6 +150,8 @@ void Rings::step() { | |||||
performance_state.chord = clampf(roundf(structure * (rings::kNumChords - 1)), 0, rings::kNumChords - 1); | performance_state.chord = clampf(roundf(structure * (rings::kNumChords - 1)), 0, rings::kNumChords - 1); | ||||
// Process audio | // Process audio | ||||
float out[24]; | |||||
float aux[24]; | |||||
if (0) { | if (0) { | ||||
// strummer.Process(NULL, 24, &performance_state); | // strummer.Process(NULL, 24, &performance_state); | ||||
// string_synth.Process(performance_state, patch, in, out, aux, 24); | // string_synth.Process(performance_state, patch, in, out, aux, 24); | ||||
@@ -153,7 +160,38 @@ void Rings::step() { | |||||
strummer.Process(in, 24, &performance_state); | strummer.Process(in, 24, &performance_state); | ||||
part.Process(performance_state, patch, in, out, aux, 24); | part.Process(performance_state, patch, in, out, aux, 24); | ||||
} | } | ||||
// Convert output buffer | |||||
{ | |||||
Frame<2> outputFrames[24]; | |||||
for (int i = 0; i < 24; i++) { | |||||
outputFrames[i].samples[0] = out[i]; | |||||
outputFrames[i].samples[1] = aux[i]; | |||||
} | |||||
outputSrc.setRatio(gRack->sampleRate / 48000.0); | |||||
int inLen = 24; | |||||
int outLen = outputBuffer.capacity(); | |||||
outputSrc.process((const float*) outputFrames, &inLen, (float*) outputBuffer.endData(), &outLen); | |||||
outputBuffer.endIncr(outLen); | |||||
} | |||||
} | } | ||||
// Set output | |||||
if (!outputBuffer.empty()) { | |||||
Frame<2> outputFrame = outputBuffer.shift(); | |||||
// "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | |||||
if (outputs[ODD_OUTPUT] && outputs[EVEN_OUTPUT]) { | |||||
setf(outputs[ODD_OUTPUT], clampf(outputFrame.samples[0], -1.0, 1.0)*5.0); | |||||
setf(outputs[EVEN_OUTPUT], clampf(outputFrame.samples[1], -1.0, 1.0)*5.0); | |||||
} | |||||
else { | |||||
float v = clampf(outputFrame.samples[0] + outputFrame.samples[1], -1.0, 1.0)*5.0; | |||||
setf(outputs[ODD_OUTPUT], v); | |||||
setf(outputs[EVEN_OUTPUT], v); | |||||
} | |||||
} | |||||
} | } | ||||
@@ -82,6 +82,8 @@ void Tides::step() { | |||||
pitch += 12.0*getf(inputs[PITCH_INPUT]); | pitch += 12.0*getf(inputs[PITCH_INPUT]); | ||||
pitch += params[FM_PARAM] * getf(inputs[FM_INPUT], 0.1) / 5.0; | pitch += params[FM_PARAM] * getf(inputs[FM_INPUT], 0.1) / 5.0; | ||||
pitch += 60.0; | pitch += 60.0; | ||||
// Scale to the global sample rate | |||||
pitch += log2f(48000.0 / gRack->sampleRate) * 12.0; | |||||
generator.set_pitch(clampf(pitch*0x80, -0x8000, 0x7fff)); | generator.set_pitch(clampf(pitch*0x80, -0x8000, 0x7fff)); | ||||
// Slope, smoothness, pitch | // Slope, smoothness, pitch | ||||
@@ -108,10 +108,10 @@ VeilsWidget::VeilsWidget() : ModuleWidget(new Veils()) { | |||||
addChild(createScrew(Vec(15, 365))); | addChild(createScrew(Vec(15, 365))); | ||||
addChild(createScrew(Vec(150, 365))); | addChild(createScrew(Vec(150, 365))); | ||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 52), module, Veils::GAIN1_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 131), module, Veils::GAIN2_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 210), module, Veils::GAIN3_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 288), module, Veils::GAIN4_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 52), module, Veils::GAIN1_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 131), module, Veils::GAIN2_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 210), module, Veils::GAIN3_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<SmallWhiteKnob>(Vec(8, 288), module, Veils::GAIN4_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TinyBlackKnob>(Vec(72, 56), module, Veils::RESPONSE1_PARAM, 0.0, 1.0, 1.0)); | addParam(createParam<TinyBlackKnob>(Vec(72, 56), module, Veils::RESPONSE1_PARAM, 0.0, 1.0, 1.0)); | ||||
addParam(createParam<TinyBlackKnob>(Vec(72, 135), module, Veils::RESPONSE2_PARAM, 0.0, 1.0, 1.0)); | addParam(createParam<TinyBlackKnob>(Vec(72, 135), module, Veils::RESPONSE2_PARAM, 0.0, 1.0, 1.0)); | ||||
@@ -61,6 +61,7 @@ void Warps::step() { | |||||
p->frequency_shift_cv = clampf(getf(inputs[ALGORITHM_INPUT]) / 5.0, -1.0, 1.0); | p->frequency_shift_cv = clampf(getf(inputs[ALGORITHM_INPUT]) / 5.0, -1.0, 1.0); | ||||
p->phase_shift = p->modulation_algorithm; | p->phase_shift = p->modulation_algorithm; | ||||
p->note = 60.0 * params[LEVEL1_PARAM] + 12.0 * getf(inputs[LEVEL1_INPUT], 2.0) + 12.0; | p->note = 60.0 * params[LEVEL1_PARAM] + 12.0 * getf(inputs[LEVEL1_INPUT], 2.0) + 12.0; | ||||
p->note += log2f(96000.0 / gRack->sampleRate) * 12.0; | |||||
float state = roundf(params[STATE_PARAM]); | float state = roundf(params[STATE_PARAM]); | ||||
p->carrier_shape = (int32_t)state; | p->carrier_shape = (int32_t)state; | ||||
lights[0] = state - 1.0; | lights[0] = state - 1.0; | ||||