This commit is contained in:
Rik Berkelder 2026-08-04 16:17:28 +02:00
parent 77a1dc85d2
commit 2aaf306a4b
2 changed files with 47 additions and 32 deletions

View file

@ -110,7 +110,8 @@ export class MidiControl<T extends MessageType> {
} }
// ugly typing here, but library overloads are a little annoying to work around. worst case scenario nothing happens // ugly typing here, but library overloads are a little annoying to work around. worst case scenario nothing happens
this.device.output?.send(type as any, { ...data, ...this.filter } as any); const outData = {...this.filter, ...data }
this.device.output?.send(type as any, outData as any);
} }
public getPage(): number { return this.page }; public getPage(): number { return this.page };
@ -136,7 +137,6 @@ export class MidiControl<T extends MessageType> {
if (typeof pages === 'number') pages = [pages]; if (typeof pages === 'number') pages = [pages];
const newValue = { ...this.defaultData(), ...this.filter, ...data }; const newValue = { ...this.defaultData(), ...this.filter, ...data };
for (const page of pages) { for (const page of pages) {
if (!noStore) this.values[page] = newValue; if (!noStore) this.values[page] = newValue;

View file

@ -161,7 +161,7 @@ export default async function mapping() {
const [xtouch, xtouch_loop] = await retry(() => { const [xtouch, xtouch_loop] = await retry(() => {
return [ return [
new MidiDevice('X-TOUCH COMPACT', true), new MidiDevice('X-TOUCH COMPACT', true),
new MidiDevice('XTouch-loop', true, true) new MidiDevice('xtouch-ma', true)
] ]
}, 1000, 'xtouch') }, 1000, 'xtouch')
@ -182,39 +182,36 @@ export default async function mapping() {
tryXTouch(); tryXTouch();
//tryKeyboard(); //tryKeyboard();
//tryApcMini(); tryApcMini();
} }
async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: OSCDevice) { async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: OSCDevice) {
const noteButtonFeedback = (note: number, address: string) => {
const button = xtouch.addControl(MessageType.NoteOnOff, { note });
ma3.addListener(address, data => { xtouch.input.on('cc', m => console.dir(m));
const value = data[0] xtouch.input.on('noteon', m => console.dir(m));
if (typeof value !== 'number') return; xtouch.input.on('noteoff', m => console.dir(m));
button.handleFeedback(0, { value: value === 1 ? true : false })
})
button.addOutput(0, data => ma3.sendInt(address, data.value ? 1 : 0))
return button;
}
// MAPPINGS // MAPPINGS
// passthroughs for encoders plugin // passthroughs for encoders plugin
numberRange(21, 26).forEach(encoder => { numberRange(18, 22).forEach(encoder => {
xtouch.addControl(MessageType.CC, { controller: encoder }).addOutput(0, message => { xtouch.addControl(MessageType.CC, { controller: encoder }).addOutput(0, message => {
xtouch_loop.output?.send(MessageType.CC, message) xtouch_loop.output?.send(MessageType.CC, message)
}) })
}) })
numberRange(8, 12).forEach(encoder => {
xtouch.addControl(MessageType.NoteOn, { note: encoder }).addOutput(0, message => {
xtouch_loop.output?.send(MessageType.NoteOn, message)
})
})
// Executor Faders // Executor Faders
const faders = numberRange(0, 8).map(f => xtouch.addControl(MessageType.CC, { controller: f })) const faders = numberRange(1, 9).map(f => xtouch.addControl(MessageType.CC, { controller: f }))
faders.forEach((fader, index) => { faders.forEach((fader, index) => {
const firstExec = 201; const firstExec = 201;
@ -227,7 +224,7 @@ async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: O
ma3.addListener(address, value => { ma3.addListener(address, value => {
if (typeof value[0] === 'number') { if (typeof value[0] === 'number') {
const mappedValue = mapNumber(value[0], 0, 1, 0, 127); const mappedValue = mapNumber(value[0], 0, 100, 0, 127);
fader.handleFeedback(0, { value: mappedValue }) fader.handleFeedback(0, { value: mappedValue })
} }
}) })
@ -241,17 +238,30 @@ async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: O
numberRange(32, 39), numberRange(32, 39),
numberRange(40, 48) numberRange(40, 48)
].map((row, rowIndex) => row.map((note, noteIndex) => { ].map((row, rowIndex) => row.map((note, noteIndex) => {
const totalIndex = rowIndex * 8 + noteIndex;
const rowLookup = [401, 301, 201, 101]; const rowLookup = [401, 301, 201, 101];
const address = `/Page/Key${rowLookup[rowIndex] ?? 101 + noteIndex}` const address = `/Page/Key${(rowLookup[rowIndex] ?? 101) + noteIndex}`
return noteButtonFeedback(note, address); const button = xtouch.addControl(MessageType.NoteOnOff, { note });
ma3.addListener(address, data => {
const value = data[0]
if (typeof value !== 'number') return;
button.handleFeedback(0, { value: true, note: totalIndex, velocity: value + 1 })
})
button.addOutput(0, data => ma3.sendInt(address, data.value ? 1 : 0))
return button;
})) }))
// Misc Buttons // Misc Buttons
const [rwd, fwd, loop, rec, stop, play] = [ const [rwd, fwd, loop, rec, stop, play] = [
{ note: 49, key: 'PAGE_UP' }, { note: 49, key: 'PAGE_DOWN' },
{ note: 50, key: 'PAGE_DOWN' }, { note: 50, key: 'PAGE_UP' },
{ note: 51, key: '' }, { note: 51, key: '' },
{ note: 52, key: '' }, { note: 52, key: '' },
{ note: 53, key: 'DEF_GOBACK' }, { note: 53, key: 'DEF_GOBACK' },
@ -268,20 +278,24 @@ async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: O
// Exec Encoders // Exec Encoders
const encoders = [11, 12, 13, 14, 15, 16, 17, 18].map((cc, index) => { const encoders = [26,27,28,29,30,31,32,33].map((cc, index) => {
const encoder = xtouch.addControl(MessageType.CC, { controller: cc }) const encoder = xtouch.addControl(MessageType.CC, { controller: cc })
const firstExec = 401; const firstExec = 401;
const address = `/Page/Encoder${firstExec + index}`; const address = `/Page/Encoder${firstExec + index}`;
const feedbackAddress = `/Page/Fader${firstExec + index}`; const feedbackAddress = `/Page/Fader${firstExec + index}`;
encoder.addOutput(0, message => { encoder.addOutput(0, message => {
ma3.sendInt(address, mapNumber(message.value, 0, 1, -1, 1)) let value = message.value;
if(message.value > 50) value = message.value - 128;
console.log(value);
ma3.sendFloat(address, value)
}) })
ma3.addListener(feedbackAddress, data => { ma3.addListener(feedbackAddress, data => {
if (typeof data[0] !== 'number') return; if (typeof data[0] !== 'number') return;
encoder.handleFeedback(0, { value: mapNumber(data[0], 0, 100, 0, 13) })
encoder.handleFeedback(0, { value: mapNumber(data[0], 0, 1, 0, 127) })
}) })
}) })
} }
@ -333,7 +347,7 @@ async function keyboardMapping(keyboard: MidiDevice, ma3: OSCDevice) {
} }
async function apcminiMapping(apcmini: MidiDevice, ma3: OSCDevice) { async function apcminiMapping(apcmini: MidiDevice, ma3: OSCDevice) {
const APC_FIRST_EXEC = 201; const APC_FIRST_EXEC = 231;
apcmini.input.on('cc', m => console.dir(m)); apcmini.input.on('cc', m => console.dir(m));
apcmini.input.on('noteon', m => console.dir(m)); apcmini.input.on('noteon', m => console.dir(m));
@ -347,7 +361,8 @@ async function apcminiMapping(apcmini: MidiDevice, ma3: OSCDevice) {
const address = `/Page/Fader${exec}`; const address = `/Page/Fader${exec}`;
fader.addOutput(0, (message) => { fader.addOutput(0, (message) => {
ma3.sendFloat(address, mapNumber(message.value, 2, 125, MA3_FADER_MIN, MA3_FADER_MAX)); console.log(address)
ma3.sendFloat(address, mapNumber(message.value, 0, 127, MA3_FADER_MIN, MA3_FADER_MAX));
}); });
}); });
@ -381,9 +396,9 @@ async function apcminiMapping(apcmini: MidiDevice, ma3: OSCDevice) {
]; ];
[ [
numberRange(101, 108), numberRange(331, 338),
numberRange(301, 308), numberRange(431, 438),
numberRange(401, 408), numberRange(131, 138),
null, null,
null, null,
null, null,