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
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 };
@ -136,7 +137,6 @@ export class MidiControl<T extends MessageType> {
if (typeof pages === 'number') pages = [pages];
const newValue = { ...this.defaultData(), ...this.filter, ...data };
for (const page of pages) {
if (!noStore) this.values[page] = newValue;

View file

@ -161,7 +161,7 @@ export default async function mapping() {
const [xtouch, xtouch_loop] = await retry(() => {
return [
new MidiDevice('X-TOUCH COMPACT', true),
new MidiDevice('XTouch-loop', true, true)
new MidiDevice('xtouch-ma', true)
]
}, 1000, 'xtouch')
@ -182,39 +182,36 @@ export default async function mapping() {
tryXTouch();
//tryKeyboard();
//tryApcMini();
tryApcMini();
}
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 => {
const value = data[0]
if (typeof value !== 'number') return;
xtouch.input.on('cc', m => console.dir(m));
xtouch.input.on('noteon', m => console.dir(m));
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
// passthroughs for encoders plugin
numberRange(21, 26).forEach(encoder => {
numberRange(18, 22).forEach(encoder => {
xtouch.addControl(MessageType.CC, { controller: encoder }).addOutput(0, 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
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) => {
const firstExec = 201;
@ -227,7 +224,7 @@ async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: O
ma3.addListener(address, value => {
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 })
}
})
@ -241,17 +238,30 @@ async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: O
numberRange(32, 39),
numberRange(40, 48)
].map((row, rowIndex) => row.map((note, noteIndex) => {
const totalIndex = rowIndex * 8 + noteIndex;
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
const [rwd, fwd, loop, rec, stop, play] = [
{ note: 49, key: 'PAGE_UP' },
{ note: 50, key: 'PAGE_DOWN' },
{ note: 49, key: 'PAGE_DOWN' },
{ note: 50, key: 'PAGE_UP' },
{ note: 51, key: '' },
{ note: 52, key: '' },
{ note: 53, key: 'DEF_GOBACK' },
@ -268,20 +278,24 @@ async function xtouchMapping(xtouch: MidiDevice, xtouch_loop: MidiDevice, ma3: O
// 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 firstExec = 401;
const address = `/Page/Encoder${firstExec + index}`;
const feedbackAddress = `/Page/Fader${firstExec + index}`;
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 => {
if (typeof data[0] !== 'number') return;
encoder.handleFeedback(0, { value: mapNumber(data[0], 0, 1, 0, 127) })
encoder.handleFeedback(0, { value: mapNumber(data[0], 0, 100, 0, 13) })
})
})
}
@ -333,7 +347,7 @@ async function keyboardMapping(keyboard: 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('noteon', m => console.dir(m));
@ -347,7 +361,8 @@ async function apcminiMapping(apcmini: MidiDevice, ma3: OSCDevice) {
const address = `/Page/Fader${exec}`;
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(301, 308),
numberRange(401, 408),
numberRange(331, 338),
numberRange(431, 438),
numberRange(131, 138),
null,
null,
null,