Boriel Basic Forum
Sound effects? - Printable Version

+- Boriel Basic Forum (https://forum.boriel.com)
+-- Forum: Compilers and Computer Languages (https://forum.boriel.com/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://forum.boriel.com/forumdisplay.php?fid=11)
+---- Forum: How-To & Tutorials (https://forum.boriel.com/forumdisplay.php?fid=13)
+---- Thread: Sound effects? (/showthread.php?tid=338)

Pages: 1 2


Sound effects? - LTee - 2011-03-25

Can anyone suggest how I could make some half-reasonable beeper sound effects? My initial experiments with BEEP are.... uninspiring. :-D

I was wondering if there was a tool or something that I could use to create some snazzier effects and then somehow integrate those into my ZXBasic setup? Or are there any tricks that people use to get more out of BEEP?

Thanks!


Re: Sound effects? - britlion - 2011-03-27

For music, you could try beepola: <!-- m --><a class="postlink" href="http://freestuff.grok.co.uk/beepola/">http://freestuff.grok.co.uk/beepola/</a><!-- m -->

What are you looking for? Lasers zaps and bangs?


Re: Sound effects? - LTee - 2011-03-27

I'm not really sure, just anything that doesn't sound like 'beep'. :-)

I've seen Beepola before but never had a play with it. I'm not exactly 'talented' in the music department, but we'll see how it goes.


Re: Sound effects? - LTee - 2011-03-28

Beepola seems quite amusing, although I'm still not entirely convinced that I have any musical talent whatsoever! It would be nice to add a couple of little jingles to my game though, and the Special FX engine sounds quite nice even without any talent. :-)

Has anyone integrated Beepola output with ZXBasic before? Wondering if there any pitfalls to watch out for before I go too far. Some of the engines use IM2, for instance - any potential problems there? I think the best thing to do would be to make a tiny test tune and see if I can get it working in-game.

Still experimenting (and not having much luck) with sound effects.


Re: Sound effects? - boriel - 2011-03-28

I was trying some special effects using Beeps (fast constant beeps) or just OUT 254, x. These techniques were uses on earlier games for the ZX Spectrum. I think there are some beep tutorials in WOS (probably someone has already asked for this at the WOS forum). Have you looked in there?


Re: Sound effects? - LTee - 2011-03-28

Maybe that's my issue, I need to do more, faster beeps so that they sound less 'beep-like' - it's kind of tricky to do this by trial and error though, especially seeing as the same code sounds slightly different when compiled with ZXBasic than it does in proper Spectrum BASIC (I surmise Spectrum BASIC isn't quite fast enough to handle the very short beeps elegantly and it results in a slightly slower, lower-pitched sound).

I did do a search of the WOS forums but it's hard to know what to search for. I might pop a question into the development forum and see if anyone there has any pointers for either a tool or a tutorial. It seems strange that there are so many great tools for beeper music but very little for snappy little sound effects.

Is there any discernible difference between using BEEP or OUT 254 in ZXBasic, or are they ultimately different ways of calling the same code?


Re: Sound effects? - LTee - 2011-03-28

In case anyone was interested, Beepola music seems to integrate with ZXBasic just fine! Created a one-pattern ditty with the SpecialFX engine and got it working in my game with no issues. :-)


Re: Sound effects? - britlion - 2011-03-28

For those of us that haven't done it yet (and I've got some stuff I want to add into my game, space permitting) can you post source of how you put it in?


Re: Sound effects? - LTee - 2011-03-28

There's no real 'source' as yet, because I sort of hacked it in there to prove a point. :-)

Basically I created a tune and 'compiled' it from Beepola, then saved it as a .TAP file with a start address of 64000. I then added a 'randomize usr 64000' call into my game at the required point and compiled it to a low-enough address that I knew the game wouldn't overwrite the music. Then I loaded both the game code and the music code before starting the game.

This seems a little fiddly, but it works.

You can get Beepola to output an .asm file instead (which I think would be easier in the long run), but I've not had time to finish playing around with that method yet - it seems a neater way of including the music so that you can build the whole thing in one go.

The ASM *almost* compiles just by wrapping it in an asm/end asm block, there just seems to be a very slight incompatibility with how ZXBasic handles EQU. Beepola outputs this:

Code:
; *** DATA *** VECTOR_TABLE_LOC: EQU $FE00 BORDER_CLR: EQU $0

But ZXBasic doesn't like the colons at the end of the label before the EQUs. Remove those and it compiles fine!

i.e.
Code:
; *** DATA *** VECTOR_TABLE_LOC EQU $FE00 BORDER_CLR EQU $0



Re: Sound effects? - britlion - 2011-03-28

Good to know the asm can be levered in without too much trouble Smile


Re: Sound effects? - LTee - 2011-03-28

Just had a quick go at integrating it via the asm file and it's proving a little more problematic than I expected, I suspect because of the 'org 64000' at the start of the file. If I #include it at the end of my game's code I end up with a tzx which is over 60000 bytes long!

I think I need to fiddle some more. :-)


