thetwom / Tuner

Tuner app
GNU General Public License v3.0
192 stars 16 forks source link

Too jittery with background noise #72

Open hackerb9 opened 10 months ago

hackerb9 commented 10 months ago

I can't always be in perfectly silent environments when I need to tune. In real world use this app keeps jumping around even when I put Maximum Allowed Background Noise to 1% (see footnote 1).

Proposed solution: Since the background noise is much quieter than the signal, a simple Minimum dB setting should solve the problem.

By the way, another tuner app I tried (see footnote 2) had the same problem initially which makes me wonder if this issue is less noticable on other phones or operating system. I'm using GrapheneOS on a Pixel 6 Pro.


Footnote 1: The slider goes below 1%, but that just seems to make the app not function at all -- maybe it was supposed to handle fractional values in a logarithmic manner but is using integers?


Footnote 2: On the other app, also called just "Tuner", I was able to workaround the issue by setting a Minimum Frequency. It would be nice if this app offered that as well, but only if it would not be too much trouble for the developers.

thetwom commented 10 months ago

Thanks for the report. Good question, if this can be improved.

Firstly: The background noise setting won't help. This is more for quiet environments, that the tuner does not try to detect a tone, when there is only background noise. Setting this to small values will stop the tuner detect tones more and more. 0 means no background noise is allowed, which is of course is never the case. It might be a good idea, not to allow 0, that is actually true.

What might help is "Jump to new pitch". Setting this to larger values will ask the tuner to only show a pitch if it is found repeatedly. A could also increase the "Moving average", but I guess, this will not really solve your problem.

It would of course be nice to make the algorithms more robust. For that it would help to get sound samples for scenarios you are describing. The tuner allows to record such. You can enable "Capture in scientific mode" by e.g. setting it to 5 seconds. If you also enable "scientific mode", you will find a "Capture button" at the bottom of the tuner main screen. When you press this button it will allow you to store the 5s seconds before pressing the button to a file. Maybe you can capture a few files and provide them? They are wav-files, so you can listen to them before sending ...

hackerb9 commented 10 months ago

Here are recordings of two environments with different background noise. The first is silent to most humans. The second one has an audible fan. I also included a plucked tone in both environments for comparison of volume levels.

envnoise.zip

By the way, are you A-weighting the input? I'm noticing now that Tuner is not just latching on to any environmental noise but particularly detecting extremely low tones that I do not perceive as loud. (C#0!)

hackerb9 commented 10 months ago

A minor note (ha ha):

You probably know this, but the Save as Wave feature could use some love. Normally a mic button means "start recording." It is not explained that this one means "save the last five seconds."

It is also awkward that it interrupts to ask for a filename. I'd find it more useful if, by default, every time the mic was pressed Tuner immediately saved to a timestamped or numbered filename with only a small, non-distracting notification. That way the user can focus on the instrument and their task at hand.

Also, if one accidentally enters a filename without a .wav extension, it is not sufficient to merely rename it later to get it to work on Android. Probably best to append .wav automatically.

thetwom commented 10 months ago

Thanks for sending the files so quickly. Maybe I didn't understand you original request incorrectly:

  1. Is the issue, that the tuner jumps around wildly, while having notes plucked?
  2. Or is the issue, that while you are having no notes plucked, the tuner will jump around?

Given your environment files, I would guess, that you are referring to the latter, while I assumed the former.

While the first issue would need to improve the robustness of the tuner, the second issue would need a better way to tell apart if one is currently playing something or not.

No, currently the tuner applies no weighting. But as soon as we clarified your issue and are able to reproduce the issue, it is worth considering if such strategies might help.

Regarding the minor note: You are right, the "capture"-functionality might be not be ideal yet. On the other side, I regard it more as kind of a "hidden feature" to allow providing sound samples if there are issues with tuning. The idea of directly saving a file, when pressing the button to a standard location sounds good. But I have to check if this is possible without asking the user for extra permissions (which I generally try to avoid, since it would seem strange if a tuner asks the user for filesystem access). At the moment, the saving procedure is done by the system, so no extra permissions are required.

hackerb9 commented 10 months ago

The latter. During what I consider silence, the tuner jumps erratically, usually to extremely low frequencies. I think a minimum dB setting would fix it for me.

