It is currently Wed Jan 16, 2019 1:01 pm

All times are UTC - 7 hours



Forum rules





Post new topic Reply to topic  [ 23 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Tue Nov 20, 2018 1:01 am 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3628
Location: Indianapolis
Thanks for posting a video, that's fantastic. I wouldn't have thought that dynamic recompiling would work very well, but there it is.

SMB was conspicuously absent from my NSF player, because I just couldn't get it to run for some reason. I don't think it's doing anything too tricky sound-wise, but it was kinda infamous for sounding wrong on a lot of emulators in the past (mostly the sound effects more than the music though, the pipe sound in particular).

For the noise channel to sound like that, seems like the code that detects writes to $400F isn't working. And it sounds like frequency sweeps aren't working. In my player, both of those are handled in main.asm 'detect_changes' subroutine, stuffing bit flags for everything into the $7F4116 variable. Also really weird how the triangle channel only shows up a few times. That indicates to me that in the same way, $400B writes aren't being detected. It could be that when the game changes the high byte of the frequency (you could play the NSF in a player with a register viewer to be sure), that's when the notes are working. But a lot of the time, only the low byte changes. Even when the high byte doesn't change, the game must write to it so the linear counter / length counter / sweep register etc. will be triggered. It was one of the weirder problems I remember solving with that detect_changes routine, how to detect the code writing the same value repeatedly to those registers. I just got lucky because writing zero to those on the NES is pretty rare, so I could count on games generally not writing zero to it normally (a rogue sound engine could have worked that way and broke my emulation, but luckily they tend to use the volume regs (and 4008 on triangle), or $4015, and in cases where they actually use the timers, they just let it expire). Since you'll be recompiling, I guess you won't have that problem exactly, but you'll have to address it in some way while you collate the sound register writes before sending it to the SPC.

It's entirely possible though that SMB1 is doing crazy weird stuff with the sound registers, because I never had it working in my player to actually observe it. I doubt it though. I'll take a look at it tomorrow. If i can remember what other NSF player had a register viewer other than mine, and the old DOS version of Nosefart. I'm certain there is one..

Also, there is one known bug in my update_dsp routine. It causes occasional glitches. The cause was something really weird with the CPU/SPC alignment, IIRC it worked fine on hardware but was breaking on every emulator. kevtris said inserting a NOP in there fixes it, I may be able to ask him tomorrow where that NOP should go exactly. But probably just in-between my $2140/$2141 accesses, they were just too close together I guess. I don't think that's affecting the audio here, but it's possible.


Top
 Profile  
 
PostPosted: Tue Nov 20, 2018 1:57 am 
Offline
User avatar

Joined: Fri Jan 24, 2014 9:05 am
Posts: 165
Location: Hungary
Some games do attempt to silence the triangle channel in weird ways that might cause some issues:
- Mega Man and Mega Man 2, plus other Capcom games from around that time silence the triangle by writing 0 to the period register, some even use $4015 afterwards, it's really odd, but it makes a popping sound.
- Tim & Geoff Follin used a similar method, only that the triangle spends releatively little time in this state in most of their music.
- Zombie Nation, Kickmaster, Doki Doki Yuuenchi, etc. use a sound driver that """silences""" the triangle by writing $7FF to the period register, where the overtones of the 4-bit quantization of the wave are still audible.

Is there any way to use the SPC-700 to directly set channel levels to simulate the effect of $4011 writes to add DPCM support? Writing a player for DPCM doesn't sound very difficult (Konami has done that themselves for Blades of Steel) but getting the timings right could be.


Top
 Profile  
 
PostPosted: Tue Nov 20, 2018 8:32 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 765
Memblers wrote:
One problem with my code is that the interpolation totally ruins the sharp edges of the waveforms. IIRC it was _mic who later released a sound emulator showing you can get a cleaner sound by using a set of larger samples played at the highest rates possible, as it will be affected less by the interpolation.

Yes, the square wave output can become square or not so square. When using a single 9-byte BRR sample (=with sixteen 4bit nibbles), it could look as so:
Code:
  Incoming BRR Data                 ---> Interpolated Data
   _   _   _   _   _   _   _   _
  | | | | | | | | | | | | | | | |         .   .   .   .   .   .   .   .    Nibbles=7979797979797979, Shift=12, Filter=0
  | | | | | | | | | | | | | | | |   ---> / \ / \ / \ / \ / \ / \ / \ / \   HALF-volume ZIGZAG-wave
  | |_| |_| |_| |_| |_| |_| |_| |_          '   '   '   '   '   '   '   '
   ___     ___     ___     ___
  |   |   |   |   |   |   |   |            .'.     .'.     .'.     .'.     Nibbles=7799779977997799, Shift=12, Filter=0
  |   |   |   |   |   |   |   |     --->  /   \   /   \   /   \   /   \    FULL-volume SINE-wave
  |   |___|   |___|   |___|   |___       '     '.'     '.'     '.'     '.
   _______         _______                   ___             ___
  |       |       |       |                .'   '.         .'   '.         Nibbles=7777999977779999, Shift=12, Filter=0
  |       |       |       |         --->  /       \       /       \        SQUARE wave (with rounded edges)
  |       |_______|       |_______       '         '.___.'         '.____
   _______________                           ___________
  |               |                        .'           '.                 Nibbles=7777777799999999, Shift=12, Filter=0
  |               |                 --->  /               \                SQUARER wave (with rounded edges)
  |               |_______________       '                 '.____________

I've tried to output a melody with 130Hz..260Hz tones today. First using the "SINE" wave (2nd graph), then using the "SQUARER" wave (4th graph) played at quad speed. The difference was surprising, the "SQUARER" one sounded more or less okay, but the "SINE" wave wasn't audible at all - which, I guess the reason is that the speakers in my PC/TFT monitor are quite crappy.
I had thought that the difference between sine & square would be more of a cosmetic thing for audiophiles, or that sine waves would sound even better and clearer - but now I agree that it's important to have edges in square waves.

When using samples with more than 9 bytes it could be made even squarer, but larger samples would work only for lower frequencies. Even the 4th graph in the above examples can output max 7999Hz (with pitch=3FFFh).
So I guess one needs to switch between different BRR samples to cover all frequencies - which could bring up it's own problems (eg. abrupt change in "volume & appearance" when switching between different samples for <=7999Hz versus >=8000Hz tones).


Last edited by nocash on Tue Nov 20, 2018 8:38 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Nov 20, 2018 8:35 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7646
Location: Chexbres, VD, Switzerland
As far as I'm aware the norm in SNES games is to have at least two full BRR blocks (18 bytes) of samples, even for short looped "synths" waves. Having 3, 4 or more BRR blocks per loop is common, too. Many SNES games had square waves and sometiemes pulse waves in their audio, so I'd recommend investigating this.


Top
 Profile  
 
PostPosted: Tue Nov 20, 2018 10:29 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20995
Location: NE Indiana, USA (NTSC)
Applying a bit of overshoot to the waveform boosts the treble, which tricks Gaussian resampling into behaving more like cubic spline resampling. I don't have all my DSP tools in front of me at the moment, but try these waves and see which of each set most closely resembles what you remember. (As usual, you'll have to insert a header byte before each 8 pairs of nibbles: C0 before the first half and C3 before the second half.)
Code:
BBBB 5555 5555 5555   5555 5555 5555 5555
ABBA 6555 5555 5555   5555 5555 5555 5556
9BB9 7555 5555 5555   5555 5555 5555 5557

