🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

codebeat

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

codebeat - npm Package Compare versions

Comparing version

to
1.1.0

index.html

2

package.json
{
"name": "codebeat",
"version": "1.0.10",
"version": "1.1.0",
"description": "A browser-based audio programming language for music composition and audio synthesis.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -114,1 +114,35 @@

This ensures that the entire duration of the slide is dictated by the duration of the source note.
## Advanced features
### Effects
Dynamics like gain, reverb, detuning, instrument, and distortion can be easily altered in a composition using the '@' tag.
~~~
@reverb 2/1.1/0.7,
@gain 75,
@instrument square,
h g3, w a5,
@instrument sine,
h g3, w a4
~~~
In the above example, the instrument is set to square and later changed to sine. Reverb and gain are set for the entire piece.
#### Reverb
@reverb accepts 3 optional parameters delimited with '/': channel #, reverb length as a function of the sample rate, and decay rate.
#### Gain
@gain accepts 1 parameter: the amount of gain from 0 (mute) to 100 (maximum volume).
#### Detune
@detune accepts 1 parameter: the value in cents to detune a frequency.
#### Instrument
@instrument accepts 1 parameter: the instrument name.
const Frequency = require('./frequency');
const Duration = require('./duration');
const Note = require('./note');
const FX = require('./fx');

@@ -17,3 +18,10 @@ class Codebeat {

this.loop = props.loop || false;
this.context = new (props.context || global.AudioContext || global.webkitAudioContext)();
this.convolverNode = this.context.createConvolver();
this.convolverNode.buffer = FX.createReverbBuffer(this, '1/1/20');
this.gainNode = this.context.createGain();
this.convolverNode.connect(this.gainNode);
this.gainNode.connect(this.context.destination);
this.parseNotes();

@@ -59,2 +67,7 @@ this.getBPM();

this.context = new (nodeContext || global.AudioContext || global.webkitAudioContext)();
this.convolverNode = this.context.createConvolver();
this.convolverNode.buffer = FX.createReverbBuffer(this, '1/1/20');
this.gainNode = this.context.createGain();
this.convolverNode.connect(this.gainNode);
this.gainNode.connect(this.context.destination);
}

@@ -66,8 +79,20 @@

parseNotes(notes = this.notes) {
// prepare variable names for notes delimiter=;
notes = Codebeat._expandMotifs(notes);
// prepare note multiples delimiter=*
notes = Codebeat._expandMultiples(notes);
// prepare note slides delimiter=-
notes = Codebeat._expandSlides(notes);
// prepare chords delimiter=+
notes = Codebeat._expandPoly(notes);
// translate data to Note object delimiter=,
notes = Codebeat._expandNotes(notes);
// update or reset notesParsed
this.notesParsed = notes;
return this.notesParsed

@@ -85,14 +110,31 @@ }

const oscillators = [];
const playNext = () => {
n < this.notesParsed.length - 1
? this.play(n += 1)
: this.ended();
}
if (note.fx[0]) {
if (note.fx[0].indexOf('@') === 0) {
FX[note.fx[0].slice(1)](this, note.value);
return playNext();
}
}
// create and configure oscillators
note.outputFrequency.forEach(f => {
let o = this.context.createOscillator();
o.connect(this.context.destination);
o.connect(this.convolverNode)
// set instrument
o.type = this.instrument;
// set detune
o.detune.setValueAtTime(this.detune || 0, this.context.currentTime);
// set note frequency
o.frequency.value = f;
oscillators.push(o)
})
oscillators.push(o);
});
oscillators.forEach(o => {
o.start(0);
if (nextNote && note.fx.slide) this.slideNote(o, n)
if (nextNote && note.fx.includes('slide')) this.slideNote(o, n)
o.stop(this.context.currentTime + stopTime);

@@ -102,5 +144,3 @@ })

oscillators.shift().onended = () => {
n < this.notesParsed.length - 1
? this.play(n += 1)
: this.ended();
playNext()
};

@@ -158,3 +198,3 @@ }

