Skip to content

Commit 30c725c

Browse files
Copilotandersnm
andauthored
Add mono input channel selection to audio configuration
Agent-Logs-Url: https://github.com/andersnm/modulyzer/sessions/f1d880be-bfe5-4d9e-b778-86ded95487ee Co-authored-by: andersnm <16575282+andersnm@users.noreply.github.com>
1 parent a3f8c0f commit 30c725c

3 files changed

Lines changed: 41 additions & 12 deletions

File tree

src/App.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ export class Appl extends CommandHost implements IComponent {
302302
this.device.outputDeviceId = await this.readSetting<string>("OutputDevice") ?? null;
303303
this.device.inputDeviceId = await this.readSetting<string>("InputDevice") ?? null;
304304
this.device.latencySec = await this.readSetting<number>("Latency") ?? 125;
305+
this.device.inputMode = await this.readSetting<"stereo" | "left" | "right">("InputMode") ?? "stereo";
305306

306307
await this.executeCommand("show-audio-configuration");
307308
}
@@ -316,7 +317,8 @@ export class Appl extends CommandHost implements IComponent {
316317
await handleMap.set(key, value);
317318
}
318319

319-
async setAudioDevice(outputDeviceId: string, inputDeviceId: string, latencySec: number) {
320+
async setAudioDevice(outputDeviceId: string, inputDeviceId: string, latencySec: number, inputMode: "stereo" | "left" | "right" = "stereo") {
321+
this.device.inputMode = inputMode;
320322
await this.device.create(outputDeviceId, inputDeviceId, latencySec);
321323

322324
this.player = new Player(this.instrumentFactories, this.device);
@@ -327,6 +329,7 @@ export class Appl extends CommandHost implements IComponent {
327329
await this.writeSetting("OutputDevice", outputDeviceId);
328330
await this.writeSetting("InputDevice", inputDeviceId);
329331
await this.writeSetting("Latency", latencySec);
332+
await this.writeSetting("InputMode", inputMode);
330333
}
331334

332335
render() {
@@ -420,17 +423,15 @@ export class Appl extends CommandHost implements IComponent {
420423
return;
421424
}
422425

423-
this.song.replaceWaveBuffer(this.recordWave, this.recordOffset, inputs);
424-
425-
for (let i = 0; i < this.recordWave.buffers.length; i++) {
426-
const output = this.recordWave.buffers[i];
427-
const input = inputs[i % inputs.length];
428-
429-
for (let j = 0; j < input.length; j++) {
430-
output[this.recordOffset + j] = input[j];
431-
}
426+
// For mono waves, select the channel specified by inputMode
427+
let effectiveInputs = inputs;
428+
if (this.recordWave.buffers.length === 1) {
429+
const channelIndex = this.device.inputMode === "right" && inputs.length > 1 ? 1 : 0;
430+
effectiveInputs = [inputs[channelIndex]];
432431
}
433432

433+
this.song.replaceWaveBuffer(this.recordWave, this.recordOffset, effectiveInputs);
434+
434435
this.recordOffset += inputLength;
435436
// notify document
436437
};

src/commands/Application/ShowAudioConfigurationCommand.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ export class ShowAudioConfigurationCommand {
1616
audioConfiguration.cancelable = !!this.app.device.context;
1717
audioConfiguration.currentOutputDeviceId = this.app.device.outputDeviceId;
1818
audioConfiguration.currentInputDeviceId = this.app.device.inputDeviceId;
19+
audioConfiguration.inputMode = this.app.device.inputMode;
1920

2021
const result = await this.app.modalDialogContainer.showModal("Audio Configuration", audioConfiguration, false);
2122
if (!result) {
2223
return;
2324
}
2425

25-
await this.app.setAudioDevice(audioConfiguration.currentOutputDeviceId, audioConfiguration.currentInputDeviceId, audioConfiguration.latencySec);
26+
await this.app.setAudioDevice(audioConfiguration.currentOutputDeviceId, audioConfiguration.currentInputDeviceId, audioConfiguration.latencySec, audioConfiguration.inputMode);
2627
}
2728
}

src/components/AudioConfiguration.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export class AudioConfiguration implements IComponent {
2727
currentInputDeviceId: string;
2828
currentOutputDeviceId: string;
2929
microphonePermission: string = "denied";
30-
inputMode: string = "stereo";
30+
inputMode: "stereo" | "left" | "right" = "stereo";
3131
currentInputSampleRate = 44100;
3232
currentInputChannelCount = 2;
3333
latencySec = 0.5;
@@ -41,6 +41,7 @@ export class AudioConfiguration implements IComponent {
4141
outputDevicesSelect: HTMLSelectElement;
4242
inputDevicesSelect: HTMLSelectElement;
4343
latencySelect: HTMLSelectElement;
44+
inputModeSelect: HTMLSelectElement;
4445
buttonBar: ModalButtonBar;
4546

4647
constructor(app: Appl) {
@@ -95,6 +96,7 @@ export class AudioConfiguration implements IComponent {
9596
this.bindOutputDevices(outputDevices)
9697
this.bindInputDevices(inputDevices)
9798
this.bindLatency();
99+
this.bindInputMode();
98100
this.bindButtons();
99101

100102
this.bind();
@@ -117,6 +119,10 @@ export class AudioConfiguration implements IComponent {
117119
} as DeviceInfo;
118120
};
119121

122+
bindInputMode() {
123+
this.inputModeSelect.value = this.inputMode;
124+
}
125+
120126
bindLatency() {
121127
while (this.latencySelect.options.length > 0) this.latencySelect.options.remove(0);
122128

@@ -228,11 +234,32 @@ export class AudioConfiguration implements IComponent {
228234

229235
const latencyGroup = FormGroup("Latency", this.latencySelect);
230236

237+
this.inputModeSelect = document.createElement("select");
238+
this.inputModeSelect.className = "w-full rounded-lg p-1 bg-neutral-800";
239+
this.inputModeSelect.addEventListener("change", () => {
240+
this.inputMode = this.inputModeSelect.value as "stereo" | "left" | "right";
241+
});
242+
243+
const inputModeOptions: { value: string; label: string }[] = [
244+
{ value: "stereo", label: "Stereo" },
245+
{ value: "left", label: "Left channel (mono)" },
246+
{ value: "right", label: "Right channel (mono)" },
247+
];
248+
for (const { value, label } of inputModeOptions) {
249+
const opt = document.createElement("option");
250+
opt.value = value;
251+
opt.label = label;
252+
this.inputModeSelect.options.add(opt);
253+
}
254+
255+
const inputModeGroup = FormGroup("Mono Input Channel", this.inputModeSelect);
256+
231257
this.buttonBar = new ModalButtonBar(this.app);
232258

233259
this.configForm.appendChild(outputGroup);
234260
this.configForm.appendChild(inputGroup);
235261
this.configForm.appendChild(latencyGroup);
262+
this.configForm.appendChild(inputModeGroup);
236263

237264
this.configForm.appendChild(this.buttonBar.getDomNode());
238265
}

0 commit comments

Comments
 (0)