Rabbit 2600 Posted May 30, 2013 Share Posted May 30, 2013 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 Quote Link to comment Share on other sites More sharing options...
purduecrum Posted May 30, 2013 Share Posted May 30, 2013 I struggled with sound too and haven't written any Bb in over a year. I couldn't figure out how to thread sound in with other game logic. I had to give sound its own "function" and call/jump to it when needed (such as a collision). Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted May 30, 2013 Author Share Posted May 30, 2013 (edited) 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 May 30, 2013 by Rabbit 2600 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 31, 2013 Share Posted May 31, 2013 AUDV0 controls the volume of channel 0. You must also set AUDF0 and AUDC0. A second sound effect can be done using AUDV1, AUDF1 and AUDC1 http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#sound Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted May 31, 2013 Author Share Posted May 31, 2013 (edited) 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 May 31, 2013 by Rabbit 2600 Quote Link to comment Share on other sites More sharing options...
iesposta Posted May 31, 2013 Share Posted May 31, 2013 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted May 31, 2013 Share Posted May 31, 2013 This has every possible thing stripped out of it: ex_sound_using_data_one_sound_2013y_05m_31d_0052t.bin ex_sound_using_data_one_sound_2013y_05m_31d_0052t.bas Press the fire button to hear a sound. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted May 31, 2013 Share Posted May 31, 2013 (edited) 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 May 31, 2013 by SeaGtGruff 1 Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 3, 2013 Author Share Posted June 3, 2013 Many thanks =) Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted June 4, 2013 Share Posted June 4, 2013 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 Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 4, 2013 Author Share Posted June 4, 2013 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? Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted June 4, 2013 Share Posted June 4, 2013 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. Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 4, 2013 Author Share Posted June 4, 2013 Ahh! Okay, now I theoretically understand how it might be done. But theory and practice are seldom the same thing =D Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 4, 2013 Author Share Posted June 4, 2013 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 Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted June 4, 2013 Share Posted June 4, 2013 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 Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 4, 2013 Author Share Posted June 4, 2013 Your method was by far the easiest I've atempted, and I'm sticking too it =) Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted June 4, 2013 Share Posted June 4, 2013 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 Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 4, 2013 Author Share Posted June 4, 2013 Cheers! Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 5, 2013 Author Share Posted June 5, 2013 (edited) 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 June 5, 2013 by Rabbit 2600 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted June 5, 2013 Share Posted June 5, 2013 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 Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 5, 2013 Author Share Posted June 5, 2013 (edited) 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 Edited June 5, 2013 by Rabbit 2600 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted June 5, 2013 Share Posted June 5, 2013 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. Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 5, 2013 Author Share Posted June 5, 2013 Aha! That answered my next question too! Excellent =) Quote Link to comment Share on other sites More sharing options...
Rabbit 2600 Posted June 5, 2013 Author Share Posted June 5, 2013 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 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted June 5, 2013 Share Posted June 5, 2013 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.