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