more calibration and VU diddling

This commit is contained in:
Marks Polakovs 2020-03-30 13:41:56 +02:00
parent c157a656ea
commit c15a1f99df
2 changed files with 55 additions and 30 deletions

View file

@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useRef } from "react";
import Modal from "react-modal";
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "../rootReducer";
@ -7,42 +7,69 @@ import * as MixerState from "./state";
import { VUMeter } from "./VUMeter";
export function MicCalibrationModal() {
const state = useSelector(
(state: RootState) => state.mixer.mic.calibration
);
const state = useSelector((state: RootState) => state.mixer.mic);
const rafRef = useRef<number | null>(null);
const [peak, setPeak] = useState(-Infinity);
const animate = () => {
if (state) {
if (state.calibration) {
const result = MixerState.getMicAnalysis();
console.log(result);
setPeak(result);
requestAnimationFrame(animate);
rafRef.current = requestAnimationFrame(animate);
} else if (rafRef.current !== null) {
cancelAnimationFrame(rafRef.current);
rafRef.current = null;
}
};
useEffect(() => {
requestAnimationFrame(animate);
}, [state]);
if (state.calibration) {
rafRef.current = requestAnimationFrame(animate);
} else if (rafRef.current !== null) {
cancelAnimationFrame(rafRef.current);
rafRef.current = null;
}
}, [state.calibration]);
const dispatch = useDispatch();
return (
<Modal
isOpen={state}
isOpen={state.calibration}
onRequestClose={() => dispatch(MixerState.stopMicCalibration())}
>
{state !== null && (
{state.calibration && (
<>
<b>
Speak into the microphone at a normal volume. Adjust the
gain slider until the bar below is green when you're speaking.
gain slider until the bar below is green when you're
speaking.
</b>
<div>
<VUMeter
width={400}
height={40}
value={peak}
range={[-70, 0]}
greenRange={[-3.5, -1.5]}
greenRange={[-20, -7]}
/>
</div>
<div>
<input
type="range"
min={1 / 10}
max={3}
step={0.05}
value={state.gain}
onChange={e =>
dispatch(
MixerState.setMicLevels({
volume: parseFloat(e.target.value),
gain: parseFloat(e.target.value)
})
)
}
/>
<b>{state.gain.toFixed(1)}</b>
</div>
<button
onClick={() =>
dispatch(MixerState.stopMicCalibration())

View file

@ -14,8 +14,6 @@ import { RootState } from "../rootReducer";
import WaveSurfer from "wavesurfer.js";
import { createLoudnessMeasurement } from "./loudness";
console.log(Between);
const audioContext = new AudioContext();
const wavesurfers: WaveSurfer[] = [];
const playerGainTweens: Array<{
@ -283,6 +281,8 @@ const mixerState = createSlice({
export default mixerState.reducer;
export const { setMicLevels } = mixerState.actions;
export const load = (
player: number,
item: PlanItem | Track | AuxItem
@ -649,8 +649,6 @@ export const openMicrophone = (micID: string): AppThunk => async (
.connect(micGain)
.connect(micCompressor)
.connect(finalCompressor);
// TODO remove this
micCompressor.connect(audioContext.destination);
dispatch(mixerState.actions.micOpen(micID));
};
@ -689,6 +687,7 @@ export const startMicCalibration = (): AppThunk => async (
input = micCompressor!;
}
analyser = audioContext.createAnalyser();
analyser.fftSize = 8192;
input.connect(analyser);
};
@ -701,15 +700,14 @@ export function getMicAnalysis() {
if (!float) {
float = new Float32Array(analyser.fftSize);
}
analyser.getFloatFrequencyData(float);
let peak = -Infinity;
analyser.getFloatTimeDomainData(float);
let sumOfSquares = 0;
let peak = 0;
for (let i = 0; i < float.length; i++) {
const dbFS = float[i];
if (dbFS > peak && dbFS !== 0) {
peak = dbFS;
peak = Math.max(peak, float[i]**2)
sumOfSquares += float[i]**2;
}
}
return peak;
return 10 * Math.log10(peak);
}
export const stopMicCalibration = (): AppThunk => (dispatch, getState) => {