It costs 2 precious variables per voice...I use voice channel 0 for music and voice channel 1 for a bit of rhythm. It should be pretty easy to see how you can use just one voice or the other.
I think the code is "fairly self-explanatory". I had some trouble with the parser, so I'm using a temp variable, and also remember that -1 can be written $FF (it made the code parse easier in some places)
Your main loop just needs the 2 code lines per voice to adjust the timer and see if it's time to change notes, and then there's the change note subroutine, and the actual note data.
The data format is simple...one set of data is the frequency, what's placed into AUDF0 or AUDF1, with -1 meaning "make no sound". THe other set of data is the length for each note, given in frames. (For North American TVs, there are 60 frames a second, so max I guess there's 3600 bpm)
It's a pretty generic music engine, maybe it could be hacked to be more efficient if you had certain usages in mind.
dim musicNotePointer=a dim musicNoteTime=b dim beatNotePointer=c dim beatNoteTime=d dim temp=e rem VOLUME DOWN AND SET CHANNELS, 'MUSIC' AND 'BEAT' AUDV0=0 AUDV1=0 AUDC0=10 AUDC1=8 rem INITIALIZE POINTERS AND TIMERS musicNotePointer=$FF musicNoteTime=0 beatNotePointer=$FF beatNoteTime=0 startLoop rem TIME TO UPDATE NOTE? if musicNoteTime = 0 then gosub changeMusicNote musicNoteTime = musicNoteTime - 1 rem TIME TO CHANGE BEAT? if beatNoteTime = 0 then gosub changeBeatNote beatNoteTime = beatNoteTime - 1 drawscreen goto startLoop changeMusicNote musicNotePointer = musicNotePointer + 1 if musicNotePointer > 16 then musicNotePointer = 0 : rem 16 notes in all musicNoteTime = musicLength[musicNotePointer] AUDV0=8 temp = musicPitch[musicNotePointer] if temp = $FF then AUDV0=0 AUDF0 = temp return data musicPitch 18,-1,18,-1,15,-1,15,-1,16,-1,16,-1,17,-1,17,-1 end data musicLength 26,10,20,40,26,10,20,40,26,10,20,40,26,10,20,40 end changeBeatNote beatNotePointer = beatNotePointer + 1 if beatNotePointer > 12 then beatNotePointer = 0 : rem 12 notes in all beatNoteTime = beatLength[beatNotePointer] AUDV1=8 temp = beatPitch[beatNotePointer] if temp = $FF then AUDV1=0 AUDF1 = temp return data beatPitch 120,-1,40,-1,120,-1,120,-1,40,-1,120,-1 end data beatLength 2,22,2,10,2,22,2,10,2,4,2,16 end
Of course, the tricky part can be selection of Voice Channel and finding the closest fit for the notes you want. And then getting the rhythm just right. (I remember having a hard time getting the rhythm...I think I slapped together a terribley hacky java program to record the length between keypresses as I tapped out the beat on my computer keyboard) For the voices and frequency stuff, see
Slocum's info at
and the hard core stuff at
ALso Thomas' Tune2600
might be a useful app.
I will try to do a fuller tutorial at some point, and maybe some tools.