Jump to content
IGNORED

How does sound work?


Rabbit 2600

Recommended Posts

I'm having big problems understanding how to set up sound.

The only thing I know about it is that " AUDV0 = 0" mutes sound.

 

I want that when player0 collides with the ball object a sound effect is played. How would I set this up?

 

I tried this but it did not work

if collision(ball,player0) then score = score+10:bally=rand&63:ballx=rand&127:AUDV0 = 1

Link to comment
Share on other sites

Ah okay. Jumps I think I can do. But what is the command to get AUDV0 to play a tune? Do I just add =1?

 

 

Edit:

I managed to get sound working:

if collision(ball,player0) then score = score+10:bally=rand&63:ballx=rand&127:AUDV0=4:AUDF0=18:AUDC0=9

Now I only need to know - How do I turn it off? It plays infinitely now

 

 

 

Entire program:

[code]
 rem Generated 2013-05-30 15:42:56 by Visual bB Version 1.0.0.554
 rem **********************************
 rem *					  *
 rem *				   *
 rem *					    *
 rem *				  *
 rem *					   *
 rem **********************************
 set smartbranching on
 set kernel_options no_blank_lines
  dim _P1_L_R = player1x.a
  dim _P1_U_D = player1y.b
  dim _P0_L_R = player0x.a
  dim _P0_U_D = player0y.b

 AUDV0=0: AUDV1=0

   player0x = 50
   player0y = 50
 player1x = rand&127
 player1y = rand&63
 ballx = rand&127
 bally = rand&63
 ballheight = 4

main
 playfield:
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 X..............................X
 X..............................X
 X......XXX.....................X
 X.....XXXXX....................X
 X.....X...X....................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
end
 player0:
 %00000000
 %00100100
 %00011000
 %00111100
 %00000000
 %00011000
 %00011000
 %00000000
end
 player1:
 %00000000
 %00100100
 %00011000
 %00111100
 %00000000
 %00011000
 %00011000
 %00000000
end
 COLUBK = $D2
 COLUP1 = rand
 COLUPF = $1A
 drawscreen
   if joy0right then player0x = player0x + 1
   if joy0left then player0x = player0x - 1
   if joy0up then player0y = player0y - 1
   if joy0down then player0y = player0y + 1
 if _P1_U_D < _P0_U_D then _P1_U_D = _P1_U_D + 0.50
 if _P1_U_D > _P0_U_D then _P1_U_D = _P1_U_D - 0.50
 if _P1_L_R < _P0_L_R then _P1_L_R = _P1_L_R + 0.50
 if _P1_L_R > _P0_L_R then _P1_L_R = _P1_L_R - 0.50
 if collision(ball,player0) then score = score+10:bally=rand&63:ballx=rand&127:AUDV0=4:AUDF0=18:AUDC0=9
 if collision(ball,playfield) then bally=rand&63:ballx=rand&127
   goto main


 

[/code]

Edited by Rabbit 2600
Link to comment
Share on other sites

Ah, okay. Hm, then I'm 1 step closer to the solution. I added them:

AUDV0=0: AUDV1=0: AUDF1=0: AUDC1=0

 

Maybe I should add an goto in this line so it resets the audio to 0?

if collision(ball,player0) then score = score+10:bally=rand&63:ballx=rand&127:AUDV0=4:AUDF0=18:AUDC0=9

 

Thanks for the link, I've checked the guides there many times but I don't really understand.

 

 

EDIT - Ah, I see that I need a counter! But I don't know how to set that up. I tried by using the examples but I never get it right.

Edited by Rabbit 2600
Link to comment
Share on other sites

Yes sound is pretty hard for me also.

You want a sound to last longer than one frame (1/60 of a second), one drawscreen loop, so you need a counter to stop the sound after a time.

The examples use data for the Volume, Frequency, and AUDCx, duration, and there is a counter to run through the data.

So now that is 2 counters for one channel. Add the other channel and counter you are up to three counters?

 

I can use examples to make tunes, but I needed help with sound effects.

 

There is no BASIC sound command, so you have to load the registers and turn the volume/effects on and off directly using loops and counters, and clever routines to start, stop and abort sound. Definitely not beginner skill level, unless you use examples already coded.

Link to comment
Share on other sites

The 2600's sound is generated by the TIA chip, which has two identical and independent audio channels. Each channel has three registers that determine the sound that will be produced.

 

Audio channel 0:

- AUDC0 (AUDio Control 0) is the control register, which determines the waveform or tonal quality that will be produced. Valid values are 0 through 15.