A-weighting might not be necessary, but if it is, my hazy recollection was that the approximate formula for dB(A) was straightforward if you already have the FFT.

As for the .wav save, I agree completely. One shouldn't spend too much time polishing the user experience of what's essentially an Easter Egg.

thetwom commented 10 months ago

OK, then I was wrong with saying that the background noise option wouldn't help. It was exactly for such scenarios. But obviously it does not help in your case. Did you try to increase "Jump to new pitch"? Especially, when to frequency contents are random and change all the time, this might have a big effect.

I will try to analyse your sound samples a bit. Maybe it indeed contains clear low frequencies. Having minimum dB could of course help, but here the question is, what low dB means and how device-dependent this is. I would prefer having a loudness-independent measure but it might be not so easy to find a good one.

But I am a bit reluctant about A-weighting. In the end it will downrate the low notes, which is not always desired. Also, to my knowledge A-weighting more applies to noise, which might not be exactly the same as when one actually wants to hear the note. As you initially mentioned, it might be better here to limit the lowest allowed pitch directly. But I wonder if there is a better solution.

hackerb9 commented 10 months ago

I increased Jump to new pitch to max (12 results) and it still scrolls the chart Y-axis down to 22 Hz before I can get a good look at what pitch had been detected.

I also tried increasing the Pitch history to max (16.97s), but the chart still zooms in on the latest pitch regardless of what else is in the history.

If the rapid scrolling is not what happens to other people, I wonder if it is something about my OS. My understanding is that Android provides different virtual microphones to applications, not just the raw audio signal. While unlikely, is it possible Tuner is listening to the wrong mic? I don't see any way to change the input in the settings.


A threshold on the lowest detected frequency may be simple but it feels drastic. Sure, I'm not likely to be tuning pipe organs with thirty-two foot Bombardes any time soon, but it would be nice if Tuner would attenuate the lower notes, not discard them.

I'm not sure what the correct solution would be as I'm no sound expert, but I can share the little I do know.

A-weighting is applicable well beyond noise. It is probably the most popular approximation for human perceived "loudness", at least in the US. Although it is an old standard and there are known flaws, it is still widely used by engineers and scientists when human perception of audio is what matters, rather than a physical measurement of the sound pressure level in kilopascals. For example, a noise meter that doesn't take human perception into account would grossly exaggerate the loudness of low-frequencies.

I suggested A-weighting for Tuner because low frequencies would still be allowed in a way that makes sense to people: a 16 Hz fan hum that humans can barely hear would be rejected, but you can still tune a 16 Hz contra-bombarde because it generates the massive sound pressure level needed to be audibly perceptible.

Or, so I believe. I've been wrong before.

thetwom commented 10 months ago

Thanks a lot for your testing and also your ideas.

I increased Jump to new pitch to max (12 results) and it still scrolls the chart Y-axis down to 22 Hz before I can get a good look at what pitch had been detected.

Was worth a try. This is another hint that the signal really contains low frequencies. I am on my way looking closer at the signal, but I guess it will just confirm this suspicion. Question would of course still be how to counteract this ...

it still scrolls the chart Y-axis down to 22 Hz before I can get a good look at what pitch had been detected.

Not really a solution, but you can at least "lock" the history plot by dragging on it. By this, you could at least avoid the scrolling.

If the rapid scrolling is not what happens to other people, I wonder if it is something about my OS. My understanding is that Android provides different virtual microphones to applications, not just the raw audio signal. While unlikely, is it possible Tuner is listening to the wrong mic? I don't see any way to change the input in the settings.

