aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDevine Lu Linvega <[email protected]>2018-11-16 20:13:01 +1200
committerDevine Lu Linvega <[email protected]>2018-11-16 20:13:01 +1200
commit934c8074c1d6154bfb81ad25c64336b0c54cbc57 (patch)
tree34c0fa4f973b52f630063b586d0c6fb917bb679c
parentac96842164dd13fb90c5775de46bd318e0af23f7 (diff)
downloadOrca-934c8074c1d6154bfb81ad25c64336b0c54cbc57.tar.gz
Orca-934c8074c1d6154bfb81ad25c64336b0c54cbc57.zip
Completed midi implementation
-rw-r--r--README.md9
-rw-r--r--desktop/core/lib/_midi.js12
-rw-r--r--desktop/sources/scripts/midi.js73
-rw-r--r--desktop/sources/scripts/terminal.js2
4 files changed, 56 insertions, 40 deletions
diff --git a/README.md b/README.md
index 884a053..481cfd6 100644
--- a/README.md
+++ b/README.md
@@ -75,15 +75,6 @@ function frequencyFromNoteNumber(note) {
The idea is to build a synth/mini sequencer, here's some tasks I need to tackle before then.
-- [ ] Add `:MID[CD]`
-- [ ] custom synth functions, like `:SYN[ADSR](C)`
-- [ ] sub programs scope
-- [ ] Implement midi
-- [ ] Finish midi channel implementation
-- [ ] Convert notes to midi values
-- [ ] Implement a block comment syntax
-- [ ] Fix M
-
## Extras
- This application supports the [Ecosystem Theme](https://github.com/hundredrabbits/Themes).
diff --git a/desktop/core/lib/_midi.js b/desktop/core/lib/_midi.js
index 17f23f9..bea63c7 100644
--- a/desktop/core/lib/_midi.js
+++ b/desktop/core/lib/_midi.js
@@ -11,7 +11,6 @@ function FnMidi (pico, x, y, passive) {
this.ports = [{ x: 1, y: 0, input: true }, { x: 2, y: 0, input: true }, { x: 3, y: 0, input: true }, { x: 0, y: 0, bang: true }]
this.haste = function () {
- pico.lock(this.x, this.y - 1)
pico.lock(this.x + 1, this.y)
pico.lock(this.x + 2, this.y)
pico.lock(this.x + 3, this.y)
@@ -20,27 +19,26 @@ function FnMidi (pico, x, y, passive) {
this.run = function () {
if (!this.bang()) { return }
+ const notes = ['C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g', 'A', 'a', 'b']
+
const channelGlyph = pico.glyphAt(this.x + 1, this.y)
const octaveGlyph = pico.glyphAt(this.x + 2, this.y)
const noteGlyph = pico.glyphAt(this.x + 3, this.y)
if (channelGlyph === '.' || octaveGlyph === '.' || noteGlyph === '.') { return }
+ if (notes.indexOf(noteGlyph) < 0) { return }
const channelValue = pico.allowed.indexOf(channelGlyph)
const octaveValue = pico.allowed.indexOf(octaveGlyph)
const noteValue = pico.allowed.indexOf(noteGlyph)
const channel = clamp(channelValue, 0, 15)
- const octave = clamp(octaveValue, 3, 8)
- const note = this.convert(noteValue)
+ const octave = clamp(octaveValue, 2, 9)
+ const note = notes.indexOf(noteGlyph)
terminal.midi.send(channel, octave, note, 127)
}
- this.convert = function (ch) {
- return 64
- }
-
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
}
diff --git a/desktop/sources/scripts/midi.js b/desktop/sources/scripts/midi.js
index d846613..232e3bb 100644
--- a/desktop/sources/scripts/midi.js
+++ b/desktop/sources/scripts/midi.js
@@ -16,14 +16,60 @@ function Midi (terminal) {
this.run = function () {
if (this.stack.length < 1) { return }
- let html = ''
+ let text = ''
for (const id in this.stack) {
const note = this.stack[id]
- html += `Ch${note[0]}:${note[1]}+${note[2]}(${note[3]}) `
+ text += `${note[0]}+${note[1]}|${note[2]}.${note[3]} `
+ this.play(note)
}
- terminal.log(`${html}`)
+
+ terminal.log(text)
+ }
+
+ this.send = function (channel, octave, note, velocity) {
+ this.stack.push([channel, octave, note, velocity])
+ }
+
+ this.play = function (note) {
+ const channel = this.makeChannel(note[0])
+ const value = this.makeValue(note[1], note[2])
+ const velocity = note[3]
+
+ this.playNote(channel, value, velocity)
+ }
+
+ this.playNote = function (channel, value, velocity) {
+ // TODO: Fix length to terminal bpm
+ const length = window.performance.now() + 100.0
+
+ terminal.midi.outputs[0].send([channel[0], value, velocity])
+ terminal.midi.outputs[0].send([channel[1], value, velocity], length)
+ }
+
+ //
+
+ this.makeChannel = function (id) {
+ if (id === 0) { return [0x90, 0x80] } // ch1
+ if (id === 1) { return [0x91, 0x81] } // ch2
+ if (id === 2) { return [0x92, 0x82] } // ch3
+ if (id === 3) { return [0x93, 0x83] } // ch4
+ if (id === 4) { return [0x94, 0x84] } // ch5
+ if (id === 5) { return [0x95, 0x85] } // ch6
+ if (id === 6) { return [0x96, 0x86] } // ch7
+ if (id === 7) { return [0x97, 0x87] } // ch8
+ if (id === 8) { return [0x98, 0x88] } // ch9
+ if (id === 9) { return [0x99, 0x89] } // ch10
}
+ this.makeValue = function (octave, note) {
+ const offset = 24
+ const value = offset + (octave * 12) + note
+ console.log(octave, note, value)
+ return value // 60 = C3
+ }
+
+ // Setup
+
this.midiSetup = function () {
if (!navigator.requestMIDIAccess) { return }
@@ -42,26 +88,7 @@ function Midi (terminal) {
console.warn('No Midi', err)
}
- this.send = function (channel, octave, note, velocity) {
- this.stack.push([channel, octave, note, velocity])
- }
-
- this.play = function () {
- this.ch1()
- this.ch3()
- }
-
- this.ch1 = function () {
- terminal.midi.outputs[0].send([0x90, 60, 127])
- terminal.midi.outputs[0].send([0x80, 60, 127], window.performance.now() + 250.0)
- }
-
- this.ch3 = function () {
- terminal.midi.outputs[0].send([0x92, 60, 127])
- terminal.midi.outputs[0].send([0x82, 60, 127], window.performance.now() + 250.0)
- }
-
- this.vu = function () {
+ this.toString = function () {
if (this.stack.length === 0) { return '------' }
if (this.stack.length === 1) { return '|-----' }
if (this.stack.length === 2) { return '||----' }
diff --git a/desktop/sources/scripts/terminal.js b/desktop/sources/scripts/terminal.js
index 4bd226a..7f35616 100644
--- a/desktop/sources/scripts/terminal.js
+++ b/desktop/sources/scripts/terminal.js
@@ -160,7 +160,7 @@ function Terminal (pico) {
this.write(`${this.cursor.inspect()}`.substr(0, col), col * 0, 0)
this.write(`${this.cursor._mode()}`, col * 1, 0)
this.write(`${this.bpm}`, col * 2, 0)
- this.write(this.midi.vu(), col * 3, 0)
+ this.write(`${this.midi}`, col * 3, 0)
}
this.write = function (text, offsetX, offsetY) {