It is currently Wed Dec 13, 2017 9:31 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: FDS registers
PostPosted: Thu Jun 18, 2015 3:37 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
I am trying to get a sense of how to implement FDS support from the wiki. I am having difficulty understanding the relationship between the registers and the actual file data. I can't figure out how it knows what it is reading from or what it is writing to. Can something provide an overview of how and when the registers are used in accessing the file data? Thanks.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Mon Jun 22, 2015 8:02 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
I made a lot of progress by studying the source codes of various emulators. For FDS Audio, I am having trouble getting the modulator unit to function properly. I implemented it as described in the wiki, but it does not modify the wave pitch appropriately. If anyone has had experience with it, please respond.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Mon Jun 22, 2015 8:09 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
What trouble are you having with the modulator?


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Mon Jun 22, 2015 9:10 pm 
Offline

Joined: Thu Apr 14, 2011 9:27 pm
Posts: 85
Some pitfalls I ran into when I got this working last week:

- The address into the modulator table is incremented after reading a value, not before. (This is very important with Bio Miracle Bokutte Upa because it resets the modulator value constantly and will result in weird pitch sweeps in that game if you get it wrong.)

- The modulator output is not added to the value of the pitch register and then put back into the pitch register; that would cause a feedback effect with the pitch rising or falling exponentially. Instead the modulator output is added to the wavetable counter at the same time as the pitch value.

- Make sure that the modulator counter wraps instead of saturating, and that you are sign-extending it correctly when storing in an 8 bit or larger variable. That would be
Code:
modCtr = (modCtr << 25) >> 25;
if in C with a 32 bit int.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Tue Jun 23, 2015 6:23 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
Grapeshot wrote:
- The modulator output is not added to the value of the pitch register and then put back into the pitch register; that would cause a feedback effect with the pitch rising or falling exponentially. Instead the modulator output is added to the wavetable counter at the same time as the pitch value.


This sounds like the issue. I'll do some experimentation and let you know. Thanks for your help.

By the way, for the low-pass single-pole filter, did you actually use a cutoff frequency of 2000 Hz ?

Edit: I made a change based on your suggestion and the result it closer, but it's still not there. Could I take a peek at your code? :)


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Tue Jun 23, 2015 9:12 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
This is my implementation of the FDS audio:
https://code.google.com/p/nsfplay/source/browse/trunk/xgm/devices/Sound/nes_fds.h
https://code.google.com/p/nsfplay/source/browse/trunk/xgm/devices/Sound/nes_fds.cpp


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Tue Jun 23, 2015 9:49 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
rainwarrior wrote:


This is quite helpful. Thanks.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Tue Jun 23, 2015 5:26 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
With that source code as a guide, I fixed my modulator unit implementation. Most of my code was correct. The issue was really sorting out what triggers what. The wiki provides information on the pieces, but it is often unclear on how to put those pieces together properly.

Grapeshot wrote:
Code:
modCtr = (modCtr << 25) >> 25;


That's a clever trick that I took advantage of.

Rainwarrior, I found it interesting that you combined the accumulators with the wave indices into a single phase variable to make the frequency addition overflow automatically update the indices. But, I decided to keep the variables separated for clarity.

Also, on lines 345 and 347, val is AND'ed with 0x7F. It's unclear why 0x07 is not used.

On line 372, I think it should read adr <= 0x407F, not adr < 0x407F.

On line 63, you chose to use the continuous-time formula to compute the smoothing factor. The discrete version produces a slightly different value. But, this is pretty irrelevant. In fact, I chose an arbitrary smoothing factor based on what I thought sounded right.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Tue Jun 23, 2015 7:17 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
zeroone wrote:
Rainwarrior, I found it interesting that you combined the accumulators with the wave indices into a single phase variable to make the frequency addition overflow automatically update the indices. But, I decided to keep the variables separated for clarity.

I don't think of that as a trick or anything. I'm pretty sure most wavetable hardware does it this way internally. You have a digital phase accumulator, where some of its high bits address the wavetable, and the lower bits just act as a fixed point precision for the pitch. Why would you want to separate them? They're always updated together in one step.

