tabahi / formantanalyzer.js

Extract formant features such as frequency, power, energy, and bandwidth of formants at syllable or word level from audio sources in a web browser using WebAudio API.
Apache License 2.0
28 stars 4 forks source link

Formants' frequencies passed to the callback function #3

Closed alexander-lazarin closed 1 week ago

alexander-lazarin commented 1 week ago

Hi! Quick question. When I choose the output level 4 (Segment Formants), I can see reasonable values for the formants' frequencies in the canvas. However, the frequencies passed to the callback function in the features array seem to be rather low. For my schwa, they are on the order of 17/40/60. I was wondering why this happens and how to get the actual values in Hz

tabahi commented 1 week ago

You are probably getting Mel filter's indices. You can convert to Hz by using a Mel-to-Hz conversion formula. It might not be completely accurate as each filter bank has different Hz range from 10Hz to 250Hz. It's better to convert the mid-point of the whole range, for example if you want to convert 60 (the raw output you are getting), then convert as: mels2Hz(60.5). I have forgotten if I already have a method to do this in the code, so here it is:

You will need the Hz value range (default f_min: 50, f_min: 4000), and the total number of bins (N_mel_bins: 128)

let f_min = 50;
let f_max = 4000;
let N_mel_bins = 128;

function mels2Hz(mels) {
  return 700 * (Math.exp(mels/ 1127) - 1);
}

function Hz2mels(hertz) {
  return 1127 * Math.log(1 + hertz/700);
}

// convert the Hz low, high and delta to Mel:
let lowM = Hz2mels(f_min); //50
let highM = Hz2mels(f_max); //4000
let delMel = ((highM - lowM) / (parseInt(N_mel_bins)+1));

let i = 60.5;
let mel_bin_Hz = mels2Hz(lowM + (i * delMel));  //between lowM and highM.

console.log(i,"-->", mel_bin_Hz); // 60.5 --> 1073.6390730047

Let me know if that doesn't give you the right frequency then I will have a deeper look into it.

alexander-lazarin commented 1 week ago

Thank you for such a fast and detailed response! Here's what I'm getting in my latest experiment:

  1. Value from features == 16 mels2Hz(lowM + (16.5 * delMel)) ~ 248 Value in the chart ~179

  2. Value from features == 49 mels2Hz(lowM + (49.5 * delMel)) ~ 816 Value in the chart ~508

  3. Value from features == 72 mels2Hz(lowM + (72.5 * delMel)) ~ 1403 Value in the chart ~833

tabahi commented 1 week ago

Sorry, I can't figure out what's wrong here. Can you check if you are using the default settings?

spec_type: 1, output_level: 4, f_min: 50, f_max: 4000, N_fft_bins: 256, N_mel_bins: 128,

alexander-lazarin commented 1 week ago

Thank you! You were right, I messed with the defaults. Now everything works as expected. The transformed values from features match the frequencies in the chart