BBBB BBBB 5555 5555   5555 5555 5555 5555
ABBB BBBA 6555 5555   5555 5555 5555 5556
9BBB BBB9 7555 5555   5555 5555 5555 5557

BBBB BBBB BBBB BBBB   5555 5555 5555 5555
ABBB BBBB BBBB BBBA   6555 5555 5555 5556
9BBB BBBB BBBB BBB9   7555 5555 5555 5557


Top
 Profile  
 
PostPosted: Tue Nov 20, 2018 1:24 pm 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 9
Absolute writes to sound ports are replaced with JSL but not absolute indexed yet. On what changes should I set flags? I understand the bits at $7F4116 and $7F4115.

I confirm that pipes are the worst.

Memblers wrote:
Also, there is one known bug in my update_dsp routine. It causes occasional glitches. The cause was something really weird with the CPU/SPC alignment, IIRC it worked fine on hardware but was breaking on every emulator. kevtris said inserting a NOP in there fixes it, I may be able to ask him tomorrow where that NOP should go exactly. But probably just in-between my $2140/$2141 accesses, they were just too close together I guess. I don't think that's affecting the audio here, but it's possible.

I noticed a bug while rewriting this and I probably fixed exactly what you're talking about. The index was written before the data byte but it should be the other way around. The SPC waits for index to change so it can read the data byte, otherwise it can fail to read the correct data. I never tried running it before changing update_dsp.


