Open ahmadsafi24 opened 1 day ago
Hi @ahmadsafi24, thank you for this question! It may be sufficient to document how to convert FFT output to equal loudness curve, and not require code change to the FFTsharp library to achieve this goal.
I am currently travelling and am writing from a smartphone so I haven't tested this, but what do you think about the strategy recommended by ChatGPT?
I have a C# function that returns the FFT power spectrum of an audio waveform. How do I convert these values to create an equal-loudness contour? Write a single function that takes the FFT values and returns the contour.
To convert FFT power spectrum values into an equal-loudness contour, you need to apply the equal-loudness weighting based on ISO 226:2003 or another reference that models the frequency-dependent sensitivity of human hearing. This process involves:
Here's a C# function to apply equal-loudness weighting:
using System;
using System.Linq;
public static class AudioProcessing
{
public static double[] ApplyEqualLoudnessContour(double[] fftValues, double sampleRate, int fftSize)
{
// Step 1: Calculate the frequencies corresponding to each FFT bin
double[] frequencies = Enumerable.Range(0, fftValues.Length)
.Select(i => i * sampleRate / fftSize)
.ToArray();
// Step 2: Get equal-loudness weights using an approximate ISO 226 model
double[] weights = frequencies.Select(f => EqualLoudnessWeight(f)).ToArray();
// Step 3: Apply weights to FFT values
double[] adjustedValues = fftValues.Zip(weights, (fft, weight) => fft * weight).ToArray();
return adjustedValues;
}
private static double EqualLoudnessWeight(double frequency)
{
if (frequency <= 0)
return 0;
// Approximate implementation of ISO 226 equal-loudness contours (A-weighting-like)
// Use constants and equations specific to the model
double f2 = frequency * frequency;
double f4 = f2 * f2;
// Empirical formula for A-weighting
double r = Math.Pow(12200 * 12200 * f4, 2);
double numerator = r;
double denominator = ((f2 + 20.6 * 20.6) * Math.Sqrt((f2 + 107.7 * 107.7) * (f2 + 737.9 * 737.9)) * (f2 + 12200 * 12200));
double aw = numerator / denominator;
// Scale to human-perceptible range
return Math.Pow(10, aw / 20);
}
}
Fi = i * sampleRate / fftSize
Equal-Loudness Weighting: The EqualLoudnessWeight
function computes a weight for each frequency based on a simplified approximation of the ISO 226 equal-loudness curve.
Apply Weights: The FFT power values are multiplied by the weights to create the equal-loudness contour.
double[] fftValues = ...; // Your FFT power spectrum values
double sampleRate = 44100; // For example, 44.1 kHz
int fftSize = 1024; // FFT size
double[] equalLoudnessContour = AudioProcessing.ApplyEqualLoudnessContour(fftValues, sampleRate, fftSize);
The FFT spectrum in the demo example doesn't resemble a realistic frequency spectrum. Is it possible to visualize audio similar to the FL Studio Parametric EQ, considering a logarithmic x-scale and the equal-loudness contour? [https://en.m.wikipedia.org/wiki/Equal-loudness_contour]()