Page 1 of 3

NSFPlay 2.1

Posted: Tue Mar 27, 2012 7:14 pm
by rainwarrior
I have begun to maintain NSFPlay/NSFPlug, and a new version is ready. If anyone is interested in an updated version it is available here:

Version history:

NSFPlay 2.1 - 3/27/2012
Audio Output:
- Fixed race condition in audio buffering; stand alone NSFPlay would occasionally get stuck stuttering.
- Produces stereo output, channel mixer dialog for panning and per-channel volume control.
- Fixed PCM playback speed; CPU execution was counting requested clocks, not clocks executed.
- Fixed accuracy of seek times.
- Loop detection now accounts for all audio registers, not just a subset of 2A03 and N163.
- N163 wavelength is actually 6-bit, not 3. Now allows sample length up to 256.
- Fixed FDS volume/sweep envelope caps. (Direct register writes can make them louder.)
- Fixed FDS modulation bias calculation and wrapping.
- Set default volume for VRC7 and FDS a little lower (to match expected levels).
- MMC5 PCM support (for both read and write mode).
- Added phase reset option to MMC5.
- MMC5 was missing length counter and audio register reads; rewrote to conform with APU.
- Adjusted phases for APU/MMC5 square channels to match NesDev's description.
- APU/DMC/MMC5 rewrite of envelope/length/sweep behaviour to use a frame sequencer instead of independent timers.
- Option to randomize noise on reset (on by default).
- Options cleanup, removed unused/deprecated options from .ini file.
- Using global LPF by default instead of on each device (saves CPU, same result).
- Keyboard view channel colour is now customizable in .ini file (CHANNEL_XX_COL).
Keyboard view:
- Fixed crash due to keyboard OnTimer being allowed before Reset() is executed by the PlayThread.
- Double buffering keyboard view to remove flicker.
- Different colours for different expansions in keyboard view.
- Fixed sound lag after seek.
- FME-7 now named 5B, N106 now named N163.
- DPCM now named DMC in keyboard view.
- Fixed 5B volume display (E now correctly indicates envelope, volume is now correct value).
- 5B now displays envelope and noise.
- VRC6 saw volume now displays accumulator register.
- Corrected VRC6 saw pitch in keyboard view.
- Fixed trailing lines on N163 waveform display.
- DMC volume display no longer flipped (is now $4011 register value).
- DMC now shows sample frequency rather than byte frequency.
- Triangle and noise were not showing muting due to length counter of 0.
- Noise now has frequency display (either rate of random samples, or tonal frequency for periodic noise).
- Removed feature that extends the life of key dots beyond the frame the channel is active (frequency can change when key is silent, esp. VRC6 squares, which visibly jump to the wrong pitch)
- Save WAV button on NSFPlay.
- Command line WAV output for batch processing.
- Added extra NSF header information to "misc" text box, initial banks, load/init/play addresses, etc.
- Fixed thread-safety issue for configuration (was accessed liberally from many threads).
- Removed legacy code for windows versions older than XP.

NSFPlay 2.0 - 2/22/2012
- Restructured sln/vcproj files, and rebuilt for VS9.
- All intermediate files go into common Debug/Release directories.
- Renamed wa2nsf project to in_yansf to match name of the plugin.
- Fixed improperly set WAVEFORMATEX header in libemuwa2 (allows execution on windows Vista/7).
- Corrected pitch of noise channel.
- Updated VRC7 default patch set.
- Added PAL support and pal flags indicator (PREFER_PAL=1 to prefer PAL for dual mode).
- Added about box for determining build version.
- Fixed some menu items in English dialogs.
- Fixed some initial config settings.
- Fixed crash when using playlist menu options with no loaded NSF.

NSFPlay - 12/09/2006
- Written by Brezza >

Posted: Wed Mar 28, 2012 12:00 am
by koitsu
Wow, looks like something I can use to replace my ageing copy of NotSoFatso! :-)

