├── index.js └── package.json /index.js: -------------------------------------------------------------------------------- 1 | /* global Audio, Blob, File, URL */ 2 | const record = require('media-recorder-stream') 3 | const MediaStream = window.MediaStream || window.webkitMediaStream 4 | 5 | module.exports = function (context) { 6 | 7 | class MediaStreamWrapper { 8 | constructor (stream) { 9 | // Hack, but Chrome won't work without this 10 | // We never do anything with this node, it's just a workaround 11 | let node = new Audio() 12 | try { 13 | node.src = URL.createObjectURL(stream) 14 | } catch (e) { 15 | // This fails in some non-Chrome browsers, ignore it. 16 | } 17 | 18 | this.microphone = context.createMediaStreamSource(stream) 19 | this.gainFilter = context.createGain() 20 | this.destination = context.createMediaStreamDestination() 21 | this.microphone.connect(this.gainFilter) 22 | this.gainFilter.connect(this.destination) 23 | this.stream = this.destination.stream 24 | } 25 | } 26 | 27 | class Waudio { 28 | constructor () { 29 | this.el = new Audio() 30 | this.source = context.createMediaElementSource(this.el) 31 | this.gainFilter = context.createGain() 32 | this.destination = context.createMediaStreamDestination() 33 | this.source.connect(this.gainFilter) 34 | this.gainFilter.connect(this.destination) 35 | this.stream = this.destination.stream 36 | this.context = context 37 | } 38 | connect (dest) { 39 | if (dest.gainFilter) dest = dest.gainFilter 40 | this.gainFilter.connect(dest) 41 | } 42 | disconnect (dest) { 43 | if (dest && dest.gainFilter) dest = dest.gainFilter 44 | this.gainFilter.disconnect(dest) 45 | } 46 | record (opts) { 47 | return record(this.stream, opts) 48 | } 49 | volume (value) { 50 | this.gainFilter.gain.value = value 51 | } 52 | seek (value) { 53 | this.el.currentTime = value 54 | } 55 | mute () { 56 | this._volume = this.gainFilter.gain.value 57 | this.volume(0) 58 | } 59 | unmute () { 60 | if (!this._volume) return 61 | this.volume(this._volume) 62 | this._volume = null 63 | } 64 | play () { 65 | this.el.play() 66 | } 67 | pause () { 68 | this.el.pause() 69 | } 70 | fadeVolume (value, delay) { 71 | let now = context.currentTime 72 | let gainNode = this.gainFilter.gain 73 | gainNode.setValueAtTime(gainNode.value, now) 74 | gainNode.linearRampToValueAtTime(value, now + delay) 75 | } 76 | } 77 | 78 | function createWaudio (inst, play) { 79 | let waud 80 | if (inst instanceof MediaStream) { 81 | let wrapper = new MediaStreamWrapper(inst) 82 | waud = new Waudio() 83 | wrapper.gainFilter.connect(waud.gainFilter) 84 | } 85 | if (inst instanceof Blob || inst instanceof File) { 86 | waud = new Waudio() 87 | waud.el.src = URL.createObjectURL(inst) 88 | } 89 | if (typeof inst === 'boolean') { 90 | play = inst 91 | inst = null 92 | } 93 | if (!inst) { 94 | waud = new Waudio() 95 | } else { 96 | // TODO: type error. 97 | } 98 | if (play) waud.gainFilter.connect(context.destination) 99 | return waud 100 | } 101 | 102 | let exports = createWaudio 103 | exports.context = context 104 | exports.Waudio = Waudio 105 | 106 | return exports 107 | } 108 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "waudio", 3 | "version": "2.7.1", 4 | "description": "Web Audio made sane.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "Mikeal Rogers (http://www.mikealrogers.com)", 11 | "license": "Apache-2.0", 12 | "dependencies": { 13 | "media-recorder-stream": "^2.1.0" 14 | } 15 | } 16 | --------------------------------------------------------------------------------