Re: Sound effects? - britlion - 2011-03-28

That would be fairly normal - it tries to make it one file, so there's a lot of zeroes along the way.

Might be easier to use align to push it there, or write a routine to relocate it to where you need it to be. (there's a block move routine in zx basic)

Or rewrite the code somewhat so it doesn't matter what address it's at - it doesn't care so long as it's placed > 32768 - but does need to be compiled correctly.

What happens if you take out the org?


Re: Sound effects? - LTee - 2011-03-29

Interestingly, that seems to work okay. I'm not exactly a Z80 whizz, but a quick glance over the code seems to suggest that the vast majority of it doesn't care where it's loaded. Only the IM2 service routine has to be at a fixed location and that's hard-coded to $FE00 and above by the player itself. So I suspect that it'll all work fine without the ORG, providing you ensure that your compiled code doesn't exceed address 65024.

This is with the Special FX engine, of course - some of the other players don't use the IM2 table if I'm reading it correctly. But they don't sound as nice. :-)


Re: Sound effects? - LTee - 2011-03-29

Hmm... or maybe not. Something's not *quite* right still. The music will play once, but it doesn't exit properly at the end of the tune (or if you press a key) - the Spectrum locks up rather than ending play gracefully.

I'll paste what I've been messing around with, maybe someone else can see what the issue is:
Code:
cls while(1) print "PRESS ANY KEY TO PLAY" while inkey <> "": end while while inkey = "": end while while inkey <> "": end while playmusic() border 7 end while sub playmusic() asm ; ORG 64000 ; ***************************************************************************** ; * Special FX Music Player Engine ; * ; * Based on code written by Jonathan Smith for the Special FX game, Firefly. ; * Modified by Chris Cowley ; * ; * Produced by Beepola v1.06.01 ; ****************************************************************************** START: DI EXX PUSH HL ; Preserve HL' for return to BASIC CALL PLAY_MUSIC IM 1 POP HL EXX EI RET PLAY_MUSIC: CALL MAKE_VECTOR_TABLE CALL INIT_ISR IM 2 LD A,VECTOR_TABLE_LOC / 256 LD I,A LD HL,MUSICDATA ; <- Pointer to Music Data. Change ; this to play a different song LD E,(HL) INC HL LD D,(HL) INC HL LD (NEXT_PATT_PTR),HL LD (NEXT_PERC_PATT_PTR),DE LD (SAVED_SP),SP LD HL,PLAYER_ISR LD ($FFF5),HL ; Set up the JP instruction to point ; to our player ISR LD A,BORDER_CLR LD (OUT_VAL1),A ; Beeper out values for chan1 LD (OUT_VAL2),A ; Beeper out values for chan1 LD (OUT_VAL3),A ; Beeper out values for chan2 LD (OUT_VAL4),A ; Beeper out values for chan2 CALL SET_NEXT_PATT CALL SET_NEXT_PERC_PATT LD C,$01 EXX LD BC,$0101 EI HALT NEXT_NOTE: CALL C,LF02C LD A,B OR A JR NZ,LEF99 LEF61: DEFB $21 ; LD HL,nn CURR_PATT_CH1: DEFW $0000 ; Current Pattern for chan1 LEF64: LD A,(HL) OR A JP M,LEB9B ; bit7 set - command (sustain, pattern end, etc) CALL LF0F6 LD (LEFA2),A SRL A SRL A SRL A LD D,A LD (LEFAD),A XOR A LD (LF02D),A INC A LD (LEFA4),A LD A,(OUT_VAL1) ; Adjust the EAR and MIC bits of this OR $18 ; port output value for the tone LD (OUT_VAL1),A ; generator INC HL POST_MUTE1: LD A,(HL) LD (LEF96),A INC HL LD (CURR_PATT_CH1),HL DEFB $06 ; LD B,n LEF96: DEFB $54 JR LEF9E LEF99: LD A,$03 LEF9B: DEC A JR NZ,LEF9B LEF9E: DEC D JR NZ,LEFB5 DEFB $16 ; LD D,n LEFA2: DEFB $3B DEFB $3E ; LD A,n LEFA4: DEFB $07 LEFA5: DEC A JR NZ,LEFA5 DEFB $3E ; LD A,n OUT_VAL1: DEFB $0 OUT ($FE),A DEFB $3E ; LD A,n LEFAD: DEFB $01 ; frequency counter for CH1 LEFAE: DEC A JR NZ,LEFAE DEFB $3E ; LD A,n OUT_VAL2: DEFB $00 OUT ($FE),A LEFB5: LD A,C OR A JR NZ,LEFEF DEFB $21 ; LD HL,nn CURR_PATT_CH2: DEFW $0000 ; Current pattern for CH2 LEFBC: LD A,(HL) OR A JP M,LEBA6 ; bit7 set - command (sustain, pattern end, etc) CALL LF0F6 LD (LEFF9),A SRL A SRL A LD (LF004),A LD E,A XOR A LD (LF045),A INC A LD (LEFFB),A LD A,(OUT_VAL3) OR $18 LD (OUT_VAL3),A INC HL POST_MUTE2: LD A,(HL) LD (LEFEC),A INC HL LD (CURR_PATT_CH2),HL DEFB $0E ; LD C,n LEFEC: DEFB $0E JR LEFF4 LEFEF: LD A,$03 LEFF1: DEC A JR NZ,LEFF1 LEFF4: DEC E JP NZ,NEXT_NOTE DEFB $1E ; LD E,n LEFF9: DEFB $3B DEFB $3E ; LD A,n LEFFB: DEFB $02 LEFFC: DEC A JR NZ,LEFFC DEFB $3E ; LD A,n OUT_VAL3: DEFB $18 OUT ($FE),A DEFB $3E ; LD A,n LF004: DEFB $0D ; ch2 note frequency LF005: DEC A JR NZ,LF005 DEFB $3E OUT_VAL4: DEFB $0 OUT ($FE),A JP NEXT_NOTE LF00F: POP HL LD A,(HL) LD (LF033),A INC HL JP LEF64 LF018: POP HL LD A,(HL) LD (LF04B),A INC HL JR LEFBC MUTE_CH1: POP HL LD A,(OUT_VAL1) AND $07 LD (OUT_VAL1),A JP POST_MUTE1 MUTE_CH2: POP HL LD A,(OUT_VAL3) AND $07 LD (OUT_VAL3),A JP POST_MUTE2 NULL_NOTE1: POP HL JP POST_MUTE1 NULL_NOTE2: POP HL JP POST_MUTE2 LF021: POP HL CALL SET_NEXT_PATT JP LEF61 LF02C: DEFB $3E LF02D: DEFB $00 INC A LD (LF02D),A DEFB $FE ; CP LF033: DEFB $02 JR C,LF044 XOR A LD (LF02D),A LD HL,LEFAD DEC (HL) JR Z,LF043 LD HL,LEFA4 LF043: INC (HL) LF044: DEFB $3E ; LD A,n LF045: DEFB $00 INC A LD (LF045),A DEFB $FE ; CP LF04B: DEFB $04 RET C XOR A LD (LF045),A LD HL,LF004 DEC (HL) JR Z,LF05A LD HL,LEFFB LF05A: INC (HL) RET LF0F6: PUSH HL PUSH DE LD HL,FREQ_TABLE LD E,A LD D,$0 ADD HL,DE LD A,(HL) POP DE POP HL RET ; ** Reads and sets up the next melody pattern to play SET_NEXT_PATT: DEFB $21 ; LD HL,nn NEXT_PATT_PTR: DEFW $0000 ; holds a pointer to the ; next pattern in the patter list GET_PATT_ADDR: LD E,(HL) INC HL LD D,(HL) INC HL LD A,E OR D JR NZ,STORE_NEXT_P JP ISR_KEY_PRESSED STORE_NEXT_P: LD (NEXT_PATT_PTR),HL EX DE,HL LD E,(HL) INC HL LD D,(HL) INC HL LD (CURR_PATT_CH1),HL LD (CURR_PATT_CH2),DE RET ; ** Reads and sets up the next percussion pattern to play SET_NEXT_PERC_PATT: DEFB $21 ; LD HL,nn NEXT_PERC_PATT_PTR: DEFW $0000 GET_PERC_ADDR: LD E,(HL) INC HL LD D,(HL) INC HL LD (NEXT_PERC_PATT_PTR),HL LD (PERC_PATT),DE LD A,E OR D RET NZ LD E,(HL) INC HL LD D,(HL) EX DE,HL JR GET_PERC_ADDR CALL SET_NEXT_PERC_PATT JR PLAY_PERC LEB9B: INC HL PUSH HL AND $7F CALL JUMP_PERC_ADDR DEFW LF021 DEFW LF00F DEFW MUTE_CH1 DEFW NULL_NOTE1 LEBA6: INC HL PUSH HL AND $7F CALL JUMP_PERC_ADDR DEFW LF021 DEFW LF018 DEFW MUTE_CH2 DEFW NULL_NOTE2 PLAY_PERC: DEFB $21 ; LD HL,nn PERC_PATT: DEFW $0000 ; Address of the percussion data LD A,(HL) INC HL LD C,(HL) INC HL LD (PERC_PATT),HL ; Point PERC_PATT at next datum AND $7F CALL JUMP_PERC_ADDR DEFW DRUM00 ; F094 DEFW DRUM01 ; F09A DEFW DRUM02 ; F0AC DEFW DRUM03 ; F0BB DEFW DRUM04 ; F0D4 DEFW DRUM05 ; F07C JUMP_PERC_ADDR: POP HL ; F0ED ADD A,A ADD A,L LD L,A LD A,(HL) INC HL LD H,(HL) LD L,A JP (HL) DRUM00: CALL SET_NEXT_PERC_PATT JR PLAY_PERC DRUM01: LD E,$0A LD A,BORDER_CLR LD HL,$0100 DRUM01NOISE: XOR $18 OUT ($FE),A LD B,(HL) DRUM01LOOP: DJNZ DRUM01LOOP INC HL DEC E JR NZ,DRUM01NOISE RET DRUM02: LD HL,$005A DRUM02LOOP: LD A,(HL) OR A RET Z AND $18 OR BORDER_CLR OUT ($FE),A INC HL JR DRUM02LOOP DRUM03: LD HL,$0F18 LD D,$0A DRUM03LOOP3: LD B,(HL) DRUM03LOOP: DJNZ DRUM03LOOP LD A,$18 OR BORDER_CLR OUT ($FE),A INC HL LD B,(HL) DRUM03LOOP2: DJNZ DRUM03LOOP2 LD A,BORDER_CLR OUT ($FE),A INC HL DEC D JR NZ,DRUM03LOOP3 RET DRUM04: LD E,$3F LD D,$05 DRUM04LOOP3: LD B,E DRUM04LOOP: DJNZ DRUM04LOOP LD A,$18 OR BORDER_CLR OUT ($FE),A LD A,E RRCA LD E,A LD B,A DRUM04LOOP2: DJNZ DRUM04LOOP2 LD A,BORDER_CLR OUT ($FE),A DEC D JR NZ,DRUM04LOOP3 DRUM05: RET ; ** Creates a vector table of 257 0xFF bytes at the location specified ; ** by VECTOR_TABLE_LOC MAKE_VECTOR_TABLE: LD HL,VECTOR_TABLE_LOC LD DE,VECTOR_TABLE_LOC + 1 LD BC,$0100 LD (HL),$FF LDIR RET ; *** The IM 2 service routine active throughout the life of the player ; *** updates counters, plays any active percussion sounds, and checks for ; *** keypresses or Kempston joystick fire button to terminate PLAYER_ISR: PUSH AF PUSH DE PUSH HL DEC C DEC B EXX DEC C CALL Z,PLAY_PERC ; EBB1 ; Read keyboard XOR A IN A,($FE) CPL AND $1F JR NZ,ISR_KEY_PRESSED XOR A IN A,($1F) BIT 5,A JR NZ,END_PLAYER_ISR BIT 4,A JR NZ,ISR_FIRE_PRESSED END_PLAYER_ISR: EXX POP HL POP DE POP AF SCF EI RETI ISR_FIRE_PRESSED: ISR_KEY_PRESSED: DEFB $31 ; LD SP,nn SAVED_SP: DEFW $0000 ; EI RETI ; ** Sets up everything for our IM2 service routine. Specifically, copies a JR ; ** instruction to $FFFF and a JP $F0FF to $FFF4 INIT_ISR: LD HL,$FFFF LD (HL),$18 ; Copies in our JR for JR FFF4 LD HL,$FFF4 LD (HL),$C3 ; JP (jump address filled-in ; during player initialization) RET ; *** DATA *** VECTOR_TABLE_LOC EQU $FE00 BORDER_CLR EQU $0 FREQ_TABLE: DEFB $FD,$EE,$E1,$D4,$C8,$BD,$B2,$A8,$9F,$96,$8E,$86,$7E DEFB $77,$70,$6A,$64,$5E,$59,$54,$4F,$4B,$47,$43,$3F DEFB $3B,$38,$35,$32,$2F,$2C,$2A,$27,$25,$23,$21,$1F DEFB $1D,$1C,$1B,$19,$17,$16,$15,$13,$12,$11,$10,$0F DEFB $0E,$0D,$0C,$01,$00 MUSICDATA: DEFW PERCSTART SONGSTART: DEFW PAT1 DEFW $0000 DEFW SONGSTART PAT1: DEFW PAT1C2 DEFB 6,14 DEFB 10,14 DEFB 8,7 DEFB 10,7 DEFB 11,7 DEFB 8,7 DEFB 6,14 DEFB 10,14 DEFB 8,7 DEFB 10,7 DEFB 11,7 DEFB 8,7 DEFB $80 PAT1C2: DEFB 23,7 DEFB 22,7 DEFB 20,7 DEFB 22,7 DEFB 23,7 DEFB 23,7 DEFB 22,7 DEFB 20,7 DEFB 23,7 DEFB 22,7 DEFB 20,7 DEFB 22,7 DEFB 23,7 DEFB 23,7 DEFB 22,7 DEFB 20,7 DEFB $80 PERCSTART: DEFW DRM1 DEFW $0000 DEFW PERCSTART DRM1: DEFB 129,28 DEFB 131,28 DEFB 129,28 DEFB 131,28 DEFB $80 end asm end sub



Re: Sound effects? - oblo - 2011-07-14

Hi all

LTee, How a song created with Beepola can be integrated in ZX Basic? I don't know how to handle the .bbsong format in Basic.

Thanks and regards