New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

scratch-audio

Package Overview
Dependencies
Maintainers
1
Versions
472
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

scratch-audio - npm Package Compare versions

Comparing version 0.1.0-prerelease.1492442591 to 0.1.0-prerelease.1492531432

.eslintrc.js

3

package.json
{
"name": "scratch-audio",
"version": "0.1.0-prerelease.1492442591",
"version": "0.1.0-prerelease.1492531432",
"description": "audio engine for scratch 3.0",

@@ -29,2 +29,3 @@ "main": "dist.js",

"eslint": "^3.19.0",
"eslint-config-scratch": "^3.1.0",
"json": "^9.0.6",

@@ -31,0 +32,0 @@ "minilog": "^3.0.1",

@@ -1,4 +0,4 @@

var ArrayBufferStream = require('./ArrayBufferStream');
var Tone = require('tone');
var log = require('./log');
const ArrayBufferStream = require('./ArrayBufferStream');
const Tone = require('tone');
const log = require('./log');

@@ -13,4 +13,3 @@ /**

*/
function ADPCMSoundDecoder () {
}
const ADPCMSoundDecoder = function () {};

@@ -21,11 +20,11 @@ /**

* @param {ArrayBuffer} audioData - containing ADPCM encoded wav audio
* @return {Tone.Buffer}
* @return {Tone.Buffer} the decoded audio buffer
*/
ADPCMSoundDecoder.prototype.decode = function (audioData) {
return new Promise(function (resolve, reject) {
var stream = new ArrayBufferStream(audioData);
return new Promise((resolve, reject) => {
const stream = new ArrayBufferStream(audioData);
var riffStr = stream.readUint8String(4);
if (riffStr != 'RIFF') {
const riffStr = stream.readUint8String(4);
if (riffStr !== 'RIFF') {
log.warn('incorrect adpcm wav header');

@@ -35,9 +34,9 @@ reject();

var lengthInHeader = stream.readInt32();
if ((lengthInHeader + 8) != audioData.byteLength) {
log.warn('adpcm wav length in header: ' + lengthInHeader + ' is incorrect');
const lengthInHeader = stream.readInt32();
if ((lengthInHeader + 8) !== audioData.byteLength) {
log.warn(`adpcm wav length in header: ${lengthInHeader} is incorrect`);
}
var wavStr = stream.readUint8String(4);
if (wavStr != 'WAVE') {
const wavStr = stream.readUint8String(4);
if (wavStr !== 'WAVE') {
log.warn('incorrect adpcm wav header');

@@ -47,3 +46,3 @@ reject();

var formatChunk = this.extractChunk('fmt ', stream);
const formatChunk = this.extractChunk('fmt ', stream);
this.encoding = formatChunk.readUint16();

@@ -59,9 +58,9 @@ this.channels = formatChunk.readUint16();

var samples = this.imaDecompress(this.extractChunk('data', stream), this.adpcmBlockSize);
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
var buffer = Tone.context.createBuffer(1, samples.length, this.samplesPerSecond);
// @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?
for (var i=0; i<samples.length; i++) {
// @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;

@@ -71,3 +70,3 @@ }

resolve(buffer);
}.bind(this));
});
};

@@ -104,10 +103,10 @@

while (stream.position < (stream.getLength() - 8)) {
var typeStr = stream.readUint8String(4);
var chunkSize = stream.readInt32();
if (typeStr == chunkType) {
var chunk = stream.extract(chunkSize);
const typeStr = stream.readUint8String(4);
const chunkSize = stream.readInt32();
if (typeStr === chunkType) {
const chunk = stream.extract(chunkSize);
return chunk;
} else {
stream.position += chunkSize;
}
stream.position += chunkSize;
}

@@ -124,6 +123,9 @@ };

ADPCMSoundDecoder.prototype.imaDecompress = function (compressedData, blockSize) {
var sample, step, code, delta;
var index = 0;
var lastByte = -1; // -1 indicates that there is no saved lastByte
var out = [];
let sample;
let step;
let code;
let delta;
let index = 0;
let lastByte = -1; // -1 indicates that there is no saved lastByte
const out = [];

@@ -134,6 +136,6 @@ // Bail and return no samples if we have no data

compressedData.position = 0;
var a = 0;
while (a==0) {
if (((compressedData.position % blockSize) == 0) && (lastByte < 0)) { // read block header
if (compressedData.getBytesAvailable() == 0) break;
const a = 0;
while (a === 0) {
if (((compressedData.position % blockSize) === 0) && (lastByte < 0)) { // read block header
if (compressedData.getBytesAvailable() === 0) break;
sample = compressedData.readInt16();

@@ -147,3 +149,3 @@ index = compressedData.readUint8();

if (lastByte < 0) {
if (compressedData.getBytesAvailable() == 0) break;
if (compressedData.getBytesAvailable() === 0) break;
lastByte = compressedData.readUint8();

@@ -172,3 +174,3 @@ code = lastByte & 0xF;

}
var samples = Int16Array.from(out);
const samples = Int16Array.from(out);
return samples;

@@ -175,0 +177,0 @@ };

@@ -11,6 +11,6 @@ /**

*/
function ArrayBufferStream (arrayBuffer) {
const ArrayBufferStream = function (arrayBuffer) {
this.arrayBuffer = arrayBuffer;
this.position = 0;
}
};

@@ -23,4 +23,4 @@ /**

ArrayBufferStream.prototype.extract = function (length) {
var slicedArrayBuffer = this.arrayBuffer.slice(this.position, this.position+length);
var newStream = new ArrayBufferStream(slicedArrayBuffer);
const slicedArrayBuffer = this.arrayBuffer.slice(this.position, this.position + length);
const newStream = new ArrayBufferStream(slicedArrayBuffer);
return newStream;

@@ -45,6 +45,6 @@ };

* 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 () {
var val = new Uint8Array(this.arrayBuffer, this.position, 1)[0];
const val = new Uint8Array(this.arrayBuffer, this.position, 1)[0];
this.position += 1;

@@ -58,9 +58,9 @@ return val;

* @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) {
var arr = new Uint8Array(this.arrayBuffer, this.position, length);
const arr = new Uint8Array(this.arrayBuffer, this.position, length);
this.position += length;
var str = '';
for (var i=0; i<arr.length; i++) {
let str = '';
for (let i = 0; i < arr.length; i++) {
str += String.fromCharCode(arr[i]);

@@ -73,6 +73,6 @@ }

* Read a 16 bit integer from the stream
* @return {number}
* @return {number} the next 16 bit integer in the stream
*/
ArrayBufferStream.prototype.readInt16 = function () {
var val = new Int16Array(this.arrayBuffer, this.position, 1)[0];
const val = new Int16Array(this.arrayBuffer, this.position, 1)[0];
this.position += 2; // one 16 bit int is 2 bytes

@@ -84,6 +84,6 @@ return val;

* 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 () {
var val = new Uint16Array(this.arrayBuffer, this.position, 1)[0];
const val = new Uint16Array(this.arrayBuffer, this.position, 1)[0];
this.position += 2; // one 16 bit int is 2 bytes

@@ -95,6 +95,6 @@ return val;

* Read a 32 bit integer from the stream
* @return {number}
* @return {number} the next 32 bit integer in the stream
*/
ArrayBufferStream.prototype.readInt32 = function () {
var val = new Int32Array(this.arrayBuffer, this.position, 1)[0];
const val = new Int32Array(this.arrayBuffer, this.position, 1)[0];
this.position += 4; // one 32 bit int is 4 bytes

@@ -106,6 +106,6 @@ return val;

* 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 () {
var val = new Uint32Array(this.arrayBuffer, this.position, 1)[0];
const val = new Uint32Array(this.arrayBuffer, this.position, 1)[0];
this.position += 4; // one 32 bit int is 4 bytes

@@ -112,0 +112,0 @@ return val;

@@ -1,3 +0,3 @@

var SoundPlayer = require('./SoundPlayer');
var Tone = require('tone');
const SoundPlayer = require('./SoundPlayer');
const Tone = require('tone');

@@ -9,7 +9,7 @@ /**

*/
function DrumPlayer (outputNode) {
const DrumPlayer = function (outputNode) {
this.outputNode = outputNode;
var baseUrl = 'https://raw.githubusercontent.com/LLK/scratch-audio/develop/sound-files/drums/';
var fileNames = [
const baseUrl = 'https://raw.githubusercontent.com/LLK/scratch-audio/develop/sound-files/drums/';
const fileNames = [
'SnareDrum(1)',

@@ -37,8 +37,8 @@ 'BassDrum(1b)',

for (var i=0; i<fileNames.length; i++) {
var url = baseUrl + fileNames[i] + '_22k.wav';
for (let i = 0; i < fileNames.length; i++) {
const url = `${baseUrl + fileNames[i]}_22k.wav`;
this.drumSounds[i] = new SoundPlayer(this.outputNode);
this.drumSounds[i].setBuffer(new Tone.Buffer(url));
}
}
};

@@ -61,3 +61,3 @@ /**

DrumPlayer.prototype.stopAll = function () {
for (var i=0; i<this.drumSounds.length; i++) {
for (let i = 0; i < this.drumSounds.length; i++) {
this.drumSounds[i].stop();

@@ -64,0 +64,0 @@ }

@@ -1,2 +0,2 @@

var Tone = require('tone');
const Tone = require('tone');

@@ -11,3 +11,3 @@ /**

*/
function EchoEffect () {
const EchoEffect = function () {
Tone.Effect.call(this);

@@ -20,3 +20,3 @@

this.effectSend.chain(this.delay, this.effectReturn);
}
};

@@ -35,3 +35,3 @@ Tone.extend(EchoEffect, Tone.Effect);

// mute the effect if value is 0
if (this.value == 0) {
if (this.value === 0) {
this.wet.value = 0;

@@ -42,4 +42,4 @@ } else {

var feedback = (this.value / 100) * 0.75;
this.delay.feedback.rampTo(feedback, 1/60);
const feedback = (this.value / 100) * 0.75;
this.delay.feedback.rampTo(feedback, 1 / 60);
};

@@ -60,2 +60,3 @@

* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/

@@ -67,2 +68,1 @@ EchoEffect.prototype.clamp = function (input, min, max) {

module.exports = EchoEffect;

@@ -1,2 +0,2 @@

var Tone = require('tone');
const Tone = require('tone');

@@ -10,3 +10,3 @@ /**

*/
function FuzzEffect () {
const FuzzEffect = function () {
Tone.Effect.call(this);

@@ -19,3 +19,3 @@

this.effectSend.chain(this.distortion, this.effectReturn);
}
};

@@ -48,2 +48,3 @@ Tone.extend(FuzzEffect, Tone.Effect);

* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/

@@ -55,2 +56,1 @@ FuzzEffect.prototype.clamp = function (input, min, max) {

module.exports = FuzzEffect;

@@ -1,2 +0,2 @@

var Tone = require('tone');
const Tone = require('tone');

@@ -10,3 +10,3 @@ /**

*/
function PanEffect () {
const PanEffect = function () {
Tone.Effect.call(this);

@@ -19,3 +19,3 @@

this.effectSend.chain(this.panner, this.effectReturn);
}
};

@@ -49,2 +49,3 @@ Tone.extend(PanEffect, Tone.Effect);

* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/

@@ -56,2 +57,1 @@ PanEffect.prototype.clamp = function (input, min, max) {

module.exports = PanEffect;

@@ -1,2 +0,2 @@

var Tone = require('tone');
const Tone = require('tone');

@@ -21,3 +21,3 @@ /**

*/
function PitchEffect () {
const PitchEffect = function () {
this.value = 0; // effect value

@@ -27,3 +27,3 @@ this.ratio = 1; // the playback rate ratio

this.tone = new Tone();
}
};

@@ -44,3 +44,3 @@ /**

* @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
*/

@@ -64,3 +64,3 @@ PitchEffect.prototype.changeBy = function (val, players) {

* 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
*/

@@ -78,3 +78,3 @@ PitchEffect.prototype.updatePlayer = function (player) {

for (var md5 in players) {
for (const md5 in players) {
if (players.hasOwnProperty(md5)) {

@@ -87,2 +87,1 @@ this.updatePlayer(players[md5]);

module.exports = PitchEffect;

@@ -1,2 +0,2 @@

var Tone = require('tone');
const Tone = require('tone');

@@ -10,3 +10,3 @@ /**

*/
function ReverbEffect () {
const ReverbEffect = function () {
Tone.Effect.call(this);

@@ -19,3 +19,3 @@

this.effectSend.chain(this.reverb, this.effectReturn);
}
};

@@ -49,2 +49,3 @@ Tone.extend(ReverbEffect, Tone.Effect);

* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/

@@ -56,2 +57,1 @@ ReverbEffect.prototype.clamp = function (input, min, max) {

module.exports = ReverbEffect;

@@ -0,4 +1,3 @@

const Tone = require('tone');
var Tone = require('tone');
/**

@@ -15,3 +14,3 @@ * A "robotic" effect that adds a low-pitched buzzing to the sound, reminiscent of the

*/
function RoboticEffect () {
const RoboticEffect = function () {
Tone.Effect.call(this);

@@ -21,7 +20,7 @@

var time = this._delayTimeForValue(100);
const time = this._delayTimeForValue(100);
this.feedbackCombFilter = new Tone.FeedbackCombFilter(time, 0.9);
this.effectSend.chain(this.feedbackCombFilter, this.effectReturn);
}
};

@@ -38,3 +37,3 @@ Tone.extend(RoboticEffect, Tone.Effect);

// mute the effect if value is 0
if (this.value == 0) {
if (this.value === 0) {
this.wet.value = 0;

@@ -46,4 +45,4 @@ } else {

// set delay time using the value
var time = this._delayTimeForValue(this.value);
this.feedbackCombFilter.delayTime.rampTo(time, 1/60);
const time = this._delayTimeForValue(this.value);
this.feedbackCombFilter.delayTime.rampTo(time, 1 / 60);
};

@@ -67,4 +66,4 @@

RoboticEffect.prototype._delayTimeForValue = function (val) {
var midiNote = ((val - 100) / 10) + 36;
var freq = Tone.Frequency(midiNote, 'midi').eval();
const midiNote = ((val - 100) / 10) + 36;
const freq = Tone.Frequency(midiNote, 'midi').eval();
return 1 / freq;

@@ -74,2 +73,1 @@ };

module.exports = RoboticEffect;

@@ -1,2 +0,2 @@

var Tone = require('tone');
const Tone = require('tone');

@@ -14,3 +14,3 @@ /**

*/
function WobbleEffect () {
const WobbleEffect = function () {
Tone.Effect.call(this);

@@ -25,3 +25,3 @@

this.effectSend.chain(this.wobbleGain, this.effectReturn);
}
};

@@ -41,3 +41,3 @@ Tone.extend(WobbleEffect, Tone.Effect);

this.wobbleLFO.frequency.rampTo(this.value / 10, 1/60);
this.wobbleLFO.frequency.rampTo(this.value / 10, 1 / 60);
};

@@ -58,2 +58,3 @@

* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/

@@ -65,2 +66,1 @@ WobbleEffect.prototype.clamp = function (input, min, max) {

module.exports = WobbleEffect;

@@ -1,16 +0,16 @@

var log = require('./log');
var Tone = require('tone');
const log = require('./log');
const Tone = require('tone');
var PitchEffect = require('./effects/PitchEffect');
var PanEffect = require('./effects/PanEffect');
const PitchEffect = require('./effects/PitchEffect');
const PanEffect = require('./effects/PanEffect');
var RoboticEffect = require('./effects/RoboticEffect');
var FuzzEffect = require('./effects/FuzzEffect');
var EchoEffect = require('./effects/EchoEffect');
var ReverbEffect = require('./effects/ReverbEffect');
const RoboticEffect = require('./effects/RoboticEffect');
const FuzzEffect = require('./effects/FuzzEffect');
const EchoEffect = require('./effects/EchoEffect');
const ReverbEffect = require('./effects/ReverbEffect');
var SoundPlayer = require('./SoundPlayer');
var ADPCMSoundDecoder = require('./ADPCMSoundDecoder');
var InstrumentPlayer = require('./InstrumentPlayer');
var DrumPlayer = require('./DrumPlayer');
const SoundPlayer = require('./SoundPlayer');
const ADPCMSoundDecoder = require('./ADPCMSoundDecoder');
const InstrumentPlayer = require('./InstrumentPlayer');
const DrumPlayer = require('./DrumPlayer');

@@ -23,2 +23,147 @@ /**

/**
* 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} audioEngine AudioEngine for player
* @constructor
*/
const AudioPlayer = function (audioEngine) {
this.audioEngine = audioEngine;
// effects setup
this.pitchEffect = new PitchEffect();
this.panEffect = new PanEffect();
// the effects are chained to an effects node for this player, then to the main audio engine
// audio is sent from each soundplayer, through the effects in order, then to the global effects
// note that the pitch effect works differently - it sets the playback rate for each soundplayer
this.effectsNode = new Tone.Gain();
this.effectsNode.chain(this.panEffect, this.audioEngine.input);
// reset effects to their default parameters
this.clearEffects();
// sound players that are currently playing, indexed by the sound's md5
this.activeSoundPlayers = {};
};
/**
* Play a sound
* @param {string} md5 - the md5 id of a sound file
* @return {Promise} a Promise that resolves when the sound finishes playing
*/
AudioPlayer.prototype.playSound = function (md5) {
// if this sound is not in the audio engine, return
if (!this.audioEngine.audioBuffers[md5]) {
return;
}
// if this sprite or clone is already playing this sound, stop it first
if (this.activeSoundPlayers[md5]) {
this.activeSoundPlayers[md5].stop();
}
// create a new soundplayer to play the sound
const player = new SoundPlayer();
player.setBuffer(this.audioEngine.audioBuffers[md5]);
player.connect(this.effectsNode);
this.pitchEffect.updatePlayer(player);
player.start();
// add it to the list of active sound players
this.activeSoundPlayers[md5] = player;
// remove sounds that are not playing from the active sound players array
for (const id in this.activeSoundPlayers) {
if (this.activeSoundPlayers.hasOwnProperty(id)) {
if (!this.activeSoundPlayers[id].isPlaying) {
delete this.activeSoundPlayers[id];
}
}
}
return player.finished();
};
/**
* Play a drum sound. The AudioEngine contains the DrumPlayer, but the AudioPlayer
* calls this function so that it can pass a reference to its own effects node.
* @param {number} drum - a drum number (0-indexed)
* @param {number} beats - a duration in beats
* @return {Promise} a Promise that resolves after the duration has elapsed
*/
AudioPlayer.prototype.playDrumForBeats = function (drum, beats) {
this.audioEngine.drumPlayer.play(drum, this.effectsNode);
return this.audioEngine.waitForBeats(beats);
};
/**
* Stop all sounds, notes and drums that are playing
*/
AudioPlayer.prototype.stopAllSounds = function () {
// stop all active sound players
for (const md5 in this.activeSoundPlayers) {
this.activeSoundPlayers[md5].stop();
}
// stop all instruments
this.audioEngine.instrumentPlayer.stopAll();
// stop drum notes
this.audioEngine.drumPlayer.stopAll();
};
/**
* Set an audio effect to a value
* @param {string} effect - the name of the effect
* @param {number} value - the value to set the effect to
*/
AudioPlayer.prototype.setEffect = function (effect, value) {
switch (effect) {
case this.audioEngine.EFFECT_NAMES.pitch:
this.pitchEffect.set(value, this.activeSoundPlayers);
break;
case this.audioEngine.EFFECT_NAMES.pan:
this.panEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.echo:
this.audioEngine.echoEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.reverb:
this.audioEngine.reverbEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.fuzz:
this.audioEngine.fuzzEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.robot:
this.audioEngine.roboticEffect.set(value);
break;
}
};
/**
* Clear all audio effects
*/
AudioPlayer.prototype.clearEffects = function () {
this.panEffect.set(0);
this.pitchEffect.set(0, this.activeSoundPlayers);
this.effectsNode.gain.value = 1;
this.audioEngine.echoEffect.set(0);
this.audioEngine.reverbEffect.set(0);
this.audioEngine.fuzzEffect.set(0);
this.audioEngine.roboticEffect.set(0);
};
/**
* Set the volume for sounds played by this AudioPlayer
* @param {number} value - the volume in range 0-100
*/
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,

@@ -29,3 +174,3 @@ * loads all the audio buffers for sounds belonging to sprites, and creates a single instrument player

*/
function AudioEngine () {
const AudioEngine = function () {

@@ -40,3 +185,3 @@ // create the global audio effects

this.input = new Tone.Gain();
this.input.chain (
this.input.chain(
this.roboticEffect, this.fuzzEffect, this.echoEffect, this.reverbEffect,

@@ -63,3 +208,3 @@ Tone.Master

this.micMeter = null;
}
};

@@ -69,3 +214,3 @@ /**

* 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
* @param {object} sound - an object containing audio data and metadata for a sound
* @property {Buffer} data - sound data loaded from scratch-storage.

@@ -78,3 +223,3 @@ * @property {string} format - format type, either empty or adpcm.

var loaderPromise = null;
let loaderPromise = null;

@@ -92,8 +237,8 @@ switch (sound.format) {

var storedContext = this;
const storedContext = this;
return loaderPromise.then(
function (decodedAudio) {
decodedAudio => {
storedContext.audioBuffers[sound.md5] = new Tone.Buffer(decodedAudio);
},
function (error) {
error => {
log.warn('audio data could not be decoded', error);

@@ -122,3 +267,3 @@ }

AudioEngine.prototype.playNoteForBeatsWithInstAndVol = function (note, beats, inst, vol) {
var sec = this.beatsToSec(beats);
const sec = this.beatsToSec(beats);
this.instrumentPlayer.playNoteForSecWithInstAndVol(note, sec, inst, vol);

@@ -130,4 +275,4 @@ return this.waitForBeats(beats);

* Convert a number of beats to a number of seconds, using the current tempo
* @param {number} beats
* @return {number} seconds
* @param {number} beats number of beats to convert to secs
* @return {number} seconds number of seconds `beats` will last
*/

@@ -140,9 +285,9 @@ AudioEngine.prototype.beatsToSec = function (beats) {

* Wait for some number of beats
* @param {number} 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) {
var storedContext = this;
return new Promise(function (resolve) {
setTimeout(function () {
const storedContext = this;
return new Promise(resolve => {
setTimeout(() => {
resolve();

@@ -166,3 +311,3 @@ }, storedContext.beatsToSec(beats) * 1000);

AudioEngine.prototype.changeTempo = function (value) {
this.setTempo(this.currentTempo + value);
this.setTempo(this.currentTempo + value);
};

@@ -182,7 +327,7 @@

}
if (this.mic && this.mic.state == 'started') {
if (this.mic && this.mic.state === 'started') {
return this.micMeter.value * 100;
} else {
return -1;
}
return -1;
};

@@ -208,3 +353,3 @@

* functionality such as playing notes.
* @return {AudioPlayer}
* @return {AudioPlayer} new AudioPlayer instance
*/

@@ -215,147 +360,2 @@ AudioEngine.prototype.createPlayer = function () {

/**
* 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}
* @constructor
*/
function AudioPlayer (audioEngine) {
this.audioEngine = audioEngine;
// effects setup
this.pitchEffect = new PitchEffect();
this.panEffect = new PanEffect();
// the effects are chained to an effects node for this player, then to the main audio engine
// audio is sent from each soundplayer, through the effects in order, then to the global effects
// note that the pitch effect works differently - it sets the playback rate for each soundplayer
this.effectsNode = new Tone.Gain();
this.effectsNode.chain(this.panEffect, this.audioEngine.input);
// reset effects to their default parameters
this.clearEffects();
// sound players that are currently playing, indexed by the sound's md5
this.activeSoundPlayers = {};
}
/**
* Play a sound
* @param {string} md5 - the md5 id of a sound file
* @return {Promise} a Promise that resolves when the sound finishes playing
*/
AudioPlayer.prototype.playSound = function (md5) {
// if this sound is not in the audio engine, return
if (!this.audioEngine.audioBuffers[md5]) {
return;
}
// if this sprite or clone is already playing this sound, stop it first
if (this.activeSoundPlayers[md5]) {
this.activeSoundPlayers[md5].stop();
}
// create a new soundplayer to play the sound
var player = new SoundPlayer();
player.setBuffer(this.audioEngine.audioBuffers[md5]);
player.connect(this.effectsNode);
this.pitchEffect.updatePlayer(player);
player.start();
// add it to the list of active sound players
this.activeSoundPlayers[md5] = player;
// remove sounds that are not playing from the active sound players array
for (var id in this.activeSoundPlayers) {
if (this.activeSoundPlayers.hasOwnProperty(id)) {
if (!this.activeSoundPlayers[id].isPlaying) {
delete this.activeSoundPlayers[id];
}
}
}
return player.finished();
};
/**
* Play a drum sound. The AudioEngine contains the DrumPlayer, but the AudioPlayer
* calls this function so that it can pass a reference to its own effects node.
* @param {number} drum - a drum number (0-indexed)
* @param {number} beats - a duration in beats
* @return {Promise} a Promise that resolves after the duration has elapsed
*/
AudioPlayer.prototype.playDrumForBeats = function (drum, beats) {
this.audioEngine.drumPlayer.play(drum, this.effectsNode);
return this.audioEngine.waitForBeats(beats);
};
/**
* Stop all sounds, notes and drums that are playing
*/
AudioPlayer.prototype.stopAllSounds = function () {
// stop all active sound players
for (var md5 in this.activeSoundPlayers) {
this.activeSoundPlayers[md5].stop();
}
// stop all instruments
this.audioEngine.instrumentPlayer.stopAll();
// stop drum notes
this.audioEngine.drumPlayer.stopAll();
};
/**
* Set an audio effect to a value
* @param {string} effect - the name of the effect
* @param {number} value - the value to set the effect to
*/
AudioPlayer.prototype.setEffect = function (effect, value) {
switch (effect) {
case this.audioEngine.EFFECT_NAMES.pitch:
this.pitchEffect.set(value, this.activeSoundPlayers);
break;
case this.audioEngine.EFFECT_NAMES.pan:
this.panEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.echo:
this.audioEngine.echoEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.reverb:
this.audioEngine.reverbEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.fuzz:
this.audioEngine.fuzzEffect.set(value);
break;
case this.audioEngine.EFFECT_NAMES.robot:
this.audioEngine.roboticEffect.set(value);
break;
}
};
/**
* Clear all audio effects
*/
AudioPlayer.prototype.clearEffects = function () {
this.panEffect.set(0);
this.pitchEffect.set(0, this.activeSoundPlayers);
this.effectsNode.gain.value = 1;
this.audioEngine.echoEffect.set(0);
this.audioEngine.reverbEffect.set(0);
this.audioEngine.fuzzEffect.set(0);
this.audioEngine.roboticEffect.set(0);
};
/**
* Set the volume for sounds played by this AudioPlayer
* @param {number} value - the volume in range 0-100
*/
AudioPlayer.prototype.setVolume = function (value) {
this.effectsNode.gain.value = value / 100;
};
module.exports = AudioEngine;

@@ -1,3 +0,3 @@

var Tone = require('tone');
var Soundfont = require('soundfont-player');
const Tone = require('tone');
const Soundfont = require('soundfont-player');

@@ -15,3 +15,3 @@ /**

*/
function InstrumentPlayer (outputNode) {
const InstrumentPlayer = function (outputNode) {
this.outputNode = outputNode;

@@ -28,3 +28,3 @@

this.instruments = [];
}
};

@@ -42,3 +42,3 @@ /**

InstrumentPlayer.prototype.playNoteForSecWithInstAndVol = function (note, sec, instrumentNum, vol) {
var gain = vol / 100;
const gain = vol / 100;
this.loadInstrument(instrumentNum)

@@ -48,4 +48,4 @@ .then(() => {

note, Tone.context.currentTime, {
duration : sec,
gain : gain
duration: sec,
gain: gain
}

@@ -64,9 +64,9 @@ );

return Promise.resolve();
} else {
return Soundfont.instrument(Tone.context, this.instrumentNames[instrumentNum])
.then((inst) => {
}
return Soundfont.instrument(Tone.context, this.instrumentNames[instrumentNum])
.then(inst => {
inst.connect(this.outputNode);
this.instruments[instrumentNum] = inst;
});
}
};

@@ -78,3 +78,3 @@

InstrumentPlayer.prototype.stopAll = function () {
for (var i=0; i<this.instruments.length; i++) {
for (let i = 0; i < this.instruments.length; i++) {
if (this.instruments[i]) {

@@ -81,0 +81,0 @@ this.instruments[i].stop();

@@ -1,4 +0,4 @@

var minilog = require('minilog');
const minilog = require('minilog');
minilog.enable();
module.exports = minilog('scratch-audioengine');

@@ -1,3 +0,3 @@

var Tone = require('tone');
var log = require('./log');
const Tone = require('tone');
const log = require('./log');

@@ -8,3 +8,3 @@ /**

*/
function SoundPlayer () {
const SoundPlayer = function () {
this.outputNode = null;

@@ -15,3 +15,3 @@ this.buffer = new Tone.Buffer();

this.isPlaying = false;
}
};

@@ -28,3 +28,3 @@ /**

* Set an audio buffer
* @param {Tone.Buffer} buffer
* @param {Tone.Buffer} buffer Buffer to set
*/

@@ -80,4 +80,4 @@ SoundPlayer.prototype.setBuffer = function (buffer) {

SoundPlayer.prototype.finished = function () {
var storedContext = this;
return new Promise(function (resolve) {
const storedContext = this;
return new Promise(resolve => {
storedContext.bufferSource.onended = function () {

@@ -84,0 +84,0 @@ this.isPlaying = false;

@@ -5,3 +5,3 @@ var path = require('path');

entry: {
'dist': './src/index.js'
dist: './src/index.js'
},

@@ -8,0 +8,0 @@ output: {

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc