Zvuk na Falconu

Jak programovat zvuka na Falconu ? Velmi sadno !

Najdete zde deklarace vsech existujicich sluzeb. Nazvy vsech funkci a nekterych kon stant jsou vzaty z oficialni dokumentace firmy Atari, jine konstanty, u kterych nebyly dosud pevne konvence vytvoreny,jsou oznaceny pokud mozno nejbeznejsim jmenem. Budete – li chtit zvuky pouzivat, opiste si deklarace (jsou tistene odlisnym pismem) do souboru SND- BIND.H. Sluzby jsou implementova- ny jako makra vyvolavajici funkci xbios (ta je u vetsiny prekladacu vhodne definovana v souborech tos.h, osbind.h nebo tosbind.h) – nekontroluji tudiz spravnost typu parametru. Aby bylo zcela zrejme, jake parametry sluzby ocekavaji a jake hodnoty vraci, jsou jako komentare uvedeny odpovidajici pro- topy funkci. I funkce, ktere nevraceji zadnou hodnotu, vraceji chybovy kod (jako long) – jak je v TOSu obvykle, cislo vetsi nebo rovno nule znamena bezchybny prubeh, zaporne cislo znamena chybu. Krome tech, u kterych je vyslovne uvedena moznost chyby, vraceji vzdy hodnotu nula, nebot u nich k zadne chybe proste dojit nemuze. Proto jsem si dovolil je v prototypech oznacit jako void – u takovych funkci muzete predpokladat bezchybny prubeh a nemusite testovat hodnotu, kterou vam vraci.

// long locksnd( void );
//long unlocksnd( void );
#define locksnd0
#defino unlacksnd()
xbioslOxBOl xbios(OxB1)
#de’ine SNDNOTLOCK – 128
#define SNDLOCKED – 129

Na pocitaci

muze bezet (obvykle bezi) vice programu najednou. I kdyz odhledneme od MultiTOSu, bezi soubezne hlavni aplikace, accessory a rezidentni programy. Pokud by se pokousely vsechny najednou pristupovat ke zvukovym obvodum, vedlo by to k dost podivnym vysledkum (muzete si to sami vyzkouset, pouzijete – li napriklad rezidentni SAM od Atari treba s Paulou). Aby se takovymto konfliktum predeslo, musi kazdy program predtim, nez bude neco delat se zvukem, pozadat system o prideleni zvukovych obvodu sluzbou locksnd a po skonceni prace zase zvuky sluzbou unlocksnd uvolnit. Po jejich uvolneni nemuzete spolehat na to, ze ve zvukovych registrech zustaly hodnoty, ktere jste tam dali, nebot’ je mohl jiny program mezitim zcela prestavit. Jsou-li zvukove obvody obsazeny jinym programem, vrati sluzba locksnd hodnotu SNDLOCKED, jinak vraci nulu.

// void devconnect(int src, int dest, int clk, int scale, int hshake);
#define
devconnect (a.b,c,d,e)
xbios (Ox8B,a,b,c,d,e)

Srdcem

celeho zvukaveho systemu je digitalni propojovaci matice. S jeji pomoci je mozno kazde zdrojove zarizeni pripojit na nektera z cilovych zarizeni. Tak je mozno dumyslne propojit nekolik zarizeni – obvykle spojeni je treba DMAPLAY-, DSPRECV a DSPXMIT – DAC.