Not sure, how many other people have this problem, since I have no feedback here. I also guess the problem is not so prominent for many instruments, where a tone lasts longer. It is true, there are different options for getting audio data, some which are already processed in some way. There is one alternative option, which could be an option (instead of Mic, using Default, AudioSource). Not sure, if it is worth to try switching in a test version? One could of course also try to check for other physical microphones and let the user choose (as requested by #65). That is currently not implemented.

A-weighting is applicable ...

I did not go too deep into the literature here. But at 30Hz A-weighting will attenuate the signal by ~35dB. That is a factor of 50 the pressure signal gets lowered. Which is clearly a lot. Which does not make it wrong of course. But as you said, there is quite some uncertainty by using it. And while this uncertainty does not matter so much for noise, it most probably will for instruments, playing mainly at these low frequencies. But as said, all this is more my opinion than I have a clear foundation. You might also be right here. I have to test this on some signals and see the influence.

but you can still tune a 16 Hz contra-bombarde because it generates the massive sound pressure level needed to be audibly perceptible

Unfortunately, you will quickly find instruments, where this does not apply so easily. Just take an electric bass, where you want to tune without amplification. But who knows, maybe one could still tune with A-weighting.

In summary, I fear, I cannot give a you a quick solution here. Ways have to be identified, if this can be generally improved, or if we need some extra option (e.g. switching on weighing, or limiting frequencies).

hackerb9 commented 10 months ago

Was worth a try. This is another hint that the signal really contains low frequencies. I am on my way looking closer at the signal, but I guess it will just confirm this suspicion. Question would of course still be how to counteract this ...

I tried looking at the spectrum using Audacity and I got very different results from what Tuner was showing me. I might be doing it wrong, but I didn't see a peak way down at 22Hz. Could there be some math confusion with my processor? Perhaps audio is being used in the wrong floating point format?

it still scrolls the chart Y-axis down to 22 Hz before I can get a good look at what pitch had been detected.

Not really a solution, but you can at least "lock" the history plot by dragging on it. By this, you could at least avoid the scrolling.

Ah! That almost makes it usable. Is there some way to pause capturing? Tapping doesn't work.

I also guess the problem is not so prominent for many instruments, where a tone lasts longer.

True. How is Tuner supposed to behave when a note fades out and silence (noise below the threshold) is detected? Does it freeze the screen on the last known good value? Does it show spurious values (22 Hz) for you, too?

One could of course also try to check for other physical microphones and let the user choose (as requested by #65). That is currently not implemented.

I'm willing to try it if you implement it, but I am dubious that it is the problem. I tested an app that let me use the raw mic and it was extremely quiet. Is it easy to get Tuner to read from a .wav file for testing? Perhaps another hidden Easter Egg?

A-weighting is applicable ...

I did not go too deep into the literature here. But at 30Hz A-weighting will attenuate the signal by ~35dB. That is a factor of 50 the pressure signal gets lowered.

My math is a bit rusty, but I think 30dB = 3B = a factor of 10³ = a factor of 1000. So, 35 dB would be a factor of several thousands.

Lindos1

The Equal Loudness Curves indicate to me that an amplified 30Hz electric bass has to emit over 35 dBSPL more than a 1000Hz flute to sound equally loud. So, as suspicious as it seems, A-weighting appears to be correct.

But as you said, there is quite some uncertainty by using it. And while this uncertainty does not matter so much for noise, it most probably will for instruments, playing mainly at these low frequencies.

My understanding is that A-weighting was designed for music and speech and it actually is worse for noise analysis (it underestimates noise in low and high frequencies).

I have to test this on some signals and see the influence.

Yup. The proof is in the pudding.

Unfortunately, you will quickly find instruments, where this does not apply so easily. Just take an electric bass, where you want to tune without amplification. But who knows, maybe one could still tune with A-weighting.

Good question. My intuition is that dB(A) is supposed to be similar to human hearing. If your bass can be heard without an amp, then it should still have a tunable signal once A-weighted.

In summary, I fear, I cannot give a you a quick solution here. Ways have to be identified, if this can be generally improved, or if we need some extra option (e.g. switching on weighing, or limiting frequencies).

Quick solutions are not expected nor necessary. I just hope you find this problem somewhat interesting.

thetwom commented 10 months ago

I tried looking at the spectrum using Audacity and I got very different results from what Tuner was showing me. I might be doing it wrong, but I didn't see a peak way down at 22Hz. Could there be some math confusion with my processor? Perhaps audio is being used in the wrong floating point format?

It is not enough to look for peaks on a spektrum. For most instruments the notes contain several harmonics (e.g. not only 440Hz for A4, but also 880Hz, 1320Hz, ...). It is even possible that the fundamental frequency has hardly any energy. A more reliable detection algorithm than peaks in the frequency space is autocorrelation. But frequency space is still used for improving the accuracy ...

Ah! That almost makes it usable. Is there some way to pause capturing? Tapping doesn't work.

No, stopping is not possible for the time being.

True. How is Tuner supposed to behave when a note fades out and silence (noise below the threshold) is detected? Does it freeze the screen on the last known good value? Does it show spurious values (22 Hz) for you, too?

Yes, the "history line" will gray out and freeze. But as you say it, it indeed can jump around a lot.

My math is a bit rusty, but I think 30dB = 3B = a factor of 10³ = a factor of 1000. So, 35 dB would be a factor of several thousands.

It's definitely not a factor of several thousands. SPL = 20 log10(p1/p2) <=> p1/p2 = 10^(SPL/20)

Good question. My intuition is that dB(A) is supposed to be similar to human hearing. If your bass can be heard without an amp, then it should still have a tunable signal once A-weighted.

It is definitely not easy to tune a e-bass without amp, even without A-weighting :-). It appears that the signal is too low.

I cannot really judge about your statements about A-weighting, its history and so on. I guess, one would have to get into literature research to understand better the applicability. But in the end, it does not matter so much. If it helps, then its good, otherwise not :-). If it inbetween, we would need an option to enable/disable it. Or one finds a better way ...

