Initial release — InstaGrain granular synthesizer v1.0

8-voice polyphonic granular synth (VST3/AU/LV2) with:
- 128 grain pool per voice, Hann windowing, linear interpolation
- Root note selector, sample rate correction, sustain pedal (CC64)
- Scatter controls, direction modes (Fwd/Rev/PingPong), freeze
- ADSR envelope, global filter (LP/HP/BP), reverb
- Waveform display with grain visualization
- Drag & drop sample loading, full state save/restore
- CI/CD for Windows/macOS/Linux

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hariel1985
2026-03-26 17:26:06 +01:00
commit 55b5f89ac5
34 fájl változott, egészen pontosan 2728 új sor hozzáadva és 0 régi sor törölve

52
Source/GrainCloud.h Normal file
Fájl megtekintése

@@ -0,0 +1,52 @@
#pragma once
#include <JuceHeader.h>
#include "Grain.h"
class GrainCloud
{
public:
static constexpr int maxGrains = 128;
enum class Direction { Forward, Reverse, PingPong };
GrainCloud();
void prepare (double sampleRate);
void processBlock (juce::AudioBuffer<float>& output, int numSamples,
const juce::AudioBuffer<float>& sourceBuffer);
void reset();
// Parameters (atomic — GUI writes, audio reads)
std::atomic<float> position { 0.5f }; // 0-1
std::atomic<float> grainSizeMs { 100.0f }; // 10-500
std::atomic<float> density { 10.0f }; // 1-100 grains/sec
std::atomic<float> pitchSemitones { 0.0f }; // -24..+24
std::atomic<float> pan { 0.0f }; // -1..+1
std::atomic<float> posScatter { 0.0f }; // 0-1
std::atomic<float> sizeScatter { 0.0f }; // 0-1
std::atomic<float> pitchScatter { 0.0f }; // 0-1
std::atomic<float> panScatter { 0.0f }; // 0-1
std::atomic<int> direction { 0 }; // 0=Fwd, 1=Rev, 2=PingPong
std::atomic<bool> freeze { false };
// Extra pitch offset from MIDI note
float midiPitchOffset = 0.0f;
// Sample rate correction: sourceSampleRate / dawSampleRate
float sampleRateRatio = 1.0f;
// For visualization — snapshot of active grains
struct GrainInfo { int startSample; int lengthSamples; float progress; };
std::array<GrainInfo, maxGrains> getActiveGrainInfo() const;
int getActiveGrainCount() const;
private:
double currentSampleRate = 44100.0;
std::array<Grain, maxGrains> grains;
GrainWindow window;
int samplesUntilNextGrain = 0;
juce::Random rng;
void spawnGrain (const juce::AudioBuffer<float>& sourceBuffer);
float readSampleInterpolated (const juce::AudioBuffer<float>& buffer, double position) const;
};