Skip to content
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

Replace 2A03/FDS audio cores with NSFPlay/Mesen #32

Merged

Conversation

nyanpasu64
Copy link
Collaborator

@nyanpasu64 nyanpasu64 commented Feb 8, 2021

rip out the guts, replace with something new, reimplement all the side-channel observability metadata (pitch/volume view, register view, channel meters) that comes with it

hopefully i didn't regress any functionality in the process... it'll be done someday, someday~

  • TODO fix 2A03 triangle volume meter pop on startup (the audible pop is already fixed)

Overview

2A03 and FDS audio emulation were replaced with nsfplay and Mesen's cores, respectively.

Both are wrapped in CSoundChip2, a newly added replacement for CSoundChip (which was the wrong abstraction). CSoundChip2 does not use CChannel. CChannel was a mistake, and CChannel plus CMixer's current API (each channel independently streams volume levels and/or deltas to the same Blip_Synth located in CMixer) is hostile to any form of channel mixing other than linear mixing.

CSoundChip2 expects to own a Blip_Synth (and CFDS also owns a Blip_Buffer used for lowpass emulation), and does not hold an aliased pointer to CMixer or Blip_Buffer (instead receiving a borrowed Blip_Buffer& whenever audio needs to be generated).

The mixing interface is still inconsistent; CFDS computes mixing levels internally (encapsulating the implementation detail of the emulation core's output levels), whereas C2A03 lets CMixer compute mixing levels.

  • TODO make C2A03 compute mixing levels internally

Behavioral changes

2A03 noise at the highest pitch may use more CPU than before due to emulation inefficiencies. This is only an issue on debug builds or possibly slow computers (did not test). FDS may use less CPU than before due to cycle-skipping.

FDS emulation changes

FDS sounds different due to the lowpass filter added. Additionally earlier FDS instruments will no longer work; the new sine preset will fix the sound with minimal audible changes on older FamiTracker versions.

TODO In the future, we may add a FDS filter strength slider.

The NSF driver performs a modulator phase reset that in-tracker playback does not, making reset-free modulator envelopes that operate deterministically in NSF export start at random positions in the tracker; modulator phase reset may be added into the tracker into the future.

TODO In the future, we may add a toggle for the FDS's non-monotonic jagged DAC (which scrambles wavetable amplitudes but does not affect their position in time).

Volume meter algorithm changes

On affected chips, the volume meters were rewritten to plot the range of volume levels seen during each engine tick, rather than the largest new volume level seen during a tick (where steady-state chip output is interpreted as 0 volume).

For example, the 2A03 DPCM meter now plots the range of DPCM counter values seen, rather than the largest new DPCM counter value. This more accurately models perceived sample volume:

  • Z7F followed by Z00 now looks identical to Z00 followed by Z7F (previously, the former would produce 0 meter output)
  • Sample playback produces the same visual appearance regardless of delta level (previously, the same sample would produce a higher volume meter reading if played at a higher delta counter value)

Note that this assumes all steps are evenly spaced, and does not take into account nonlinearity (output deltas being smaller at high values), but it's closer than before.

2A03 triangle waves will flicker more than before (they were never flicker-free) at very low pitches (below 60 Hz).

Potential issues

The latest commit (373331c) was written on Linux and I did not try compiling it. Hopefully it builds on CI, doesn't have warnings, and works properly (on Wine?)

Shift-JIS doesn't have ~ and \,
and the ASCII/UTF-8 codepoints for those map to overline and yen.
https://stackoverflow.com/questions/56819615/
As a result, we have to postprocess the output of iconv.

fd -t f -x iconv -f SHIFT-JIS -t UTF-8 {} -o {}
fd -t f -x sed 's/‾/~/g; s/¥/\\/g;' {} -i

Additionally, iconv corrupts emu2413.c by turning
"OPLL_reset(OPLL" into "OPLL_rePLL_reLL".
So I had to revert this change.
@nyanpasu64 nyanpasu64 marked this pull request as ready for review February 25, 2021 04:49
nyanpasu64 and others added 20 commits February 24, 2021 21:01
Blip_Buffer::mix_samples() delays all incoming samples
by the same amount as Blip_Synth::offset() delays deltas.
This is the right choice for audio generated by output-rate synths
(used in FamiTracker for VRC7 audio), but causes audio generated by
another Blip_Buffer (and already delayed) to be delayed twice.

I add a new method, Blip_Buffer::mix_samples_raw(), which does not delay
incoming audio, and use it for mixing in filtered FDS audio.
The old code delayed global output by 1 sample, and also delayed CFDS
by 1 sample relative to other sound chips.
The constructor with parameters is currently unused.
The nsfplay emulator's APU2 triangle wave has a nonzero offset
when reset. This may or may not be accurate.
Either way, subtract the offset when the chip resets.
This way, when switching between sound chip emulators with different
output levels, we only need to edit the sound chip class to compensate,
not any code in CMixer.
@nyanpasu64 nyanpasu64 changed the title Replace 2A03/FDS audio cores with nsfplay/Mesen Replace 2A03/FDS audio cores with NSFPlay/Mesen Feb 26, 2021
@nyanpasu64 nyanpasu64 merged commit 4df251e into Dn-Programming-Core-Management:master Feb 26, 2021
@nyanpasu64 nyanpasu64 deleted the replace-audio-cores branch February 26, 2021 07:34
@nyanpasu64 nyanpasu64 restored the replace-audio-cores branch February 26, 2021 07:34
@nyanpasu64 nyanpasu64 deleted the replace-audio-cores branch February 26, 2021 07:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants