Great info!
Actually, this is only starting to scratch the surface of what I want to know about audio. I have been totally ignoring the "sound" aspect of the X16 and VERA up to this point because I didn't want to be involved in more "learning curves" than I can handle at a single moment. But as each learning curve is steamrollered flat, I can take on more.
Ok, so ZSM (Which I've heard of, but thought only did sampled audio.) sends data to the chips in real time, I.E. as a stream just as it's needed. This seems to be the proper way to do this, as you can just open a file and stream it straight into a player that wakes up every frame and decides what to do that frame. But I get that you need the entire data set for development.
Ok, so the diamonds mean the channel is active, not necessarily making actual sound at the moment. Ok, that makes sense.
MIDI and sync. I can see how this could be problematic. While I expect that a noob like me couldn't tell the difference, someone with an "ear" could probably tell if incoming MIDI data is artificially constrained to the 60 hz rate of the vsync interrupt. It probably sounds like a guitar string out of tune to them, or something.
I'm definitely going to be following your efforts and your github.
Dream Tracker
Re: Dream Tracker
Yep pretty much spot on there for ZSM. The tracker engine could certainly be used in a game but most of the ZSM will likely be more efficient for the reasons you mention. It just needs a long enough buffer to be able to process the data coming in to send to the chips.
Minor clarification on MIDI sync. That won't really affect the ear in terms of pitch. MIDI clock sync is really there for being able to keep multiple instruments (both hardware and software) in sync with each other. Without it, we have to try and sync things up "manually" and it's a messy proposition that can also affect audio quality potentially (we have to "warp" the audio in Ableton Live, a modern DAW, to keep things in sync).
For the tracker, I could use a VIA timer to sync audio (and might have that as an option down the road as well). vsync just made it easy and is pretty granular given it's 1/60 of a second. Because song speed is a divisor, it does mean there isn't as fine a control for song speed. That's where a VIA timer (and MIDI clock) comes in.
All that said, if you want to get an idea of music makins on the X16 using a modern computer, Furnace Tracker supports a copious amount of sound chips and retro systems, the X16 is included and it supports ZSM export. One might wonder why I'm bothering to make a native tracker when Furnace exists and it's because I like the idea of making music ON the computer and am using a different UI approach. My tracker is closer to Impulse Tracker, which is the tracker I grew up on. Furnace Tracker seems to be based around FamiTracker which, in turn, is based around FastTracker ][. It's a very different approach.
Minor clarification on MIDI sync. That won't really affect the ear in terms of pitch. MIDI clock sync is really there for being able to keep multiple instruments (both hardware and software) in sync with each other. Without it, we have to try and sync things up "manually" and it's a messy proposition that can also affect audio quality potentially (we have to "warp" the audio in Ableton Live, a modern DAW, to keep things in sync).
For the tracker, I could use a VIA timer to sync audio (and might have that as an option down the road as well). vsync just made it easy and is pretty granular given it's 1/60 of a second. Because song speed is a divisor, it does mean there isn't as fine a control for song speed. That's where a VIA timer (and MIDI clock) comes in.
All that said, if you want to get an idea of music makins on the X16 using a modern computer, Furnace Tracker supports a copious amount of sound chips and retro systems, the X16 is included and it supports ZSM export. One might wonder why I'm bothering to make a native tracker when Furnace exists and it's because I like the idea of making music ON the computer and am using a different UI approach. My tracker is closer to Impulse Tracker, which is the tracker I grew up on. Furnace Tracker seems to be based around FamiTracker which, in turn, is based around FastTracker ][. It's a very different approach.
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/
Re: Dream Tracker
Audio sync:
Is there an absolute sync point for a given note? I.E. Is there a point at which a note in one instrument needs to sync with a note in another instrument?
What I mean by this is: If you have a note, I'll call it "A", that has a group of elements each with their own envelope, like this:
I.E. If every character lasted 1 tick in duration, would the goal to be to have the ! characters all hit simultaneously with the envelope just leading or lagging as they would need to to keep it in sync?
So the player would need to know the sync point and how far before the sync point each component of the note would need to be played such that the sync point for all the notes playing at once would hit at the same time.
Is there an absolute sync point for a given note? I.E. Is there a point at which a note in one instrument needs to sync with a note in another instrument?
What I mean by this is: If you have a note, I'll call it "A", that has a group of elements each with their own envelope, like this:
Code: Select all
Note A Made of elements 0 to 4: E is the envelope, period is "no data" the ! is the hypothetical sync point.
0...EEE!EEE...
1..EEEE!EE...
3.....E!EEEE.
4....EEEEE!E.
So the player would need to know the sync point and how far before the sync point each component of the note would need to be played such that the sync point for all the notes playing at once would hit at the same time.
Re: Dream Tracker
I think if I understood the question, envelopes are essentially just an array of bytes. Currently up to 256 (that makes the address math easier to fetch an envelope quickly). Each channel supports, eventually, 3 envelopes at present. Volume, Pulse-Width (PWM), and Pitch. Currently only volume is actually implemented with PWM to follow and at some point pitch (it's a bit different). For each of these, one can set whether or not the envelope is enabled, how much of the envelope to evaluate (the length), when the envelope triggers (at note start or note release), if it can loop and type (forward or ping-pong), and start/end points of the loop. If loop is enabled, the loop is honored until note-release. I have some bits saved in the bit-flags for envelope speed as well.
Of note, most of that logic doesn't exist yet But that's the plan and is already baked into the instrument UI. At present, enable and length are working.
The tick routine is responsible for engine state updates that happen outside of the pattern data. This happens at vsync so 1/60th of second and currently is only handling envelopes though it will eventually handle other things like channel effects (e.g. arpeggiation). When a note is played, the channel is enabled. That channel has a pointer to the envelope of the instrument active on the channel. For each tick, the envelope is marched ahead one position and the state is evaluated. So for a volume envelope, when a note is triggered the engine will start marching through the envelopes and update state 1/60th of a second.
So in other words, each channel has a set of envelopes that can be used to modify the sound for that channel in some way. The "instruments" setup the default state of the sound in the channel which can then be modified via envelopes and pattern effects (once those exist).
The notes themselves are triggered via the playing pattern. In trackers, patterns are sequenced together in a order list to produce a full song. A pattern usually has 64 rows (sometimes 48 or 96 for 3/4 and 6/8 times, etc.). Notes go on the pattern so in terms of syncing between notes, that happens via vblank / speed. For a song speed of 6, it means a new row is read in every 6th vblank. When that happens the routine scans the data within that row and updates all the VERA channels. This also can cause envelope resets for channels (if a new note was played for instance).
Hopefully that makes sense. This is more or less pretty standard for a tracker. If it's hazy I do plan on doing some live streams via my band's Bandcamp to spend more time going over the tracker, why I made it, what it can do at present, and mess about making some muzak with it. Nothing is scheduled and admittedly it's in part a way to generate some band buzz at the same time but if you have lots of these sorts of questions that might be a good time to ask them since I can also dig into the code.
Of note, most of that logic doesn't exist yet But that's the plan and is already baked into the instrument UI. At present, enable and length are working.
The tick routine is responsible for engine state updates that happen outside of the pattern data. This happens at vsync so 1/60th of second and currently is only handling envelopes though it will eventually handle other things like channel effects (e.g. arpeggiation). When a note is played, the channel is enabled. That channel has a pointer to the envelope of the instrument active on the channel. For each tick, the envelope is marched ahead one position and the state is evaluated. So for a volume envelope, when a note is triggered the engine will start marching through the envelopes and update state 1/60th of a second.
So in other words, each channel has a set of envelopes that can be used to modify the sound for that channel in some way. The "instruments" setup the default state of the sound in the channel which can then be modified via envelopes and pattern effects (once those exist).
The notes themselves are triggered via the playing pattern. In trackers, patterns are sequenced together in a order list to produce a full song. A pattern usually has 64 rows (sometimes 48 or 96 for 3/4 and 6/8 times, etc.). Notes go on the pattern so in terms of syncing between notes, that happens via vblank / speed. For a song speed of 6, it means a new row is read in every 6th vblank. When that happens the routine scans the data within that row and updates all the VERA channels. This also can cause envelope resets for channels (if a new note was played for instance).
Hopefully that makes sense. This is more or less pretty standard for a tracker. If it's hazy I do plan on doing some live streams via my band's Bandcamp to spend more time going over the tracker, why I made it, what it can do at present, and mess about making some muzak with it. Nothing is scheduled and admittedly it's in part a way to generate some band buzz at the same time but if you have lots of these sorts of questions that might be a good time to ask them since I can also dig into the code.
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/
Re: Dream Tracker
With some wonderful help from folks on #asm-dev on the Discord, I've managed to get effects working!
The effect param numbers will surely change, but the above does a pitch slide on channel 1 and a volume slide on channel 2. Right now pitch can wrap (just like it does on the GameBoy/LSDJ) and I haven't decided if I wanna keep that. Volume also wraps and encroaches on the panning bits but I'll fix that soon. I don't expect I will wrap volume.
I plan on adding some of the easier effects first, notably vol/pitch slide (up AND down), PWM (perhaps both slide up/down and set to specific value). I still want some channel effects (e.g. speed, pattern cut, jump to order, etc.). Some of the fancier effects, such as arp, will require storing more state.
These are implemented via a jump table, which is why the effect #'s are 00 and 01. I still want to have letters eventually. For that I'll likely use a PETSCII to effect # mapping array just like I have for keyboard-to-note (e.g. 'Q' on the keyboard is C-1 + octave). I am also planning on either sharing global effects across PSG, FM, PCM or only allowing them on the PSG channel. FM and PCM will have their own effect jump tables. This is for reuse to support multiple effects while hopefully not running out of alphanumeric characters to define effects. Or I can just keep doing it the way I am now (hex values). It's just more typing and less screen real-estate that way (see previous posts for my ideas on this).
There is a problem with some of these effects though as exist in pattern data. I'm doing a pretty naive evaluation of volume and pitch where I just subtract the value from whatever is in the channel registers. This means trying to do something like a kickdrum doesn't work without making the song speed go super fast.
I could remedy that by making the routines more complicated and storing more state where I evaluate the effects via the sound engine update routine (which runs at vsync). Some effects will require this (like arp). I still might but I kinda like that these are coarse and the more state I track, the more memory and overhead I have to deal with. And they're only coarse when doing very fast slides at slowish song speeds.
My current preferred way to solve this is via a feature I've been talking about quite a bit - Tables/Macros. Here's a dirty mockup:
Much like LSDJ on the GameBoy, one can assign tables to instruments but these can also be changed via a pattern effect. Tables would be evaluated at engine speed (again currently vsync) which is the same speed envelopes are evaluated at, perhaps optionally with a speed divisor. These are sort of like sub-patterns in a way.
Since they run at engine speed, pitch slides would be basically as smooth as I could make them without doing something crazier and in doing some tests, I think would be perfectly sufficient for some good ole chiptune PWM kickdrumz.
Notice also that they support up to 4 effects. This one way to work around not having multiple effects per channel. The number of effects with this implementation would be hard set and might change, though I think 4 is sufficient (that's double what LSDJ supports). I arbitrarily picked a length of 32 since that gives me 256 bytes which means, much like envelopes, table-math would be easy but would only provide 32 tables.
I'll also need to define whether or not they loop (and perhaps direction - forward or ping-pong). In LSDJ, you stop tables from looping via an effect and can also shorten the loop via another effect. I'll likely support the latter. The former I'm debating on if that should be an instrument flag and a configureable pattern effect, optionally using the unused bits of the effect value. Since there are only 32 tables in this implementation, I can use the top 3 bits of the byte as flags/modifiers for the tables.
I don't expect I'll have all this done right at the get-go but I really want some sick chiptune kicks and feel that's a pretty important feature. Not just kicks but being able to do more complicated modulations in general without having to use envelopes (noting they can have limitations too).
It's a pretty huge feature but one I'm fairly excited to get to and will probably start work on it once I add some basic pattern effects as noted above.
The effect param numbers will surely change, but the above does a pitch slide on channel 1 and a volume slide on channel 2. Right now pitch can wrap (just like it does on the GameBoy/LSDJ) and I haven't decided if I wanna keep that. Volume also wraps and encroaches on the panning bits but I'll fix that soon. I don't expect I will wrap volume.
I plan on adding some of the easier effects first, notably vol/pitch slide (up AND down), PWM (perhaps both slide up/down and set to specific value). I still want some channel effects (e.g. speed, pattern cut, jump to order, etc.). Some of the fancier effects, such as arp, will require storing more state.
These are implemented via a jump table, which is why the effect #'s are 00 and 01. I still want to have letters eventually. For that I'll likely use a PETSCII to effect # mapping array just like I have for keyboard-to-note (e.g. 'Q' on the keyboard is C-1 + octave). I am also planning on either sharing global effects across PSG, FM, PCM or only allowing them on the PSG channel. FM and PCM will have their own effect jump tables. This is for reuse to support multiple effects while hopefully not running out of alphanumeric characters to define effects. Or I can just keep doing it the way I am now (hex values). It's just more typing and less screen real-estate that way (see previous posts for my ideas on this).
There is a problem with some of these effects though as exist in pattern data. I'm doing a pretty naive evaluation of volume and pitch where I just subtract the value from whatever is in the channel registers. This means trying to do something like a kickdrum doesn't work without making the song speed go super fast.
I could remedy that by making the routines more complicated and storing more state where I evaluate the effects via the sound engine update routine (which runs at vsync). Some effects will require this (like arp). I still might but I kinda like that these are coarse and the more state I track, the more memory and overhead I have to deal with. And they're only coarse when doing very fast slides at slowish song speeds.
My current preferred way to solve this is via a feature I've been talking about quite a bit - Tables/Macros. Here's a dirty mockup:
Much like LSDJ on the GameBoy, one can assign tables to instruments but these can also be changed via a pattern effect. Tables would be evaluated at engine speed (again currently vsync) which is the same speed envelopes are evaluated at, perhaps optionally with a speed divisor. These are sort of like sub-patterns in a way.
Since they run at engine speed, pitch slides would be basically as smooth as I could make them without doing something crazier and in doing some tests, I think would be perfectly sufficient for some good ole chiptune PWM kickdrumz.
Notice also that they support up to 4 effects. This one way to work around not having multiple effects per channel. The number of effects with this implementation would be hard set and might change, though I think 4 is sufficient (that's double what LSDJ supports). I arbitrarily picked a length of 32 since that gives me 256 bytes which means, much like envelopes, table-math would be easy but would only provide 32 tables.
I'll also need to define whether or not they loop (and perhaps direction - forward or ping-pong). In LSDJ, you stop tables from looping via an effect and can also shorten the loop via another effect. I'll likely support the latter. The former I'm debating on if that should be an instrument flag and a configureable pattern effect, optionally using the unused bits of the effect value. Since there are only 32 tables in this implementation, I can use the top 3 bits of the byte as flags/modifiers for the tables.
I don't expect I'll have all this done right at the get-go but I really want some sick chiptune kicks and feel that's a pretty important feature. Not just kicks but being able to do more complicated modulations in general without having to use envelopes (noting they can have limitations too).
It's a pretty huge feature but one I'm fairly excited to get to and will probably start work on it once I add some basic pattern effects as noted above.
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/
Re: Dream Tracker
Made faster progress than I thought! Here's a quick demo showing off some of the new effects (arpeggio notably):
https://www.youtube.com/channel/UCtcsYP ... qSYOzyp2mA
It's notable because the arp effect requires tracking state which will be required for other effects that also need to track state (like glide, virbrato, etc.). I would like to have some of those but I really want a chip-kick so I'll probably start working on the table idea pretty soon. I had thought of the LSDJ instrument Shape/Sweep route too. That would allow making a kick without having to burn a table. Of course I could end up doing both! So long as I have the memory and CPU anyway.
EDIT: I'm making too many self replies so just a quick edit that yep managed to give a sweet effect a try and it works! Kick drumz for days!
https://www.youtube.com/channel/UCtcsYP ... qSYOzyp2mA
It's notable because the arp effect requires tracking state which will be required for other effects that also need to track state (like glide, virbrato, etc.). I would like to have some of those but I really want a chip-kick so I'll probably start working on the table idea pretty soon. I had thought of the LSDJ instrument Shape/Sweep route too. That would allow making a kick without having to burn a table. Of course I could end up doing both! So long as I have the memory and CPU anyway.
EDIT: I'm making too many self replies so just a quick edit that yep managed to give a sweet effect a try and it works! Kick drumz for days!
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/
-
- Posts: 4
- Joined: Sun Apr 16, 2023 8:15 am
Re: Dream Tracker
Looks pretty cool, I wish there was a .MOD import feature in the near future... And then, also .VGM import NES (Famicom only) and PCE (TG16) would be great too...
I love making my own stuff, but I want to also lay back and remix some tunes from my fave games and stuff (megazeux has plenty of .MOD files, some also at the MOD archive, of which I picked from that place...)
And yes, I edit and Make my own music, but it's labor too!!! I use programs as OpenMPT to start off as an example...
NOTE: Not really for any games that are considered FOSS, but if I do, The games will be using Free Music as a base for the games/programs that are Free, for all my FOSS-Licenced works (Or I will remove and replace the music, 100% Garenteed, only for my FOSS softwares, no matter if GPLed or MIT, etc...)
I love making my own stuff, but I want to also lay back and remix some tunes from my fave games and stuff (megazeux has plenty of .MOD files, some also at the MOD archive, of which I picked from that place...)
And yes, I edit and Make my own music, but it's labor too!!! I use programs as OpenMPT to start off as an example...
NOTE: Not really for any games that are considered FOSS, but if I do, The games will be using Free Music as a base for the games/programs that are Free, for all my FOSS-Licenced works (Or I will remove and replace the music, 100% Garenteed, only for my FOSS softwares, no matter if GPLed or MIT, etc...)
----------------------------------------
Just a common user interested in 6502 stuff, not much to see here folks!!!
----------------------------------------
Just a common user interested in 6502 stuff, not much to see here folks!!!
----------------------------------------
Re: Dream Tracker
Added a few more effects since last post (a complete list of currently available effects is here) and also a simple playback screen. I don't have full song pattern scrolling yet. I know how I'll want to do that but that will be after I get all the soundchips working. But even the current play screen at least has some useful tidbits on it:
Last edited by m00dawg on Tue Aug 29, 2023 5:56 pm, edited 1 time in total.
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/
Re: Dream Tracker
Ah didn't see your reply until now @hamtaro126 - sorry about that!
For PCM support I am still debating. I will probably tackle this next (before FM) sort of selfishly so I can have NES style PCM drums and things. I am worried about the overhead though which may limit the quality of the samples. For NES, it was quite low (I forget the sample rate) so I was looking at around 8-bit/11KHz or so to start. If I have more processing headroom I can increase that but I may need to see after I have finished implementing effects and FM.
MODs require software mixing since there is only 1 PCM buffer for VERA. There's been lots of talk of as "GUS" style sound card on the Discord (myself included) and that may end up being a much better fit for MODs. But we'll see! It's not completely out of the question.
For playing existing things, I think Mooing Lemur (Discord)'s Melodious is a ZSM player and _I think_ he's working on compatibility for some platforms. The TG16 would be interesting because it has wavetable/GameBoy style PSGs though. That would require the PCM channel again so that might take some work. I really like unaliased raw lofi wavetables myself (in fact, related, I made a 4-bit/32-slot wavetable Eurorack module called the WaveBoy which implements the GameBoy's wave quite closely, complete with all the glorious aliasing). I'd like a multi-channel version for the X16 as well.
All that said, file conversion/import in the Tracker is possible but there's a lot of features I need to work on first and I'll have to look at how much processing power and programming lift would be required. I absolutely will be supporting ZSM export though since ZSMs are quickly turnout out to be the music file standard for the X16 (and for pretty good reason).
For PCM support I am still debating. I will probably tackle this next (before FM) sort of selfishly so I can have NES style PCM drums and things. I am worried about the overhead though which may limit the quality of the samples. For NES, it was quite low (I forget the sample rate) so I was looking at around 8-bit/11KHz or so to start. If I have more processing headroom I can increase that but I may need to see after I have finished implementing effects and FM.
MODs require software mixing since there is only 1 PCM buffer for VERA. There's been lots of talk of as "GUS" style sound card on the Discord (myself included) and that may end up being a much better fit for MODs. But we'll see! It's not completely out of the question.
For playing existing things, I think Mooing Lemur (Discord)'s Melodious is a ZSM player and _I think_ he's working on compatibility for some platforms. The TG16 would be interesting because it has wavetable/GameBoy style PSGs though. That would require the PCM channel again so that might take some work. I really like unaliased raw lofi wavetables myself (in fact, related, I made a 4-bit/32-slot wavetable Eurorack module called the WaveBoy which implements the GameBoy's wave quite closely, complete with all the glorious aliasing). I'd like a multi-channel version for the X16 as well.
All that said, file conversion/import in the Tracker is possible but there's a lot of features I need to work on first and I'll have to look at how much processing power and programming lift would be required. I absolutely will be supporting ZSM export though since ZSMs are quickly turnout out to be the music file standard for the X16 (and for pretty good reason).
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/
Re: Dream Tracker
Time to play the good news/bad news game!
Good news: I've re-added in FM channels and have added shortcuts in the pattern editor to jump between PSG, FM, and PSG (currently CMD-[1-3]) and I've adding saving which channel you were on when jumping out of the pattern editor. I need to add similar things to the other screens (such as the orders page).
Bad news: This required a file-format change which will break existing files. For the alpha I said I wouldn't be preserving compatibility, which is kind of true since I still need to add more potential breaking changes (PCM storage, FM instruments, and tables at least).
I ran into this own problem with my own tracks so wrote some python scripts to help output, troubleshoot, and convert from the old format to the new one. I'm not quite done with that yet but hope to be soon so at least folks have an option.
Future format changes, I'm hoping, won't be so messy since the pattern size should now stay the same for a while.
I haven't quite fixed everything yet on the master branch (and noticed the download on dreamtracker.org is kinda busted) but I hope to soon (as early as this evening but in the next couple of days if not)
Good news: I've re-added in FM channels and have added shortcuts in the pattern editor to jump between PSG, FM, and PSG (currently CMD-[1-3]) and I've adding saving which channel you were on when jumping out of the pattern editor. I need to add similar things to the other screens (such as the orders page).
Bad news: This required a file-format change which will break existing files. For the alpha I said I wouldn't be preserving compatibility, which is kind of true since I still need to add more potential breaking changes (PCM storage, FM instruments, and tables at least).
I ran into this own problem with my own tracks so wrote some python scripts to help output, troubleshoot, and convert from the old format to the new one. I'm not quite done with that yet but hope to be soon so at least folks have an option.
Future format changes, I'm hoping, won't be so messy since the pattern size should now stay the same for a while.
I haven't quite fixed everything yet on the master branch (and noticed the download on dreamtracker.org is kinda busted) but I hope to soon (as early as this evening but in the next couple of days if not)
Author of Dreamtracker (https://www.dreamtracker.org/)
Check Out My Band: https://music.victimcache.com/
Check Out My Band: https://music.victimcache.com/