paulstretch
Version:
Extreme time-stretching for audio files in the browser using Web Audio API
234 lines (174 loc) • 6.88 kB
Markdown
# paulstretch
<div align="center">
<img src="paul-stretch.png" alt="PaulStretch Logo" width="400"/>
### 🎮 [Live Demo](https://josephvolmer.github.io/paulstretch/) | 📦 [NPM Package](https://www.npmjs.com/package/paulstretch) | 📖 [Documentation](#api-reference)
</div>
Extreme time-stretching for audio files in the browser using Web Audio API. This library implements Paul's Extreme Sound Stretch algorithm (PaulStretch) to create dramatic time stretching effects while maintaining sound quality.
## 🚀 Try It Now!
**→ [Launch the Interactive Demo](https://josephvolmer.github.io/paulstretch/)**
Experience the power of extreme audio stretching directly in your browser. Upload any audio file and stretch it up to 50x its original length!
## Features
- 🎵 Browser-based audio processing
- ⚡ Asynchronous processing
- 🎚️ Adjustable stretch factor and window size
- 📱 Works with Files, Blobs, and URL strings
- 🌐 UMD module support
- 🔧 Customizable AudioContext
## Installation
```bash
npm install paulstretch
```
## Usage
### Basic Example
```javascript
import PaulStretch from 'paulstretch';
async function stretchAudio() {
// Initialize with default settings (8x stretch, 0.25s window)
const ps = new PaulStretch();
try {
// Load audio file
const audioBuffer = await ps.loadAudio('path/to/audio.mp3');
// Process the audio
const stretchedBuffer = await ps.stretch(audioBuffer);
// Use the stretched audio buffer...
} catch (error) {
console.error('Error processing audio:', error);
}
}
```
### Custom Configuration
```javascript
const options = {
stretchFactor: 10.0, // Stretch audio to 10x original length
windowSize: 0.5, // Window size in seconds
audioContext: CustomAudioContext // Optional custom AudioContext
};
const ps = new PaulStretch(options);
```
### Simple File Processing
```html
<input type="file" id="audioInput" accept="audio/*">
<button id="playButton">Stretch & Play</button>
<button id="downloadButton">Stretch & Download</button>
<audio id="player" controls></audio>
```
```javascript
const fileInput = document.getElementById('audioInput');
const playButton = document.getElementById('playButton');
const downloadButton = document.getElementById('downloadButton');
const player = document.getElementById('player');
const ps = new PaulStretch({ stretchFactor: 8.0 });
// One-line stretch and play
playButton.addEventListener('click', async () => {
if (fileInput.files[0]) {
await ps.processAndPlay(fileInput.files[0]);
}
});
// One-line stretch and download
downloadButton.addEventListener('click', async () => {
if (fileInput.files[0]) {
await ps.processAndDownload(fileInput.files[0], 'my-stretched-audio.wav');
}
});
// For audio player
document.getElementById('playerButton').addEventListener('click', async () => {
if (fileInput.files[0]) {
const audioBuffer = await ps.loadAudio(fileInput.files[0]);
const stretched = await ps.stretch(audioBuffer);
player.src = await ps.toUrl(stretched);
}
});
```
### Even Simpler Examples
```javascript
// Just stretch and play - that's it!
await ps.processAndPlay('audio.mp3');
// Just stretch and download - that's it!
await ps.processAndDownload('audio.mp3', 'stretched.wav');
// Get a URL for embedding in audio elements
const audioBuffer = await ps.loadAudio('audio.mp3');
const stretched = await ps.stretch(audioBuffer);
const audioUrl = await ps.toUrl(stretched);
document.querySelector('#player').src = audioUrl;
```
## API Reference
### `PaulStretch` Class
#### Constructor Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `stretchFactor` | number | 8.0 | The amount to stretch the audio (e.g., 8.0 = 8x longer) |
| `windowSize` | number | 0.25 | Size of the processing window in seconds |
| `audioContext` | AudioContext | window.AudioContext | Custom AudioContext instance |
#### Methods
##### Core Methods
##### `loadAudio(input)`
- **Parameters:**
- `input`: File | Blob | string (URL)
- **Returns:** Promise<AudioBuffer>
- **Description:** Loads and decodes audio from various input sources
##### `stretch(audioBuffer)`
- **Parameters:**
- `audioBuffer`: AudioBuffer
- **Returns:** Promise<AudioBuffer>
- **Description:** Performs the time-stretching operation on the provided audio buffer
##### Utility Methods
##### `toBlob(audioBuffer, format = 'audio/wav')`
- **Parameters:**
- `audioBuffer`: AudioBuffer - The stretched audio buffer
- `format`: string - Audio format (default: 'audio/wav')
- **Returns:** Promise<Blob>
- **Description:** Converts AudioBuffer to a downloadable audio blob
##### `toUrl(audioBuffer, format = 'audio/wav')`
- **Parameters:**
- `audioBuffer`: AudioBuffer - The stretched audio buffer
- `format`: string - Audio format (default: 'audio/wav')
- **Returns:** Promise<string>
- **Description:** Creates an object URL from the AudioBuffer for use in audio elements
##### `play(audioBuffer)`
- **Parameters:**
- `audioBuffer`: AudioBuffer - The stretched audio buffer
- **Returns:** Promise<void>
- **Description:** Plays the stretched audio directly through the browser's audio output
##### `download(audioBuffer, filename = 'stretched-audio.wav', format = 'audio/wav')`
- **Parameters:**
- `audioBuffer`: AudioBuffer - The stretched audio buffer
- `filename`: string - Name of the downloaded file
- `format`: string - Audio format
- **Returns:** Promise<void>
- **Description:** Triggers download of the stretched audio as a file
##### Convenience Methods
##### `processAndPlay(input)`
- **Parameters:**
- `input`: File | Blob | string (URL)
- **Returns:** Promise<AudioBuffer>
- **Description:** One-step method to load, stretch, and play audio
##### `processAndDownload(input, filename = 'stretched-audio.wav', format = 'audio/wav')`
- **Parameters:**
- `input`: File | Blob | string (URL)
- `filename`: string - Name of the downloaded file
- `format`: string - Audio format
- **Returns:** Promise<AudioBuffer>
- **Description:** One-step method to load, stretch, and download audio
## Technical Details
The extreme stretching algorithm (based on PaulStretch) works by:
1. Breaking the audio into overlapping windows
2. Applying spectral processing to each window
3. Reconstructing the stretched audio using overlap-add synthesis
This implementation uses Web Audio API for processing and is optimized for browser environments, delivering extreme time-stretching capabilities directly in your web applications.
## Browser Compatibility
- Chrome 66+
- Firefox 75+
- Safari 14.1+
- Edge 79+
## Development
### Building from Source
```bash
# Install dependencies
npm install
# Run tests
npm test
# Build distribution files
npm run build
# Running Tests
npm test
```