Skip to content

Commit

Permalink
Merge pull request #534 from ogg-decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
release-train[bot] authored Aug 28, 2019
2 parents 9c671dd + 74c92cd commit 7ec61dd
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 1 deletion.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
**/node_modules/**/*
**/vendor/**/*
**/lib/**/*
**/dist/**/*
**/build/**/*
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
**/node_modules/**/*
**/vendor/**/*
**/lib/**/*
**/dist/**/*
**/build/**/*
Expand Down
19 changes: 18 additions & 1 deletion src/sampling-master/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import defaultAudioContext from 'bemuse/audio-context'
import readBlob from 'bemuse/utils/read-blob'
import { decodeOGG } from './ogg'

export const FADE_LENGTH = 0.001

let dummyAudioTag = document.createElement('audio')

// Checks whether an audio format is supported.
export function canPlay(type) {
// We have a Vorbis audio decoder!
if (type === 'audio/ogg; codecs="vorbis"') return true
return dummyAudioTag.canPlayType(type) === 'probably'
}

const needsVorbisDecoder = !dummyAudioTag.canPlayType(
'audio/ogg; codecs="vorbis"'
)

// The sampling master is a wrapper class around Web Audio API
// that takes care of:
//
Expand Down Expand Up @@ -92,6 +98,17 @@ export class SamplingMaster {

_decodeAudio(arrayBuffer) {
return new Promise((resolve, reject) => {
if (needsVorbisDecoder && arrayBuffer.byteLength > 4) {
const view = new Uint8Array(arrayBuffer, 0, 4)
if (
view[0] === 0x4f &&
view[1] === 0x67 &&
view[2] === 0x67 &&
view[3] === 0x53
) {
return resolve(decodeOGG(this.audioContext, arrayBuffer))
}
}
this.audioContext.decodeAudioData(
arrayBuffer,
function decodeAudioDataSuccess(audioBuffer) {
Expand Down
92 changes: 92 additions & 0 deletions src/sampling-master/ogg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import throat from 'throat'

let decoderPromise

const limit = throat(1)

/**
* Decodes an OGG file using stbvorbis.js.
*
* @param {AudioContext} audioContext
* @param {ArrayBuffer} arrayBuffer
*/
export async function decodeOGG(audioContext, arrayBuffer) {
if (!decoderPromise) {
decoderPromise = import(/* webpackChunkName: 'stbvorbis' */ 'raw-loader!./vendor/stbvorbis/stbvorbis-e6da5fe.js')
.then(ns => ns.default)
.then(src => {
// eslint-disable-next-line no-eval
return (0, eval)(src + ';stbvorbis')
})
}
const stbvorbis = await decoderPromise
return limit(
() =>
new Promise((resolve, reject) => {
const buffers = []
let totalLength = 0
let sampleRate
stbvorbis.decode(arrayBuffer, function(e) {
if (e.data) {
sampleRate = e.sampleRate
buffers.push(e.data)
totalLength += e.data[0].length
}
if (e.error) {
reject(
e.error instanceof Error
? e.error
: `stbvorbis.js Error: ${e.error}`
)
}
if (e.eof) {
resolve(
createBuffer(audioContext, buffers, totalLength, sampleRate)
)
}
})
})
)
}

/**
* @param {AudioContext} audioContext
* @param {Float32Array[]} decodedChunks
* @param {number} totalLength
* @param {number} sampleRate
*/
async function createBuffer(
audioContext,
decodedChunks,
totalLength,
sampleRate
) {
if (!totalLength) {
throw new Error(`stbvorbis.js Error: No length`)
}
if (!sampleRate) {
throw new Error(`stbvorbis.js Error: No sample rate`)
}
var audioBuffer = audioContext.createBuffer(
decodedChunks[0].length,
totalLength,
sampleRate
)
var track = Array(audioBuffer.numberOfChannels)
.fill()
.map(() => 0)
var data = Array(audioBuffer.numberOfChannels)
.fill()
.map((_, ch) => audioBuffer.getChannelData(ch))
for (const chunk of decodedChunks) {
chunk.forEach(function(a, ch) {
// buf.copyToChannel(a, ch, track[ch]) — not supported in iOS Safari!
var offset = track[ch]
for (var i = 0; i < a.length; i++) {
data[ch][i + offset] = a[i]
}
track[ch] += a.length
})
}
return audioBuffer
}
1 change: 1 addition & 0 deletions src/sampling-master/vendor/stbvorbis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/hajimehoshi/stbvorbis.js
1 change: 1 addition & 0 deletions src/sampling-master/vendor/stbvorbis/stbvorbis-e6da5fe.js

Large diffs are not rendered by default.

0 comments on commit 7ec61dd

Please sign in to comment.