Openvario / variod

Daemon for autonomous e-vario
4 stars 8 forks source link

Clicks and Pops #33

Closed hpmax closed 3 years ago

hpmax commented 3 years ago

The audio amplifier on my OV died. I replaced it and found that you'd occasionally hear clicks and pops, typically at the "end" of a tone. I was speaking to Stefan and he said he believed it was a software issue. I suspect he may be correct. Looking at the code, it appears the output goes to zero immediately upon going mute or being within the deadband. I may be misreading the code, but I would think it would be better to keep the output going until the output nears 0, and then hold it there... In other words, wait until fmodf(phase,2m_pi) == m_pi/2 or 3 m_pi/2 and then shut it off. If it were to shut off when phase is near 0 or pi, there would be massive change in frequency, and it would probably be pretty broad spectrum.

Same should go with turn-on. A soft-start should always start with phase at pi/2 or 3pi/2.

Thoughts?

hpmax commented 3 years ago

I made some code changes which do the following:

1) The triangular waveform is shifted by 90 degrees, that is it's at 0 when phase_ptr is 0.

2) Instead of running from 0 to 2 *pi it now goes from 0 to 4, this wasn't necessary but it simplifies the math and makes things a little cleaner. The triangle function is simplified such that:

if (phase_ptr>3) return phase_ptr-4; if (phase_ptr>1) return 2-phase_ptr; return phase_ptr;

3) I now calculate a "deltaphase" and "deltapulse" which represent how much the phase changes per sample. Within the loop I increment phase_ptr by deltaphase (and pulse_phase_ptr by deltapulse) and then check if they exceed (4 or 2pi) and if so, decrement by (4 or 2pi). This removes the modulus stuff.

4) At the beginning of the function if the sound is muted (either because its on mute or its in a deadband) I reset phase_ptr and pulse_phase_ptr to 0. This assures a soft-start. Similarly, I set pulse_phase_ptr to 0 if it's in down.

5) Most critically I calculate where phase_ptr will be at the end of frame and I reduce frames_n by the minimum required such that the phase_ptr ends near either 0, 2, or 4, essentially assuring that at the end of the buffer the audio is effectively off. This assures that if the output mode changes, or the buffer underflows that you can't get a sudden change in the output waveform.

The code should be a little faster than the old stuff. None of this may be necessary, but the only way it could hurt is that the buffer may have to be updated a little more frequently (this could be compensated for by increasing the buffer size by 100 words). My big concern in all of this is that I don't really understand pulseaudio. I can't figure out what is causing the buffer to be filled, and I don't know for sure there are no consequences to fully filling it. However, it does appear to work fine.