adds mono-mode

This commit is contained in:
André Michelle
2026-01-20 11:33:03 +01:00
parent 0577102a4b
commit c8adb45885
3 changed files with 36 additions and 30 deletions
+1
View File
@@ -20,3 +20,4 @@ lerna-debug.log
/certs/localhost-key.pem
/packages/app/soundfont/public/soundfonts/
/packages/studio/scripting/src/api.declaration.d.ts
tsconfig.tsbuildinfo
@@ -28,7 +28,7 @@ type Construct = {
}
export const AudioUnitChannelControls = ({lifecycle, service, adapter}: Construct) => {
const {project, audioContext} = service
const {project} = service
const {captureDevices, editing, midiLearning} = project
const {volume, panning, mute, solo} = adapter.namedParameter
const volumeControl = (
@@ -77,20 +77,20 @@ export const AudioUnitChannelControls = ({lifecycle, service, adapter}: Construc
attachParameterContextMenu(editing, midiLearning, adapter.tracks, panning, panningControl),
attachParameterContextMenu(editing, midiLearning, adapter.tracks, mute, muteControl),
attachParameterContextMenu(editing, midiLearning, adapter.tracks, solo, soloControl),
captureOption.ifSome(capture => {
if (!isInstanceOf(capture, CaptureAudio)) {return}
const streamLifeCycle = lifecycle.own(new Terminator())
capture.stream.catchupAndSubscribe(optStream => {
captureOption.match({
none: () => Terminable.Empty,
some: capture => {
if (!isInstanceOf(capture, CaptureAudio)) {return Terminable.Empty}
const meterLifeCycle = lifecycle.own(new Terminator())
const connectMeter = () => {
streamRunning = false
streamLifeCycle.terminate()
return optStream.ifSome(stream => {
const numberOfChannels = stream.getAudioTracks().at(0)?.getSettings().channelCount ?? 2
meterLifeCycle.terminate()
capture.outputNode.ifSome(outputNode => {
const numberOfChannels = capture.effectiveChannelCount
const meterWorklet = service.audioWorklets.createMeter(numberOfChannels)
const streamSource = audioContext.createMediaStreamSource(stream)
streamSource.connect(meterWorklet)
outputNode.connect(meterWorklet)
streamRunning = true
streamLifeCycle.ownAll(
Terminable.create(() => streamSource.disconnect()),
meterLifeCycle.ownAll(
meterWorklet.subscribe(({peak}) => {
peaksInDb[0] = gainToDb(peak[0])
peaksInDb[1] = gainToDb(peak[1] ?? peak[0])
@@ -98,8 +98,13 @@ export const AudioUnitChannelControls = ({lifecycle, service, adapter}: Construc
meterWorklet
)
})
})
}) ?? Terminable.Empty,
}
return Terminable.many(
capture.stream.catchupAndSubscribe(() => connectMeter()),
capture.captureBox.requestChannels.subscribe(() => connectMeter())
)
}
}),
project.liveStreamReceiver.subscribeFloats(adapter.address, values => {
if (streamRunning) {return}
peaksInDb[0] = gainToDb(values[0])
@@ -25,7 +25,6 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
#isMonitoring: boolean = false
#requestChannels: Option<1 | 2> = Option.None
#gainDb: number = 0.0
#audioChain: Nullable<{
sourceNode: MediaStreamAudioSourceNode
gainNode: GainNode
@@ -78,9 +77,7 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
}
get gainDb(): number {return this.#gainDb}
get requestChannels(): Option<1 | 2> {return this.#requestChannels}
set requestChannels(value: 1 | 2) {
this.captureBox.requestChannels.setValue(value)
}
set requestChannels(value: 1 | 2) {this.captureBox.requestChannels.setValue(value)}
get stream(): MutableObservableOption<MediaStream> {return this.#stream}
get streamDeviceId(): Option<string> {
return this.streamMediaTrack.map(settings => settings.getSettings().deviceId ?? "")
@@ -90,6 +87,8 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
get streamMediaTrack(): Option<MediaStreamTrack> {
return this.#stream.flatMap(stream => Option.wrap(stream.getAudioTracks().at(0)))
}
get outputNode(): Option<AudioNode> {return Option.wrap(this.#audioChain?.gainNode)}
get effectiveChannelCount(): number {return this.#audioChain?.gainNode.channelCount ?? 1}
async prepareRecording(): Promise<void> {
const {project} = this.manager
@@ -157,8 +156,8 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
const gotDeviceId = settings?.deviceId
console.debug(`new stream. device requested: ${deviceId ?? "default"}, got: ${gotDeviceId ?? "unknown"}. channelCount requested: ${channelCount}, got: ${settings?.channelCount}`)
if (isUndefined(deviceId) || deviceId === gotDeviceId) {
this.#stream.wrap(stream)
this.#rebuildAudioChain(stream)
this.#stream.wrap(stream)
} else {
stream.getAudioTracks().forEach(track => track.stop())
return Errors.warn(`Could not find audio device with id: '${deviceId}' (got: '${gotDeviceId}')`)
@@ -209,7 +208,8 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
#disconnectMonitoring(): void {
if (isDefined(this.#audioChain)) {
this.#audioChain.gainNode.disconnect()
const {audioContext} = this.manager.project.env
this.#audioChain.gainNode.disconnect(audioContext.destination)
}
}
}