Nes_Snd_Emu-0.1.7 noise, test_apu_timers attn: blargg

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Nes_Snd_Emu-0.1.7 noise, test_apu_timers attn: blargg
by on (#44234)
i was testing out the noise channel on my emulator using blarggs test_apu_timers/noise_pitch.nes test. the timer is right, all changes are at multiples of 0.00228 sec ( freq 15, look up table is 4068). the first few pulses are the same as test_apu_timers/noise_pitch.nes, but then its different like my shifter is not right.

then i looked at Nes_Snd_Emu-0.1.7/nes_apu/Nes_Oscs.cpp to see if i missed something with the shifter. blargg, if i read the code right ..

silenced:
Code:
// approximate noise cycling while muted, by shuffling up noise register
// to do: precise muted noise cycling?
if ( !(regs [2] & mode_flag) )
{
     int feedback = (noise << 13) ^ (noise << 14);
     noise = (feedback & 0x4000) | (noise >> 1);
}
not silenced
Code:
const int tap = (regs [2] & mode_flag ? 8 : 13);

do
{
     int feedback = (noise << tap) ^ (noise << 14);
     time += period;

     if ( (noise + 1) & 2 ) {
          // bits 0 and 1 of noise differ
          delta = -delta;
          synth.offset_resampled( rtime, delta, output );
     }

     rtime += rperiod;
     noise = (feedback & 0x4000) | (noise >> 1);
     }
while ( time < end_time );

if i am reading this right, you dont use the loop flag to determine the bit used, variable tap, when noise is silenced. i thought the timer would always clock the shift register, and the loop flag would always determine which bit is used.

above is the comment that says approximate. seems that it would be just as easy to do the same noise shifting for silenced or not silenced.

blargg, could you explain what you mean with "to do: precise muted noise cycling?"

if the noise pattern is 32767 bits long, then i should see that pattern in the wave, i tried to see if i could line up my output with the timer test, but found no match when shifted in time.

matt

by on (#44235)
That code doesn't precisely emulate the noise shift register when it's not making any sound. When it's running at maximum rate, it can take quite a bit of processing time. If you want full accuracy, ignore that optimization and do whatever the main loop does.

by on (#45008)
By the way, I just wrote a function which quickly clocks the noise LFSR any number of times. At its heart, it uses algorithms which calculate the equivalent of shifting the LFSR many times in a row, found using an automated LFSR-analyzing program. For example, n ^= (n >> 3) ^ ((n & 0xE) << 11) ^ ((n & 0x7) << 12) is equivalent to executing n = ((n << 13) ^ (n << 14)) & 0x4000 | (n >> 1) repeatedly 255 times in a row.

Code:
/* Clocks NES noise LFSR 'n' count times and returns new LFSR contents. */
int clock_lfsr( int n, int mode, int count )
{
    if ( mode )
    {
        count %= 93;
       
        for ( ; count >= 9; count -= 9 )
            n = (n >> 9) ^
                (n & 0x7FC0) ^
                ((n & 0x1FF) << 6);
       
        while ( --count >= 0 )
            n = ((n << 8) ^ (n << 14)) & 0x4000 | (n >> 1);
    }
    else
    {
        count %= 32767;
       
        for ( ; count >= 255; count -= 255 )
            n ^= (n >> 3) ^
                 ((n & 0xE) << 11) ^
                 ((n & 0x7) << 12);
       
        for ( ; count >= 15; count -= 15 )
            n ^= (n >> 1) ^
                 ((n & 0x2) << 13) ^
                 ((n & 0x1) << 14);
       
        while ( --count >= 0 )
            n = ((n << 13) ^ (n << 14)) & 0x4000 | (n >> 1);
    }
   
    return n;
}

by on (#45023)
not-completely-off-topic: any candidates for n = ((n << 13) ^ (n << 16)) & 0x10000 | (n >> 1) ? (AY8910 noise LFSR)
Which program did you use?

by on (#45101)
Here's the program (very simple C affair): iterated_lfsr.zip

Here are a couple of equivalent expressions for that AY sound chip LFSR. Do you need really high iteration counts, like in the thousands?
n = ((n << 13) ^ (n << 16)) & 0x10000 | (n >> 1); // 1 iter
n = n ^ (n >> 3) ^ ((n & 0x38) << 11) ^ ((n & 0x7) << 14); // 17 iter
n = n ^ (n >> 11) ^ (n >> 8) ^ ((n & 0x3FF8) << 3) ^ ((n & 0x7) << 6) ^ ((n & 0xFF) << 9); // 266 iter

by on (#45114)
Thanks, this is a pretty smart optimization for when noise is not in use. :)
In the thousands: I don't think that's needed.