; ************************************************************ ; Program pro přehrávání čtyřhlasé hudby na 1-bitovém výstupu ; pro PMD-85. Jádro vyvinuto na základě analýzy algoritmu ZX10 ; od Jána Deáka, zde ovšem použita technologie přímé digitální ; syntézy (DDS) s 16-bitovým rozlišením. ; Na rozdíl od 4-násobného převzorkování nesčítá energie ; jednotlivých kanálů. Pro simulaci hlasitosti nutno posunout ; fázi jednotlivých kanálů změnou výchozí hodnoty akumulátorů. ; U nepoužívaných kanálů nastavit konstantu na hodnotu 0000h. ; Kanály se sčítají funkcí OR. ; Teoreticky lze řadit až 127 zvukových kanálů, nutno však ; vždy přepočítat dělicí konstanty a posunout bit repro. ; Samotná procedura "sound" mění nastavení registru konfigura- ; ce paměti. Nutno po návratu správně ošetřit. ; ************************************************************ ; verze z 22. 3. 2019 ; ************************************************************ kbdled .equ 0f6h ; PC 8255 kbdcwr .equ 0f7h ; CWR 8255 BPM .equ 120 ; Beats per minute tick32 .equ (52965/BPM)/2*2 ; základní doba (1/32 nota) ; ********* notaend .equ 0 ; konec notového zápisu ; ********* nota01P .equ 1 ; prodloužená celá nota nota01 .equ 2 ; celá nota nota02P .equ 3 ; doba prodl. půlové noty nota02 .equ 4 ; doba půlové noty nota04P .equ 5 ; doba prodl. čtvrťové noty nota04 .equ 6 ; doba čtvrťové noty nota08P .equ 7 ; doba prodl. osminové noty nota08 .equ 8 ; doba osminové noty nota16P .equ 9 ; doba prodl. 1/16-ové noty nota16 .equ 10 ; doba 1/16-ové noty nota32P .equ 11 ; doba prodl. 1/32-ové noty nota32 .equ 12 ; doba 1/32-ové noty ; ********* ntPAUSE .equ 00h ; PAUZA ; ********* ntA2 .equ 01h ; nota A2 ntAIS2 .equ 02h ; nota AIS2 ntH2 .equ 03h ; nota H2 ; ********* ntC1 .equ 04h ; nota C1 ntCIS1 .equ 05h ; nota CIS1 ntD1 .equ 06h ; nota D1 ntDIS1 .equ 07h ; nota DIS1 ntE1 .equ 08h ; nota E1 ntF1 .equ 09h ; nota F1 ntFIS1 .equ 0ah ; nota FIS1 ntG1 .equ 0bh ; nota G1 ntGIS1 .equ 0ch ; nota GIS1 ntA1 .equ 0dh ; nota A1 ntAIS1 .equ 0eh ; nota AIS1 ntH1 .equ 0fh ; nota H1 ; ********* ntC0 .equ 10h ; nota C0 ntCIS0 .equ 11h ; nota CIS0 ntD0 .equ 12h ; nota D0 ntDIS0 .equ 13h ; nota DIS0 ntE0 .equ 14h ; nota E0 ntF0 .equ 15h ; nota F0 ntFIS0 .equ 16h ; nota FIS0 ntG0 .equ 17h ; nota G0 ntGIS0 .equ 18h ; nota GIS0 ntA0 .equ 19h ; nota A0 ntAIS0 .equ 1ah ; nota AIS0 ntH0 .equ 1bh ; nota H0 ; ********* ntc0 .equ 1ch ; nota c0 ntcis0 .equ 1dh ; nota cis0 ntd0 .equ 1eh ; nota d0 ntdis0 .equ 1fh ; nota dis0 nte0 .equ 20h ; nota e0 ntf0 .equ 21h ; nota f0 ntfis0 .equ 22h ; nota fis0 ntg0 .equ 23h ; nota g0 ntgis0 .equ 24h ; nota gis0 nta0 .equ 25h ; nota a0 ntais0 .equ 26h ; nota ais0 nth0 .equ 27h ; nota h0 ; ********* ntc1 .equ 28h ; nota c1 ntcis1 .equ 29h ; nota cis1 ntd1 .equ 2ah ; nota d1 ntdis1 .equ 2bh ; nota dis1 nte1 .equ 2ch ; nota e1 ntf1 .equ 2dh ; nota f1 ntfis1 .equ 2eh ; nota fis1 ntg1 .equ 2fh ; nota g1 ntgis1 .equ 30h ; nota gis1 nta1 .equ 31h ; nota a1 ntais1 .equ 32h ; nota ais1 nth1 .equ 33h ; nota h1 ; ********* ntc2 .equ 34h ; nota c2 ntcis2 .equ 35h ; nota cis2 ntd2 .equ 36h ; nota d2 ntdis2 .equ 37h ; nota dis2 nte2 .equ 38h ; nota e2 ntf2 .equ 39h ; nota f2 ntfis2 .equ 3ah ; nota fis2 ntg2 .equ 3bh ; nota g2 ntgis2 .equ 3ch ; nota gis2 nta2 .equ 3dh ; nota a2 ntais2 .equ 3eh ; nota ais2 nth2 .equ 3fh ; nota h2 ; ********* ntc3 .equ 40h ; nota c3 ntcis3 .equ 41h ; nota cis3 ntd3 .equ 42h ; nota d3 ntdis3 .equ 43h ; nota dis3 nte3 .equ 44h ; nota e3 ntf3 .equ 45h ; nota f3 ntfis3 .equ 46h ; nota fis3 ntg3 .equ 47h ; nota g3 ntgis3 .equ 48h ; nota gis3 nta3 .equ 49h ; nota a3 ntais3 .equ 4ah ; nota ais3 nth3 .equ 4bh ; nota h3 ; ********* ntc4 .equ 4ch ; nota c4 ntcis4 .equ 4dh ; nota cis4 ntd4 .equ 4eh ; nota d4 ntdis4 .equ 4fh ; nota dis4 nte4 .equ 50h ; nota e4 ntf4 .equ 51h ; nota f4 ntfis4 .equ 52h ; nota fis4 ntg4 .equ 53h ; nota g4 ntgis4 .equ 54h ; nota gis4 nta4 .equ 55h ; nota a4 .org 0 ; ******************* ; čtyřhlasý přehrávač ; ******************* mvi a,8ah ; nastavení obvodu 8255 out kbdcwr lxi b,hudba ; začátek skladby smycka: ldax b ; načíst délku noty inx b ana a rz ; 0 = konec skladby call nota2k ; překódovat na časovou konstantu do DE call precod ; nota #1 >> konstanta shld soundA+1 call precod ; nota #2 >> konstanta shld soundB+1 call precod ; nota #3 >> konstanta shld soundC+1 call precod ; nota #4 >> konstanta shld soundD+1 call sound ; souzvuk 4 tónů jmp smycka ; ***************************************** ; procedura generování čtyř souběžných tónů ; ***************************************** sound: push b ; uschovat ukazatel do notového zápisu soundL: xra a ; příprava funkce OR pro slučování soundA: lxi b,0 ; #1 konstanta výšky tónu lxi h,0 ; akumulátor DDS generátoru dad b ; vlastní DDS syntéza shld soundA+4 ; uložit výsledek sbi 0 ; CY <= výstup frekvence syntezátoru ; (přetečení nahodí A := 11111111) soundB: lxi b,0 ; #2 konstanta výšky tónu lxi h,0 ; akumulátor DDS generátoru dad b ; vlastní DDS syntéza shld soundB+4 ; uložit výsledek sbi 0 ; CY <= výstup frekvence syntezátoru ; (přetečení nahodí A := 1111111x) soundC: lxi b,0 ; #3 konstanta výšky tónu lxi h,0 ; akumulátor DDS generátoru dad b ; vlastní DDS syntéza shld soundC+4 ; uložit výsledek sbi 0 ; CY <= výstup frekvence syntezátoru ; (přetečení nahodí A := 111111xx) soundD: lxi b,0 ; #4 konstanta výšky tónu lxi h,0 ; akumulátor DDS generátoru dad b ; vlastní DDS syntéza shld soundD+4 ; uložit výsledek sbi 0 ; CY <= výstup frekvence syntezátoru ; (přetečení nahodí A := 111111xx) ;rar ; (posun pro 8-kanálový přehrávač) ani 4 ; OUT <= F1 OR F2 OR F3 OR F4 out kbdled dcx d ; odpočet délky souzvuku tónů mov a,d ora e jnz soundL pop b ; obnovit ukazatel do notového zápisu ret ; a konec generování souzvuku 4 tónů ; *************************************************** ; překódování hudební délky tónu na časovou konstantu ; vstup: ACC = kód délky tónu ; výstup: DE = časová konstanta ; *************************************************** nota2k: lxi d,notlen-2 ; začátek tabulky délek (přeskoč nulu) add a ; 2x <=> int16 mov l,a mvi h,0 ; HL = posun v tabulce dad d mov e,m ; do DE přečíst konstantu int16 inx h mov d,m ret notlen: .dw tick32*48 ; #1 prodloužená celá .dw tick32*32 ; #2 celá .dw tick32*24 ; #3 prodloužená půlová .dw tick32*16 ; #4 půlová .dw tick32*12 ; #5 prodloužená čtvrťová .dw tick32*8 ; #6 čtvrťová .dw tick32*6 ; #7 prodloužená osminová .dw tick32*4 ; #8 osminová .dw tick32*3 ; #9 prodloužená 1/16-ová .dw tick32*2 ; #10 1/16-ová .dw tick32*3/2 ; #11 prodloužená 1/32-ová .dw tick32 ; #12 1/32-ová ; ********************************************** ; překódování čísla tónu na generující konstantu ; číslo tónu 0 implicitně kóduje jako pauzu ; vstup: BC = ukazatel na číslo tónu ; výstup: HL = generující konstanta ; BC = inkrementovaný ukazatel ; ********************************************** precod: ldax b ; načíst notu inx b ; posun ukazatele ana a jz preco0 ; pauzu nebudu transponovat sui 12 ; transpoziční konstanta preco0: lxi h,ladeni ; začátek tabulky výšek add a add l ; nalistovat číslo tónu mov l,a mov a,h aci 0 mov h,a mov a,m ; přečíst konstantu int16 inx h mov h,m mov l,a ret ; ****************************************************** ; Tabulka dělicích poměrů tónu ; Další (i nižší) tóny lze libovolně přidávat do seznamu ; za poslední uvedenou notu až do pořadového čísla ; 0FFh včetně. ; ****************************************************** ; Pro PMD-85 platí následující, experimentálně ověřený ; koeficient převodu frekvence tónu na hodnotu děličky: ; divider = 9.2827 x f (kalibrace 22. 3. 2019) ; ****************************************************** ladeni: ; PAUZA ; 00h .dw 0000h ; N'' (velká dvoučárkovaná, subkontra) ; 01h..03h .dw 00FFh,010Eh,011Eh ; N' (velká jednočárkovaná, kontra) ; 04h..0Fh .dw 012Fh,0141h,0154h,0169h,017Eh,0195h .dw 01ADh,01C6h,01E1h,01FEh,021Ch,023Ch ; N (velká) ; 10h..1Bh .dw 025Eh,0282h,02A8h,02D2h,02FCh,032Ah .dw 035Ah,038Ch,03C2h,03FCh,0438h,0478h ; n (malá) ; 1Ch..27h .dw 04BCh,0504h,0550h,05A4h,05F8h,0654h .dw 06B4h,0718h,0784h,07F8h,0870h,08F0h ; řazení not v oktávě ; C CIS D DIS E F ; FIS G GIS A AIS H ; n' (malá jednočárkovaná, komorní a) ; 28h..33h .dw 0978h,0A08h,0AA0h,0B48h,0BF0h,0CA8h .dw 0D68h,0E30h,0F08h,0FF0h,10E0h,11E0h ; n'' (malá dvoučárkovaná) ; 34h..3Fh .dw 12F0h,1410h,1540h,1690h,17E0h,1950h .dw 1AD0h,1C60h,1E10h,1FE0h,21C0h,23C0h ; n''' (malá trojčárkovaná) ; 40h..4Bh .dw 25E0h,2820h,2A80h,2D20h,2FC0h,32A0h .dw 35A0h,38C0h,3C20h,3FC0h,4380h,4780h ; n'''' (malá čtyřčárkovaná) ; 4Ch..55h .dw 4BC0h,5040h,5500h,5A40h,5F80h,6540h .dw 6B40h,7180h,7840h,7F80h ; ****************************************** ; zápis skladby ve formátu: ; následují pětice bajtů s významem: ; - délka noty, výška tónu 1 až výška tónu 4 ; - je-li délka noty = 0, ukončí se skladba ; ****************************************** ; J. M. Jarré - Band In The Rain ; unplugged version hudba: ; takt 1 .db nota08, ntc2, ntc2, 0, ntg0 .db nota08, ntdis2,ntc2, 0, ntg0 .db nota08, ntg2, ntc2, ntdis2,0 .db nota08, ntg2, ntc2, 0, 0 .db nota08, ntc2, ntais1,0, ntc0 .db nota08, ntdis2,ntais1,0, ntc0 .db nota08, ntg2, ntais1,ntc2, ntdis2 .db nota08, ntg2, ntais1,0, 0 ; takt 2 .db nota08, ntgis2,ntf1, 0, ntf0 .db nota08, ntf2, ntf1, 0, ntf0 .db nota08, ntf2, ntc2, ntgis2,ntf0 .db nota08, ntc2, ntf1, 0, ntf0 .db nota08, ntc2, ntf1, 0, ntc0 .db nota16P,ntc2, ntf1, 0, ntc0 .db nota32, ntc2, nte1, 0, ntc0 .db nota08, ntc2, nte1, ntf2, ntgis2 .db nota32, ntc2, nte1, 0, 0 .db nota16P,ntc2, ntf1, 0, 0 ; takt 3 .db nota08, ntc2, ntc2, 0, ntg0 .db nota08, ntdis2,ntc2, 0, ntg0 .db nota08, ntg2, ntc2, ntdis2,0 .db nota08, ntg2, ntc2, 0, 0 .db nota08, ntc2, ntais1,0, ntc0 .db nota08, ntdis2,ntais1,0, ntc0 .db nota08, ntg2, ntais1,ntc2, ntdis2 .db nota08, ntg2, ntais1,0, 0 ; takt 4 .db nota08, ntgis2,ntf1, 0, ntf0 .db nota08, ntf2, ntf1, 0, ntf0 .db nota08, ntf2, ntc2, ntgis2,ntf0 .db nota08, ntc2, ntf1, 0, ntf0 .db nota08, ntc2, ntf1, 0, ntc0 .db nota16P,ntc2, ntf1, 0, ntc0 .db nota32, ntc2, nte1, 0, ntc0 .db nota08, ntc2, nte1, ntf2, ntgis2 .db nota32, ntc2, nte1, 0, 0 .db nota16P,ntc2, ntf1, 0, 0 ; takt 5 .db nota08, nth1, ntg1, 0, ntg0 .db nota08, ntd2, ntg1, 0, ntg0 .db nota08, ntf2, ntg1, nth1, ntd2 .db nota08, ntf2, ntg1, 0, 0 .db nota08, nth1, ntf1, 0, ntd0 .db nota08, ntd2, ntf1, 0, ntd0 .db nota08, ntf2, ntf1, nth1, ntd1 .db nota08, ntf2, ntf1, 0, 0 ; takt 6 .db nota08, ntg2, ntg1, 0, ntc0 .db nota08, ntdis2,ntg1, 0, ntc0 .db nota08, ntdis2,ntg1, ntc2, ntg0 .db nota08, ntc2, ntg1, 0, ntg0 .db nota08, ntc2, ntg1, 0, ntc0 .db nota16P,ntc2, ntg1, 0, ntc0 .db nota32, ntc2, ntfis1,0, ntc0 .db nota08, ntc2, ntfis1,ntdis2,ntg2 .db nota32, ntc2, ntfis1,0, 0 .db nota16P,ntc2, ntg1, 0, 0 ; takt 7 .db nota08, nth1, ntg1, 0, ntg0 .db nota08, ntd2, ntg1, 0, ntg0 .db nota08, ntf2, ntg1, nth1, ntd2 .db nota08, ntf2, ntg1, 0, 0 .db nota08, nth1, ntf1, 0, ntd0 .db nota08, ntd2, ntf1, 0, ntd0 .db nota08, ntf2, ntf1, nth1, ntd1 .db nota08, ntf2, ntf1, 0, 0 ; takt 8 .db nota08, ntg2, ntg1, 0, ntc0 .db nota08, ntdis2,ntg1, 0, ntc0 .db nota08, ntdis2,ntg1, ntc2, ntg0 .db nota08, ntc2, ntg1, 0, ntg0 .db nota08, ntc2, ntg1, 0, ntc0 .db nota16P,ntc2, ntg1, 0, ntc0 .db nota32, ntc2, ntfis1,0, ntc0 .db nota08, ntc2, ntfis1,ntdis2,ntg2 .db nota32, ntc2, ntfis1,0, 0 .db nota16P,ntc2, ntg1, 0, 0 ; takt 9 .db nota04, ntc2, ntc2, 0, ntg0 .db nota08, ntc2, ntc2, ntdis2,ntg2 .db nota08, ntc2, ntc2, 0, ntg0 .db nota08, ntd2, ntc2, 0, ntc0 .db nota08, ntdis2,ntc2, 0, ntc0 .db nota08, ntdis2,ntc2, 0, ntg2 .db nota08, ntdis2,ntc2, 0, ntc0 ; takt 10 .db nota04, ntf2, ntc2, 0, ntg0 .db nota08, ntf2, nth1, ntc2, ntdis2 .db nota08, ntf2, ntc2, 0, 0 .db nota08, ntg2, ntc2, 0, ntc0 .db nota08, ntgis2,ntc2, 0, ntc0 .db nota08, ntgis2,ntc2, ntdis2,ntg0 .db nota08, ntgis2,ntc2, 0, ntg0 ; takt 11 .db nota04, ntf2, ntc2, 0, ntf0 .db nota08, ntg2, ntc2, ntf2, ntgis2 .db nota08, ntf2, ntc2, 0, 0 .db nota08, ntf2, ntc2, 0, ntc0 .db nota08, ntf2, ntd2, 0, ntc0 .db nota08, ntf2, ntc2, ntgis2,0 .db nota08, ntf2, ntd2, 0, 0 .db notaend .end