sound range, blip, 0..15, 0..127, 0.. 1.0 zero axis, center

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
sound range, blip, 0..15, 0..127, 0.. 1.0 zero axis, center
by on (#43474)
just started with sound on my emu. i tested with zelda intro and it doesnt sound too bad ( i dont have to quickly turn it off :P)

square1, square2, triangle, noise range from 0 to 15, is the zero axis 7.5 ?
dmc ranges from 0 to 127, is the zero axis 63.5 ?

i am using the normalized audio equation from the wiki and apu_ref.txt that normalizes from 0.0 to 1.0, is the zero axis 0.5 ?

for testing i grabbed the wave_writer code from blip to dump to a wav so i could see before playing. after opening with audacity, my wav dump ranges from -0.45 to -0.90 ( audacity scale is 1.0 to -1.0) and says 32 bit float, i guess thats audacities internal format ? file reports the file as zelda-first-test.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 96000 Hz. the waveform looks ok, and sounds ok, but is not centered about the 0 axis virtically.

after normalizing the nes data in my sound code, i multiply by USHRT_MAX (65535) and add SHRT_MIN (-32768) to convert to the range of short (-32768 to 32767) then pass that to wave_write that i grabbed from blip.

could anyone suggest why my audio is not centered ?

matt

by on (#43485)
The NES audio path centers the audio by applying a high-pass filter to the mixed output. Try passing blip's output through a digital DC blocker.
Re: sound range, blip, 0..15, 0..127, 0.. 1.0 zero axis, ce
by on (#43489)
mattmatteh wrote:
square1, square2, triangle, noise range from 0 to 15, is the zero axis 7.5 ? dmc ranges from 0 to 127, is the zero axis 63.5 ?

No; the 2A03 generates a positive-only signal, so no zero adjustment is necessary. This means it has a DC offset internally, which is later gradually removed by a high-pass filter (as tepples mentioned). Here's a simple high-pass filter (conversion to fixed-point left as exercise for reader):
Code:
double adjust = 0.9975;
double old;
double out;

double high_pass( double in )
{
    double delta = in - old;
    old = in;
   
    out = out * adjust + delta;
    return out;
}

Note that this will result in input of range [0,1.0] turning into an output of [-1.0,+1.0], so to convert the result of this to 16-bit audio, you'd merely multiply by 32767, unlike what you'd do to convert the range [0,1.0] to [-32767,+32767].

Quote:
i am using the normalized audio equation from the wiki and apu_ref.txt that normalizes from 0.0 to 1.0, is the zero axis 0.5 ?

It's 0.0.

Quote:
the waveform looks ok, and sounds ok, but is not centered about the 0 axis virtically.

Why would it? A square wave of volume 1 goes between 0 and 1. One of volume 15 goes between 0 and 15. Even if you subtract 7.5, the centers of these will be in different places.

by on (#43511)
- What about this? ($4011 output)
Code:
        dmc->regs[1] = value & 0x7F;
        dmc->output_dac += ((int)dmc->regs[1] - (int)dmc->old_reg) << 8;
        dmc->old_reg = dmc->regs[1];

by on (#43524)
The high-pass filter must be applied for every output sample, not just when the DAC changes. The effect is to gradually move the output level towards zero when it's not changing.

by on (#43529)
Can't you also get DC centering by making the volume range for each channel -n to n instead of 0 to n? Obviously this won't work with the DMC channel, but for other channels, it sounds like it would work.

by on (#43534)
I think the goal is accurate sound emulation. Centering by making channels go from -n to +n alters the sound noticeably, and makes non-linear mixing more complex (or not even possible?).
Re: sound range, blip, 0..15, 0..127, 0.. 1.0 zero axis, ce
by on (#43541)
blargg wrote:
(conversion to fixed-point left as exercise for reader)


I'm curious as to why you prefer fixed point... is it for accuracy or speed? With the range of results we're talking about, I wouldn't think accuracy would come into play and surely any modern processor isn't going to sweat the floating point calculations. ???

by on (#43547)
old skoooool maaan old skoool

by on (#43550)
Well, I did use floating-point for the example due to its clarity. Many people are afflicted with premature optimizationitis, so I like to direct its tendencies in mildly-productive ways. In my own library code, I avoid trivial floating-point operations because some of the most commonly used processors do not usually have floating-point hardware, for example ARM and MIPS, and using it can involve linking in extra library code.

by on (#43554)
blargg wrote:
The high-pass filter must be applied for every output sample, not just when the DAC changes. The effect is to gradually move the output level towards zero when it's not changing.


It's not only that, I forgot to mention the decay code, output -= output >> N.

by on (#43555)
I see; yes, as long as you do output-=output>>N every output sample, and add deltas to the output, you'll get a high-pass. For the NES, N should be 8 or 9, as this gives an effective equivalent to approximately output*=0.9961 and output*=0.998, respectively. Note that these assume a sample rate of around 44 kHz.

by on (#43559)
Dwedit wrote:
Can't you also get DC centering by making the volume range for each channel -n to n instead of 0 to n?

Then my "hello hello" demo would fail. It sets the square wave to a high frequency and treats $4000 as if it were $4011. The "say-gah!" intro of Game Gear games would fail for the same reason.

by on (#43561)
blargg wrote:
because some of the most commonly used processors do not usually have floating-point hardware, for example ARM and MIPS


makes sense. thanks for the info.

by on (#43701)
thanks tepples and blargg. i underestimated the high pass filter. i applied a simple high pass in audacity and it was fine.

by on (#43789)
Quote:
I think the goal is accurate sound emulation.
Given how many libraries/players offer enhancements like reverb, arbitrary stereo, DMC pop remover etc., "nice" sound emulation might be a worthwhile option. I for one prefer perfectly zero-adjusted square waves and linear mixing for listening.

Again, just as a selectable option, not as a default setting.

by on (#43796)
Yup, same here... ;)

by on (#43800)
enhancements might be fun to play with but i would prefer the sound be as close to the hardware as possible. ill just apply the high pass filter.

by on (#43812)
I must record some music from the NES and edit it to see how it shapes. Until then, I'm unable to confirm possible clipping when a bunch of unsigned waves are overlapping...