Files
InstaGrain/Source/Grain.h
hariel1985 55b5f89ac5 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>
2026-03-26 17:26:06 +01:00

46 sor
1.5 KiB
C++

#pragma once
#include <JuceHeader.h>
// ============================================================
// Hann window lookup table (1024 points, computed once)
// ============================================================
struct GrainWindow
{
static constexpr int tableSize = 1024;
float table[tableSize];
GrainWindow()
{
for (int i = 0; i < tableSize; ++i)
{
float phase = (float) i / (float) (tableSize - 1);
table[i] = 0.5f * (1.0f - std::cos (juce::MathConstants<float>::twoPi * phase));
}
}
float getValue (float phase) const
{
float index = juce::jlimit (0.0f, 1.0f, phase) * (float) (tableSize - 1);
int i0 = (int) index;
int i1 = std::min (i0 + 1, tableSize - 1);
float frac = index - (float) i0;
return table[i0] + frac * (table[i1] - table[i0]);
}
};
// ============================================================
// Single grain
// ============================================================
struct Grain
{
int startSample = 0; // where in source buffer
int lengthSamples = 0; // grain duration in samples
float pitchRatio = 1.0f; // playback speed
double readPosition = 0.0; // current fractional read position
int samplesElapsed = 0; // output samples generated
float panPosition = 0.0f; // -1 left, +1 right
float volume = 1.0f;
bool reverse = false;
bool active = false;
};