Skip to content

Commit d55484e

Browse files
authored
Merge pull request #25 from billorcutt/midi-writer
v0.2.20
2 parents 78a2324 + 9c021ba commit d55484e

File tree

5 files changed

+157
-49
lines changed

5 files changed

+157
-49
lines changed

app/index.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
var fs = require('fs');
55
var path = path || require('path');
66
var electron = require('electron');
7+
const MidiWriter = require('midi-writer-js');
78
var flipShutdownFlag = electron.remote.getGlobal("flipShutdownFlag");
89
var app = electron.remote.app;
910
var dialog = electron.remote.dialog;
1011
var crackedFile = null;
1112
var fontSize = 14;
1213
const currentWindow = electron.remote.getCurrentWindow();
14+
var trackArr = []
1315

1416
//shared object
1517
var _shared_object = electron.remote.getGlobal("shared_object");
@@ -129,6 +131,50 @@ function insertCSS() {
129131
return result;
130132
}
131133

134+
//takes an array of notes and writes a midi file
135+
function writeMidiFile(midiArr,noteLen,isChord) {
136+
// Start with a new track
137+
const track = new MidiWriter.Track();
138+
139+
if(typeof midiArr[0] === 'string') {
140+
midiArr.forEach(arr=>{
141+
track.addLyric(arr);
142+
})
143+
} else if(!isChord) {
144+
track.addEvent([
145+
new MidiWriter.NoteEvent({pitch: midiArr, duration: noteLen})
146+
], function(event, index) {
147+
return {sequential: true};
148+
});
149+
} else {
150+
midiArr.forEach(arr=>{
151+
track.addEvent([
152+
new MidiWriter.NoteEvent({pitch: arr, duration: noteLen})
153+
]);
154+
})
155+
}
156+
trackArr.push(track);
157+
}
158+
159+
function saveMidiFile() {
160+
if(trackArr.length) {
161+
// Generate a data URI
162+
const write = new MidiWriter.Writer(trackArr);
163+
164+
fs.writeFile("/Users/billorcutt/Desktop/midiFile" + Math.floor(Math.random()*1000) + ".mid", Buffer.from(write.buildFile()), 'utf8',function(err){
165+
if(!err) {
166+
console.log("saved file");
167+
} else {
168+
console.error(err)
169+
}
170+
});
171+
172+
trackArr = [];
173+
} else {
174+
console.error("No midi files to save");
175+
}
176+
}
177+
132178
//read a directory and return an array of its contents.
133179
function readDirectory(pathToDirectory,filelist) {
134180
filelist = filelist || [];

lib/cracked/cracked.js

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3095,7 +3095,7 @@ cracked.array_next = function(arr,offset,limit,callback) {
30953095
* @returns {boolean}
30963096
*/
30973097
cracked.chance = function(percentage) {
3098-
return percentage > __.random(0,100);
3098+
return percentage > __.random(0,99);
30993099
};
31003100

31013101
/**
@@ -3212,6 +3212,33 @@ cracked.shuffle = function (arr) {
32123212
return arr;
32133213
};
32143214

3215+
/**
3216+
* Returns a function that generates a unique random number between 0 & max.
3217+
* If max is exceeded, then repeat the sequence of random numbers.
3218+
* @plugin
3219+
* @category Algorithmic
3220+
* @function
3221+
* @memberof cracked
3222+
* @name cracked#urnFactory
3223+
* @public
3224+
* @param {Number} max
3225+
*/
3226+
cracked.urnFactory = function (max) {
3227+
3228+
var arr = [];
3229+
while(arr.length < max){
3230+
var r = Math.floor(Math.random() * max);
3231+
if(arr.indexOf(r) === -1) {
3232+
arr.push(r);
3233+
}
3234+
}
3235+
3236+
return function() {
3237+
return cracked.array_next(arr);
3238+
};
3239+
3240+
};
3241+
32153242
/**
32163243
* Returns a random number between min & max
32173244
* @plugin
@@ -3224,7 +3251,7 @@ cracked.shuffle = function (arr) {
32243251
* @param {Number} max
32253252
*/
32263253
cracked.random = function (min, max) {
3227-
return Math.round(min + Math.random() * (max - min));
3254+
return Math.round(min + Math.random() * (max - min) );
32283255
};
32293256

32303257
/**
@@ -3246,43 +3273,6 @@ cracked.throttle_factory = function (num) {
32463273
};
32473274
};
32483275

3249-
/**
3250-
* Factory to create a sequencing function that returns true when called every nth times
3251-
* @plugin
3252-
* @category Algorithmic
3253-
* @function
3254-
* @memberof cracked
3255-
* @name cracked#sequence_factory
3256-
* @public
3257-
* @param {Array} arr
3258-
* @param {Function} fn
3259-
*/
3260-
cracked.sequence_factory = function (arr,fn) {
3261-
var count = 0;
3262-
var current_index = 0;
3263-
var arr_copy = arr.slice();
3264-
var current_value = arr_copy[current_index];
3265-
var transition = true;
3266-
var first_run = true;
3267-
return function() {
3268-
if(count===current_value) {
3269-
if(current_index===arr_copy.length-1) {
3270-
current_index = 0;
3271-
} else {
3272-
current_index++;
3273-
}
3274-
count = 1;
3275-
transition=true;
3276-
current_value = arr_copy[current_index];
3277-
} else {
3278-
count++;
3279-
transition=first_run||false;
3280-
}
3281-
fn(transition,current_index);
3282-
first_run=false;
3283-
};
3284-
};
3285-
32863276
//Sequence
32873277

32883278
/*
@@ -3297,7 +3287,7 @@ cracked.sequence_factory = function (arr,fn) {
32973287
cracked.__sequence_storage = {};
32983288

32993289
/**
3300-
* Sequence - create a series of steps that take a function to execute and a time in minutes for when to execute it
3290+
* Sequence - create a series of steps that take a function to execute and a time in minutes (including fractions) for when to execute it
33013291
*
33023292
* [See more sampler examples](examples/sequence.html)
33033293
*
@@ -3330,7 +3320,7 @@ cracked.sequence = function(name) {
33303320
var steps = Object.keys(cracked.__sequence_storage[name].steps);
33313321
if(steps.length) {
33323322
steps.map(function(x){
3333-
if(Math.floor(time_elapsed/60000) >= x) {
3323+
if(time_elapsed >= (x * 60000)) {
33343324
cracked.__sequence_storage[name].steps[x]();
33353325
delete cracked.__sequence_storage[name].steps[x];
33363326
}
@@ -5686,4 +5676,19 @@ cracked.freq2pitch = function (freq) {
56865676
return Math.floor(69 + 12 * Math.log2(freq / 440));
56875677
};
56885678

5679+
/**
5680+
* Converts a midi number to a note value
5681+
* @plugin
5682+
* @category Utility
5683+
* @function
5684+
* @memberof cracked
5685+
* @name cracked#pitch2note
5686+
* @public
5687+
* @param {Number} freq
5688+
*/
5689+
cracked.pitch2note = function (notenum) {
5690+
var octave = parseInt((notenum / 12) - 1);
5691+
var index = notenum % 12;
5692+
return ([ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ][index] + "" + octave);
5693+
};
56895694
})();