Top
 Profile  
 
PostPosted: Tue Nov 20, 2018 2:52 pm 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2789
I was trying to make an SNES music program a couple months ago and I think I went up to 7, down to 3 and then plataued at 4, for the overshoot.


Top
 Profile  
 
PostPosted: Wed Nov 21, 2018 11:58 pm 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3628
Location: Indianapolis
Myself086 wrote:
Absolute writes to sound ports are replaced with JSL but not absolute indexed yet. On what changes should I set flags? I understand the bits at $7F4116 and $7F4115.


I think games almost always write to the sound registers with absolute indexed. Before, I was thinking the flags in $7F4116 would be set anytime $4003,$4007,$400B,$400F are written, but now I'm not 100% certain. Looking at my code I see that I only set those flags when length counter enable is turned on. I'm having trouble understanding my old code 100% at the moment, doesn't seem like I can do an adequate job explaining it. The SPC code will only trigger decay if that bit is set, so I'm not sure why I have those 2 features seemingly interdependent.. either I'm misunderstanding my code, or I did it wrong (and I'm finding a bug).

edit: Also, sweep register flags (D6 and D7 of $7F4116) need to be set whenever $4002,$4006 are written

I've been looking through my code for the first time in a while (hard to believe it's been 17 years since I wrote most of this), made some observations:

Right off the bat in 'detect_changes', this branch label implies it has checked the decay enable (D4), but it's actually checking the length counter enable (D5). Very misleading.
Code:
detect_changes:
        lda $7F4000
        and #%00100000
        bne decay_disabled0


D5 of $7F4116 selects mono/stereo mode for the 2 pulse channels, you probably noticed that.

There sure is ton of commented-out code left in there. From the bad old days before I used version control.

Lots of copy+pasted+manually edited code in there. Not sure why I didn't just use macros instead.

Lots of annoying inconsistencies. Like I have this defined:
no4016 = $56 ; $4016
But sometimes I refer to it as no4016, sometimes as $56. Ugh, WTF. Also some places where I use hex like 20h instead of $20 like everywhere else.. minor WTF.

Myself086 wrote:
Memblers wrote:
Also, there is one known bug in my update_dsp routine. It causes occasional glitches. The cause was something really weird with the CPU/SPC alignment, IIRC it worked fine on hardware but was breaking on every emulator. kevtris said inserting a NOP in there fixes it, I may be able to ask him tomorrow where that NOP should go exactly. But probably just in-between my $2140/$2141 accesses, they were just too close together I guess. I don't think that's affecting the audio here, but it's possible.

I noticed a bug while rewriting this and I probably fixed exactly what you're talking about. The index was written before the data byte but it should be the other way around. The SPC waits for index to change so it can read the data byte, otherwise it can fail to read the correct data. I never tried running it before changing update_dsp.


Good find, that is exactly the fix. It's really weird that it apparently works on the actual hardware, but it's still a race condition and should be fixed.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group