hackerb9 commented 10 months ago

Thanks for the math correction. I'm so rusty, I can't even tell how wrong I am. 😀 I think A-weighting is a tool that is not "right", but it is a good enough heuristic that is fast and easy in frequency space.

However, since you're using autocorrelation, not FFTs for pitch detection, I am not sure if it makes sense to even look in to it any further.

(I am reading about autocorrelation now. Are you using the yin algorithm? There are implementations by aubio in C and Tarsos in Java.)

However, now that I know the graph is supposed to turn gray and freeze, I think an even simpler solution would be to figure out why the background in those wav files I attached wasn't rejected as "noise". Can you confirm that env2 and tone2 (before the sound) should be detected as having a 22 Hz signal? Or is the math getting miscalculated on my phone?

thetwom commented 10 months ago

However, since you're using autocorrelation, not FFTs for pitch detection, I am not sure if it makes sense to even look in to it any further.

Autocorrelation can roughly be seen as the FFT of the FFT. So after the first FFT one can actually do A-weighting. I actually tried this some time ago already. But this was more in the context of finding correct notes, not to separate noise from tones. So it is not such a big task to try if it helps for the latter.

(I am reading about autocorrelation now. Are you using the yin algorithm? There are implementations by aubio in C and Tarsos in Java.)

I did read about the yin algorithm some time ago. But either I did not try to understand hard enough or I just did not get the major benefit of this algorithm in the context of pitch detection. (I think they mention weaknesses of using autocorrelation, but this seems not to be an issue here). The current implementation of pitch detection appears to be quite robust and accurate for what I was able to test.

Can you confirm that env2 and tone2 (before the sound) should be detected as having a 22 Hz signal? Or is the math getting miscalculated on my phone?

Sorry, I missed answering this before. This is definitely not a miscalculation by your phone. A quick rough test showed that there is low frequency content in your signal. In the end, it appears that the noise detection algorithm is just not good enough. The current algorithm is extremely simple, obviously too simple. There must be better ways. Up to now, this seemed not be an issue, since nobody was mentioning it but I bet that there are many with the same issue. Just that it is not a problem there due to longer lasting notes ...

thetwom commented 10 months ago

Can I ask, which window size you are using?

hackerb9 commented 10 months ago

Can I ask, which window size you are using?

The default. I had tried changing that and the overlap percent randomly to see if it helped, but it didn't seem to so I reset it. (By the way, thank you for putting in a RESET TO DEFAULT button. Every app should have that.)

A quick rough test showed that there is low frequency content in your signal.

Ah. I wonder what is causing the low frequency notes. A fluke in in my phone's microphone? I have never seen Tuner detect silence as you described (turn gray and freeze), but I should make sure that I've tested it in different environments.

In the end, it appears that the noise detection algorithm is just not good enough.

I wonder if a better noise detection algorithm will also let you tune an unamplified electric bass. If not, I have a wacky idea: use the data from the magnetometers in the phone as an audio signal. I'm presuming that if the phone is close enough to the strings, it will pick up the magnetic perturbations, which may not be true.

