jsd1982 |
Posted on 18-12-01, 17:20
|
Post: #1 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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 https://github.com/JamesDunne/vgm2midi 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: https://github.com/JamesDunne/libgme 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. |
neologix |
Posted on 18-12-02, 00:39
|
Post: #9 of 49 Since: 10-29-18 Last post: 1914 days Last view: 1799 days |
FWIW, Kode54 maintains an updated version of GME within his various audio projects like foo_gep and Cog.app. 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 |
Posted on 18-12-03, 00:33
|
Post: #2 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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. https://github.com/JamesDunne/vgm2midi Next milestone is an SPC player which looks not too difficult to implement. |
jsd1982 |
Posted on 18-12-04, 16:19
|
Post: #3 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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. |
funkyass |
Posted on 18-12-05, 05:53
|
Post: #9 of 202
Since: 11-01-18 Last post: 673 days Last view: 28 days |
its waiting on the CPU. |
Kakashi |
Posted on 18-12-05, 11:21
|
Post: #44 of 210 Since: 10-29-18 Last post: 1889 days Last view: 1861 days |
Yup. Two timing crystals. |
jsd1982 |
Posted on 18-12-05, 23:54
|
Post: #4 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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. |
jsd1982 |
Posted on 18-12-06, 00:03
|
Post: #5 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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? |
funkyass |
Posted on 18-12-06, 05:27
|
Post: #10 of 202
Since: 11-01-18 Last post: 673 days Last view: 28 days |
in rough strokes, the SPC is an instrument played by the CPU. |
Screwtape |
Posted on 18-12-06, 06:56
|
Full mod
Post: #52 of 443 Since: 10-30-18 Last post: 1114 days Last view: 185 days |
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? The ending of the words is ALMSIVI. |
creaothceann |
Posted on 18-12-06, 07:21
|
Post: #29 of 456 Since: 10-29-18 Last post: 56 days Last view: 1 day |
Posted by jsd1982 From what game is the SPC file? Tried others? My current setup: Super Famicom ("2/1/3" SNS-CPU-1CHIP-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10 |
Nicholas Steel |
Posted on 18-12-06, 07:25
|
Post: #41 of 426
Since: 10-30-18 Last post: 511 days Last view: 26 days |
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. AMD Ryzen 3700X | MSI Gamer Geforce 1070Ti 8GB | 16GB 3600MHz DDR4 RAM | ASUS Crosshair VIII Hero (WiFi) Motherboard | Windows 10 x64 |
jsd1982 |
Posted on 18-12-06, 13:04
|
Post: #6 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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. |
jsd1982 |
Posted on 18-12-07, 21:27
|
Post: #7 of 7
Since: 12-01-18 Last post: 2188 days Last view: 2180 days |
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. |
CaptainJistuce |
Posted on 18-12-08, 00:53
|
Custom title here
Post: #113 of 1164 Since: 10-30-18 Last post: 76 days Last view: 4 days |
Hooray! --- In UTF-16, where available. --- |
Kakashi |
Posted on 18-12-09, 15:42
|
Post: #45 of 210 Since: 10-29-18 Last post: 1889 days Last view: 1861 days |
What happened to that new format that replaced SPC? |
creaothceann |
Posted on 18-12-09, 18:20
|
Post: #32 of 456 Since: 10-29-18 Last post: 56 days Last view: 1 day |
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?). My current setup: Super Famicom ("2/1/3" SNS-CPU-1CHIP-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10 |
NTI |
Posted on 18-12-09, 21:55 (revision 1)
|
Post: #7 of 40 Since: 10-29-18 Last post: 724 days Last view: 724 days |
There was SFM, however:Posted by byuu Oh, well... |