New music format for sequenced DS music: NCSF (potentially to replace 2SF) by CyberBotX at 2:09 AM EDT on March 27, 2013
Hello everyone. As the subject of this thread states, I have made a new PSF-style format for Nintendo DS sequenced music. I am calling it NCSF, short for Nitro Composer Sound Format, due to the fact that it uses the SDAT files made with Nitro Composer from the Nintendo DS Nitro SDK.
Full details of the format, as well as the tool(s) to make them and the Winamp plugin to play them, can be found at the NCSF Home Page.
Current listing of files will slowly grow. The process of making a good NCSF set is time consuming, although the time to create the files is much faster than making a 2SF set, and NDS to NCSF includes an automated timer, avoiding the need for sseq2mid.
I'd like to give special thanks to fincs for his work on FeOS Sound System, a library for his Nintendo DS operating system, FeOS. The library's code was adapted by me to play without the DS, and if it wasn't for this library in the first place, playing the sequences would've taken a lot more work. I also used small portions of code from DeSmuME, so thanks go out to them as well.
While stated on the home page, I'd like to point out my reasoning behind creating NCSF. While I like the idea behind 2SF, I dislike the overhead needed by the DS emulation of DeSmuME, as well as noticing that 2SFs made via VGMToolbox still write the entire SDAT to the final 2sflib (I know it "cleans" them, but the process of cleaning them is only to zero out the unused data, the file size is unchanged).
While NCSFs can have some minor playback issues (I am unsure whether this is an issue with my own code or with FeOS Sound System), I feel that it can eventually replace 2SF.
As an aside, I had to make a small change to VGMToolbox to get it to allow me to tag the minincsf files with it's xSF Tag Editor. I cannot recall where the change was, but if the demand for NCSF grows, I will work with snakemeat and any others who work on VGMToolbox into incorporating NCSF within it. I do not wish to have a 100% automated NDS to NCSF creation tool like the current NDS to 2SF tool works, but I think mostly automated with some toggles to allow for more manual operation would work better.
This is neat. While I don't see myself redoing all the sets on JoshW archive, when the time comes for pmh to do NDS sets, unless some outstanding bugs will be find with this approach, I can see this becoming the main standard for NDS rips.
I don't really mind the high level approach, we've been using this for ages, both for VGMStream and module related formats (and PSFs, I guess, what with both davironica and Mark Grass drivers).
Please give some examples about the playback issues so far, I haven't tested much, but can only say that the games that didn't work with CaitSith2's ripkit (Touch Detective, Neves) work with yours.
Some things you might consider re: NDS2NCSF:
a) I'd switch the -t behaviour, to have it enabled by default. I don't think many people will bother to RTFM, and if you output untimed sets by default, prepare for some mails/messages asking why the rips play for 2:00 for all files.
b) I'd also suggest to round them to full seconds - it currently outputs timers with 1/1000th of second resolution, which isn't really needed, I think. So, 1:37.6667 should be written as 1:38, 1:24.2222 should be written as 1:24 (saving of 4 bytes per minincsf).
c) The current trimming method could be improved - it isn't really all that great for larger SDATs. You can either go full auto, and have the tool generate thousands of SFX files in some cases, or manually toggle them by hand. I haven't really played with the exclude/include options, but would it be possible for the program to generate a (preferably SMAP) text file, listing all sequences, let the user edit that by hand (removing lines with unwanted items) and then just read that from NDS2NCSF and output only the files listed? It's what I've been using for the non-VGMToolbox 2sf sets, seems to be the fastest way to trim them.
d) I know you aren't really the person to ask this, but are there any chances for support for other drivers? Especially Procyon Studio (Layton 2-4, Soma Bringer, Luminous Arc, Shiren 4-5, list goes on) - since it's used in some of the best NDS games music-wise. There are at least few dozen games that don't use NitroComposer for music, would be nice to have a way to listen to them as well. Let me know if you need more information
e) I'm all in for adding STRM/WAVE/ADX/AHX/HCA extraction capabilities to the tool. Loads of games, even those that use mostly sequences for music use them for title themes - adding filerippers for them should be a 10-20 minutes job - just reuse VGMToolbox schemas if you need.
f) Speaking of streamed tracks - is there any way to demux the ActImagine/Mobiclip videos? Many games have their opening/ending tracks embedded in those movies - while I can just record their audio with Desmume, it'd be much better to have them in their native format.
As for tagging, I don't think there's any need for special VGMToolbox modifcation, psfpoint should work on them fine, right?
//EDIT
Ah, one more thing - you might want to look at building an option for 2SF->NCSF tag export/matching, akin to the stuff VGMToolbox does for 2SF(UF version)->2SF(CaitSith2 version). Might save a lot of time with tagging files.
a) Are you doing any SWAR optimization? Some games (Ninja Gaiden Dragon Sword for example) have only one large SWAR file and SSEQ/SBNK pairs which use it. The SWAR file is 8MB in size, only a quarter of which is used by the music SBNKs. For proper size optimization, you'd need to rebuild the SWAR file and remove the SWAVs not used by any of the selected SSEQs.
b) On that note, some games would benefit from selective sample removal from SWAR as well. For example, most music tracks from Rune Factory 3 have a water flowing sample that is always on (and I imagine, dynamically switched on/off by game logic). Would be nice to actually be able to listen to the game without that noise on top.
c) A bunch of games uses NitroComposer files for music, but don't keep them in SDAT container. Off the top of my head, Tengen Toppa Gurren Lagan required me manually building SDAT files with a hex editor. Since you do some SDAT rebuilding with your tools, how about adding a simple SDAT builder as well (merges SSEQ/SBNK/SWAR with the same filename from a dir into a single SDAT, nothing else is really needed, since you can then merge those with NDStoNCSF)
d) There are games that use invalid volume values for some of the tracks - usually setting it to zero. Rips done with VGMToolbox allowed for manually overriding this value to play those songs - does your tool do that as well? Or is that irrelevant with your method? Try Sonic Colors SEQ_glad
e) Same with tempo command override - look at Mario Kart DS 2sf rip for example - it has two version of most race tunes (normal and sped up)
e) Last on the agenda, how do you handle dynamic tracks? I recall Star Fox Command having some of them, maybe Animal Crossing: Wild World as well. Do you allow for splitting them into separate minincsf files?
And with your current code, DSI enhanced games will have wrong suffix - they use TWL instead of NTR. Not sure if you can detect that and modify the prefix automatically, if not no big deal, since it can easily be done by hand.
At the moment I don't have time to go into depth on all those, but I'll come back to these tonight and look them over more thoroughly. But thank you for looking into it.
I look forward to seeing some nice previously unripped stuff from this.
I've updated VGMToolbox in SVN to handle NCSF in the xSF tagger, XSF2EXE, the xSF Recompressor, and anywhere else xSF formats are handled generically (thanks to the nice generic nature of the PSF format and OOP interfaces). See r927. I'll update the download when time allows.
I know for a fact that Phoenix Wright: Ace Attorney: Trials and Tribulations wouldn't play with Caitsith2's 2SF driver (mostly the music exclusive to that game and not the music from the prior 2 games in it). But those songs play perfectly find through NCSF.
Re: a) I think this is a great suggestion. I might even change the -t flag so it takes an argument instead, with 0 meaning not to time and any other number being the number of loops to time for.
Re: b) This is also a good suggestion. Chances are I might go the route of always rounding up, though. I'm not sure about that yet. But I think extra time might be slightly better than less time.
Re: c) I can say that you might be right about this, since Sonic Rush Adventure was an absolute pain in the ass to work with. It has 32 separate SDATs in it, and most of them contain only 1 or 2 actual sequences with the rest being dummies that are named the same as actual ones in other SDATs. But I do like the idea of dumping to an SMAP and reading that in later for trimming purposes.
The main goal behind the trimming/merging was to make it so only a single minincsf was needed. On top of that, I didn't want to go down the route that VGMToolbox took, as I described earlier. I also didn't want to keep around sequences that were actual duplicates. Elebits: The Adventures of Kai and Zero, for example, had the same song repeated 11 times. The sequence itself was only in there as 1 file (and referenced 11 times), but it also contained 11 duplicate banks, and those were not separate files.
Re: d) I never really looked too hard into the non-SDAT sequenced formats, but I know that Luminous Arc's music is actually streams, in SAD format, but with a different header than what Professor Layton had. And PL2, from what I had seen, uses Procyon's sequenced format, which I have no idea about it's format.
Re: e) STRM is easy to add support for, since those are already in the SDATs in most cases (and hell, just searching for them instead of using the SDATs would work too). I'm sure searching for other streamed formats wouldn't be hard either, as long as they have a distinct header with size information on them.
Re: f) I've never tried doing this, and I suppose it would depend on how the audio is stored in the movie file. I can't say how easy/hard this would be without looking at one of the files, though.
Re: tagging, I didn't need VGMToolbox to tag the files, but I find that psfpoint works nicely for batch tagging multiple files with the same tags while being harder to work with for tagging individual information. I do like the suggestion of a 2SF->NCSF tag copier, I'll look into figuring this out.
Re: Knurek's second post
Re: a) I am not doing any SWAR optimization. I could look into doing so, but that would probably have to be an additional step that the tool does, as it would have to "play" the music and determine which waveforms are actually being used, and then after that, it would have to modify the SSEQs and SBNKs accordingly. I had toyed with the idea of optimizing the SBNKs when I was initially making the stripping tool, but I decided against it at the time just because of needing to edit the SSEQ.
Re: b) Hmm, perhaps for something like this, a minor edit to the specs would be in order, possibly to allow for the minincsf to edit the SDAT in the ncsflib, similar to what most of the other xSF formats do. I'll give that one some though.
Re: c) This could be done. And while I haven't tested it, I think NDS to NCSF actually will take a single SDAT as input, although there is a possibility that it'll give a strange output filename for the ncsflib if there happens to be a valid country code stored in the byte where the game code would be in a DS ROM. Although I doubt that would ever happen.
Re: d) I've not checked out the music from Sonic Colors, but I'll do so in a bit. I make no changes to any of the volumes coming in from the SSEQ itself. So if the sequence really does set the volume to 0 for that track, then it'll be 0 on playback as well.
Re: e) This might be another reason for the spec change I mentioned earlier.
Re: e2) I think it would depend on how they are laid out in the SSEQ, but currently it only outputs 1 minincsf for each SSEQ.
Re: the country code thing, I had copied those from VGMToolbox, so it is also wrong about those 2 country codes. I can fix it in NDS to NCSF, though.
Re: DSi detection, I'd probably only do this if there is an easy way to detect that the incoming file is a DSi ROM and not a DS ROM. Even the current methods don't check if the incoming file is a DS ROM, it just assumes that it is and tries to read the game code regardless.
Re: snakemeat
Thanks for doing that so quickly! I'm not sure if the change I had made to my local copy applied to all those tools (I had only been using the xSF Tag Editor with the NCSFs), but it's awesome to hear that you've made all those other tools handle them as well. :D
Re: JFD62780
I'll have to download XMPlay and see what happens. As for Sinc interpolation, I'd have to look into the algorithm for that. The current interpolation was copied from DeSmuME, which only had Linear and Cosine interpolation in it. But since I'm not limited to that, I can look into other forms of interpolation as well.
I know for a fact that PW3 wouldn't play with Caitsith2's 2SF driver (...) But those songs play perfectly find through NCSF.
Yeah, I noticed that your approach nets more playable files, but what I'm actually interested in are examples of songs that don't work with NCSF currently -> While NCSFs can have some minor playback issues.
I might even change the -t flag so it takes an argument instead
As long as it defaults to 2, no problems with me. :) I also don't see any problems with applying ceil() function to timers.
Sonic Rush Adventure was an absolute pain in the ass to work with. It has 32 separate SDATs
Have fun with Pokemon White/Black - ~3000 sequences IIRC, 90% of which are SFX. Should take a few seconds to trim with SMAP file, but manually selecting all BGM entries (without an undo function, I should add) will take... dunno, 10-20 minutes, I guess. 2sf->ncsf matching should be really easy to add, especially if you stick with CaitSith2 format only - both mini2sf and minincsf should only have a matching sequence number, so all you really need to do is unpack them and compare. :)
Elebits: The Adventures of Kai and Zero, for example, had the same song repeated 11 times. The sequence itself was only in there as 1 file (and referenced 11 times), but it also contained 11 duplicate banks, and those were not separate files.
Please take caution with that, there are games that use the same SSEQ with a bunch of different SBNK to have the same song play with different instruments. At least a binary compare should be done on all suspect SBNK (I didn't read the source, so I can't say if you're doing that already). Preferably SBNK+SWAR parsing and then binary compare on all data used by each song variation (SSEQ+SBNK+SWAVs)
but I know that Luminous Arc's music is actually streams, in SAD format
Uhh, no, there are a few SAD streams, true, but most of the game music is sequenced. Procyon Studio format, matching *.smd and *.swd files. Both are completely different than NitroComposer stuff, and as such would require loads more effort/skill to play than I have. I'll upload some ActImagine/Mobiclip examples later. Both should just use IMA ADPCM, but it's muxed with the video stream.
STRM is easy to add (..) (and hell, just searching for them instead of using the SDATs would work too).
But you loose the filename information then. I'd stick with SDAT extraction for them. :)
I am not doing any SWAR optimization. I could look into doing so, but that would probably have to be an additional step that the tool does, as it would have to "play" the music and determine which waveforms are actually being used, and then after that, it would have to modify the SSEQs and SBNKs accordingly. I had toyed with the idea of optimizing the SBNKs when I was initially making the stripping tool, but I decided against it at the time just because of needing to edit the SSEQ.
Please note that many games (especially those made later in systems lifetime) use the same approach as Ninja Gaiden Dragon Sword - single SWAR file with all instruments/SFX. That game is the extreme example though - it has only two sequenced music files, totaling at around 1MB of instruments, rest of the SWAR file is SFX. NCSF rip could be optimized by around 90% size-wise if you'd add SWAR rebuilding.
That said, I don't think you need to parse/change the SSEQ in any way to do the optimization.
For each ripped SSEQ, find the matching SBNK. Parse SBNK, note which SWAR files it uses (up to 4 can be used IIRC), then note down instruments used for each SWAR file (that data is in SBNK AFAIR). Repeat for all user-selected SSEQ files, then rebuild each SWAR used - just null the unused SWAVs, so that you don't have to touch SSEQs).
It's a lot of work, but as you said yourself - you don't want to have files larger than required. This is the biggest size optimization you're not doing already that I can think of.
I make no changes to any of the volumes coming in from the SSEQ itself. So if the sequence really does set the volume to 0 for that track, then it'll be 0 on playback as well.
The volume data I'm talking about is in SDAT header, the SSEQs themselves do not set it to 0.
INFO block of SDAT,
typedef struct tagSDATInfoSseq { u16 fileID; // for accessing this file u16 unknown; u16 bnk; // Associated BANK u8 vol; // Volume (...) } SDATINFOSSEQ;
For 2sf ripping, changing that value from zero to, uhh, default value (can't recall what it was ATM) fixes some unplayable songs. Not sure if it's needed with your approach.
DSi detection, I'd probably only do this if there is an easy way to detect that the incoming file is a DSi ROM and not a DS ROM.
According to this byte 0x1C0 in the header not being 0x000000000 should do the trick. Haven't verified versus actual NDS files though. Like I said, don't spend too much time at this, it's easily fixable with any mass-rename capable tool.
I'll have to download XMPlay and see what happens.
Easily reproducible - the whole player crashes in in_ncsf.dll as soon as you stop (not pause) the music. No problems like that with vio2sf or any other winamp plugins.
Odd thing is, when I mentioned that some NCSFs were not playing correctly, my example was track 2 of Time Hollow, Fragment of Memories. I don't know if I had fixed something since I made the NCSF rip, but there was a note that sounded like it was getting cut off early. But after I applied ReplayGain to the tracks and checked it again, it sounded identical to my current 2SF of the song. So I have no idea where it got fixed.
At the moment, I am actually doing a full binary compare of every file when checking for duplicates, so if 2 duplicate SSEQs use 2 separate SBNKs, they will not be considered duplicates.
I'll still look into SWAR optimization, but I'm not going to put it at a high point on my list of things.
Originally I was going to use the vol value from the INFO header for the SSEQs, but I found some songs just were not working properly when utilizing it, so I decided to just not use it at all. I can't recall the example, but I think it was one of the tracks from Ace Attorney Investigations: Miles Edgeworth.
I'll look into the crash, I'm sure it would probably also affect my 3 other plugins that I've made which use the same framework (I have ones for SNSF, GSF, and 2SF, all based on the vio*sf plugins [with SNSF being based on Caitsith2's plugin as well], which is why I haven't released those ones yet).
I forgot to ask, CaitSith's rip are playable on real hardware (verified that myself), yours will not work though since the playback routine is high level, is that correct?