What's a good NSF(E) player these days?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
What's a good NSF(E) player these days?
by on (#239843)
What's a good program these days to play nsf(e) files?
Back in the day I used Meridian to play my game music, but at some point that program stopped running properly on my computer, I think when I switched to a 64-bit OS.
Today I've got plug-ins in Winamp that I use, and most work pretty well. For NSF files I use NotSo Fatso. But it doesn't work quite as well as I would like. I think Winamp has this process of normalizing music, because I can hear it slightly increasing the volume of my SNES music files as it figures out how loud the music really is. And with the NSF files, it swallows a bit of that very first note in a track and it quickly fades in.

It's a little annoying, but what really bothers me is that I can't get a even and clean version to record so I can transfer a song to mp3, for those times when I want to play a song on another device.
Winamp has some great options to automatically copy songs to a new mp3 file, with far more ease and speed than when I used to record my computer's audio while running Meridian. But if Winamp doesn't play the song flawlessly, then it simply isn't a viable solution.
Plus NotSoFatso treats the entire NSF file like a single track within winamp, and I have to use a special dialogue box to control the song playback.

So I'm wondering what's another good option for playing NSF files on a modern computer these days. Bonus points for a program that can also transfer an NSFE file into a collection of mp3's.
Re: What's a good NSF(E) player these days?
by on (#239850)
NSFPlay, maintained by rainwarrior, is probably the best choice under Windows or Wine.
Re: What's a good NSF(E) player these days?
by on (#239862)
Well, the standalone player is certainly working properly. (Though using it is making me miss Meridian.) And it lets me save files as a wav, and I can convert that to an MP3 without too much trouble.
Except that for some reason my Dragon Warrior and Dragon Warrior 2 files don't play properly. I get silence on the first and a sustained square beep on the second. I tried a couple other randomly-selected files and they run fine. It does the same thing with the Winamp plugin. But the NotSoFatso plugin plays them just fine.

As far as the Winamp plugin is concerned, it seems to have the same problem as NotSoFatso in that the song "fades in" for a brief moment at the start. (I imagine it's a fault of Winamp and can't be overcome with a plugin, but that's just speculation.) And since Winamp still treats the nsfe file as "one file" the navigation controls don't skip between tracks inside the file, but jumps straight to the next file. So this makes this plugin less usable than NotSoFatso, which at least gives me a custom window with navigation controls. (Though the way it changes the track name in the player is nice.)
What I really would want from an NSF(E) plugin for Winamp is one that splits the file into individual tracks, like when I play .rsn files. When I try to play an rsn file, Winamp suddenly populates my playlist with all the individual tracks from that file. I don't know what plugin they are using though.
But... while trying to see if I could get that information, I saw some file info that makes me think the rsn file is just a zip-like file containing individual spc files. If that's the case, then this is a file-format issue, not a plugin issue. I guess we couldn't resolve this without making a new format that just contains several NSFE files of individual tracks. I mean, I'd be down for doing that, but I don't know how many other people would share my interest.

Random sidenote: I got curious and tried looking up what happened to Meridian Advance. Apparently the original author lost his source code. So he started up a new version called Meridian Prime which was open-source. However the only site I can find that acknowledges Meridian Prime doesn't show any updates since 2003. And Meridian Prime never got all the features implemented that Meridian Advance had; it currently only supports NSF files. Also finding info on this program is hard, since most search results turn up a modern android music app called Meridian.
Re: What's a good NSF(E) player these days?
by on (#239865)
Checking the Dragon Warrior and Dragon Warrior II NSF rips, these seem to have a problem in NSFPlay 2.4, but they worked previously.

In the options, in the bottom right of the panel there is an "IRQ Support" checkbox. Uncheck this and they will work.

I'll have to look into whether these are bad rips, or if the new IRQ support features (for NSF2) have a bug that makes this a false positive, but for the mean while you can use that option to get it to work. (Or use 2.3 instead, if you prefer.)

I too would like a Winamp track expansion like you're describing, but I have been putting off researching how to do this until NSFPlay 3.0. If you could provide an open source example, or some good documentation on how to do it maybe I could sneak it into 2.5 though. I plan to write a more robust playlist UI in general for 3.0, so I'm trying to avoid writing too many new features that I'm just going to throw away in 3.0. (3.0 will be the next version after 2.5)

There is a separate track advance UI within the info page, however. It doesn't open by default but in Winamp you can double click the track name to open the info page which has a "song selector" at the bottom.
Re: What's a good NSF(E) player these days?
by on (#239867)
I remember I tried a few times to rerip Dragon Quest 1 and Dragon Warrior.
It turns out that the sound driver is completely different between regions.
Re: What's a good NSF(E) player these days?
by on (#239878)
K, I disabled the IRQ box and its working.

rainwarrior wrote:
I too would like a Winamp track expansion like you're describing, but I have been putting off researching how to do this until NSFPlay 3.0. If you could provide an open source example, or some good documentation on how to do it maybe I could sneak it into 2.5 though.


Okay, I just tracked down some info on what is going on when I play .rsn files in Winamp, and I found this little tidbit out about them:

Quote:
All archives are RAR files (version 3) renamed to RSN, you can easily rename them back to RAR and open them with your favorite program capable of opening and viewing standard RAR files.

So yeah, it's literally just a .rar file containing all of the .spc files in it.
So if we want to have track expansions in Winamp, the only feasible way I see to do this is:
1) Take an nsfe file, extract all the tracks into separate files so that each track is its own .nsfe file.
2) Combine all these files into one zip file
3) Rename zip file to a new extension, like maybe .nsfz
4) Make the plugin recognize the nsfz format. This, of course, is the hard part.
I'm looking around, but I don't see any open-source plugins for Winamp that read the .rsn file format, but maybe you could ask the developers of SNES Amp how they get winamp to read a compressed file?

I'd like to be of more help than this, but this is a bit outside of my programming "abilities."
Re: What's a good NSF(E) player these days?
by on (#239879)
So, the short of it is, Winamp is stupid. It does not particularly allow you to "queue up" (in the playlist) multiple songs that are stored within a single file. The playlist is literally architected to reference physical files on disk; Winamp supports absolutely nothing else. I will describe this in detail for RSN below, but here's what you need to know:

Think about what now has to happen with NSFE: you have to quite literally split the NSFE file up into N separate NSF files, write them all to disk, and then build the playlist with IPC_ENQUEUEFILE. This is pretty ugly/terrible: think about those NSFEs that have hundreds of songs. You now get to extract hundreds of files to disk, which means lots of disk I/O and wasted disk space just to play what is essentially a single file, and you risk causing Winamp to block/stall (i.e. could report "Not responding") while the plugin does this, depending on all sorts of variables. If the source file is on a CIFS/SMB share, or a USB stick, or whatever else, it means tons of network I/O or silly writes to the USB media. Additionally -- and this is a HUGE one -- if Winamp crashes, which I have had happen with NSFPlay on rare occasion (I still can't pinpoint what I'm doing that causes it), nothing is going to clean up all those files on disk so you now have junk laying around somewhere. I imagine all of this is partially what's been plaguing rainwarrior for some time now and why he has to think long and hard about how (or if) he wants to try and solve it.

The RAR loading/extraction routines for RSN are compiled/built into the plugin itself, using unrar.dll from the official RAR owner/maintainer. Winamp does not do archive decompression or management natively in any way. SNESAmp hooks into the DLL by loading it at runtime and then using GetProcAddress to find the locations of the functions it cares about -- RAROpenArchive (using RAR_OM_EXTRACT) and RARProcessFile are the two relevant ones. RARProcessFile, when given a valid open archive, will extract the relevant file from the archive into a directory of your choice -- but if you pass NULL as the parameter, which SNESAmp does via rar.ProcessFile(rh, RAR_TEST, NULL, NULL);, it extracts the file into the current working directory, then tells Winamp "here's the path to the extracted file" + adding it to the playlist. So, in other words: it does things exactly like how I just described in my above paragraph. RAR is a somewhat "touchy" format licensing-wise as well, but whatever. Here's the terrible code (which is compatible with Winamp 2.x, so you won't see IPC_ENQUEUEFILE mentioned -- it instead does things the old/hard way):

Code:
   case(ID6_UNK):                        //File was unknown, it could be a RAR file
      if (!xpl || !rar.GetDllVersion || parsing) return ID6_UNK;

      parsing = 1;                     //RAR file is being parsed

      //Open RSN file ------------------------
      memset(&ropen, 0, sizeof(RAROpenArchiveData));
      ropen.ArcName   = fn;
      ropen.OpenMode   = RAR_OM_EXTRACT;//LIST;

      rh = rar.OpenArchive(&ropen);
      if (!rh) goto Error;

      rf.pData = NULL;
      rf.alloc = 0;
      rf.size = -1;
      rar.SetCallback(rh, RARCallback, (s32)&rf);

      //Get pointer to internal filename -----
      strcpy(str, fn);
      s = ::StrEnd(str);
      *s++ = '\\';

      setCur = 0;                        //Initial file hasn't been found yet

      cds.dwData = IPC_PLAYFILE;
      cds.lpData = str;

      while(!rar.ReadHeader(rh, &rhdr))
      {
         if ((rhdr.Flags & 0xE0) != 0xE0)
         {
            if (!strcmpi(ScanStrR(rhdr.FileName, '.'), "spc"))
            {
               strcpy(s, rhdr.FileName);

               //Extract file -------------
               rf.size = 0;
               rar.ProcessFile(rh, RAR_TEST, NULL, NULL);

               lastType = lastID6.LoadTag(rf.pData, rf.size);
               strcpy(lastID6.file, str);
               lastRAR = 1;

               if (lastType == ID6_SPC || lastType == ID6_EXT)
                  memcpy(lastFile, rf.pData, 0x10200);
               else
                  lastType = ID6_UNK;

               rf.size = -1;

               //Add file to playlist -----
               if (!setCur)            //If this is the first SPC, change current PL file
               {
                  SendMessage(inMod.hMainWindow, WM_WA_IPC, (WPARAM)str, IPC_CHANGECURRENTFILE);
                  setCur = 1;
               }
               else                  //Otherwise add the file to the play list
               {
                  cds.cbData = strlen(str) + 1;
                  SendMessage(inMod.hMainWindow, WM_COPYDATA, (WPARAM)0, (LPARAM)&cds);
               }

               continue;
            }
         }

         if (rar.ProcessFile(rh, RAR_SKIP, NULL, NULL)) break;
      }

      if (rf.pData) free(rf.pData);
      rar.CloseArchive(rh);

You can read a "general" comprehension of how unrar.dll functions behave here (ignore the fact this is for Python, it doesn't matter): https://python-unrar.readthedocs.io/en/ ... manual.txt

You can get the SNESAmp source here (does not include unrar.dll -- that is included with the SNESAmp installer, and the DLL ends up in your Winamp plugins dir (yes really)): https://www.alpha-ii.com/Source/index.html

Circling back:

You can blame Winamp for all of this nonsense. It was never, ever intended to be able to "play multiple songs from a single file", and .m3u/m3u8 won't work either (that is just a on-disk playlist of filenames also on the disk). Winamp, in every way/shape/form, expects physical files on the disk for its playlist. It was designed to be an MP3 player. I think sometimes people forget that. So, any plugin you see that supports a file format with multiple songs within a single file has to extract the files to disk somewhere for the Winamp playlist to be able to work with it. What's going on under the hood is hidden from you, but this is what's going on.

Now I hope you understand how/why NSFPlug/NSFPlay works the way it does with its native plugin song UI/dialog selector. Yes, I too would love for it to work in the playlist, but once I saw how it has to be done, I learned to not complain and just use it.

I think with NSFPlay (not NSFPlug!) it will be 100% possible to have a kind of "song playlist" natively within the program. But with Winamp, nope, not gonna happen.

Finally: I should add that music formats, *ESPECIALLY* those with compression wrappers, have been under extreme scrutiny in the past several years for security-related problems: such as allowing someone to inject a malicious file into the archive and due to bugs in the decompressor, running code when the file is loaded (song is played). I really have to suggest not going this route if it can be avoided. The one format that's been generally pretty good over the years is VGZ (multiple VGMs in a zlib/gzip archive), but again, the process is the same as I just described.
Re: What's a good NSF(E) player these days?
by on (#239912)
Geez, the stuff people on this forum know never ceases to astound me. I mean, you are citing the specific functions and everything.

Okay, the point about security is pretty relevant.

I guess then the best thing I could ask for is a tool that easily splits a nsfe file into an nsfe file for each track, just so I can have each track as a separate entity for my own listening pleasure.