Jedine omezeni, na ktere jsem dosud prisel, je v tom, ze vsechna spojeni, ktera pouzivaji stejny zdroj taktovacich hodin, museji pouzivat stejnou frekvenci. (Delice kmitoctu jsou umisteny u hodin, ne na matici.!

Zdrojova zarizeni (par. src) jsou.

#define ADC 3 // A/D
#define EXTINP 2 // DSP kon.
#define DSPXMIT 1 // DSP cip
#define DMAPLAY 0 // DMA

Cilova zarizeni (par. dest) jsou;

#define DAC 8 // D/A
#define EXTOUT 4 // DSP kon.
#define DSPRECV 2 // DSP cip
#define DMAREC 1 // DMA

Cilova zarizeni Ize kombinovat (napr. DAC: DMAREC).

Kazdy prenos musi byt taktovan hodinami (parametr clkl:

#define CLK_ 25M 0 //hodiny 25.175 MHz
#define CLK_ EXT 1 // externi hodiny (DSP konektor)
#define CLK_ 32M 2 // hoduny DSP (32 MHz)

Pro taktovani zvuku jdou pouzit jen hodiny 25.175 MHz nebo externi hodiny.

Parametr hshake urcuje druh prenosu:

#define NO SHAKE 1 // synchronni rezim
#define HANDSHAKE 0 // prenos s potvrzovanim

Pro prenos,

zvuku se vždy pouziva synchroni rezim, nebot’ je treba udrzet stalou vzorkovaci frekvenci. V dusledku toho muze dojit ke ztrate dat, nestihne– li je zdroj posilat nebo cilove zarizeni dost rychle odebirat. Tato situace pri slusnem pouziti nenastava, nicmene pri pretizene sbernici se projevi (napr. True Color rezim, a k tomu jeste osmikanalovy zvuk na 50 kHz).

V synchronnim rezimu je jeste nutne urcit prenosovou frekvenci (parametr scale):

#define CLK50K 1 // viz dale
#define CLK33K 2
#define CLK25K 3
#define CLK20K 4
#define CLK16K 5
#define CLK12K 7
#define CLK10K 9
#define CLK8K 11

Je – li hodnota parametru scale rovna 0, pouzivaji se STE/TT kompatibilni frekvence.
Mají- li na Falconu fungovat programy psane pro STE, musi po sobe kazdy program nastavit jednostopy rezim STEREO8 (viz dale ) a zavest spojeni z DMAPLAY do DAC se scale 0, aby programy zmenami v registru, ktery na STE iidi frekvenci dosahly pozadovane odezvy.

Ostatnim hodnotam parametu scale odpovidaji tyto frekvence:

#efine ACT_ CLK50K 49170 L
#define ACT CLK33K 32780 L
#define ACT CLK25K 24585 L
#define ACT CLK20K 19668 L
#define ACT CLK16K 16390 L
#define ACT CLK12K 12292 L
#define ACT CLK10K 9834 L
#define ACT CLKSK 8195 L

Ve vetsine programu se setkate s jinymi hodnotami, nez jsou zde uvedeny je to zpusobeno chybnymi frekvencemi uvedenymi v oficialni dokumentaci firmy Atari. Skutecnou frekvenci spojeni Ize tez vypocitat jako:

freq = frekvence hodin / 256 / (scale+1)
// long soundcmd(int mode, int data);
#define soundcmd(a,b) xbios(Ox82,a,b)

Sluzba soundcmd slouzi k nastavovani ruznych parametru zvuku (hlasitosti apod.). Hodnotu libovolneho z registru nastavovanych touto sluzbou Ize zjistit tak, ze zadate jako parametr data hodnotu INQUIRE:
#define INQUIRE ( – 1)
a funkce soundcmd vam hodnotu prislusneho registru vrati. Pro jednotlive hodnoty mode nastavuje parametr data tyto veliciny:


#define LTATTEN 0 //zesileni leveho vystupu
#define RTATTEN 1 //zesileni praveho vystupu
#define LTGAIN 2 //zisk leveho vstupu
#define RTGAIN 3 //zisk praveho vstupu

Zesileni a zisk,jsou

formatu xxxxxxxxVVVVxxxx. Cislo V v rozsahu (0 az 15) udava zesileni po 1.5 dB. Doporucuji vam se o hodnotu techto parametru nestarat – Ize je totiz nastavovat v ovladacim panelu. Vam tak odpadne kus prace a i pro uzivateie je nejpohodlnejsi moci je menit tam a nemuset hledat ve vasem programu, kam jste ty hlasitosti schovali.

#define ADDRIN 4 //vstup scitacky před D/A prevodnikem

Bit     7    6    5
         0    0    0
        
2    1     0
        0    M    A

Bity M a A povoluji

vstup z matice respektive A/D prevodniku. Tento povel nabizi propojeni A/D a D/A prevodniku mimo propojovaci matici. S jeho pomoci je napriklad mozne michat zvuk z mikrofonu se zvukem prehravanym v

DMA. Casto jej vyuyivaji programy pro on – line efekty (WinRec a dalsi) k michani originalniho a zefektovaneho zvuku.

#define ADCINPUT 5
Bit      7    6    5     43
          0    0     0    00
          2    1     0
          0    L     P

Je – li bit L/P nulovy,

bere se odpovidajici vstup z mikrofonu, jinak se bere z AY – 3 – 8910. Tohoto nenapadneho povelu si dobre v simnete. Slouzi totiz k zapojovani mikrofonu anebo stereho zvukoveho obvodu z ST (zvuk z nej totiz na Falconu prochazi A/D a D/A prevodniky). Kvuli kompatibilite je obvykle pripojen vstup z ST – zvuku – chcete – li tedy pouzit mikrofon, musite vynulovat odpovidajici bity.

#define SETPRESCALE 6
Je-li hodnota parametru scale ve sluzbe devconnect rovna nule, pouziva se delitel nastaveny povelem SETPRESCALE. Tato sluzba ovlada tentyz registr, ktery se na STE pouziva k rizeni frekvence.
Hodnota       Delitel
1                     640
2                     320
3                     160

Tim bychom meli za sebou zakladni inicializacni sluzby a muzeme se pustit do vlastni prace se zvukem.
Nasledujici skupina funkci ovlada DMA nahravani a prehravani.
// void setmode( int mode );
#define sstmode(a) xbios(Qx84,a)
Nastavuje rezim DMA.

V parametru mode ocekava jednu z techto hodnot:
#define STEREO8 0 // 8 bitu stereo
#define STEREO16 1 // 16 bitu stereo
#detine MONO8 2 // 8 bitu mono
// void settracks( int playtracks, int rectracks );
#define settracks(a, b)
xbios(Ox85,a,b)

Nastavi pocet stereofonnich stop pro DMA nahravani a prehravani na hodnoty o jednu vetsi nez jsou hodnoty patametru. Ty mohou byt v rozsahu 0 az 3 – tak dostavate moznost pouzit jednu az ctyri mo nofonni nebo stereofonni stopy. Vicestope DMA vsak vyuzijete jen pro komunikaci s DSP nebo s externim zarizenim – D/A prevodnik totiz umi prevadet jen jednu stopu.

// void setmontrack( int trackno );
#define setmontrack(a)
xbios(Ox86,a)

Pokud prece jen pouzivate vicekanalove DMA, muzete se pomoci teto sluzby rozhodnout, kterou ze stop pustite do D/A prevodniku.
// void setbuffer( int playrec, void *be- gaddr, void endaddr );

#define setbuffer(a,b,c)
xbios(Qx83,a,b,c)

Touto funkci nastavite zacatek bufferu pro DMA na adresu begaddr, konec na endaddr(endaddr je adresa prvniho slova za koncem bufferu, tedy adresa bufferu + delka bufferu).

Parametrem playrec rozhodujete o tom, ktery buffer nastavujete:

#define PLAY 0 //nastavit prehravaci buffer
#define RECORD 1 // nastavit nahravaci buffer

Vsechny vzorky jsou vzdy ukahdany se znamenkem, podle rezimu bud jako 16 – ti bitovy int, nebo 8 – bitovy char.

Usporadani zvukovych dat v bufferech vypada v typickych pripadech takto:

1 stopa, 16 bitu, stereo

LO  PO  L1  P1  L2  P2
int  int  int  int  int  int
L3    P3
int     int

1 stopa, 8 bitu, stereo

LO   PO   L1   P1   L2   P2
char   char    char   char   char    char
char
L3   P3
char   char

2 stopy, 16 bitu, stereo

SO,LO   SO,PO   S1,LO
int   int   int
S1,PO   SO,L1   SO,P1
int   int
S1,L1   S1,P1
int   int

// long buffoper( int mode );

#define buffoper(a)
xbios(Ox88,a)

Sluzba buffoper spousti a zastavuje nahravani a prehravani. Jednotlive bity parametru mode urcuji, ktere DMA prenosy pobezi a zda pobezi opakovane.

#define PLAY_ ENABLE 1 // prehravej
#define PLAY REPEAT 2 // opakuj prehravani
#define RECORD ENABLE 4 //nahravej
#define RECQRD REPEAT 8 // opakuj nahravani

Z hardwarovych duvodu je vzdy pred spustenim nahravani vhodne nahravani explicitne zakazat – jinak se nahravani nemusi vubec spustit. Zadate – li jako mode INQUIRE, vrati buffoper aktualnf stav DMA operaci.

// void buffpt(void ’pointer);
#define buffptr(a)
xbios(OxBD,a)

Ukazatel pointer musi ukazovat na strukturu;
      struct  {
void ’play,*rec;
             void *reservedO, *reserved1;
};

Do slozek play a rec teto struktury vam funkce zapise, kde prave probiha prenos dat. Muzete ji pouzit ke zjisteni toho, jestli uz skoncilo prehrhvani zvuku (v takovem pripade ukazuje na zacatek bufferu), Tato sluzba vsak neni zcela korektni cte totiz postupne tri hardwarove registry, ze kterych se sklada kazdy z vnitrnich ukazatelu DMA cteni a zapisu. Pokud dojde k prenosu mezi ctenim jednotlivych casti, vrati tato sluzba nespravny vysledek. Nejhorsi pripad nastane tehdy, pokud doslo pri zvetsovani registru k prenosu do vyssi casti pak sluzba muze precist starou (tj. vysokou) hodnotu nizsi casti adresy a novou (tj. vysokou) hodnotu vyssi casti. Muze tak dokonce dojit k tomu, ze vam vrati hodnotu, ktera lezi zcela mimo rozsah vaseho bufferu. Zminenym potizim je casto mozno predejit tak, ze tuto sluzbu vyvolate dvakrat po sobe a z obou hodnot se pokusite odvodit hodnotu spravnou.

Zcela ciste reseni

problemu s funkci buffptr umoznuje sluzba setinterrupt. Jeji pouziti je ale dost komplikovane, a proto se jim pro tentokrat zabyvat nebudeme. Pro ty z vas, kdo by s ni prece jen chteli experimentovat, uvadim jeji strucny popis:

void setinterrupt(int srcinter, int cause);
#tdefine setinterrupt(a,b)
xbios(Ox87,a,b)
srcin. preruseni cause kdy vyslat
0 timer A 0 nikdy
1 MFP i7 1 konec prehravani
2 konec nahravani

    1. konec prehravani nebo nahravani

Zbyvajici funkce

Se zabyvaji vaji propojenim zvukoveho systemu a DSP. V tomto clanku se jimi zabyvat nebudeme, pro uplnost uvadim alespoh jejich deklarace.

// void dsptristate( int xmintenable, int rcvenable );
#define dsptristate(a,b)
xbios(0x89,a,b)
#define ENABLE 1
#define TRISTATE 0
// povoluje pripojeni DSP na matici
// long gpio( int readwrite, int data );
#define gpio(a,b)
xbios(Ox8A,a.b)

// ovlada vstupne-vystupni bity na DSP konektoru
// long sndstatus( int reset );
#define sndstatus(a)
xbios(0x8C,a)


// indikuje chyby a preteceni na A/D prevodniku
// umozhuje zcela vyradit zvukovy system

Nez se pustite

do experimentovani se zvukem, rozmyslete si, jaka zvukova zarizeni budete pripojovat. Je samozrejme mozne pouzlt do vstupu signal z magnetofonu a poslouchat ho potom pres interni reproduktor – jestli ale chcete pracovat se zvukem takhle, tak jste si vubec nemuseli kupovat Falcona s jeho 16 – bitovym zvukem na 50 kHz, Rozhodne se vyplati poridit si mikrofon (pro prvni pokusy staci i dost laciny) a zesilovac (cim lepsi, tim lepe).

Tauto funkci muzete pozadat DMA, aby vyslalo na konci bufferu preruseni. Parametrern cause urcujete, kdy chcete preruseni aktivovat, parametrem srcinter rozhodnete, jake preruseni to ma byt.

Podle intenzity vstupniho signalu budete muset v Control Panelu casto menit nastaveni vstupni citlivosti. Pro bezne mikrofony je vetsinou vhodne mit zisk vstupniho zesilovace nastaven na maximum. Pro zpra- covai line signalu (z CD prehravacu a podobnych zarizeni) musite dokonce predradit na levy i pravy ka- nal 200 kilohmovy odpor, jinak budete mit vstupni prevodnik prebuzeny (nebo zniceny).