diff --git a/simulator/main.cpp b/simulator/main.cpp index c8eae31..c5ae767 100644 --- a/simulator/main.cpp +++ b/simulator/main.cpp @@ -19,7 +19,7 @@ #endif // --- Configuration --- -const uint32_t SAMPLE_RATE = 44100; +const uint32_t SAMPLE_RATE = 44100 / 4; const uint32_t CHANNELS = 1; // Mono const int CELL_SIZE = 60; const int GRID_PANEL_WIDTH = 12 * CELL_SIZE; // 720 @@ -46,6 +46,7 @@ Uint32 auto_melody_next_event_time = 0; const int c_major_scale[] = {0, 2, 4, 5, 7, 9, 11, 12}; // Semitones from root int current_preset = 0; int current_patch_slot = 0; // 0-7 +SynthEngine::GridCell clipboardCell; float note_to_freq(int octave, int semitone_offset); @@ -165,7 +166,7 @@ void checkSerialInput(FILE* serialPort) { } else if (state == 1) { // Count elementCount = b; printf("Grid element count: %d\n", elementCount); - if (1 + elementCount * 5 + 1 > sizeof(buffer)) { + if ((size_t)(1 + elementCount * 5 + 1) > sizeof(buffer)) { state = 0; bufferIdx = 0; printf("ERROR: Grid too large (count: %d)\n", elementCount); @@ -1363,6 +1364,39 @@ int main(int argc, char* argv[]) { engine.setGate(true); } } + + // Copy & Paste + if (e.key.keysym.scancode == SDL_SCANCODE_C) { + int mx, my; + SDL_GetMouseState(&mx, &my); + if (mx < GRID_PANEL_WIDTH) { + int gx = mx / CELL_SIZE; + int gy = my / CELL_SIZE; + if (gx >= 0 && gx < SynthEngine::GRID_W && gy >= 0 && gy < SynthEngine::GRID_H) { + SynthLockGuard lock(engine.gridMutex); + clipboardCell = engine.grid[gx][gy]; + } + } + } else if (e.key.keysym.scancode == SDL_SCANCODE_V) { + int mx, my; + SDL_GetMouseState(&mx, &my); + if (mx < GRID_PANEL_WIDTH) { + int gx = mx / CELL_SIZE; + int gy = my / CELL_SIZE; + if (gx >= 0 && gx < SynthEngine::GRID_W && gy >= 0 && gy < SynthEngine::GRID_H) { + { + SynthLockGuard lock(engine.gridMutex); + engine.grid[gx][gy] = clipboardCell; + // Reset runtime state + engine.grid[gx][gy].value = 0; + engine.grid[gx][gy].next_value = 0; + engine.grid[gx][gy].phase = 0; + engine.grid[gx][gy].phase_accumulator = 0; + } + engine.rebuildProcessingOrder(); + } + } + } } } else if (e.type == SDL_MOUSEBUTTONUP) { if (exportButtonPressed) { @@ -1567,6 +1601,12 @@ int main(int argc, char* argv[]) { snprintf(slotBuf, sizeof(slotBuf), "SLOT %d", current_patch_slot); drawString(renderer, 380, 600, 12, slotBuf); + // Buffer Preview + drawString(renderer, 50, 560, 12, "BUFFER"); + drawGridCell(renderer, 50, 580, CELL_SIZE, clipboardCell); + drawString(renderer, 50, 580 + CELL_SIZE + 10, 12, "C-COPY"); + drawString(renderer, 50, 580 + CELL_SIZE + 30, 12, "V-PASTE"); + drawButton(renderer, 270, 535, 80, 30, "SAVE", saveButtonPressed); drawButton(renderer, 450, 535, 80, 30, "LOAD", loadButtonPressed); diff --git a/synth_engine.cpp b/synth_engine.cpp index 2e0c5ea..1c528aa 100644 --- a/synth_engine.cpp +++ b/synth_engine.cpp @@ -55,8 +55,8 @@ SynthEngine::SynthEngine(uint32_t sampleRate) _increment(0), _volume(0.5f), _waveform(SAWTOOTH), - _isGateOpen(false), _freqToPhaseInc(0.0f), + _isGateOpen(false), _rngState(12345) { fill_wave_tables();