- AUDF0 (AUDio Frequency 0) is the frequency register, which determines the frequency or note that will be produced. Valid values are 0 through 31.

- AUDV0 (AUDio Volume 0) is the volume register, which determines the volume or amplitude of the sound that will be produced. Valid values are 0 through 15.

 

Audio channel 1:

- AUDC1

- AUDF1

- AUDV1

(These are identical to AUDC0, AUDF0, and AUDV0.)

 

To play a note, you set AUDC0 or AUDC1 to pick the waveform you want to use. With one exception, each waveform is just a stream of 0s and 1s that are repeated endlessly in a specific pattern, causing the speaker to vibrate in that pattern and create a sound. The length of the pattern determines the primary frequency of the sound, and the complexity of the pattern determines how "pure" or "noisy" the sound is. One waveform is just a stream of 1s (or "always on"), so it sounds "silent" (because the speaker doesn't vibrate back and forth the way it does with the other waveforms)-- but you can use the volume register with this "always on" waveform to create your own waveforms. I'll come back to the control register and the TIA's "native" waveforms in a later post.

 

You also need to set AUDV0 or AUDV1 to pick the volume or amplitude of the sound you want to play-- 0 is "off" and 15 is the loudest.

 

Finally, you must set AUDF0 or AUDF1 to pick the frequency or note you want to play. But the TIA doesn't use the standard set of musical notes (C, D, F#, G, etc.)-- instead, it uses harmonics (or really "subharmonics") of the primary frequency that's been selected with the AUDC0 or AUDC1 register. To determine what the resulting frequency will be, add 1 to the AUDF0 or AUDF1 setting and divide the primary frequency by that number-- for example, AUDF0 = 3 divides the primary frequency by 4 (3 plus 1), whereas AUDF0 = 7 divides it by 8.

 

Unless you're using the "always on" waveform, making music with the TIA is a "set it and forget it" thing, meaning you can set AUDC0, AUDV0, and AUDF0 (or AUDC1, AUDV1, and AUDF1) and they'll keep their values, playing the same sound continuously until you change their settings to pick a different sound. In practical terms, this means you don't need to keep setting them over and over again within a loop to keep playing the same sound; you just set them once and then you don't have to worry about them again until you're ready to play a different sound. To give a simple example of what I mean, you can do this:

loop
  if triggering_event then gosub play_a_sound
  drawscreen
  goto loop
play_a_sound
  AUDC0 = 4 : AUDV0 = 15 : AUDF0 = 11 : return

instead of this:

loop
  AUDC0 = 4 : AUDV0 = 15 : AUDF0 = 11
  drawscreen
  goto loop

 

Of course, if you want to play a sequence of different notes, or even just play one note for a specific length of time (and then turn the note off), you'll need to do something a little more complicated than that example-- you'll need a counter to keep track of how long the current note has been playing, and you'll need to fetch the data for the next note after you're finished playing the current note. And depending on how long you want each note to play, you might even need more than one counter. For example, if your shortest note is going to be 1 second long, and you want each note to play for some multiple of 1 second, you'll probably want to use one counter to count frames, and another counter to count the duration of each note. In general terms, you can think in terms of a "tick," where 1 tick is the shortest period of time you want to work with as far as changing the notes or (if you're being really sophisticated and are using ADSR envelopes) dynamically changing the amplitude of each note. For example, you might want to define 1 "tick" as being equal 10 frames, such that each note's duration is specified in terms of a particular number of "ticks"-- e.g., a duration of 6 would really mean 60 frames (10 frames per "tick"),

 

You'll also want to create one or more data tables for your notes. You can put all of the data into one data or sdata table, or you can split the data into separate tables-- say, one table for the frequency of each note and another table for the length of each note. Following is a simple example of the multi-table method:

 

  rem * for counting the number of frames drawn
  dim frame_counter = a
  rem * for counting the number of "ticks" to play the current note
  dim note_counter = b
  rem * for keeping track of which note is currently being played
  dim note_index = c

  rem * set the number of frames per "tick"
  const playback_rate = 30
  rem * set the number of notes in the tune
  const number_of_notes = 8

  rem * initialize the variables
  frame_counter = 0 : note_counter = 0 : note_index = 255

  rem * set the waveform and amplitude
  AUDC0 = 4 : AUDV0 = 15

loop

  rem * if the current note is finished, play the next note
  if note_counter = 0 then gosub play_next_note

  drawscreen

  rem * update the frame counter
  frame_counter = frame_counter + 1
  rem * if it's been 1 "tick," update the note counter
  if frame_counter = playback_rate then frame_counter = 0 : note_counter = note_counter - 1

  goto loop

