added a spinlock on the scope

This commit is contained in:
2026-01-23 21:53:03 -06:00
parent 2a1ea708a1
commit 9ca60ced76
7 changed files with 17 additions and 3 deletions

View File

@@ -17,7 +17,7 @@ This synthesizer isn't very good, but it's neat :3
responds to note-on/note-off events responds to note-on/note-off events
- [x] Make midi/keyboard control cross-platform. Use case will mostly be - [x] Make midi/keyboard control cross-platform. Use case will mostly be
Midi -> linux and Keyboard -> windows though Midi -> linux and Keyboard -> windows though
- [ ] Create oscillator class where the actual tone generation occurs. Multiple - [x] Create oscillator class where the actual tone generation occurs. Multiple
oscillators increase the sound complexity considerably oscillators increase the sound complexity considerably
- [x] Create a UI scope to visualize the synthesized composite waveform - [x] Create a UI scope to visualize the synthesized composite waveform
- [ ] Create wavetables for more complex tone generation. Needs to be selectable from ui - [ ] Create wavetables for more complex tone generation. Needs to be selectable from ui
@@ -60,7 +60,7 @@ Build. The script will build and install dependencies automatically
On Windows (MSVC): On Windows (MSVC):
```PowerShell ```PowerShell
.\scripts\build.ps1 .\scripts\build.ps1 # builds in build/Debug/
``` ```
On Linux (GCC): On Linux (GCC):

View File

@@ -14,6 +14,9 @@ void ScopeBuffer::push(float sample) {
// TODO: needs a mutex to prevent flickering // TODO: needs a mutex to prevent flickering
// outputs value from the scope buffer, called by the scope widget // outputs value from the scope buffer, called by the scope widget
void ScopeBuffer::read(std::vector<float>& out) const { void ScopeBuffer::read(std::vector<float>& out) const {
while(!spinLock_) { int x = 1 + 1; }
size_t w = writeIndex_.load(std::memory_order_relaxed); size_t w = writeIndex_.load(std::memory_order_relaxed);
for (size_t i = 0; i < out.size(); i++) { for (size_t i = 0; i < out.size(); i++) {
size_t idx = (w + trigger_ + i * wavelength_ / out.size()) % buffer_.size(); size_t idx = (w + trigger_ + i * wavelength_ / out.size()) % buffer_.size();

View File

@@ -21,6 +21,7 @@ public:
void setWavelength(int32_t wavelength) { wavelength_ = wavelength; } void setWavelength(int32_t wavelength) { wavelength_ = wavelength; }
int32_t trigger() { return trigger_; } int32_t trigger() { return trigger_; }
int32_t wavelength() { return wavelength_; } int32_t wavelength() { return wavelength_; }
void spinlock(bool lock) { spinLock_ = lock; };
// NOTE: there are limits to the wavelengths that the scope can show cleanly due to the size of the audio buffer // NOTE: there are limits to the wavelengths that the scope can show cleanly due to the size of the audio buffer
// at a buffer size of 256 at 44100hz the min visible steady frequency is ~172hz // at a buffer size of 256 at 44100hz the min visible steady frequency is ~172hz
@@ -33,4 +34,6 @@ private:
int32_t trigger_ = 0; // units in array indices int32_t trigger_ = 0; // units in array indices
int32_t wavelength_ = 400; int32_t wavelength_ = 400;
bool spinLock_ = false;
}; };

View File

@@ -92,6 +92,9 @@ void Synth::process(float* out, uint32_t nFrames, uint32_t sampleRate) {
} }
} }
// lock the scope from the buffer
scope_->spinlock(true);
for (uint32_t i = 0; i < nFrames; i++) { for (uint32_t i = 0; i < nFrames; i++) {
// updates internal buffered parameters for smoothing // updates internal buffered parameters for smoothing
@@ -133,4 +136,7 @@ void Synth::process(float* out, uint32_t nFrames, uint32_t sampleRate) {
} }
} }
// unlock the scope from the buffer
scope_->spinlock(false);
} }

View File

@@ -63,6 +63,7 @@ private:
// filters // filters
Filter filter1_; Filter filter1_;
Filter filter2_; Filter filter2_;
// TODO: I think the filter's state being uninitialized is what's causing popping when a voice starts for the first time
// paramstore pointer // paramstore pointer
SmoothedParam* params_; SmoothedParam* params_;

View File

@@ -24,7 +24,7 @@ void Scope::setScopeBuffer(ScopeBuffer* buffer) {
} }
void Scope::paintEvent(QPaintEvent*) { void Scope::paintEvent(QPaintEvent*) {
if (!buffer_) return; if(!buffer_) return;
int32_t wavelength = buffer_->wavelength(); int32_t wavelength = buffer_->wavelength();
int32_t trigger = buffer_->trigger(); int32_t trigger = buffer_->trigger();

View File

@@ -32,4 +32,5 @@ private:
ScopeBuffer* buffer_ = nullptr; ScopeBuffer* buffer_ = nullptr;
std::vector<float> samples_; std::vector<float> samples_;
QTimer timer_; QTimer timer_;
}; };