-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Yisheng Jiang
committed
May 18, 2024
1 parent
f71a3ef
commit 02bcddf
Showing
8 changed files
with
382 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
export function readMidi(buffer) { | ||
const reader = bufferReader2(buffer); | ||
const {fgetc, btoa, read32, readVarLength, read16} = | ||
reader; | ||
const chunkType = [btoa(), btoa(), btoa(), btoa()].join(""); | ||
const headerLength = read32(); | ||
|
||
const DEFAULT_TEMPO = { | ||
tempo: 500000, //msqn, | ||
t: 0 //start time | ||
} | ||
const format = read16(); | ||
const ntracks = read16(); | ||
const division = read16(); | ||
const headerInfo = {chunkType, headerLength, format}; | ||
const tracks = []; | ||
const DEFAULT_TIMEBASE = { | ||
relative_ts: 4, numerator: 4, denum: 4, ticksPerBeat: division, eigthNotePerBeat: 8 | ||
}; | ||
const limit = buffer.byteLength; | ||
let lasttype; | ||
|
||
const presets = []; | ||
const tempos = []; | ||
let time_base = null; | ||
while (reader.offset < limit) { | ||
console.log(fgetc(), fgetc(), fgetc(), fgetc()); | ||
let t = 0; | ||
const mhrkLength = read32(); | ||
const endofTrack = reader.offset + mhrkLength; | ||
const track = []; | ||
while (reader.offset < limit && reader.offset < endofTrack) { | ||
const delay = readVarLength(); | ||
const nextEvent = readNextEvent(); | ||
if (!nextEvent) break; | ||
if (nextEvent.eot) break; | ||
t += delay; | ||
if (nextEvent.relative_ts) { | ||
time_base = nextEvent; | ||
track.push({offset: reader.offset, t, delay, ...nextEvent}); | ||
} | ||
if (nextEvent.tempo) { | ||
tempos.push({ | ||
t, | ||
delay, | ||
track: track.length, | ||
...nextEvent, | ||
}); | ||
const evtObj = {offset: reader.offset, t, delay, ...nextEvent}; | ||
track.push(evtObj); | ||
} else if (nextEvent.channel && nextEvent.channel[0] >> 4 === 0x0c) { | ||
presets.push({ | ||
t, | ||
channel: nextEvent.channel[0] & 0x0f, | ||
pid: nextEvent.channel[1] & 0x7f, | ||
}); | ||
const evtObj = {offset: reader.offset, t, delay, ...nextEvent}; | ||
track.push(evtObj); | ||
} else { | ||
const evtObj = {offset: reader.offset, t, delay, ...nextEvent}; | ||
track.push(evtObj); | ||
} | ||
} | ||
if (track.length) tracks.push(track); | ||
reader.offset = endofTrack; | ||
} | ||
if (time_base == null) { | ||
time_base = DEFAULT_TIMEBASE | ||
} | ||
if (tempos.length === 0) { | ||
tempos.push(DEFAULT_TEMPO) | ||
} | ||
return {headerInfo, division, tracks, ntracks, presets, tempos, time_base}; | ||
function readNextEvent() { | ||
const {fgetc, read24, readString, readVarLength} = reader; | ||
let type = fgetc(); | ||
if (type === null) return []; | ||
if ((type & 0xf0) === 0xf0) { | ||
switch (type) { | ||
case 0xff: { | ||
const meta = fgetc(); | ||
const len = readVarLength(); | ||
switch (meta) { | ||
case 0x21: | ||
return {port: fgetc()}; | ||
case 0x51: | ||
return {tempo: read24()}; | ||
case 0x58: //0xFF 0x58 0x04 [ | ||
// 0x04 0x02 0x18 0x08 | ||
const [numerator, denomP2, ticksPerBeat, eigthNotePerBeat] = [fgetc(), fgetc(), fgetc(), fgetc()]; | ||
const denum = Math.pow(2, denomP2); | ||
const relative_ts = numerator / denum * 4; | ||
return {relative_ts, numerator, denum, ticksPerBeat, eigthNotePerBeat}; | ||
case 0x59: | ||
return {meta, payload: [fgetc(), fgetc()]}; | ||
default: | ||
return {meta, payload: readString(len), len}; | ||
} | ||
} | ||
case 0xf0: | ||
case 0xf7: | ||
return {sysex: readString(readVarLength())}; | ||
default: | ||
return {type, system: readString(readVarLength())}; | ||
} | ||
} else { | ||
let param; | ||
if (0 === (type & 0x80)) { | ||
param = type; | ||
type = lasttype; | ||
} else { | ||
param = fgetc(); | ||
lasttype = type; | ||
} | ||
switch (type >> 4) { | ||
case 0x0c: | ||
case 0x0d: | ||
return { | ||
ch: type & 0x0f, | ||
cmd: (type >> 4).toString(16), | ||
channel: [type, param, 0], | ||
}; | ||
default: | ||
return { | ||
ch: type & 0x0f, | ||
cmd: (type >> 4).toString(16), | ||
channel: [type, param, fgetc()], | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
function bufferReader2(bytes) { | ||
let _offset = 0; | ||
const fgetc = () => bytes[_offset++]; | ||
const read32 = () => | ||
(fgetc() << 24) | (fgetc() << 16) | (fgetc() << 8) | fgetc(); | ||
const read16 = () => (fgetc() << 8) | fgetc(); | ||
const read24 = () => (fgetc() << 16) | (fgetc() << 8) | fgetc(); | ||
function readVarLength() { | ||
let v = 0; | ||
let n = fgetc(); | ||
v = n & 0x7f; | ||
while (n & 0x80) { | ||
n = fgetc(); | ||
v = (v << 7) | (n & 0x7f); | ||
} | ||
return v; | ||
} | ||
function btoa() { | ||
const code = fgetc(); | ||
return code >= 32 && code <= 122 | ||
? ` !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[~]^_@abcdefghijklmnopqrstuvwxyz`.split( | ||
"" | ||
)[code - 32] | ||
: code; | ||
} | ||
const readString = (n) => { | ||
let str = ""; | ||
while (n--) str += btoa(); | ||
return str; | ||
}; | ||
return { | ||
get offset() { | ||
return _offset; | ||
}, | ||
set offset(o) { | ||
_offset = o; | ||
}, | ||
fgetc, | ||
read32, | ||
read24, | ||
read16, | ||
readVarLength, | ||
readString, | ||
btoa, | ||
}; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,20 @@ | ||
{ | ||
"name": "grep-fifo", | ||
"type": "module", | ||
"version": "1.0.0", | ||
"description": "ES6 compliant and (typescript friendly) implementation of circular fifo in C99", | ||
"main": "fifo.wasmodule.js", | ||
"scripts": { | ||
"build": "docker run --rm -v `pwd`:/src trzeci/emscripten-slim emcc yofi.c -s EXPORT_ALL=1 -o yofi.js", | ||
"test": "node ./test.js" | ||
"test": "node ./test.mjs" | ||
}, | ||
"keywords": [ | ||
"pain in the arse", | ||
"allegedly faster than javascript" | ||
], | ||
"author": "", | ||
"license": "ISC" | ||
"license": "ISC", | ||
"dependencies": { | ||
"midi-file": "^1.2.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,20 @@ | ||
#include <stdint.h> | ||
|
||
#define QUEUE_SIZE 1 << 16 | ||
#define QUEUE_SIZE 0xffff | ||
|
||
typedef struct { | ||
uint16_t head; | ||
uint16_t tail; | ||
char data[QUEUE_SIZE]; | ||
uint8_t data[QUEUE_SIZE]; | ||
} queue_t; | ||
|
||
queue_t instance[1]; | ||
|
||
queue_t* getInstance() { return instance; } | ||
int queue_count(queue_t* queue) { return queue->head - queue->tail; } | ||
uint8_t queue_read(queue_t* queue) { return queue->data[queue->tail++] & 0xff; } | ||
|
||
uint16_t queue_count(queue_t* queue) { return queue->head - queue->tail; } | ||
|
||
char queue_read(queue_t* queue) { | ||
if (queue->tail == queue->head) return 0; | ||
return queue->data[queue->tail++]; | ||
} | ||
|
||
int queue_write(queue_t* queue, char c) { | ||
int queue_write(queue_t* queue, uint8_t c) { | ||
if (queue->tail - queue->head >= QUEUE_SIZE) return 1; | ||
queue->data[queue->head++] = c; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.