Add ProMode (TM) VU meters to each channel. Closes #71
This commit is contained in:
parent
ddf701de14
commit
1132862d9a
3 changed files with 49 additions and 1 deletions
|
@ -38,6 +38,10 @@ $number-of-channels: 3;
|
||||||
grid-template-rows: 100%;
|
grid-template-rows: 100%;
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
|
.channel-vu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#sidebar {
|
#sidebar {
|
||||||
grid-area: sb;
|
grid-area: sb;
|
||||||
|
|
|
@ -144,6 +144,7 @@ class Player extends ((PlayerEmitter as unknown) as { new (): EventEmitter }) {
|
||||||
|
|
||||||
(wavesurfer as any).backend.gainNode.disconnect();
|
(wavesurfer as any).backend.gainNode.disconnect();
|
||||||
(wavesurfer as any).backend.gainNode.connect(engine.finalCompressor);
|
(wavesurfer as any).backend.gainNode.connect(engine.finalCompressor);
|
||||||
|
(wavesurfer as any).backend.gainNode.connect(engine.playerAnalysers[player])
|
||||||
|
|
||||||
wavesurfer.load(url);
|
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;
|
const ANALYSIS_FFT_SIZE = 8192;
|
||||||
|
|
||||||
|
@ -190,6 +191,11 @@ export class AudioEngine extends ((EngineEmitter as unknown) as {
|
||||||
finalCompressor: DynamicsCompressorNode;
|
finalCompressor: DynamicsCompressorNode;
|
||||||
streamingDestination: MediaStreamAudioDestinationNode;
|
streamingDestination: MediaStreamAudioDestinationNode;
|
||||||
|
|
||||||
|
player0Analyser: AnalyserNode;
|
||||||
|
player1Analyser: AnalyserNode;
|
||||||
|
player2Analyser: AnalyserNode;
|
||||||
|
playerAnalysers: AnalyserNode[];
|
||||||
|
|
||||||
streamingAnalyser: AnalyserNode;
|
streamingAnalyser: AnalyserNode;
|
||||||
|
|
||||||
newsStartCountdownEl: HTMLAudioElement;
|
newsStartCountdownEl: HTMLAudioElement;
|
||||||
|
@ -214,6 +220,14 @@ export class AudioEngine extends ((EngineEmitter as unknown) as {
|
||||||
this.finalCompressor.release.value = 0.2;
|
this.finalCompressor.release.value = 0.2;
|
||||||
this.finalCompressor.knee.value = 0;
|
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 = this.audioContext.createAnalyser();
|
||||||
this.streamingAnalyser.fftSize = ANALYSIS_FFT_SIZE;
|
this.streamingAnalyser.fftSize = ANALYSIS_FFT_SIZE;
|
||||||
// this.streamingAnalyser.maxDecibels = 0;
|
// this.streamingAnalyser.maxDecibels = 0;
|
||||||
|
@ -334,6 +348,15 @@ export class AudioEngine extends ((EngineEmitter as unknown) as {
|
||||||
case "master":
|
case "master":
|
||||||
this.streamingAnalyser.getFloatTimeDomainData(this.analysisBuffer);
|
this.streamingAnalyser.getFloatTimeDomainData(this.analysisBuffer);
|
||||||
break;
|
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:
|
default:
|
||||||
throw new Error("can't getLevel " + source);
|
throw new Error("can't getLevel " + source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { RootState } from "../rootReducer";
|
||||||
import * as MixerState from "../mixer/state";
|
import * as MixerState from "../mixer/state";
|
||||||
import { secToHHMM, timestampToHHMM } from "../lib/utils";
|
import { secToHHMM, timestampToHHMM } from "../lib/utils";
|
||||||
import ProModeButtons from "./ProModeButtons";
|
import ProModeButtons from "./ProModeButtons";
|
||||||
|
import { VUMeter } from "../optionsMenu/helpers/VUMeter";
|
||||||
|
|
||||||
export const USE_REAL_GAIN_VALUE = false;
|
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 proMode = useSelector((state: RootState) => state.settings.proMode);
|
||||||
const dispatch = useDispatch();
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
|
@ -239,6 +253,13 @@ export function Player({ id }: { id: number }) {
|
||||||
Full
|
Full
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{ proMode && <VUMeter
|
||||||
|
className="channel-vu"
|
||||||
|
width={200}
|
||||||
|
height={40}
|
||||||
|
source={VUsource(id)}
|
||||||
|
range={[-40, 0]}
|
||||||
|
/>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue