Jump to content

Photo

A Simple Music/SFX Engine


4 replies to this topic

#1 kisrael OFFLINE  

kisrael

    HMBL 2600 coder

  • 4,071 posts
  • Location:Boston Burbs, MA

Posted Thu Jul 28, 2005 5:03 PM

Here for your listening and coding pleasure is a humble Musical engine, currently playing the JoustPong/flap-ping theme.

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
http://qotile.net/sequencer.html
and the hard core stuff at
http://home.arcor.de...ts/freqform.txt
ALso Thomas' Tune2600
http://www.biglist.c...9/msg00254.html
might be a useful app.

I will try to do a fuller tutorial at some point, and maybe some tools.

Attached Files



#2 kisrael OFFLINE  

kisrael

    HMBL 2600 coder

  • Topic Starter
  • 4,071 posts
  • Location:Boston Burbs, MA

Posted Thu Jul 28, 2005 5:19 PM

And just to be cute, here's the sound of Joust's Pterry, demonstrating what the engine looks like for a single voice:
  dim musicNotePointer=a
  dim musicNoteTime=b
  dim temp=e

  rem VOLUME DOWN AND SET CHANNELS, 'MUSIC' AND 'BEAT'
  AUDV0=0
  AUDC0=7

  rem INITIALIZE POINTERS AND TIMERS
  musicNotePointer=$FF
  musicNoteTime=0

startLoop
  rem TIME TO UPDATE NOTE?
  if musicNoteTime = 0 then gosub changeMusicNote
  musicNoteTime = musicNoteTime - 1

  drawscreen
  goto startLoop

changeMusicNote
  musicNotePointer = musicNotePointer + 1
  if musicNotePointer > 11 then musicNotePointer = 0 : rem 11 notes in all
  musicNoteTime = musicLength[musicNotePointer]
  AUDV0=8
  temp = musicPitch[musicNotePointer]
  if temp = $FF then AUDV0=0
  AUDF0 = temp
  return

  data musicPitch
  6,7,8,9,10,11,12,13,14,15,-1
end
  data musicLength
  16,2,2,2,2,2,2,2,2,6,60

end
It might be a stretch to call it "music"....(don't tell the lawyers but I used PCAEWin back in the day to go frame by frame through 2600 Joust and record what was in the sound registers as Pterry made her (his?) Mighty Squawk...)

Attached Files



#3 kisrael OFFLINE  

kisrael

    HMBL 2600 coder

  • Topic Starter
  • 4,071 posts
  • Location:Boston Burbs, MA

Posted Thu Jul 28, 2005 5:27 PM

Forgot to add -- please let me know if you find this useful or if you have any suggestions.

#4 potatohead OFFLINE  

potatohead

    River Patroller

  • 4,404 posts
  • Location:Portland, Oregon

Posted Fri Jul 29, 2005 1:09 AM

Forgot to add -- please let me know if you find this useful or if you have any suggestions.

View Post



Was thinking about some goofy music to play during a title screen. This might be just the trick!

Personally, I am looking at all the program listings right now. There are lots of ways to do things! Useful for sure.

#5 kisrael OFFLINE  

kisrael

    HMBL 2600 coder

  • Topic Starter
  • 4,071 posts
  • Location:Boston Burbs, MA

Posted Fri Jul 29, 2005 8:35 AM

(just testing a new toy)

Edited by kisrael, Fri Jul 29, 2005 8:49 AM.





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users