-
Notifications
You must be signed in to change notification settings - Fork 2.3k
sound/cem3394.cpp: implement self-oscillation when no waveforms are enabled #14680
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
base: master
Are you sure you want to change the base?
Conversation
|
That's kinda gross... |
|
Open to other ideas. I tried a few things before resorting to this. For context, the problematic case is when the filter is configured with no input and full resonance. The fixes below, and in this PR, were only applied in this configuration. I tried exciting the filter with noise and a pulse wave. Both fixed self-oscillation, but in both cases, the fake input came through to the output. As an aside, an incorrect pulse input seems to be why self-oscillation was (sometimes) working before #14497. I also tried just using DC as an input, but that didn't work. The "least gross" approach that worked was to avoid clamping the resonance to 0.99 when there are no inputs. mame/src/devices/sound/cem3394.cpp Lines 221 to 223 in 098b4ed
But AFAICT, that's not guaranteed to always work (though it did in my tests). Furthermore, it looks like the clamping was done for stability, and removing it might increase the risk of the filter exploding and losing audio. So it felt a bit risky. |
If the risk is acceptable, I can go with this approach after doing some more testing. And can revisit if there are reports of lost audio or missing sounds. There seem to be additional safeguards for filter stability, which might help mitigate the risk: mame/src/devices/sound/cem3394.cpp Lines 248 to 256 in 098b4ed
|
|
I'm quite surprised you can have zero input in the first place. The oscillators are usually free-running and the envelope/gating happens after the filter. Checking the 3394 schematics, it seems to be the case. The VCA only switches between external and internal, but other than that there's always some signal doing through as far as I can see. Am I wrong? The self-oscillation filters out the input, so it's not a problem to get the sine if the digital implementation of the filter manages self-resonance in the first place. |
|
Thanks for taking a closer look.
Yeah, it is a bit unexpected. Zero input is possible because of how waveform selection works. The waveform CV selects between "none", "triangle", "triangle + saw" and "saw" (note the switches drawn as open in the block diagram). The pulse waveform is controlled by a pulse-width CV, and is zero (well, constant) if PW is 0% or 100%. So when the waveform CV is "none", PW CV is 0% (or 100%), and the external input is switched off, there will be zero AC to the filter. That zero input + max resonance configuration is used as a sine oscillator, for some of the FM patches. Those are the ones currently not working.
The existing implementation works well when there is an input, though it doesn't seem to cancel the input completely. This might be due to the resonance clamping I mentioned in the previous post. It is the zero input configuration that does not work. Removing resonance clamping (when the input is zero) seems to fix that. But It feels a bit more risky. Nonetheless, I could pursue this "no clamp" approach (with some more testing), instead of the "explicit sine oscillator" approach in this PR, and revisit if there are reported issues. Let me know if that's preferable. |
|
I don't think you should resonance-clamp, like, ever. There's no reason for it, I think... |
Detecting the special case of a filter with high resonance and no input waveforms, and generating a sine wave to implement self-oscillation.
Fixes the regression reporter here. Also fixes patches 98 and 99 on the
sixtrak, and enables ever more sounds insente6vb.Finally, corrected the value of
m_pulse_widthwhen PW is at 100%. Though this does not make a difference, sincem_pulse_widthis not used when the PW is 100%.