thetwom commented 10 months ago

I wonder what is causing the low frequency notes.

It might be just as it is. It appears that your environment noise has quite some now noise content: grafik

But not to forget, that the signal is of course very low. But if you e.g. compare the environments signal to a bass note, you see that the spectrum has indeed very different characteristics. A bass signal has quite some spikes at the different harmonics, while the environment is more concentrated at low frequencies. Now a measure must be find to take this apart. Maybe some easy measure to stop below a certain overall SPL. Or something different. Most probably it will stay a compromise, but this is one can at least let the user choose by providing a setting ...

I wonder if a better noise detection algorithm will also let you tune an unamplified electric bass. If not, I have a wacky idea: use the data from the magnetometers in the phone as an audio signal. I'm presuming that if the phone is close enough to the strings, it will pick up the magnetic perturbations, which may not be true.

:D, not sure about the sampling rate and if the signal can really be detected , but would indeed by funny ...

thetwom commented 10 months ago

The best option which currently comes to my mind is comparing the "energy" of the detected pitch against the overall energy of the signal. It is still a bit difficult. Especially your signal seems to contain prominent peaks at low frequencies. Can you give this version a try: v6.6.0-rc1. In the settings, you will find now the option "Required signal strength". Try turning this up, maybe to 50% or even a bit more.

If this does not help, we could alternatively switch off at a given total signal strength (at the moment it is the ratio of pitch energy to total energy). Or limit the frequency range ...

I am planning to remove the noise option, to make the settings not too many.

thetwom commented 10 months ago

Did you have any chance to test the rc already?

HubbyG commented 9 months ago

Hackerb9 raised an issue of interest to me here.

Downloaded 6.6.0rc1 and was using as is since release (i.e. Ignore noise > 10% and ignore signal < 20%)... just reading the thread more thoroughly, I see you are suggesting trying with ignore sig 50%... Will see if this impacts noise intrusions to measurement and report back.

My instrument is also plucked and so there is a pitch settling period of a few seconds during the decay (time to settle varies depending on octave). I will be curious to see if there is enough signal to continue measuring after these 2-3 seconds with the 50% setting over about 5 octaves (AA-c3)

HubbyG commented 9 months ago

With noise 20% and min sig 30% improvement - not so jittery across the range. 50% min sig looses trace too soon during note decay... Still, a useful addition, will keep with appreciation on any further augmentation forthcoming 🙏🏻

thetwom commented 9 months ago

Thanks a lot for for the testing. I guess, you are talking about the newly introduced "signal strength" option. Increasing this is definitely a compromise as you are describing. I wonder, if there are better options to take a note apart from no note. If you are able to extract sound samples, where you think that it is obvious, that there is no tone, but the tuner still detects one, it might be helpful for finding ideas ...

Or maybe I should introduce settings for the lowest allowed frequency ... not sure yet.

HubbyG commented 9 months ago

Admittedly a windy day here, but, certainly low frequency noise which affects tuning. wav attached

Hope that is useful Byron

17 Dec 2023, 19:21 by @.***:

Thanks a lot for for the testing. I guess, you are talking about the newly introduced "signal strength" option. Increasing this is definitely a compromise as you are describing. I wonder, if there are better options to take a note apart from no note. If you are able to extract sound samples, where you think that it is obvious, that there is no tone, but the tuner still detects one, it might be helpful for finding ideas ...

Or maybe I should introduce settings for the lowest allowed frequency ... not sure yet.

— Reply to this email directly, > view it on GitHub https://github.com/thetwom/Tuner/issues/72#issuecomment-1859256929> , or > unsubscribe https://github.com/notifications/unsubscribe-auth/AK4KQTJDRRTTRLGZYCMSCY3YJ5A5BAVCNFSM6AAAAAA7IF2JS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNJZGI2TMOJSHE> . You are receiving this because you commented.> Message ID: > <thetwom/Tuner/issues/72/1859256929> @> github> .> com>

thetwom commented 9 months ago

Thanks, but it seems that the attached file is missing or was somehow removed ...

HubbyG commented 9 months ago

...Trying again. Merry Christmas 🎅🎄 Ah no, the githib attach file dialog says it doesn't support .wav files. Will try to convert and resend in the new year 🙏🏻

