Skip to content

Commit

Permalink
Merge pull request #4 from soundcut/misc-updates-for-v2
Browse files Browse the repository at this point in the history
Misc updates for v2
  • Loading branch information
ziir authored Aug 26, 2020
2 parents 994848c + 251c8f8 commit 40d5aeb
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 27 deletions.
100 changes: 73 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,64 @@ Decode audio file data **in the browser** from a [File](https://developer.mozill

This package was originally created and is used in [soundcut](https://github.com/soundcut/app).

## Why use this over native `AudioContext.decodeAudioData()` ?

`AudioContext.decodeAudioData()`is *slow* and *does not work for large files*.
By splitting the source into chunks and decoding these in parallel, `decode-audio-data-fast` works around the native API's limitations.

## Benchmarks

*FIXME*
## Why decoding audio file data ?

Quick tests performed on my own devices (ThinkPad X280 & Pixel 3).
In the current state of [Web Audio API](https://developer.mozilla.org/docs/Web/API/Web_Audio_API), there is a variety of use-cases where one might need to decode a file (`Blob`, or `ArrayBuffer`) audio data (`AudioBuffer`) (though the current APIs are arguably quite inneficient at this, decoding the whole file upfront), including but not limited to:

Test file is a 13MB 320kbps CBR MP3 export of https://www.youtube.com/watch?v=BigolJfoANw

### Native

- Firefox Mobile: 13100ms
- Chrome Mobile: 1500ms
- [Drawing audio waveform](https://github.com/soundcut/app/blob/9feb2fe161e95e34c7a36e7ddff840d67b1f6d97/shared/components/WaveForm.js)
- Audio manipulation, such as looping, etc...

- Firefox Desktop: 3700ms
- Chrome Desktop: 2100ms

### decode-audio-data-fast
## Why use this over native `AudioContext.decodeAudioData()` ?

- Firefox Mobile: 7900ms
- Chrome Mobile: 800ms
`AudioContext.decodeAudioData()` is **slow** and **does not work for large files**.

- Firefox Desktop: 1700ms
- Chrome Desktop: 1000ms
By splitting the source into chunks and decoding these in concurrently, `decode-audio-data-fast` works around the native API's limitations.

## Usage

```sh
npm i --save @soundcut/decode-audio-data-fast
```

### ESM

```js
import { getFileAudioBuffer } from '@soundcut/decode-audio-data-fast';

function decodeFileAudioData(file) {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
return getFileAudioBuffer(file, audioCtx);
}
```

### CJS

```js
const getFileAudioBuffer = require('@soundcut/decode-audio-data-fast');
const { getFileAudioBuffer } = require('@soundcut/decode-audio-data-fast');

async function decodeFileAudioData(file) {
function decodeFileAudioData(file) {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
return await getFileAudioBuffer(file, audioCtx);
return getFileAudioBuffer(file, audioCtx);
}
```

### UMD

```html
<script src="{YOUR_HOST}/decode-audio-data-fast.standalone.umd.min.js"></script>
<script>
function decodeFileAudioData(file) {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
return window.DADF.getFileAudioBuffer(file, audioCtx);
}
</script>
```

### CDN (unpkg)

https://unpkg.com/@soundcut/decode-audio-data-fast

See all files published in [`./dist` directory](https://github.com/soundcut/decode-audio-data-fast/tree/master/dist).

## Are there other alternatives ?

Expand All @@ -57,11 +71,43 @@ async function decodeFileAudioData(file) {

At the moment, `decode-audio-data-fast` only supports `mp3` files that can be read through [mp3-parser](https://github.com/biril/mp3-parser).

## Benchmarks

See [`./benchmark` directory](benchmark/).

Visit [decodeAudioData / decode-audio-data-fast benchmark page](https://soundcut.github.io/decode-audio-data-fast/benchmark/) (open your browser console, wait a reasonably long time for all the benchmarks to run).

<img alt="Benchmark of decodeAudioData vs decode-audio-data-fast in Firefox" src="benchmark/benchmark-decode-audio-data-fast.png" />

<img alt="Benchmark of decodeAudioData vs decode-audio-data-fast in Chromium" src="benchmark/benchmark-decode-audio-data-fast-chromium.png" />

Test file is a 13MB 320kbps CBR MP3 export of https://www.youtube.com/watch?v=BigolJfoANw

## Options

The last argument of `getFileAudioBuffer` is an optional `options: { concurrency: number }` object:

```js
getFileAudioBuffer(file, audioCtx, { concurrency: 4 })
```

When omitted, `getFileAudioBuffer` will use "automatic concurrency mode", relying on [`navigator.hardwareConcurrency`](https://developer.mozilla.org/docs/Web/API/NavigatorConcurrentHardware/hardwareConcurrency):

```js
const DEFAULT_CONCURRENCY = 4;
const CONCURRENCY =
((typeof navigator !== 'undefined' && navigator.hardwareConcurrency) || 1) > 2
? navigator.hardwareConcurrency
: DEFAULT_CONCURRENCY;
```

[See rationale for "automatic concurrency mode" on Twitter.](https://twitter.com/tpillard/status/1297562478822543360)

## Browser support

*FIXME*

This module uses and assumes availability of the following APIs:
This module is intended for ~modern browsers, uses and assumes availability of the following syntax/API, among others:

- [async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
- [decodeAudioData](https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/decodeAudioData)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added benchmark/benchmark-decode-audio-data-fast.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "@soundcut/decode-audio-data-fast",
"version": "1.0.1",
"description": "Decode audio data asynchronously, in the browser using Base​Audio​Context​.decode​Audio​Data(), as fast as possible.",
"unpkg": "dist/decode-audio-data-fast.standalone.umd.min.js",
"browser": "dist/decode-audio-data-fast.standalone.umd.js",
"module": "dist/decode-audio-data-fast.esm.js",
"main": "dist/decode-audio-data-fast.cjs.js",
Expand Down

0 comments on commit 40d5aeb

Please sign in to comment.