-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathapp.js
156 lines (131 loc) · 4.29 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
const Tonal = require("tonal");
const SerialPort = require('serialport')
const Speaker = require('audio-speaker/stream');
const Generator = require('audio-generator/stream');
const FIRST_BUTTON_PRESSED_MASK = 0b00000001;
const SECOND_BUTTON_PRESSED_MASK = 0b00000010
const THIRD_BUTTON_PRESSED_MASK = 0b00000100
const FOURTH_BUTTON_PRESSED_MASK = 0b00001000
const FIFTH_BUTTON_PRESSED_MASK = 0b00010000
const SIXTH_BUTTON_PRESSED_MASK = 0b00100000
const SEVENTH_BUTTON_PRESSED_MASK = 0b01000000
const EIGHTH_BUTTON_PRESSED_MASK = 0b10000000
const ARDUINO_CONTROLLER_BAUD = 9600;
const { fork } = require('child_process');
const forked = fork('run_genie.js');
const buttonMap = new Map();
const pressedMap = new Map();
let LOWEST_NOTE = 24;
let NUM_CHANNELS = 3;
let NUM_BUTTONS = 8;
let genieReady = false;
let currentNotes = [];
let processing = false;
SerialPort.list((err, devices) => {
console.log(devices)
})
const arduino = new SerialPort('/dev/tty.usbmodem3364981', {
baudRate: ARDUINO_CONTROLLER_BAUD
})
// Setup the arduino port to listen for key presses
let Readline = SerialPort.parsers.Readline
let parser = new Readline()
arduino.pipe(parser);
forked.on('message', (msg) => {
if (msg.genieReady == true) {
genieReady = true;
arduino.write("S\n");
} else {
noteOn(msg.note + LOWEST_NOTE, msg.button)
}
processing = false;
});
let channelMap = new Map();
for (let i = 0; i < NUM_CHANNELS; i++) {
channelMap.set(i, new Map())
for (let j = 0; j < NUM_BUTTONS; j++) {
channelMap.get(i).set(j, []);
}
}
function dec2bin(dec){
return (dec >>> 0).toString(2);
}
let context = this;
parser.on('data', (data) => {
let dataByte = parseInt(data.split('b')[1]);
let firstButton = !(FIRST_BUTTON_PRESSED_MASK & dataByte);
let secondButton = !(SECOND_BUTTON_PRESSED_MASK & dataByte);
let thirdButton = !(THIRD_BUTTON_PRESSED_MASK & dataByte);
let fourthButton = !(FOURTH_BUTTON_PRESSED_MASK & dataByte);
let fifthButton = !(FIFTH_BUTTON_PRESSED_MASK & dataByte);
let sixthButton = !(SIXTH_BUTTON_PRESSED_MASK & dataByte);
let seventhButton = !(SEVENTH_BUTTON_PRESSED_MASK & dataByte);
let eighthButton = !(EIGHTH_BUTTON_PRESSED_MASK & dataByte);
handleButtonValue(0, firstButton);
handleButtonValue(1, secondButton);
handleButtonValue(2, thirdButton);
handleButtonValue(3, fourthButton);
handleButtonValue(4, fifthButton);
handleButtonValue(5, sixthButton);
handleButtonValue(6, seventhButton);
handleButtonValue(7, eighthButton);
})
handleButtonValue = function(button, value) {
if (!genieReady) {
// Wait for Tensorflow to load Piano Genie network
return;
}
if (pressedMap.has(button)) {
if (pressedMap.get(button) != value) {
if (!value) {
if (!processing) {
processing = true;
forked.send({note: button})
}
} else {
noteOff(button)
}
}
} else {
if (!value) {
forked.send({note: button})
} else {
noteOff(button)
}
}
pressedMap.set(button, value);
}
noteOn = function(note, button) {
// Add to current list of output notes
currentNotes.push(note);
buttonMap.set(button, note)
}
noteOff = function(button) {
if (buttonMap.has(button)) {
let note = buttonMap.get(button)
currentNotes.splice(currentNotes.indexOf(note), 1);
buttonMap.delete(button);
}
}
startAudioOutput = function() {
let stream = Generator(function (time) {
var τ = Math.PI * 2;
let notesToPlay = []
for (let buttonMapKey of buttonMap.keys()) {
let frequency = Tonal.Note.freq(Tonal.Note.fromMidi(buttonMap.get(buttonMapKey)))
notesToPlay.push(Math.sin(τ * time * frequency))
}
return notesToPlay;
})
stream.pipe(Speaker());
}
startAudioOutput();
process.on('exit', function(code) {
keyboard.close();
forked.kill();
// Turn off any stray notes
for (let i = 0 ; i < NUM_BUTTONS; i++) {
noteOff(i)
}
return console.log(`About to exit with code ${code}`);
});