play_next_note

  rem * update the index to point to the next note's data
  note_index = note_index + 1
  rem * if the tune is finished, start over from the beginning
  if note_index = number_of_notes then note_index = 0

  rem * fetch the data for the new current note
  AUDF0 = note_frequency[note_index] : note_counter = note_length[note_index]

  return

  data note_frequency
  31,28,24,23,20,18,16,15
end

  data note_length
  2,2,1,1,1,3,2,1
end

 

That's an example of a simple music driver to play a single tune over and over again (in this case, an out-of-tune scale). You might want to tinker with that example by increasing or decreasing the value of the playback_rate constant to see how it affects the speed at which each note changes, or try changing the value of AUDC0, changing the numbers in the data tables, etc.

 

To play different sounds for different events, you'd want to start (gosub to a routine for the desired sound) when the triggering event occurs, then stop the sound when its timer runs out. Depending on which event occurs, gosub to the desired routine. If you want two sounds at the same time, call one routine for one audio channel and a different routine for the other audio channel, and use a separate counter for each channel. But I'm not going to try to give an example of that right now.

Edited by SeaGtGruff
  • Like 1
Link to comment
Share on other sites

How sound works for you in bB is your choice. I take a somewhat wasteful approach and set aside a timer for each sound effect. For Cyber Willy I shut up both sound channels at the beginning of the main loop (AUDV0 = 0 : AUDV1 = 0). Next, I see if Fire Sound A is above a certain value (firesounda > 10). If it is I play the appropriate firing sound (AUDV0 = 3 : AUDC0 = 12 : AUDF0 = firesounda) and decrement the timer of that particular sound (firesounda = firesounda - 1). I do the same thing for Fire Sound B.

 

gameloop
AUDV0 = 0 : AUDV1 = 0
if firesounda > 10 then AUDV0 = 3 : AUDC0 = 12 : AUDF0 = firesounda : firesounda = firesounda - 1
if firesoundb > 10 then AUDV0 = 3 : AUDC0 = 7 : AUDF0 = firesoundb : firesoundb = firesoundb - 1

Link to comment
Share on other sites

Aha, so with that you could do a collision between player0 and ball for example and then set firesound1 = 11 for example and that would get a sound?

 

Right, but only a single iteration since the code checks to see if the timer is more than 10. So 11 would only get a single loop of noise. As a side you notice I re-use the timer as part of the actual sound?

 

AUDF0 = firesounda

 

A big part of making distinct sound effects on the Atari 2600 is experimenting with varying the tones. I could have done many other things too.

AUDF0 = counter

AUDC0 = rand

AUDV0 = firesounda

etc..

 

NOTE: The counter I mention is not part of bB but my own variable I set aside to constantly loop from 0 to 255.

Link to comment
Share on other sites

Managed to get sound working! Finaly! Though sometimes it plays for a short while and sometimes a bit longer, but atleast it always ends.

 

h = h + 0
if collision(missile0,player1) then score = score +50 : missile0y = 255 : h = h + 11 : goto startsound
startsound
if h > 10 then AUDV0 = 3 : AUDC0 = 12 : AUDF0 = 1 : h = h - 1
nosound
if h < 11 then AUDV0 = 0 : AUDC0 = 0 : AUDF0 = 0

Link to comment
Share on other sites

Managed to get sound working! Finaly! Though sometimes it plays for a short while and sometimes a bit longer, but atleast it always ends.

 

h = h + 0
if collision(missile0,player1) then score = score +50 : missile0y = 255 : h = h + 11 : goto startsound
startsound
if h > 10 then AUDV0 = 3 : AUDC0 = 12 : AUDF0 = 1 : h = h - 1
nosound
if h < 11 then AUDV0 = 0 : AUDC0 = 0 : AUDF0 = 0

 

Good work! I always start the main game loop by silencing the audio channels. A better programmer would know all occasions when sound is playing (and when it should stop). I'm not that programmer, so I just arbitrarily turn the volume off.

 

gameloop

_AUDV0 = 0 : AUDV1 = 0

Link to comment
Share on other sites

Managed to get sound working! Finaly! Though sometimes it plays for a short while and sometimes a bit longer, but atleast it always ends.

 

  h = h + 0
  if collision(missile0,player1) then score = score +50 : missile0y = 255 : h = h + 11 : goto startsound
startsound
  if h > 10 then AUDV0 = 3 : AUDC0 = 12 : AUDF0 = 1 : h = h - 1
