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 FileKolejny 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 FileOba 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 FileKolejne 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 FileW 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 |