//TODO: Brief chords as well
const singleNotes = this.notesParsed.filter(n => !n.fx.poly)
const singleNotes = this.notesParsed.filter(n => !n.fx.includes('poly'))
const origin = this.notesParsed.map(f => Codebeat._originFrequency(f.outputFrequency[0]));

@@ -254,7 +294,7 @@ const notes = origin.filter((note, i) => i === origin.indexOf(note));

static _expandMotifs(notes, delimiter = ';') {
static _expandMotifs(notes) {
const motifs = {};
if (notes.includes(delimiter)) {
notes = notes.split(delimiter);
if (notes.includes(';')) {
notes = notes.split(';');
const motifOccursAt = [];

@@ -283,3 +323,3 @@ const operator = '=';

static _expandMultiples(notes, delimiter = '*') {
static _expandMultiples(notes) {
const multiply = {

@@ -291,3 +331,3 @@ occursAt: [],

notes.forEach((n, i) => {
if (n.includes(delimiter)) {
if (n.includes('*')) {
multiply.occursAt.push(i);

@@ -309,3 +349,3 @@ }

static _expandSlides(notes, delimiter = '-') {
static _expandSlides(notes) {
const slide = {

@@ -317,3 +357,3 @@ occursAt: [],

notes.forEach((n, i) => {
if (n.includes(delimiter)) {
if (n.includes('-')) {
slide.occursAt.push(i);

@@ -333,7 +373,7 @@ }

static _expandPoly(notes, delimiter = '+') {
static _expandPoly(notes) {
notes = notes.map((n, i) => {
if (n.includes(delimiter)) {
if (n.includes('+')) {
const duration = n.shift()
const pitch = n.filter(p => p != delimiter)
const pitch = n.filter(p => p != '+')
.reduce((a,b) => a.concat(' ').concat(b))

@@ -363,3 +403,3 @@

const nextNote = this.notesParsed[n + 1];
if (!nextNote.fx.slide) return
if (!nextNote.fx.includes('slide')) return

@@ -366,0 +406,0 @@ const note = this.notesParsed[n];

@@ -8,6 +8,10 @@ const Codebeat = require('./Codebeat');

@reverb 4/1.5/1.5,
@instrument sine,
t g3 * 3,
first, second,
h c5, q g4,
second, third,
@reverb 1/1/20,
second,
third,
h d4`;

@@ -14,0 +18,0 @@

@@ -5,25 +5,70 @@ const Frequency = require('./frequency');

module.exports = (note) => {
const inputDuration = note[0];
const inputFrequency = note[1];
const fx = note[2] || [];
const slide = fx.includes('slide');
const poly = fx.includes('poly');
const firstParam = note[0];
const secondParam = note[1];
const fx = note[2] || [];
if (firstParam[0] === '@') fx.push(firstParam)
const noteSchema = {
inputDuration,
inputFrequency,
outputDuration: Duration[inputDuration],
outputFrequency: (() => {
return poly
? inputFrequency.split(' ').map(f => Frequency[f])
: [Frequency[inputFrequency]]
})(),
fx: {
all: fx,
slide,
poly
}
}
let noteSchema = {};
switch(fx[0]) {
case 'slide':
noteSchema = {
fx,
firstParam,
secondParam,
outputDuration: Duration[firstParam],
outputFrequency: [Frequency[secondParam]],
};
break;
case 'poly':
noteSchema = {
fx,
firstParam,
secondParam,
outputDuration: Duration[firstParam],
outputFrequency: secondParam.split(' ').map(f => Frequency[f]),
};
break;
case '@gain':
noteSchema = {
fx,
value: secondParam,
};
break;
case '@instrument':
noteSchema = {
fx,
value: secondParam,
};
break;
case '@detune':
noteSchema = {
fx,
value: secondParam,
};
break;
case '@reverb':
noteSchema = {
fx,
value: secondParam,
};
break;
default:
noteSchema = {
fx,
firstParam,
secondParam,
outputDuration: Duration[firstParam],
outputFrequency: [Frequency[secondParam]],
};
break;
}
return noteSchema
}