diff --git a/src/Peaks.cpp b/src/Peaks.cpp index 1f02494..f91ac24 100644 --- a/src/Peaks.cpp +++ b/src/Peaks.cpp @@ -5,7 +5,6 @@ #include "dsp/samplerate.hpp" #include "dsp/ringbuffer.hpp" -#include "peaks/io_buffer.h" #include "peaks/processors.h" #include "AudibleInstruments.hpp" @@ -47,38 +46,15 @@ struct Settings { }; +static const size_t kNumBlocks = 2; +static const size_t kNumChannels = 2; +static const size_t kBlockSize = 4; static const int32_t kLongPressDuration = 600; static const uint8_t kNumAdcChannels = 4; 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, @@ -128,9 +104,12 @@ struct Peaks : Module { int32_t adc_threshold_[kNumAdcChannels] = {0, 0, 0, 0}; long long press_time_[2] = {0, 0}; - SchmittTrigger switches_[2]; + peaks::Processors processors[2]; + + int16_t output[kBlockSize]; + int16_t brightness[kNumChannels] = {0, 0}; - peaks::IOBuffer ioBuffer; + SchmittTrigger switches_[2]; peaks::GateFlags gate_flags[2] = {0, 0}; @@ -139,7 +118,21 @@ struct Peaks : Module { bool initNumberStation = false; - peaks::Processors processors[2]; + struct Block { + peaks::GateFlags input[kNumChannels][kBlockSize]; + uint16_t output[kNumChannels][kBlockSize]; + }; + + struct Slice { + Block* block; + size_t frame_index; + }; + + Block block_[kNumBlocks]; + size_t io_frame_ = 0; + size_t io_block_ = 0; + size_t render_block_ = kNumBlocks / 2; + Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { settings_.edit_mode = EDIT_MODE_TWIN; @@ -148,10 +141,8 @@ struct Peaks : Module { 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); } @@ -163,7 +154,7 @@ struct Peaks : Module { 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(&brightness[0], &brightness[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); @@ -261,7 +252,11 @@ struct Peaks : Module { } if (outputBuffer.empty()) { - ioBuffer.Process(process); + + while (render_block_ != io_block_) { + process(&block_[render_block_], kBlockSize); + render_block_ = (render_block_ + 1) % kNumBlocks; + } uint32_t external_gate_inputs = 0; external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0); @@ -276,16 +271,16 @@ struct Peaks : Module { // Prepare sample rate conversion. // Peaks is sampling at 48kHZ. outputSrc.setRates(48000, engineGetSampleRate()); - int inLen = peaks::kBlockSize; + int inLen = kBlockSize; int outLen = outputBuffer.capacity(); - Frame<2> f[peaks::kBlockSize]; + Frame<2> f[kBlockSize]; // Process an entire block of data from the IOBuffer. - for (size_t k = 0; k < peaks::kBlockSize; ++k) { + for (size_t k = 0; k < kBlockSize; ++k) { - peaks::IOBuffer::Slice slice = ioBuffer.NextSlice(1); + Slice slice = NextSlice(1); - for (size_t i = 0; i < peaks::kNumChannels; ++i) { + for (size_t i = 0; i < kNumChannels; ++i) { gate_flags[i] = peaks::ExtractGateFlags( gate_flags[i], gate_inputs & (1 << i)); @@ -315,10 +310,39 @@ struct Peaks : Module { } } + inline Slice NextSlice(size_t size) { + Slice s; + s.block = &block_[io_block_]; + s.frame_index = io_frame_; + io_frame_ += size; + if (io_frame_ >= kBlockSize) { + io_frame_ -= kBlockSize; + io_block_ = (io_block_ + 1) % kNumBlocks; + } + return s; + } + inline Function function() const { return edit_mode_ == EDIT_MODE_SECOND ? function_[1] : function_[0]; } + inline void set_led_brightness(int channel, int16_t value) { + brightness[channel] = value; + } + + inline void process(Block* block, size_t size) { + for (size_t i = 0; i < kNumChannels; ++i) { + processors[i].Process(block->input[i], output, size); + set_led_brightness(i, output[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(output[j]); + CONSTRAIN(shifted_value, 0, 65535); + block->output[i][j] = static_cast(shifted_value); + } + } + } + void changeControlMode(); void setFunction(uint8_t index, Function f); void onPotChanged(uint16_t id, uint16_t value); @@ -564,21 +588,21 @@ void Peaks::refreshLeds() { switch (function_[i]) { case FUNCTION_DRUM_GENERATOR: case FUNCTION_FM_DRUM_GENERATOR: - b[i] = (int16_t) std::abs(gBrightness[i]) >> 8; + b[i] = (int16_t) abs(brightness[i]) >> 8; b[i] = b[i] >= 255 ? 255 : b[i]; break; case FUNCTION_LFO: case FUNCTION_TAP_LFO: case FUNCTION_MINI_SEQUENCER: { - int32_t brightness = int32_t(gBrightness[i]) * 409 >> 8; - brightness += 32768; - brightness >>= 8; - CONSTRAIN(brightness, 0, 255); - b[i] = brightness; + int32_t brightnessVal = int32_t(brightness[i]) * 409 >> 8; + brightnessVal += 32768; + brightnessVal >>= 8; + CONSTRAIN(brightnessVal, 0, 255); + b[i] = brightnessVal; } break; default: - b[i] = gBrightness[i] >> 7; + b[i] = brightness[i] >> 7; break; } } @@ -651,6 +675,10 @@ struct PeaksWidget : ModuleWidget { void onAction(EventAction &e) override { peaks->initNumberStation = true; } + void step() override { + rightText = (peaks->processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) ? "✔" : ""; + MenuItem::step(); + } }; menu->addChild(construct());