Skip to content

Commit

Permalink
Merge pull request #26 from hemit-s/jat-78
Browse files Browse the repository at this point in the history
JAT-78 Sort and animate frequency bands
  • Loading branch information
xenown authored Oct 25, 2022
2 parents a08b75b + 0e510b7 commit 2eee62e
Show file tree
Hide file tree
Showing 17 changed files with 481 additions and 211 deletions.
37 changes: 35 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.3.0",
"regedit": "^5.1.1"
"regedit": "^5.1.1",
"uid": "^2.0.0"
},
"devDependencies": {
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.6",
Expand Down Expand Up @@ -269,4 +270,4 @@
],
"logLevel": "quiet"
}
}
}
2 changes: 1 addition & 1 deletion release/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aqua",
"version": "0.0.8",
"version": "1.0.0",
"description": "An audio equalizer app",
"license": "MIT",
"author": {
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/unit_tests/common/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DEFAULT_STATE } from 'common/constants';
import { getDefaultState } from 'common/constants';
import { computeAvgFreq, roundToPrecision } from 'common/utils';

describe('utils', () => {
Expand All @@ -16,7 +16,7 @@ describe('utils', () => {
});

describe('computeAvgFreq', () => {
const filters = [...DEFAULT_STATE.filters];
const filters = [...getDefaultState().filters];
it('should compute average of first filter and min frequency for index 0', () => {
expect(computeAvgFreq(filters, 0)).toBe(6);
});
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/utils/mockAquaProvider.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { DEFAULT_STATE } from 'common/constants';
import { getDefaultState } from 'common/constants';
import { ErrorDescription } from 'common/errors';
import { FilterAction, IAquaContext } from 'renderer/utils/AquaContext';

const DEFAULT_STATE = getDefaultState();

const defaultAquaContext: IAquaContext = {
isLoading: false,
globalError: undefined,
Expand Down
36 changes: 22 additions & 14 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/** ----- Application Constants ----- */

import { uid } from 'uid';

export const MAX_GAIN = 30;
export const MIN_GAIN = -30;

Expand Down Expand Up @@ -46,6 +48,7 @@ export const WINDOW_HEIGHT_EXPANDED = 1036;
/** ----- Application Interfaces ----- */

export interface IFilter {
id: string;
frequency: number;
gain: number;
type: FilterTypeEnum;
Expand All @@ -66,26 +69,31 @@ const FIXED_FREQUENCIES = [
32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000,
];

export const DEFAULT_FILTER: IFilter = {
const DEFAULT_FILTER_TEMPLATE = {
frequency: 1000,
gain: 0,
quality: 1,
type: FilterTypeEnum.PK,
};

const DEFAULT_FILTERS: IFilter[] = FIXED_FREQUENCIES.map((f) => {
export const getDefaultFilter = () => {
return {
id: uid(8),
...DEFAULT_FILTER_TEMPLATE,
};
};

const getDefaultFilters = (): IFilter[] =>
FIXED_FREQUENCIES.map((f) => {
return { ...getDefaultFilter(), frequency: f };
});

export const getDefaultState = (): IState => {
return {
frequency: f,
gain: 0,
quality: 1,
type: FilterTypeEnum.PK,
isEnabled: true,
isAutoPreAmpOn: true,
isGraphViewOn: false,
preAmp: 0,
filters: getDefaultFilters(),
};
});

export const DEFAULT_STATE: IState = {
isEnabled: true,
isAutoPreAmpOn: true,
isGraphViewOn: false,
preAmp: 0,
filters: DEFAULT_FILTERS,
};
9 changes: 3 additions & 6 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ export const roundToPrecision = (value: number, precision: number) => {
return Math.round(value * precisionFactor) / precisionFactor;
};

export const computeAvgFreq = (filters: IFilter[], insertIndex: number) => {
const lo =
insertIndex === 0 ? MIN_FREQUENCY : filters[insertIndex - 1].frequency;
export const computeAvgFreq = (filters: IFilter[], index: number) => {
const lo = index === 0 ? MIN_FREQUENCY : filters[index - 1].frequency;
const hi =
insertIndex === filters.length
? MAX_FREQUENCY
: filters[insertIndex].frequency;
index === filters.length ? MAX_FREQUENCY : filters[index].frequency;
const exponent = (Math.log10(lo) + Math.log10(hi)) / 2;
return roundToPrecision(10 ** exponent, 0);
};
4 changes: 2 additions & 2 deletions src/main/flush.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'fs';
import path from 'path';
import { DEFAULT_STATE, IState } from '../common/constants';
import { getDefaultState, IState } from '../common/constants';

export const stateToString = (state: IState) => {
if (!state.isEnabled) {
Expand Down Expand Up @@ -49,7 +49,7 @@ export const fetchSettings = () => {
return JSON.parse(content) as IState;
} catch (ex) {
// if unable to fetch the state, use a default one
return DEFAULT_STATE;
return getDefaultState();
}
};

Expand Down
34 changes: 24 additions & 10 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { app, BrowserWindow, ipcMain, shell } from 'electron';
import log from 'electron-log';
import { autoUpdater } from 'electron-updater';
import path from 'path';
import { uid } from 'uid';
import {
checkConfigFile,
fetchSettings,
Expand Down Expand Up @@ -41,6 +42,7 @@ import {
import { ErrorCode } from '../common/errors';
import { computeAvgFreq } from '../common/utils';
import { TSuccess, TError } from '../renderer/utils/equalizerApi';
import { sortHelper } from '../renderer/utils/utils';

export default class AppUpdater {
constructor() {
Expand Down Expand Up @@ -103,9 +105,10 @@ const updateConfigPath = async (
return true;
};

const handleUpdate = async (
const handleUpdateHelper = async <T>(
event: Electron.IpcMainEvent,
channel: ChannelEnum | string
channel: ChannelEnum | string,
response: T
) => {
// Check whether EqualizerAPO is installed every time a change is made
const isInstalled = await isEqualizerAPOInstalled();
Expand All @@ -123,13 +126,20 @@ const handleUpdate = async (
}

// Return a success message of undefined
const reply: TSuccess<void> = { result: undefined };
const reply: TSuccess<T> = { result: response };
event.reply(channel, reply);

// Flush changes to our local state file after informing UI that the changes have been applied
save(state);
};

const handleUpdate = async (
event: Electron.IpcMainEvent,
channel: ChannelEnum | string
) => {
return handleUpdateHelper<void>(event, channel, undefined);
};

ipcMain.on(ChannelEnum.HEALTH_CHECK, async (event) => {
const channel = ChannelEnum.HEALTH_CHECK;
const res = await updateConfigPath(event, channel);
Expand Down Expand Up @@ -352,13 +362,17 @@ ipcMain.on(ChannelEnum.ADD_FILTER, async (event, arg) => {
}

const frequency = computeAvgFreq(state.filters, insertIndex);
state.filters.splice(insertIndex, 0, {
frequency,
gain: 0,
quality: 1,
type: FilterTypeEnum.PK,
});
await handleUpdate(event, channel);
const filterId = uid(8);
state.filters
.splice(insertIndex, 0, {
id: filterId,
frequency,
gain: 0,
quality: 1,
type: FilterTypeEnum.PK,
})
.sort(sortHelper);
await handleUpdateHelper(event, channel, filterId);
});

ipcMain.on(ChannelEnum.REMOVE_FILTER, async (event, arg) => {
Expand Down
29 changes: 11 additions & 18 deletions src/renderer/MainContent.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { createRef, Fragment } from 'react';
import { MAX_NUM_FILTERS, MIN_NUM_FILTERS } from 'common/constants';
import FrequencyBand from './components/FrequencyBand';
import { useAquaContext } from './utils/AquaContext';
import './styles/MainContent.scss';
import AddSliderDivider from './components/AddSliderDivider';
import SortWrapper from './SortWrapper';

const MainContent = () => {
const { filters } = useAquaContext();

const wrapperRef = createRef<HTMLDivElement>();
return (
<div className="center mainContent">
<div className="col center bandLabel">
Expand All @@ -20,36 +22,27 @@ const MainContent = () => {
<span className="rowLabel">Gain (dB)</span>
<span className="rowLabel">Quality</span>
</div>
<div className="bands row center">
<div ref={wrapperRef} className="bands row center">
<AddSliderDivider
sliderIndex={-1}
isMaxSliderCount={filters.length >= MAX_NUM_FILTERS}
// eslint-disable-next-line react/no-array-index-key
key={`add-slider-${-1}`}
/>
{filters
.flatMap((filter, sliderIndex) => [
{ filter, sliderIndex },
{ sliderIndex },
])
.map(({ filter, sliderIndex }) =>
filter ? (
<SortWrapper wrapperRef={wrapperRef}>
{filters.map((filter, sliderIndex) => (
<Fragment key={`slider-${filter.id}`}>
<FrequencyBand
sliderIndex={sliderIndex}
filter={filter}
isMinSliderCount={filters.length <= MIN_NUM_FILTERS}
// eslint-disable-next-line react/no-array-index-key
key={`slider-${sliderIndex}`}
ref={createRef()}
/>
) : (
<AddSliderDivider
sliderIndex={sliderIndex}
isMaxSliderCount={filters.length >= MAX_NUM_FILTERS}
// eslint-disable-next-line react/no-array-index-key
key={`add-slider-${sliderIndex}`}
/>
)
)}
</Fragment>
))}
</SortWrapper>
</div>
</div>
);
Expand Down
Loading

0 comments on commit 2eee62e

Please sign in to comment.