# rsgp

Audio synthesis web application for generating random sound samples. Users generate sounds via different synthesis engines, mutate parameters, apply audio processors in multiple passes, and export as WAV. Built for musicians seeking unexpected textures and one-shots.

## Technologies

- Svelte 5 + TypeScript
- Web Audio API
- Vite (rolldown-vite)
- pnpm

## Structure

```
src/
├── main.ts              # Entry point
├── App.svelte           # Main UI
└── lib/
    ├── components/      # UI components (waveform, VU meter, modals)
    ├── audio/
    │   ├── engines/     # synthesis engines + registry
    │   ├── processors/  # audio processors + registry
    │   ├── services/    # AudioService (Web Audio API wrapper)
    │   └── utils/       # WAVEncoder, AudioEdit
    └── utils/           # Colors, keyboard, pitch, settings
public/
├── fonts/               # DepartureMono
└── wavetables/          # 1000+ AKWF wavetables
```

## Development

```sh
pnpm install
pnpm dev
pnpm build
```

## Docker

```sh
docker build -t rsgp .
docker run -p 8080:80 rsgp
```

Opens on http://localhost:8080

## Extending

### Adding Synthesis Engines

1. Create a single file in `src/lib/audio/engines/` implementing the `SynthEngine` interface
2. Implement `getName()`, `getDescription()`, `generate()`, `randomParams()`, and `mutateParams()`
3. Must return stereo output: `[Float32Array, Float32Array]`
4. Keep all DSP code, helpers, and types in the same file
5. Register in `src/lib/audio/engines/registry.ts`

### Adding CSound-Based Synthesis Engines

For complex DSP algorithms, you can leverage CSound's powerful audio language:

1. Create a single file in `src/lib/audio/engines/` extending the `CsoundEngine<ParamsType>` abstract class
2. Define a TypeScript interface for your parameters
3. Implement required methods:
   - `getName()`: Engine display name
   - `getDescription()`: Brief description
   - `getType()`: Return `'generative'`, `'sample'`, or `'input'`
   - `getOrchestra()`: Return CSound orchestra code as a string
   - `getParametersForCsound(params)`: Map TypeScript params to CSound channel parameters
   - `randomParams(pitchLock?)`: Generate random parameter values
   - `mutateParams(params, mutationAmount?, pitchLock?)`: Mutate existing parameters
4. Keep all enums, interfaces, and helper logic in the same file
5. Register in `src/lib/audio/engines/registry.ts`

**CSound Orchestra Guidelines:**
- Use `instr 1` as your main instrument
- Read parameters via `chnget "paramName"`
- Duration is available as `p3`
- Time-based parameters (attack, decay, release) should be ratios (0-1) scaled by `p3`
- Output stereo audio with `outs aLeft, aRight`
- The base class handles WAV parsing, normalization, and fade-in

**Example:**
```typescript
import { CsoundEngine, type CsoundParameter } from './base/CsoundEngine';

interface MyParams {
  frequency: number;
  resonance: number;
}

export class MyEngine extends CsoundEngine<MyParams> {
  getName() { return 'My Engine'; }
  getDescription() { return 'Description'; }
  getType() { return 'generative' as const; }

  protected getOrchestra(): string {
    return `
instr 1
  iFreq chnget "frequency"
  iRes chnget "resonance"
  aNoise noise 1, 0
  aOut butterbp aNoise, iFreq, iRes
  outs aOut, aOut
endin
`;
  }

  protected getParametersForCsound(params: MyParams): CsoundParameter[] {
    return [
      { channelName: 'frequency', value: params.frequency },
      { channelName: 'resonance', value: params.resonance }
    ];
  }

  randomParams() { /* ... */ }
  mutateParams(params, amount = 0.15) { /* ... */ }
}
```

### Adding Audio Processors

1. Create a single file in `src/lib/audio/processors/` implementing the `AudioProcessor` interface
2. Implement `getName()`, `getDescription()`, and `process()`
3. Must take and return stereo: `[Float32Array, Float32Array]`
4. Keep all processing logic, helpers, and types in the same file
5. Register in `src/lib/audio/processors/registry.ts`

## Credits

- Wavetables from [Adventure Kid Waveforms](https://www.adventurekid.se/akrt/waveforms/adventure-kid-waveforms/) by Kristoffer Ekstrand
- [Garten Salat](https://garten.salat.dev/) by Felix Roos for drum synthesis inspiration.
- [Csound](https://csound.com/) for powerful audio synthesis capabilities.
  - Steven Yi for some synths: [csound-live-code](https://github.com/kunstmusik/csound-live-code).
