Skip to content

Commit

Permalink
Merge pull request #46 from bananu7/gain-over-1.0
Browse files Browse the repository at this point in the history
Gain over 1.0
  • Loading branch information
bananu7 authored Apr 4, 2024
2 parents 7478518 + 556e2bb commit 4e143a0
Show file tree
Hide file tree
Showing 11 changed files with 2,378 additions and 12 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ jobs:

- name: Run TypeScript
run: npx tsc

- name: Run tests
run: npm run test
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"test": "vitest",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"timingsrc":"^1.4.8"
"timingsrc": "^1.4.8"
},
"devDependencies": {
"@types/react": "^18.2.15",
Expand All @@ -24,6 +25,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"typescript": "^5.0.2",
"vite": "^4.4.5"
"vite": "^4.4.5",
"vitest": "^1.4.0"
}
}
65 changes: 65 additions & 0 deletions public/fader.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/audio/util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { expect, test } from 'vitest'
import { faderPosToDb } from '../audio/util'

const faderMidPoint = 80;

test('fader pos is 0dB at midpoint', () => {
expect(faderPosToDb(faderMidPoint)).toBe(0);
})

test('fader pos is +10dB at max', () => {
expect(faderPosToDb(100)).toBe(10);
})
15 changes: 15 additions & 0 deletions src/audio/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type Decibels = number;

export function dbToGain(db: Decibels): number {
return Math.pow(10, (db / 20));
}

export function faderPosToDb(pos: number): Decibels {
// TODO: parametrize those properly
// 80 is at 0dB
pos -= 80;
// each step is 0.5dB
pos /= 2;

return pos;
}
9 changes: 7 additions & 2 deletions src/components/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ChannelController } from '../audio'
import { Fader } from './Fader'
import { MuteButton } from './MuteButton'
import { Meter } from './Meter'
import { dbToGain, faderPosToDb } from '../audio/util'
import './Channel.css'

export type AudioStatus = "ok" | "warning" | "error";
Expand All @@ -16,7 +17,7 @@ export type ChannelProps = {

export function Channel(props: ChannelProps) {
const [muted, setMuted] = useState(false);
const [volume, setVolumeState] = useState(100);
const [volume, setVolumeState] = useState(80);

const muteClick = useCallback(() => {
setMuted(m => {
Expand All @@ -27,7 +28,11 @@ export function Channel(props: ChannelProps) {

const setVolume = useCallback((vol: number) => {
setVolumeState(vol);
props.controller.setGain(vol / 100);

const db = faderPosToDb(vol);
const gain = dbToGain(db);

props.controller.setGain(gain);
}, [props.controller]);

const statusClass = {'ok':'toggledGreen', 'warning':'toggledYellow', 'error':'toggledRed'}[props.status];
Expand Down
3 changes: 3 additions & 0 deletions src/components/Fader.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.fader {
background-image: url("fader.svg");
}
11 changes: 7 additions & 4 deletions src/components/Fader.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { useCallback, ChangeEvent, WheelEvent } from 'react'
import './Fader.css'

export type FaderProps = {
value: number,
setValue: (v: number) => void,
color?: "none" | "red" | "blue";
}

const steps = 100;

export function Fader(props: FaderProps) {
const onChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
const vol = Number(e.target.value);
props.setValue(vol);
}, [props.setValue]);

const wheelHandler = useCallback((e: WheelEvent<HTMLDivElement>) => {
const delta = e.deltaY / 100 * 2;
const delta = e.deltaY / steps * 2;

if ((e.deltaY < 0 && props.value < 100) ||
if ((e.deltaY < 0 && props.value < steps) ||
(e.deltaY > 0 && props.value > 0))
{
let newVal = props.value - delta;
newVal = newVal < 0 ? 0 : newVal;
newVal = newVal > 100 ? 100 : newVal;
newVal = newVal > steps ? steps : newVal;
props.setValue(newVal);
}
}, [props.value]);
Expand All @@ -29,7 +32,7 @@ export function Fader(props: FaderProps) {

return (
<div className={className} onWheel={wheelHandler}>
<input type="range" value={props.value} onChange={onChange}></input>
<input type="range" max={steps} value={props.value} onChange={onChange}></input>
</div>
);
}
9 changes: 7 additions & 2 deletions src/components/FxChannel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { Fader } from './Fader'
import { MuteButton } from './MuteButton'
import { Meter } from './Meter'
import { SimpleChannelController } from '../audio'
import { dbToGain, faderPosToDb } from '../audio/util'

export type FxChannelProps = {
controller: SimpleChannelController,
}

export function FxChannel(props: FxChannelProps) {
const [muted, setMuted] = useState(false);
const [volume, setVolumeState] = useState(100);
const [volume, setVolumeState] = useState(80);
const muteClick = useCallback(() => {
setMuted(m => {
props.controller.setMute(!m);
Expand All @@ -19,7 +20,11 @@ export function FxChannel(props: FxChannelProps) {
}, [props.controller.setMute]);
const setVolume = useCallback((vol: number) => {
setVolumeState(vol);
props.controller.setGain(vol / 100);

const db = faderPosToDb(vol);
const gain = dbToGain(db);

props.controller.setGain(gain);
}, [props.controller]);

const name = "FX";
Expand Down
9 changes: 7 additions & 2 deletions src/components/MasterChannel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { Fader } from './Fader'
import { MuteButton } from './MuteButton'
import { Meter } from './Meter'
import { SimpleChannelController } from '../audio'
import { dbToGain, faderPosToDb } from '../audio/util'

export type MasterChannelProps = {
controller: SimpleChannelController,
}

export function MasterChannel(props: MasterChannelProps) {
const [muted, setMuted] = useState(false);
const [volume, setVolumeState] = useState(100);
const [volume, setVolumeState] = useState(80);
const muteClick = useCallback(() => {
setMuted(m => {
props.controller.setMute(!m);
Expand All @@ -19,7 +20,11 @@ export function MasterChannel(props: MasterChannelProps) {
}, [props.controller.setMute]);
const setVolume = useCallback((vol: number) => {
setVolumeState(vol);
props.controller.setGain(vol / 100);

const db = faderPosToDb(vol);
const gain = dbToGain(db);

props.controller.setGain(gain);
}, [props.controller]);

const name = "MASTER";
Expand Down
Loading

0 comments on commit 4e143a0

Please sign in to comment.