UNPKG

webdaw-modules

Version:

a set of modules for building a web-based DAW

272 lines (242 loc) 7.23 kB
var sequencer; // import { version } from "../package.json"; var version = "0.0.25"; function openModule() { "use strict"; var protectedScope, initMethods = [], webaudioUnlocked = false, src, context, gainNode, compressor, sampleIndex = 0, compressorParams = [ "threshold", "knee", "ratio", "reduction", "attack", "release", ], ua = navigator.userAgent, os, browser, legacy = false; if (ua.match(/(iPad|iPhone|iPod)/g)) { os = "ios"; // webaudioUnlocked = false; } else if (ua.indexOf("Android") !== -1) { os = "android"; } else if (ua.indexOf("Linux") !== -1) { os = "linux"; } else if (ua.indexOf("Macintosh") !== -1) { os = "osx"; } else if (ua.indexOf("Windows") !== -1) { os = "windows"; } if (ua.indexOf("Chrome") !== -1) { // chrome, chromium and canary browser = "chrome"; if (ua.indexOf("OPR") !== -1) { browser = "opera"; } else if (ua.indexOf("Chromium") !== -1) { browser = "chromium"; } } else if (ua.indexOf("Safari") !== -1) { browser = "safari"; } else if (ua.indexOf("Firefox") !== -1) { browser = "firefox"; } else if (ua.indexOf("Trident") !== -1) { browser = "Internet Explorer"; } if (os === "ios") { if (ua.indexOf("CriOS") !== -1) { browser = "chrome"; } } // console.log(os, browser, '---', ua); if (window.AudioContext) { context = new window.AudioContext(); if (typeof context.createGainNode !== "function") { context.createGainNode = context.createGain; } } else if (window.webkitAudioContext) { context = new window.webkitAudioContext(); if (typeof context.createGainNode !== "function") { context.createGainNode = context.createGain; } } else { //alert('Your browser does not support AudioContext!\n\nPlease use one of these browsers:\n\n- Chromium (Linux | Windows)\n- Firefox (OSX | Windows)\n- Chrome (Linux | Android | OSX | Windows)\n- Canary (OSX | Windows)\n- Safari (iOS 6.0+ | OSX)\n\nIf you use Chrome or Chromium, heartbeat uses the WebMIDI api'); throw new Error( "The WebAudio API hasn't been implemented in " + browser + ", please use any other browser" ); } compressor = context.createDynamicsCompressor(); compressor.connect(context.destination); //console.log(compressor); gainNode = context.createGainNode(); //gainNode.connect(compressor); gainNode.connect(context.destination); gainNode.gain.value = 1; protectedScope = { context: context, //destination: context.destination, masterGainNode: gainNode, masterCompressor: compressor, useDelta: false, timedTasks: {}, scheduledTasks: {}, repetitiveTasks: {}, getSampleId: function () { return "S" + sampleIndex++ + new Date().getTime(); }, addInitMethod: function (method) { initMethods.push(method); }, callInitMethods: function () { var i, maxi = initMethods.length; for (i = 0; i < maxi; i++) { initMethods[i](); } }, }; /** @namespace sequencer */ sequencer = { name: "qambi", version, protectedScope: protectedScope, ui: {}, ua: ua, os: os, browser: browser, legacy: false, midi: false, webmidi: false, webaudio: true, jazz: false, ogg: false, mp3: false, record_audio: navigator.getUserMedia !== undefined, bitrate_mp3_encoding: 128, util: {}, debug: 0, // 0 = off, 1 = error, 2 = warn, 3 = info, 4 = log defaultInstrument: "sinewave", pitch: 440, bufferTime: 350 / 1000, //seconds autoAdjustBufferTime: false, noteNameMode: "sharp", minimalSongLength: 60000, //millis pauseOnBlur: false, restartOnFocus: true, defaultPPQ: 960, overrulePPQ: true, precision: 3, // means float with precision 3, e.g. 10.437 midiInputs: {}, midiOutputs: {}, storage: { midi: { id: "midi", }, audio: { id: "audio", recordings: {}, }, instruments: { id: "instruments", }, samplepacks: { id: "samplepacks", }, assetpacks: { id: "assetpacks", }, }, getAudioContext: function () { return context; }, getMasterGainNode: function () { return gainNode; }, getTime: function () { return context.currentTime; // return performance.now() / 1000; }, getTimeDiff: function () { var contextTime = context.currentTime * 1000; return performance.now() - contextTime; }, setMasterVolume: function (value) { value = value < 0 ? 0 : value > 1 ? 1 : value; gainNode.gain.value = value; }, getMasterVolume: function () { return gainNode.gain.value; }, getCompressionReduction: function () { //console.log(compressor); return compressor.reduction.value; }, enableMasterCompressor: function (flag) { if (flag) { gainNode.disconnect(0); gainNode.connect(compressor); compressor.disconnect(0); compressor.connect(context.destination); } else { compressor.disconnect(0); gainNode.disconnect(0); gainNode.connect(context.destination); } }, configureMasterCompressor: function (cfg) { /* readonly attribute AudioParam threshold; // in Decibels readonly attribute AudioParam knee; // in Decibels readonly attribute AudioParam ratio; // unit-less readonly attribute AudioParam reduction; // in Decibels readonly attribute AudioParam attack; // in Seconds readonly attribute AudioParam release; // in Seconds */ var i, param; for (i = compressorParams.length; i >= 0; i--) { param = compressorParams[i]; if (cfg[param] !== undefined) { compressor[param].value = cfg[param]; } } }, unlockWebAudio: function () { // console.log('unlock webaudio'); if (webaudioUnlocked === true) { // console.log('already unlocked'); return; } if (typeof context.resume === "function") { context.resume(); } var src = context.createOscillator(), gainNode = context.createGainNode(); gainNode.gain.value = 0; src.connect(gainNode); gainNode.connect(context.destination); if (src.noteOn !== undefined) { src.start = src.noteOn; src.stop = src.noteOff; } src.start(0); src.stop(0.001); webaudioUnlocked = true; }, }; // debug levels Object.defineProperty(sequencer, "ERROR", { value: 1 }); Object.defineProperty(sequencer, "WARN", { value: 2 }); Object.defineProperty(sequencer, "INFO", { value: 3 }); Object.defineProperty(sequencer, "LOG", { value: 4 }); }