One thing I've noticed, however, when using the Winamp plugin version: the vumetres / oscilloscope aren't in sync with the actual audio playback. It looks like the visuals start maybe 0.5 seconds too soon. This is the only plugin I see this behaviour with (NotSoFatso for example doesn't behave this way).

Anything I can do to help/debug this?

Posted: Wed Mar 28, 2012 12:36 am
by rainwarrior
Hmm, that's odd. Yeah, I do see a small lead time (maybe 1/6 of a second); it's really just feeding samples to the visualizer as it writes them to the output, maybe it's necessary to stick in a delay. I dunno. I'll put it on my list of things to look at for the next version, but it is not something that seems terribly important (I will fix it if it doesn't take too much time).

Posted: Wed Mar 28, 2012 1:58 pm
by koitsu
I have a different theory based on the behaviour:

It looks like, for example, when clicking Play on a song, the visuals (metres + osc) start immediately, then the audio kicks in 1/6th or 0.5 seconds late.

So it may be that the delay is in when the actual audio playback begins, rather than the visuals "trailing behind". I'm trying to say that I think the audio waveform generation appears to be done immediately (and fed into Winamp immediately, since the visuals start immediately), but the actual audio playback seems to be buffered.

I went looking at the source to see if I could find anything in there that stuck out like a sore thumb, but it's C++, extremely Windows-oriented and Winamp-API-oriented, thus difficult for me to discern what's what. I was trying to see if there's some kind of plugin or playback engine buffering that's going on which would explain it.

I wonder if this is one of the buffering options I have set in Winamp, although I think those are all for streaming (e.g. Shoutcast streams), which wouldn't be relevant here.

Posted: Wed Mar 28, 2012 2:46 pm
by rainwarrior
The visualizer is handed data from SAAddPCMData and VSAAddPCMData in in_module.cpp. Both of these come with a timestamp, however, so I think Winamp is supposed to store them and display the correct one when it's being played.

I can add an arbitrary delay to the timestamp as a hack solution, but I don't think that's really the correct way to fix it, because looking at other plugin sources I don't see anybody else doing that.

Edit: ah, I've found the problem. Winamp's visualizer expects to recieve 576 samples at a time, but the plugin was producing 2048. This was fine for playback, but seems to introduce timing inaccuracy for the visualizer. So... this will be fixed in the next version.

Posted: Wed Mar 28, 2012 4:45 pm
by koitsu
Wahoo! I like how they picked some arbitrary value. 576, man. Cuz you know, 576 is better than 459, and it's not as hefty as 2048. Makes lots of sense you know. (Nullsoft... sigh...)

Thanks for looking into this, rainwarrior. <3

Posted: Thu Mar 29, 2012 7:15 am
by tepples
koitsu wrote:Wahoo! I like how they picked some arbitrary value. 576, man.
MP3 operates in 576-sample granules. I imagine that this size dictated a lot of the internal data structures of early Winamp.

Posted: Thu Mar 29, 2012 8:18 am
by rainwarrior
By the way, there was a mistake in ppMCK prior to 2007 with the N163, and NSFs from before then have a problem playing back in NSFPlay (and also NezPlug++, and real hardware AFAIK). The problem stems from poor knowledge of the sample length register, which uses 6 bits for length and not just 3.

Here's a quick fix, if you run into these:

1. You'll need a hex editor. Search the NSF for a string of the following form:

Code: Select all

09 80 9D ?? 06 8D 00 48
There should only be one string that fits this form, and it's probably at an offset in the range $0D00-$1300 somewhere. If there's more than one, something else may be going on.

2. Replace the 80 in that string with E0:

Code: Select all

09 E0 9D ?? 06 8D 00 48
3. Save it, and you should be good.

If you can't find this string in the bad NSF file, then let me know.

For the curious, that string means:

Code: Select all

09 80    = ORA $80
9D ?? 06 = STA $06??, X  ;  (RAM variable)
8D 00 48 = STA $4800     ;  (N163 register)
Changing $80 to $E0 sets all three of the top bits, which unless they are all set will contribute to the length of the sample (making it too long). Old ppMCK versions assumed a maximum sample length of 32, and thought that the high bit was simply an enable bit (it is not, it subtracts 128 from the maximum sample length of 256, the other two bits we are setting subtract 64 and 32).

Posted: Mon Jun 25, 2012 1:43 am
by koitsu
rainwarrior, has there been any development on this? Sorry to sound like I'm expecting some degree of support, I'm not :-) Just curious if there is a debug or test build available with the 576-sample fix.

...I guess I could snag the source and take a stab at it myself. From briefly skimming the source, I assume this requires Visual Studio (I see vcproj files...)? What version of Visual Studio is this known to compile correctly with? I might have to make an XP VM just to deal with this, since I never install Microsoft devtools (they're always a complete clusterfuck) on my native system...

EDIT: Is the 2048 sample count defined in WA2InputModule::PlayThread()? Relevant code below...

EDIT #2: And shouldn't blank_time's divisor (48000) be based on the selected playback sample rate in the GUI (which is usually 44100)?

Code: Select all

DWORD WINAPI __stdcall WA2InputModule::PlayThread(WA2InputModule *_t)
  xgm::INT16 *packet_buf;
  int packet_size = 2048 * _t->nch * _t->bps / 8; // バッファサイズ2048bytes固定
  int blank_time = 10 * _t->rate / 48000; // 最初の数パケットは無音にする(DirectX plugin対策)
  int wsize; // dsp処理後の書き込みサイズ
  int sample_size = _t->nch * _t->bps / 8;

Posted: Mon Jun 25, 2012 10:33 am
by rainwarrior
Yes I have been working on NSFPlay, though it is not my only ongoing project. I am not really expecting to release a new version for a few months.

I do have the fix for the winamp visualizer. The fix is a few lines different in in_module.cpp; if you want the code or a quick build now, e-mail me or PM me. I've been considering lately moving the code into a public repository like Google Code, haven't gotten around to that yet. (edit: okay I've moved it to Google Code, see below)

I wasn't planning to release a new version until I had more significant changes to post. I've mostly been doing hardware tests to verify the emulation accuracy:
- famicom expansions
- linear counter
- MMC5

The accuracy is actually pretty good in most cases. N163 needs a complete rewrite, more or less, to accomodate for new information about it, and the VRC7, even though it's "pretty good", is going to take a lot of work to fix the lingering differences from the real thing.

Edit: I have moved my development workspace for this project to Google Code, in case anybody wants to watch me code things very slowly.

Re: NSFPlay 2.1

Posted: Mon Aug 20, 2012 11:34 am
by rainwarrior
Beta testing for version 2.2 begins:

--- file removed, beta over ---

Let me know if you find any problems with this. When I stop getting bug reports I'll do a proper release. The main change is NSFe support, but here's a complete list:

Audio Emulation:
- Unmute on reset now sets $4015 to $0F instead of $1F.
- PAL noise frequency $1 now 8 instead of incorrectly 7.
- New VRC7 patch set, option to select alternative patch sets via VRC7_PATCH.
- 5B polarity inverted, envelope adjusted, volume tweak.
- MMC5 polarity inverted, length counter runs at double speed, highest 8 frequencies are not muted.
- VRC6 $9003 register implemented (controls halt and frequency multiplier)
- VRC6 polarity inverted, phase reset now functions properly.
- FDS now uses NSF header $76/$77 to set up $6000-7FFF memory range.
- Fixed improper $4015 read implementation (should return length counter status), also DPCM IRQ was not initialized.
- Default focus in keyboard window now the track list (to prevent accidental mouse scroll time expansion).
- Fixed Winamp visualizer timing inaccuracy, changed default keyboard delay/freq.
- Inverted VRC7 volume display in keyboard view.
- NSFe support.
- Added NSFe extension block 'text', contains null terminated string of any length (NSF text).
- Removed broken ENABLE_DCF config option. HPF=256 now correctly disables HPF.
- Rewrote LPF and HPF, should have a more usable range of options now.
- Removed XXX_FR/XXX_FC options, now XXX_FILTER works like LPF for each device.
- Memory R/W access is now exclusive to the first device that accepts it; prevents FDS multi-expansion write conflicts.

Beta versions:

2.2 beta 0 - 8/20/2012
- first beta release

2.2 beta 1
- fixed loop detector bug (false positives causing some NSFs to fade out at 30s)

2.2 beta 2 - 8/26/2012
- fix incorrect pitch on PAL with QUALITY=0
- fix conflicts between keyboard commands and menus
- fix enable periodic noise
- strip whitespace from title string ends
- FDS $4087 bit 7 now silences modulator
- documetation

2.2 beta 3 - 8/28/2012
- fix NSFe bug where track list is not in NSF order (had incorrect playtimes)

Re: NSFPlay 2.1

Posted: Tue Aug 21, 2012 4:37 am
by B00daW
I'm still looking for more bugs, but as for GUI issues:

- NSFe track titles do not appear on the front of the GUI.
- Channel and keyboard note coloration should be the same in keyboard view. Ex: If the SQR0 note on the keyboard is red, SQR0 should be red.

Re: NSFPlay 2.1

Posted: Tue Aug 21, 2012 7:23 am
by rainwarrior
Hmm, the track title should appear as you have specified in the TITLE_FORMAT option. I forgot to document it but %L/%l is the NSFe song title. The default string should be "%L (%n/%e) %T - %A" unless you've replaced it or are using an old in_yansf.ini file.

As for the colour indicators, I'll think about some way of doing that in a future version.

Re: NSFPlay 2.1

Posted: Tue Aug 21, 2012 11:41 am
by B00daW
I overwrote my old INI file. The NSFe track titles show within the media player, in my case XMPlay, but they do not show up in the NSFPlay GUI.

Re: NSFPlay 2.1

Posted: Tue Aug 21, 2012 12:48 pm
by rainwarrior
Hmm, it's working on my end. Could you attach an example NSFe that doesn't show its track names?