diff --git a/src/App.scss b/src/App.scss index 77ba8a4..1915f2e 100644 --- a/src/App.scss +++ b/src/App.scss @@ -38,6 +38,10 @@ $number-of-channels: 3; grid-template-rows: 100%; grid-gap: 10px; padding: 10px; + + .channel-vu { + width: 100%; + } } #sidebar { grid-area: sb; diff --git a/src/mixer/audio.ts b/src/mixer/audio.ts index 6afefb3..31f3929 100644 --- a/src/mixer/audio.ts +++ b/src/mixer/audio.ts @@ -144,6 +144,7 @@ class Player extends ((PlayerEmitter as unknown) as { new (): EventEmitter }) { (wavesurfer as any).backend.gainNode.disconnect(); (wavesurfer as any).backend.gainNode.connect(engine.finalCompressor); + (wavesurfer as any).backend.gainNode.connect(engine.playerAnalysers[player]) wavesurfer.load(url); @@ -160,7 +161,7 @@ class Player extends ((PlayerEmitter as unknown) as { new (): EventEmitter }) { } } -export type LevelsSource = "mic-precomp" | "mic-final" | "master"; +export type LevelsSource = "mic-precomp" | "mic-final" | "master" | "player-0" | "player-1" | "player-2"; const ANALYSIS_FFT_SIZE = 8192; @@ -190,6 +191,11 @@ export class AudioEngine extends ((EngineEmitter as unknown) as { finalCompressor: DynamicsCompressorNode; streamingDestination: MediaStreamAudioDestinationNode; + player0Analyser: AnalyserNode; + player1Analyser: AnalyserNode; + player2Analyser: AnalyserNode; + playerAnalysers: AnalyserNode[]; + streamingAnalyser: AnalyserNode; newsStartCountdownEl: HTMLAudioElement; @@ -214,6 +220,14 @@ export class AudioEngine extends ((EngineEmitter as unknown) as { this.finalCompressor.release.value = 0.2; this.finalCompressor.knee.value = 0; + this.player0Analyser = this.audioContext.createAnalyser(); + this.player0Analyser.fftSize = ANALYSIS_FFT_SIZE; + this.player1Analyser = this.audioContext.createAnalyser(); + this.player1Analyser.fftSize = ANALYSIS_FFT_SIZE; + this.player2Analyser = this.audioContext.createAnalyser(); + this.player2Analyser.fftSize = ANALYSIS_FFT_SIZE; + this.playerAnalysers = [this.player0Analyser, this.player1Analyser, this.player2Analyser]; + this.streamingAnalyser = this.audioContext.createAnalyser(); this.streamingAnalyser.fftSize = ANALYSIS_FFT_SIZE; // this.streamingAnalyser.maxDecibels = 0; @@ -334,6 +348,15 @@ export class AudioEngine extends ((EngineEmitter as unknown) as { case "master": this.streamingAnalyser.getFloatTimeDomainData(this.analysisBuffer); break; + case "player-0": + this.player0Analyser.getFloatTimeDomainData(this.analysisBuffer); + break; + case "player-1": + this.player1Analyser.getFloatTimeDomainData(this.analysisBuffer); + break; + case "player-2": + this.player2Analyser.getFloatTimeDomainData(this.analysisBuffer); + break; default: throw new Error("can't getLevel " + source); } diff --git a/src/showplanner/Player.tsx b/src/showplanner/Player.tsx index 4fa5435..340ade4 100644 --- a/src/showplanner/Player.tsx +++ b/src/showplanner/Player.tsx @@ -13,6 +13,7 @@ import { RootState } from "../rootReducer"; import * as MixerState from "../mixer/state"; import { secToHHMM, timestampToHHMM } from "../lib/utils"; import ProModeButtons from "./ProModeButtons"; +import { VUMeter } from "../optionsMenu/helpers/VUMeter"; export const USE_REAL_GAIN_VALUE = false; @@ -68,6 +69,19 @@ export function Player({ id }: { id: number }) { const proMode = useSelector((state: RootState) => state.settings.proMode); const dispatch = useDispatch(); + const VUsource = + (id: number) => { + switch(id) { + case 0: + return "player-0"; + case 1: + return "player-1"; + case 2: + return "player-2"; + default: + return "master"; + } + }; return (
+ { proMode && } ); }