From 0a7eed3276f1cae45704778bc4097c783e4791bf Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sat, 16 May 2020 10:25:55 +0800 Subject: [PATCH] Sound driver changes Add scaling to the tone table period to maintain maximum range and minimize error. --- Source/HBIOS/audio.inc | 40 --------------------- Source/HBIOS/ay38910.asm | 77 +++++++++++++++++++++++++--------------- Source/HBIOS/sn76489.asm | 40 +++++++++++++++++++-- 3 files changed, 86 insertions(+), 71 deletions(-) diff --git a/Source/HBIOS/audio.inc b/Source/HBIOS/audio.inc index 41d6273c..e02e7af4 100644 --- a/Source/HBIOS/audio.inc +++ b/Source/HBIOS/audio.inc @@ -34,44 +34,4 @@ #IFNDEF AUDIOUTILS #DEFINE AUDIOUTILS - -AUD_NOTE: - AUDDEBUG("AUDNOTE ") - AUDTRACE_HL - AUDTRACE_CR - AUDTRACE_DE - AUDTRACE_CR -; - PUSH DE ; ON ENTRY HL IS THE NOTE TO PLAY - LD DE, 48 ; AND DE IS THE START OF NOTE TABLE - CALL DIV16 ; LOAD DE WITH NOTE TABLE SIZE - ; AND CALCULATE OCTAVE COUNT IN BC - - ADD HL, HL ; HL IS THE REMAINDER FROM ABOVE DIVISION (0-47) AND THE NOTE - POP DE ; TO PLAY IN THE OCTAVE. ADD IT TO THE START OF THE NOTE TABLE - ADD HL, DE ; TO POINT TO THE PERIOD FOR THE NOTE WE WANT TO PLAY. - - LD A, (HL) ; HL POINT TO CURRENT PERIOD COUNT WE WANT TO PLAY - INC HL ; SO LOAD PERIOD COUNT FROM NOTE TABLE INTO HL - LD H, (HL) ; SO WE CAN UPDATE IT FOR THE REQUIRED OCTAVE - LD L, A - - INC C -AUD_NOTE1: ; DIVIDE THE PERIOD - DEC C ; BY TWO -; JR Z, AUD_NOTE2 ; FOR EACH OCTAVE - RET Z - SRL H - RR L - JR AUD_NOTE1 - -;AUD_NOTE2: -; LD A, L ; IF NOT ZERO -; OR H -; RET NZ ; RETURN THE CALCULATED PERIOD -; -; CPL -; LD H, A ; OTHERWISE RETURN -1 PERIOD (ERROR) -; LD L, A -; RET #ENDIF diff --git a/Source/HBIOS/ay38910.asm b/Source/HBIOS/ay38910.asm index deec80d3..1cff70b3 100644 --- a/Source/HBIOS/ay38910.asm +++ b/Source/HBIOS/ay38910.asm @@ -4,10 +4,8 @@ ; ;====================================================================== ; - #include "cfg_state.inc" - - +; AY_RCSND .EQU 0 ; 0 = EB MODULE, 1=MF MODULE ; #IF (AYMODE == AYMODE_SCG) @@ -15,6 +13,7 @@ AY_RSEL .EQU $9A AY_RDAT .EQU $9B AY_RIN .EQU AY_RSEL AY_ACR .EQU $9C +AY_CLK .SET 3579545 ; MSX NTSC COLOUR BURST FREQ = 315/88 #ENDIF ; #IF (AYMODE == AYMODE_N8) @@ -73,10 +72,13 @@ SBCV2004 .EQU 0 ; USE SBC-V2-004 HALF CLOCK DIVIDER AY_TONECNT .EQU 3 ; COUNT NUMBER OF TONE CHANNELS AY_NOISECNT .EQU 1 ; COUNT NUMBER OF NOISE CHANNELS ; -AY_PHICLK .EQU 3579545 ; MSX NTSC COLOUR BURST FREQ = 315/88 -;AY_PHICLK .EQU 3500000 ; ZX SPECTRUM 3.5MHZ -;AY_PHICLK .EQU 4000000 ; RETROBREW SCB-SCG -AY_RATIO .EQU AY_CLK * 100 / 16 +#IF (AY_CLK > 3579545) ; DEPENDING ON THE +AY_SCALE .EQU 2 ; INPUT CLOCK FREQUENCY +#ELSE ; PRESCALE THE TONE PERIOD +AY_SCALE .EQU 3 ; DATA TO MAINTAIN MAXIMUM +#ENDIF ; RANGE AND ACCURACY +; +AY_RATIO .EQU (AY_CLK * 100) / (16 >> AY_SCALE) ; #INCLUDE "audio.inc" ; @@ -127,54 +129,50 @@ AY_FND: LD IY, AY_IDAT ; SETUP FUNCTION TABLE LD DE,(AY_R3CHBP*256)+$00 CALL AY_WRTPSG ; R03 = $00 = XXXX0000 ; - #IF SYSTIMEN LD A, TICKFREQ / 3 ; SCHEDULE IN 1/3 SECOND TO TURN OFF SOUND LD (AY_TIMTIK), A - +; LD HL, (VEC_TICK + 1) ; GET CUR TICKS VECTOR LD (AY_TIMHOOK), HL ; SAVE IT INTERNALLY LD HL, AY_TIMER ; INSTALL TIMER HOOK HANDLER LD (VEC_TICK + 1), HL - +; LD A, $02 ; NOT READY & IN INTERUPT HANDLER LD (AY_READY), A - #ELSE CALL LDELAY ; HALF SECOND DELAY LD E,$00 ; SET VOLUME OFF CALL AY_SETV ; ON ALL CHANNELS LD A, $01 ; READY & NOT IN INTERUPT HANDLER LD (AY_READY), A - #ENDIF ; XOR A ; SUCCESSFULL INIT RET - +; #IF SYSTIMEN AY_TIMER: LD A, (AY_TIMTIK) DEC A LD (AY_TIMTIK), A JR NZ, AY_TIMER1 - +; LD E,$00 ; SET VOLUME OFF CALL AY_SETV ; ON ALL CHANNELS LD A, $01 ; READY & NOT IN INTERUPT HANDLER LD (AY_READY), A - +; LD DE, AY_TIMER ; MAKE AY_TIMER A NO_OP HANDLER LD HL, AY_TIMER1 LD BC, 3 LDIR - +; AY_TIMER1: JP 0 ; OVERWRITTEN WITH NEXT HANDLER AY_TIMHOOK: .EQU $ - 2 AY_TIMTIK .DB 0 ; COUNT DOWN TO FINISH BOOT BEEP - #ENDIF ; ;====================================================================== @@ -184,7 +182,7 @@ AY_TIMTIK .DB 0 ; COUNT DOWN TO FINISH BOOT BEEP AY_INIT: LD DE,(AY_R7ENAB*256)+$F8 ; SET MIXER CONTROL / IO ENABLE. $F8 - 11 111 000 JP AY_WRTPSG ; I/O PORTS = OUTPUT, NOISE CHANNEL C, B, A DISABLE, TONE CHANNEL C, B, A ENABLE - +; AY_CHKREDY: LD A, (AY_READY) BIT 0, A @@ -218,7 +216,7 @@ AY_SV: CALL AY_WRTPSG ; CYCLING THROUGH ALL CHANNELS AY_RESET: AUDTRACE(AYT_INIT) CALL AY_CHKREDY ; RETURNS TO OUR CALLER IF NOT READY - +; PUSH DE PUSH HL CALL AY_INIT ; SET DEFAULT CHIP CONFIGURATION @@ -260,10 +258,34 @@ AY_NOTE: AUDTRACE(AYT_NOTE) AUDTRACE_HL AUDTRACE_CR - - LD DE, AY3NOTETBL - CALL AUD_NOTE ; RETURNS PERIOD IN HL, FALL THRU - ; TO SET THIS PERIOD +; +; CALL PRTHEXWORDHL +; CALL PC_COLON +; + LD DE, AY3NOTETBL ; ON ENTRY HL IS THE NOTE TO PLAY + PUSH DE ; AND DE IS THE START OF NOTE TABLE + LD DE, 48 ; LOAD DE WITH NOTE TABLE SIZE + CALL DIV16 ; AND CALCULATE OCTAVE COUNT IN BC +; + ADD HL, HL ; HL IS THE REMAINDER FROM ABOVE DIVISION (0-47) AND THE NOTE + POP DE ; TO PLAY IN THE OCTAVE. ADD IT TO THE START OF THE NOTE TABLE + ADD HL, DE ; TO POINT TO THE PERIOD FOR THE NOTE WE WANT TO PLAY. +; + LD A, (HL) ; HL POINT TO CURRENT PERIOD COUNT WE WANT TO PLAY + INC HL ; SO LOAD PERIOD COUNT FROM NOTE TABLE INTO HL + LD H, (HL) ; SO WE CAN UPDATE IT FOR THE REQUIRED OCTAVE + LD L, A +; + LD A,AY_SCALE ; THE NOTE TABLE PERIOD DATA HAS BEEN + ADD A,C ; PRESCALED TO MAINTAIN RANGE SO ALLOW + LD B,A ; FOR THIS WHEN CHANGING OCTAVE +AY_NOTE1: + SRL H ; ADJUST THE PERIOD DATA + RR L ; FOR THE DESIRED OCTAVE + DJNZ AY_NOTE1 ; FALL THROUGH TO SET PERIOD AND RANGE CHECK +; +; CALL PRTHEXWORDHL +; CALL NEWLINE ; ;====================================================================== ; SOUND DRIVER FUNCTION - PERIOD @@ -277,7 +299,7 @@ AY_PERIOD: LD A, H ; IF ZERO - ERROR OR L JR Z, AY_PERIOD1 - +; LD A, H ; MAXIMUM TONE PERIOD IS 12-BITS AND 11110000B ; ALLOWED RANGE IS 0001-0FFF (4095) JR NZ, AY_PERIOD1 ; RETURN NZ IF NUMBER TOO LARGE @@ -425,7 +447,6 @@ AY_EI: RET NZ HB_EI RET - ; ;====================================================================== ; @@ -459,7 +480,6 @@ AY_WRTPSG: OUT (112),A ; NORMAL CLOCK SPEED #ENDIF JP AY_EI - ; ;====================================================================== ; @@ -509,13 +529,14 @@ AYT_REGWR .DB "\r\nOUT AY-3-8910 $" #ENDIF ; ;====================================================================== -; BBC MICRO QUARTER TONE FREQUENCY TABLE +; QUARTER TONE FREQUENCY TABLE ;====================================================================== ; -; THE FREQUENCY BY QUARTER TONE STARTING AT A0# OCATVE 0 +; THE FREQUENCY BY QUARTER TONE STARTING AT A0# OCTAVE 0 ; USED TO MAP EACH OCTAVE (DIV BY 2 TO JUMP AN OCTAVE UP) ; FIRST PLAYABLE NOTE WILL BE 0 ; ASSUMING A CLOCK OF 1843200 THIS MAPS TO A0# +; AY3NOTETBL: .DW AY_RATIO / 2913 .DW AY_RATIO / 2956 diff --git a/Source/HBIOS/sn76489.asm b/Source/HBIOS/sn76489.asm index 220e07e3..d1b784cc 100644 --- a/Source/HBIOS/sn76489.asm +++ b/Source/HBIOS/sn76489.asm @@ -24,7 +24,8 @@ CHANNEL_1_SILENT .EQU $BF CHANNEL_2_SILENT .EQU $DF CHANNEL_3_SILENT .EQU $FF -SN7RATIO .EQU SN7CLK * 100 / 32 +SN7_SCALE .EQU 4 +SN7RATIO .EQU (SN7CLK * 100) / (32 >> SN7_SCALE) .ECHO "SN76489 CLOCK: " .ECHO SN7CLK @@ -104,9 +105,42 @@ SN7_VOLUME: RET SN7_NOTE: + +; CALL PRTHEXWORDHL +; CALL PC_COLON + + AUDDEBUG("AUDNOTE ") + AUDTRACE_HL + AUDTRACE_CR + AUDTRACE_DE + AUDTRACE_CR + LD DE, SN7NOTETBL - CALL AUD_NOTE ; RETURNS PERIOD IN HL, FALL THRU - ; TO SET THIS PERIOD + PUSH DE ; ON ENTRY HL IS THE NOTE TO PLAY + LD DE, 48 ; AND DE IS THE START OF NOTE TABLE + CALL DIV16 ; LOAD DE WITH NOTE TABLE SIZE + ; AND CALCULATE OCTAVE COUNT IN BC + + ADD HL, HL ; HL IS THE REMAINDER FROM ABOVE DIVISION (0-47) AND THE NOTE + POP DE ; TO PLAY IN THE OCTAVE. ADD IT TO THE START OF THE NOTE TABLE + ADD HL, DE ; TO POINT TO THE PERIOD FOR THE NOTE WE WANT TO PLAY. + + LD A, (HL) ; HL POINT TO CURRENT PERIOD COUNT WE WANT TO PLAY + INC HL ; SO LOAD PERIOD COUNT FROM NOTE TABLE INTO HL + LD H, (HL) ; SO WE CAN UPDATE IT FOR THE REQUIRED OCTAVE + LD L, A + + LD A,SN7_SCALE ; THE NOTE TABLE PERIOD DATA HAS BEEN + ADD A,C ; PRESCALED TO MAINTAIN RANGE SO ALLOW + LD B,A ; FOR THIS WHEN CHANGING OCTAVE +SN7_NOTE1: + SRL H ; ADJUST THE PERIOD DATA + RR L ; FOR THE DESIRED OCTAVE + DJNZ SN7_NOTE1 ; FALL THROUGH TO SET PERIOD AND RANGE CHECK + +; CALL PRTHEXWORDHL +; CALL NEWLINE + SN7_PERIOD: AUDTRACE(SNT_PERIOD) AUDTRACE_HL