nosound
  if h < 11 then AUDV0 = 0 : AUDC0 = 0 : AUDF0 = 0

 

This might be a little better:

 

  if collision(missile0,player1) then score = score + 50 : missile0y = 255 : h = 11

  if h > 0 then AUDV0 = 8 : AUDC0 = 12 : AUDF0 = 1 : h = h - 1 : if !h then AUDV0 = 0

Link to comment
Share on other sites

I'm making progress on the sound. I can make 1 code work, but if I add 2 sounds, the second always gets stuck in a loop.Any thoughts of wisdom?

 

startsound
if h > 10 then AUDV0 = 15 : AUDC0 = 1 : AUDF0 = 6 : h = h - 1
nosound
if h < 11 then AUDV0 = 0 : AUDC0 = 0 : AUDF0 = 0
crashsound
if s > 10 then AUDV0 = 15 : AUDC0 = 1 : AUDF0 = 6 : s = s - 1
nocrashsound
if s < 11 then AUDV1 = 0 : AUDC1 = 0 : AUDF1 = 0

Edited by Rabbit 2600
Link to comment
Share on other sites

I'm making progress on the sound. I can make 1 code work, but if I add 2 sounds, the second always gets stuck in a loop.

 

Here's a quick example using two noises for the two sound channels using g and h:

  if [something] then [do something] : g = 11

  if g > 0 then AUDV0 = 8 : AUDC0 = 12 : AUDF0 = 1 : g = g - 1 : if !g then AUDV0 = 0

  if [something] then [do something] : h = 11

  if h > 0 then AUDV1 = 8 : AUDC1 = 12 : AUDF1 = 1 : h = h - 1 : if !h then AUDV1 = 0

 

If you want to use the same sound channel for more than one noise, you'd do something like this and turn off the other variable or variables you're using to activate a noise or noises:

  if [something] then [do something] : g = 11 : h = 0

  if g > 0 then AUDV0 = 8 : AUDC0 = 12 : AUDF0 = 1 : g = g - 1 : if !g then AUDV0 = 0

  if [something] then [do something] : h = 11 : g = 0

  if h > 0 then AUDV0 = 8 : AUDC0 = 12 : AUDF0 = 1 : h = h - 1 : if !h then AUDV0 = 0

 

So, if you want to use more than one noise with one sound channel, remember to turn off the other noise activation variables. Say you were using a, b, c, d, e, and f to activate different noises on the same sound channel, and you want to turn on a and turn off the rest. You'd do something like this:

 

if [something] then [do something] : a = 11 : b = 0 : c = 0 : d = 0 : e = 0 : f = 0

Link to comment
Share on other sites

Ahh. That explains it. A thousand thanks!

 

Let's see. So for example this would be correct?

if player0x = 94 then s = 11 : h = 10

 

11 being the sound on. and 10 being the sound off

 

Not in my fixed version of your code. In my version, any number above 0 is on. The higher the number, the longer the noise plays. 0 is off.

Link to comment
Share on other sites

Cool!

 

So, in this code I would go from this

s = s + 10


 if player0x = 94 then o = 1 : s = 11
 if player0x = 60 then o = 1: s = 11

if s > 10 then AUDV1 = 15 : AUDC1 = 2 : AUDF1 = 1 if h > 10 then AUDV0 = 15 : AUDC0 = 1 : AUDF0 = 6 : h = h - 1: if h = 10 then AUDV0 = 0 : s = s - 1: if s = 10 then AUDV1 = 0

 

To this?

s = s + 10


 if player0x = 94 then o = 1 : s = 22
 if player0x = 60 then o = 1: s = 22

if s > 10 then AUDV1 = 15 : AUDC1 = 2 : AUDF1 = 1 if h > 10 then AUDV0 = 15 : AUDC0 = 1 : AUDF0 = 6 : h = h - 1: if h = 10 then AUDV0 = 0 : s = s - 1: if s = 10 then AUDV1 = 0

Link to comment
Share on other sites

Nope. Forget about the number 10. Here is a simple example with two sounds:

 

  if joy0up then g = 22 : h = 0

  if joy0down then h = 11 : g = 0

  if g > 0 then AUDV0 = 8 : AUDC0 = 15 : AUDF0 = 10 : g = g - 1 : if !g then AUDV0 = 0

  if h > 0 then AUDV0 = 8 : AUDC0 = 12 : AUDF0 = 1 : h = h - 1 : if !h then AUDV0 = 0

 

In that example, g will play longer than h because I made it 22 instead of 11.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...