feat: improve spectrogram pitch mapping and vertical smoothing
This commit is contained in:
@@ -6,6 +6,7 @@ export const SPECTROGRAM_FULL_SEMITONES =
|
||||
SPECTROGRAM_FULL_MAX_MIDI_PITCH - SPECTROGRAM_FULL_MIN_MIDI_PITCH + 1;
|
||||
export const SPECTROGRAM_VISIBLE_SEMITONES =
|
||||
SPECTROGRAM_MAX_MIDI_PITCH - SPECTROGRAM_MIN_MIDI_PITCH + 1;
|
||||
export const SPECTROGRAM_ANALYSIS_RESOLUTION_MULTIPLIER = 2;
|
||||
|
||||
export type SpectrogramHeightResolution = 1 | 3 | 5;
|
||||
|
||||
@@ -19,13 +20,13 @@ export function normalizeSpectrogramHeightResolution(value: unknown): Spectrogra
|
||||
}
|
||||
|
||||
export function getSpectrogramPitchBinCount(
|
||||
resolution: SpectrogramHeightResolution,
|
||||
resolution: number,
|
||||
): number {
|
||||
return SPECTROGRAM_FULL_SEMITONES * resolution;
|
||||
}
|
||||
|
||||
export function getSpectrogramVisibleBinRange(
|
||||
resolution: SpectrogramHeightResolution,
|
||||
resolution: number,
|
||||
): { start: number; end: number } {
|
||||
return {
|
||||
start: (SPECTROGRAM_MIN_MIDI_PITCH - SPECTROGRAM_FULL_MIN_MIDI_PITCH) * resolution,
|
||||
@@ -33,9 +34,15 @@ export function getSpectrogramVisibleBinRange(
|
||||
};
|
||||
}
|
||||
|
||||
export function getSpectrogramAnalysisResolution(
|
||||
resolution: SpectrogramHeightResolution,
|
||||
): number {
|
||||
return resolution * SPECTROGRAM_ANALYSIS_RESOLUTION_MULTIPLIER;
|
||||
}
|
||||
|
||||
export function mapMidiPitchToSpectrogramPosition(
|
||||
midiPitch: number,
|
||||
resolution: SpectrogramHeightResolution,
|
||||
resolution: number,
|
||||
): number | null {
|
||||
const pitchOffset = midiPitch - SPECTROGRAM_FULL_MIN_MIDI_PITCH;
|
||||
if (pitchOffset < 0 || pitchOffset > SPECTROGRAM_FULL_MAX_MIDI_PITCH) {
|
||||
@@ -48,3 +55,21 @@ export function mapMidiPitchToSpectrogramPosition(
|
||||
const maxBin = getSpectrogramPitchBinCount(resolution) - 1;
|
||||
return Math.max(0, Math.min(maxBin, scaled));
|
||||
}
|
||||
|
||||
export function frequencyToMidiPitch(frequency: number): number | null {
|
||||
if (!Number.isFinite(frequency) || frequency <= 0) {
|
||||
return null;
|
||||
}
|
||||
return 69 + 12 * Math.log2(frequency / 440);
|
||||
}
|
||||
|
||||
export function mapFrequencyToSpectrogramPosition(
|
||||
frequency: number,
|
||||
resolution: number,
|
||||
): number | null {
|
||||
const midiPitch = frequencyToMidiPitch(frequency);
|
||||
if (midiPitch === null) {
|
||||
return null;
|
||||
}
|
||||
return mapMidiPitchToSpectrogramPosition(midiPitch, resolution);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user