Piszemy DEMOOstatnim razem zakończyliśmy zmagania nad grafika naszego komputera. Tym razem zajmiemy się dźwiękiem.
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Consol Equ $D01F
Opt List_err+Code_mem
Org Procedure
Ldx #$00
Txa
L1 Eor #$0F
Sta Consol
Ldy #$00
L2 Dey
Bne L2
Inx
Bne L1
Rts
End of File
Łatwo zauważyć, że nie można dokładnie określić częstotliwości generowanego tym sposobem dźwięku. Możliwość określenia głośności, wysokości i stopnia zniekształcenia dźwięku dają dopiero cztery niezależne generatory dźwięku. Każdy z nich posiada dwa rejestry kontrolne. Pierwszy rejestr, o nazwie AUDFx {x - numer kanału 1-4), określa częstotliwość pracy danego generatora. Standardowo częstotliwość dźwięku mierzy się w Hz. W naszym przypadku mamy do dyspozycji tylko jeden bajt i aby wygenerować odpowiedni dźwięk trzeba skorzystać z zależności:częstotliwość = 31960/(x+1), gdzie x to bajt wysyłany do AUDF. Natomiast rejestr drugi o nazwie AUDCx (gdzie x oznacza również nr kanału), określa głośność i stopień zniekształcenia dźwięku. Bity 0-3 tego rejestru określają głośność dźwięku, bitem czwartym zajmiemy się później, natomiast bity 5-7 sterują zniekształceniami dźwięku. Najwyższa pora, aby podać adresy wszystkich ośmiu rejestrów: AUDF1 - częst. pracy generatora 1 AUDC1 - sterowanie generatorem 1 AUDF2 - częst. pracy generatora 2 AUDC2 - sterowanie generatorem 2 AUDF3 - częst. pracy generatora 3 AUDC3 - sterowanie generatorem 3 AUDF4 - częst. pracy generatora 4 AUDC4 - sterowanie generatorem 4 Rejestry te zajmują w pamięci lokacje $D200 - $D207 i wszystkie są rejestrami sprzętowymi, które przy odczycie pętała mną funkcję. Poniższy przykład odgrywa dźwięki o losowej częstotliwości, wykorzystując generator 1.
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Audc1 Equ $D201
Audf1 Equ $D200
Kbcodes Equ $02FC
Random Equ $D20A
Rtclok Equ $12
Opt List err+Code_mem
Org Procedure
L1 Lda Random
Sta Audf1
Lda #$AA
Sta Audc1
Lda Rtclok+$02
L2 Cmp Rtclok+$02
Beq L2
Lda Kbcodes
Bmi L1
Lda #$00
Sta Audc1
Rts
End of File
Kolejny przykład produkuje dźwięki na dwóch generatorach. Jeden ze wzrastającą częstotliwością, drugi z malejącą.
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Audcl Equ $D201
Audc2 Equ $D203
Audfl Equ $D200
Audf2 Equ $0202
Kbcodes Equ $02FC
Random Equ $D20A
Rtclok Equ $12
Opt List_err+Code_main
Org Procedure
Ldx #$00
Ldy #$FF
L1 Lda #$AA
Stx Audfl
Sty Audf2
Sta Audcl
Sta Audc2
Lda Rtclok+$02
L2 Cmp Rtclok+$02
Beq L2
Inx
Dey
Bne L1
Sty Audcl
Sty Audc2
Rts
End of File
Oba zaprezentowane przykłady generują czyste dźwięki, bez zniekształceń. Dźwięk czysty otrzymujemy, jeśli bity 5-7 AUDCx ustawione są w następujący sposób: 101 lub 111. Przy innym ustawieniu bitów, np. 100 lub 011, otrzymuje się dźwięk zniekształcony.Bit 4 AUDCx zwany jest dwustanowym bitem regulacji głośności lub kontrolą siły głosu bez modulacji. Głośnik wytwarza dźwięk przez drgania membrany. Czwarty bit AUDCx umożliwia właśnie poruszanie membraną głośnika w przód i w tył. W ten sposób wytworzyć można również ciekawe dźwięki. Jak w przykładzie poniżej:
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Audcl Equ $D201
Kbcodes Equ $02FC
Rtclok Equ $12
Opt List_err+Code_mem
Org Procedure
L1 Ldx #$0A
L2 Lda Tabela,x
Sta Audcl
Jsr Opoz
Lda #$00
Sta Audcl
Jsr Opoz
Dex
Bpl L2
Lda Kbcodes
Bmi L1
Rts
Opoz Ldy Rtclok+$02
L3 Cpy Rtclok+$02
Beg L3
Rts
Tabela Dta B($15),B($16)
Dta B($17),B($18)
Dta B($19),B($1A)
Dta B($19),B($18)
Dta B($17),B($16)
Dta B($15)
End of File
Kolejne wartości dla AUDC1 pobierane są z tabeli Tabela. Po 1/50 sekundy membrana powraca do stanu pierwotnego, aby po kolejnej 1/50 sekundy pobrać następną wartość z tablicy.Ostatni program zamienia klawiaturę Atari w klawiaturę syntezatora. Klawisz Y odpowiada środkowemu C w piątej oktawie (261 Hz).
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Audcl Equ $D201
Audfl Equ $D200
Kbcodes Equ $02FC
Skstat Equ $D20F
Opt List_err+Code_mem
Org Procedure
L0 Ldy #$FF
Sty Kbcodes
L1 Lda Kbcodes
Bmi L1
Cmp #$1C
Beg L5
Ldx #$17
L2 Cmp Klawisze,x
Beq L3
Dex
Bpl L2
Bmi L0
L3 Lda Dzwięki,x
Sta Audf1
Lda #$AA
Sta Audcl
L4 Lda Skstat
And #$04
Beg L4
Lda #$00
Sta Audcl
Sta Audfl
Beg L0
L5 Rts
Klawisze Dta B($2C),B($1F)
Dta B($2F),B($1E)
Dta B($2E),B($2A)
Dta B($18),B($28)
Dta B($1D),B($2D)
Dta B($1B),B($2B)
Dta B($0B),B($35)
Dta B($0D),B($30)
Dta B($08),B($0A)
Dta B($36),B($0E)
Dta B($37),B($0F)
Dta B($34),B($0C)
Dzwieki Dta B($F3),B($E6)
Dta B($D9),B($CC)
Dta B($C1),B($B6)
Dta B($AD),B($A2)
Dta B($99),B($90)
Dta B($88),B($80)
Dta B($79),B($72)
Dta B($6C),B($66)
Dta B($60),B($5B)
Dta B($55),B($51)
Dta B($4C),B($48)
Dta B($44),B($40)
End of File
W tablicy Klawisze umieszczone są kody klawiszy dwóch górnych rzędów klawiatury, a w tablicy Dźwięki - odpowiadające im częstotliwości. Naciśnięcie klawisza ESC przerywa działanie programu. Naciśnięcie klawisza powoduje odszukanie jego kodu w tablicy Klawisze, wybranie odpowiedniego dźwięku z tablicy Dźwięki i przesłanie go do generatora 1. Dźwięk trwa tak długo, jak długo naciśnięty jest klawisz. Informacja o tym zawarta jest w rejestrze Skstat.Dodatkowym rejestrem modyfikującym dźwięk jest rejestr AUDCTL ($D208). Bit 0 tego rejestru przełącza główny zegar bazowy z częstotliwości 64 kHz na 15 kHz, co w praktyce pozwala uzyskać niższe częstotliwości dźwięku. Bity 1 i 2 to filtry górnoprzepustowe kontrolujące dźwięki. Bit 3 łączy kanały 3 i 4 dając szesnastobitową zmienną kontrolującą i tym samym zmniejszając skok częstotliwości z 1/256 (jeden bajt) do 1/65536 (jedno słowo). Bit 4 ma takie samo znaczenie jak bit 3, przy czym łączone są kanały 1 i 2. Bity 5 i 6 działają podobnie jak bit 0, przy czym zwiększają wysokość generowanego tonu odpowiednio w generatorach 3 i 1. Bit 7 przełącza licznik "poly" z 17 na 9 bitów. Im mniejsza pojemność tego licznika, tym częściej powtarzane są zniekształcenia generowanego dźwięku. Używanie filtrów "na własną rękę" może być ciekawym eksperymentem. Rejestr AUDCTL nie został jednak opisany tak dokładnie, aby jego możliwości można było profesjonalnie wykorzystać, tym zajmują się programy muzyczne. Zaprezentowaliśmy procedury tworzące proste dźwięki, natomiast skomplikowaną muzykę, wykonywaną, co ważniejsze - na przerwaniach, tworzy się z wykorzystaniem np. Chaos Music Composer'a lub Future Composer'a, które uważamy za najlepsze (nie biorąc pod uwagę programów dołączających dźwięki digitalizowane). W następnym artykule rozpoczniemy już pisanie naszego dema. Nabyte dotąd wiadomości pozwolą nam zrozumieć w pełni działanie wszystkich procedur. Tomasz Bielak
Rafał Bielecki |