Sound Effect Engine

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Sound Effect Engine

Post by chysn »

My medium of choice, at the moment anyway, is the unexpanded VIC. So for much of 2020, I've been working on a loose suite of tools to make game development easier, with a focus on smallness. I thought I'd share my sound effect engine, which anybody may use in whole, or as a starting point, or whatever.

The basic ideas are (1) It's lightweight, at around 100 bytes. (2) Each sound effect is in an indexed table, and is described by two bytes, with a minimum number of parameters. (3) A sound effect may be easily launched in the code with

Code: Select all

LDA #EffectIndex
JSR FXLaunch
Once launched, the effect will be handled by the IRQ service routine, which calls JSR FXService once per interrupt, and automatically ends when it's done.

I used a variant of this engine for TRBo and Helix Colony. This is a new version that supports bi-directional movement of the shift register. Each effect specifies a shift direction, a 7-bit starting frequency, a 4-bit length, and a 4-bit rotation speed. From this small group of parameters, you can get a wide variety of 8-bit arcade-style effects.

Everything you need is in the attached archive, the ML routine, and a BASIC demo program.

Code: Select all

* = $1800                       ; Sample location
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; SAMPLE INSTALL AND ISR CODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
Install:    php
            sei
            lda #<ISR
            sta $0314
            lda #>ISR
            sta $0315
            plp
            rts

; Sample ISR
; Your project's interrupt service routine should call FXService at some
; point
ISR:        jsr FXService
            jmp $eabf


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; CONFIGURATION
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
FX_VOICE =  $900c               ; $900c=high, $900b=mid, $900a=low, $900d=noise

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; VARIABLES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; No need to do anything with these; they are managed by the FXService and
; FXLaunch routines
FX_REG      .byte $00           ; Current effect frequency register
FX_LEN:     .byte $00           ; Effect length for current effect
FX_COUNT:   .byte $00           ; Effect countdown for current effect
FX_DIR:     .byte $00           ; Effect direction ($00 if left, $80 is right)
FX_SPEED:   .byte $00           ; Effect countdown reset value

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; EFFECTS SERVICE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;              
; Play Next Sound Effect
; Rotates the 8-bit sound effect register and
; plays the pitch      
FXService:  lda FX_LEN          ; Has the sound been launched?
            beq fx_end          ; If unlaunched, kill voice and return
            dec FX_LEN          ; Decrement both length
            dec FX_COUNT        ;   and countdown
            bne fx_r            ; If countdown has elapsed,
            lda FX_SPEED        ;   reset it with the current effect speed
            sta FX_COUNT        ;   ,,
            bit FX_DIR          ; Rotate the register, based on the direction
            bmi fx_right        ;   specified by the direction flag
fx_left:    lda #$00
            asl FX_REG          ; Rotate the register left if flag = $00
            adc FX_REG          ; If carry was set, set bit 0
            jmp fx_update       ; Update and play the new frequency
fx_right:   lsr FX_REG          ; Rotate the register right if flag = $80
            lda FX_REG          ; ,,
            bcc fx_play         ; If carry was set, set bit 7
            lda #%10000000      ; ,,
            ora FX_REG          ; ,,
fx_update:  sta FX_REG          ; ,,
fx_play:    ora #$80            ; Gate the high voice
fx_end:     sta FX_VOICE        ; ,,
fx_r:       rts      
        
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; EFFECTS LAUNCHER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;         
; Launch Sound Effect
; Preparations
;     A - The sound effect index
FXLaunch:   sei                 ; Don't play anything while setting up
            asl                 ; Each effect has two bytes in the table
            tax
            lda FXTable,x       ; Get the register byte
            sta FX_DIR          ; Set the direction (only bit 7 will be used)
            and #$7f            ; Mask away the direction bit to get the 7-bit
            sta FX_REG          ;   frequency
            lda FXTable+1,x     ; Get the length byte
            tax                 ;   and preserve it
            and #$f0            ; Length is in bits 4-7 of the length byte
            sta FX_LEN          ;  ,,
            txa
            and #$0f            ; Speed (jiffies per rotation) is in the low
            sta FX_SPEED        ;   nybble of the length byte
            sta FX_COUNT        ;   ,,
            cli                 ; Go! 
            rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; EFFECTS TABLE (EXAMPLES)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; Sound effects for the sound effects player
; Each effect has four parameters (DFFFFFFF LLLLSSSS)
;   (1) Bit 7 (D) of the first byte is the direction
;       * Unset=shift left, or a rising sound 
;       * Set=shift right, or a falling sound
;   (2) Bits 0-6 (F) of the first byte is the frequency register
;   (3) High nybble of the second byte (L) is the length in jiffies x 16
;       * Between approx. 1/4 sec and 4 sec in length
;   (4) Low nybble of second byte (S) is speed in jiffies
FXTable:    .byte $7a,$13       ; 0- Insert Coin
            .byte $55,$68       ; 1- Klaxon
            .byte $f0,$26       ; 2- Falling Into Something
            .byte $07,$13       ; 3- Power Up
            .byte $3b,$31       ; 4- Laser Cannon
            .byte $6c,$74       ; 5- Command Ship Crossing
            .byte $95,$14       ; 6- Dropped Something
            .byte $92,$11       ; 7- Explosion
Attachments
VIC20-SoundFX.zip
(3.59 KiB) Downloaded 63 times
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
Post Reply