can't get AYFX to work

Page 2/3
1 | | 3

By Tangent

Supporter (4)

Tangent's picture

15-10-2019, 06:01

Thanks Manel! Your instructions made it simple to implement the replayer.

Is the C register meant to be loaded with the sample's priority value (0-15) in this routine? The comments on ayFX_INIT say so, but it doesn't seem to be working. Is the sample's priority meant to be defined another way? Question

Manel46 wrote:

Call FX:

 LD HL,"name.afb"
 LD A,200
 LD (ayFX_VOLUME),A
 CALL ayFX_SETUP
 XOR A
 LD C,1
 CALL ayFX_INIT
 XOR A
 LD (ayFX_VOLUME),A 
 RET

By Manel46

Champion (431)

Manel46's picture

15-10-2019, 09:58

I guess this is effective for PSG music. With msx music or opl4, it surely doesn't work.
I say it by logic, but I'm not sure.

By norakomi

Paladin (992)

norakomi's picture

15-10-2019, 12:08

@Tangent

Yeah, the C register is meant to be used as a priority for the sfx.
I have found 5 different ayfx replayers online, and not all of them support this priority setting.
Some of them seem to rotate the 3 psg registers, allowing 3 sfx to be played at the same time.
In this case you don't need the priority setting at all.
Let me know what your findings are, I'm also trying my best to understand what is happening.
I don't yet understand the code completely

By Tangent

Supporter (4)

Tangent's picture

16-10-2019, 01:57

I was able to get the priorities working well (tested with 2 sounds) by calling my sound effects this way:

PLAY_FX_EXPLODE:
    ; A = Index of sample in bank
    LD      A,2
    ; C = Priority (0-15) of sample
    LD      C,2
    CALL    ayFX_INIT
    RET
PLAY_FX_SHOOT:
    LD      A,1
    LD      C,1
    CALL    ayFX_INIT
    RET

I set up the replayer with:

    ; Load FX bank to ayFX replayer
    LD      HL,FX_BANK
    CALL    ayFX_SETUP

FX_BANK:
    INCBIN  "FX.AFB"

And added to my VDP interrupt routine:

    CALL    PT3_ROUT
    CALL    PT3_PLAY
    CALL    ayFX_PLAY

I used the ROM version of the ayFX Replayer v1.31 provided by theNestruo here. According to the readme this should be all that's required to set up and call the replayer.

As far as I can tell, the channel rotation is intended to prevent interference with music. A sample with a higher priority will interrupt one which is playing at a lower priority, but only one sound will play at a time. I would be interested to see if this is not the case however. :)

By norakomi

Paladin (992)

norakomi's picture

17-10-2019, 10:37

The version I'm using plays back multiple sound effect at the same time.
3 max obviously.
I think it also uses channel rotation to cause less interference with the music.
If you are interested I can copy the code.
So far I really like it.

By thegeps

Champion (272)

thegeps's picture

17-10-2019, 11:45

I'm interested. What about music? Wich tools do you use to compose and replay it as bgm?

By norakomi

Paladin (992)

norakomi's picture

17-10-2019, 18:06

Alright,
This is the sfx code:

;;;;;;;;;;;;;;;;based on Shiru's, modified by Artrag in April 6 2014
; map 0C000h
DATA_AREA: ;$
afxNoisePeriod: ds 1
afxBnkAdr: ds 2
AYREGS: ds 14

; descriptors channels 11 bytes to the channel:
; 0 (2) the current address (the channel is free, if the high byte = $ 00)
; 2 (2) Time effect
; 4 (1) the volume
; 5 (1) bits of the mixer
; 6 (2) pitch period
; 8 (1) looping effect if != $00
; 9 (2) starting point if looping

afxChData: ds 3*11
END_DATA_AREA: ;$
; endmap

TonA: EQU 0
TonB: EQU 2
TonC: EQU 4
Noise: EQU 6
Mixer: EQU 7
AmplA: EQU 8
AmplB: EQU 9
AmplC: EQU 10

loopingsfx: equ 0 ; sfx with $ up to loopingsfx (excluded) will loop, the higher $ will go once

; ------------------------------------------------- ------------- ;
; Initialization player effects. ;
; Turns off all channels , sets variables . ;
; ------------------------------------------------- ------------- ;

AFXINIT:

; ld hl, sfxBank_miz
; ld de,miz_buffer
; call mom_depack_rom

