Main » Projects » NSF/SPC to MIDI automated converter project » New reply
    You are about to bump an old thread. This is usually a very bad idea. Please think about what you are about to do before you press the Post button.
    New reply
    Post help


    [b]…[/b] — bold type
    [i]…[/i] — italic
    [u]…[/u] — underlined
    [s]…[/s] — strikethrough
    [code]…[/code] — code block
    [spoiler]…[/spoiler] — spoiler block
    [source]…[/source] — colorcoded block, assuming C#
    [source=…]…[/source] — colorcoded block, specific language[which?]
    [abbr=…]…[/abbr] — abbreviation
    [color=…]…[/color] — set text color
    [jest]…[/jest] — you're kidding
    [sarcasm]…[/sarcasm] — you're not kidding


    [img]http://…[/img] — insert image
    >>… — link to post by ID
    [user=##] — link to user's profile by ID


    [quote]…[/quote] — untitled quote
    [quote=…]…[/quote] — "Posted by …"
    [quote="…" id="…"]…[/quote] — ""Post by …" with link by post ID


    [youtube]…[/youtube] — video ID only please
    Thread review
    NTI There was SFM, however:
    Posted by byuu
    we got bogged down because a true state capture has internal variables, and different emulators will want to name those fields differently (they definitely don't have official names.) Some emulators won't even support certain state fields, others may require new ones not yet known for a perfect capture. Forking the format with emulator-specific sections is the worst possible thing you can do.

    Oh, well...
    creaothceann There's SNSF, though I'm not sure if byuu or someone else didn't release another format (recording all the data that is sent over the CPU->APU interface?).
    Kakashi What happened to that new format that replaced SPC?
    CaptainJistuce Hooray!
    jsd1982 Finally, a working SPC player!

    I found some code from bsnes-plus which is able to plays SPCs and was able to get my code working. I think the key was initializing the SMP and DSP internal registers.
    jsd1982 Exactly. The SPC file format only includes the state of the SPC and DSP. I've loaded in the SPC registers PC, A, X, Y, P, and S. Also loaded in the 128 DSP registers for voice control and others.

    My test SPC tracks include f-zero, jurassic park, zelda 3. Every SPC I've tried exhibits this behavior of just stopping after the first chord, so it must be something I'm missing in my player.

    The DSP sounds right, since the instruments sound correct and ring out, so the problem must be in the SPC side. I've got the IPL ROM loaded in, and I've tried both both the IPL from higan/bsnes and the 64 bytes at the end of the SPC file. Neither affect the outcome differently.
    Nicholas Steel Afaik although the SPU does not need continual guidance from the CPU (unlike on the NES?) it still needs the CPU to tell it to begin playback and when to switch songs etc.
    Posted by jsd1982
    I've set up the emulator to disable the SNES CPU and PPU, leaving only the SMP and DSP running. I load up the SPC RAM and registers and the DSP registers from the SPC file and start the emulator but I only get the first note/chord of music and then the instruments just ring out and no further music is played. I think the SPC700 is waiting on something to continue but I'm not sure what.

    From what game is the SPC file? Tried others?
    Screwtape But the SPC file-format only provides initial registers and RAM content for the SPC, it doesn't give the CPU anything to do. So what should an SPC-player do?
    funkyass in rough strokes, the SPC is an instrument played by the CPU.
    jsd1982 Can you elaborate on "two timing crystals"? I realize the SPC and cpu run at different rates and are largely independent except for the communication registers. The SPC emulation treats them as ram when written to and read from. The cpu can of course write to them as well. Is there an implied tiny cpu support program I need to emulate that responds to certain SPC requests?
    jsd1982 Any idea what in particular it's waiting for from the cpu? I was fairly certain I wouldn't have to emulate the cpu for a SPC player.

    Maybe I just need to emulate the cpu responses or write-back? SPC player documentation is nearly non-existent. The file spec is documented but the emulation process and semantics are not.
    Kakashi Yup. Two timing crystals.
    funkyass its waiting on the CPU.
    jsd1982 I've hit a snag in my SPC player. Can anyone help me out here?

    I've set up the emulator to disable the SNES CPU and PPU, leaving only the SMP and DSP running. I load up the SPC RAM and registers and the DSP registers from the SPC file and start the emulator but I only get the first note/chord of music and then the instruments just ring out and no further music is played. I think the SPC700 is waiting on something to continue but I'm not sure what.
    jsd1982 I now have a working NSF player that supports both bank-switched and non-bank-switched NSFs. NSF file and track may be selected by command line argument.

    Next milestone is an SPC player which looks not too difficult to implement.
    neologix FWIW, Kode54 maintains an updated version of GME within his various audio projects like foo_gep and I don't remember which service he prefers to host on, though, but I'm 95% sure there's a link to the foo_gep source on the foo_gep page on Foobar2000's site.
    jsd1982 Just thought I'd announce that I'm starting to work on a standalone NSF/SPC player based on higan source code.

    For those curious to watch my progress, I'm hosting the code on

    Obviously, no warantee nor guarantee of functionality here. It's just a very early work in progress.

    Once compiled, it produces a console application that emits a WAV file given an input NSF file passed as a commandline argument, if it works at all. It's woefully incomplete and doesn't play most NSFs at the moment. I'm currently working on creating a custom cartridge Board (aka mapper) implementation of the custom iNES mapper 031 to better support NSFs since most seem to require/expect it.

    This project is actually more of a stepping stone to my ultimate goal of writing an NSF (and SPC) to MIDI converter. The first milestone is to get a working NSF player, or more simply an NSF to WAV converter. After that I'll augment the APU code to do the MIDI conversion work.

    I've actually already prototyped out my NSF/SPC to MIDI converter project based on libgme sources. However, its lack of emulation accuracy was causing issues that couldn't easily be resolved without an impossibly large refactoring or rewrite due to the way it emulates the systems. You can find that effort here:

    NSF is fairly trivial to convert to MIDI because the melodic channels (pulse and triangle) all provide absolute pitch information, so simply taking the log2(pitch / 55.0) * 12 + 36 yields a standard MIDI note number representing the pitch, largely solving the problem. After that you can do more nuanced heuristics to support pitch wheel changes, channel changes, patch changes, etc. It's a fun problem to solve iteratively and listen to your results as the process evolves to produce better and better sounding results.

    SPC poses a little bit more of a challenge to convert to MIDI than does NSF. The primary reason being that the SPC is just 8 channels of digital samplers, and the instruments sampled are basically PCM waveforms (after decoding from BRR). The reason this poses a challenge is because the SPC's pitch registers only provide a relative-pitch resampling of the original sample (-2 oct to +2 oct, and lots of semitones in between); there is no absolute pitch information readily available to the SPC. One would have to somehow "know" the absolute pitch of the recorded sample. In practice, there is no "standard" pitch at which to sample an instrument so no real assumption can be made that would cover all samples.

    I've had very good success with identifying the fundamental pitch of a PCM sampled instrument by running an FFT (Fast Fourier Transform) over its looped section and using some heuristics to identify the lowest-pitched highest peak which I presume to be the fundamental pitch of the instrument. If one naively grabs simply the highest peak you will get some false-positives due to some instruments having stronger overtones present over the fundamental pitch (like trumpets).

    This works great for melodic instruments like strings, piano, guitar, horns, etc. but does not work at all for percussive instruments like drums: kick, snare, hi-hat, drum loops, etc.

    To solve this general problem, I've opted to allow the end user to supply a custom mapping file that specifies what exact MIDI representation to use for each sample, including which MIDI program numbers to use, a transposition amount in semitones to adjust for having the wrong octave or erroneously detecting an overtone instead of the fundamental pitch, and even an optional mapping to the General MIDI percussion channel 10 specific notes for samples like kick, snare, hi-hat, crash, bongos, toms, etc. No support for drum loops (think Jurassic Park soundtrack) yet but it does sound feasible to emit a MIDI drum loop every time a sample of a drum loop is seen. It'd just be very difficult to encode such a MIDI drum loop in a mapping file.

    All of that MIDI conversion effort is present in my libgme fork but I'm stopping work there so I can get a much more stable/accurate emulation base with higan sources. Once I get a basic NSF and SPC player going, I can port over my MIDI conversion work to higan and pick up where I left off.
      Main » Projects » NSF/SPC to MIDI automated converter project » New reply
      Yes, it's an ad.