zeroone wrote:
Also, on lines 345 and 347, val is AND'ed with 0x7F. It's unclear why 0x07 is not used.

On line 372, I think it should read adr <= 0x407F, not adr < 0x407F.

On line 63, you chose to use the continuous-time formula to compute the smoothing factor. The discrete version produces a slightly different value. But, this is pretty irrelevant. In fact, I chose an arbitrary smoothing factor based on what I thought sounded right.

Those are both bugs. Thanks. I'll fix them. I probably didn't notice the mistake because there aren't any games that attempt to read back the wavetable, and I don't think anything writes the mod-table with out of bounds values either, but that could do some crummy things. :S

As for the RC filter implementation, I'll look into that. It's not important for emulation (the real FDS filter isn't a simple lowpass, this is just an approximation that is similar), but if the cutoff is inaccurate vs. the specified value it would be good to improve them. I think the calculations I used were taken from an old DSP reference book that I like, but I don't mind taking another look at the theory.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Wed Jun 24, 2015 9:27 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
rainwarrior wrote:
I don't think of that as a trick or anything. I'm pretty sure most wavetable hardware does it this way internally. You have a digital phase accumulator, where some of its high bits address the wavetable, and the lower bits just act as a fixed point precision for the pitch. Why would you want to separate them? They're always updated together in one step.


First of all, I just want to say that your code is brilliant and I greatly appreciate that you made it readily available to help other developers like myself. I hope that the details eventually makes it into the wiki.

I agree that it is likely that the hardware uses a combined register and that a single addition effectively updates both values. But, there are several instances of reads and writes to just the wavetable index bits requiring shifts and masks:

Code:
UINT32 start_pos = phase[TMOD] >> 16;
phase[TMOD] += (clocks * freq[TMOD]);
UINT32 end_pos = phase[TMOD] >> 16;

phase[TMOD] = phase[TMOD] & 0x3FFFFF;

phase[TMOD] = mod_write_pos << 16;

phase[TMOD] = phase[TMOD] & 0x3F0000;

wave[TMOD][(phase[TMOD] >> 16) & 0x3F] = val & 0x7F;
phase[TMOD] = (phase[TMOD] + 0x010000) & 0x3FFFFF;
wave[TMOD][(phase[TMOD] >> 16) & 0x3F] = val & 0x7F;
phase[TMOD] = (phase[TMOD] + 0x010000) & 0x3FFFFF;
mod_write_pos = phase[TMOD] >> 16;

fout = wave[TWAV][(phase[TWAV]>>16)&0x3F] * vol_out;


In other words, combining them in code simplifies the update. But, everywhere else, it is difficult to use, in my humble opinion. So, I opted to break it up.


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Wed Jun 24, 2015 2:08 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
Heh, fair enough, I suppose.

Actually, I've kinda wondered about the internal mod table application, actually. I guess it's actually clocked by the carry. It doesn't necessarily have to store an index; the mod table might be some kind of bucket-brigade? Since there's actually no way to externally reset or determine the mod table index, it's kind of unclear whether it really exists.

I tried to keep the mod table implementation mostly parallel to the wave table, since in most other ways they work the same way. (To a lesser extent, it's also parallel to the N163.)


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Thu Jun 25, 2015 10:41 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
Here's a link to FDS audio emulation comparisons:

https://www.youtube.com/watch?v=C2fIJFhh1sc

How close is the model described in the wiki to reality?


Top
 Profile  
 
 Post subject: Re: FDS registers
PostPosted: Thu Jun 25, 2015 1:21 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
The wiki should describe the best known knowledge at the moment. I revised it as I did my own reverse engineering work on it last year.

NSFPlay's emulation is very close to the authentic sound. I don't have any test cases that would show a significant difference, except the discontinuous-DAC issue (which is mentioned on the Wiki, and I will add an option for in the future).

As for that video comparing the state of emulators circa 2009, I don't have much to say about them. Most emulators have only OK sound emulation. Nestopia was usually one of the better ones.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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