Skip to content

Commit

Permalink
outsource melscale to different file
Browse files Browse the repository at this point in the history
  • Loading branch information
Tarek committed Mar 8, 2024
1 parent 9e5ba88 commit 008c5ff
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 67 deletions.
68 changes: 68 additions & 0 deletions src/lenses/SpectrogramLens/MelScale.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as d3 from 'd3';

interface MelScale {
(value: number): number;
toMelScale(value: number): number;
fromMelScale(frequency: number): number;
domain(): number[];
domain(domain: number[]): MelScale;
range(): number[];
range(range: number[]): MelScale;
copy(): MelScale;
invert(value: number): number;
ticks(count?: number): number[];
tickFormat(count?: number, specifier?: string): (d: number) => string;
}

const melScale = (): MelScale => {
// Create the base log scale
const linearScale = d3.scaleLinear();
const logScale = d3.scaleLog();

// Our custom scale function
const scale: MelScale = ((value: number) => {
return linearScale(value);
}) as MelScale;

scale.toMelScale = (frequency: number): number => {
return 2595 * Math.log10(1 + frequency / 700);
};

scale.fromMelScale = (mel: number): number => {
return 700 * (Math.pow(10, mel / 2595) - 1);
};

// Copy methods from the log scale
// eslint-disable-next-line @typescript-eslint/no-explicit-any
scale.domain = (domain?: number[]): any => {
if (domain === undefined) {
return linearScale.domain().map((d) => scale.toMelScale(d));
}
logScale.domain(domain);
return domain ? (linearScale.domain(domain), scale) : linearScale.domain();
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
scale.range = (range?: number[]): any => {
if (range) logScale.range(range);
return range ? (linearScale.range(range), scale) : linearScale.range();
};
scale.copy = () => {
return melScale().domain(scale.domain()).range(scale.range());
};
scale.invert = (value: number): number => {
return scale.fromMelScale(linearScale.invert(value));
};

scale.ticks = (count?: number): number[] => {
const ticks = logScale.ticks(count).map((val) => {
return scale.toMelScale(val);
});
if (!count) return ticks;

return [ticks[0]].concat(ticks.slice(ticks.length - count, ticks.length));
};

return scale;
};

export default melScale;
72 changes: 5 additions & 67 deletions src/lenses/SpectrogramLens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ColorsState, useColors } from '../../stores/colors';
import { Lens } from '../../types';
import useSetting from '../useSetting';
import MenuBar from './MenuBar';
import melScale from './MelScale';
import { fixWindow, freqType, unitType, amplitudeToDb } from './Spectrogram';

const Container = tw.div`flex flex-col w-full h-full items-stretch justify-center`;
Expand All @@ -25,69 +26,6 @@ interface WebAudio_ extends WebAudio {
const DOMAIN_LOWER_LIMIT = 10;
const FFT_SAMPLES = 1024;

interface MelScale {
(value: number): number;
domain(): number[];
domain(domain: number[]): MelScale;
range(): number[];
range(range: number[]): MelScale;
copy(): MelScale;
invert(value: number): number;
ticks(count?: number): number[];
tickFormat(count?: number, specifier?: string): (d: number) => string;
}

function toMelScale(frequency: number): number {
return 2595 * Math.log10(1 + frequency / 700);
}

function fromMelScale(mel: number): number {
return 700 * (Math.pow(10, mel / 2595) - 1);
}

function melScale(): MelScale {
// Create the base log scale
const linearScale = d3.scaleLinear();
const logScale = d3.scaleLog();

// Our custom scale function
const scale: MelScale = ((value: number) => {
return linearScale(value);
}) as MelScale;

// Copy methods from the log scale
// eslint-disable-next-line @typescript-eslint/no-explicit-any
scale.domain = (domain?: number[]): any => {
if (domain === undefined) {
return linearScale.domain().map((d) => toMelScale(d));
}
logScale.domain(domain);
return domain ? (linearScale.domain(domain), scale) : linearScale.domain();
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
scale.range = (range?: number[]): any => {
if (range) logScale.range(range);
return range ? (linearScale.range(range), scale) : linearScale.range();
};
scale.copy = () => {
return melScale().domain(scale.domain()).range(scale.range());
};
scale.invert = (value: number): number => {
return fromMelScale(linearScale.invert(value));
};

scale.ticks = (count?: number): number[] => {
const ticks = logScale.ticks(count).map((val) => {
return toMelScale(val);
});
if (!count) return ticks;

return [ticks[0]].concat(ticks.slice(ticks.length - count, ticks.length));
};

return scale;
}

/*
* Redraws the scale for resized spectrogram
*/
Expand Down Expand Up @@ -138,8 +76,8 @@ const drawScale = (
.ticks(numTicks)
.tickFormat(
(x: number) =>
`${freqType(fromMelScale(x).valueOf()).toFixed(1)} ${unitType(
fromMelScale(x).valueOf()
`${freqType(scale.fromMelScale(x).valueOf()).toFixed(1)} ${unitType(
scale.fromMelScale(x).valueOf()
)}`
);
} else {
Expand Down Expand Up @@ -352,7 +290,7 @@ const SpectrogramLens: Lens = ({ columns, urls, values }) => {
value = heightScale(height - y);
} else if (freqScale === 'mel') {
const scaleFunc = melScale()
.domain([DOMAIN_LOWER_LIMIT, toMelScale(upperLimit)])
.domain([DOMAIN_LOWER_LIMIT, melScale().toMelScale(upperLimit)])
.range(range);
heightScale = d3.scaleLinear([0, upperLimit], [0, FFT_SAMPLES / 2]);
value = heightScale(scaleFunc.invert(height - y));
Expand Down Expand Up @@ -475,7 +413,7 @@ const SpectrogramLens: Lens = ({ columns, urls, values }) => {

const domain: [number, number] = [
DOMAIN_LOWER_LIMIT,
toMelScale(upperLimit),
melScale().toMelScale(upperLimit),
];
const range: [number, number] = [0, height];

Expand Down

0 comments on commit 008c5ff

Please sign in to comment.