fix scope triggering

This commit is contained in:
2026-01-15 23:51:51 -06:00
parent b160c8ae69
commit bb392c4d9d
4 changed files with 24 additions and 12 deletions

View File

@@ -47,7 +47,7 @@ private:
RtAudio audio_{AUDIO_API}; // audio device RtAudio audio_{AUDIO_API}; // audio device
// TODO: id like a yml config file or something for these // TODO: id like a yml config file or something for these
uint32_t sampleRate_ = 44100; uint32_t sampleRate_ = 44100;
uint32_t bufferFrames_ = 256; // time per buffer = BF/SR (256/44100 = 5.8ms) uint32_t bufferFrames_ = 512; // time per buffer = BF/SR (256/44100 = 5.8ms)
uint32_t channels_ = 2; // stereo uint32_t channels_ = 2; // stereo
}; };

View File

@@ -76,6 +76,7 @@ void Synth::process(float* out, uint32_t nFrames, uint32_t sampleRate) {
float sampleOut = 0.0f; float sampleOut = 0.0f;
bool triggered = false; bool triggered = false;
bool once = false;
for (uint32_t i = 0; i < nFrames; i++) { for (uint32_t i = 0; i < nFrames; i++) {
@@ -88,10 +89,24 @@ void Synth::process(float* out, uint32_t nFrames, uint32_t sampleRate) {
params[i] = params_[i].current; params[i] = params_[i].current;
} // maybe take this outside the loop if performance is an issue } // maybe take this outside the loop if performance is an issue
// find the lowest voice for scope triggering
int lowestVoice = 0;
float lowestFreq = 100000.0f;
for(int i = 0; i < voices_.size(); i++) {
if(!voices_[i].isActive()) continue;
float currentFreq = voices_[i].frequency();
if(currentFreq < lowestFreq) {
lowestVoice = i;
lowestFreq = currentFreq;
}
}
// foreach voice, process... // foreach voice, process...
float mix = 0.0f; float mix = 0.0f;
for(Voice& v : voices_) { for(int i = 0; i < voices_.size(); i++) {
mix += v.process(params, triggered); bool temp = false;
mix += voices_[i].process(params, temp);
if(i == lowestVoice) triggered = temp;
} }
mix /= 4.0f; // for number of voices to prevent clipping mix /= 4.0f; // for number of voices to prevent clipping
mix = tanh(mix); // really prevents clipping mix = tanh(mix); // really prevents clipping
@@ -109,16 +124,11 @@ void Synth::process(float* out, uint32_t nFrames, uint32_t sampleRate) {
} }
// triggering business // triggering business
// TODO: get trigger info from voice (lowest frequency voice) if(triggered && (!once)) {
float phase_ = 0.0f;
if (phase_ > 2.0f * M_PI) {
phase_ -= 2.0f * M_PI;
if(!triggered) {
scope_->setTrigger(i); // this is where we consider the start of a waveform scope_->setTrigger(i); // this is where we consider the start of a waveform
triggered = true; once = true;
// TODO: investigate triggering accross buffers when a single wave period transcends a single audio buffer // TODO: investigate triggering accross buffers when a single wave period transcends a single audio buffer
} }
} }
}
} }

View File

@@ -125,6 +125,7 @@ float Voice::process(float* params, bool& scopeTrigger) {
// state tracking, may keep this here even if oscillators store their own phase because it might help with scope triggering // state tracking, may keep this here even if oscillators store their own phase because it might help with scope triggering
phase_ += phaseInc; phase_ += phaseInc;
if (phase_ > 2.0f * M_PI) { if (phase_ > 2.0f * M_PI) {
scopeTrigger = true;
phase_ -= 2.0f * M_PI; phase_ -= 2.0f * M_PI;
} }

View File

@@ -40,6 +40,7 @@ public:
float process(float* params, bool& scopeTrigger); float process(float* params, bool& scopeTrigger);
uint8_t note() { return note_; } uint8_t note() { return note_; }
float frequency() { return frequency_; }
private: private: