nakakq / AudioPitchEstimatorForUnity

A simple real-time pitch estimator for Unity
The Unlicense
30 stars 1 forks source link

Above Max Frequency #1

Open Kidkiwi opened 1 year ago

Kidkiwi commented 1 year ago

Hi there,

If you use https://www.szynalski.com/tone-generator/ and set it to square mode and set the frequency ABOVE the max frequency set in unity, suddenly everything goes weird. The reported frequency is all over the place, compared when you set it just below max frequency its almost perfect. Is there any advice here on why or how to fix?

Thanks!

nakakq commented 1 year ago

Thank you for letting me know!

There is no warranty if the input frequency exceed the FrequencyMax parameter. It is characteristics of the detection algorithm (SRH method) in my opinion.

I intended that the FrequencyMax parameter means possible upper bound of input frequency. For example, if your voice is ranged between 40–400 Hz, you should set FrequencyMax as above 400.

By the way: SRH method is suitable for estimating the vocal pitch and will get worse for square waves. SRH detects the pitch using harmonics information, but square waves lack even harmonics. (I tried to reproduce your procedure, but it fails to estimate on square wave mode even if the frequency below max frequency....)

Kidkiwi commented 1 year ago

Hi there.

Thanks for getting back to me.

Is there a way to if frequency goes above or below maximum/minimum to just clamp it to those values for a safe result instead?

Square wave is very accurate when it's between the frequency min and max, but how would you suggest we test it otherwise? The other waves we didn't get any accurate results.

Thank you!

On Sun, 8 Oct 2023, 6:51 pm nakak, @.***> wrote:

Thank you for letting me know!

There is no warranty if the input frequency exceed the FrequencyMax parameter. It is characteristics of the detection algorithm (SRH method) in my opinion.

I intended that the FrequencyMax parameter means possible upper bound of input frequency. For example, if your voice is ranged between 40–400 Hz, you should set FrequencyMax as above 400.

By the way: SRH method is suitable for estimating the vocal pitch and will get worse for square waves. SRH detects the pitch using harmonics information, but square waves lack even harmonics. (I tried to reproduce your procedure, but it fails to estimate on square wave mode even if the frequency below max frequency....)

— Reply to this email directly, view it on GitHub https://github.com/nakakq/AudioPitchEstimatorForUnity/issues/1#issuecomment-1751929763, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJFEGB27I6TLKO4M2ANBBNDX6I5PRAVCNFSM6AAAAAA5TOWY3SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJRHEZDSNZWGM . You are receiving this because you authored the thread.Message ID: @.***>

nakakq commented 1 year ago

Is there a way to if frequency goes above or below maximum/minimum to just clamp it to those values for a safe result instead?

Unfortunately no, because of limitation of the algorithm. I don't have any idea to ensure out-of-range safety at the moment. Many other estimators will also produce unreliable results when you input out-of-range frequency.

A possible simple solution is post-processing like this:

  1. Set min&max frequency with enough wide range.
  2. Clamp the estimated frequency.

Square wave is very accurate when it's between the frequency min and max, but how would you suggest we test it otherwise? The other waves we didn't get any accurate results.

I recommend to use sawtooth wave or singing vocal. They contain enough harmonics. So it's weird for me that only square wave achieves accurate result. Have you tried Assets/Examples/Example2 scene (which is microphone example) without any modifications in this repository?

Kidkiwi commented 1 year ago

Thanks for your reply.

  1. Clamp the estimated frequency.

How would I do this? I've tried averaging out the frequency over a couple of frames, and then removing outliers, but when you go above the set maximum, it drops back down to a new frequency, so you can't really clamp it to a max or minimum because when you break the minimum or maximum, the estimator returns a result within range.

Thanks

On Sun, Oct 8, 2023 at 10:23 PM nakak @.***> wrote:

Is there a way to if frequency goes above or below maximum/minimum to just clamp it to those values for a safe result instead?

Unfortunately no, because of limitation of the algorithm. I don't have any idea to ensure out-of-range safety at the moment. Many other estimators will also produce unreliable results when you input out-of-range frequency.

A possible simple solution is post-processing like this:

  1. Set min&max frequency with enough wide range.
  2. Clamp the estimated frequency.

Square wave is very accurate when it's between the frequency min and max, but how would you suggest we test it otherwise? The other waves we didn't get any accurate results.

I recommend to use sawtooth wave or singing vocal. They contain enough harmonics. So it's weird for me that only square wave achieves accurate result. Have you tried Assets/Examples/Example2 scene (which is microphone example) without any modifications in this repository?

— Reply to this email directly, view it on GitHub https://github.com/nakakq/AudioPitchEstimatorForUnity/issues/1#issuecomment-1751974365, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJFEGB2UGRZ2DSHI2ADY4ETX6JWJRAVCNFSM6AAAAAA5TOWY3SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJRHE3TIMZWGU . You are receiving this because you authored the thread.Message ID: @.***>

nakakq commented 1 year ago

My suggestion in the last reply was combination of both of 1 and 2, not just only 2. Here is a pseudo code:

estimator = this.GetComponent<AudioPitchEstimator>();

// 1. Set min and max frequency with enough wide range.
estimator.frequencyMin = 20;    // input will not be lower than this frequency, for example 20 here
estimator.frequencyMax = 10000; // input will not be higher than this frequency, for example 10000 here

float frequency = estimator.Estimate(audioSource);

// 2. Clamp the estimated frequency.
if (!float.IsNaN(frequency))
{
    frequency = Mathf.Clamp(frequency, 110, 440);  // estimated frequency will be clamped within [110, 440]
}

This is a “simple and stupid” solution. I hope it will fit your situation, but this approach may not work properly in some situations. For example, setting too distant min/max can produce unstable results. To overcome this problem, I should improve tracking method in the code. Perhaps it’s time to implement richer tracking algorithms :)

Kidkiwi commented 1 year ago

I tried that already, the problem was if you inputted a frequency above the max (440), the estimate(audiosource) would start returning values way less than the max frequency. So the clamping didn't work.

It might be time for more advanced tracking! Haha. If you did that. I would really appreciate it 😄

On Mon, 9 Oct 2023, 6:25 pm nakak, @.***> wrote:

My suggestion in the last reply was combination of both of 1 and 2, not just only 2. Here is a pseudo code:

estimator = this.GetComponent(); // 1. Set min and max frequency with enough wide range. estimator.frequencyMin = 20; // input will not be lower than this frequency, for example 20 here estimator.frequencyMax = 10000; // input will not be higher than this frequency, for example 10000 here float frequency = estimator.Estimate(audioSource); // 2. Clamp the estimated frequency.if (!float.IsNaN(frequency)){ frequency = Mathf.Clamp(frequency, 110, 440); // estimated frequency will be clamped within [110, 440]}

This is a “simple and stupid” solution. I hope it will fit your situation, but this approach may not work properly in some situations. For example, setting too distant min/max can produce unstable results. To overcome this problem, I should improve tracking method in the code. Perhaps it’s time to implement richer tracking algorithms :)

— Reply to this email directly, view it on GitHub https://github.com/nakakq/AudioPitchEstimatorForUnity/issues/1#issuecomment-1752364602, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJFEGB5XEEE6HJLRF6H46U3X6ODENAVCNFSM6AAAAAA5TOWY3SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJSGM3DINRQGI . You are receiving this because you authored the thread.Message ID: @.***>