Update syntax for eslint-config-scratch

This commit is contained in:
Ray Schamp 2017-04-17 11:44:51 -04:00
parent ee8462f53f
commit e50ba400f9
13 changed files with 240 additions and 233 deletions

View file

@ -10,14 +10,13 @@ const log = require('./log');
* https://github.com/LLK/scratch-flash/blob/master/src/sound/WAVFile.as
* @constructor
*/
function ADPCMSoundDecoder () {
}
const ADPCMSoundDecoder = function () {};
/**
* Decode an ADPCM sound stored in an ArrayBuffer and return a promise
* with the decoded audio buffer.
* @param {ArrayBuffer} audioData - containing ADPCM encoded wav audio
* @return {Tone.Buffer}
* @return {Tone.Buffer} the decoded audio buffer
*/
ADPCMSoundDecoder.prototype.decode = function (audioData) {
@ -25,18 +24,18 @@ ADPCMSoundDecoder.prototype.decode = function (audioData) {
const stream = new ArrayBufferStream(audioData);
const riffStr = stream.readUint8String(4);
if (riffStr != 'RIFF') {
if (riffStr !== 'RIFF') {
log.warn('incorrect adpcm wav header');
reject();
}
const lengthInHeader = stream.readInt32();
if ((lengthInHeader + 8) != audioData.byteLength) {
if ((lengthInHeader + 8) !== audioData.byteLength) {
log.warn(`adpcm wav length in header: ${lengthInHeader} is incorrect`);
}
const wavStr = stream.readUint8String(4);
if (wavStr != 'WAVE') {
if (wavStr !== 'WAVE') {
log.warn('incorrect adpcm wav header');
reject();
}
@ -54,10 +53,10 @@ ADPCMSoundDecoder.prototype.decode = function (audioData) {
const samples = this.imaDecompress(this.extractChunk('data', stream), this.adpcmBlockSize);
// todo: this line is the only place Tone is used here, should be possible to remove
// @todo this line is the only place Tone is used here, should be possible to remove
const buffer = Tone.context.createBuffer(1, samples.length, this.samplesPerSecond);
// todo: optimize this? e.g. replace the divide by storing 1/32768 and multiply?
// @todo optimize this? e.g. replace the divide by storing 1/32768 and multiply?
for (let i = 0; i < samples.length; i++) {
buffer.getChannelData(0)[i] = samples[i] / 32768;
}
@ -97,12 +96,12 @@ ADPCMSoundDecoder.prototype.extractChunk = function (chunkType, stream) {
while (stream.position < (stream.getLength() - 8)) {
const typeStr = stream.readUint8String(4);
const chunkSize = stream.readInt32();
if (typeStr == chunkType) {
if (typeStr === chunkType) {
const chunk = stream.extract(chunkSize);
return chunk;
}
stream.position += chunkSize;
}
};
@ -114,7 +113,10 @@ ADPCMSoundDecoder.prototype.extractChunk = function (chunkType, stream) {
* @return {Int16Array} the uncompressed audio samples
*/
ADPCMSoundDecoder.prototype.imaDecompress = function (compressedData, blockSize) {
let sample, step, code, delta;
let sample;
let step;
let code;
let delta;
let index = 0;
let lastByte = -1; // -1 indicates that there is no saved lastByte
const out = [];
@ -124,9 +126,9 @@ ADPCMSoundDecoder.prototype.imaDecompress = function (compressedData, blockSize)
compressedData.position = 0;
const a = 0;
while (a == 0) {
if (((compressedData.position % blockSize) == 0) && (lastByte < 0)) { // read block header
if (compressedData.getBytesAvailable() == 0) break;
while (a === 0) {
if (((compressedData.position % blockSize) === 0) && (lastByte < 0)) { // read block header
if (compressedData.getBytesAvailable() === 0) break;
sample = compressedData.readInt16();
index = compressedData.readUint8();
compressedData.position++; // skip extra header byte
@ -135,7 +137,7 @@ ADPCMSoundDecoder.prototype.imaDecompress = function (compressedData, blockSize)
} else {
// read 4-bit code and compute delta from previous sample
if (lastByte < 0) {
if (compressedData.getBytesAvailable() == 0) break;
if (compressedData.getBytesAvailable() === 0) break;
lastByte = compressedData.readUint8();
code = lastByte & 0xF;
} else {

View file

@ -8,10 +8,10 @@
* @param {ArrayBuffer} arrayBuffer - array to use as a stream
* @constructor
*/
function ArrayBufferStream (arrayBuffer) {
const ArrayBufferStream = function (arrayBuffer) {
this.arrayBuffer = arrayBuffer;
this.position = 0;
}
};
/**
* Return a new ArrayBufferStream that is a slice of the existing one
@ -40,7 +40,7 @@ ArrayBufferStream.prototype.getBytesAvailable = function () {
/**
* Read an unsigned 8 bit integer from the stream
* @return {number}
* @return {number} the next 8 bit integer in the stream
*/
ArrayBufferStream.prototype.readUint8 = function () {
const val = new Uint8Array(this.arrayBuffer, this.position, 1)[0];
@ -52,7 +52,7 @@ ArrayBufferStream.prototype.readUint8 = function () {
* Read a sequence of bytes of the given length and convert to a string.
* This is a convenience method for use with short strings.
* @param {number} length - the number of bytes to convert
* @return {String} a String made by concatenating the chars in the input
* @return {string} a String made by concatenating the chars in the input
*/
ArrayBufferStream.prototype.readUint8String = function (length) {
const arr = new Uint8Array(this.arrayBuffer, this.position, length);
@ -66,7 +66,7 @@ ArrayBufferStream.prototype.readUint8String = function (length) {
/**
* Read a 16 bit integer from the stream
* @return {number}
* @return {number} the next 16 bit integer in the stream
*/
ArrayBufferStream.prototype.readInt16 = function () {
const val = new Int16Array(this.arrayBuffer, this.position, 1)[0];
@ -76,7 +76,7 @@ ArrayBufferStream.prototype.readInt16 = function () {
/**
* Read an unsigned 16 bit integer from the stream
* @return {number}
* @return {number} the next unsigned 16 bit integer in the stream
*/
ArrayBufferStream.prototype.readUint16 = function () {
const val = new Uint16Array(this.arrayBuffer, this.position, 1)[0];
@ -86,7 +86,7 @@ ArrayBufferStream.prototype.readUint16 = function () {
/**
* Read a 32 bit integer from the stream
* @return {number}
* @return {number} the next 32 bit integer in the stream
*/
ArrayBufferStream.prototype.readInt32 = function () {
const val = new Int32Array(this.arrayBuffer, this.position, 1)[0];
@ -96,7 +96,7 @@ ArrayBufferStream.prototype.readInt32 = function () {
/**
* Read an unsigned 32 bit integer from the stream
* @return {number}
* @return {number} the next unsigned 32 bit integer in the stream
*/
ArrayBufferStream.prototype.readUint32 = function () {
const val = new Uint32Array(this.arrayBuffer, this.position, 1)[0];

View file

@ -6,7 +6,7 @@ const Tone = require('tone');
* @param {Tone.Gain} outputNode - a webAudio node that the drum sounds will send their output to
* @constructor
*/
function DrumPlayer (outputNode) {
const DrumPlayer = function (outputNode) {
this.outputNode = outputNode;
const baseUrl = 'https://raw.githubusercontent.com/LLK/scratch-audio/develop/sound-files/drums/';
@ -38,7 +38,7 @@ function DrumPlayer (outputNode) {
this.drumSounds[i] = new SoundPlayer(this.outputNode);
this.drumSounds[i].setBuffer(new Tone.Buffer(url));
}
}
};
/**
* Play a drum sound.

View file

@ -12,7 +12,7 @@ const Soundfont = require('soundfont-player');
* @param {Tone.Gain} outputNode - a webAudio node that the instrument will send its output to
* @constructor
*/
function InstrumentPlayer (outputNode) {
const InstrumentPlayer = function (outputNode) {
this.outputNode = outputNode;
// Instrument names used by Musyng Kite soundfont, in order to
@ -24,7 +24,7 @@ function InstrumentPlayer (outputNode) {
'music_box', 'steel_drums', 'marimba', 'lead_1_square', 'fx_4_atmosphere'];
this.instruments = [];
}
};
/**
* Play a note for some number of seconds with a particular instrument.
@ -63,7 +63,7 @@ InstrumentPlayer.prototype.loadInstrument = function (instrumentNum) {
inst.connect(this.outputNode);
this.instruments[instrumentNum] = inst;
});
};
/**

View file

@ -5,13 +5,13 @@ const log = require('./log');
* A SoundPlayer stores an audio buffer, and plays it
* @constructor
*/
function SoundPlayer () {
const SoundPlayer = function () {
this.outputNode = null;
this.buffer = new Tone.Buffer();
this.bufferSource = null;
this.playbackRate = 1;
this.isPlaying = false;
}
};
/**
* Connect the SoundPlayer to an output node
@ -23,7 +23,7 @@ SoundPlayer.prototype.connect = function (node) {
/**
* Set an audio buffer
* @param {Tone.Buffer} buffer
* @param {Tone.Buffer} buffer Buffer to set
*/
SoundPlayer.prototype.setBuffer = function (buffer) {
this.buffer = buffer;

View file

@ -8,7 +8,7 @@ const Tone = require('tone');
* Clamped 0-100
* @constructor
*/
function EchoEffect () {
const EchoEffect = function () {
Tone.Effect.call(this);
this.value = 0;
@ -16,7 +16,7 @@ function EchoEffect () {
this.delay = new Tone.FeedbackDelay(0.25, 0.5);
this.effectSend.chain(this.delay, this.effectReturn);
}
};
Tone.extend(EchoEffect, Tone.Effect);
@ -30,7 +30,7 @@ EchoEffect.prototype.set = function (val) {
this.value = this.clamp(this.value, 0, 100);
// mute the effect if value is 0
if (this.value == 0) {
if (this.value === 0) {
this.wet.value = 0;
} else {
this.wet.value = 0.5;
@ -53,6 +53,7 @@ EchoEffect.prototype.changeBy = function (val) {
* @param {number} input - the input to clamp
* @param {number} min - the min value to clamp to
* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/
EchoEffect.prototype.clamp = function (input, min, max) {
return Math.min(Math.max(input, min), max);

View file

@ -7,7 +7,7 @@ const Tone = require('tone');
* Clamped 0-100
* @constructor
*/
function FuzzEffect () {
const FuzzEffect = function () {
Tone.Effect.call(this);
this.value = 0;
@ -15,7 +15,7 @@ function FuzzEffect () {
this.distortion = new Tone.Distortion(1);
this.effectSend.chain(this.distortion, this.effectReturn);
}
};
Tone.extend(FuzzEffect, Tone.Effect);
@ -43,6 +43,7 @@ FuzzEffect.prototype.changeBy = function (val) {
* @param {number} input - the input to clamp
* @param {number} min - the min value to clamp to
* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/
FuzzEffect.prototype.clamp = function (input, min, max) {
return Math.min(Math.max(input, min), max);

View file

@ -7,7 +7,7 @@ const Tone = require('tone');
* Clamped -100 to 100
* @constructor
*/
function PanEffect () {
const PanEffect = function () {
Tone.Effect.call(this);
this.value = 0;
@ -15,7 +15,7 @@ function PanEffect () {
this.panner = new Tone.Panner();
this.effectSend.chain(this.panner, this.effectReturn);
}
};
Tone.extend(PanEffect, Tone.Effect);
@ -44,6 +44,7 @@ PanEffect.prototype.changeBy = function (val) {
* @param {number} input - the input to clamp
* @param {number} min - the min value to clamp to
* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/
PanEffect.prototype.clamp = function (input, min, max) {
return Math.min(Math.max(input, min), max);

View file

@ -18,12 +18,12 @@ const Tone = require('tone');
* on one SoundPlayer or a group of them.
* @constructor
*/
function PitchEffect () {
const PitchEffect = function () {
this.value = 0; // effect value
this.ratio = 1; // the playback rate ratio
this.tone = new Tone();
}
};
/**
* Set the effect value
@ -39,7 +39,7 @@ PitchEffect.prototype.set = function (val, players) {
/**
* Change the effect value
* @param {number} val - the value to change the effect by
* @param {Object} players - a dictionary of SoundPlayer objects indexed by md5
* @param {object} players - a dictionary of SoundPlayer objects indexed by md5
*/
PitchEffect.prototype.changeBy = function (val, players) {
this.set(this.value + val, players);
@ -58,7 +58,7 @@ PitchEffect.prototype.getRatio = function (val) {
/**
* Update a sound player's playback rate using the current ratio for the effect
* @param {Object} player - a SoundPlayer object
* @param {object} player - a SoundPlayer object
*/
PitchEffect.prototype.updatePlayer = function (player) {
player.setPlaybackRate(this.ratio);

View file

@ -7,7 +7,7 @@ const Tone = require('tone');
* Clamped 0 to 100
* @constructor
*/
function ReverbEffect () {
const ReverbEffect = function () {
Tone.Effect.call(this);
this.value = 0;
@ -15,7 +15,7 @@ function ReverbEffect () {
this.reverb = new Tone.Freeverb();
this.effectSend.chain(this.reverb, this.effectReturn);
}
};
Tone.extend(ReverbEffect, Tone.Effect);
@ -44,6 +44,7 @@ ReverbEffect.prototype.changeBy = function (val) {
* @param {number} input - the input to clamp
* @param {number} min - the min value to clamp to
* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/
ReverbEffect.prototype.clamp = function (input, min, max) {
return Math.min(Math.max(input, min), max);

View file

@ -11,7 +11,7 @@ const Tone = require('tone');
* Exterminate.
* @constructor
*/
function RoboticEffect () {
const RoboticEffect = function () {
Tone.Effect.call(this);
this.value = 0;
@ -20,7 +20,7 @@ function RoboticEffect () {
this.feedbackCombFilter = new Tone.FeedbackCombFilter(time, 0.9);
this.effectSend.chain(this.feedbackCombFilter, this.effectReturn);
}
};
Tone.extend(RoboticEffect, Tone.Effect);
@ -32,7 +32,7 @@ RoboticEffect.prototype.set = function (val) {
this.value = val;
// mute the effect if value is 0
if (this.value == 0) {
if (this.value === 0) {
this.wet.value = 0;
} else {
this.wet.value = 1;

View file

@ -11,7 +11,7 @@ const Tone = require('tone');
* Clamped 0 to 100
* @constructor
*/
function WobbleEffect () {
const WobbleEffect = function () {
Tone.Effect.call(this);
this.value = 0;
@ -21,7 +21,7 @@ function WobbleEffect () {
this.wobbleLFO.connect(this.wobbleGain.gain);
this.effectSend.chain(this.wobbleGain, this.effectReturn);
}
};
Tone.extend(WobbleEffect, Tone.Effect);
@ -52,6 +52,7 @@ WobbleEffect.prototype.changeBy = function (val) {
* @param {number} input - the input to clamp
* @param {number} min - the min value to clamp to
* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/
WobbleEffect.prototype.clamp = function (input, min, max) {
return Math.min(Math.max(input, min), max);

View file

@ -19,195 +19,14 @@ const DrumPlayer = require('./DrumPlayer');
* that handles global functionality, and AudioPlayers, belonging to individual sprites and clones.
*/
/**
* There is a single instance of the AudioEngine. It handles global audio properties and effects,
* loads all the audio buffers for sounds belonging to sprites, and creates a single instrument player
* and a drum player, used by all play note and play drum blocks.
* @constructor
*/
function AudioEngine () {
// create the global audio effects
this.roboticEffect = new RoboticEffect();
this.fuzzEffect = new FuzzEffect();
this.echoEffect = new EchoEffect();
this.reverbEffect = new ReverbEffect();
// chain the global effects to the output
this.input = new Tone.Gain();
this.input.chain(
this.roboticEffect, this.fuzzEffect, this.echoEffect, this.reverbEffect,
Tone.Master
);
// global tempo in bpm (beats per minute)
this.currentTempo = 60;
// instrument player for play note blocks
this.instrumentPlayer = new InstrumentPlayer(this.input);
this.numInstruments = this.instrumentPlayer.instrumentNames.length;
// drum player for play drum blocks
this.drumPlayer = new DrumPlayer(this.input);
this.numDrums = this.drumPlayer.drumSounds.length;
// a map of md5s to audio buffers, holding sounds for all sprites
this.audioBuffers = {};
// microphone, for measuring loudness, with a level meter analyzer
this.mic = null;
this.micMeter = null;
}
/**
* Decode a sound, decompressing it into audio samples.
* Store a reference to it the sound in the audioBuffers dictionary, indexed by md5
* @param {Object} sound - an object containing audio data and metadata for a sound
* @property {Buffer} data - sound data loaded from scratch-storage.
* @property {string} format - format type, either empty or adpcm.
* @property {string} md5 - the MD5 and extension of the sound.
* @returns {?Promise} - a promise which will resolve after the audio buffer is stored, or null on error.
*/
AudioEngine.prototype.decodeSound = function (sound) {
let loaderPromise = null;
switch (sound.format) {
case '':
loaderPromise = Tone.context.decodeAudioData(sound.data.buffer);
break;
case 'adpcm':
loaderPromise = (new ADPCMSoundDecoder()).decode(sound.data.buffer);
break;
default:
return log.warn('unknown sound format', sound.format);
}
const storedContext = this;
return loaderPromise.then(
decodedAudio => {
storedContext.audioBuffers[sound.md5] = new Tone.Buffer(decodedAudio);
},
error => {
log.warn('audio data could not be decoded', error);
}
);
};
/**
* An older version of the AudioEngine had this function to load all sounds
* This is a stub to provide a warning when it is called
* @todo remove this
*/
AudioEngine.prototype.loadSounds = function () {
log.warn('The loadSounds function is no longer available. Please use Scratch Storage.');
};
/**
* Play a note for a duration on an instrument with a volume
* @param {number} note - a MIDI note number
* @param {number} beats - a duration in beats
* @param {number} inst - an instrument number (0-indexed)
* @param {number} vol - a volume level (0-100%)
* @return {Promise} a Promise that resolves after the duration has elapsed
*/
AudioEngine.prototype.playNoteForBeatsWithInstAndVol = function (note, beats, inst, vol) {
const sec = this.beatsToSec(beats);
this.instrumentPlayer.playNoteForSecWithInstAndVol(note, sec, inst, vol);
return this.waitForBeats(beats);
};
/**
* Convert a number of beats to a number of seconds, using the current tempo
* @param {number} beats
* @return {number} seconds
*/
AudioEngine.prototype.beatsToSec = function (beats) {
return (60 / this.currentTempo) * beats;
};
/**
* Wait for some number of beats
* @param {number} beats
* @return {Promise} a Promise that resolves after the duration has elapsed
*/
AudioEngine.prototype.waitForBeats = function (beats) {
const storedContext = this;
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, storedContext.beatsToSec(beats) * 1000);
});
};
/**
* Set the global tempo in bpm (beats per minute)
* @param {number} value - the new tempo to set
*/
AudioEngine.prototype.setTempo = function (value) {
this.currentTempo = value;
};
/**
* Change the tempo by some number of bpm (beats per minute)
* @param {number} value - the number of bpm to change the tempo by
*/
AudioEngine.prototype.changeTempo = function (value) {
this.setTempo(this.currentTempo + value);
};
/**
* Get the current loudness of sound received by the microphone.
* Sound is measured in RMS and smoothed.
* @return {number} loudness scaled 0 to 100
*/
AudioEngine.prototype.getLoudness = function () {
if (!this.mic) {
this.mic = new Tone.UserMedia();
this.micMeter = new Tone.Meter('level', 0.5);
this.mic.open();
this.mic.connect(this.micMeter);
}
if (this.mic && this.mic.state == 'started') {
return this.micMeter.value * 100;
}
return -1;
};
/**
* Names of the audio effects.
* @readonly
* @enum {string}
*/
AudioEngine.prototype.EFFECT_NAMES = {
pitch: 'pitch',
pan: 'pan',
echo: 'echo',
reverb: 'reverb',
fuzz: 'fuzz',
robot: 'robot'
};
/**
* Create an AudioPlayer. Each sprite or clone has an AudioPlayer.
* It includes a reference to the AudioEngine so it can use global
* functionality such as playing notes.
* @return {AudioPlayer}
*/
AudioEngine.prototype.createPlayer = function () {
return new AudioPlayer(this);
};
/**
* Each sprite or clone has an audio player
* the audio player handles sound playback, volume, and the sprite-specific audio effects:
* pitch and pan
* @param {AudioEngine}
* @param {AudioEngine} audioEngine AudioEngine for player
* @constructor
*/
function AudioPlayer (audioEngine) {
const AudioPlayer = function (audioEngine) {
this.audioEngine = audioEngine;
@ -226,7 +45,7 @@ function AudioPlayer (audioEngine) {
// sound players that are currently playing, indexed by the sound's md5
this.activeSoundPlayers = {};
}
};
/**
* Play a sound
@ -344,4 +163,185 @@ AudioPlayer.prototype.setVolume = function (value) {
this.effectsNode.gain.value = value / 100;
};
/**
* There is a single instance of the AudioEngine. It handles global audio properties and effects,
* loads all the audio buffers for sounds belonging to sprites, and creates a single instrument player
* and a drum player, used by all play note and play drum blocks.
* @constructor
*/
const AudioEngine = function () {
// create the global audio effects
this.roboticEffect = new RoboticEffect();
this.fuzzEffect = new FuzzEffect();
this.echoEffect = new EchoEffect();
this.reverbEffect = new ReverbEffect();
// chain the global effects to the output
this.input = new Tone.Gain();
this.input.chain(
this.roboticEffect, this.fuzzEffect, this.echoEffect, this.reverbEffect,
Tone.Master
);
// global tempo in bpm (beats per minute)
this.currentTempo = 60;
// instrument player for play note blocks
this.instrumentPlayer = new InstrumentPlayer(this.input);
this.numInstruments = this.instrumentPlayer.instrumentNames.length;
// drum player for play drum blocks
this.drumPlayer = new DrumPlayer(this.input);
this.numDrums = this.drumPlayer.drumSounds.length;
// a map of md5s to audio buffers, holding sounds for all sprites
this.audioBuffers = {};
// microphone, for measuring loudness, with a level meter analyzer
this.mic = null;
this.micMeter = null;
};
/**
* Decode a sound, decompressing it into audio samples.
* Store a reference to it the sound in the audioBuffers dictionary, indexed by md5
* @param {object} sound - an object containing audio data and metadata for a sound
* @property {Buffer} data - sound data loaded from scratch-storage.
* @property {string} format - format type, either empty or adpcm.
* @property {string} md5 - the MD5 and extension of the sound.
* @returns {?Promise} - a promise which will resolve after the audio buffer is stored, or null on error.
*/
AudioEngine.prototype.decodeSound = function (sound) {
let loaderPromise = null;
switch (sound.format) {
case '':
loaderPromise = Tone.context.decodeAudioData(sound.data.buffer);
break;
case 'adpcm':
loaderPromise = (new ADPCMSoundDecoder()).decode(sound.data.buffer);
break;
default:
return log.warn('unknown sound format', sound.format);
}
const storedContext = this;
return loaderPromise.then(
decodedAudio => {
storedContext.audioBuffers[sound.md5] = new Tone.Buffer(decodedAudio);
},
error => {
log.warn('audio data could not be decoded', error);
}
);
};
/**
* An older version of the AudioEngine had this function to load all sounds
* This is a stub to provide a warning when it is called
* @todo remove this
*/
AudioEngine.prototype.loadSounds = function () {
log.warn('The loadSounds function is no longer available. Please use Scratch Storage.');
};
/**
* Play a note for a duration on an instrument with a volume
* @param {number} note - a MIDI note number
* @param {number} beats - a duration in beats
* @param {number} inst - an instrument number (0-indexed)
* @param {number} vol - a volume level (0-100%)
* @return {Promise} a Promise that resolves after the duration has elapsed
*/
AudioEngine.prototype.playNoteForBeatsWithInstAndVol = function (note, beats, inst, vol) {
const sec = this.beatsToSec(beats);
this.instrumentPlayer.playNoteForSecWithInstAndVol(note, sec, inst, vol);
return this.waitForBeats(beats);
};
/**
* Convert a number of beats to a number of seconds, using the current tempo
* @param {number} beats number of beats to convert to secs
* @return {number} seconds number of seconds `beats` will last
*/
AudioEngine.prototype.beatsToSec = function (beats) {
return (60 / this.currentTempo) * beats;
};
/**
* Wait for some number of beats
* @param {number} beats number of beats to wait for
* @return {Promise} a Promise that resolves after the duration has elapsed
*/
AudioEngine.prototype.waitForBeats = function (beats) {
const storedContext = this;
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, storedContext.beatsToSec(beats) * 1000);
});
};
/**
* Set the global tempo in bpm (beats per minute)
* @param {number} value - the new tempo to set
*/
AudioEngine.prototype.setTempo = function (value) {
this.currentTempo = value;
};
/**
* Change the tempo by some number of bpm (beats per minute)
* @param {number} value - the number of bpm to change the tempo by
*/
AudioEngine.prototype.changeTempo = function (value) {
this.setTempo(this.currentTempo + value);
};
/**
* Get the current loudness of sound received by the microphone.
* Sound is measured in RMS and smoothed.
* @return {number} loudness scaled 0 to 100
*/
AudioEngine.prototype.getLoudness = function () {
if (!this.mic) {
this.mic = new Tone.UserMedia();
this.micMeter = new Tone.Meter('level', 0.5);
this.mic.open();
this.mic.connect(this.micMeter);
}
if (this.mic && this.mic.state === 'started') {
return this.micMeter.value * 100;
}
return -1;
};
/**
* Names of the audio effects.
* @readonly
* @enum {string}
*/
AudioEngine.prototype.EFFECT_NAMES = {
pitch: 'pitch',
pan: 'pan',
echo: 'echo',
reverb: 'reverb',
fuzz: 'fuzz',
robot: 'robot'
};
/**
* Create an AudioPlayer. Each sprite or clone has an AudioPlayer.
* It includes a reference to the AudioEngine so it can use global
* functionality such as playing notes.
* @return {AudioPlayer} new AudioPlayer instance
*/
AudioEngine.prototype.createPlayer = function () {
return new AudioPlayer(this);
};
module.exports = AudioEngine;