AFXSTOP:
ld hl,DATA_AREA
ld b,END_DATA_AREA-DATA_AREA
.loop:
ld (hl),0
inc hl
djnz .loop

; LD HL,DATA_AREA
; LD (HL),0
; LD DE,DATA_AREA+1
; LD BC,END_DATA_AREA-DATA_AREA+1
; LDIR

ld hl,$4000 ;miz_buffer
inc hl
ld (afxBnkAdr), hl; reserve table address offsets

xor a
ld (afxNoisePeriod), a

ld hl, afxChData; mark all channels as empty
ld de, $00ff
ld b, 3

afxInit0:
ld (hl), d
inc hl
ld (hl), d
inc hl
ld (hl), e
inc hl
ld (hl), e
inc hl
ld (hl), d
inc hl
ld (hl), e
inc hl
ld (hl), d
inc hl
ld (hl), d
inc hl
ld (hl), d
inc hl
ld (hl), d
inc hl
ld (hl), d
inc hl
djnz afxInit0
ret

; ------------------------------------------------- ------------- ;
; Playback of the current frame . ;
; With no parameters . ;
; ------------------------------------------------- ------------- ;

AFXFRAME:
;out buffered sfx data
xor a ; --- FIXES BITS 6 AND 7 OF MIXER ---
ld hl,AYREGS+Mixer
set 7,(hl)
res 6,(hl)
ld c,$a0
ld hl,AYREGS
.sfxloop:
out (c),a
inc c
outi
dec c
inc a
cp 13
jr nz,.sfxloop
;/out buffered sfx data

;out buffered sfx data
; xor a ; --- FIXES BITS 6 AND 7 OF MIXER ---
; ld hl,AYREGS+Mixer
; set 7,(hl)
; res 6,(hl)
; ld c,$A1
; ld hl,AYREGS
;.sfxloop:
; out ($A0),A
; inc a
; outi
; cp 13
; jr nz,.sfxloop
;/out buffered sfx data

ld ix, afxChData
ld b, 3
afxFrameLoop:
ld a, (ix +1) ; significant byte addresses effect
or a ; if 0, the channel is not active
jr z, afxFrameChSkip
ld h, a
ld l, (ix +0) ; low byte address effect

ld a, (hl) ; read information bytes
inc hl

ld c, a
ld (ix +5), a ; remember bits mixer
and 15
ld (ix +4), a ; remember volume

bit 5 , c ; changing pitch period
jr z, afxFrameNoTone

ld a, (hl) ; remember period
inc hl
ld (ix +6), a
ld a, (hl)
inc hl
ld (ix +7), a

afxFrameNoTone:
bit 6 , c ; period change noise
jr z, afxFrameNoNoise
ld a, (hl) ; period obtain
cp $20 ; if it is more than 31 , the effect is over
jr c, afxFrameNoise

ld a,(ix+ 8)
and a
jr z,a1
; looping effect
ld l,(ix+ 9) ; restart the effect from the beginning
ld h,(ix+ 10)

ld (ix +0), l ; remember address
ld (ix +1), h

inc (ix +2) ; increment the playing time
jr nz, afxFrameLoop
inc (ix +3)
jr afxFrameLoop

a1: ; no loop
xor a ; vanishes high byte address and the volume
ld (ix +1), a
ld (ix +4), a
jr afxFrameChSkip

afxFrameNoise:
inc hl ; remember period noise
ld (afxNoisePeriod), a

afxFrameNoNoise:

ld (ix +0), l ; remember address
ld (ix +1), h

inc (ix +2) ; increment the playing time
jr nz, afxFrameChSkip
inc (ix +3)

afxFrameChSkip:
ld de, 11 ; the next channel
add ix, de
djnz afxFrameLoop

; ld a, (AYREGS + AmplA)
; ld c, a
ld a, (afxChData +0 * 11 +4)
; cp c
; jr c, afxSkipCh0
ld (AYREGS + AmplA), a
ld a, (afxChData +0 * 11 + 6 )
ld (AYREGS + TonA +0), a
ld a, (afxChData +0 * 11 +7 )
ld (AYREGS + TonA +1), a

ld a, (AYREGS + Mixer)
and %11110110
ld c, a
ld a, (afxChData +0 * 11 + 5 )
rra
rra
rra
rra
and %00001001
or c
ld (AYREGS + Mixer), a

afxSkipCh0:

