Ok, I have a small demo which should demonstrate sound from NSF (Nintendo Sound Format, sound-related NES code and data isolated and ripped from the original ROM) played in BlitzMax.
1) Choose a location for all the following files (e.g. "C:\Blitz\NSF\")
2) Download the Festalon source code from here: http://www.2a03.org/software.php and extract the "festalon" directory into the directory chosen above (not the contents of the directory, the directory itself).
3) Download the Super Mario Bros 1 NSF file from the top of here: http://www.ocremix.org/list.php?type=soundarchives&offset=143&sort=gameasc (the "NSF" link in the right column) into the directory and rename it to "smb.nsf".
4) Create festalonheader.bmx in the directory and paste this code into it:
5) Create nsfdemo.bmx and paste this code into it:
6) Compile & execute nsfdemo.bmx
That's it! I have only tested this on Windows, I'd be interested to hear if it works on Linux/OSX.
There are some issues with this:
* It can only load fixed-length samples, not properly streaming music. I would be able to do this if I knew how to reset the WritePos of the FreeAudio sample data interface, but I don't. FMOD is a possibility but I can't seem to get that working either.
* There is a noticeable delay as the sound is emulated and stored in a FreeAudio buffer. I actually have another demo that uses threading and the sound plays immediately, but didn't include it as (a) it's Windows-only since I don't understand threads for anything else and (b) Festalon's internal state is one set of variables, which means that you cannot load in multiple sounds in parellel - not without changing a bunch of stuff in the Festalon source that I'm not smart enough to do.
1) Choose a location for all the following files (e.g. "C:\Blitz\NSF\")
2) Download the Festalon source code from here: http://www.2a03.org/software.php and extract the "festalon" directory into the directory chosen above (not the contents of the directory, the directory itself).
3) Download the Super Mario Bros 1 NSF file from the top of here: http://www.ocremix.org/list.php?type=soundarchives&offset=143&sort=gameasc (the "NSF" link in the right column) into the directory and rename it to "smb.nsf".
4) Create festalonheader.bmx in the directory and paste this code into it:
Import "festalon\nsf.c" Import "festalon\x6502.c" Import "festalon\sound.c" Import "festalon\cart.c" Import "festalon\filter.c" Import "festalon\ext\ay.c" Import "festalon\ext\emu2413.c" Import "festalon\ext\fds.c" Import "festalon\ext\mmc5.c" Import "festalon\ext\n106.c" Import "festalon\ext\vrc6.c" Import "festalon\ext\vrc7.c" Extern "C" Function FESTAI_SetVolume(volume:Int) Function FESTAI_SetSoundQuality(q:Int) Function FESTAI_Sound(Rate:Int) Function FESTAI_Disable(t:Int) Function FESTAI_Load:Byte Ptr(buf:Byte Ptr, size:Int) ' Returns an NSFHeader struct Function FESTAI_NSFControl:Int(z:Int, o:Int) ' z = track, o = absolute (1) or relative (0). Returns the actual ' track, in case the chosen track is in fact not available. Function FESTAI_Emulate:Byte Ptr(Count:Int Var) ' Returns a pointer to a chunk of sample data. Count is set to the ' length of it. Function FESTAI_Close() End Extern OnEnd FESTAI_Close FESTAI_SetSoundQuality(0) FESTAI_SetVolume(100)
5) Create nsfdemo.bmx and paste this code into it:
Strict Import "festalonheader.bmx" Incbin "smb.nsf" Local SMB1_Overworld:TFreeAudioSound = LoadSoundFromNSF("smb.nsf", 1, 10.0) Local SMB1_Death:TFreeAudioSound = LoadSoundFromNSF("smb.nsf", 8, 2.7) Local ch:TFreeAudioChannel = PlayNSFSound(SMB1_Overworld) While ChannelPlaying(ch) ' ... Wend PlayNSFSound(SMB1_Death, ch) While ChannelPlaying(ch) ' ... Wend End Function PlayNSFSound:TFreeAudioChannel( Snd:TFreeAudioSound, alloced_channel:TChannel = Null ) Local channel:TFreeAudioChannel,fa_channel If alloced_channel channel=TFreeAudioChannel( alloced_channel ) If Not channel Return fa_channel=channel.fa_channel EndIf fa_channel=fa_PlaySound(Snd.fa_sound,False,fa_channel) If Not fa_channel Return If channel And channel.fa_channel=fa_channel Return channel Return TFreeAudioChannel.CreateWithChannel( fa_channel ) End Function Function LoadSoundFromNSF:TFreeAudioSound(IncbinURL:String, Track:Short, Seconds:Float, Rate:Int=44100) Local SAMPLES:Int = Ceil(Rate * Seconds) FESTAI_Load(IncbinPtr(IncbinURL), IncbinLen(IncbinURL)) FESTAI_NSFControl(Track,1) FESTAI_Sound(Rate) Local fa_sound:Int = fa_CreateSound( SAMPLES,16,2,Rate ) Local buf:Byte Ptr Local sam:Int Local written:Int While (written < SAMPLES) buf = FESTAI_Emulate(sam) If (written + sam) > SAMPLES sam = SAMPLES - written End If fa_WriteSound( fa_sound,buf,sam ) written :+ sam Wend FESTAI_Close() Return TFreeAudioSound.CreateWithSound(fa_sound) End Function
6) Compile & execute nsfdemo.bmx
That's it! I have only tested this on Windows, I'd be interested to hear if it works on Linux/OSX.
There are some issues with this:
* It can only load fixed-length samples, not properly streaming music. I would be able to do this if I knew how to reset the WritePos of the FreeAudio sample data interface, but I don't. FMOD is a possibility but I can't seem to get that working either.
* There is a noticeable delay as the sound is emulated and stored in a FreeAudio buffer. I actually have another demo that uses threading and the sound plays immediately, but didn't include it as (a) it's Windows-only since I don't understand threads for anything else and (b) Festalon's internal state is one set of variables, which means that you cannot load in multiple sounds in parellel - not without changing a bunch of stuff in the Festalon source that I'm not smart enough to do.