SourMesen / Mesen

Mesen is a cross-platform (Windows & Linux) NES/Famicom emulator built in C++ and C#
https://www.mesen.ca
GNU General Public License v3.0
1.26k stars 320 forks source link

Audio Effect Addition: Stereo Enhancing Comb Filtering #443

Open torridgristle opened 6 years ago

torridgristle commented 6 years ago

Currently there's 2 stereo effects, arguably 3, that do nothing but pan the sound by two means: amplitude adjustment or timing adjustment. This does make it sound stereo but also it makes it sound not in front of you.

An option for widening the sound while keeping it centered is comb filtering. This works by applying complementary comb filters on the left and right channels such that the frequencies cut or boosted on one side are boosted or cut on the other. Here's a video of the process in general. mda-vst has an open source MIT license plugin called mdaStereo with this effect, as well as modulated delay which might be useful? Sometimes it sounds more natural with some slight modulation, your ears don't get a chance to hone in on a constant sound and it stays organic, kinda like dithering away errors but with timbre I suppose.

torridgristle commented 6 years ago

My brain turned on while I was thinking about comb filtering and how it's typically, if not always, the result of very short delays / reflections cancelling out / adding up frequencies relating to the delay length. I thought "Can't I just delay it a bit and add them together for one channel's comb filter, then delay the other channel by a multiple of it? No, no, I don't think that math will work out. Just like inverted it and add--oh."

So here's how mdaStereo does it:

  1. Mono the input signal just in case something's panned or the input is otherwise not mono.
  2. Delay a copy of the signal by several milliseconds
  3. Add the delayed copy to one channel and subtract the delayed copy from the other channel.

It's beautiful, and I feel so profoundly and thoroughly foolish for thinking it was anything else. That's literally all a comb filter is, just delay it and add it back in, and it's the same thing with opposite polarities on the left and right so the Mid (as in Mid/Side as opposed to Left/Right where Mid is L+R and Side is L-R) is exactly the same as the original mono signal, and the Side isn't biased toward the left or right except for some problem areas in the bass which is mentioned later with a proposed solution.

You can adjust the intensity of the effect by altering the amplitude of the delayed side signal and you can filter it as well with things like:

SourMesen commented 6 years ago

Thanks for the info!

I gave it a quick try by modifying the current "delay" stereo filter a tiny bit, and it seems to work pretty nicely (without adding any particular filtering to it). At the very least, it gives a pretty stereo sound to the audio, without making it sound like it's not in front of you. I'll try to get a proper version of it (including the UI) done tomorrow night.

SourMesen commented 6 years ago

I've added the filter to the audio config UI (with settings for the delay & amplitude), it should be available in the latest appveyor build. Let me know what you think!

Cibomatto2002 commented 6 years ago

It works really good.

torridgristle commented 6 years ago

With the stereo comb filter on 9ms delay (probably not relevant) and 100% intensity with the mixer's master output set to 100% the audio will pop. If I take the intensity down to 90% or so the popping stops, if I instead take the mixer's master output down to 90% or so the popping stops.

close up

It kinda looks like the audio samples exceed their maximum value and roll over. I reckon this isn't an issue from the stereo comb filter and is pre-existing.

The stereo comb filter's delayed signal could use a highpass filter to preserve the bass and a highshelf filter. Just plain butterworth filters (or bessel for smoother transitions on the cutoff) with custom poles and cutoff frequencies so bass-centric games like Recca can get a stronger removal of bass from the stereo effect to keep it heavy and centered without phase issues and anything else can have whatever the user would want. The highshelf is for dampening the delayed sound or for adding more air to it, sometimes one sounds better than the other.

Something to remove small spikes from the delayed signal could help with noisy sounds and maintaining RMS when cutting bass / boosting treble, and even now. Since it's just for the sides a soft clipper wouldn't be very noticeable but would still provide benefits should a game provide the right noises.

Normal - Comb - Highpass Comb - Highshelf Comb then Clipper Halfway Through - Comb.zip

Here's a track from Recca playing from its sound test menu in MesenDevWin-0.9.5.170.exe with the plain audio, then stereo comb filter with 9ms or 9.18ms (ain't remember which) delay and 25% amplitude, then with a 2 or 3 or 4 pole bessel highpass (ain't wrote it down while it was open), then a bessel highshelf boosting the treble, then halfway through that a soft clipper comes in and shaves off the transients, then back to normal stereo comb filter. It's not a massive change but it sounds cleaner and much more tolerable without the stereoized bass, at least to me.

It's definitely a big step in the right direction though, it just really needs a side highpass. Virtually all stereo effects are this way with music.

Also with convolution this whole process could be baked into a single impulse response, barring the clipper, with many tweaks available outside of Mesen. I could bake an EQ match of a television set with stereo comb filter enhancements and subtle room reverberations into a single WAV and no matter what effects were applied to it they're all used the same way in the convolution process for the same CPU hit.

SourMesen commented 6 years ago

Thanks for the feedback. Setting the master volume to 100% is generally not a good idea, the more filters you add, the more likely the output is to clip. The default value for master volume is 25% (not the most user friendly thing, but that's how it is at the moment).

I just released 0.9.6 (with the new stereo filter as it was in the appveyor builds) and I won't have much time to work on Mesen for most of the rest of 2018 I'm afraid, so this will probably have to wait for a while.