lib/cracked/overrides.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,29 @@ cracked.ls = function(path) {
3333
}
3434
};
3535

36+
/**
37+
* writeMidiFile - takes an array of notes and a note length values, creates a midi file in memory if none exists.
38+
* If a midi file does exists, it adds the data as a track
39+
*
40+
*/
41+
cracked.writeMidiFile = function(midiArray,noteLen,isChord) {
42+
if(midiArray && noteLen && typeof window.parent.writeMidiFile === "function") {
43+
return window.parent.writeMidiFile(midiArray,noteLen,isChord);
44+
}
45+
};
46+
47+
/**
48+
* saveMidiFile - writes midi file in memory as a file to disk.
49+
*
50+
*/
51+
cracked.saveMidiFile = function() {
52+
if(typeof window.parent.saveMidiFile === "function") {
53+
return window.parent.saveMidiFile();
54+
} else {
55+
console.error("not found");
56+
}
57+
};
58+
3659
/**
3760
* expose the method to reload/re-eval the editor
3861
*/

package-lock.json

Lines changed: 39 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cracked",
33
"productName": "Cracked",
4-
"version": "0.2.19",
4+
"version": "0.2.20",
55
"main": "main.js",
66
"description": "Web audio, cracked.",
77
"keywords": [
@@ -16,6 +16,7 @@
1616
"author": "Bill Orcutt <info@fakeestates.org> (https://twitter.com/billorcutt)",
1717
"dependencies": {
1818
"electron-json-storage": "1.1.0",
19+
"midi-writer-js": "^2.1.4",
1920
"monode": "2.2.3"
2021
},
2122
"devDependencies": {
@@ -24,7 +25,7 @@
2425
"electron-installer-dmg": "^3.0.0",
2526
"electron-notarize": "1.0.0",
2627
"electron-builder": "23.6.0",
27-
"dotenv": "8.2.0"
28+
"dotenv": "8.2.0"
2829
},
2930
"scripts": {
3031
"start": "./node_modules/electron/dist/Electron.app/Contents/MacOS/Electron main.js",

0 commit comments

Comments
 (0)