mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 13:48:40 +00:00
- add defaultmidimap function
- add midisounds function - add midiport control
This commit is contained in:
parent
d86df33b8c
commit
c810a02a79
@ -1515,6 +1515,7 @@ export const { hbrick } = registerControl('hbrick');
|
|||||||
export const { lbrick } = registerControl('lbrick');
|
export const { lbrick } = registerControl('lbrick');
|
||||||
export const { midichan } = registerControl('midichan');
|
export const { midichan } = registerControl('midichan');
|
||||||
export const { midimap } = registerControl('midimap');
|
export const { midimap } = registerControl('midimap');
|
||||||
|
export const { midiport } = registerControl('midiport');
|
||||||
export const { control } = registerControl('control');
|
export const { control } = registerControl('control');
|
||||||
export const { ccn } = registerControl('ccn');
|
export const { ccn } = registerControl('ccn');
|
||||||
export const { ccv } = registerControl('ccv');
|
export const { ccv } = registerControl('ccv');
|
||||||
|
|||||||
@ -90,7 +90,7 @@ if (typeof window !== 'undefined') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// registry for midi mappings, converting control names to cc messages
|
// registry for midi mappings, converting control names to cc messages
|
||||||
export const midiMappings = new Map();
|
export const midicontrolMap = new Map();
|
||||||
|
|
||||||
// takes midimap and converts each control key to the main control name
|
// takes midimap and converts each control key to the main control name
|
||||||
function unifyMapping(mapping) {
|
function unifyMapping(mapping) {
|
||||||
@ -103,10 +103,6 @@ function unifyMapping(mapping) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// adds a midimap to the registry
|
|
||||||
export function addMidimap(name, mapping) {
|
|
||||||
midiMappings.set(name, unifyMapping(mapping));
|
|
||||||
}
|
|
||||||
|
|
||||||
function githubPath(base, subpath = '') {
|
function githubPath(base, subpath = '') {
|
||||||
if (!base.startsWith('github:')) {
|
if (!base.startsWith('github:')) {
|
||||||
@ -121,6 +117,11 @@ function githubPath(base, subpath = '') {
|
|||||||
return `https://raw.githubusercontent.com/${path}/${subpath}`;
|
return `https://raw.githubusercontent.com/${path}/${subpath}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// configures the default midimap, which is used when no "midimap" port is set
|
||||||
|
export function defaultmidimap(mapping) {
|
||||||
|
midicontrolMap.set('default', unifyMapping(mapping));
|
||||||
|
}
|
||||||
|
|
||||||
let loadCache = {};
|
let loadCache = {};
|
||||||
// adds multiple midimaps to the registry
|
// adds multiple midimaps to the registry
|
||||||
export async function midimaps(map) {
|
export async function midimaps(map) {
|
||||||
@ -134,10 +135,34 @@ export async function midimaps(map) {
|
|||||||
map = await loadCache[map];
|
map = await loadCache[map];
|
||||||
}
|
}
|
||||||
if (typeof map === 'object') {
|
if (typeof map === 'object') {
|
||||||
Object.entries(map).forEach(([name, mapping]) => addMidimap(name, mapping));
|
Object.entries(map).forEach(([name, mapping]) => midicontrolMap.set(name, unifyMapping(mapping)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// registry for midi sounds, converting sound names to controls
|
||||||
|
export const midisoundMap = new Map();
|
||||||
|
// adds multiple midimaps to the registry
|
||||||
|
export async function midisounds(map) {
|
||||||
|
if (typeof map === 'object') {
|
||||||
|
Object.entries(map).forEach(([name, mapping]) => midisoundMap.set(name, mapping));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyMidisounds(hapValue) {
|
||||||
|
const { s } = hapValue;
|
||||||
|
if (!midisoundMap.has(s)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let controls = midisoundMap.get(hapValue.s);
|
||||||
|
if (Array.isArray(controls)) {
|
||||||
|
controls = controls[hapValue.n || 0];
|
||||||
|
}
|
||||||
|
if (typeof controls === 'string') {
|
||||||
|
controls = { note: controls };
|
||||||
|
}
|
||||||
|
Object.assign(hapValue, controls);
|
||||||
|
}
|
||||||
|
|
||||||
// normalizes the given value from the given range and exponent
|
// normalizes the given value from the given range and exponent
|
||||||
function normalize(value = 0, min = 0, max = 1, exp = 1) {
|
function normalize(value = 0, min = 0, max = 1, exp = 1) {
|
||||||
if (min === max) {
|
if (min === max) {
|
||||||
@ -197,20 +222,39 @@ Pattern.prototype.midi = function (output) {
|
|||||||
console.log('not enabled');
|
console.log('not enabled');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const device = getDevice(output, WebMidi.outputs);
|
|
||||||
hap.ensureObjectValue();
|
hap.ensureObjectValue();
|
||||||
//magic number to get audio engine to line up, can probably be calculated somehow
|
//magic number to get audio engine to line up, can probably be calculated somehow
|
||||||
const latencyMs = 34;
|
const latencyMs = 34;
|
||||||
// passing a string with a +num into the webmidi api adds an offset to the current time https://webmidijs.org/api/classes/Output
|
// passing a string with a +num into the webmidi api adds an offset to the current time https://webmidijs.org/api/classes/Output
|
||||||
const timeOffsetString = `+${getEventOffsetMs(targetTime, currentTime) + latencyMs}`;
|
const timeOffsetString = `+${getEventOffsetMs(targetTime, currentTime) + latencyMs}`;
|
||||||
|
// convert s to midisounds preset (if set)
|
||||||
|
applyMidisounds(hap.value);
|
||||||
|
|
||||||
// destructure value
|
// destructure value
|
||||||
let { note, nrpnn, nrpv, ccn, ccv, midichan = 1, midicmd, gain = 1, velocity = 0.9, midimap } = hap.value;
|
let {
|
||||||
|
note,
|
||||||
|
ccn,
|
||||||
|
ccv,
|
||||||
|
midichan = 1,
|
||||||
|
midicmd,
|
||||||
|
gain = 1,
|
||||||
|
velocity = 0.9,
|
||||||
|
midimap = 'default',
|
||||||
|
midiport = output,
|
||||||
|
} = hap.value;
|
||||||
|
|
||||||
|
const device = getDevice(midiport, WebMidi.outputs);
|
||||||
|
if (!device) {
|
||||||
|
logger(
|
||||||
|
`[midi] midiport "${midiport}" not found! available: ${WebMidi.outputs.map((output) => `'${output.name}'`).join(', ')}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
velocity = gain * velocity;
|
velocity = gain * velocity;
|
||||||
|
|
||||||
// if midimap is set, send a cc messages from defined controls
|
// if midimap is set, send a cc messages from defined controls
|
||||||
if (!!midimap && midiMappings.has(midimap)) {
|
if (midicontrolMap.has(midimap)) {
|
||||||
const ccs = mapCC(midiMappings.get(midimap), hap.value);
|
const ccs = mapCC(midicontrolMap.get(midimap), hap.value);
|
||||||
ccs.forEach(({ ccn, ccv }) => sendCC(ccn, ccv, device, midichan, timeOffsetString));
|
ccs.forEach(({ ccn, ccv }) => sendCC(ccn, ccv, device, midichan, timeOffsetString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user