HubbyG commented 9 months ago

Trying as .zip

Byron

22 Dec 2023, 21:30 by @.***:

Thanks, but it seems that the attached file is missing or was somehow removed ...

— Reply to this email directly, > view it on GitHub https://github.com/thetwom/Tuner/issues/72#issuecomment-1868080921> , or > unsubscribe https://github.com/notifications/unsubscribe-auth/AK4KQTMKTWRLOJJFE6MK5KDYKX3XVAVCNFSM6AAAAAA7IF2JS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNRYGA4DAOJSGE> . You are receiving this because you commented.> Message ID: > <thetwom/Tuner/issues/72/1868080921> @> github> .> com>

thetwom commented 9 months ago

Still no success. Maybe it doesn't work per mail?

HubbyG commented 9 months ago

Still no success. Maybe it doesn't work per mail?

tuner-export.wav.zip

Last try - This is that zipped wav direct through github portal. Happy new year 🙏🏻

thetwom commented 9 months ago

finally worked :-). Looks like a 70Hz signal this time. I will see if this helps finding ideas for improvement. Thanks a lot.

thetwom commented 8 months ago

I am starting to wonder, if we should ignore signals based on their absolute levels. Up to now I was trying to avoid this, comparing how strong the pitch signal is compared to the overall sound input. But it appears that one can have very quiet but still clear signals in the background. The tuner will pick them up, but in many cases this is not wanted. I wonder, if users expect a "loudness" threshold, when the tuner should start detecting tones.

What is a bit unfortunate is, that there seems not to be a very obvious loudness level, when it makes sense to start the detection. I compared the provided environment signals to some instrument signals and especially if tuning instruments like an e-bass, the environment is louder. However, maybe this is the relevant setting, users expect ...

thetwom commented 8 months ago

Here is a new test version: v6.6.0-rc3. This introduces a "sensitivity" option and removes "signal strength" and "maximum noise". Compared to the previous options, I moved this more to the top in the settings. Turn the value down to smaller values to avoid reacting to very quiet signals. In my experience, it makes not much sense to go below ~40. Let me know your results, maybe it makes sense to adjust the minimum allowed value a bit ...

HubbyG commented 8 months ago

Many thanks for this.I will try out the new sensitivity control later today and let you know how I get on soon after 👍🏻

HubbyG commented 8 months ago

At the very first try I set the new sensitivity to 65% (somewhere between your lowest recommended 40% & default 95%)... Definitely an improvement in stability for my purposes (by far less jitters) - and I will keep.   Many thanks again :-)  If I notice anything else, will keep in touch.

9 Jan 2024, 14:16 by @.***:

Here is a new test version: > v6.6.0-rc3 https://github.com/thetwom/Tuner/releases/tag/v6.6.0-rc3> . This introduces a "sensitivity" option and removes "signal strength" and "maximum noise". Compared to the previous options, I moved this more to the top in the settings. Turn the value down to smaller values to avoid reacting to very quiet signals. In my experience, it makes not much sense to go below ~40. Let me know your results, maybe it makes sense to adjust the minimum allowed value a bit ...

— Reply to this email directly, > view it on GitHub https://github.com/thetwom/Tuner/issues/72#issuecomment-1883127856> , or > unsubscribe https://github.com/notifications/unsubscribe-auth/AK4KQTN22TQBP7P27474ABTYNVGLRAVCNFSM6AAAAAA7IF2JS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBTGEZDOOBVGY> . You are receiving this because you commented.> Message ID: > <thetwom/Tuner/issues/72/1883127856> @> github> .> com>

thetwom commented 8 months ago

Thanks a lot for the testing. I reckon, this sensitivity option might be the most natural way to adjust the behaviour. I think, I will adapt the bounds a bit to avoid having large ranges of 0-40 where one does not experience any changes and then publish.

thetwom commented 8 months ago

Ok, I adapted available sensitivity range a bit and released v6.6.0. So when you install the new version you have to find a new good setting for you. But I guess it will be at ~50.

Thanks for you support!

hackerb9 commented 5 months ago

Just wanted to say, Thank you. Sensitivity of 50% works well enough for me. Now I can see what the pitch is before it jumps to something else!