; ld a, (AYREGS + AmplB)
; ld c, a
ld a, (afxChData +1 * 11 +4)
; cp c
; jr c, afxSkipCh1
ld (AYREGS + AmplB), a
ld a, (afxChData +1 * 11 + 6 )
ld (AYREGS + TonB +0), a
ld a, (afxChData +1 * 11 +7 )
ld (AYREGS + TonB +1), a

ld a, (AYREGS + Mixer)
and %11101101
ld c, a
ld a, (afxChData +1 * 11 + 5 )
rra
rra
rra
and %00010010
or c
ld (AYREGS + Mixer), a

afxSkipCh1:

; ld a, (AYREGS + AmplC)
; ld c, a
ld a, (afxChData +2 * 11 +4)
; cp c
; jr c, afxSkipCh2
ld (AYREGS + AmplC), a
ld a, (afxChData +2 * 11 + 6 )
ld (AYREGS + TonC +0), a
ld a, (afxChData +2 * 11 +7 )
ld (AYREGS + TonC +1), a

ld a, (AYREGS + Mixer)
and %11011011
ld c, a
ld a, (afxChData +2 * 11 + 5 )
rra
rra
and %00100100
or c
ld (AYREGS + Mixer), a

afxSkipCh2:

ld ix, afxChData
ld a,(ix +0 * 11 +5)
and (ix +1 * 11 +5)
and (ix +2 * 11 +5)
rla
jr c, afxNoNoise
ld a, (afxNoisePeriod)
ld (AYREGS + Noise), a
afxNoNoise:

ret

; ------------------------------------------------- ------------- ;
; Running effect on the free channel. In the absence ;
; free channels selects the most long -sounding . ;
; Input : A = number of effect 0 .. 255 ;
; ------------------------------------------------- ------------- ;

AFXPLAY:
push ix
push iy
ex af,af'

ld ix, afxChData ; empty channel search
ld de,11
ld b,3
b1: ld a,(ix +1)
or a
jr z,freechan
add ix,de
djnz b1
; no free channels

ld iy, afxChData ; search the channel that plays from more time
ld ix, afxChData ; in case of 3 looping channels use channel A
ld de, 0 ; in de the longest time while searching
ld bc,11
ld a, 3
afxPlay0:
inc (iy+8)
dec (iy+8)
jr nz, afxPlay1 ; skip channels with looping effects
ld l, (iy+2) ; compare time channel with the highest
ld h, (iy+3)
sbc hl,de
jr c, afxPlay1
add hl,de ; remember the longest time
ex de,hl
push iy ; remember the address of the channel in ix
pop ix
afxPlay1:
add iy,bc
dec a
jr nz,afxPlay0
; expect to address the effect
freechan:
ld h, a
ex af,af'
ld l, a
add hl, hl
ld bc, (afxBnkAdr) ; address offset table effects
add hl, bc
ld c, (hl)
inc hl
ld b, (hl)
add hl, bc ; effect address obtained in hl

ld (ix+0), l ; record in the channel descriptor
ld (ix+1), h
ld (ix+2), 0 ; reset execution Time
ld (ix+3), 0

ld (ix+8), 0 ; reset looping flag

cp loopingsfx ; up to sfx $loopingsfx-1 will loop
jr nc,c1

ld (ix+ 8), -1 ; set looping flag
ld (ix+ 9), l ; record in the channel descriptor for later use
ld (ix+10), h

c1:
pop iy
pop ix
ret

ROUT:
xor A ; --- FIXES BITS 6 AND 7 OF MIXER ---
LD HL,AYREGS+Mixer
set 7,( hl)
res 6,( hl)

LD C,0xA1
LD HL,AYREGS
d1: OUT (0xA0),A
INC A
OUTI
CP 13
JR NZ,d1
RET

By norakomi

Paladin (992)

norakomi's picture

17-10-2019, 18:10

in the code you see:
ld hl,$4000 ;miz_buffer
This is the address where I have stored my sfx bank.
Of course you can change this to any address you want.

I really love the fact that this code can play 3 sfx at the same time, and really barely interferes with the music.

For music I use MBPLAY. Moonblaster songs.

By thegeps

Champion (272)

thegeps's picture

17-10-2019, 18:20

Ops! I plan to use only PSG for both BGM and SFX. So better I use only one channel for SFX, I think... (but I'll look this code anyway, I have a lot to learn)

By ARTRAG

Enlighted (6250)

ARTRAG's picture

17-10-2019, 20:43

Page 2/3
1 | | 3