GGSound is a lightweight sound engine for NES games. It can do most of the things you hear in games from the 80's and 90's. It comes with a converter which can convert FamiTracker text exports into asm data for use with GGSound.
Thanks to zxdplay for using GGSound in StarKeeper, this inspired me to keep improving my sound engine and continue to make it available for others.
GGSound can be cloned or downloaded from the
Github repository.
There is also a snapshot available on this post, but from now on please use the Github repository.
Features:
-Exporter for FamiTracker text exports
-Works with nesasm3, asm6 and ca65
-Square 1, 2, Triangle, Noise, and DPCM channels
-Volume, Arpeggio, Pitch and Duty envelopes
-Looping envelopes at an arbitrary loop point
-Speed and Tempo
-Looping with the Bxx (must be present in all channels, in unique patterns) command
-Note cuts
-Tempo and pitch adjustment for NTSC, PAL, and Dendy
-Multi-song export
-Sound effects on two channels
-Pause/unpause
-All 87 audible notes in FamiTracker
-No FamiTracker channel effects can be used, only envelopes/macros
-128 of each type of envelope
-128 songs
-128 sound effects
-256 byte long envelopes
You can watch a short intro video for how to use GGSound in a NESASM3 program here:
https://youtu.be/Unc3veECcxc
NOTE: The below is obsolete, see OP for most up to date information on GGSound.
I'm coming very close to having a nice new version of my sound engine ready. Updates include:
-1:1 tempo mapping between FamiTracker and my sound engine
-Loop point implementation for envelopes.
-Support for NTSC and PAL, including tempo adjustment from the converter script and correct pitch values for each region
-Multi song export with the converter script, including a facility which interprets all tracks prefixed as sfx_ to be a sound effect, and modifies them accordingly to terminate after the longest envelope finishes (so, loops are ignored for sound effects by default).
-Better song compression. Repeated patterns are re-used.
-Shared envelopes for your entire song/sound effect collection for more efficient ROM space usage.
-support for B00 to loop your song at a point other than the end of your last frame
-sound effects temporarily cancel the playing note on the channel that they overlay, to help reduce ugly volume shifts
Still no arpeggios or DPCM---primarily because I do not intend to use either in my own projects. If you try out GGSound and enjoy its features and ease of use, but would like these features, please post in this thread and I will add them.
Given that there are already several nice solutions around such as FamiTone2, would there be any interest in yet another sound solution, including versions for nesasm and asm6?
The only substantial advantage that I know of between my sound engine and FamiTone2, is that FamiTone2's converter (with my own music anyway) frequently outputs a note range error, which does not happen with my converter script or engine. I assume this was due to a design decision for efficient packing of data on Shiru's part rather than a flaw, but this particular quirk of FamiTone2 pushed me to update my engine to support the features I wanted from FamiTone2.
Another advantage I've learned about from reading others' posts is that it is a little trickier to use sound effects with FamiTone2. GGSound makes this very easy. Just prefix your song name with sfx_ and the converter does the rest.
If there seems to be any interest out there I'll go ahead and prepare a public version of the engine.
There is interest!
OP updated. GGSound is now available for ca65, asm6 and nesasm3. There's a readme file, and a quick youtube video showing how to use it with nesasm3. Please use this thread for bug reports or other feedback.
I tried to make an NSF init and play routine, but it's not working yet, can you tell what I screwed up?
Code:
nsf_play:
jsr sound_update
jsr sound_upload
rts
nsf_init:
sta current_song
;initialize modules
lda #0 ; region, don't care
sta sound_param_byte_0
lda #<(song_list)
sta sound_param_word_0
lda #>(song_list)
sta sound_param_word_0+1
lda #<(sfx_list)
sta sound_param_word_1
lda #>(sfx_list)
sta sound_param_word_1+1
jsr sound_initialize
;load a song
lda current_song
sta sound_param_byte_0
jsr play_song
rts
Hmm, I'm not really sure what could be wrong...that all looks right to me. The only possibility I can think of is perhaps an nmi is firing before anybody sets sound_update_disable to a known state...that could potentially mess things up. I may want to introduce some kind of module init prior to the sound init that can be used before nmi is ever turned on to ensure this isn't a problem. Can you let me know any more context of how you're integrating ggsound? Which of the three versions are you using and how is it being used? I don't think I've ever looked into how NSF players are supposed to work---perhaps there are requirements I never thought about, though I have no reason to believe this engine couldn't be adapted to work as one.
D'oh, nevermind, the problem was located between my seat and my keyboard. I was manually putting the NSF header on, and I accidentally left the iNES header on. I took it off the first time but I screwed up elsewhere, fixed that, but left the iNES header on next build. Whoops. As I figured, the more confounding the problem is, the more likely it's something really dumb.
NSF format works by specifying 3 addresses, load, init and play. Load is just where the file is loaded in memory, init gets called with the song number in A, then the play address gets called at the frame rate. It shouldn't be possible for the play address to run first, and NSF format doesn't include NMI or IRQ support (usually the vectors aren't even in the file).
I added it to my NSF benchmarking thread. It looks at CPU usage only.
http://forums.nesdev.com/viewtopic.php?f=6&t=13580&p=160061Thanks for sharing, it never hurts to have more sound options.
Cool, thanks for adding it to that thread Memblers!
There is a problem... a song I wanted to convert from text is working, but the song seems to go EXTREMELY slow in your engine...
I've tried changing both the song default tempo and using the tempo command... nothing works!
I've encountered this problem before with other adopters. It turned out that he was using Python 2 rather than Python 3 to run the converter script. What version of Python are you using?
If the version of python is critical, you might want to check for that in the script, e.g.
Code:
#!/usr/bin/env python3
import sys
assert sys.version_info[0] >= 3, "Python 3 required."
rainwarrior wrote:
If the version of python is critical, you might want to check for that in the script, e.g.
Code:
#!/usr/bin/env python3
import sys
assert sys.version_info[0] >= 3, "Python 3 required."
Thanks for the tip, much appreciated!
The #!
hashbang line should be the first line in the file. On some systems it can sort out which version of Python to run.
The assert you can put anywhere you want it to check, but probably want that near the top as well.
After
looking it up, this
might be is an alternative, but not a better #! line:
Edit: tepples explains below why the /usr/bin/env version is preferred.Code:
#! python3
I guess it depends on whether you expect all users to be on Windows. Under UNIX, I think the first word of a shebang line has to be an absolute path. Thus
/usr/bin/env is used as a placeholder to get it to search the
PATH for the
python3 executable, which would usually be in either
/usr/bin (if provided by a distribution) or
/usr/local/bin (if compiled by the machine's owner) but occasionally elsewhere. See
GNU env's man page and
info page as well as
this question on UNIX and Linux Stack Exchange.
Ah, I see. Thank you for the tip.
Yeah, the /usr/bin/env version should work on Windows too, that page I linked mentions that the Windows python launcher should simulate them in some way, so I guess it is the better way to do it. Kind of annoying how many established ways there are; but it's also kind of annoying that we're stuck with the Python 2 / 3 schism in the first place.
Turns out there wasn't much in the script incompatible with Python 2.x. The only problem (known) was that I was relying on Python 3's default behavior of outputting a float value when you divide one integer by another. The fix was to add .0 in the values in the NTSC and PAL tempo calculations.
Hamtaro---should work in Python 2.x now, let me know if you try it out (re-uploaded the distro in the OP, with description of change in the readme file)
To force Python 3 division behavior in Python 2, include the following
future statement at the top of the program, after the shebang line (if present), other comments (if present), and the module docstring (if present), but before any code or other imports:
Code:
from __future__ import division
Added support for note cuts to the converter (distro updated in OP). I hadn't used these very much in my compositions until now, now that I'm using them a lot it was pretty cumbersome to have an instrument that acts as a note cut with a silent volume envelope. This is much nicer.
Would there be a chance to add more support for the Bxx Loop Command?
For example, If there is a song that starts with a intro, it supposed to use B01, or maybe B02, or so on... but currently only B00 is supported. That would help if it gets added!
That's a good idea hamtaro. I'd find this useful as well, I'll consider adding it soon.
Hello, I'm trying to use your GGSound engine with cc65.
Currently, I have one question : is there a way to pause a music, and also to stop it to start it again from the beginning ?
GradualGames wrote:
Still no arpeggios or DPCM---primarily because I do not intend to use either in my own projects. If you try out GGSound and enjoy its features and ease of use, but would like these features, please post in this thread and I will add them.
.
Yes, that will be a great thing if you add add that to the converter and sound engine.
I'm currently using it with ca65/cc65 and it is really great !
This is great! I'm glad you are working on more features. I too would like to get arpeggios (0xx?) and DPCM, please. That would be a boon to the work I've already done on 11 songs for the project we are working on. I'm currently still playing around with everything but noticed that the FT volume lane doesn't work (but I haven't tried Exx yet). Also, pitch, portemento, and tremolo seem to not work, I think it's 1xx,2xx,3xx, and 4xx. Are any of these types of pattern effects possible or would that be too much of a bother? Thank you so much for your work! Please, don't lose interest!
I'm sorry for asking for so much!
Thanks for the interest in GGSound guys. Of the current outstanding feature requests, I can add:
-Using Bxx for allowing song intros to work.
-Pause feature.
-DPCM.
-envelope based arpeggios.
These in addition to the existing feature set would be the max feature set I will allow in GGSound. Going much beyond this would get closer to something like FamiTracker's own NSF driver, and use enough cpu time and rom space it'd not really be a "lightweight" game sound engine any longer. I'll update this thread and the distro once these features are added.
Thanks a lot !
That is exactly what I need for my project
!
Hope you will have success adding these features
GradualGames wrote:
Thanks for the interest in GGSound guys. Of the current outstanding feature requests, I can add:
-Using Bxx for allowing song intros to work.
-Pause feature.
-DPCM.
-envelope based arpeggios.
This much is awesome and I thank you! Is there a limit to how many instruments I can put in a song or limit to how many songs in a single file? These were limitations from Famitone that having a larger full game soundtrack can kinda run into for an effects heavy composer like myself.
GradualGames wrote:
These in addition to the existing feature set would be the max feature set I will allow in GGSound. Going much beyond this would get closer to something like FamiTracker's own NSF driver, and use enough cpu time and rom space it'd not really be a "lightweight" game sound engine any longer. I'll update this thread and the distro once these features are added.
Yeah, I thought as much. I'm still kinda groking NES hardware and such but I figured the overhead would be way too much. I was thinking though, perhaps converting channel effects; to something like envelope->macro data or similar; might work rather than trying to make the engine work as hard as the nsf engine would? My NES ASM-fu-jitsu is blue belt at best so I'm just assuming that the macros generated from envelops are used to make the ASM opcodes for the APU effects to work, correct me if I'm wrong. It's probably more work than either of us are interested in but since I'm working on Unity versions in Famitracker as well as multiple retro-console ROM versions of games' soundtracks, it would help me keep all of my notation using famitracker and deflemask in one place and have to tweak less for each system after the Unity version is composed. Again, sorry for suggesting so much and I'm more than willing to do whatever work I need to make things work for me, just looking for the easiest possible solution for my future needs. Thanks again!
Yeah, basically the primary problem is you have these miniature state machines running for each stream: square 1, square 2, triangle, noise, and DPCM, every frame. Those state machines handle volume, pitch, duty envelopes and dpcm sound effect priority (just added, not yet released in distro), each of which are simple to execute. If I were to go beyond this and add additional features that could do a "secondary" modification of various settings such as the effects famitracker offers *on top* of instrument envelopes/sequences, we're talking yet more state machines working in concert for every stream. It's certainly doable, but like I said we'd be getting into a more heavy lifting kind of engine at that point. In addition to running these additional state machines there'd have to be some kind of tweening or combination of values going on as well.
It's also conceivable to write a much more sophisticated famitracker text-to-asm converter which could create all possible permutations of each instrument and effects based on usages in your song, but then the data would get huge and I kind of shudder to think of the complexity that would introduce into my script.
I'd be surprised if any other game sound engine goes much beyond basic instrument execution and into effects. I'm sure some do. As for myself, I'm more than satisfied with soundtracks that are good not because they wow you with portatos, arpeggios and other such "shock and awe," but are elegant and beautiful much the way a mozart piano sonata might be. So...after I add the above listed features, GGSound will be feature complete. If you're looking for much higher sophistication musically/effect wise, I'd recommend using FamiTracker's own nsf driver. Not sure how easy it would be to use sound effects with that, however.
Thanks again for the interest guys! Cool thing is, I'd never had a reason to look into DPCM. I still don't think I'm going to be using it in my own games, but it was cool to look into it and finally see how to use it.
*edit* I realized you asked about song and instrument limitations. I believe you can have 128 instruments as those are represented as lists of words using an 8 bit index. Same for songs. 128 of each thing. Envelopes can be 256 bytes long. I don't recall if FamiTracker has any limitations which would prevent taking full advantage of GGSound's limits or if they exceed them. I should probably list these facts next time I update the distro.
GradualGames wrote:
Yeah, basically the primary problem is you have these miniature state machines running for each stream: square 1, square 2, triangle, noise, and DPCM, every frame. Those state machines handle volume, pitch, duty envelopes and dpcm sound effect priority (just added, not yet released in distro), each of which are simple to execute. If I were to go beyond this and add additional features that could do a "secondary" modification of various settings such as the effects famitracker offers *on top* of instrument envelopes/sequences, we're talking yet more state machines working in concert for every stream. It's certainly doable, but like I said we'd be getting into a more heavy lifting kind of engine at that point. In addition to running these additional state machines there'd have to be some kind of tweening or combination of values going on as well.
It's also conceivable to write a much more sophisticated famitracker text-to-asm converter which could create all possible permutations of each instrument and effects based on usages in your song, but then the data would get huge and I kind of shudder to think of the complexity that would introduce into my script.
I'd be surprised if any other game sound engine goes much beyond basic instrument execution and into effects. I'm sure some do. As for myself, I'm more than satisfied with soundtracks that are good not because they wow you with portatos, arpeggios and other such "shock and awe," but are elegant and beautiful much the way a mozart piano sonata might be. So...after I add the above listed features, GGSound will be feature complete. If you're looking for much higher sophistication musically/effect wise, I'd recommend using FamiTracker's own nsf driver. Not sure how easy it would be to use sound effects with that, however.
Thanks again for the interest guys! Cool thing is, I'd never had a reason to look into DPCM. I still don't think I'm going to be using it in my own games, but it was cool to look into it and finally see how to use it.
*edit* I realized you asked about song and instrument limitations. I believe you can have 128 instruments as those are represented as lists of words using an 8 bit index. Same for songs. 128 of each thing. Envelopes can be 256 bytes long. I don't recall if FamiTracker has any limitations which would prevent taking full advantage of GGSound's limits or if they exceed them. I should probably list these facts next time I update the distro.
Thanks for looking into it all and I'm glad you found the DPCM groking and implementation interesting.
To be of little help, I can't find limits for Famitracker as such and some of the old limitations aren't listed on the Famitracker site FAQ as if they were removed and maybe are irrelevant to the project file, since that isn't NES specific but using whatever file system the OS uses.
http://famitracker.com/wiki/index.php?title=Frequently_Asked_QuestionsThe old instrument limit was 64 and that was listed in the instrument section of the FAQ quite a while back. I think they may have lifted that limit for project files and I think the project files would have pretty vast limits, if any. FTM export not so much but I can't find that on the wiki; as well as actual game and ROM or flashcart usage, it's probably limited by combination of the NES/hardware with any fancy cartridge hardware (or an emulator's implementation of the two), and the sound engine and how it's converter works (something like that). The version of Famitone2 we were using was limited to 64 instruments and 16 songs so you beat that one. Since we are also limited to whatever flashcart hardware we can afford, an .NSF engine is probably not as ideal as a simpler solution like GGSound.
Thanks again for everything!
All of the following features have been added to the distro in the OP:
-DPCM (supported for one instrument only---if you have more than one instrument with DPCM sample mappings, the behavior is undefined)
-envelope/macro based arpeggios in your instruments, with loop points
-Bxx instead of just B00. Must be present in all channels. This enables you to use a song intro. Forward skip for intros which are not a full frame long are not yet supported.
-Pause/unpause.
Thanks for the requests guys. DPCM and arpeggios may be disabled with two equates at the top of ggsound.inc, FEATURE_DPCM and FEATURE_ARPEGGIOS. If disabling arpeggios, you must set ARPEGGIOS_ENABLED to False at the top of ft_txt_to_asm.py. I did this because as I said I'm probably not going to use these features myself. Happy to provide them for others though, it was fun to code them up.
GGSound is now considered feature complete and no significant new features are planned. Please continue to use this thread for bug reports, and I will also update periodically with any fixes I come up with or improvements/optimizations.
Thanks YOU for this update !
Will test it soon with shiru C lib
I tested with my nsf file but the dpcm channel is playing with bad sounds in FCE and no$.
I think they are not located in the good area.
Triangle, square and noise are playing OK.
I need to have more space than the default space and so, I located the CODE segment to 8000 instead of C000.
You said in your readme file that we need to be at C000 but I do not have enough room if I create a new entry with that address.
I use same code as you did in demo to locate the tracks :
Code:
.include "tracks.inc"
.include "ggsound.inc"
.segment "CODE"
.include "dpcm.ins"
.include "music.ins"
Here is an extract my cfg file for code segment :
Code:
PRG: start = $8000, size = $7fc0, file = %O ,fill = yes, define = yes;
CODE: load = PRG, type = ro, align = $40, define = yes;
And here is an extract of the map file of where the xx_list are located :
Code:
dpcm_list 00C8E3 RLA envelopes_list 00C8DB RLA
incsp4 00ED64 RLA initlib 008700 RLA
play_song 008F18 RLA popa 00ED69 RLA
sfx_list 00C8EB RLA song_list 00C8C5 RLA
sound_disable_update 00002A RLZ sound_initialize 0088B7 RLA
sound_param_byte_0 000034 RLZ sound_param_word_0 000037 RLZ
sound_param_word_1 000039 RLZ sound_param_word_2 00003B RLZ
sound_param_word_3 00003D RLZ sound_update 008977 RLA
sound_upload 009310 RLA sp 000072 RLZ
Do you have any idea of what I'm going wrong ?
Would you be willing to send me your nsf, or a stripped-down version of it that continues to give you trouble with DPCM? That'd be the most efficient way for me to look into the problem. I've only tested it with a couple of short drum samples---perhaps there are bugs with longer samples, or a bug in the exporter.
Since you're using CA65, you can use .align 64. I think you will need to add that above your dpcm samples (they are automatically aligned against one another, but the very beginning of them needs to be aligned manually) as well as aligning the segment itself within your config file (unless you know for sure the samples are already at the very beginning of the segment. which would already be a 64 byte boundary). Try that first, and if that doesn't work please pm me and I'll work with you further on this. Thanks for the bug report!
Hello, I'm currently in vacations, will try to test next week with a smaller file.
Thanks for your reply.
This now totally demystifies music programming on the NES. Very inspiring!
OK, I've also tested with your sample ftm file and I have the same issue :/
I tested with a smaller config file (128 instead of 256), So the code entry is located in c000 and it works.
So I think the issue is because i'm using a larger config file for 256K.
As I located the code segment in 8000 instead of C000 with 256K, does I have to modify something in your ggsound asm file ?
You'll just have to ensure somehow that your DPCM samples always reside in $C000 or later. That means they have to be in the fixed bank in many mappers---or, you could use a mapper which allows swapping out of both $8000 and $C000 so that you can have more space available. The APU is hard-wired to only be able to read DPCM samples from $C000 on.
*edit* No matter what configuration you use, you'll have to keep your DPCM samples at the same location (duplicated) in all banks swapped into $C000 (for configs that don't have a fixed bank at $C000). The reason is as you require other code/data in other banks, the DPCM hardware may still be playing (concurrently with your code that might suddenly need another bank)
Simplest thing by far would just be to have a fixed bank at $C000, with a swappable bank/banks at $8000. Keep your DPCM samples at $C000. Then, keep ggsound in the fixed bank at $C000 as well. If you wish, it's not too hard to wrap ggsound in bankswitching to keep ggsound and music data in a swappable bank at $8000, I do this in my games. DPCM samples however as explained must remain at $C000. (really, anywhere at or after $C000, as long as you .align 64 right before including the samples)
Thanks for reply GradualGames.
I'm new in NES development and really don't know how to manage such bank switching, will check in shiru examples to learn how to do that.
What I understood is that I need the samples have to be after $c000, so we can't have more than 16 K for samples ?
If you have a example how to do bank switching, it will be a great help for me
*EDIT* I found that, will certainly help me a lot :
https://nesdoug.com/2016/01/15/24-mmc3- ... hing-irqs/, thanks to nesdoug
!
I'm pretty new to DPCM but from what I know of it, that's right the longest possible sample you could have would be 16kb. I'd be interested to learn if it is possible to have more. I am aware of course one could manually play longer samples (while pausing other action), but for the purposes of using the hardware to concurrently play a sample while your code continues to run, I believe that is the limitation.
Glad you found those tutorials, they are looking to be some of the best out there for helping new folks into the scene, since asm is a dealbreaker for many.
GradualGames wrote:
I'm pretty new to DPCM but from what I know of it, that's right the longest possible sample you could have would be 16kb.
The sample length limit is actually ~4KB. However, the APU can generate an IRQ when the sample ends, so that can be used to start a new sample more or less immediately after another. With PRG banking you're then only limited by amount of available PRG-ROM, basically.
You think 16K is the law? I've
broken that law.
The longest possible sample is 16*255+1 = 4081 bytes, just under 4 KiB. But on a mapper that bankswitches $C000-$DFFF, such as MMC3, FME-7, several VRCs, or even the repurposed UNROM board used for
Crazy Climber, you can switch a bunch of audio.
Klax, for instance, does this.
I figured it'd be naive to assume that the "basics" were all that was possible.
So, is it bankswitching each time the sample ends using the DPCM irq?
It switches every time it starts a sample. Run the ROM behind the "broken that law" link in a debugging emulator and set breakpoints on $8000-$8001 to see what's going on.
Is this compatible with MMC5? And does it play the extra channels of MMC5?
The feature list in the OP is a complete list of GGSound's capabilities. It handles square 1&2, triangle, noise, and DPCM, no additional sound hardware is supported.
I'm getting an error while running the Python script.
Code:
H:\BLAHBLAH\Workspace\NES\Project03>H:\BLAHBLAH\Workspace\NES\Project03\ft_t
xt_to_asm.py H:\BLAHBLAH\Workspace\NES\Project03\battle.txt
Traceback (most recent call last):
File "H:\BLAHBLAH\Workspace\NES\Project03\ft_txt_to_asm.py", line 717, in <m
odule>
main()
File "H:\BLAHBLAH\Workspace\NES\Project03\ft_txt_to_asm.py", line 348, in ma
in
macros[macro_type_to_str[macro["type"]]].append(macro)
KeyError: 3
I have Python 3.5.1. I've deleted all spaces in song names and instrument names as well as erasing non-ASCII characters in song info and wherever text exists.
Hi-pitch sequences are not supported at the moment. Please confirm if this problem goes away if you remove usage of hi-pitch.
Can you please fix this song for me? I've been using VRC6 in my compositions and there's so many hidden features of it buried in the file. Please send it back to me in ftm format.
https://www.dropbox.com/s/33p062atowtu4 ... e.ftm?dl=0
Thanks so much for sharing your song, this is EXTREMELY helpful to me for making ggsound the best it can be for others to use.
First, I was able to successfully convert your song without error from ft_txt_to_asm.py by going into Edit -> Clean up -> Remove Unused Instruments. I will add a note to the README.txt advising users to do this before converting.
The only error you made 8bitmicroguy, with regards to how I have documented GGSound's features was:
-You need to duplicate your usage of B00, B01 etc. in all channels, in unique patterns at the very end of your song or you'll get incorrect looping. I may improve this in the future but that's how it works right now.
The issues I found in GGSound to play your song were:
-Parentheses in names in FamiTracker became symbols the assembler has trouble with. I will add a feature to the converter to sanitize all labels so you don't have to worry about renaming anything in your FamiTracker compositions.
-One of the channels incorrectly set itself up for looping.
Once I fix up the converter to sanitize names for you and fix the looping bug, I'll update the distro again. I'll also re-upload your song with the minor changes that were necessary to make it work.
Updated OP with distro with the above described fixes.
8bitmicroguy,
here is your battle song with the fixes required to work with the latest version of the ggsound distro. Let me know once you've got it and I'll delete it from dropbox. The only new thing you'll need from that distro is ft_txt_to_asm.py for the assembler you were using, it's the only thing that changed.
The only changes I made to your song were:
-Edit -> Clean Up -> Remove Unused Instruments
-Duplicated B01 in all channels at the end of your song, in unique patterns.
Let me know if it works out for you! Thanks again.
I've got it now and the script works. There are now battle3.asm and battle3_dpcm.asm files. I'm going to try and make a ROM.
Urgh great. -.-
Relearned basic NES stuff again, wrote the program, tried to compile, bank overflow.
Then, I deleted one sample and looks like I broke my FTM file again
Code:
H:\BLAHBLAH\Workspace\NES\Project03>H:\BLAHBLAH\Workspace\NES\Project03\ft_t
xt_to_asm.py H:\BLAHBLAH\Workspace\NES\Project03\battle3.txt
Traceback (most recent call last):
File "H:\BLAHBLAH\Workspace\NES\Project03\ft_txt_to_asm.py", line 717, in <m
odule>
main()
File "H:\BLAHBLAH\Workspace\NES\Project03\ft_txt_to_asm.py", line 608, in ma
in
dpcm_note_to_sample_length = dpcm_samples[dpcm_note_to_sample_index]["length
"] >> 4
IndexError: list index out of range
If you're willing to continue sharing each file which has trouble converting, I'd be happy to take a look! I've only ever tested with my own compositions, so there are bound to be some more bugs to weed out.
If I had to guess though, ggsound really only supports a single instrument having DPCM samples associated with it. If you have more than one, the behavior is undefined, as stated in the readme.
Secondly, I hope edit ...clean up...remove unused instruments will fix that up (I don't know if this affects deleted DPCM sample slots...). If not, I'd like to take a look at your ftm. Thanks!
Upon further thought, I bet the only problem is that your song is still trying to play a note which had been associated with the sample that you deleted. This is an assumption I made, so it just dies in this case. Perhaps I can try to add some easier to understand errors to guide the user. I'll update Wednesday.
The sample that I've deleted wasn't used at all either by mapped notes or an instrument. Only the "DPCM" instrument plays the DPCM samples.
8bitmicroguy, dpcm sample indexing was done incorrectly in ft_txt_to_asm.py. You can now remove an unused sample from anywhere in the list and it'll work. If you remove a sample that is indeed mapped somewhere, you'll get a nice error describing the octave, semitone and sample index (in FT) that was missing. OP updated with latest version. Let me know if it works out for you! Thanks once again for exercising this tool, you're helping me make this better for anybody who comes along and uses it.
Code:
Traceback (most recent call last):
File "H:\BLAHBLAH\Workspace\NES\Project03\ft_txt_to_asm.py", line 731, in <m
odule>
main()
File "H:\BLAHBLAH\Workspace\NES\Project03\ft_txt_to_asm.py", line 720, in ma
in
master_stream.insert(loop_index + jump_frame, "%s:\n" % master_stream_loop)
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
Would you mind sharing the song that caused this error? Thanks!
*edit* Nevermind, it appears to be a regression from the fix for Bxx. Fix coming.
Alrighty, that should be fixed up now. The problem was when I fixed Bxx, I broke songs that don't use it
See OP for updated GGSound distro.
Wow. Now I get this error:
Code:
H:\BLAHBLAH\Workspace\NES\Project03>H:\BLAHBLAH\Workspace\NES\Project03\NESA
SM3.exe H:\BLAHBLAH\Workspace\NES\Project03\Project03.asm
NES Assembler (v3.1)
pass 1
pass 2
#[1] H:\BLAHBLAH\Workspace\NES\Project03\Project03.asm
87 03:E051 lda #low(sfx_list)
Undefined symbol in operand field!
89 03:E056 lda #high(sfx_list)
Undefined symbol in operand field!
101 03:E072 lda #song_index_battle
Undefined symbol in operand field!
130 03:E0AC lda #sfx_index_sfx_0
Undefined symbol in operand field!
# 4 error(s)
And in the battle3.asm file,
Code:
song_index_abattlea = 0
song_index_asfx_0a = 1
song_list:
.dw abattlea
.dw asfx_0a
Why does it say "a"? Why didn't it recognize sound effects? Is it some problem with strings? Also, I see that the samples that have brackets and dots in them have these weird names in the generated file:
"dpcm_sample_aD800udmca:" instead of "D800.dmc"
I think your string escapism code is doing nonsense. Can you make it that weird characters produce _?
Also, is there a quickfix for this where I can add sfx_list myself?
Whoops! I see another problem I just introduced. This is making me want to add regression tests... I'll try to get it fixed up tonight. Cheers!
Also, you should license your code with an open-source license like BSD because nobody is legally allowed to use it without it.
P.S. Please don't license it with GPL because the terms and conditions of that license would force my code to be open-source and unprofitable, but I'm planning to make a commercial NES game with a license allowing only those who buy the game to see the source code, modify, fork, etc..
Alright! Sorry about that, fixed the regression I introduced in the label sanitization, see OP for download. It isn't producing nonsense---what it is doing is replacing characters which are allowed in windows filenames with alphabetical characters. It used to be underscores, but then it is technically possible to cause more errors if somebody say named their file +++ and another file ++- or something, then it would have all been ___ and would have been treated as the same label. By replacing them with aaa and aab (example) you still get unique labels, consumable by assemblers. The mistake I made was that quotes need to be removed entirely. Teaches me not to regression test after a change! Haha!
As the sole copyright holder of the code in GGSound, I can assure you I will prosecute nobody if they use it. I don't think a full open source license is really necessary with this. This is a rather small, niche area of software with few (if any) people who would want to contribute to the project. A fair number of folks enjoy rolling their own anyway, that's part of the fun of this hobby.
GradualGames wrote:
As the sole copyright holder of the code in GGSound, I can assure you I will prosecute nobody if they use it. I don't think a full open source license is really necessary with this.
A license is necessary in order to assure people that the first sentence is binding. It can be as simple as the
WTFPL:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
OP updated with GGSound distro attached with following changes:
-Duty cycles now support loop points for square waves.
-Added UNLICENSE.txt to state GGSound is public domain software. Use it however you like. Legal issues aside, of course it would make me happy to see GGSound in your credits regardless.
...Next update, I'm going to add support for duty cycles to the noise channel (I know that's not what it is called in the APU, but the same sequences within FT are applied, using just one of the bits). I realized suddenly GGSound has never supported that "buzz" capability of the noise channel, because I'd never thought to use it, myself. I'll try to get that in this weekend.
As promised, added duty/noise sequence processing to the noise channel. OP updated with ggsound_distro.zip.
These recent updates to duty cycle processing got me wondering about how people commonly use duty cycle envelopes out there. My approach has been that for the most part, I'm not using loops in duty cycles. I usually just set it and forget it. I do not use loop points in my FT files. So in GGSound's code, it preserves the last written duty cycle (or noise bit) every frame. So if you have a duty envelope which is just 1 frame long and stops and does not loop, you're going to continue to hear that setting as though it were looping. However, now that looping is supported, you can also set an arbitrary loop point somewhere in the cycle and it will loop over those values. I think this is how most people would expect duty cycles to work. Or would you expect to be forced to always specify a loop point if you want to keep that setting as a note plays? I'd be interested in feedback on this because I've been thinking about the feature in a vaccuum based on how I've been using it, myself.
GradualGames wrote:
These recent updates to duty cycle processing got me wondering about how people commonly use duty cycle envelopes out there.
The
Skate or Die 2 title music has what sounds like looped duty cycles.
My hi-hats usually alternate normal noise ($03) and looped noise ($83) frame by frame. But they're usually fairly short anyway, and besides, Pently bakes noise period and noise quality into one byte written to $400E. For pulse instruments, duty is baked into the volume envelope.
Duty sequences are very good for creating an attack portion to the sound. 1 or 2 frames of different duty at the start of a note might be good for a
guitar pluck, or a
piano "ping". You can get a nice ring to the start of a hi-hat sound by using looped noise in a similar way.
Looped duty is less common but still has its uses. For example, it might approximate a
raunchy saxophpone.
Sort of a combination of both, a volume that falls off combined with a looped duty that has an attack can make an "
automatic echo" kind of sound, where having that attack frame repeat at lower volumes.
Sorry to be using only my own stuff as examples, but we're getting into territory where I can't think of examples from the commercial NES library so easily. I can see why shiru chose not to implement duty envelopes in famitone, since they're not quite so obviously useful, but I think they have a lot of utility.
GradualGames wrote:
However, now that looping is supported, you can also set an arbitrary loop point somewhere in the cycle and it will loop over those values. I think this is how most people would expect duty cycles to work. Or would you expect to be forced to always specify a loop point if you want to keep that setting as a note plays? I'd be interested in feedback on this because I've been thinking about the feature in a vaccuum based on how I've been using it, myself.
I would just want the loop thing to work in the way that I simply export to text, text to asm and compile and have it work. I don't know what the question asks, really.
Hi,
First of all, hello everyone. Long story short, I'm currently writing music for a project in which I need to follow ggsounds limitations. I am not particularly knowledgeable about the technical side of nes programming, and I was wondering if someone here could help me determine why my project won't output correctly.
This is a single pattern. I can't figure out why I'm getting the "music.asm (184) : Incomplete expression" and "music.asm(193) : Can't determine adress" error when I try to output it with ggsound assembly test. The module was written in with the last version of famitracker (0.4.6).
I think I've respected the limitation of ggsounds and I'm trying yo determine if the error comes from my famitracker module or from something else. Any help would be appreciated.
I figured out the issue with this one. It's pretty small and wouldn't actually be visible from just the Famitracker file.
It had to do with the linker which references the files containing song data as well as the one containing GGsound constants. It had the include for the DPCM file commented out, and the test song contains DPCM. So it's referencing a location that isn't there.
To fix it, all you'd need to do is open the "linker.asm" file and remove the semicolon before the line including dpcm.asm. My apologies if I was confusing in my initial explanation.
I think what you ran into is that if you don't have any sfx, sfx_list won't be output and the demo program references the sfx_list symbol. If you don't have any sfx you can just let ggsound point to a bogus sfx list, and then never use any sfx and all will be well.
I noticed your loop doesn't sound quite right (edit: it seems your DPCM stream does not get exported) when it plays back in ggsound (nice loop, btw, I was mesmerized by it listening to it in FT for a few seconds). I'm going to try to figure out why and then update the distro.
Velathnos 2.0: DPCM is not exporting for you. Your DPCM instrument needs to specify a volume envelope even though DPCM does not use it. This is just a quirk of the converter and how it determines if an entire stream is silent. Easy workaround.
I noticed that ggsound produces a strange bend in your triangle instrument, too, which also seems wrong as I do not hear this in FT. I'll investigate this as well, next.
Thanks!
GradualGames wrote:
Velathnos 2.0: DPCM is not exporting for you. Your DPCM instrument needs to specify a volume envelope even though DPCM does not use it. This is just a quirk of the converter and how it determines if an entire stream is silent. Easy workaround.
I noticed that ggsound produces a strange bend in your triangle instrument, too, which also seems wrong as I do not hear this in FT. I'll investigate this as well, next.
Thanks!
All right, thanks for looking into it!
Thanks Velathnos 2.0 and darryl.revok, you helped me find a bunch of stuff to fix!
OP ggsound_distro.zip updated with the following fixes:
-Fixed bug in converter so that all envelopes revert
to default for instruments that do not specify them.
-Fixed how beginning of note is detected.
-Fixed arpeggio processing to work with new beginning
of note code.
-Fixed bug in converter which was processing spaces in
track and dpcm names incorrectly.
-Convert spaces to underscores in output asm for
readability.
Velathnos 2.0 your song should now export and work perfectly except for needing to specify the (unused/bogus) volume envelope in the DPCM instrument. I put a note in the README about needing to do this. And of course also being aware that if you do not have any sfx, the demo program will still be looking for the sfx list so you'll have to remove that.
GradualGames wrote:
Thanks Velathnos 2.0 and darryl.revok, you helped me find a bunch of stuff to fix!
OP ggsound_distro.zip updated with the following fixes:
-Fixed bug in converter so that all envelopes revert
to default for instruments that do not specify them.
-Fixed how beginning of note is detected.
-Fixed arpeggio processing to work with new beginning
of note code.
-Fixed bug in converter which was processing spaces in
track and dpcm names incorrectly.
-Convert spaces to underscores in output asm for
readability.
Velathnos 2.0 your song should now export and work perfectly except for needing to specify the (unused/bogus) volume envelope in the DPCM instrument. I put a note in the README about needing to do this. And of course also being aware that if you do not have any sfx, the demo program will still be looking for the sfx list so you'll have to remove that.
Thanks for the update, it's effectively working. Glad to have helped fix some stuff!
That being said, I have questions concerning the implementation of sound effects (sorry if it's explained somewhere, I've searched but haven't found the answers I'm searching for). So sound effects should be in the same famitracker file containing the music, with the "sfx_" prefix. What channels can be used for those effects? Also, should the effects be looped, like should I end them with the bxx effect? Thanks!
Velathnos 2.0 wrote:
Thanks for the update, it's effectively working. Glad to have helped fix some stuff!
That being said, I have questions concerning the implementation of sound effects (sorry if it's explained somewhere, I've searched but haven't found the answers I'm searching for). So sound effects should be in the same famitracker file containing the music, with the "sfx_" prefix. What channels can be used for those effects? Also, should the effects be looped, like should I end them with the bxx effect? Thanks!
You can use up to 2 of the 5 channels for sound effects. You don't need to loop them. Also it is strongly recommended not to use looped envelopes or the Bxx effect for sfx, as the behavior may be undefined. I'll try to update the README to better explain how sound effects work. Basically they are processed to terminate after the longest envelope ends (after the last note). So if you use a looped envelope it'll only play that loop once for your sound effect. Also sound effects are not affected by tempo, they are assumed to primarily rely on envelope playback. Notes are played once on every frame (basically fastest possible update). So, they may sound slightly different on NTSC vs PAL, unlike music where tempo adjustments are made. Pitch adjustments in theory should be working the same way for both music and sfx.
If I have a duty cycle pattern loop in an instrument that I use in a sound effect, will it loop only once?
It finds the max length of all envelope types for your instrument and terminates the sound effect after that many frames (the length of your envelope sequence corresponds to rendered frames) have elapsed. Typically the volume envelope is the longest, so if your duty cycle is a fairly standard one that is used for a crisp sounding attack or what not and you have a longer volume envelope, the duty cycle will loop as expected.
Perhaps I should use the pattern length in rows instead to determine the length of sound effects---that way you can control it more precisely. Thoughts?
Pattern lengths are how I expect sfx to work so yes
Hello!
I made something that I thought might be useful to others.
It's pretty simple, just a slight modification to the GGsound demo. It's in ASM6 format but I can make a CA65 one if it someone requests it.
The purpose of this is to help a composer, without programming knowledge, to demo their songs on an NES console or emulator. I wanted it so that a composer could export their FTM song, convert to ASM, rename the output files to "track_data.inc" and "track_dpcm.inc" and drop them into the demo file, build, and listen. I wanted to make sure that the track list would stop at the beginning and end no matter how many songs were included, I also wanted the same for SFX, and for a sound designer to be able to select the various sound effects.
All of the changes that I made are included in one file, demo.asm. This file can be dropped into the "ggsound_asm6" folder to apply these changes to the demo. Opcodes that I added are capitalized. There is an additional variable declaration for current_sfx, and an initialization of that variable. There are constants called SONG_INDEX_END and SFX_INDEX_END which are calculated at assembly. A song will no longer restart when you hit the end of the track list, which is just personal preference and it was a little easier to set up that way.
I hope this helps somebody!
OP updated with distro with two new bug fixes in the converter. Sfx lengths were not being calculated correctly for more complex sfx, and pattern indices were not being treated properly in some cases. Thanks to Peter McQuillan for these bug reports!
GGSound now has its own
Github repository.
I'm getting an error when converting a song but I guess this has to do with the fact that I don't have cc65 properly installed. I managed to run the build demo python script when I copied ca65.exe and ld65.exe do the same folder as the py script, but converting a song isn't working when I use that dirty fix. Even copying all cc65 exes to the folder doesn't cut it. So, when searching for instructions on how to install cc65 I run into a problem.
This page says:
"Extract cc65-win32-#####.zip to a new folder.
Open this folder and run the install.vbs file as an administrator to copy it to Program Files."
Now, the original cc65 website doesn't have anything anymore, and it says:
"Oliver Schmidt, long time contributor to the libraries is providing support for the old version. See
http://cc65.github.io/cc65/ for more information."
So I go to that new site and the package is presented in a new portable format only. I can't install it, it seems.
I tried unzipping the package to c:\cc65 as I recall someone suggesting that, but still doesn't work.
Code:
D:\programas\_nes modding\assembly\_cc65\ggsound-master\ggsound_ca65>ft_txt_to_a
sm.py tension.txt
Traceback (most recent call last):
File "D:\programas\_nes modding\assembly\_cc65\ggsound-master\ggsound_ca65\ft_
txt_to_asm.py", line 754, in <module>
main()
File "D:\programas\_nes modding\assembly\_cc65\ggsound-master\ggsound_ca65\ft_
txt_to_asm.py", line 367, in main
macros[macro_type_to_str[macro["type"]]].append(macro)
KeyError: 3
Any ideas? Just to be clear: when simply unzipping the files to new folders it doesn't work (build demo or convert song). I have python 3.6.2 installed and the latest zips of cc65 and gg-sound. Build demo works when I copy ca65.exe and ld65.exe to the "ggsound_ca65" folder.
edit: there is a space character in the path on "_nes modding" folder, but even when working from c:\ggsound it throws the same error.
Here is one song that I've tried to make as featureless as possible and still can't export:
http://nesrocks.com/files/runner.ftm
nesrocks wrote:
I'm getting an error when converting a song but I guess this has to do with the fact ...
Sorry I haven't been on nesdev in a little while. I'll look into it. Or if you wind up fixing it, pull requests on the github project are welcome as well.
nesrocks wrote:
Here is one song that I've tried to make as featureless as possible and still can't export:
http://nesrocks.com/files/runner.ftmHmm...I'm not sure what's going on yet. When I try to open your file in FamiTracker 0.4.2, it says I need a newer version of FamiTracker. So I went to FamiTracker's website and got 0.4.6. Tried to open your file again. It still tells me I need a newer version. Are you using some kind of bleeding edge beta version from somewhere...? Haha.
GradualGames wrote:
Are you using some kind of bleeding edge beta version from somewhere...? Haha.
Yeah, everyone uses 0.5 and that's what I had to use too if I was to download several of the tracks posted on the famitracker forums. I 100% agree this is super confusing as that 0.5 version isn't easily found on their download sections, and yet, it is what most of the composers use. Note this thing is from 2015!
http://forums.famitracker.com/viewtopic.php?t=173
nesrocks wrote:
GradualGames wrote:
Are you using some kind of bleeding edge beta version from somewhere...? Haha.
Yeah, everyone uses 0.5 and that's what I had to use too if I was to download several of the tracks posted on the famitracker forums. I 100% agree this is super confusing as that 0.5 version isn't easily found on their download sections, and yet, it is what most of the composers use. Note this thing is from 2015!
http://forums.famitracker.com/viewtopic.php?t=173Interesting, I was not aware of this build of FamiTracker.
The issue is that some hi-pitch sequences are present in your file---these are unsupported by GGSound. This is listed on the guide on the
github page.If you're working with a sophisticated composer, they will probably need some coaxing as GGSound supports a rather limited subset of FamiTracker's features.
Ohhh... But they are unchecked. Shouldn't they be ignored by the converter? Anyway, I'll remove it and test again.
Just added Dendy support to
GGSound.
A bug in arpeggio execution has been fixed. Arpeggio support has been added to the noise channel.
GGSound repository
Introducing arpeggios to the noise channel caused a regression with noise pitch envelopes which has been fixed. Also: "Fixed" arpeggios are hard-coded to the noise channel, "Absolute" arpeggios are hard coded to all other channels. I do not use arpeggios myself---if anyone runs into issues with using arpeggios, please use this thread to report bugs and provide a sample song which causes your issue so that I can fix it.
Does anyone know how common it is to use absolute/relative/fixed with arpeggios on different channels?
GradualGames wrote:
Also: "Fixed" arpeggios are hard-coded to the noise channel, "Absolute" arpeggios are hard coded to all other channels. I do not use arpeggios myself---if anyone runs into issues with using arpeggios, please use this thread to report bugs and provide a sample song which causes your issue so that I can fix it.
Does anyone know how common it is to use absolute/relative/fixed with arpeggios on different channels?
Almost all my triangle arp sequences are fixed. Here's why:
My drum kit in FamiTracker 0.4.x and 0CC-FamiTracker uses an absolute arpeggio sequence so that the same instrument can serve as kick and snare, though that could easily be redone with fixed arp using one additional instrument.
Kick (noise part)note: 0-#
volume: 12 10 8 6 4 3 2 2 1 1 1 0
arpeggio: absolute 10 0
duty: 0
Snare (noise part)note: A-#
volume: 12 10 8 6 4 3 2 2 1 1 1 0
arpeggio: absolute 10 0
duty: 0
Volume, arpeggio, and duty sequences are identical for the two. (This volume sequence may vary between modules based on the rest of the mix.) It relies on the modulo 16 nature of arpeggio sequences in FamiTracker to act as both kick (whose fixed arpeggio would be 10 0) and snare (whose fixed arpeggio would be 4 10).
Since
this post by rainwarrior, kick and snare also have a triangle part that uses fixed arpeggio so that the drum can share the channel with the bass.
Kick (triangle part)arpeggio: fixed 40 36 33 (E-3 C-3 A-2)
Snare (triangle part)arpeggio: fixed 47 45 (B-3 A-3)
The remainder of my stock drums, for completeness:
Hi-hat (noise)note: C-#
volume: 6 4 2 1 1 0
arpeggio: none
duty: | 0 1
Open hi-hat (noise)note: C-#
volume: 7 6 5 4 3 2 2 1
arpeggio: none
duty: | 0 1
Here, duty is looped to combine hiss noise (duty 0) with buzz noise (duty 1) to simulate a cymbal.
I've attached a FamiTracker port of the drum and bass from the 3 AM music in
Thwaite.
Frame 0: Contrasting noise-only drums with tri+noise drums
Frame 1-2: Combining drum and bass
Frame 3: Mute the noise to hear only the bass and the triangle portion of the drum
tepples wrote:
GradualGames wrote:
Also: "Fixed" arpeggios are hard-coded to the noise channel, "Absolute" arpeggios are hard coded to all other channels. I do not use arpeggios myself---if anyone runs into issues with using arpeggios, please use this thread to report bugs and provide a sample song which causes your issue so that I can fix it.
Does anyone know how common it is to use absolute/relative/fixed with arpeggios on different channels?
Almost all my triangle arp sequences are fixed. Here's why:
My drum kit in FamiTracker 0.4.x and 0CC-FamiTracker uses an absolute arpeggio sequence so that the same instrument can serve as kick and snare, though that could easily be redone with fixed arp using one additional instrument.
Kick (noise part)note: 0-#
volume: 12 10 8 6 4 3 2 2 1 1 1 0
arpeggio: absolute 10 0
duty: 0
Snare (noise part)note: A-#
volume: 12 10 8 6 4 3 2 2 1 1 1 0
arpeggio: absolute 10 0
duty: 0
Volume, arpeggio, and duty sequences are identical for the two. (This volume sequence may vary between modules based on the rest of the mix.) It relies on the modulo 16 nature of arpeggio sequences in FamiTracker to act as both kick (whose fixed arpeggio would be 10 0) and snare (whose fixed arpeggio would be 4 10).
Since
this post by rainwarrior, kick and snare also have a triangle part that uses fixed arpeggio so that the drum can share the channel with the bass.
Kick (triangle part)arpeggio: fixed 40 36 33 (E-3 C-3 A-2)
Snare (triangle part)arpeggio: fixed 47 45 (B-3 A-3)
The remainder of my stock drums, for completeness:
Hi-hat (noise)note: C-#
volume: 6 4 2 1 1 0
arpeggio: none
duty: | 0 1
Open hi-hat (noise)note: C-#
volume: 7 6 5 4 3 2 2 1
arpeggio: none
duty: | 0 1
Here, duty is looped to combine hiss noise (duty 0) with buzz noise (duty 1) to simulate a cymbal.
I've attached a FamiTracker port of the drum and bass from the 3 AM music in
Thwaite.
Frame 0: Contrasting noise-only drums with tri+noise drums
Frame 1-2: Combining drum and bass
Frame 3: Mute the noise to hear only the bass and the triangle portion of the drum
Thanks tepples. I've added support for all 3 arpeggio types for all channels now, and I am going to try out your example song to see if it executes properly. However, ggsound does not support Sxx. Should it be possible to imitate this effect by other means such as a volume envelope?
Yes. For an engine known not to support Sxx or overlay drums, I'd make separate instruments for use with and without a following pitch, one with a volume envelope that terminates and one without.
tepples wrote:
Yes. For an engine known not to support Sxx or overlay drums, I'd make separate instruments for use with and without a following pitch, one with a volume envelope that terminates and one without.
The only additional thing I had to change so this sample would work with ggsound is every instrument must specify a volume envelope, so I added one for the triangle instruments which lacked one (with a single value of "1").
Would you mind if I included this sample in GGSound's test songs? Worked perfectly with the new arpeggio implementation, happy to say. I will credit you for the contribution in the README.md.
Also, are arpggios ever used with DPCM?
GradualGames wrote:
The only additional thing I had to change so this sample would work with ggsound is every instrument must specify a volume envelope, so I added one for the triangle instruments which lacked one (with a single value of "1").
Pently also needs a volume envelope on all instruments, but it defaults to
8 because I've found that more musically useful when pulse and triangle instruments share a volume envelope.
GradualGames wrote:
Would you mind if I included this sample in GGSound's test songs?
Go ahead. I'll provide a more fleshed out version later.
EDIT: Now
GradualGames wrote:
Also, are arpggios ever used with DPCM?
I haven't seen it used.