Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

demo request #91

Open
ahmadsafi24 opened this issue Nov 26, 2024 · 1 comment
Open

demo request #91

ahmadsafi24 opened this issue Nov 26, 2024 · 1 comment

Comments

@ahmadsafi24
Copy link

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

@swharden
Copy link
Owner

swharden commented Nov 27, 2024

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:

  1. Mapping the FFT frequencies to equal-loudness levels.
  2. Adjusting the FFT power values by the corresponding loudness weights.

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);
    }
}

Explanation:

  1. Frequency Calculation: The function calculates the frequency corresponding to each FFT bin using the formula:

Fi = i * sampleRate / fftSize

  1. Equal-Loudness Weighting: The EqualLoudnessWeight function computes a weight for each frequency based on a simplified approximation of the ISO 226 equal-loudness curve.

  2. Apply Weights: The FFT power values are multiplied by the weights to create the equal-loudness contour.

Usage:

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);

Notes:

  1. This implementation uses a simplified equal-loudness weighting approximation. For a more precise model, consider using detailed equal-loudness curves or lookup tables based on ISO 226 data.
  2. Ensure the FFT values are appropriately scaled (e.g., normalized) before applying the weights.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants