From ba6b22e5e39547a1d5ccb062aa5b2596670ee3d0 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Tue, 13 Mar 2018 05:55:25 -0400 Subject: [PATCH] Refactor Peaks, disable Peaks --- src/AudibleInstruments.cpp | 2 +- src/Peaks.cpp | 400 ++++++++++++++++++------------------- 2 files changed, 196 insertions(+), 206 deletions(-) diff --git a/src/AudibleInstruments.cpp b/src/AudibleInstruments.cpp index d2f1e76..57ba4e7 100644 --- a/src/AudibleInstruments.cpp +++ b/src/AudibleInstruments.cpp @@ -21,5 +21,5 @@ void init(rack::Plugin *p) { p->addModel(modelBlinds); p->addModel(modelVeils); p->addModel(modelFrames); - p->addModel(modelPeaks); + // p->addModel(modelPeaks); } diff --git a/src/Peaks.cpp b/src/Peaks.cpp index 5e97e96..a14949b 100644 --- a/src/Peaks.cpp +++ b/src/Peaks.cpp @@ -53,6 +53,32 @@ static const uint16_t kAdcThresholdUnlocked = 1 << (16 - 10); // 10 bits static const uint16_t kAdcThresholdLocked = 1 << (16 - 8); // 8 bits +// Global scope, so variables can be accessed by process() function. +int16_t gOutputBuffer[peaks::kBlockSize]; +int16_t gBrightness[2] = {0, 0}; + + +static void set_led_brightness(int channel, int16_t value) { + gBrightness[channel] = value; +} + +// File scope because of IOBuffer function signature. +// It cannot refer to a member function of class Peaks(). +static void process(peaks::IOBuffer::Block* block, size_t size) { + for (size_t i = 0; i < peaks::kNumChannels; ++i) { + // TODO + // processors[i].Process(block->input[i], gOutputBuffer, size); + set_led_brightness(i, gOutputBuffer[0]); + for (size_t j = 0; j < size; ++j) { + // From calibration_data.h, shifting signed to unsigned values. + int32_t shifted_value = 32767 + static_cast(gOutputBuffer[j]); + CONSTRAIN(shifted_value, 0, 65535); + block->output[i][j] = static_cast(shifted_value); + } + } +} + + struct Peaks : Module { enum ParamIds { KNOB_1_PARAM, @@ -86,15 +112,154 @@ struct Peaks : Module { NUM_LIGHTS }; - Peaks(); - ~Peaks(); + static const peaks::ProcessorFunction function_table_[FUNCTION_LAST][2]; + + EditMode edit_mode_ = EDIT_MODE_TWIN; + Function function_[2] = {FUNCTION_ENVELOPE, FUNCTION_ENVELOPE}; + Settings settings_; + + uint8_t pot_value_[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + + bool snap_mode_ = false; + bool snapped_[4] = {false, false, false, false}; + + int32_t adc_lp_[kNumAdcChannels] = {0, 0, 0, 0}; + int32_t adc_value_[kNumAdcChannels] = {0, 0, 0, 0}; + int32_t adc_threshold_[kNumAdcChannels] = {0, 0, 0, 0}; + long long press_time_[2] = {0, 0}; + + SchmittTrigger switches_[2]; + + peaks::IOBuffer ioBuffer; + + peaks::GateFlags gate_flags[2] = {0, 0}; + + SampleRateConverter<2> outputSrc; + DoubleRingBuffer, 256> outputBuffer; + + bool initNumberStation = false; + + peaks::Processors processors[2]; + + Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + settings_.edit_mode = EDIT_MODE_TWIN; + settings_.function[0] = FUNCTION_ENVELOPE; + settings_.function[1] = FUNCTION_ENVELOPE; + settings_.snap_mode = false; + std::fill(&settings_.pot_value[0], &settings_.pot_value[8], 0); + + memset(&ioBuffer, 0, sizeof(ioBuffer)); + memset(&processors[0], 0, sizeof(processors[0])); + memset(&processors[1], 0, sizeof(processors[1])); + ioBuffer.Init(); + processors[0].Init(0); + processors[1].Init(1); + } - void step() override; void onReset() override { init(); } - void init(); + void init() { + std::fill(&pot_value_[0], &pot_value_[8], 0); + std::fill(&press_time_[0], &press_time_[1], 0); + std::fill(&gBrightness[0], &gBrightness[1], 0); + std::fill(&adc_lp_[0], &adc_lp_[kNumAdcChannels], 0); + std::fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0); + std::fill(&adc_threshold_[0], &adc_threshold_[kNumAdcChannels], 0); + std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false); + + edit_mode_ = static_cast(settings_.edit_mode); + function_[0] = static_cast(settings_.function[0]); + function_[1] = static_cast(settings_.function[1]); + std::copy(&settings_.pot_value[0], &settings_.pot_value[8], &pot_value_[0]); + + if (edit_mode_ == EDIT_MODE_FIRST || edit_mode_ == EDIT_MODE_SECOND) { + lockPots(); + for (uint8_t i = 0; i < 4; ++i) { + processors[0].set_parameter( + i, + static_cast(pot_value_[i]) << 8); + processors[1].set_parameter( + i, + static_cast(pot_value_[i + 4]) << 8); + } + } + + snap_mode_ = settings_.snap_mode; + + changeControlMode(); + setFunction(0, function_[0]); + setFunction(1, function_[1]); + } + + void step() override { + poll(); + pollPots(); + + // Initialize "secret" number station mode. + if (initNumberStation) { + processors[0].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); + processors[1].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); + initNumberStation = false; + } + + if (outputBuffer.empty()) { + ioBuffer.Process(process); + + uint32_t external_gate_inputs = 0; + external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0); + external_gate_inputs |= (inputs[GATE_2_INPUT].value ? 2 : 0); + + uint32_t buttons = 0; + buttons |= (params[TRIG_1_PARAM].value ? 1 : 0); + buttons |= (params[TRIG_2_PARAM].value ? 2 : 0); + + uint32_t gate_inputs = external_gate_inputs | buttons; + + // Prepare sample rate conversion. + // Peaks is sampling at 48kHZ. + outputSrc.setRates(48000, engineGetSampleRate()); + int inLen = peaks::kBlockSize; + int outLen = outputBuffer.capacity(); + Frame<2> f[peaks::kBlockSize]; + + // Process an entire block of data from the IOBuffer. + for (size_t k = 0; k < peaks::kBlockSize; ++k) { + + peaks::IOBuffer::Slice slice = ioBuffer.NextSlice(1); + + for (size_t i = 0; i < peaks::kNumChannels; ++i) { + gate_flags[i] = peaks::ExtractGateFlags( + gate_flags[i], + gate_inputs & (1 << i)); + + f[k].samples[i] = slice.block->output[i][slice.frame_index]; + } + + // A hack to make channel 1 aware of what's going on in channel 2. Used to + // reset the sequencer. + slice.block->input[0][slice.frame_index] = gate_flags[0] | (gate_flags[1] << 4) | (buttons & 8 ? peaks::GATE_FLAG_FROM_BUTTON : 0); + + slice.block->input[1][slice.frame_index] = gate_flags[1] | (buttons & 2 ? peaks::GATE_FLAG_FROM_BUTTON : 0); + } + + outputSrc.process(f, &inLen, outputBuffer.endData(), &outLen); + outputBuffer.endIncr(outLen); + } + + // Update outputs. + if (!outputBuffer.empty()) { + Frame<2> f = outputBuffer.shift(); + + // Peaks manual says output spec is 0..8V for envelopes and 10Vpp for audio/CV. + // TODO Check the output values against an actual device. + outputs[OUT_1_OUTPUT].value = rescale(static_cast(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f); + outputs[OUT_2_OUTPUT].value = rescale(static_cast(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f); + } + } + + json_t *toJson() override { @@ -167,33 +332,6 @@ struct Peaks : Module { void refreshLeds(); long long getSystemTimeMs(); - - static const peaks::ProcessorFunction function_table_[FUNCTION_LAST][2]; - - EditMode edit_mode_ = EDIT_MODE_TWIN; - Function function_[2] = {FUNCTION_ENVELOPE, FUNCTION_ENVELOPE}; - Settings settings_; - - uint8_t pot_value_[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - - bool snap_mode_ = false; - bool snapped_[4] = {false, false, false, false}; - - int32_t adc_lp_[kNumAdcChannels] = {0, 0, 0, 0}; - int32_t adc_value_[kNumAdcChannels] = {0, 0, 0, 0}; - int32_t adc_threshold_[kNumAdcChannels] = {0, 0, 0, 0}; - long long press_time_[2] = {0, 0}; - - SchmittTrigger switches_[2]; - - std::shared_ptr ioBuffer; - - peaks::GateFlags gate_flags[2] = {0, 0}; - - SampleRateConverter<2> outputSrc; - DoubleRingBuffer, 256> outputBuffer; - - bool initNumberStation = false; }; const peaks::ProcessorFunction Peaks::function_table_[FUNCTION_LAST][2] = { @@ -208,153 +346,6 @@ const peaks::ProcessorFunction Peaks::function_table_[FUNCTION_LAST][2] = { { peaks::PROCESSOR_FUNCTION_FM_DRUM, peaks::PROCESSOR_FUNCTION_FM_DRUM }, }; -Peaks::Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { - ioBuffer = std::make_shared(); - - settings_.edit_mode = EDIT_MODE_TWIN; - settings_.function[0] = FUNCTION_ENVELOPE; - settings_.function[1] = FUNCTION_ENVELOPE; - settings_.snap_mode = false; - std::fill(&settings_.pot_value[0], &settings_.pot_value[8], 0); - - ioBuffer->Init(); - peaks::processors[0].Init(0); - peaks::processors[1].Init(1); -} - -Peaks::~Peaks() { -} - - -// Global scope, so variables can be accessed by process() function. -int16_t gOutputBuffer[peaks::kBlockSize]; -int16_t gBrightness[2] = {0, 0}; - -void set_led_brightness(int channel, int16_t value) { - gBrightness[channel] = value; -} - -// File scope because of IOBuffer function signature. -// It cannot refer to a member function of class Peaks(). -void process(peaks::IOBuffer::Block* block, size_t size) { - for (size_t i = 0; i < peaks::kNumChannels; ++i) { - peaks::processors[i].Process(block->input[i], gOutputBuffer, size); - set_led_brightness(i, gOutputBuffer[0]); - for (size_t j = 0; j < size; ++j) { - // From calibration_data.h, shifting signed to unsigned values. - int32_t shifted_value = 32767 + static_cast(gOutputBuffer[j]); - CONSTRAIN(shifted_value, 0, 65535); - block->output[i][j] = static_cast(shifted_value); - } - } -} - -void Peaks::init() { - std::fill(&pot_value_[0], &pot_value_[8], 0); - std::fill(&press_time_[0], &press_time_[1], 0); - std::fill(&gBrightness[0], &gBrightness[1], 0); - std::fill(&adc_lp_[0], &adc_lp_[kNumAdcChannels], 0); - std::fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0); - std::fill(&adc_threshold_[0], &adc_threshold_[kNumAdcChannels], 0); - std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false); - - edit_mode_ = static_cast(settings_.edit_mode); - function_[0] = static_cast(settings_.function[0]); - function_[1] = static_cast(settings_.function[1]); - std::copy(&settings_.pot_value[0], &settings_.pot_value[8], &pot_value_[0]); - - if (edit_mode_ == EDIT_MODE_FIRST || edit_mode_ == EDIT_MODE_SECOND) { - lockPots(); - for (uint8_t i = 0; i < 4; ++i) { - peaks::processors[0].set_parameter( - i, - static_cast(pot_value_[i]) << 8); - peaks::processors[1].set_parameter( - i, - static_cast(pot_value_[i + 4]) << 8); - } - } - - snap_mode_ = settings_.snap_mode; - - changeControlMode(); - setFunction(0, function_[0]); - setFunction(1, function_[1]); -} - -void Peaks::step() { - - poll(); - pollPots(); - - // Initialize "secret" number station mode. - if (initNumberStation) { - peaks::processors[0].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); - peaks::processors[1].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); - initNumberStation = false; - } - - if (outputBuffer.empty()) { - - ioBuffer->Process(process); - - uint32_t external_gate_inputs = 0; - external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0); - external_gate_inputs |= (inputs[GATE_2_INPUT].value ? 2 : 0); - - uint32_t buttons = 0; - buttons |= (params[TRIG_1_PARAM].value ? 1 : 0); - buttons |= (params[TRIG_2_PARAM].value ? 2 : 0); - - uint32_t gate_inputs = external_gate_inputs | buttons; - - // Prepare sample rate conversion. - // Peaks is sampling at 48kHZ. - outputSrc.setRates(48000, engineGetSampleRate()); - int inLen = peaks::kBlockSize; - int outLen = outputBuffer.capacity(); - Frame<2> f[peaks::kBlockSize]; - - // Process an entire block of data from the IOBuffer. - for (size_t k = 0; k < peaks::kBlockSize; ++k) { - - peaks::IOBuffer::Slice slice = ioBuffer->NextSlice(1); - - for (size_t i = 0; i < peaks::kNumChannels; ++i) { - gate_flags[i] = peaks::ExtractGateFlags( - gate_flags[i], - gate_inputs & (1 << i)); - - f[k].samples[i] = slice.block->output[i][slice.frame_index]; - } - - // A hack to make channel 1 aware of what's going on in channel 2. Used to - // reset the sequencer. - slice.block->input[0][slice.frame_index] = gate_flags[0] \ - | (gate_flags[1] << 4) \ - | (buttons & 8 ? peaks::GATE_FLAG_FROM_BUTTON : 0); - - slice.block->input[1][slice.frame_index] = gate_flags[1] \ - | (buttons & 2 ? peaks::GATE_FLAG_FROM_BUTTON : 0); - - } - - outputSrc.process(f, &inLen, outputBuffer.endData(), &outLen); - outputBuffer.endIncr(outLen); - } - - // Update outputs. - if (!outputBuffer.empty()) { - Frame<2> f = outputBuffer.shift(); - - // Peaks manual says output spec is 0..8V for envelopes and 10Vpp for audio/CV. - // TODO Check the output values against an actual device. - outputs[OUT_1_OUTPUT].value = \ - rescale(static_cast(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f); - outputs[OUT_2_OUTPUT].value = \ - rescale(static_cast(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f); - } -} void Peaks::changeControlMode() { uint16_t parameters[4]; @@ -363,32 +354,32 @@ void Peaks::changeControlMode() { } if (edit_mode_ == EDIT_MODE_SPLIT) { - peaks::processors[0].CopyParameters(¶meters[0], 2); - peaks::processors[1].CopyParameters(¶meters[2], 2); - peaks::processors[0].set_control_mode(peaks::CONTROL_MODE_HALF); - peaks::processors[1].set_control_mode(peaks::CONTROL_MODE_HALF); + processors[0].CopyParameters(¶meters[0], 2); + processors[1].CopyParameters(¶meters[2], 2); + processors[0].set_control_mode(peaks::CONTROL_MODE_HALF); + processors[1].set_control_mode(peaks::CONTROL_MODE_HALF); } else if (edit_mode_ == EDIT_MODE_TWIN) { - peaks::processors[0].CopyParameters(¶meters[0], 4); - peaks::processors[1].CopyParameters(¶meters[0], 4); - peaks::processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); - peaks::processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); + processors[0].CopyParameters(¶meters[0], 4); + processors[1].CopyParameters(¶meters[0], 4); + processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); + processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); } else { - peaks::processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); - peaks::processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); + processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); + processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); } } void Peaks::setFunction(uint8_t index, Function f) { if (edit_mode_ == EDIT_MODE_SPLIT || edit_mode_ == EDIT_MODE_TWIN) { function_[0] = function_[1] = f; - peaks::processors[0].set_function(function_table_[f][0]); - peaks::processors[1].set_function(function_table_[f][1]); + processors[0].set_function(function_table_[f][0]); + processors[1].set_function(function_table_[f][1]); } else { function_[index] = f; - peaks::processors[index].set_function(function_table_[f][index]); + processors[index].set_function(function_table_[f][index]); } } @@ -399,8 +390,8 @@ void Peaks::onSwitchReleased(uint16_t id, uint16_t data) { edit_mode_ = static_cast( (edit_mode_ + EDIT_MODE_FIRST) % EDIT_MODE_LAST); function_[0] = function_[1]; - peaks::processors[0].set_function(function_table_[function_[0]][0]); - peaks::processors[1].set_function(function_table_[function_[0]][1]); + processors[0].set_function(function_table_[function_[0]][0]); + processors[1].set_function(function_table_[function_[0]][1]); lockPots(); } else { @@ -470,17 +461,17 @@ void Peaks::pollPots() { void Peaks::onPotChanged(uint16_t id, uint16_t value) { switch (edit_mode_) { case EDIT_MODE_TWIN: - peaks::processors[0].set_parameter(id, value); - peaks::processors[1].set_parameter(id, value); + processors[0].set_parameter(id, value); + processors[1].set_parameter(id, value); pot_value_[id] = value >> 8; break; case EDIT_MODE_SPLIT: if (id < 2) { - peaks::processors[0].set_parameter(id, value); + processors[0].set_parameter(id, value); } else { - peaks::processors[1].set_parameter(id - 2, value); + processors[1].set_parameter(id - 2, value); } pot_value_[id] = value >> 8; break; @@ -488,7 +479,7 @@ void Peaks::onPotChanged(uint16_t id, uint16_t value) { case EDIT_MODE_FIRST: case EDIT_MODE_SECOND: { uint8_t index = id + (edit_mode_ - EDIT_MODE_FIRST) * 4; - peaks::Processors* p = &peaks::processors[edit_mode_ - EDIT_MODE_FIRST]; + peaks::Processors* p = &processors[edit_mode_ - EDIT_MODE_FIRST]; int16_t delta = static_cast(pot_value_[index]) - \ static_cast(value >> 8); @@ -594,16 +585,15 @@ void Peaks::refreshLeds() { } } - if (peaks::processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) { - uint8_t pattern = \ - peaks::processors[0].number_station().digit() ^ \ - peaks::processors[1].number_station().digit(); + if (processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) { + uint8_t pattern = processors[0].number_station().digit() + ^ processors[1].number_station().digit(); for (size_t i = 0; i < 4; ++i) { lights[FUNC_1_LIGHT + i].value = (pattern & 1) ? 1.0f : 0.0f; pattern = pattern >> 1; } - b[0] = peaks::processors[0].number_station().gate() ? 255 : 0; - b[1] = peaks::processors[1].number_station().gate() ? 255 : 0; + b[0] = processors[0].number_station().gate() ? 255 : 0; + b[1] = processors[1].number_station().gate() ? 255 : 0; } lights[TRIG_1_LIGHT].value = rescale(static_cast(b[0]), 0.0f, 255.0f, 0.0f, 1.0f); @@ -685,4 +675,4 @@ struct PeaksWidget : ModuleWidget { -Model *modelPeaks = Model::create("Audible Instruments", "Peaks", "Percussive Synthesizer", UTILITY_TAG, LFO_TAG, DRUM_TAG); \ No newline at end of file +Model *modelPeaks = Model::create("Audible Instruments", "Peaks", "Percussive Synthesizer", UTILITY_TAG, LFO_TAG, DRUM_TAG);