A native macOS app that stretches audio into long-form ambient drones — a Swift/ AVFoundation + Accelerate port of the in-house PaulStretch engine from the browser project Driftscape. Drop in a WAV, pick a vibe and a length, get back a 15-second-to-60-minute stretched, reverbed drone.
Everything runs on-device. No dependencies beyond Apple frameworks.
Drone · Slow · Freeze — with a source region-looper, live spectrum, Apple stock effects, presets and batch export.
- Open
PaulStretchMac.xcodeprojin Xcode. - Press ⌘R.
⚠️ Run in Release. The bundled shared scheme already defaults Run to Release. Do not run Debug for real use — unoptimised Swift is 20–50× slower for the FFT/DSP loops (a 5-min render goes from ~0.2 s to minutes). If you ever see it crawl, check Product ▸ Scheme ▸ Edit Scheme ▸ Run ▸ Build Configuration = Release.
Signing: the project ad-hoc signs ("Sign to Run Locally"), so it runs on your own Mac with no Apple Developer account. If Xcode nags, pick your team once.
Requirements: macOS 13+, Xcode 15+ (built/tested on Xcode 17 / macOS 26 SDK).
- Five sound engines (the Style control):
- Drone — classic PaulStretch: FFT + phase-randomised STFT wash. Layered (1/3/5 passes incl. octave-shifted Shimmer layerings), pitch, onset preservation, smoothness, wash amount.
- Slow — tape-style slow-down (varispeed) tiled to length ("slowed + reverb").
- Freeze — spectral freeze: captures one instant's spectrum and sustains it forever with shimmering phase → a frozen pad. Position + Motion (a slowly scanning capture point) + Blur.
- Vocoder — phase-vocoder stretch: slows cleanly, keeping the source's structure and pitch — no wash, no tape pitch-drop.
- Grains — granular cloud: grain size, density, scatter, pitch spread and stereo pan spread.
- Source region-looper — load audio, drag on the waveform to select a region; it loops that region with a moving playhead. Drag inside to move it, click outside to deselect. The region is what gets stretched.
- Seekable render transport — play/pause, scrub, stop-to-start, plus a live 56-band spectrum analyser of the output.
- Effects — Reverb (room→cathedral→plate), Tone (3-band EQ), Filter (resonant low-pass), Echo (delay) live on playback and baked into export, plus a Shimmer reverb (pitch-shifted feedback that climbs in octaves; applied to the render itself since feedback loops can't live on the playback graph).
- Presets — 6 built-ins + save/load your own (persisted in
UserDefaults), and a Reset-to-defaults. - Export — 24/16-bit WAV, 256k AAC or Apple Lossless (
.m4a). Batch exports N random-seed variations to a folder (feeds a "pre-generate loops, host on a CDN" pipeline). - Multicore — the stretch and freeze run across all CPU cores (measured ~2000× realtime single-layer, ~280× lush, on a 14-core Mac).
The DSP engine lives in the swift-paul-stretch package
(github.com/arraypress/swift-paul-stretch),
consumed as a local SPM dependency from ../Libraries/swift-paul-stretch.
This repo is the GUI host:
swift-paul-stretch-mac/
Lifecycle/ PaulStretchApp (@main) + StretchEngine (the coordinator)
Views/ ContentView + one file per Form section
Components/ SliderRow, WaveShape, WaveformScrubber, SpectrumView
Utilities/ Panels (NSOpenPanel/NSSavePanel wrappers)
Models/ Preset + built-ins/store + legacy migration
Enums/ ExportFormat, ExportLoudness, LaneMotion
Extensions/ Binding, Double, readout formatting
genproj.py regenerates project.pbxproj (file list + package reference)
- The fast "grain" you hear on a bare stretch is inherent to PaulStretch (phase randomisation, ~30% amplitude variation — the browser has it too). The intended masker is Reverb — turn it on (Cathedral) and it smooths out.
- Effects are printed into exports. The dry render is kept in memory for scrubbing; the moment you Export, the current effect settings are baked in.
- Long renders hold a lot of RAM (~1.3 GB per 60-min stereo buffer, more for Lush). Fine on a Mac; start short while auditioning.
The engine was ported from Driftscape (Vite + React + Web Audio) — the DSP was translated faithfully (verified bit-for-bit during extraction into the swift-paul-stretch package). The stock effects are Apple units; the shimmer reverb is the package's own DSP.