Repository navigation
Expand file tree
/
Copy pathutils.ts
More file actions
113 lines (96 loc) · 2.66 KB
/
Copy pathutils.ts
File metadata and controls
113 lines (96 loc) · 2.66 KB
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
import type { Midi } from "@tonejs/midi";
import type { Instruments } from "./mapping";
const NOTE_NAMES = [
'C',
'C#',
'D',
'D#',
'E',
'F',
'F#',
'G',
'G#',
'A',
'A#',
'B',
];
export function midiToNote(midi: number): string {
const note = midi % 12;
const octave = Math.floor(midi / 12) - 1;
return `${NOTE_NAMES[note]}${octave}`;
}
export interface Mapping {
[note: number]: number;
}
export function generateMappingFromMIDI(midi: Midi, channel = -1): Mapping {
const output: Mapping = {};
const notes = midi.tracks
.filter((track) => {
// Not filtering by channel
if (channel === -1) {
return true
}
return track.channel === channel
})
.flatMap((track) => track.notes);
for (const note of notes) {
output[note.midi] = note.midi;
}
return output;
}
export function transformMapping(
input: Mapping,
source: Instruments,
target: Instruments,
): Mapping {
// Loop once and create a map of target notes
// instead of looping every time we need to convert.
const targetInstrumentNote = new Map<string, number>();
for (const [note, instrument] of Object.entries(target)) {
targetInstrumentNote.set(instrument, parseInt(note, 10));
}
return Object.fromEntries(
Object.entries(input).map(([note, originalTargetNote]) => {
const noteAsNum = parseInt(note, 10);
const instrumentName = source[noteAsNum];
// Source map does not have an instrument for this note.
// Keep the original key:value pair.
if (!instrumentName) {
return [noteAsNum, originalTargetNote];
}
// Source map has an instrument for this note.
// Check if the target map has a note for this instrument.
// If not, keep the original key:value pair.
return [noteAsNum, targetInstrumentNote.get(instrumentName) ?? originalTargetNote];
}),
);
}
export function remapMIDI(midi: Midi, mapping: Mapping): Midi {
const newMidi = midi.clone();
newMidi.tracks.forEach((track) => {
track.notes.forEach((note) => {
note.midi = mapping[note.midi] ?? note.midi;
})
})
return newMidi;
}
// This should do it for now.
// Ideally we would have a mapping of constants to names.
export function getName(constant: string): string {
return constant
.split('_')
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');
};
export function getLibraryName(constant: string) {
switch (constant) {
case 'gm':
return 'General MIDI';
case 'mm-ggd':
return 'GGD Modern & Massive';
case 'okw-ar-ggd':
return 'GGD One Kit Wonder: Aggressive Rock'
default:
return 'Unknown';
}
}