Kvarteto na jednom bitu

motto: „Víš, že jsme založili kvarteto? Kdo? No přece my tři. Kdo my tři? No já a brácha. Ty máš bráchu? Ne, a proč?“

Tak takhle ne. Budeme opravdu přehrávat čtyři hlasy na jednom jednobitovém výstupu. U mikropočítače PMD-85 se jedná konkrétně o bit PC2 „služebního“ PPI typu MHB8255A.

Dlouho jsem se trápil s variantou se čtyřnásobným převzorkováním a vyčleněním časových slotů pro čtyři původní zvukové kanály. Bylo to super, umělo to pracovat s energií jednotlivých zvukových kanálů (bylo možno simulovat čtyři hladiny hluku, linoucí se z PMD-85) a .. to bylo vlastně vše. Procedura byla extrémně dlouhá, silně závislá na synchronizaci se vzorkováním zvukové karty při běhu v emulátoru, a hlavně – hlavně produkovala parazitní frekvence.

Na Foreveru 2019 mi Busy (https://busy.speccy.cz) poradil, abych použil řešení s mísením zvukových kanálů prostou funkcí OR a doporučil mi rutinu Jána Deáka s názvem ZX10. Osmibitové dělicí konstanty jsem nahradil 16-bitovou přímou digitální syntézou (DDS) a výsledek je dalším evolučním krokem v generování vícehlasé hudby na PMD-85. Rutinu lze beze změny funkčnosti expandovat teoreticky až na 127-hlasovou polyfonii, ovšem frekvenční rastr bude už asi dosti hrubý. Při zvětšení počtu přehrávaných hlasů bude vždy nutno přepočítat generující konstanty tónů a vhodně posunout pozici bitu, budicího reproduktor (to je ta zablokovaná instrukce RAR). Rutina nemá na rozdíl od ZX10 sofistikovaný předkousávač datového toku not, prostě bere, co jí dáte, a to přehraje.

Samotné jádro přehrávače vypadá takto:

; *****************************************
; 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     ; výstup na reproduktor

        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

Jednodušší to už asi být nemůže. Samotné generování každého jednoho zvukového kanálu (DDS ) se odehrává v šestnáctibitových registrech BC a HL a neovlivňuje obsah 8-bitového registru A. Do registru A se přenáší pouze informace o požadavku na vygenerování pulsu každým ze čtyř generátorů. Že chce daný generátor vyrobit puls, dá vědět pomocí nastavení příznaku CY, který pomocí instrukce „SBI 0“ postoupí tuto informaci právě do registru A. Na konci smyčky se podle obsahu registru A pošle na reproduktor buď logická 0 (žádný kanál negeneruje puls, registr A zůstal nulový) nebo logická 1 (minimálně jeden z kanálů generuje puls, registr A má hodnotu 111111xxb – tedy jednu z hodnot 0FFh/0FEh/0FDh/0FCh).

zdrojový kód demonstračního příkladu s využitím přehrávače VOICE416

zvukový záznam uvedeného demonstračního příkladu

2 komentáře u „Kvarteto na jednom bitu

  1. Libor L.A.

    Ještě připojím praktickou informaci pro případné zájemce.

    Pomocí čítače, připojeného na konektor klávesnice, jsem ověřoval skutečnou generovanou frekvenci zvuku přes všechny oktávy a podle toho nastavil hodnoty generujících konstant. Nakonec se však ukázalo, že je vhodné proměřit a nastavit generující konstanty pouze pro 12 nejnižších použitých tónů (nemusí ležet všechny v rámci jedné oktávy), a generující konstanty všech vyšších tónů již nastavit jako přesné dvojnásobky konstant tónů vždy o oktávu nižších. To je důležité kvůli libozvučnosti oktávových intervalů. To není teoretická rada ale prakticky ověřená zkušenost.

    Jakkoliv je rutina technicky schopná přehrávat tóny v rozsahu zhruba 7 oktáv, je tzv. jitter zejména u posledních dvou, tří oktáv značný (tím myslím morbidní). Proto je dobré měřit nějakým čítačem, který měřenou frekvenci průměruje, jinak vám může údaj hodně lítat. Ale kupodivu (moje nezkušené) ucho si to zprůměruje rovněž a subjektivně vnímaná stupnice i v těchto vyšších polohách zní jako plynule rostoucí. Mění se samozřejmě i „barva“ zvuku. Na tom se však podepisuje jak proměnný činitel plnění výsledného obdélníkového signálu, tak i vlastní amplitudová charakteristika použitého akustického měniče (reproduktoru). Pravda ovšem je, že jako hudebník jsem naprostý laik.

Napsat komentář

Vaše emailová adresa nebude zveřejněna.