SlideShare a Scribd company logo
1 of 133
Download to read offline
IL LINUX OPEN SOUND SYSTEM

         ANTONIO TRINGALI


            maggio 1999
ii
Indice

1 LA     SCHEDA AUDIO E OSS                                                                                       4
  1.1     Modello della scheda audio . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .    4
  1.2     Lā€™interfaccia di programmazione di OSS         .   .   .   .   .   .   .   .   .   .   .   .   .   .    6
  1.3     Inizializzazione di OSS . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
          1.3.1 Gestione degli errori . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   10
          1.3.2 Lā€™exit handler . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
          1.3.3 Il signal handler . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   13
   1.4    Scrittura di codice portabile . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   14
   1.5    Anatomia del driver . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
          1.5.1 Scrittura sul buļ¬€er DMA . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
          1.5.2 Lettura dal buļ¬€er DMA . . . . .          .   .   .   .   .   .   .   .   .   .   .   .   .   .   18
   1.6    Schede audio ISA e PCI . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   19
   1.7    File system e device ļ¬le . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20
   1.8    Le versioni di OSS . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   21

2 IL MIXER E LA GESTIONE DEI CANALI                                                                              23
  2.1 Descrizione di /dev/mixer . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   23
  2.2 I canali del mixer . . . . . . . . . . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   24
      2.2.1 Lettura della conļ¬gurazione . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   26
      2.2.2 Selezione del canale da campionare . .                   .   .   .   .   .   .   .   .   .   .   .   27
  2.3 Livelli di volume dei canali . . . . . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   28
  2.4 Dipendenza dallā€™hardware . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   29
  2.5 Nuove caratteristiche . . . . . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   .   30
  2.6 Esempio di programma . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   31

3 CAMPIONAMENTO E RIPRODUZIONE                                                                                   36
  3.1 I device ļ¬le audio . . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   36
  3.2 Il buļ¬€er audio . . . . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   36
  3.3 Parametri di campionamento . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   37
      3.3.1 Reset dei parametri . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   .   .   38
      3.3.2 Pause nelle operazioni . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   39
  3.4 Il campionamento . . . . . . . . . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   39
  3.5 La riproduzione . . . . . . . . . . . . . . . .            .   .   .   .   .   .   .   .   .   .   .   .   40
  3.6 Il formato audio . . . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   41

                                          iii
3.6.1 Little e big endian . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
          3.6.2 La codiļ¬ca lineare . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
   3.7    Il tempo reale . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
          3.7.1 Le capacit` del driver . . . . .
                              a                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
          3.7.2 Gestione del buļ¬€er DMA . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   46
          3.7.3 I/O non bloccante . . . . . .          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   48
          3.7.4 La sincronizzazione . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   52
          3.7.5 Accesso diretto al buļ¬€er DMA           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   53
   3.8    Il full duplex . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   55
   3.9    Uso di coprocessori . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   56
   3.10   Nuove caratteristiche . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   58
   3.11   Esempio di programma . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   59

4 SINTETIZZATORI E MIDI                                                                                                 64
  4.1 I device ļ¬le del sequencer . . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .    64
       4.1.1 I chip sintetizzatori . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .    65
       4.1.2 I sintetizzatori MIDI . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .    66
  4.2 Il buļ¬€er degli eventi . . . . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .    67
  4.3 Lettura della conļ¬gurazione . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .    69
       4.3.1 Parametri generali . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .    70
       4.3.2 Le porte MIDI . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .   .   .   .    71
  4.4 Predisposizione dei chip sintetizzatori . . . . .                    .   .   .   .   .   .   .   .   .   .   .    72
       4.4.1 Caricamento degli algoritmi FM . . . .                        .   .   .   .   .   .   .   .   .   .   .    73
       4.4.2 Caricamento delle patch wavetable . .                         .   .   .   .   .   .   .   .   .   .   .    76
       4.4.3 Caricamento delle sysex patch . . . . .                       .   .   .   .   .   .   .   .   .   .   .    81
  4.5 La temporizzazione . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .    81
       4.5.1 La sincronizzazione per /dev/music . .                        .   .   .   .   .   .   .   .   .   .   .    83
       4.5.2 La sincronizzazione per /dev/sequencer                        .   .   .   .   .   .   .   .   .   .   .    85
  4.6 Output degli eventi . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .    86
       4.6.1 Messaggi di canale . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .    86
       4.6.2 Messaggi di sistema . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .    89
       4.6.3 Controllo della coda degli eventi . . . .                     .   .   .   .   .   .   .   .   .   .   .    91
  4.7 Formato degli eventi . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .    92
  4.8 Input degli eventi . . . . . . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .    94
       4.8.1 Eventi per /dev/music . . . . . . . . .                       .   .   .   .   .   .   .   .   .   .   .    95
       4.8.2 Eventi per /dev/sequencer . . . . . . .                       .   .   .   .   .   .   .   .   .   .   .    97
  4.9 Nuove caratteristiche . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .    97
       4.9.1 SoftOSS . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   100
       4.9.2 OSSlib . . . . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .   101
  4.10 Esempio di programma . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   102

                                           iv
5 IL MIDI A BASSO LIVELLO                                                                                          106
  5.1 Descrizione dei device ļ¬le MIDI .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   106
  5.2 Lettura dalla porta MIDI . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   107
  5.3 Scrittura sulla porta MIDI . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   109
  5.4 Programmazione della MPUā€“401         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   109
  5.5 Esempio di programma . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   110

A GENERAL MIDI                                                               121
  A.1 Timbri strumentali . . . . . . . . . . . . . . . . . . . . . . . . . . 121
  A.2 Timbri delle percussioni . . . . . . . . . . . . . . . . . . . . . . . 125




                                       1
Sommario

Questo lavoro si propone come tutorial per la programmazione della scheda audio
tramite lā€™Open Sound System (OSS) per il sistema operativo Linux, ponendo
particolare enfasi sulle strategie di programmazione pi` opportune per la sintesi
                                                       u
audio in tempo reale.

Capitolo 1 Si introduce un modello ā€œmedioā€ delle varie schede audio presenti
    sul mercato; dopo sono descritte la visione orientata a UNIX che ne ha OSS
    (in particolare alla ļ¬ne descrivendo il funzionamento interno del driver), la
    sua inizializzazione e la gestione delle uscite da programma e dei segnali in
    un ambiente multiutente e multiprogrammato, con qualche riferimento alla
    scrittura di programmi portabili

Capitolo 2 Il mixer gestisce i canali di ingresso/uscita facenti capo alla scheda
    audio; ` spiegato come scoprire le capacit` di questā€™ultima, selezionare i
            e                                    a
    canali e regolare i livelli di volume per campionamento e riproduzione
            `
Capitolo 3 E spiegato come campionare da un qualsiasi canale del mixer e ripro-
    durre i campioni sintetizzati o immagazzinati su un ļ¬le, eventualmente in
    maniera non bloccante

Capitolo 4 Ci si occupa della programmazione ad alto livello, cio` in maniera
                                                                       e
    indipendente dai dispositivi, del chip sintetizzatore interno alla scheda audio
    e delle porte MIDI

Capitolo 5 Si tratta della programmazione MIDI a basso livello, cio` a livello
                                                                   e
    di I/O di byte dei messaggi
               `
Appendice A E riportata una tabella di corrispondenza fra i preset timbrici
    deļ¬niti nello standard General MIDI level 1 e i nomi delle patch wavetable
    per la Gravis UltraSound
INTRODUZIONE ALLā€™OPEN SOUND SYSTEM

     Allā€™inizio degli anni ā€™90 Hannu Savolainen scrisse la prima versione di un driver
per la scheda audio Sound Blaster 1.5 sotto Minixā€“386; nel 1992 ne fece il porting
sotto Linux: era nato il Linux Sound Driver (LSD).
     Al crescere del numero di versione e delle funzionalit` implementate, nonchĀ“
                                                              a                      e
allā€™aumentare del numero di porting ad altre variet` di UNIX, il driver cambi`
                                                         a                           o
il nome in VoxWare; sfortunatamente era omonimo della VoxWare Incorporat-
ed, quindi per problemi di copyright per un certo periodo rest` il Temporarily
                                                                     o
Anonymous Sound Driver (TASD).
     Poco dopo la 4Front Technologies, con la collaborazione dello stesso Hannu
Savolainen, svilupp` lā€™Unix Sound System (USS), avente qualche caratteristica in
                       o
pi` rispetto al driver freeware e un maggior numero di schede audio supportate;
   u
lo stesso Savolainen continuava indipendentemente a sviluppare il driver freeware
(il cui codice sorgente era diļ¬€erente da quello di USS), noto ora come USS/Lite.
     In ossequio a POSIX e alla gran variet` di sistemi di tipo UNIX al quale `
                                              a                                      e
stato portato, il nome ` cambiato nuovamente e il driver ` commercializzato dalla
                          e                                  e
4Front Technologies come Open Sound System, mentre nella versione freeware
` noto come OSS/Free. Di questo Savolainen non mantiene pi` il codice: la
e                                                                      u
responsabilit` ` passata a Alan Cox dagli inizi del 1998.
                ae
     Dā€™ora in poi ci si riferir` a questi driver globalmente come OSS, sottinten-
                                a
dendo che ci` che sar` detto vale per entrambi (evidenziando, ove necessario,
                o         a
le diļ¬€erenze); la versione assunta come ā€œriferimentoā€ ` la 3.5.4. A seguire dal
                                                            e
Capitolo 2, la penultima Sezione di ogni Capitolo elenca le diļ¬€erenze di program-
mazione introdotte dalla versione 3.6 in poi e lā€™ultima Sezione ospita un breve
programma di esempio in C che illustra le caratteristiche di OSS introdotte nel
Capitolo stesso. Delle chiamate alla libreria di OSS elencate in soundcard.h, si
` scelto di riportare solo quelle pienamente supportate.
e
     OSS ` in pratica il primo tentativo di uniļ¬care lā€™architettura di audio digitale
           e
per UNIX: alle capacit` di campionamento e riproduzione (piuttosto articolate
                           a
rispetto a quanto prima disponibile per questo ambiente) sono aļ¬ƒancate le possi-
bilit` del MIDI, con il supporto dellā€™audio sincronizzato alla riproduzione video.
      a
`
E allo stato attuale un insieme modulare di device driver che garantiscono unā€™in-
terfaccia di programmazione uniforme e compatibile a livello di codice sorgente
per tutte le piattaforme su cui ` stato portato, tanto che per queste ` valido la
                                   e                                       e
quasi totalit` di ci` che ` scritto nel seguito di questo lavoro.
               a      o      e
     Una panoramica generica delle caratteristiche supportate sia dallā€™OSS com-
merciale (OSS/Linux) che da OSS/Free ` la seguente:
                                            e

   ā€¢ supporto di vari formati audio per i campioni (8 e 16 bit signed e unsigned,
     8 bit Āµā€“Law e A-Law, IMAā€“ADPCM)

   ā€¢ supporto di canali stereo e mono

   ā€¢ frequenze di campionamento comprese tra 4kHz e 48kHz

                                          2
ā€¢ supporto half e full duplex (con apposite schede audio)
   ā€¢ possibilit` di accesso diretto al buļ¬€er audio DMA (per applicazioni con
               a
     richieste temporali pi` stringenti, come i giochi)
                           u
   ā€¢ possibilit` di accesso indipendente dallā€™hardware a MIDI e a sintetizzatori
               a
     FM o wavetable sulla scheda audio
   ā€¢ caricamento delle patch in maniera indipendente dallā€™hardware
   ā€¢ supporto per SMPTE/MTC
   ā€¢ supporto per UART di tipo MPā€“401, Sound Blaster MIDI e XG MIDI
   ā€¢ supporto di IBM/Motorola PowerPC (bus ISA e PCI), 386/486/Pentium
     (bus ISA, EISA e PCI), Sun SPARC e DEC Alpha/AXP (bus ISA e PCI)

   Rispetto a OSS/Free, OSS/Linux ha in pi` le seguenti caratteristiche:
                                          u
   ā€¢ supporto diretto dello standard PnP (senza dover inizializzare precedente-
     mente le schede con il comando isapnp)
   ā€¢ supporto di un maggior numero di schede audio
   ā€¢ non si deve ricompilare il kernel ad ogni cambio di conļ¬gurazione o driver
     (questo ` un modulo separato)
             e
   ā€¢ supporto delle schede Sound Blaster 16/32/64/AWE in full duplex
   ā€¢ supporto delle patch wavetable Eā€“mu SoundFont 2.0
   ā€¢ librerie DirectAudio per lā€™accesso diretto ai chip sintetizzatori FM e alle
     porte MIDI
si ` scelto di non trattare gli ultimi due punti, in quanto di interesse marginale
   e
per la sintesi in tempo reale.

                    CONVENZIONI TIPOGRAFICHE

Per tutto il testo sono seguite per le parole le seguenti convenzioni:
     corsivo indica una sigla o un termine tecnico rilevante introdotto per la prima
volta
     neretto indica un identiļ¬catore o una variabile (con speciļ¬cato il tipo) per
lā€™interfaccia di programmazione di OSS o di Linux
     spaziatura fissa indica una parola chiave appartenente alla libreria di
OSS o codice sorgente di esempio; se le parole sono contenute tra parentesi an-
golate, come ad esempio per <valore>, si intende che il programmatore debba
sostituirvi un adeguato valore numerico


                                         3
Capitolo 1

LA SCHEDA AUDIO E OSS

1.1       Modello della scheda audio
Una scheda audio ha diverse funzioni: converte i suoni immagazzinati nel sistema
(ad esempio, su ļ¬le) dalla forma digitale allā€™analogica aļ¬ƒnchĀ“ li si possa udire
                                                                e
o registrare, converte da opportuni canali di ingresso (Lineā€“In1 , microfono, CD
audio) i segnali da analogico a digitale aļ¬ƒnchĀ“ possano essere immagazzinati o
                                                e
manipolati dal computer, pu` consentire essa stessa di creare nuovi suoni tramite
                              o
eventuali sintetizzatori interni.
     Secondo le speciļ¬che MPC2 deve anche essere dotata di una porta MIDI perchĀ“  e
il computer possa controllare strumenti musicali o sintetizzatori esterni con tali
capacit`, invece di generare da sĀ“ i suoni. Il PC diventa in pratica un sequencer,
        a                         e
cio` un direttore dā€™orchestra allo stato solido; virtualmente non ` pi` di una
    e                                                                e u
memoria e un sistema di messaggi dalla e alla strumentistica, con capacit` di  a
editing.
     Lā€™OSS cerca di oļ¬€rire una visione idealizzata della scheda audio al program-
matore, nascondendo le diļ¬€erenze tecniche fra le varie schede presenti sul mercato;
essa pu` essere vista come un mixer, di cui il programmatore (il Disc Jockey) ha
        o
possibilit` di controllare ogni canale3 .
           a
     Per la riproduzione (conversione D/A) la sorgente ` da ļ¬le (brano digitaliz-
                                                         e
zato o MIDI) o i campioni sono creati con un opportuno algoritmo di sintesi, da
CD audio4 (il segnale ` semplicemente spedito alla sezione analogica della scheda
                        e
   1`
      E un ingresso con livelli simili a quelli dā€™ingresso per un ampliļ¬catore HIā€“FI, utile per
campionare il segnale proveniente da un registratore analogico o da un CD player esterni
    2
      Speciļ¬che rilasciate da Microsoft e Intel nel 1991 per deļ¬nire una conļ¬gurazione hardware
minima aļ¬ƒnchĀ“ un computer potesse essere deļ¬nito ā€œmultimedialeā€: si doveva cio` disporre
                e                                                                      e
almeno di un PC 386SX/16MHz con 4MB di RAM e 40MB di hard disk, una VGA a colori, un
mouse, una scheda audio e un CDā€“ROM player
    3
      Indipendentemente o meno dagli altri; relativamente alle capacit` della scheda audio stessa,
                                                                       a
con il programmatore che pu` interrogare OSS sulle capacit` di questā€™ultima
                               o                                a
    4
      Non ` presa in considerazione la programmazione del drive CD in questo tutorial, solo come
           e
si fa a campionare o riprodurre il segnale che ` presente sullā€™eventuale canale CD Audio In della
                                                e
scheda audio

                                                4
CAPITOLO 1. LA SCHEDA AUDIO E OSS                         1.1. MODELLO DELLA SCHEDA AUDIO



audio senza che sia stato campionato prima), da Lineā€“In e da microfono. In cam-
pionamento (conversione A/D) si pu` acquisire dagli ingressi CD Audio, Lineā€“In
                                       o
e microfono o si possono acquisire eventi MIDI.
    La coppia di convertitori A/D e D/A viene spesso chiamata PCM, DSP,
CODEC o ADC/DAC ; nella Tabella seguente sono elencate le massime frequenze
di campionamento5 per le varie generazioni di schede audio che OSS supporta (la
minima ` sempre intorno ai 5 kHz); la fc ` generata dividendo lā€™alta frequenza di
         e                                  e
un oscillatore di riferimento, per cui non ` possibile ottenere tutte le frequenze
                                              e
dellā€™intervallo: le diļ¬€erenze di qualche percento dovrebbero essere ignorate perchĀ“
                                                                                  e
solitamente non avvertibili (OSS cerca di ottenere dalla scheda audio la frequenza
pi` vicina a quella richiesta). La risoluzione di campionamento pu` essere di 8 o
  u                                                                  o
16 bit, in mono o stereo.


                    Generazione         Max fc        Note
                        1a            22.05 kHz       in riproduzione
                                      11.025 kHz      in campionamento
                          2a           44.1 kHz       mono
                                      22.05 kHz       stereo
                          3a           44.1 kHz       qualit` audio CD
                                                            a
                                        48 kHz        qualit` DAT
                                                            a
                          4a            96 kHz        Ultra Hiā€“Fi


    Oltre alle succitate possibilit` di sintesi FM6 e di gestione dei dispositivi MI-
                                    a
DI, alcune schede consentono la wavetable synthesis e la possibilit` di caricare
                                                                         a
campioni di uno strumento (patch) in una speciale memoria della scheda stessa.
    In ļ¬gura 1.1 ` evidenziata la visione che possiamo dare della nostra scheda
                   e
audio idealizzata come output mixer per quanto riguarda la riproduzione, che ben
si conf` alle caratteristiche pi` comuni riscontrabili nelle schede audio attualmente
       a                        u
presenti sul mercato (1999). In ļ¬gura 1.2 ` invece schematizzato lā€™input mixer a
                                              e
cui fare riferimento per quanto riguarda il campionamento.
    Infatti dentro una scheda audio possono esserci realmente due mixer che gestis-
cono separatamente i casi di campionamento e riproduzione, ma OSS gestisce
automaticamente il passaggio dallā€™uno allā€™altro in base ai comandi del program-
matore di lettura o scrittura dalla/alla scheda audio. In particolare, se tali attivit`
                                                                                      a
sono implementate dalla scheda audio come mutuamente esclusive ` deļ¬nita half
                                                                        e
duplex, mentre ` deļ¬nita full duplex se possono aver luogo contemporaneamente.
                 e

   5
    Alcune vecchie schede permettono di scegliere solo fra frequenze di campionamento ļ¬sse:
11025 Hz, 22050 Hz, 32000 Hz e 44100 Hz
   6`
    E sfruttata la tecnica degli operatori per produrre pi` voci: i chip ā€œclassiciā€ sono lo Yamaha
                                                          u
OPLā€“2 (a due operatori, nove voci con timbri non realistici) e OPLā€“3 (a quattro operatori,
diciotto voci): aumentando il numero di operatori per voce migliora la qualit` della sintesi
                                                                                  a

                                                5
1.2. Lā€™INTERFACCIA DI PROGRAMMAZIONE DI OSS                                                            CAPITOLO 1. LA SCHEDA AUDIO E OSS




                                                                                                            Memoria del computer
                                                                                                              o Hard-Disk
            LINE-OUT
                                       ALTOPARLANTI



                                                                                                   L    R                      L       R    L       R

        L      R                              L         R   L       R    L       R                             STEREO   MONO


                              STEREO   MONO


                   TREBLE




                       BASS
                                                                                                   RECORD                      CD Audio     LINE-IN      MIC
        MASTER                                    DAT       CD Audio     LINE-IN      MIC                      MIDI ON/OFF
                                                                                                   VOLUME                          ON/OFF       ON/OFF   ON/OFF
                              MIDI ON/OFF
        VOLUME                                    ON/OFF        ON/OFF       ON/OFF   ON/OFF




    Figura 1.1: Modello come mixer della
                                         Figura 1.2: Modello come mixer
    scheda audio in riproduzione
                                         della scheda audio in campiona-
                                         mento

1.2                Lā€™interfaccia di programmazione di OSS
Per gestire il ā€œmixer virtualeā€ delle ļ¬gure 1.1 e 1.2 OSS sfrutta la visione orientata
al ļ¬leā€“system che Linux ha di ogni device 7 . I canali del mixer, campionamento
e riproduzione possono quindi essere gestiti manipolando degli speciali ļ¬le che
si trovano nella directory /dev tramite le primitive di sistema open(), ioctl(),
read(), write() e close().
    In ļ¬gura 1.3 sono evidenziati i device ļ¬le relativi alla manipolazione dei vari
canali per la riproduzione, mentre in ļ¬gura 1.4 cā€™` lo schema equivalente per il
                                                      e
campionamento.
    Questā€™organizzazione ` conveniente, poichĀ“ in tal modo sono schermate sia le
                           e                     e
complessit` dellā€™hardware e del software sottostante (la scheda audio, ma anche
            a
la gestione del DMA, della memoria virtuale e del multitasking), sia le diversit`    a
fra le varie schede audio in commercio.
    Si pu` ora procedere alla descrizione di ogni device ļ¬le:
          o

/dev/mixer Questa ` lā€™interfaccia di accesso alle funzioni del mixer e pu`
                        e                                                    o
    essere un link simbolico a /dev/mixer0; se ` presente un secondo mixer, ci
                                               e
    si riferisce ad esso come /dev/mixer1

/dev/dsp Identiļ¬ca il DSP della scheda (per default con codiļ¬ca lineare 8 bit
    unsigned) e pu` essere un link simbolico a /dev/dsp0; in genere ` presente
                  o                                                 e
   7`
     E unā€™interfaccia a un dispositivo hardware (dischi, linee seriali, etc.) o a ā€œentit`ā€ a cui
                                                                                        a
non corrisponde un vero e proprio dispositivo hardware (memoria di sistema, kernel, etc.); a un
device ļ¬sico ā€” come la scheda audio ā€” corrisponde un device driver ā€” come OSS ā€” che ha
il compito di pilotarlo

                                                                                               6
CAPITOLO 1. LA SCHEDA AUDIO E OSS                                                           1.2. Lā€™INTERFACCIA DI PROGRAMMAZIONE DI OSS



                                                                         = Link simbolico




                                                                                                                         OSS driver
                                  OSS driver
       Memoria del computer
         o Hard-Disk
                                                             /dev/dsp     /dev/dsp0
                                                                          /dev/dsp1                  MIDI in
                                                                                                                                              /dev/dsp
                                                         /dev/dspW        /dev/dspW0
                                                                                                                                              /dev/dspW
        MIDI file (out)                                                   /dev/dspW1
                                                                                                                                              /dev/audio
                                                        /dev/audio        /dev/audio0
                                                                                                   CD Audio                                   /dev/music
                                                                          /dev/audio1
                                                                                                                                              /dev/sequencer
          CD Audio                                                                                                                            /dev/midi00    Memoria del computer
                                                                                                                                              /dev/midi01      o Hard-Disk
                              /dev/sndstat
                                                                                                                   /dev/sndstat               /dev/midi02
                              /dev/sndproc                                                        Line-In
                                                             /dev/music                                            /dev/sndproc               /dev/midi03
         Line-In                                             /dev/sequencer
                                                             /dev/midi00
                                                             /dev/midi01                                             MIXER
                               MIXER                         /dev/midi02
                                                             /dev/midi03                             Mic
            Mic



                   /dev/mixer                  /dev/mixer0                                                  /dev/mixer                /dev/mixer0
                                               /dev/mixer1                                                                            /dev/mixer1




       Figura 1.3: Visione della scheda au- Figura 1.4: Visione della scheda
       dio in riproduzione che OSS d` al audio in campionamento che OSS
                                       a
       programmatore                        d` al programmatore
                                             a


           anche /dev/dsp1, che pu` identiļ¬care un secondo DSP o lo stesso con una
                                  o
           diversa funzione

/dev/dspW Se presente (dipende dalla versione di OSS), si riferisce al DSP con
    codiļ¬ca lineare 16 bit signed e little endian8 ; pu` essere un link simbolico
                                                       o
    a /dev/dspW0 ed eventualmente ` presente anche /dev/dspW1
                                      e

              `
/dev/audio E presente per limitata compatibilit` con le workstation Sun (non
                                                 a
    sono supportati cambiamenti da 8 kHz/mono/8 bit) e utilizza la codiļ¬ca
    Āµā€“Law9 ; ` disponibile in mutua esclusione con /dev/dsp e generalmente `
             e                                                             e
    un link a /dev/audio0, potendo essere presente anche /dev/audio1

/dev/music Permette di accedere al sintetizzatore interno alla scheda audio e
    alle porte MIDI in maniera indipendente dal dispositivo (sono trattati allo
    stesso modo dal punto di vista dellā€™interfaccia di programmazione), con
    modalit` di temporizzazione piuttosto articolate; pu` essere presente il link
            a                                           o
    simbolico ad esso /dev/sequencer2 (obsoleto)

                  `
/dev/sequencer E un device ļ¬le a pi` basso livello di /dev/music, rispetto al
                                      u
    quale ha capacit` limitate di temporizzazione, sincronizzazione e gestione
                    a
    automatica del chip sintetizzatore interno alla scheda audio
   8
     Little endian e big endian si riferiscono a come sono conservati i campioni in memoria dalla
CPU: per il primo lā€™indirizzo del dato corrisponde allā€™indirizzo del byte meno signiļ¬cativo (Intel,
Alpha), per il secondo al byte pi` signiļ¬cativo (Motorola, Sparc, PowerPC, HPā€“PA)
                                   u
   9
     Un campione a 12 o 16 bit ` compresso logaritmicamente a 8 bit: OSS in riproduzione
                                    e
non eļ¬€ettua lā€™operazione opposta, ma converte in un campione a 8 bit lineare prima di inviare
al device audio (sono introdotti un overhead per il calcolo e della distorsione); ` un formato
                                                                                     e
derivante dalla tecnologia telefonica digitale

                                                                                              7
1.2. Lā€™INTERFACCIA DI PROGRAMMAZIONE DI OSS     CAPITOLO 1. LA SCHEDA AUDIO E OSS



                `
/dev/midi00 E unā€™interfaccia a basso livello al canale MIDI, orientata ai carat-
    teri come tty (raw mode) e indirizzata ad applicazioni che non richiedono
    una sincronizzazione in tempo reale come i sequencer (pu` essere usata
                                                                 o
    per inviare sysex, per caricare campioni sugli strumenti o per eļ¬€ettuare il
    dump dei canali); se presenti, possono essere gestite altre porte MIDI con
    /dev/midi01, /dev/midi02 e /dev/midi03

/dev/sndproc Rappresenta lā€™interfaccia interna di accesso a un eventuale co-
    processore presente sulla scheda audio; pu` essere una soluzione tempo-
                                              o
    ranea, da eliminare in seguito

/dev/sndstat Questo, a diļ¬€erenza degli altri, ` un device ļ¬le a sola lettura:
                                                   e
    stampa informazioni diagnostiche riguardo la conļ¬gurazione di OSS in for-
    ma leggibile agli umani, ma se ne sconsiglia lā€™utilizzo da parte dei programmi
    perch` in futuro il formato delle informazioni da esso fornite potrebbe cam-
          e
    biare; non ci si far` pi` riferimento dā€™ora in poi. Lā€™output ha una sezione
                         a u
    per ogni categoria di dispositivi, e questi sono numerati nellā€™ordine in cui il
    driver li inizializza (che non ` ļ¬sso, per cui ` meglio non fare assunzioni a
                                   e               e
    priori); un esempio del suo utilizzo ` il seguente:
                                          e

     ~>cat /dev/sndstat
     Sound Driver:3.5.4-960630
     Kernel: Linux papo 2.0.32 #1 Wed Nov 19 00:46:45 EST 1997 i486
     Config options: 0

     Installed drivers:

     Card config:

     Audio devices:
     0: Sound Blaster 16 (4.13)

     Synth devices:
     0: Yamaha OPL-3

     Midi devices:

     Timers:
     0: System clock

     Mixers:
     0: Sound Blaster

   OSS consente di avere pi` schede audio installate nel computer, il che si
                           u
traduce in un maggior numero di device ļ¬le indirizzabili, elencati nellā€™output

                                        8
CAPITOLO 1. LA SCHEDA AUDIO E OSS                        1.3. INIZIALIZZAZIONE DI OSS




di /dev/sndstat: lā€™esempio sopra rivela che il computer ha solo /dev/dsp0,
ma in generale con pi` DSP li si potrebbe indirizzare operando su /dev/dspn;
                     u
analogamente per il mixer su /dev/mixern, etc.


1.3      Inizializzazione di OSS
Il minimo insieme di header ļ¬le da includere ` rappresentato da stdio.h (per le
                                               e
funzioni di libreria tipo printf() e perror()), unistd.h, fcntl.h (per open(),
ioctl(), read(), write() e close()) e sys/soundcard.h (le deļ¬nizioni vere e
proprie per la libreria di OSS).
    Adesso si riporter` uno scheletro di codice C per lā€™apertura di un device ļ¬le di
                       a
OSS (nellā€™esempio ` /dev/dsp, ma potrebbe essere /dev/mixer, . . . ); nei succes-
                     e
sivi Capitoli lo si dar` come sottinteso man mano che si introducono le primitive
                       a
per una gestione vieppi` soļ¬sticata della scheda audio.
                          u

#include   <stdio.h>
#include   <unistd.h>
#include   <fcntl.h>
#include   <sys/soundcard.h>

int main()
{
   int dspfd;                        /* File descriptor per /dev/dsp */

    dspfd = open("/dev/dsp", O_WRONLY);      /* Apre il device                */
    if (dspfd == -1) {
        perror("/dev/dsp");                 /* Gestione errore                */
        exit(-1);
    }
       /* Qui ci puoā€™ andare tutto il codice per sfruttare il                 */
       /* device file, con le ioctl() necessarie a configurare                */
       /* il driver poste prima delle read() o write()                        */

    close(dspfd);                            /* Chiusura del device file */
    return 0;
}

   Il secondo argomento di open() ` la modalit` di accesso al device ļ¬le, che nel
                                    e         a
caso di OSS pu` essere una fra le seguenti:
               o

O RDONLY Accesso in sola lettura (read() o ioctl())

O WRONLY Accesso in sola scrittura (write() o ioctl())

O RDWR Accesso in lettura/scrittura (read(), write() o ioctl())

                                         9
1.3. INIZIALIZZAZIONE DI OSS                   CAPITOLO 1. LA SCHEDA AUDIO E OSS




    Per read() e write() i ļ¬‚ag O_NDELAY o O_NONBLOCK, aļ¬ƒnchĀ“ le operazioni di
                                                              e
I/O sul device ļ¬le non blocchino il processo chiamante, non hanno eļ¬€etto: se il
processo eļ¬€ettua una read() e i campioni richiesti non sono ancora disponibili,
questo viene messo in wait ļ¬nchĀ“ lā€™operazione ` completata (analogamente con
                                e               e
una write(), se il buļ¬€er del driver non ha spazio suļ¬ƒciente per i campioni che
si vogliono riprodurre).
    Per la open() il funzionamento ` sempre del tipo O_NDELAY; se fallisce il
                                     e
ļ¬le descriptor ` posto uguale a -1 e la macro errno ` impostata a un oppor-
                e                                     e
tuno valore (questa ` messa a disposizione del programmatore per mezzo di
                      e
#include <errno.h>).


1.3.1     Gestione degli errori
I codici di errore pi` comuni riportati da errno sono i seguenti:
                     u

ENOENT Il device ļ¬le che si ` tentato di aprire non ` presente in /dev
                            e                       e

ENODEV Esiste il device ļ¬le in /dev, ma il driver non ` stato caricato dal
                                                       e
   kernel (si pu` controllare con cat /dev/sndstat o dmesg | more)
                o

ENOSPC Esiste il device ļ¬le in /dev, ma il driver non ` stato in grado di
                                                            e
   allocare la memoria per il buļ¬€er DMA tramite sound_mem_init() durante
   il boot del sistema; il modulo del driver dovrebbe essere uno dei primi ad
   esser caricato dal kernel, in modo da garantire tale operazione anche in caso
   di poca memoria installata

ENXIO Esiste il device ļ¬le in /dev e il driver ` presente nel kernel, ma non
                                                   e
   esiste il dispositivo hardware che si tenta di indirizzare (ad esempio, perchĀ“
                                                                                e
   la conļ¬gurazione del driver non corrisponde allā€™hardware audio)

EINVAL Uno degli argomenti della chiamata a una funzione non ha un valore
    valido

EBADF Il ļ¬le descriptor non si riferisce a un device ļ¬le aperto, una read() `
                                                                            e
   stata rivolta a un device ļ¬le aperto con O_WRONLY o una write() ` stata
                                                                       e
   rivolta a un device ļ¬le aperto con O_RDONLY

EBUSY Solo un processo alla volta pu` gestire /dev/dspn e /dev/audion, per
                                        o
   cui si veriļ¬ca se un altro processo (anche appartenente allo stesso utente)
   tenta di accedervi (si veriļ¬ca anche se lā€™IRQ o il canale DMA sono occupati);
   pu` essere gestito dal programma tentando di riaprire il device ļ¬le che ha
      o
   causato lā€™errore dopo qualche tempo, ma non ` garantito che esso divenga
                                                     e
   mai disponibile
        `
EINTR E ritornato da read() o write() qualora queste siano risultate bloccan-
   ti e durante lo stato di wait il processo utente abbia ricevuto un signal()

                                       10
CAPITOLO 1. LA SCHEDA AUDIO E OSS                       1.3. INIZIALIZZAZIONE DI OSS




EAGAIN La risorsa a cui si ` cercato di accedere ` temporaneamente non
                               e                       e
   disponibile (ad esempio, si ` cercato di scrivere su un buļ¬€er pieno o leggere
                               e
   da un buļ¬€er vuoto con il device ļ¬le aperto in O_NONBLOCK)

EACCES Per i device /dev/dspn e /dev/audion lā€™accesso ` consentito solo al
                                                           e
   root (a meno che il sistema sia stato conļ¬gurato in altro modo), e questo
   errore si veriļ¬ca se un utente normale cerca di accedere a tali device ļ¬le;
   questa ` una misura di sicurezza per impedire che, ad esempio, qualora il
           e
   computer sia connesso in rete e abbia un microfono qualcuno possa ascoltare
   remotamente le conversazioni che si svolgono nella stanza ove si trova il
   computer

   Un error handler un poā€™ pi` soļ¬sticato potrebbe rassomigliare a:
                             u

if ((dspfd = open("/dev/dsp2", O_WRONLY)) == -1) {
  switch (errno) {
    case ENOENT: perror("/dev/dsp2");
                 exit(-1);
    case EBUSY: close(dspfd);    /* Aspetta un poā€™ per riaprire */
                 sleep(10);
                 if (dspfd = open("/dev/dsp2", O_WRONLY)) == -1) {
                     perror("/dev/dsp2");
                     exit(-1);
                 }
                 break;
    default: perror("Altro tipo di errore");
              fprintf(stderr, "Errore numero: %dn", errno);
              exit(-1);
  }
}

   Per quanto invece riguarda il seguito di questo lavoro, si demander` la gestione
                                                                      a
degli errori a una semplice routine del tipo:

void errore(const char *msgerr)
{
    perror(msgerr);
    exit(-1);
}

    Sarebbe corretto mettere un error handler non solo dopo una open(), ma an-
che dopo read() o write() per veriļ¬care se siano stati letti o scritti il numero
corretto di byte; tuttavia nella sintesi in tempo reale ci` tende a rappresentare
                                                           o
cicli di CPU sprecati. Invece dopo una ioctl() conviene controllare quasi ob-
bligatoriamente il valore ritornato dal driver nellā€™ultimo dei suoi argomenti, per
vedere cosa si riesce a ottenere rispetto a quanto richiesto dal programmatore.

                                        11
1.3. INIZIALIZZAZIONE DI OSS                         CAPITOLO 1. LA SCHEDA AUDIO E OSS




   Un altro buon accorgimento di programmazione ` di installare un exit handler
                                                   e
e/o un signal handler subito dopo una open() riuscita: il primo pu` essere utile
                                                                   o
                                                      10
per operazioni di routine alla chiusura del programma (regolare o in seguito a
exit()), il secondo pu` gestire i segnali impostati da altri processi, dal kernel
                       o
o dal processo stesso. Per una dettagliata descrizione di questi argomenti si
veda [10].

1.3.2      Lā€™exit handler
Un exit handler richiede la funzione di libreria atexit(), disponibile in segui-
to a #include <stdlib.h>. Essa registra le funzioni di tipo void f() date in
argomento come exit handler (max 32), venendo richiamate nellā€™ordine inverso
rispetto a quello con cui sono state registrate; atexit() restituisce 0 se la regis-
trazione ` stata possibile, altrimenti -1 con errno==ENOMEM (memoria insuļ¬ƒciente
          e
per aggiungere la funzione).
    Nellā€™esempio seguente si dimostra lā€™utilizzo di atexit() chiudendo un device
ļ¬le allā€™uscita dal programma (anche se ci` non ` strettamente necessario per
                                               o     e
quanto prima aļ¬€ermato):

#include    <stdio.h>
#include    <stdlib.h>
#include    <unistd.h>
#include    <fcntl.h>
#include    <sys/soundcard.h>

int dspfd;                                             /* Variabile globale */

void Messaggio()                        /* Chiamata per prima */
{
   puts("Premi <Invio> per chiudere /dev/dsp...");
   getchar();
}

void ChiudiTutto()                                   /* Chiamata per ultima */
{
   close(dspfd);
   puts("Fine del programma");
}

void errore(const char *msgerr)                   /* Gestione degli errori */
{
    perror(msgerr);
  10
    Linux svuota i buļ¬€er di I/O e chiude automaticamente i device ļ¬le rimasti eventualmente
aperti prima che il processo termini, tramite librerie a livello utente o tramite kernel

                                            12
CAPITOLO 1. LA SCHEDA AUDIO E OSS                              1.3. INIZIALIZZAZIONE DI OSS




         exit(-1);
}

int main()
{
   if ((dspfd = open("/dev/dsp", O_RDONLY)) == -1)
       errore("/dev/dsp");

         if (atexit(ChiudiTutto) == -1)             /* Registrata per prima */
             errore("ChiudiTutto()");
         if (atexit(Messaggio) == -1)               /* Registrata per ultima */
             errore("Messaggio()");

         return 0;                                  /* Uscita dal programma */
}

    Lā€™exit handler ` richiamato in seguito ad exit(), abort()11 , return o alla
                   e
consegna di un segnale la cui azione di default ` di uccidere il processo; lā€™output
                                                e
del programma sarebbe:

Premi <Invio> per chiudere /dev/dsp...

Fine del programma

   Per evitare la chiamata allā€™exit handler lo standard POSIX.1 (1990) prevede
_exit(), che inoltre evita lo svuotamento dei buļ¬€er prima della chiusura dei ļ¬le.


1.3.3         Il signal handler
Un signal handler funziona in modo molto simile ad un exit handler: previo
#include <signal.h>, si usa la funzione di libreria signal() per registrare delle
funzioni (non di libreria) che hanno il compito di reagire a segnali provenienti da
altri processi o dallo stesso processo12 (rispettivamente generati tramite le funzioni
di libreria kill() e raise()).
    In signum.h sono deļ¬niti una trentina di segnali che si conformano ad ANSI,
POSIX, System V e BSD 4.2, per i quali esistono delle disposizioni di default
(ci` equivale a signal(<segnale>, SIG_DFL)); se si vuole ignorare un partico-
   o
lare segnale si pu` porre nel codice signal(<segnale>, SIG_IGN). La signal()
                   o
ritorna il valore precedente del signal handler o SIG_ERR se si veriļ¬ca un errore.
    11
     Viene impostato un segnale SIGABRT al processo chiamante: non ` ignorabile o bloccabile
                                                                      e
da un signal handler
  12
     Un segnale ` deļ¬nibile come unā€™interruzione asincrona software nel ļ¬‚usso di un processo:
                e
esso ` ā€œimpostatoā€ dal processo che lo genera ed ` ā€œconsegnatoā€ al processo che lo riceve; il
     e                                              e
modo in cui questā€™ultimo reagisce al segnale si chiama ā€œdisposizioneā€

                                             13
1.4. SCRITTURA DI CODICE PORTABILE             CAPITOLO 1. LA SCHEDA AUDIO E OSS




   Per esempio, se si vuole che il processo reagisca a un segnale di interruzione
(SIGINT) e a un segnale di terminazione del programma (SIGTERM) con una
disposizione diversa dalla predeļ¬nita, allā€™inizio di main() si potr` porre:
                                                                   a
signal(SIGINT, SignalHandler);          /* Le funzioni possono essere */
signal(SIGTERM, SignalHandler);         /* uguali o diverse           */
ove SignalHandler ` una funzione del tipo:
                  e
void SignalHandler(int segnale) /* Il segnale invocante   */
{                               /* eā€™ passato allā€™handler */
    switch (segnale) {
        case SIGINT:
        case SIGTERM: puts("SIGINT o SIGTERM");
                       exit(0);
        default:
    }
}
il processo relativo termina se da shell di comando si digita kill -s SIGINT <PID>
o kill -s SIGTERM <PID>, ove <PID> ` lā€™identiļ¬catore del processo (visualizz-
                                            e
abile tramite il comando ps).
    Sono da tenere presenti i seguenti fatti:
   ā€¢ non possono essere variate le disposizioni di SIGKILL e SIGSTOP (signal()
     ritorna EINVAL)

   ā€¢ il comportamento di un programma ` indeļ¬nito se sono ignorati SIGFPE,
                                      e
     SIGILL o SIGSEGV

   ā€¢ ignorare il segnale derivante dalla divisione intera per zero ha un compor-
     tamento indeļ¬nito, che potrebbe condurre a un blocco del computer

   ā€¢ per certi segnali la disposizione di default implica la terminazione del pro-
     cesso e il salvataggio dellā€™area dati e heap in un ļ¬le core a ļ¬ni di debug;
     altri provocano la semplice terminazione del processo o sono ignorati

   ā€¢ a diļ¬€erenza di BSD, Linux non ridispone il signal handler a SIG_DFL dopo
     la consegna di un segnale
   Si veda man 7 signal per una dettagliata descrizione dei segnali e della loro
disposizione di default, e in ogni caso [10] per una gestione pi` soļ¬sticata.
                                                                u


1.4     Scrittura di codice portabile
Di seguito sono elencati alcuni consigli per la scrittura di programmi che siano
portabili sotto i vari sistemi operativi per cui sia stato portato anche OSS:

                                       14
CAPITOLO 1. LA SCHEDA AUDIO E OSS               1.4. SCRITTURA DI CODICE PORTABILE




   ā€¢ Come si vedr` nei successivi Capitoli, conviene usare delle speciļ¬che macro
                   a
     per impostare dei parametri, ad esempio del mixer, tramite ioctl() (queste
     schermano i dettagli dellā€™implementazione dei parametri per le future ver-
     sioni del driver); in particolare bisognerebbe controllare se ` adeguato il
                                                                    e
     valore ritornato nellā€™ultimo argomento (per le chiamate che lo prevedono)

     `
   ā€¢ E meglio riferirsi a un link simbolico per un device piuttosto che utilizzare un
     riferimento assoluto, ad esempio usando /dev/dsp al posto di /dev/dsp0;
     ci` d` ļ¬‚essibilit` allā€™utente per poter far puntare i link simbolici ad altri
       o a            a
     device ļ¬le, se questi garantiscono migliori risultati (i programmi dovrebbero
     sfruttare i nomi ā€œveriā€ solo se resi facilmente conļ¬gurabili)

   ā€¢ Non bisogna sfruttare delle caratteristiche non documentate (in quanto
     obsolete ā€” scompariranno in futuro ā€” o non ancora ben testate)

   ā€¢ Lā€™appesantimento di un programma con caratteristiche al di fuori dellā€™essen-
     ziale o con ā€œtrucchiā€ pu` compromettere la compatibilit` del codice con le
                              o                             a
     future versioni del driver

   ā€¢ Se si utilizza la risoluzione a 16 bit bisogna fare attenzione che la CPU
     memorizzi i campioni come il DSP della scheda audio, cio` coincida per
                                                                   e
     entrambi la codiļ¬ca big endian o little endian; in tal senso bisogna evitare
     di accedere ai campioni a 16 bit ciecamente come signed short

   ā€¢ Non bisogna ļ¬darsi delle impostazioni di default di un device (anche perch`
                                                                               e
     potrebbero essere state modiļ¬cate da un precedente processo); ad esempio,
     anche se il default per /dev/dsp ` 8 kHz/8 bit unsigned/mono, molte schede
                                      e
     non supportano la frequenza di campionamento di 8 kHz e si corre il rischio
     di ottenere solo rumore con le future schede audio a 24 bit; analogamente,
     non bisogna assumere per /dev/sequencer il clock di default di 100 Hz
     (Linux/Alpha ha un clock di 1024 Hz), mentre non ci sono valori di de-
     fault per /dev/music (bisogna sempre impostare per primi i parametri di
     temporizzazione)

   ā€¢ Non si devono scrivere programmi che funzionano solo a 16 bit, poichĀ“ molte
                                                                         e
     schede vecchie sono a 8 bit: campioni da 16 bit riprodotti su queste danno
     luogo solo a rumore ad alto volume

   ā€¢ Non si deve dare per scontato che per ogni scheda audio ci sia /dev/mixer
     (non lo possiedono le pi` vecchie, o quelle non ancora pienamente support-
                             u
     ate, o le schede audio completamente digitali); non tutti i mixer hanno un
     controllo di master volume (ma se ce lā€™hanno bisogna tenere presente che
     questo inļ¬‚uenza il volume di tutti i canali), inoltre si deve sempre testare
     la presenza di un canale prima di cercare di indirizzarlo (ad esempio, non
     tutte le schede possiedono un sintetizzatore interno e/o una porta MIDI)

                                        15
1.5. ANATOMIA DEL DRIVER                              CAPITOLO 1. LA SCHEDA AUDIO E OSS




   ā€¢ Non si deve usare il full duplex senza prima controllare che la scheda audio
     supporti tale modalit`a


   ā€¢ I device audio non devono essere tenuti aperti quando non sono richiesti,
     altrimenti altri programmi non vi possono accedere; in tal senso un pro-
     gramma dovrebbe gestire ļ¬‚essibilmente le situazioni di EBUSY, ad esempio
     riprovando ad accedere dopo qualche tempo al device ļ¬le



1.5       Anatomia del driver
OSS sfrutta il Direct Memory Access (DMA) per trasferire i campioni dalla scheda
audio a unā€™opportuna area di RAM e viceversa: questa in genere non coincide
con il buļ¬€er del processo che li elabora, per cui il driver deve copiare i campioni
dal/al buļ¬€er DMA a/da questā€™ultimo13 .
    Nei PCā€“compatibili della copia se ne occupa la CPU, dal momendo che il
DMA Controller (DMAC) compatibile Intel 8237 ha dei pesanti limiti: non pu`          o
eļ¬€ettuare copie fra le porte di I/O o fra memoria e memoria; inoltre il buļ¬€er
DMA deve risiedere al di sotto dei primi 16 MB di RAM per le schede audio
ISA (non per le PCI), poichĀ“ questo ` il limite di indirizzamento del bus, e deve
                              e         e
essere un blocco di memoria non frammentato che inizia e ļ¬nisce nella stessa
pagina DMA. Questā€™ultima ha dimensione di 64 kB per i canali 0Ć·3 a 8 bit e
128 kB per i canali 5Ć·7 a 16 bit: ci` rende diļ¬ƒcile usare direttamente il buļ¬€er
                                       o
locale del processo come buļ¬€er DMA con le schede ISA e pi` di 16 MB, poichĀ“
                                                                 u                   e
dovrebbe risiedere al di sotto del limite dei 16 MB; tuttavia i nuovi controller nelle
periferiche bypassano lā€™Intel 8237 completamente (ļ¬‚yā€“by), per cui in particolari
condizioni si pu` arrivare a mappare il buļ¬€er DMA allā€™interno dellā€™area dati del
                 o
processo (ci` ` sempre possibile con le schede PCI).
            oe
    Lā€™elaborazione dei campioni da parte del processo deve avvenire almeno un
poā€™ pi` velocemente del ritmo al quale il DMAC trasferisce i campioni, aļ¬ƒnchĀ“
       u                                                                             e
non ci siano pause in fase di campionamento o riproduzione. Se ci` si veriļ¬ca
                                                                         o
bisogner` usare una frequenza di campionamento inferiore allā€™attuale, o usare un
         a
formato audio pi` ā€œcompattoā€ per i campioni, in modo da ridurre la quantit` di
                  u                                                               a
byte trasferiti dal DMAC.
    Linux ha il ā€œproblemaā€ di essere multiutente e multiprogrammato, per cui
i processi competono per lā€™utilizzo della CPU e un processo a pi` alta pri-
                                                                          u
orit` potrebbe porre il processo che sfrutta i servizi di OSS in stato di wait
    a
per diversi ms: in tal modo il tempo che questo ha per elaborare i campioni

  13
    Alcune schede possono autoā€“iniziare il trasferimento senza attendere risposta dal driver,
usando il DMAC in modalit` autoā€“restart (ci` non ` supportato da tutti i sistemi operativi, ad
                          a                 o      e
esempio da BSD)

                                             16
CAPITOLO 1. LA SCHEDA AUDIO E OSS                                    1.5. ANATOMIA DEL DRIVER




diminuisce. In pratica ci deve essere abbastanza spazio nel buļ¬€er DMA per
garantire lā€™operativit` per il tempo di wait14 .
                      a
   OSS gestisce il buļ¬€er DMA con la tecnica del multiā€“buļ¬€ering: in pratica
questo ` diviso in frammenti di uguale dimensione, per default calcolata dal driver
        e
in modo tale che la latenza15 sia attorno a 0.5s per la riproduzione e attorno a 0.1s
per il campionamento. In tal modo ` possibile aumentare la dimensione del buļ¬€er
                                     e
senza inļ¬‚uire sulla latenza stessa poichĀ“ il DMAC lavora solo su un frammento
                                         e
per volta, mentre lā€™applicazione legge o scrive sul resto del buļ¬€er.

   memoria
                    wait                                                             Scheda audio
                                        Kernel

         Processo
                                                 1111
                                                 0000         DMAC

                                                 1111
                                                 0000
                                                                     bus ISA o PCI
                                       OSS
        buffer audio                  driver
                           read() o
                            write()


                                                 buffer DMA




                       Figura 1.5: Schema di utilizzo del multiā€“buļ¬€ering



1.5.1        Scrittura sul buļ¬€er DMA
In fase di riproduzione, quando il programma chiama write() per la prima volta
dopo lā€™apertura del device, si veriļ¬cano i seguenti eventi:

    ā€¢ il driver programma la scheda audio con i parametri di campionamento
      predisposti (risoluzione, numero di canali e frequenza)

    ā€¢ di default ` calcolata la dimensione adeguata per un frammento, se tramite
                 e
      unā€™opportuna chiamata ioctl() non se ne ` stabilita unā€™altra
                                                  e

    ā€¢ viene iniziato il riempimento del primo frammento del buļ¬€er con i dati
      passati dalla write()

    ā€¢ se il primo frammento ` stato riempito completamente, il DMAC ne inizia
                               e
      il trasferimento alla scheda audio
  14
     Alcune schede dispongono di RAM locale per la riproduzione, ma prima che questa possa
avvenire i campioni devono esservi trasferiti (per la Gravis UltraSound ci sono 256 kB per
canale, ovvero sono ā€œcopertiā€ 2.9 s di suono continuo in modalit` 16 bit/stereo/44.1 kHz)
                                                                a
  15
     La latenza ` il tempo che il processo deve aspettare per avere accesso a un frammento
                e
in campionamento o perchĀ“ questo venga suonato in riproduzione quando il buļ¬€er ` pieno;
                            e                                                          e
essa dipende dal data rate, che ` la quantit` di dati che il DMAC deve trasferire nellā€™unit` di
                                e           a                                              a
tempo (per esempio, con un campionamento 16 bit/stereo/44.1 kHz il data rate ` 2 Ā· 2 Ā· 44.1 =
                                                                                e
176.4 kB/s), nonchĀ“ dalla dimensione del frammento
                    e

                                                     17
1.5. ANATOMIA DEL DRIVER                       CAPITOLO 1. LA SCHEDA AUDIO E OSS




   ā€¢ il driver copia il resto dei dati nel buļ¬€er, eventualmente riempiendo altri
     frammenti; se tutti i frammenti del buļ¬€er sono stati riempiti il processo
     relativo al programma che ha chiamato la write() ` messo in stato di wait
                                                          e
     ļ¬nchĀ“ non ` libero almeno un frammento (condizione di overrun)
           e     e

    Alle successive chiamate di write() i dati sono immagazzinati nel buļ¬€er
secondo la disponibilit` di frammenti liberi.
                        a
    Lā€™overrun si veriļ¬ca normalmente per un processo che scriva i campioni nel
buļ¬€er pi` velocemente di quanto vengano riprodotti. Se al contrario il processo
         u
` leggermente pi` lento a scrivere i campioni rispetto alla velocit` con la quale
e                u                                                  a
sono riprodotti si veriļ¬ca la condizione di underrun, per uno dei seguenti motivi:

   ā€¢ lā€™applicazione ` troppo lenta nellā€™elaborazione dei campioni (perchĀ“ la CPU
                    e                                                   e
     ` troppo lenta rispetto al data rate richiesto o ci sono troppi processi in
     e
     esecuzione che competono per la CPU)

   ā€¢ ci sono leggere variazioni nel tempo di CPU ricevuto (unā€™applicazione gen-
     eralmente ben funzionante pu` occasionalmente andare in underrun)
                                     o

   ā€¢ lā€™applicazione tenta di lavorare troppo in tempo reale (frammenti pi` piccoli
                                                                         u
     decrescono la latenza, tuttavia bisogna sempre scrivere altri campioni prima
     che il buļ¬€er si svuoti)

    Un underrun provoca in genere un difetto udibile nel segnale riprodotto: pu`o
essere una breve pausa, un ā€œclickā€ o la ripetizione di una parte del segnale
(looping); se questā€™ultima si veriļ¬ca con frequenza uniforme si avvertir` un tono
                                                                        a
sovrapposto al segnale riprodotto, con frequenza pari a quella con cui si veriļ¬ca
lā€™underrun.


1.5.2    Lettura dal buļ¬€er DMA
In fase di campionamento, quando il programma chiama read() per la prima
volta dopo lā€™apertura del device, si veriļ¬cano i seguenti eventi:

   ā€¢ il driver programma la scheda audio con i parametri di campionamento
     predisposti (risoluzione, numero di canali e frequenza)

   ā€¢ di default ` calcolata la dimensione adeguata per un frammento, se tramite
                e
     unā€™opportuna chiamata ioctl() non se ne ` stabilita unā€™altra
                                                 e

   ā€¢ sono attivati il processo di campionamento da parte della scheda audio e il
     trasferimento dei campioni nel primo frammento del buļ¬€er

   ā€¢ il processo ` messo in wait ļ¬nchĀ“ non ` riempito un numero di frammenti
                 e                   e     e
     che forniscono globalmente una quantit` di campioni maggiore o uguale a
                                            a
     quella richiesta

                                       18
CAPITOLO 1. LA SCHEDA AUDIO E OSS                        1.6. SCHEDE AUDIO ISA E PCI




   ā€¢ i campioni richiesti sono copiati nel buļ¬€er del processo; gli eventuali cam-
     pioni in pi` rimangono nel buļ¬€er DMA
                u

    Le read() successive funzionano come sopra, senza che sia necessario ripredis-
porre la scheda audio.
    Un overrun in campionamento si veriļ¬ca se il buļ¬€er ` completamente riempito:
                                                         e
in tal caso gli ulteriori campioni sono scartati; le ragioni per cui si veriļ¬ca sono
simili a quelle per cui si veriļ¬ca in riproduzione.


1.6      Schede audio ISA e PCI
Lā€™approccio seguito in questo lavoro ` di essere il pi` indipendenti possibile dal-
                                         e              u
lā€™hardware, in modo da poter creare dei programmi che girino su ogni piattaforma
per cui ` stato portato OSS con tuttā€™al pi` una semplice ricompilata del codice
         e                                     u
sorgente. Tuttavia si vogliono elencare i motivi per i quali le schede audio PCI
sono superiori alle schede audio ISA (al di l` della qualit` audio); al momento in
                                                a             a
cui si scrive (1999) la quasi totalit` delle schede audio in commercio sono PCI, ma
                                     a
ļ¬no a un anno fa erano quasi tutte ISA: un musicista professionista dovrebbe pren-
dere in considerazione lā€™acquisto di una scheda audio PCI, anche se attualmente
OSS non supporta del tutto le nuove caratteristiche, come lā€™audio 3D.
    Si elencheranno ora le diļ¬€erenze fra ISA e PCI pertinenti le schede audio:

   ā€¢ Il bus ISA ha un clock nominale di 8 MHz, il che darebbe un throughput
     teorico di 16 MB/s; in realt`, a causa di overhead vari nella gestione dei seg-
                                  a
     nali, nonchĀ“ il fatto che sono richiesti due cicli di clock per il trasferimento
                  e
     dei dati, il throughput si aggira attorno ai 5 MB/s. Se si guarda la quantit`  a
     di dati da trasferire per una scheda che campiona a 16 bit/stereo/44.1 kHz
     (circa 176 kB/s) questo throughput appare adeguato, ma si pu` veriļ¬care
                                                                          o
     che il DMA blocchi lā€™accesso della CPU al bus durante il trasferimento dei
     campioni o se la richiesta dā€™interrupt ` occupata (con ISA le IRQ non sono
                                             e
     condivisibili), il che pu` causare click nel suono in sistemi pesantemente
                              o
     caricati. La capacit` di indirizzamento massima per ISA ` di 16 MB, per
                           a                                        e
     cui sono diļ¬ƒcilmente applicabili le tecniche di allocazione del buļ¬€er DMA
     nel buļ¬€er del processo, che dovrebbe risiedere al di sotto di tale limite anche
     per sistemi con pi` RAM. Pu` inoltre risultare diļ¬ƒcile la conļ¬gurazione di
                         u          o
     una scheda audio, soprattutto con OSS/Free se ` PnP.e

   ā€¢ Le speciļ¬che PCI 2.1 consentono un clock sul bus ļ¬no a 66 MHz, con un
     throughput teorico di 264 MB/s, mentre in pratica ci si aggira intorno ai
     108 MB/s; con un clock sul bus di 33 MHz questi valori si dimezzano. Gli
     interrupt sono condivisibili, per cui con la tecnica dellā€™interrupt binding, se
     si veriļ¬cano pi` interrupt contemporaneamente, questi vengono raggrup-
                     u
     pati e serviti in base alla priorit` (e Linux distingue fra fast interrupt ā€”
                                        a
     quelli che richiedono un salvataggio del contesto parziale, come la richiesta

                                        19
1.7. FILE SYSTEM E DEVICE FILE                  CAPITOLO 1. LA SCHEDA AUDIO E OSS




      di un servizio DMA ā€” e gli interrupt normali, con salvataggio completo del
      contesto ā€” riducendo in tal modo lā€™overhead). Il PCI consente il busmas-
      tering multiplo (con due busmaster), ovvero due arbitri nella gestione del
      bus, il che si traduce nellā€™accesso contemporaneo di CPU e DMA al bus se
      le aree di memoria interessate non coincidono; lā€™indirizzamento ` a 32 bit,
                                                                        e
      per cui sono applicabili le tecniche di allocazione del buļ¬€er DMA nel buļ¬€er
                      `
      del processo. E inoltre pi` semplice la conļ¬gurazione delle periferiche PCI,
                                 u
      in quanto dopo il boot queste negoziano fra loro, in pratica autoallocandosi.

   Queste ed altre considerazioni, come la tendenza delle nuove schede audio
ad incrementare la frequenza di campionamento, spingono a concludere che una
scheda audio PCI pu` risultare ļ¬no a dieci volte pi` eļ¬ƒciente di una scheda ISA.
                     o                             u


1.7      File system e device ļ¬le
Come si ` avuto occasione di aļ¬€ermare precedentemente, OSS ` un driver che
           e                                                        e
fornisce al programmatore la possibilit` di gestire audio e MIDI tramite opportuni
                                         a
device ļ¬le inseriti nella struttura dellā€™albero monolitico del ļ¬le system di Linux.
Ogni device ļ¬le ` caratterizzato da un major number e da un minor number : il
                  e
primo ` utilizzato come indice in una tabella del kernel per identiļ¬care il tipo
         e
di driver che deve gestire un dispositivo hardware, il secondo ` passato al driver
                                                                 e
stesso per identiļ¬care lā€™unit` su cui agire (classe del device).
                              a
     In Linux il major number per OSS ` 14, ma per altri sistemi operativi potrebbe
                                        e
essere diverso. Il minor number pu` essere codiļ¬cato tramite un solo byte: in
                                      o
tal caso, come da ļ¬gura 1.6, i quattro bit meno signiļ¬cativi identiļ¬cano la classe
del dispositivo, mentre i quattro bit pi` signiļ¬cativi identiļ¬cano un dispositivo
                                           u
allā€™interno di una stessa classe; ne consegue che ci possono essere ļ¬no a sedici
dispositivi dello stesso tipo per ogni classe.

                                                 Tipo device    Classe
                                                   mixer           0
                                                   sequencer       1
                                                   midi            2
        7                 4 3             0
                                                   dsp             3
            num. device          classe            audio           4
                                                   dspW            5
                       1 byte
                                                   sndstat         6
                                                   riservato       7
                                                   music           8
                                                   sndproc         9

         Figura 1.6: Codiļ¬ca del minor number di un device ļ¬le di OSS

                                          20
CAPITOLO 1. LA SCHEDA AUDIO E OSS                             1.8. LE VERSIONI DI OSS




    Ad esempio, /dev/midi00 identiļ¬ca il primo dispositivo di classe 2 (MIDI),
per cui ` il numero del device ` 0: ci` implica che il minor number per il device ļ¬le
        e                       e     o
relativo ` 0x02 (2 in decimale). Analogamente per /dev/midi01 il minor number
         e
per il device ļ¬le relativo sar` 0x12 (18 in decimale), per /dev/midi02 sar` 0x22
                              a                                               a
(34 in decimale) e per /dev/midi03 sar` 0x32 (50 in decimale).
                                          a
    Anche se nelle odierne distribuzioni di Linux non ci dovrebbero essere problemi
del genere, se un device ļ¬le dovesse mancare ` possibile crearlo eļ¬€ettuando il login
                                               e
come root e dando il seguente comando:

mknod -m <permessi> <nome device file> c 14 <classe del device>

ad esempio, il nome del device ļ¬le potrebbe essere /dev/music e la classe sarebbe 8;
<permessi> ` un numero ottale che predispone i permessi di accesso al ļ¬le, che
             e
pu` essere posto pari a 666 per accesso in lettura/scrittura da parte di tutti gli
  o
utenti (vedere man chmod).


1.8      Le versioni di OSS
Il riconoscimento della versione di OSS in uso varia secondo che si stia utilizzando
una versione precedente o successiva alla 3.6. Ad esempio, la versione 3.5.4 di
soundcard.h deļ¬nisce le seguenti macro:

#define SOUND_VERSION   350
#define UNIX_SOUND_SYSTEM

mentre nella versione 3.8.2 sono deļ¬nite le seguenti altre macro:

#define SOUND_VERSION   0x030802
#define OPEN_SOUND_SYSTEM

SOUND_VERSION contiene il numero di versione, con formato che varia secondo che
sia deļ¬nito UNIX_SOUND_SYSTEM o OPEN_SOUND_SYSTEM.
    Dalla versione 3.6 in poi ` possibile usare il seguente frammento di codice, che
                              e
interroga direttamente il driver per ricavare il numero di versione (` pi` aļ¬ƒdabile
                                                                     e u
che ricavarlo da SOUND_VERSION):

int versione;
if (ioctl(dspfd, OSS_GETVERSION, &versione) == -1) {
    /* Versione precedente alla 3.6: errno==EINVAL */
}

   Il seguente frammento di codice ricava i numeri di versione e release indipen-
dentemente dalla versione di OSS utilizzata:

int versione, release1, release2, tmpver;
#ifdef UNIX_SOUND_SYSTEM

                                         21
1.8. LE VERSIONI DI OSS                CAPITOLO 1. LA SCHEDA AUDIO E OSS




   versione = SOUND_VERSION / 100;
   release1 = (SOUND_VERSION - versione*100) / 10;
   release2 = SOUND_VERSION - versione*100 - release1*10;
#else   /* eā€™ definito OPEN_SOUND_SYSTEM */
   if (ioctl(dspfd, OSS_GETVERSION, &tmpver) == -1)
       errore("OSS_GETVERSION");
   versione = (tmpver & 0x00ff0000) >> 16;
   release1 = (tmpver & 0x0000ff00) >> 8;
   release2 = tmpver & 0x000000ff;
#endif




                                22
Capitolo 2

IL MIXER E LA GESTIONE
DEI CANALI

2.1      Descrizione di /dev/mixer
Non tutte le schede audio possiedono un mixer: nella fattispecie possono non
averlo le schede pi` vecchie, quelle non ancora pienamente supportate, quelle
                    u
professionali e le completamente digitali. Anche se il mixer ` mancante si pu`
                                                                 e                 o
sempre aprire /dev/mixer, ma unā€™eventuale ioctl() ritorna errno==ENXIO.
    Nella Sezione 1.3 si ` fornito uno scheletro di codice C per lā€™apertura e la
                          e
chiusura di un device ļ¬le; si ` scritto che fra la open() e la close() di questo
                                e
ci possono essere delle read(), write() o ioctl(). /dev/mixer ` un device ļ¬le
                                                                     e
atipico, in quanto non accetta operazioni di read() o write() e lā€™unica primitiva
utilizzabile ` ioctl(): infatti il mixer svolge solo un lavoro di gestione dei canali
             e
cambiando la conļ¬gurazione della scheda audio, praticamente non impiegando
risorse di calcolo per operare.
    A diļ¬€erenza di /dev/dsp e /dev/audio, pi` di un processo alla volta pu`
                                                   u                               o
aprire /dev/mixer; generalmente si usa O_RDONLY come argomento di open().
Le modiļ¬che eļ¬€ettuate alla conļ¬gurazione del mixer permangono anche dopo
la chiusura dellā€™ultimo processo modiļ¬cante, ļ¬no a quando un eventuale altro
processo non eļ¬€ettuer` nuovi cambiamenti o ļ¬no al reboot del computer. Allā€™atto
                       a
del boot ` il kernel che si occupa di conļ¬gurare la scheda audio con dei valori
           e
di default ragionevoli, ma che non dovrebbero comunque essere dati per scontati
per non creare programmi inaļ¬ƒdabili.
    Solo per il primo mixer, lā€™uso delle ioctl() per /dev/mixer su questo o su un
altro device di OSS sono equivalenti: ad esempio, se si ` aperto /dev/sequencer `
                                                         e                         e
inutile aprire anche /dev/mixer per variare la conļ¬gurazione della scheda audio,
basta usare gli ioctl() che si sarebbero utilizzati col secondo direttamente col
primo.
    `
    E importante veriļ¬care le capacit` del mixer prima di usarne i canali, in mo-
                                        a
do da creare programmi che siano portabili per quasi tutte le schede audio. Le

                                         23
2.2. I CANALI DEL MIXER              CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI




diļ¬€erenze di comportamento riscontrate dovrebbero essere indicate nella docu-
mentazione, evitando descrizioni troppo speciļ¬che nei confronti dei canali, che
possono avere caratteristiche diverse con schede diverse.



2.2      I canali del mixer
Per i canali del mixer ci si pu` rifare alla metafora delle ļ¬gure 1.1 e 1.2, per cui
                               o
un canale identiļ¬ca la classe del dispositivo (CD, microfono, . . . ) che a questo
` connesso; il programmatore pu` eļ¬€ettuarne la selezione per la riproduzione o
e                                  o
il campionamento, regolandone il livello di volume (se il dispositivo ` stereo ci
                                                                         e
sono due livelli di volume indipendentemente controllabili, il che consente di real-
izzare il balance). Il volume principale pu` essere mancante (Gravis UltraSound,
                                            o
Microsoft Sound System).
    Sono deļ¬niti SOUND_MIXER_NRDEVICES canali, a cui ` associato un numero da
                                                          e
0 a SOUND_MIXER_NRDEVICES-1; un programma non dovrebbe cercare di accedere
a numeri di canale superiori a questā€™ultimo.
    OSS mette a disposizione del programmatore dei nomi simbolici per ogni
canale; quelli deļ¬niti in soundcard.h versione 3.5.4 si trovano nella tabella della
prossima pagina.
    Ad ogni canale ` associato un int, nella cui rappresentazione in binario (bit-
                     e
mask ) ` posto a 1 il bit di posizione corrispondente al numero del canale; le
        e
bitmask sono utili con i comandi di gestione della conļ¬gurazione del mixer.
    Sempre in soundcard.h sono deļ¬niti dei nomi simbolici da dare ai canali
tramite le macro:


#define SOUND_DEVICE_LABELS {"Vol ",           "Bass ",    "Trebl",   "Synth", 
                             "Pcm ",           "Spkr ",    "Line ",   
                             "Mic ",           "CD   ",    "Mix ",    "Pcm2 ", 
                             "Rec ",           "IGain",    "OGain",   
                             "Line1",          "Line2",    "Line3"}

#define SOUND_DEVICE_NAMES         {"vol", "bass", "treble", "synth", 
                                    "pcm", "speaker", "line", "mic", 
                                    "cd", "mix", "pcm2", "rec", "igain", 
                                    "ogain", "line1", "line2", "line3"}


la diļ¬€erenza fra i due ` che il primo formato ` adatto per la stampa dei nomi a
                        e                       e
video quali etichette dei canali, mentre del secondo formato ` pi` adatto lā€™utilizzo
                                                             e u
quando i nomi dei device audio sono forniti sulla riga di comando di una shell.

                                        24
CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI              2.2. I CANALI DEL MIXER




 Nomi dei canali         Bitmask associate      Descrizione
 SOUND_MIXER_VOLUME      SOUND_MASK_VOLUME      Livello volume principale
 SOUND_MIXER_BASS        SOUND_MASK_BASS        Regolazione toni bassi principale
 SOUND_MIXER_TREBLE      SOUND_MASK_TREBLE      Regolazione toni acuti principale
 SOUND_MIXER_SYNTH       SOUND_MASK_SYNTH       Livello di uscita sintetizzatore
                                                interno (FM, wavetable); per alcune
                                                schede ne controlla anche il livello
                                                di campionamento
 SOUND_MIXER_PCM         SOUND_MASK_PCM         Livello di uscita di /dev/dsp
                                                e /dev/audio
 SOUND_MIXER_SPEAKER     SOUND_MASK_SPEAKER     Livello di uscita del segnale
                                                allā€™altoparlantino nel PC (se
                                                connesso alla scheda audio);
                                                su altre schede pu` essere un
                                                                    o
                                                generico ingresso mono con
                                                qualche altra funzione
 SOUND_MIXER_LINE        SOUND_MASK_LINE        Livello di ingresso per Lineā€“In
 SOUND_MIXER_MIC         SOUND_MASK_MIC         Livello del segnale microfonico in
                                                campionamento o inviato a cuļ¬ƒe e
                                                Lineā€“Out; qualche volta il microfono
                                                non ` connesso a questo canale, ma
                                                     e
                                                a un line level input della scheda
 SOUND_MIXER_CD          SOUND_MASK_CD          Livello del CD Audioā€“In
 SOUND_MIXER_IMIX        SOUND_MASK_IMIX        Recording monitor campionamento;
                                                durante tale fase, su alcune schede
                                                controlla il volume delle cuļ¬ƒe
 SOUND_MIXER_ALTPCM      SOUND_MASK_ALTPCM      Livello di un DSP secondario; nella
                                                Pro Audio Spectrum 16 ` il canale
                                                                           e
                                                dellā€™emulazione della Sound Blaster
 SOUND_MIXER_RECLEV      SOUND_MASK_RECLEV      Livello di campionamento per tutti
                                                i canali (nella Sound Blaster 16 si
                                                hanno solo quattro livelli possibili)
 SOUND_MIXER_IGAIN       SOUND_MASK_IGAIN       Livello di guadagno di ingresso
 SOUND_MIXER_OGAIN       SOUND_MASK_OGAIN       Livello di guadagno di uscita
 SOUND_MIXER_LINE1       SOUND_MASK_LINE1       Canale generico 1 (aux1); i codec
                                                AD1848 e compatibili hanno tre
                                                line level input a cui diversi
                                                costruttori assegnano funzioni
                                                diverse, per cui tali nomi si
                                                usano quando il signiļ¬cato preciso
                                                di un canale ļ¬sico ` sconosciuto
                                                                     e
 SOUND_MIXER_LINE2       SOUND_MASK_LINE2       Canale generico 2 (aux2)
 SOUND_MIXER_LINE3       SOUND_MASK_LINE3       Canale generico 3 (line)




                                       25
2.2. I CANALI DEL MIXER             CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI




   Se in un programma si eļ¬€ettuano le assegnazioni:

const char *nome_canale[] = SOUND_DEVICE_LABELS;
const char *nome_cmline[] = SOUND_DEVICE_NAMES;

allora, ad esempio, nome_canale[SOUND_MIXER_CD] corrisponde a ā€œCD           ā€, men-
tre nome_cmline[SOUND_MIXER_CD] corrisponde a ā€œcdā€.
    Il mixer consente la selezione dei canali da cui eļ¬€ettuare il campionamento,
che per buona parte delle schede avviene in mutua esclusione.
    Il canale di default dopo il boot ` quello del microfono, ma non dovrebbe
                                        e
essere dato per scontato, poichĀ“ il driver non altera le predisposizioni del mixer
                                e
a meno di un comando da programma; un qualche altro processo dopo il boot
potrebbe averle modiļ¬cate, con tali modiļ¬che che permangono anche dopo la sua
terminazione.
    Lā€™insieme di canali disponibili non ` ļ¬sso, ma dipende dalla scheda audio; si
                                         e
pu` veriļ¬care che ai canali dello stesso chip mixer costruttori diversi assegnino
   o
funzioni diverse, per cui bisogner` veriļ¬carne caso per caso il reale signiļ¬cato.
                                  a
    Sarebbe meglio non includere funzionalit` di mixer nei programmi se si vuole
                                               a
la massima portabilit` del proprio codice, demandandole a programmi specializ-
                      a
zati per le varie schede audio. Nel caso si volesse realizzare un tale programma
mixer bisogna ben documentare le sue capacit` se ` sviluppato per una precisa
                                                 a    e
scheda, altrimenti ` meglio evitare di essere troppo speciļ¬ci nella documentazione
                    e
per non trarre in inganno gli utenti: potrebbero credere che la propria scheda
audio sia diversa da come ` realmente, basandosi su ci` che il programma fa
                             e                             o
vedere.


2.2.1     Lettura della conļ¬gurazione
Come ` stato visto sopra, converrebbe eļ¬€ettuare il controllo sia delle capacit`
        e                                                                       a
della scheda audio che dellā€™esistenza o meno dei canali di interesse prima di in-
traprendere qualsiasi altra azione; unā€™operazione di ioctl() fallita (ad esempio,
perchĀ“ il canale non esiste) ritorna -1 e errno==EINVAL.
      e
    Per eļ¬€ettuare la lettura della conļ¬gurazione dei canali del mixer il codice `
                                                                                e
simile per tutti i comandi a disposizione:

int bitmask;
if (ioctl(mixfd, SOUND_MIXER_READ_****, &bitmask) == -1) {
    /* Il mixer eā€™ mancante - errno==ENXIO */
}

ove SOUND_MIXER_READ_**** ` lā€™identiļ¬catore del comando di lettura che ritorna
                              e
in bitmask una maschera di bit; questa pu` essere esaminata per determinare le
                                           o
capacit` di un canale o del mixer in base al comando dato.
       a

                                        26
CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI              2.2. I CANALI DEL MIXER




   Per i canali il controllo si pu` eļ¬€ettuare con:
                                  o
if (bitmask & (1 << numero_canale)) {
    /* Il canale possiede la capacitaā€™ in esame */
}
ove numero_canale ` un intero tra 0 e SOUND_MIXER_NRDEVICES-1 o il nome
                     e
mnemonico del canale; al posto di (1 << numero_canale) si pu` utilizzare di-
                                                                  o
rettamente la bitmask ad esso associata.
    I comandi a disposizione per la lettura della conļ¬gurazione sono:

 Comandi                             Richiesta a OSS
 SOUND_MIXER_READ_DEVMASK            Quali canali sono presenti?
 SOUND_MIXER_READ_STEREODEVS         Quali canali sono stereo?
 SOUND_MIXER_READ_RECMASK            Quali sono i canali campionabili?
 SOUND_MIXER_READ_RECSRC             Qual ` il canale campionabile attivo?
                                          e
 SOUND_MIXER_READ_CAPS               Si pu` campionare solo un canale per volta?
                                          o
    Con lā€™ultimo comando si testa se si possono campionare i canali solo in mutua
esclusione; il controllo si eļ¬€ettua con:
if (bitmask & SOUND_CAP_EXCL_INPUT) {
    /* Campionamento solo in mutua esclusione */
}
    La diļ¬€erenza fra SOUND_MIXER_READ_RECMASK e SOUND_MIXER_READ_RECSRC
` che il primo comando ritorna una bitmask con un bit a 1 per ogni canale per
e
cui la scheda audio possiede la capacit` di campionamento, mentre il secondo
                                       a
ritorna una bitmask con un bit a 1 per ogni canale attualmente selezionato per
il campionamento (se questo ` possibile in mutua esclusione solo un bit in tutta
                            e
la bitmask pu` essere a 1).
              o

2.2.2    Selezione del canale da campionare
Per selezionare il canale da cui campionare basta il seguente frammento di codice:
int bitmask = SOUND_MASK_****;
if (ioctl(mixfd, SOUND_MIXER_WRITE_RECSRC, &bitmask) == -1) {
    /* Non cā€™eā€™ il mixer o il canale */
    /* errno==ENXIO oppure EINVAL    */
}
ove SOUND_MASK_**** ` la bitmask associata al canale desiderato.
                       e
    Nel caso fosse possibile campionare da pi` canali contemporaneamente, li si
                                             u
seleziona ponendo in bitmask un OR aritmetico delle bitmask associate ai canali;
ad esempio, per selezionare il campionamento simultaneo da CD e da microfono:

                                        27
2.3. LIVELLI DI VOLUME DEI CANALI     CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI




bitmask = SOUND_MASK_CD | SOUND_MASK_MIC;

    Se nessun bit ` posto a 1 (bitmask==0x00000000), il driver seleziona il canale
                  e
del microfono.


2.3      Livelli di volume dei canali
Le schede audio rappresentano il livello di un canale con un numero di bit vari-
abile: 3, 8 e anche 16 bit. Lā€™architettura di OSS svincola il programmatore dalla
conoscenza dei livelli assoluti di volume introducendo una rappresentazione in
percentuale: il volume di un canale pu` variare fra 0 (spento) e 100 (massimo);
                                         o
se il canale ` stereo si hanno due di queste percentuali, che possono essere uguali
             e
o meno per realizzare il balance.
    Per leggere il livello attuale di volume per un canale si sfrutta il seguente
frammento di codice:

int volume;
if ((ioctl(mixfd, MIXER_READ(numero_canale), &volume) == -1) {
    /* Non cā€™eā€™ il mixer o il canale */
    /* errno==ENXIO oppure EINVAL    */
}

ove numero_canale ` un numero compreso tra 0 e SOUND_MIXER_NRDEVICES-1,
                       e
oppure il nome mnemonico del canale. Al posto di MIXER_READ(numero_canale)
si pu` utilizzare anche SOUND_MIXER_READ_****, con **** nome del canale; ad
      o
esempio, per il microfono ` SOUND_MIXER_READ_MIC.
                             e
    Il volume ` codiļ¬cato come in ļ¬gura 2.1: se il dispositivo ` stereo la codiļ¬ca dei
               e                                               e
canali destro e sinistro si trova nella parola meno signiļ¬cativa di volume (intero
a 32 bit); i 16 bit della parola pi` signiļ¬cativa sono indeļ¬niti e dovrebbero essere
                                   u
ignorati. Nel byte pi` signiļ¬cativo della LSW cā€™` il volume del canale destro, nel
                       u                            e
byte meno signiļ¬cativo il volume del canale sinistro; per i canali mono ` valido
                                                                              e
solo il byte meno signiļ¬cativo, essendo lā€™MSB posto uguale allā€™LSB dal driver.

             31                       16 15             8 7           0
                  XXXXXXXX Destro Sinistro

                      MSW                     MSB             LSB
                   (da ignorare)
                                                      LSW
          Figura 2.1: Rappresentazione del volume di un canale stereo

                                         28
CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI     2.4. DIPENDENZA DALLā€™HARDWARE




   Per estrarre il volume dei canali destro e sinistro si possono sfruttare le
seguenti linee di codice:
int volume, vol_sinistro, vol_destro;
vol_sinistro = volume & 0x000000ff;
vol_destro   = (volume & 0x0000ff00) >> 8;
   Inversamente, per costituire una parola di volume:
int volume;
volume = (vol_destro << 8) | vol_sinistro;
   Per cambiare il volume si utilizza il seguente frammento di codice:
int volume = <valore>;
if ((ioctl(fd, MIXER_WRITE(numero_canale), &volume) == -1) {
    /* Non cā€™eā€™ il mixer o il canale */
    /* errno==ENXIO oppure EINVAL    */
}
ove numero_canale ` un numero compreso tra 0 e SOUND_MIXER_NRDEVICES-1,
                       e
oppure il nome mnemonico del canale. Al posto di MIXER_WRITE(numero_canale)
si pu` utilizzare anche SOUND_MIXER_WRITE_****, con **** nome del canale; ad
      o
esempio, per il CD ` SOUND_MIXER_WRITE_CD.
                     e
    Dopo il cambiamento bisognerebbe veriļ¬care se il livello ritornato in volume
risulta di proprio gradimento, dal momento che ` di solito pi` piccolo di quanto
                                                 e           u
richiesto; sequenze di scrittura/lettura ripetute (senza cambiare tale variabile)
                                       `
possono portare al suo azzeramento. E conveniente eļ¬€ettuare la predisposizione
del volume durante lā€™inizializzazione del programma, ignorando poi il volume
ritornato in seguito.


2.4     Dipendenza dallā€™hardware
Per ottenere dal mixer il nome della scheda audio si pu` utilizzare il seguente
                                                       o
frammento di codice:
mixer_info info;
if ((ioctl(fd, SOUND_MIXER_INFO, &info) == -1) {
    /* Non cā€™eā€™ il mixer - errno==ENXIO */
}
ove mixer_info ` una struct cos` composta:
               e               ı
char id[16 ] identiļ¬catore della scheda audio (in genere un paio di caratteri)
char name[32 ] nome per esteso della scheda
   Ecco un output di esempio per SOUND_MIXER_INFO con una scheda Sound
Blaster 16:
SB
Sound Blaster

                                       29
2.5. NUOVE CARATTERISTICHE           CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI




2.5      Nuove caratteristiche
In questa Sezione ci si occuper` di descrivere le nuove caratteristiche di OSS
                                 a
riguardanti il mixer introdotte dalla versione 3.6 in poi.

   ā€¢ ` stata implementata la possibilit` di gestire dei canali in pi` :
     e                                 a                            u


       Nomi dei canali           Bitmask associate         Descrizione
       SOUND_MIXER_DIGITAL1      SOUND_MASK_DIGITAL1       Ingresso digitale 1
       SOUND_MIXER_DIGITAL2      SOUND_MASK_DIGITAL2       Ingresso digitale 2
       SOUND_MIXER_DIGITAL3      SOUND_MASK_DIGITAL3       Ingresso digitale 3
       SOUND_MIXER_PHONEIN       SOUND_MASK_PHONEIN        Ingresso livello fono
       SOUND_MIXER_PHONEOUT      SOUND_MASK_PHONEOUT       Uscita livello fono
       SOUND_MIXER_VIDEO         SOUND_MASK_VIDEO          Ingresso audio per video/TV
       SOUND_MIXER_RADIO         SOUND_MASK_RADIO          Ingresso radio
       SOUND_MIXER_MONITOR       SOUND_MASK_MONITOR        Volume monitor (di solito
                                                           il microfono)

   ā€¢ le macro SOUND_DEVICE_LABELS e SOUND_DEVICE_NAMES risultano di con-
     seguenza arricchite rispettivamente delle etichette e dei nomi da linea di
     comando dei nuovi canali:

      #define SOUND_DEVICE_LABELS        {"Vol ", "Bass ", "Trebl", "Synth", 
                                          "Pcm ", "Spkr ", "Line ", "Mic ", 
                                          "CD   ", "Mix ", "Pcm2 ", "Rec ", 
                                          "IGain", "OGain", "Line1", "Line2", 
                                          "Line3", "Digital1", "Digital2", 
                                          "Digital3", "PhoneIn", "PhoneOut", 
                                          "Video", "Radio", "Monitor"}

      #define SOUND_DEVICE_NAMES         {"vol", "bass", "treble", "synth", 
                                          "pcm", "speaker", "line", "mic", 
                                          "cd", "mix", "pcm2", "rec", "igain", 
                                          "ogain", "line1", "line2", "line3", 
                                          "dig1", "dig2", "dig3", "phin", 
                                          "phout", "video", "radio", "monitor"}

   ā€¢ ` stata modiļ¬cata mixer_info; la sua nuova struttura ` la seguente:
     e                                                    e

      char id[16 ] identiļ¬catore della scheda audio (in genere un paio di caratteri)
      char name[32 ] nome per esteso della scheda
      int modify counter numero di modiļ¬che
      int ļ¬llers[10 ] ā€œriempitiviā€ per evoluzioni future

                                        30
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System
Il Linux OpenSound System

More Related Content

What's hot

Inoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxInoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linux
Ce.Se.N.A. Security
Ā 
Il tutorial di Python
Il tutorial di PythonIl tutorial di Python
Il tutorial di Python
AmmLibera AL
Ā 
Joseki : un server per interrogare risorse RDF attraverso un interfaccia Web
Joseki : un server per interrogare risorse RDF attraverso un interfaccia WebJoseki : un server per interrogare risorse RDF attraverso un interfaccia Web
Joseki : un server per interrogare risorse RDF attraverso un interfaccia Web
Cyclope86
Ā 
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
maaske
Ā 
domenicoCaputiTriennale
domenicoCaputiTriennaledomenicoCaputiTriennale
domenicoCaputiTriennale
Domenico Caputi
Ā 
Monitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di MarkovMonitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di Markov
rkjp
Ā 

What's hot (20)

Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientaleInterfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Ā 
MARKETING ED ECOMMERCE NELLā€™EDITORIA: IL CASO TRADING LIBRARY
MARKETING ED ECOMMERCE NELLā€™EDITORIA: IL CASO TRADING LIBRARYMARKETING ED ECOMMERCE NELLā€™EDITORIA: IL CASO TRADING LIBRARY
MARKETING ED ECOMMERCE NELLā€™EDITORIA: IL CASO TRADING LIBRARY
Ā 
A.Dionisi Thesis
A.Dionisi ThesisA.Dionisi Thesis
A.Dionisi Thesis
Ā 
Inoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxInoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linux
Ā 
Il tutorial di Python
Il tutorial di PythonIl tutorial di Python
Il tutorial di Python
Ā 
Brother
BrotherBrother
Brother
Ā 
Tesiandroid
TesiandroidTesiandroid
Tesiandroid
Ā 
Joseki : un server per interrogare risorse RDF attraverso un interfaccia Web
Joseki : un server per interrogare risorse RDF attraverso un interfaccia WebJoseki : un server per interrogare risorse RDF attraverso un interfaccia Web
Joseki : un server per interrogare risorse RDF attraverso un interfaccia Web
Ā 
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
Ā 
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Ā 
Dv100
Dv100Dv100
Dv100
Ā 
Banovaz Diego - Tesi
Banovaz Diego - TesiBanovaz Diego - Tesi
Banovaz Diego - Tesi
Ā 
domenicoCaputiTriennale
domenicoCaputiTriennaledomenicoCaputiTriennale
domenicoCaputiTriennale
Ā 
Profilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiProfilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzati
Ā 
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Ā 
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Ā 
Monitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di MarkovMonitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di Markov
Ā 
Montalti - "Interactive Musical Agents" (2010, paper ITA)
Montalti - "Interactive Musical Agents" (2010, paper ITA)Montalti - "Interactive Musical Agents" (2010, paper ITA)
Montalti - "Interactive Musical Agents" (2010, paper ITA)
Ā 
Tesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGPTesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGP
Ā 
Esercizi di programmazione in C (v. 2.01)
Esercizi di programmazione in C (v. 2.01)Esercizi di programmazione in C (v. 2.01)
Esercizi di programmazione in C (v. 2.01)
Ā 

Viewers also liked (10)

Tv Video Formats
Tv Video FormatsTv Video Formats
Tv Video Formats
Ā 
I formati audio (slide)
I formati audio (slide)I formati audio (slide)
I formati audio (slide)
Ā 
L'Ć udio digital
L'Ć udio digitalL'Ć udio digital
L'Ć udio digital
Ā 
I cavi audio
I cavi audioI cavi audio
I cavi audio
Ā 
MPEG4 AVC-H.264
MPEG4 AVC-H.264MPEG4 AVC-H.264
MPEG4 AVC-H.264
Ā 
Esempio di storyboard
Esempio di storyboardEsempio di storyboard
Esempio di storyboard
Ā 
Video Digitale - Acquisizione e Manipolazione
Video Digitale - Acquisizione e ManipolazioneVideo Digitale - Acquisizione e Manipolazione
Video Digitale - Acquisizione e Manipolazione
Ā 
Pragmatic Introduction to writing a Business Plan
Pragmatic Introduction to writing a Business PlanPragmatic Introduction to writing a Business Plan
Pragmatic Introduction to writing a Business Plan
Ā 
Le codifiche audio percettive
Le codifiche audio percettiveLe codifiche audio percettive
Le codifiche audio percettive
Ā 
Slide formati video
Slide formati videoSlide formati video
Slide formati video
Ā 

Similar to Il Linux OpenSound System

Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Francesco De Giorgi
Ā 
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
guest85785c7
Ā 
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
danielenicassio
Ā 
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Myrteza Kertusha
Ā 
Andrea_Gangemi_tesi
Andrea_Gangemi_tesiAndrea_Gangemi_tesi
Andrea_Gangemi_tesi
Andrea Gangemi
Ā 

Similar to Il Linux OpenSound System (16)

Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques
Ā 
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Ā 
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Ā 
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Ā 
Sviluppo di un sistema per il monitoraggio ambientale basato su reti di senso...
Sviluppo di un sistema per il monitoraggio ambientale basato su reti di senso...Sviluppo di un sistema per il monitoraggio ambientale basato su reti di senso...
Sviluppo di un sistema per il monitoraggio ambientale basato su reti di senso...
Ā 
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Ā 
Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilitĆ 
Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilitĆ Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilitĆ 
Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilitĆ 
Ā 
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Ā 
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Ā 
Andrea_Gangemi_tesi
Andrea_Gangemi_tesiAndrea_Gangemi_tesi
Andrea_Gangemi_tesi
Ā 
My Thesis
My ThesisMy Thesis
My Thesis
Ā 
Sat howto
Sat howtoSat howto
Sat howto
Ā 
Tesi
TesiTesi
Tesi
Ā 
Pattern Recognition Lecture Notes
Pattern Recognition Lecture NotesPattern Recognition Lecture Notes
Pattern Recognition Lecture Notes
Ā 
Thesis marco de_marco
Thesis marco de_marcoThesis marco de_marco
Thesis marco de_marco
Ā 
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Ā 

Il Linux OpenSound System

  • 1. IL LINUX OPEN SOUND SYSTEM ANTONIO TRINGALI maggio 1999
  • 2. ii
  • 3. Indice 1 LA SCHEDA AUDIO E OSS 4 1.1 Modello della scheda audio . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Lā€™interfaccia di programmazione di OSS . . . . . . . . . . . . . . 6 1.3 Inizializzazione di OSS . . . . . . . . . . . . . . . . . . . . . . . . 9 1.3.1 Gestione degli errori . . . . . . . . . . . . . . . . . . . . . 10 1.3.2 Lā€™exit handler . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3.3 Il signal handler . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4 Scrittura di codice portabile . . . . . . . . . . . . . . . . . . . . . 14 1.5 Anatomia del driver . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5.1 Scrittura sul buļ¬€er DMA . . . . . . . . . . . . . . . . . . . 17 1.5.2 Lettura dal buļ¬€er DMA . . . . . . . . . . . . . . . . . . . 18 1.6 Schede audio ISA e PCI . . . . . . . . . . . . . . . . . . . . . . . 19 1.7 File system e device ļ¬le . . . . . . . . . . . . . . . . . . . . . . . . 20 1.8 Le versioni di OSS . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2 IL MIXER E LA GESTIONE DEI CANALI 23 2.1 Descrizione di /dev/mixer . . . . . . . . . . . . . . . . . . . . . . 23 2.2 I canali del mixer . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.2.1 Lettura della conļ¬gurazione . . . . . . . . . . . . . . . . . 26 2.2.2 Selezione del canale da campionare . . . . . . . . . . . . . 27 2.3 Livelli di volume dei canali . . . . . . . . . . . . . . . . . . . . . . 28 2.4 Dipendenza dallā€™hardware . . . . . . . . . . . . . . . . . . . . . . 29 2.5 Nuove caratteristiche . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.6 Esempio di programma . . . . . . . . . . . . . . . . . . . . . . . . 31 3 CAMPIONAMENTO E RIPRODUZIONE 36 3.1 I device ļ¬le audio . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.2 Il buļ¬€er audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.3 Parametri di campionamento . . . . . . . . . . . . . . . . . . . . . 37 3.3.1 Reset dei parametri . . . . . . . . . . . . . . . . . . . . . . 38 3.3.2 Pause nelle operazioni . . . . . . . . . . . . . . . . . . . . 39 3.4 Il campionamento . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.5 La riproduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.6 Il formato audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 iii
  • 4. 3.6.1 Little e big endian . . . . . . . . . . . . . . . . . . . . . . 42 3.6.2 La codiļ¬ca lineare . . . . . . . . . . . . . . . . . . . . . . 43 3.7 Il tempo reale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.7.1 Le capacit` del driver . . . . . a . . . . . . . . . . . . . . . . 45 3.7.2 Gestione del buļ¬€er DMA . . . . . . . . . . . . . . . . . . . 46 3.7.3 I/O non bloccante . . . . . . . . . . . . . . . . . . . . . . 48 3.7.4 La sincronizzazione . . . . . . . . . . . . . . . . . . . . . . 52 3.7.5 Accesso diretto al buļ¬€er DMA . . . . . . . . . . . . . . . . 53 3.8 Il full duplex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.9 Uso di coprocessori . . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.10 Nuove caratteristiche . . . . . . . . . . . . . . . . . . . . . . . . . 58 3.11 Esempio di programma . . . . . . . . . . . . . . . . . . . . . . . . 59 4 SINTETIZZATORI E MIDI 64 4.1 I device ļ¬le del sequencer . . . . . . . . . . . . . . . . . . . . . . . 64 4.1.1 I chip sintetizzatori . . . . . . . . . . . . . . . . . . . . . . 65 4.1.2 I sintetizzatori MIDI . . . . . . . . . . . . . . . . . . . . . 66 4.2 Il buļ¬€er degli eventi . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.3 Lettura della conļ¬gurazione . . . . . . . . . . . . . . . . . . . . . 69 4.3.1 Parametri generali . . . . . . . . . . . . . . . . . . . . . . 70 4.3.2 Le porte MIDI . . . . . . . . . . . . . . . . . . . . . . . . 71 4.4 Predisposizione dei chip sintetizzatori . . . . . . . . . . . . . . . . 72 4.4.1 Caricamento degli algoritmi FM . . . . . . . . . . . . . . . 73 4.4.2 Caricamento delle patch wavetable . . . . . . . . . . . . . 76 4.4.3 Caricamento delle sysex patch . . . . . . . . . . . . . . . . 81 4.5 La temporizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4.5.1 La sincronizzazione per /dev/music . . . . . . . . . . . . . 83 4.5.2 La sincronizzazione per /dev/sequencer . . . . . . . . . . . 85 4.6 Output degli eventi . . . . . . . . . . . . . . . . . . . . . . . . . . 86 4.6.1 Messaggi di canale . . . . . . . . . . . . . . . . . . . . . . 86 4.6.2 Messaggi di sistema . . . . . . . . . . . . . . . . . . . . . . 89 4.6.3 Controllo della coda degli eventi . . . . . . . . . . . . . . . 91 4.7 Formato degli eventi . . . . . . . . . . . . . . . . . . . . . . . . . 92 4.8 Input degli eventi . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 4.8.1 Eventi per /dev/music . . . . . . . . . . . . . . . . . . . . 95 4.8.2 Eventi per /dev/sequencer . . . . . . . . . . . . . . . . . . 97 4.9 Nuove caratteristiche . . . . . . . . . . . . . . . . . . . . . . . . . 97 4.9.1 SoftOSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 4.9.2 OSSlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 4.10 Esempio di programma . . . . . . . . . . . . . . . . . . . . . . . . 102 iv
  • 5. 5 IL MIDI A BASSO LIVELLO 106 5.1 Descrizione dei device ļ¬le MIDI . . . . . . . . . . . . . . . . . . . 106 5.2 Lettura dalla porta MIDI . . . . . . . . . . . . . . . . . . . . . . . 107 5.3 Scrittura sulla porta MIDI . . . . . . . . . . . . . . . . . . . . . . 109 5.4 Programmazione della MPUā€“401 . . . . . . . . . . . . . . . . . . 109 5.5 Esempio di programma . . . . . . . . . . . . . . . . . . . . . . . . 110 A GENERAL MIDI 121 A.1 Timbri strumentali . . . . . . . . . . . . . . . . . . . . . . . . . . 121 A.2 Timbri delle percussioni . . . . . . . . . . . . . . . . . . . . . . . 125 1
  • 6. Sommario Questo lavoro si propone come tutorial per la programmazione della scheda audio tramite lā€™Open Sound System (OSS) per il sistema operativo Linux, ponendo particolare enfasi sulle strategie di programmazione pi` opportune per la sintesi u audio in tempo reale. Capitolo 1 Si introduce un modello ā€œmedioā€ delle varie schede audio presenti sul mercato; dopo sono descritte la visione orientata a UNIX che ne ha OSS (in particolare alla ļ¬ne descrivendo il funzionamento interno del driver), la sua inizializzazione e la gestione delle uscite da programma e dei segnali in un ambiente multiutente e multiprogrammato, con qualche riferimento alla scrittura di programmi portabili Capitolo 2 Il mixer gestisce i canali di ingresso/uscita facenti capo alla scheda audio; ` spiegato come scoprire le capacit` di questā€™ultima, selezionare i e a canali e regolare i livelli di volume per campionamento e riproduzione ` Capitolo 3 E spiegato come campionare da un qualsiasi canale del mixer e ripro- durre i campioni sintetizzati o immagazzinati su un ļ¬le, eventualmente in maniera non bloccante Capitolo 4 Ci si occupa della programmazione ad alto livello, cio` in maniera e indipendente dai dispositivi, del chip sintetizzatore interno alla scheda audio e delle porte MIDI Capitolo 5 Si tratta della programmazione MIDI a basso livello, cio` a livello e di I/O di byte dei messaggi ` Appendice A E riportata una tabella di corrispondenza fra i preset timbrici deļ¬niti nello standard General MIDI level 1 e i nomi delle patch wavetable per la Gravis UltraSound
  • 7. INTRODUZIONE ALLā€™OPEN SOUND SYSTEM Allā€™inizio degli anni ā€™90 Hannu Savolainen scrisse la prima versione di un driver per la scheda audio Sound Blaster 1.5 sotto Minixā€“386; nel 1992 ne fece il porting sotto Linux: era nato il Linux Sound Driver (LSD). Al crescere del numero di versione e delle funzionalit` implementate, nonchĀ“ a e allā€™aumentare del numero di porting ad altre variet` di UNIX, il driver cambi` a o il nome in VoxWare; sfortunatamente era omonimo della VoxWare Incorporat- ed, quindi per problemi di copyright per un certo periodo rest` il Temporarily o Anonymous Sound Driver (TASD). Poco dopo la 4Front Technologies, con la collaborazione dello stesso Hannu Savolainen, svilupp` lā€™Unix Sound System (USS), avente qualche caratteristica in o pi` rispetto al driver freeware e un maggior numero di schede audio supportate; u lo stesso Savolainen continuava indipendentemente a sviluppare il driver freeware (il cui codice sorgente era diļ¬€erente da quello di USS), noto ora come USS/Lite. In ossequio a POSIX e alla gran variet` di sistemi di tipo UNIX al quale ` a e stato portato, il nome ` cambiato nuovamente e il driver ` commercializzato dalla e e 4Front Technologies come Open Sound System, mentre nella versione freeware ` noto come OSS/Free. Di questo Savolainen non mantiene pi` il codice: la e u responsabilit` ` passata a Alan Cox dagli inizi del 1998. ae Dā€™ora in poi ci si riferir` a questi driver globalmente come OSS, sottinten- a dendo che ci` che sar` detto vale per entrambi (evidenziando, ove necessario, o a le diļ¬€erenze); la versione assunta come ā€œriferimentoā€ ` la 3.5.4. A seguire dal e Capitolo 2, la penultima Sezione di ogni Capitolo elenca le diļ¬€erenze di program- mazione introdotte dalla versione 3.6 in poi e lā€™ultima Sezione ospita un breve programma di esempio in C che illustra le caratteristiche di OSS introdotte nel Capitolo stesso. Delle chiamate alla libreria di OSS elencate in soundcard.h, si ` scelto di riportare solo quelle pienamente supportate. e OSS ` in pratica il primo tentativo di uniļ¬care lā€™architettura di audio digitale e per UNIX: alle capacit` di campionamento e riproduzione (piuttosto articolate a rispetto a quanto prima disponibile per questo ambiente) sono aļ¬ƒancate le possi- bilit` del MIDI, con il supporto dellā€™audio sincronizzato alla riproduzione video. a ` E allo stato attuale un insieme modulare di device driver che garantiscono unā€™in- terfaccia di programmazione uniforme e compatibile a livello di codice sorgente per tutte le piattaforme su cui ` stato portato, tanto che per queste ` valido la e e quasi totalit` di ci` che ` scritto nel seguito di questo lavoro. a o e Una panoramica generica delle caratteristiche supportate sia dallā€™OSS com- merciale (OSS/Linux) che da OSS/Free ` la seguente: e ā€¢ supporto di vari formati audio per i campioni (8 e 16 bit signed e unsigned, 8 bit Āµā€“Law e A-Law, IMAā€“ADPCM) ā€¢ supporto di canali stereo e mono ā€¢ frequenze di campionamento comprese tra 4kHz e 48kHz 2
  • 8. ā€¢ supporto half e full duplex (con apposite schede audio) ā€¢ possibilit` di accesso diretto al buļ¬€er audio DMA (per applicazioni con a richieste temporali pi` stringenti, come i giochi) u ā€¢ possibilit` di accesso indipendente dallā€™hardware a MIDI e a sintetizzatori a FM o wavetable sulla scheda audio ā€¢ caricamento delle patch in maniera indipendente dallā€™hardware ā€¢ supporto per SMPTE/MTC ā€¢ supporto per UART di tipo MPā€“401, Sound Blaster MIDI e XG MIDI ā€¢ supporto di IBM/Motorola PowerPC (bus ISA e PCI), 386/486/Pentium (bus ISA, EISA e PCI), Sun SPARC e DEC Alpha/AXP (bus ISA e PCI) Rispetto a OSS/Free, OSS/Linux ha in pi` le seguenti caratteristiche: u ā€¢ supporto diretto dello standard PnP (senza dover inizializzare precedente- mente le schede con il comando isapnp) ā€¢ supporto di un maggior numero di schede audio ā€¢ non si deve ricompilare il kernel ad ogni cambio di conļ¬gurazione o driver (questo ` un modulo separato) e ā€¢ supporto delle schede Sound Blaster 16/32/64/AWE in full duplex ā€¢ supporto delle patch wavetable Eā€“mu SoundFont 2.0 ā€¢ librerie DirectAudio per lā€™accesso diretto ai chip sintetizzatori FM e alle porte MIDI si ` scelto di non trattare gli ultimi due punti, in quanto di interesse marginale e per la sintesi in tempo reale. CONVENZIONI TIPOGRAFICHE Per tutto il testo sono seguite per le parole le seguenti convenzioni: corsivo indica una sigla o un termine tecnico rilevante introdotto per la prima volta neretto indica un identiļ¬catore o una variabile (con speciļ¬cato il tipo) per lā€™interfaccia di programmazione di OSS o di Linux spaziatura fissa indica una parola chiave appartenente alla libreria di OSS o codice sorgente di esempio; se le parole sono contenute tra parentesi an- golate, come ad esempio per <valore>, si intende che il programmatore debba sostituirvi un adeguato valore numerico 3
  • 9. Capitolo 1 LA SCHEDA AUDIO E OSS 1.1 Modello della scheda audio Una scheda audio ha diverse funzioni: converte i suoni immagazzinati nel sistema (ad esempio, su ļ¬le) dalla forma digitale allā€™analogica aļ¬ƒnchĀ“ li si possa udire e o registrare, converte da opportuni canali di ingresso (Lineā€“In1 , microfono, CD audio) i segnali da analogico a digitale aļ¬ƒnchĀ“ possano essere immagazzinati o e manipolati dal computer, pu` consentire essa stessa di creare nuovi suoni tramite o eventuali sintetizzatori interni. Secondo le speciļ¬che MPC2 deve anche essere dotata di una porta MIDI perchĀ“ e il computer possa controllare strumenti musicali o sintetizzatori esterni con tali capacit`, invece di generare da sĀ“ i suoni. Il PC diventa in pratica un sequencer, a e cio` un direttore dā€™orchestra allo stato solido; virtualmente non ` pi` di una e e u memoria e un sistema di messaggi dalla e alla strumentistica, con capacit` di a editing. Lā€™OSS cerca di oļ¬€rire una visione idealizzata della scheda audio al program- matore, nascondendo le diļ¬€erenze tecniche fra le varie schede presenti sul mercato; essa pu` essere vista come un mixer, di cui il programmatore (il Disc Jockey) ha o possibilit` di controllare ogni canale3 . a Per la riproduzione (conversione D/A) la sorgente ` da ļ¬le (brano digitaliz- e zato o MIDI) o i campioni sono creati con un opportuno algoritmo di sintesi, da CD audio4 (il segnale ` semplicemente spedito alla sezione analogica della scheda e 1` E un ingresso con livelli simili a quelli dā€™ingresso per un ampliļ¬catore HIā€“FI, utile per campionare il segnale proveniente da un registratore analogico o da un CD player esterni 2 Speciļ¬che rilasciate da Microsoft e Intel nel 1991 per deļ¬nire una conļ¬gurazione hardware minima aļ¬ƒnchĀ“ un computer potesse essere deļ¬nito ā€œmultimedialeā€: si doveva cio` disporre e e almeno di un PC 386SX/16MHz con 4MB di RAM e 40MB di hard disk, una VGA a colori, un mouse, una scheda audio e un CDā€“ROM player 3 Indipendentemente o meno dagli altri; relativamente alle capacit` della scheda audio stessa, a con il programmatore che pu` interrogare OSS sulle capacit` di questā€™ultima o a 4 Non ` presa in considerazione la programmazione del drive CD in questo tutorial, solo come e si fa a campionare o riprodurre il segnale che ` presente sullā€™eventuale canale CD Audio In della e scheda audio 4
  • 10. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.1. MODELLO DELLA SCHEDA AUDIO audio senza che sia stato campionato prima), da Lineā€“In e da microfono. In cam- pionamento (conversione A/D) si pu` acquisire dagli ingressi CD Audio, Lineā€“In o e microfono o si possono acquisire eventi MIDI. La coppia di convertitori A/D e D/A viene spesso chiamata PCM, DSP, CODEC o ADC/DAC ; nella Tabella seguente sono elencate le massime frequenze di campionamento5 per le varie generazioni di schede audio che OSS supporta (la minima ` sempre intorno ai 5 kHz); la fc ` generata dividendo lā€™alta frequenza di e e un oscillatore di riferimento, per cui non ` possibile ottenere tutte le frequenze e dellā€™intervallo: le diļ¬€erenze di qualche percento dovrebbero essere ignorate perchĀ“ e solitamente non avvertibili (OSS cerca di ottenere dalla scheda audio la frequenza pi` vicina a quella richiesta). La risoluzione di campionamento pu` essere di 8 o u o 16 bit, in mono o stereo. Generazione Max fc Note 1a 22.05 kHz in riproduzione 11.025 kHz in campionamento 2a 44.1 kHz mono 22.05 kHz stereo 3a 44.1 kHz qualit` audio CD a 48 kHz qualit` DAT a 4a 96 kHz Ultra Hiā€“Fi Oltre alle succitate possibilit` di sintesi FM6 e di gestione dei dispositivi MI- a DI, alcune schede consentono la wavetable synthesis e la possibilit` di caricare a campioni di uno strumento (patch) in una speciale memoria della scheda stessa. In ļ¬gura 1.1 ` evidenziata la visione che possiamo dare della nostra scheda e audio idealizzata come output mixer per quanto riguarda la riproduzione, che ben si conf` alle caratteristiche pi` comuni riscontrabili nelle schede audio attualmente a u presenti sul mercato (1999). In ļ¬gura 1.2 ` invece schematizzato lā€™input mixer a e cui fare riferimento per quanto riguarda il campionamento. Infatti dentro una scheda audio possono esserci realmente due mixer che gestis- cono separatamente i casi di campionamento e riproduzione, ma OSS gestisce automaticamente il passaggio dallā€™uno allā€™altro in base ai comandi del program- matore di lettura o scrittura dalla/alla scheda audio. In particolare, se tali attivit` a sono implementate dalla scheda audio come mutuamente esclusive ` deļ¬nita half e duplex, mentre ` deļ¬nita full duplex se possono aver luogo contemporaneamente. e 5 Alcune vecchie schede permettono di scegliere solo fra frequenze di campionamento ļ¬sse: 11025 Hz, 22050 Hz, 32000 Hz e 44100 Hz 6` E sfruttata la tecnica degli operatori per produrre pi` voci: i chip ā€œclassiciā€ sono lo Yamaha u OPLā€“2 (a due operatori, nove voci con timbri non realistici) e OPLā€“3 (a quattro operatori, diciotto voci): aumentando il numero di operatori per voce migliora la qualit` della sintesi a 5
  • 11. 1.2. Lā€™INTERFACCIA DI PROGRAMMAZIONE DI OSS CAPITOLO 1. LA SCHEDA AUDIO E OSS Memoria del computer o Hard-Disk LINE-OUT ALTOPARLANTI L R L R L R L R L R L R L R STEREO MONO STEREO MONO TREBLE BASS RECORD CD Audio LINE-IN MIC MASTER DAT CD Audio LINE-IN MIC MIDI ON/OFF VOLUME ON/OFF ON/OFF ON/OFF MIDI ON/OFF VOLUME ON/OFF ON/OFF ON/OFF ON/OFF Figura 1.1: Modello come mixer della Figura 1.2: Modello come mixer scheda audio in riproduzione della scheda audio in campiona- mento 1.2 Lā€™interfaccia di programmazione di OSS Per gestire il ā€œmixer virtualeā€ delle ļ¬gure 1.1 e 1.2 OSS sfrutta la visione orientata al ļ¬leā€“system che Linux ha di ogni device 7 . I canali del mixer, campionamento e riproduzione possono quindi essere gestiti manipolando degli speciali ļ¬le che si trovano nella directory /dev tramite le primitive di sistema open(), ioctl(), read(), write() e close(). In ļ¬gura 1.3 sono evidenziati i device ļ¬le relativi alla manipolazione dei vari canali per la riproduzione, mentre in ļ¬gura 1.4 cā€™` lo schema equivalente per il e campionamento. Questā€™organizzazione ` conveniente, poichĀ“ in tal modo sono schermate sia le e e complessit` dellā€™hardware e del software sottostante (la scheda audio, ma anche a la gestione del DMA, della memoria virtuale e del multitasking), sia le diversit` a fra le varie schede audio in commercio. Si pu` ora procedere alla descrizione di ogni device ļ¬le: o /dev/mixer Questa ` lā€™interfaccia di accesso alle funzioni del mixer e pu` e o essere un link simbolico a /dev/mixer0; se ` presente un secondo mixer, ci e si riferisce ad esso come /dev/mixer1 /dev/dsp Identiļ¬ca il DSP della scheda (per default con codiļ¬ca lineare 8 bit unsigned) e pu` essere un link simbolico a /dev/dsp0; in genere ` presente o e 7` E unā€™interfaccia a un dispositivo hardware (dischi, linee seriali, etc.) o a ā€œentit`ā€ a cui a non corrisponde un vero e proprio dispositivo hardware (memoria di sistema, kernel, etc.); a un device ļ¬sico ā€” come la scheda audio ā€” corrisponde un device driver ā€” come OSS ā€” che ha il compito di pilotarlo 6
  • 12. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.2. Lā€™INTERFACCIA DI PROGRAMMAZIONE DI OSS = Link simbolico OSS driver OSS driver Memoria del computer o Hard-Disk /dev/dsp /dev/dsp0 /dev/dsp1 MIDI in /dev/dsp /dev/dspW /dev/dspW0 /dev/dspW MIDI file (out) /dev/dspW1 /dev/audio /dev/audio /dev/audio0 CD Audio /dev/music /dev/audio1 /dev/sequencer CD Audio /dev/midi00 Memoria del computer /dev/midi01 o Hard-Disk /dev/sndstat /dev/sndstat /dev/midi02 /dev/sndproc Line-In /dev/music /dev/sndproc /dev/midi03 Line-In /dev/sequencer /dev/midi00 /dev/midi01 MIXER MIXER /dev/midi02 /dev/midi03 Mic Mic /dev/mixer /dev/mixer0 /dev/mixer /dev/mixer0 /dev/mixer1 /dev/mixer1 Figura 1.3: Visione della scheda au- Figura 1.4: Visione della scheda dio in riproduzione che OSS d` al audio in campionamento che OSS a programmatore d` al programmatore a anche /dev/dsp1, che pu` identiļ¬care un secondo DSP o lo stesso con una o diversa funzione /dev/dspW Se presente (dipende dalla versione di OSS), si riferisce al DSP con codiļ¬ca lineare 16 bit signed e little endian8 ; pu` essere un link simbolico o a /dev/dspW0 ed eventualmente ` presente anche /dev/dspW1 e ` /dev/audio E presente per limitata compatibilit` con le workstation Sun (non a sono supportati cambiamenti da 8 kHz/mono/8 bit) e utilizza la codiļ¬ca Āµā€“Law9 ; ` disponibile in mutua esclusione con /dev/dsp e generalmente ` e e un link a /dev/audio0, potendo essere presente anche /dev/audio1 /dev/music Permette di accedere al sintetizzatore interno alla scheda audio e alle porte MIDI in maniera indipendente dal dispositivo (sono trattati allo stesso modo dal punto di vista dellā€™interfaccia di programmazione), con modalit` di temporizzazione piuttosto articolate; pu` essere presente il link a o simbolico ad esso /dev/sequencer2 (obsoleto) ` /dev/sequencer E un device ļ¬le a pi` basso livello di /dev/music, rispetto al u quale ha capacit` limitate di temporizzazione, sincronizzazione e gestione a automatica del chip sintetizzatore interno alla scheda audio 8 Little endian e big endian si riferiscono a come sono conservati i campioni in memoria dalla CPU: per il primo lā€™indirizzo del dato corrisponde allā€™indirizzo del byte meno signiļ¬cativo (Intel, Alpha), per il secondo al byte pi` signiļ¬cativo (Motorola, Sparc, PowerPC, HPā€“PA) u 9 Un campione a 12 o 16 bit ` compresso logaritmicamente a 8 bit: OSS in riproduzione e non eļ¬€ettua lā€™operazione opposta, ma converte in un campione a 8 bit lineare prima di inviare al device audio (sono introdotti un overhead per il calcolo e della distorsione); ` un formato e derivante dalla tecnologia telefonica digitale 7
  • 13. 1.2. Lā€™INTERFACCIA DI PROGRAMMAZIONE DI OSS CAPITOLO 1. LA SCHEDA AUDIO E OSS ` /dev/midi00 E unā€™interfaccia a basso livello al canale MIDI, orientata ai carat- teri come tty (raw mode) e indirizzata ad applicazioni che non richiedono una sincronizzazione in tempo reale come i sequencer (pu` essere usata o per inviare sysex, per caricare campioni sugli strumenti o per eļ¬€ettuare il dump dei canali); se presenti, possono essere gestite altre porte MIDI con /dev/midi01, /dev/midi02 e /dev/midi03 /dev/sndproc Rappresenta lā€™interfaccia interna di accesso a un eventuale co- processore presente sulla scheda audio; pu` essere una soluzione tempo- o ranea, da eliminare in seguito /dev/sndstat Questo, a diļ¬€erenza degli altri, ` un device ļ¬le a sola lettura: e stampa informazioni diagnostiche riguardo la conļ¬gurazione di OSS in for- ma leggibile agli umani, ma se ne sconsiglia lā€™utilizzo da parte dei programmi perch` in futuro il formato delle informazioni da esso fornite potrebbe cam- e biare; non ci si far` pi` riferimento dā€™ora in poi. Lā€™output ha una sezione a u per ogni categoria di dispositivi, e questi sono numerati nellā€™ordine in cui il driver li inizializza (che non ` ļ¬sso, per cui ` meglio non fare assunzioni a e e priori); un esempio del suo utilizzo ` il seguente: e ~>cat /dev/sndstat Sound Driver:3.5.4-960630 Kernel: Linux papo 2.0.32 #1 Wed Nov 19 00:46:45 EST 1997 i486 Config options: 0 Installed drivers: Card config: Audio devices: 0: Sound Blaster 16 (4.13) Synth devices: 0: Yamaha OPL-3 Midi devices: Timers: 0: System clock Mixers: 0: Sound Blaster OSS consente di avere pi` schede audio installate nel computer, il che si u traduce in un maggior numero di device ļ¬le indirizzabili, elencati nellā€™output 8
  • 14. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.3. INIZIALIZZAZIONE DI OSS di /dev/sndstat: lā€™esempio sopra rivela che il computer ha solo /dev/dsp0, ma in generale con pi` DSP li si potrebbe indirizzare operando su /dev/dspn; u analogamente per il mixer su /dev/mixern, etc. 1.3 Inizializzazione di OSS Il minimo insieme di header ļ¬le da includere ` rappresentato da stdio.h (per le e funzioni di libreria tipo printf() e perror()), unistd.h, fcntl.h (per open(), ioctl(), read(), write() e close()) e sys/soundcard.h (le deļ¬nizioni vere e proprie per la libreria di OSS). Adesso si riporter` uno scheletro di codice C per lā€™apertura di un device ļ¬le di a OSS (nellā€™esempio ` /dev/dsp, ma potrebbe essere /dev/mixer, . . . ); nei succes- e sivi Capitoli lo si dar` come sottinteso man mano che si introducono le primitive a per una gestione vieppi` soļ¬sticata della scheda audio. u #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/soundcard.h> int main() { int dspfd; /* File descriptor per /dev/dsp */ dspfd = open("/dev/dsp", O_WRONLY); /* Apre il device */ if (dspfd == -1) { perror("/dev/dsp"); /* Gestione errore */ exit(-1); } /* Qui ci puoā€™ andare tutto il codice per sfruttare il */ /* device file, con le ioctl() necessarie a configurare */ /* il driver poste prima delle read() o write() */ close(dspfd); /* Chiusura del device file */ return 0; } Il secondo argomento di open() ` la modalit` di accesso al device ļ¬le, che nel e a caso di OSS pu` essere una fra le seguenti: o O RDONLY Accesso in sola lettura (read() o ioctl()) O WRONLY Accesso in sola scrittura (write() o ioctl()) O RDWR Accesso in lettura/scrittura (read(), write() o ioctl()) 9
  • 15. 1.3. INIZIALIZZAZIONE DI OSS CAPITOLO 1. LA SCHEDA AUDIO E OSS Per read() e write() i ļ¬‚ag O_NDELAY o O_NONBLOCK, aļ¬ƒnchĀ“ le operazioni di e I/O sul device ļ¬le non blocchino il processo chiamante, non hanno eļ¬€etto: se il processo eļ¬€ettua una read() e i campioni richiesti non sono ancora disponibili, questo viene messo in wait ļ¬nchĀ“ lā€™operazione ` completata (analogamente con e e una write(), se il buļ¬€er del driver non ha spazio suļ¬ƒciente per i campioni che si vogliono riprodurre). Per la open() il funzionamento ` sempre del tipo O_NDELAY; se fallisce il e ļ¬le descriptor ` posto uguale a -1 e la macro errno ` impostata a un oppor- e e tuno valore (questa ` messa a disposizione del programmatore per mezzo di e #include <errno.h>). 1.3.1 Gestione degli errori I codici di errore pi` comuni riportati da errno sono i seguenti: u ENOENT Il device ļ¬le che si ` tentato di aprire non ` presente in /dev e e ENODEV Esiste il device ļ¬le in /dev, ma il driver non ` stato caricato dal e kernel (si pu` controllare con cat /dev/sndstat o dmesg | more) o ENOSPC Esiste il device ļ¬le in /dev, ma il driver non ` stato in grado di e allocare la memoria per il buļ¬€er DMA tramite sound_mem_init() durante il boot del sistema; il modulo del driver dovrebbe essere uno dei primi ad esser caricato dal kernel, in modo da garantire tale operazione anche in caso di poca memoria installata ENXIO Esiste il device ļ¬le in /dev e il driver ` presente nel kernel, ma non e esiste il dispositivo hardware che si tenta di indirizzare (ad esempio, perchĀ“ e la conļ¬gurazione del driver non corrisponde allā€™hardware audio) EINVAL Uno degli argomenti della chiamata a una funzione non ha un valore valido EBADF Il ļ¬le descriptor non si riferisce a un device ļ¬le aperto, una read() ` e stata rivolta a un device ļ¬le aperto con O_WRONLY o una write() ` stata e rivolta a un device ļ¬le aperto con O_RDONLY EBUSY Solo un processo alla volta pu` gestire /dev/dspn e /dev/audion, per o cui si veriļ¬ca se un altro processo (anche appartenente allo stesso utente) tenta di accedervi (si veriļ¬ca anche se lā€™IRQ o il canale DMA sono occupati); pu` essere gestito dal programma tentando di riaprire il device ļ¬le che ha o causato lā€™errore dopo qualche tempo, ma non ` garantito che esso divenga e mai disponibile ` EINTR E ritornato da read() o write() qualora queste siano risultate bloccan- ti e durante lo stato di wait il processo utente abbia ricevuto un signal() 10
  • 16. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.3. INIZIALIZZAZIONE DI OSS EAGAIN La risorsa a cui si ` cercato di accedere ` temporaneamente non e e disponibile (ad esempio, si ` cercato di scrivere su un buļ¬€er pieno o leggere e da un buļ¬€er vuoto con il device ļ¬le aperto in O_NONBLOCK) EACCES Per i device /dev/dspn e /dev/audion lā€™accesso ` consentito solo al e root (a meno che il sistema sia stato conļ¬gurato in altro modo), e questo errore si veriļ¬ca se un utente normale cerca di accedere a tali device ļ¬le; questa ` una misura di sicurezza per impedire che, ad esempio, qualora il e computer sia connesso in rete e abbia un microfono qualcuno possa ascoltare remotamente le conversazioni che si svolgono nella stanza ove si trova il computer Un error handler un poā€™ pi` soļ¬sticato potrebbe rassomigliare a: u if ((dspfd = open("/dev/dsp2", O_WRONLY)) == -1) { switch (errno) { case ENOENT: perror("/dev/dsp2"); exit(-1); case EBUSY: close(dspfd); /* Aspetta un poā€™ per riaprire */ sleep(10); if (dspfd = open("/dev/dsp2", O_WRONLY)) == -1) { perror("/dev/dsp2"); exit(-1); } break; default: perror("Altro tipo di errore"); fprintf(stderr, "Errore numero: %dn", errno); exit(-1); } } Per quanto invece riguarda il seguito di questo lavoro, si demander` la gestione a degli errori a una semplice routine del tipo: void errore(const char *msgerr) { perror(msgerr); exit(-1); } Sarebbe corretto mettere un error handler non solo dopo una open(), ma an- che dopo read() o write() per veriļ¬care se siano stati letti o scritti il numero corretto di byte; tuttavia nella sintesi in tempo reale ci` tende a rappresentare o cicli di CPU sprecati. Invece dopo una ioctl() conviene controllare quasi ob- bligatoriamente il valore ritornato dal driver nellā€™ultimo dei suoi argomenti, per vedere cosa si riesce a ottenere rispetto a quanto richiesto dal programmatore. 11
  • 17. 1.3. INIZIALIZZAZIONE DI OSS CAPITOLO 1. LA SCHEDA AUDIO E OSS Un altro buon accorgimento di programmazione ` di installare un exit handler e e/o un signal handler subito dopo una open() riuscita: il primo pu` essere utile o 10 per operazioni di routine alla chiusura del programma (regolare o in seguito a exit()), il secondo pu` gestire i segnali impostati da altri processi, dal kernel o o dal processo stesso. Per una dettagliata descrizione di questi argomenti si veda [10]. 1.3.2 Lā€™exit handler Un exit handler richiede la funzione di libreria atexit(), disponibile in segui- to a #include <stdlib.h>. Essa registra le funzioni di tipo void f() date in argomento come exit handler (max 32), venendo richiamate nellā€™ordine inverso rispetto a quello con cui sono state registrate; atexit() restituisce 0 se la regis- trazione ` stata possibile, altrimenti -1 con errno==ENOMEM (memoria insuļ¬ƒciente e per aggiungere la funzione). Nellā€™esempio seguente si dimostra lā€™utilizzo di atexit() chiudendo un device ļ¬le allā€™uscita dal programma (anche se ci` non ` strettamente necessario per o e quanto prima aļ¬€ermato): #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/soundcard.h> int dspfd; /* Variabile globale */ void Messaggio() /* Chiamata per prima */ { puts("Premi <Invio> per chiudere /dev/dsp..."); getchar(); } void ChiudiTutto() /* Chiamata per ultima */ { close(dspfd); puts("Fine del programma"); } void errore(const char *msgerr) /* Gestione degli errori */ { perror(msgerr); 10 Linux svuota i buļ¬€er di I/O e chiude automaticamente i device ļ¬le rimasti eventualmente aperti prima che il processo termini, tramite librerie a livello utente o tramite kernel 12
  • 18. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.3. INIZIALIZZAZIONE DI OSS exit(-1); } int main() { if ((dspfd = open("/dev/dsp", O_RDONLY)) == -1) errore("/dev/dsp"); if (atexit(ChiudiTutto) == -1) /* Registrata per prima */ errore("ChiudiTutto()"); if (atexit(Messaggio) == -1) /* Registrata per ultima */ errore("Messaggio()"); return 0; /* Uscita dal programma */ } Lā€™exit handler ` richiamato in seguito ad exit(), abort()11 , return o alla e consegna di un segnale la cui azione di default ` di uccidere il processo; lā€™output e del programma sarebbe: Premi <Invio> per chiudere /dev/dsp... Fine del programma Per evitare la chiamata allā€™exit handler lo standard POSIX.1 (1990) prevede _exit(), che inoltre evita lo svuotamento dei buļ¬€er prima della chiusura dei ļ¬le. 1.3.3 Il signal handler Un signal handler funziona in modo molto simile ad un exit handler: previo #include <signal.h>, si usa la funzione di libreria signal() per registrare delle funzioni (non di libreria) che hanno il compito di reagire a segnali provenienti da altri processi o dallo stesso processo12 (rispettivamente generati tramite le funzioni di libreria kill() e raise()). In signum.h sono deļ¬niti una trentina di segnali che si conformano ad ANSI, POSIX, System V e BSD 4.2, per i quali esistono delle disposizioni di default (ci` equivale a signal(<segnale>, SIG_DFL)); se si vuole ignorare un partico- o lare segnale si pu` porre nel codice signal(<segnale>, SIG_IGN). La signal() o ritorna il valore precedente del signal handler o SIG_ERR se si veriļ¬ca un errore. 11 Viene impostato un segnale SIGABRT al processo chiamante: non ` ignorabile o bloccabile e da un signal handler 12 Un segnale ` deļ¬nibile come unā€™interruzione asincrona software nel ļ¬‚usso di un processo: e esso ` ā€œimpostatoā€ dal processo che lo genera ed ` ā€œconsegnatoā€ al processo che lo riceve; il e e modo in cui questā€™ultimo reagisce al segnale si chiama ā€œdisposizioneā€ 13
  • 19. 1.4. SCRITTURA DI CODICE PORTABILE CAPITOLO 1. LA SCHEDA AUDIO E OSS Per esempio, se si vuole che il processo reagisca a un segnale di interruzione (SIGINT) e a un segnale di terminazione del programma (SIGTERM) con una disposizione diversa dalla predeļ¬nita, allā€™inizio di main() si potr` porre: a signal(SIGINT, SignalHandler); /* Le funzioni possono essere */ signal(SIGTERM, SignalHandler); /* uguali o diverse */ ove SignalHandler ` una funzione del tipo: e void SignalHandler(int segnale) /* Il segnale invocante */ { /* eā€™ passato allā€™handler */ switch (segnale) { case SIGINT: case SIGTERM: puts("SIGINT o SIGTERM"); exit(0); default: } } il processo relativo termina se da shell di comando si digita kill -s SIGINT <PID> o kill -s SIGTERM <PID>, ove <PID> ` lā€™identiļ¬catore del processo (visualizz- e abile tramite il comando ps). Sono da tenere presenti i seguenti fatti: ā€¢ non possono essere variate le disposizioni di SIGKILL e SIGSTOP (signal() ritorna EINVAL) ā€¢ il comportamento di un programma ` indeļ¬nito se sono ignorati SIGFPE, e SIGILL o SIGSEGV ā€¢ ignorare il segnale derivante dalla divisione intera per zero ha un compor- tamento indeļ¬nito, che potrebbe condurre a un blocco del computer ā€¢ per certi segnali la disposizione di default implica la terminazione del pro- cesso e il salvataggio dellā€™area dati e heap in un ļ¬le core a ļ¬ni di debug; altri provocano la semplice terminazione del processo o sono ignorati ā€¢ a diļ¬€erenza di BSD, Linux non ridispone il signal handler a SIG_DFL dopo la consegna di un segnale Si veda man 7 signal per una dettagliata descrizione dei segnali e della loro disposizione di default, e in ogni caso [10] per una gestione pi` soļ¬sticata. u 1.4 Scrittura di codice portabile Di seguito sono elencati alcuni consigli per la scrittura di programmi che siano portabili sotto i vari sistemi operativi per cui sia stato portato anche OSS: 14
  • 20. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.4. SCRITTURA DI CODICE PORTABILE ā€¢ Come si vedr` nei successivi Capitoli, conviene usare delle speciļ¬che macro a per impostare dei parametri, ad esempio del mixer, tramite ioctl() (queste schermano i dettagli dellā€™implementazione dei parametri per le future ver- sioni del driver); in particolare bisognerebbe controllare se ` adeguato il e valore ritornato nellā€™ultimo argomento (per le chiamate che lo prevedono) ` ā€¢ E meglio riferirsi a un link simbolico per un device piuttosto che utilizzare un riferimento assoluto, ad esempio usando /dev/dsp al posto di /dev/dsp0; ci` d` ļ¬‚essibilit` allā€™utente per poter far puntare i link simbolici ad altri o a a device ļ¬le, se questi garantiscono migliori risultati (i programmi dovrebbero sfruttare i nomi ā€œveriā€ solo se resi facilmente conļ¬gurabili) ā€¢ Non bisogna sfruttare delle caratteristiche non documentate (in quanto obsolete ā€” scompariranno in futuro ā€” o non ancora ben testate) ā€¢ Lā€™appesantimento di un programma con caratteristiche al di fuori dellā€™essen- ziale o con ā€œtrucchiā€ pu` compromettere la compatibilit` del codice con le o a future versioni del driver ā€¢ Se si utilizza la risoluzione a 16 bit bisogna fare attenzione che la CPU memorizzi i campioni come il DSP della scheda audio, cio` coincida per e entrambi la codiļ¬ca big endian o little endian; in tal senso bisogna evitare di accedere ai campioni a 16 bit ciecamente come signed short ā€¢ Non bisogna ļ¬darsi delle impostazioni di default di un device (anche perch` e potrebbero essere state modiļ¬cate da un precedente processo); ad esempio, anche se il default per /dev/dsp ` 8 kHz/8 bit unsigned/mono, molte schede e non supportano la frequenza di campionamento di 8 kHz e si corre il rischio di ottenere solo rumore con le future schede audio a 24 bit; analogamente, non bisogna assumere per /dev/sequencer il clock di default di 100 Hz (Linux/Alpha ha un clock di 1024 Hz), mentre non ci sono valori di de- fault per /dev/music (bisogna sempre impostare per primi i parametri di temporizzazione) ā€¢ Non si devono scrivere programmi che funzionano solo a 16 bit, poichĀ“ molte e schede vecchie sono a 8 bit: campioni da 16 bit riprodotti su queste danno luogo solo a rumore ad alto volume ā€¢ Non si deve dare per scontato che per ogni scheda audio ci sia /dev/mixer (non lo possiedono le pi` vecchie, o quelle non ancora pienamente support- u ate, o le schede audio completamente digitali); non tutti i mixer hanno un controllo di master volume (ma se ce lā€™hanno bisogna tenere presente che questo inļ¬‚uenza il volume di tutti i canali), inoltre si deve sempre testare la presenza di un canale prima di cercare di indirizzarlo (ad esempio, non tutte le schede possiedono un sintetizzatore interno e/o una porta MIDI) 15
  • 21. 1.5. ANATOMIA DEL DRIVER CAPITOLO 1. LA SCHEDA AUDIO E OSS ā€¢ Non si deve usare il full duplex senza prima controllare che la scheda audio supporti tale modalit`a ā€¢ I device audio non devono essere tenuti aperti quando non sono richiesti, altrimenti altri programmi non vi possono accedere; in tal senso un pro- gramma dovrebbe gestire ļ¬‚essibilmente le situazioni di EBUSY, ad esempio riprovando ad accedere dopo qualche tempo al device ļ¬le 1.5 Anatomia del driver OSS sfrutta il Direct Memory Access (DMA) per trasferire i campioni dalla scheda audio a unā€™opportuna area di RAM e viceversa: questa in genere non coincide con il buļ¬€er del processo che li elabora, per cui il driver deve copiare i campioni dal/al buļ¬€er DMA a/da questā€™ultimo13 . Nei PCā€“compatibili della copia se ne occupa la CPU, dal momendo che il DMA Controller (DMAC) compatibile Intel 8237 ha dei pesanti limiti: non pu` o eļ¬€ettuare copie fra le porte di I/O o fra memoria e memoria; inoltre il buļ¬€er DMA deve risiedere al di sotto dei primi 16 MB di RAM per le schede audio ISA (non per le PCI), poichĀ“ questo ` il limite di indirizzamento del bus, e deve e e essere un blocco di memoria non frammentato che inizia e ļ¬nisce nella stessa pagina DMA. Questā€™ultima ha dimensione di 64 kB per i canali 0Ć·3 a 8 bit e 128 kB per i canali 5Ć·7 a 16 bit: ci` rende diļ¬ƒcile usare direttamente il buļ¬€er o locale del processo come buļ¬€er DMA con le schede ISA e pi` di 16 MB, poichĀ“ u e dovrebbe risiedere al di sotto del limite dei 16 MB; tuttavia i nuovi controller nelle periferiche bypassano lā€™Intel 8237 completamente (ļ¬‚yā€“by), per cui in particolari condizioni si pu` arrivare a mappare il buļ¬€er DMA allā€™interno dellā€™area dati del o processo (ci` ` sempre possibile con le schede PCI). oe Lā€™elaborazione dei campioni da parte del processo deve avvenire almeno un poā€™ pi` velocemente del ritmo al quale il DMAC trasferisce i campioni, aļ¬ƒnchĀ“ u e non ci siano pause in fase di campionamento o riproduzione. Se ci` si veriļ¬ca o bisogner` usare una frequenza di campionamento inferiore allā€™attuale, o usare un a formato audio pi` ā€œcompattoā€ per i campioni, in modo da ridurre la quantit` di u a byte trasferiti dal DMAC. Linux ha il ā€œproblemaā€ di essere multiutente e multiprogrammato, per cui i processi competono per lā€™utilizzo della CPU e un processo a pi` alta pri- u orit` potrebbe porre il processo che sfrutta i servizi di OSS in stato di wait a per diversi ms: in tal modo il tempo che questo ha per elaborare i campioni 13 Alcune schede possono autoā€“iniziare il trasferimento senza attendere risposta dal driver, usando il DMAC in modalit` autoā€“restart (ci` non ` supportato da tutti i sistemi operativi, ad a o e esempio da BSD) 16
  • 22. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.5. ANATOMIA DEL DRIVER diminuisce. In pratica ci deve essere abbastanza spazio nel buļ¬€er DMA per garantire lā€™operativit` per il tempo di wait14 . a OSS gestisce il buļ¬€er DMA con la tecnica del multiā€“buļ¬€ering: in pratica questo ` diviso in frammenti di uguale dimensione, per default calcolata dal driver e in modo tale che la latenza15 sia attorno a 0.5s per la riproduzione e attorno a 0.1s per il campionamento. In tal modo ` possibile aumentare la dimensione del buļ¬€er e senza inļ¬‚uire sulla latenza stessa poichĀ“ il DMAC lavora solo su un frammento e per volta, mentre lā€™applicazione legge o scrive sul resto del buļ¬€er. memoria wait Scheda audio Kernel Processo 1111 0000 DMAC 1111 0000 bus ISA o PCI OSS buffer audio driver read() o write() buffer DMA Figura 1.5: Schema di utilizzo del multiā€“buļ¬€ering 1.5.1 Scrittura sul buļ¬€er DMA In fase di riproduzione, quando il programma chiama write() per la prima volta dopo lā€™apertura del device, si veriļ¬cano i seguenti eventi: ā€¢ il driver programma la scheda audio con i parametri di campionamento predisposti (risoluzione, numero di canali e frequenza) ā€¢ di default ` calcolata la dimensione adeguata per un frammento, se tramite e unā€™opportuna chiamata ioctl() non se ne ` stabilita unā€™altra e ā€¢ viene iniziato il riempimento del primo frammento del buļ¬€er con i dati passati dalla write() ā€¢ se il primo frammento ` stato riempito completamente, il DMAC ne inizia e il trasferimento alla scheda audio 14 Alcune schede dispongono di RAM locale per la riproduzione, ma prima che questa possa avvenire i campioni devono esservi trasferiti (per la Gravis UltraSound ci sono 256 kB per canale, ovvero sono ā€œcopertiā€ 2.9 s di suono continuo in modalit` 16 bit/stereo/44.1 kHz) a 15 La latenza ` il tempo che il processo deve aspettare per avere accesso a un frammento e in campionamento o perchĀ“ questo venga suonato in riproduzione quando il buļ¬€er ` pieno; e e essa dipende dal data rate, che ` la quantit` di dati che il DMAC deve trasferire nellā€™unit` di e a a tempo (per esempio, con un campionamento 16 bit/stereo/44.1 kHz il data rate ` 2 Ā· 2 Ā· 44.1 = e 176.4 kB/s), nonchĀ“ dalla dimensione del frammento e 17
  • 23. 1.5. ANATOMIA DEL DRIVER CAPITOLO 1. LA SCHEDA AUDIO E OSS ā€¢ il driver copia il resto dei dati nel buļ¬€er, eventualmente riempiendo altri frammenti; se tutti i frammenti del buļ¬€er sono stati riempiti il processo relativo al programma che ha chiamato la write() ` messo in stato di wait e ļ¬nchĀ“ non ` libero almeno un frammento (condizione di overrun) e e Alle successive chiamate di write() i dati sono immagazzinati nel buļ¬€er secondo la disponibilit` di frammenti liberi. a Lā€™overrun si veriļ¬ca normalmente per un processo che scriva i campioni nel buļ¬€er pi` velocemente di quanto vengano riprodotti. Se al contrario il processo u ` leggermente pi` lento a scrivere i campioni rispetto alla velocit` con la quale e u a sono riprodotti si veriļ¬ca la condizione di underrun, per uno dei seguenti motivi: ā€¢ lā€™applicazione ` troppo lenta nellā€™elaborazione dei campioni (perchĀ“ la CPU e e ` troppo lenta rispetto al data rate richiesto o ci sono troppi processi in e esecuzione che competono per la CPU) ā€¢ ci sono leggere variazioni nel tempo di CPU ricevuto (unā€™applicazione gen- eralmente ben funzionante pu` occasionalmente andare in underrun) o ā€¢ lā€™applicazione tenta di lavorare troppo in tempo reale (frammenti pi` piccoli u decrescono la latenza, tuttavia bisogna sempre scrivere altri campioni prima che il buļ¬€er si svuoti) Un underrun provoca in genere un difetto udibile nel segnale riprodotto: pu`o essere una breve pausa, un ā€œclickā€ o la ripetizione di una parte del segnale (looping); se questā€™ultima si veriļ¬ca con frequenza uniforme si avvertir` un tono a sovrapposto al segnale riprodotto, con frequenza pari a quella con cui si veriļ¬ca lā€™underrun. 1.5.2 Lettura dal buļ¬€er DMA In fase di campionamento, quando il programma chiama read() per la prima volta dopo lā€™apertura del device, si veriļ¬cano i seguenti eventi: ā€¢ il driver programma la scheda audio con i parametri di campionamento predisposti (risoluzione, numero di canali e frequenza) ā€¢ di default ` calcolata la dimensione adeguata per un frammento, se tramite e unā€™opportuna chiamata ioctl() non se ne ` stabilita unā€™altra e ā€¢ sono attivati il processo di campionamento da parte della scheda audio e il trasferimento dei campioni nel primo frammento del buļ¬€er ā€¢ il processo ` messo in wait ļ¬nchĀ“ non ` riempito un numero di frammenti e e e che forniscono globalmente una quantit` di campioni maggiore o uguale a a quella richiesta 18
  • 24. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.6. SCHEDE AUDIO ISA E PCI ā€¢ i campioni richiesti sono copiati nel buļ¬€er del processo; gli eventuali cam- pioni in pi` rimangono nel buļ¬€er DMA u Le read() successive funzionano come sopra, senza che sia necessario ripredis- porre la scheda audio. Un overrun in campionamento si veriļ¬ca se il buļ¬€er ` completamente riempito: e in tal caso gli ulteriori campioni sono scartati; le ragioni per cui si veriļ¬ca sono simili a quelle per cui si veriļ¬ca in riproduzione. 1.6 Schede audio ISA e PCI Lā€™approccio seguito in questo lavoro ` di essere il pi` indipendenti possibile dal- e u lā€™hardware, in modo da poter creare dei programmi che girino su ogni piattaforma per cui ` stato portato OSS con tuttā€™al pi` una semplice ricompilata del codice e u sorgente. Tuttavia si vogliono elencare i motivi per i quali le schede audio PCI sono superiori alle schede audio ISA (al di l` della qualit` audio); al momento in a a cui si scrive (1999) la quasi totalit` delle schede audio in commercio sono PCI, ma a ļ¬no a un anno fa erano quasi tutte ISA: un musicista professionista dovrebbe pren- dere in considerazione lā€™acquisto di una scheda audio PCI, anche se attualmente OSS non supporta del tutto le nuove caratteristiche, come lā€™audio 3D. Si elencheranno ora le diļ¬€erenze fra ISA e PCI pertinenti le schede audio: ā€¢ Il bus ISA ha un clock nominale di 8 MHz, il che darebbe un throughput teorico di 16 MB/s; in realt`, a causa di overhead vari nella gestione dei seg- a nali, nonchĀ“ il fatto che sono richiesti due cicli di clock per il trasferimento e dei dati, il throughput si aggira attorno ai 5 MB/s. Se si guarda la quantit` a di dati da trasferire per una scheda che campiona a 16 bit/stereo/44.1 kHz (circa 176 kB/s) questo throughput appare adeguato, ma si pu` veriļ¬care o che il DMA blocchi lā€™accesso della CPU al bus durante il trasferimento dei campioni o se la richiesta dā€™interrupt ` occupata (con ISA le IRQ non sono e condivisibili), il che pu` causare click nel suono in sistemi pesantemente o caricati. La capacit` di indirizzamento massima per ISA ` di 16 MB, per a e cui sono diļ¬ƒcilmente applicabili le tecniche di allocazione del buļ¬€er DMA nel buļ¬€er del processo, che dovrebbe risiedere al di sotto di tale limite anche per sistemi con pi` RAM. Pu` inoltre risultare diļ¬ƒcile la conļ¬gurazione di u o una scheda audio, soprattutto con OSS/Free se ` PnP.e ā€¢ Le speciļ¬che PCI 2.1 consentono un clock sul bus ļ¬no a 66 MHz, con un throughput teorico di 264 MB/s, mentre in pratica ci si aggira intorno ai 108 MB/s; con un clock sul bus di 33 MHz questi valori si dimezzano. Gli interrupt sono condivisibili, per cui con la tecnica dellā€™interrupt binding, se si veriļ¬cano pi` interrupt contemporaneamente, questi vengono raggrup- u pati e serviti in base alla priorit` (e Linux distingue fra fast interrupt ā€” a quelli che richiedono un salvataggio del contesto parziale, come la richiesta 19
  • 25. 1.7. FILE SYSTEM E DEVICE FILE CAPITOLO 1. LA SCHEDA AUDIO E OSS di un servizio DMA ā€” e gli interrupt normali, con salvataggio completo del contesto ā€” riducendo in tal modo lā€™overhead). Il PCI consente il busmas- tering multiplo (con due busmaster), ovvero due arbitri nella gestione del bus, il che si traduce nellā€™accesso contemporaneo di CPU e DMA al bus se le aree di memoria interessate non coincidono; lā€™indirizzamento ` a 32 bit, e per cui sono applicabili le tecniche di allocazione del buļ¬€er DMA nel buļ¬€er ` del processo. E inoltre pi` semplice la conļ¬gurazione delle periferiche PCI, u in quanto dopo il boot queste negoziano fra loro, in pratica autoallocandosi. Queste ed altre considerazioni, come la tendenza delle nuove schede audio ad incrementare la frequenza di campionamento, spingono a concludere che una scheda audio PCI pu` risultare ļ¬no a dieci volte pi` eļ¬ƒciente di una scheda ISA. o u 1.7 File system e device ļ¬le Come si ` avuto occasione di aļ¬€ermare precedentemente, OSS ` un driver che e e fornisce al programmatore la possibilit` di gestire audio e MIDI tramite opportuni a device ļ¬le inseriti nella struttura dellā€™albero monolitico del ļ¬le system di Linux. Ogni device ļ¬le ` caratterizzato da un major number e da un minor number : il e primo ` utilizzato come indice in una tabella del kernel per identiļ¬care il tipo e di driver che deve gestire un dispositivo hardware, il secondo ` passato al driver e stesso per identiļ¬care lā€™unit` su cui agire (classe del device). a In Linux il major number per OSS ` 14, ma per altri sistemi operativi potrebbe e essere diverso. Il minor number pu` essere codiļ¬cato tramite un solo byte: in o tal caso, come da ļ¬gura 1.6, i quattro bit meno signiļ¬cativi identiļ¬cano la classe del dispositivo, mentre i quattro bit pi` signiļ¬cativi identiļ¬cano un dispositivo u allā€™interno di una stessa classe; ne consegue che ci possono essere ļ¬no a sedici dispositivi dello stesso tipo per ogni classe. Tipo device Classe mixer 0 sequencer 1 midi 2 7 4 3 0 dsp 3 num. device classe audio 4 dspW 5 1 byte sndstat 6 riservato 7 music 8 sndproc 9 Figura 1.6: Codiļ¬ca del minor number di un device ļ¬le di OSS 20
  • 26. CAPITOLO 1. LA SCHEDA AUDIO E OSS 1.8. LE VERSIONI DI OSS Ad esempio, /dev/midi00 identiļ¬ca il primo dispositivo di classe 2 (MIDI), per cui ` il numero del device ` 0: ci` implica che il minor number per il device ļ¬le e e o relativo ` 0x02 (2 in decimale). Analogamente per /dev/midi01 il minor number e per il device ļ¬le relativo sar` 0x12 (18 in decimale), per /dev/midi02 sar` 0x22 a a (34 in decimale) e per /dev/midi03 sar` 0x32 (50 in decimale). a Anche se nelle odierne distribuzioni di Linux non ci dovrebbero essere problemi del genere, se un device ļ¬le dovesse mancare ` possibile crearlo eļ¬€ettuando il login e come root e dando il seguente comando: mknod -m <permessi> <nome device file> c 14 <classe del device> ad esempio, il nome del device ļ¬le potrebbe essere /dev/music e la classe sarebbe 8; <permessi> ` un numero ottale che predispone i permessi di accesso al ļ¬le, che e pu` essere posto pari a 666 per accesso in lettura/scrittura da parte di tutti gli o utenti (vedere man chmod). 1.8 Le versioni di OSS Il riconoscimento della versione di OSS in uso varia secondo che si stia utilizzando una versione precedente o successiva alla 3.6. Ad esempio, la versione 3.5.4 di soundcard.h deļ¬nisce le seguenti macro: #define SOUND_VERSION 350 #define UNIX_SOUND_SYSTEM mentre nella versione 3.8.2 sono deļ¬nite le seguenti altre macro: #define SOUND_VERSION 0x030802 #define OPEN_SOUND_SYSTEM SOUND_VERSION contiene il numero di versione, con formato che varia secondo che sia deļ¬nito UNIX_SOUND_SYSTEM o OPEN_SOUND_SYSTEM. Dalla versione 3.6 in poi ` possibile usare il seguente frammento di codice, che e interroga direttamente il driver per ricavare il numero di versione (` pi` aļ¬ƒdabile e u che ricavarlo da SOUND_VERSION): int versione; if (ioctl(dspfd, OSS_GETVERSION, &versione) == -1) { /* Versione precedente alla 3.6: errno==EINVAL */ } Il seguente frammento di codice ricava i numeri di versione e release indipen- dentemente dalla versione di OSS utilizzata: int versione, release1, release2, tmpver; #ifdef UNIX_SOUND_SYSTEM 21
  • 27. 1.8. LE VERSIONI DI OSS CAPITOLO 1. LA SCHEDA AUDIO E OSS versione = SOUND_VERSION / 100; release1 = (SOUND_VERSION - versione*100) / 10; release2 = SOUND_VERSION - versione*100 - release1*10; #else /* eā€™ definito OPEN_SOUND_SYSTEM */ if (ioctl(dspfd, OSS_GETVERSION, &tmpver) == -1) errore("OSS_GETVERSION"); versione = (tmpver & 0x00ff0000) >> 16; release1 = (tmpver & 0x0000ff00) >> 8; release2 = tmpver & 0x000000ff; #endif 22
  • 28. Capitolo 2 IL MIXER E LA GESTIONE DEI CANALI 2.1 Descrizione di /dev/mixer Non tutte le schede audio possiedono un mixer: nella fattispecie possono non averlo le schede pi` vecchie, quelle non ancora pienamente supportate, quelle u professionali e le completamente digitali. Anche se il mixer ` mancante si pu` e o sempre aprire /dev/mixer, ma unā€™eventuale ioctl() ritorna errno==ENXIO. Nella Sezione 1.3 si ` fornito uno scheletro di codice C per lā€™apertura e la e chiusura di un device ļ¬le; si ` scritto che fra la open() e la close() di questo e ci possono essere delle read(), write() o ioctl(). /dev/mixer ` un device ļ¬le e atipico, in quanto non accetta operazioni di read() o write() e lā€™unica primitiva utilizzabile ` ioctl(): infatti il mixer svolge solo un lavoro di gestione dei canali e cambiando la conļ¬gurazione della scheda audio, praticamente non impiegando risorse di calcolo per operare. A diļ¬€erenza di /dev/dsp e /dev/audio, pi` di un processo alla volta pu` u o aprire /dev/mixer; generalmente si usa O_RDONLY come argomento di open(). Le modiļ¬che eļ¬€ettuate alla conļ¬gurazione del mixer permangono anche dopo la chiusura dellā€™ultimo processo modiļ¬cante, ļ¬no a quando un eventuale altro processo non eļ¬€ettuer` nuovi cambiamenti o ļ¬no al reboot del computer. Allā€™atto a del boot ` il kernel che si occupa di conļ¬gurare la scheda audio con dei valori e di default ragionevoli, ma che non dovrebbero comunque essere dati per scontati per non creare programmi inaļ¬ƒdabili. Solo per il primo mixer, lā€™uso delle ioctl() per /dev/mixer su questo o su un altro device di OSS sono equivalenti: ad esempio, se si ` aperto /dev/sequencer ` e e inutile aprire anche /dev/mixer per variare la conļ¬gurazione della scheda audio, basta usare gli ioctl() che si sarebbero utilizzati col secondo direttamente col primo. ` E importante veriļ¬care le capacit` del mixer prima di usarne i canali, in mo- a do da creare programmi che siano portabili per quasi tutte le schede audio. Le 23
  • 29. 2.2. I CANALI DEL MIXER CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI diļ¬€erenze di comportamento riscontrate dovrebbero essere indicate nella docu- mentazione, evitando descrizioni troppo speciļ¬che nei confronti dei canali, che possono avere caratteristiche diverse con schede diverse. 2.2 I canali del mixer Per i canali del mixer ci si pu` rifare alla metafora delle ļ¬gure 1.1 e 1.2, per cui o un canale identiļ¬ca la classe del dispositivo (CD, microfono, . . . ) che a questo ` connesso; il programmatore pu` eļ¬€ettuarne la selezione per la riproduzione o e o il campionamento, regolandone il livello di volume (se il dispositivo ` stereo ci e sono due livelli di volume indipendentemente controllabili, il che consente di real- izzare il balance). Il volume principale pu` essere mancante (Gravis UltraSound, o Microsoft Sound System). Sono deļ¬niti SOUND_MIXER_NRDEVICES canali, a cui ` associato un numero da e 0 a SOUND_MIXER_NRDEVICES-1; un programma non dovrebbe cercare di accedere a numeri di canale superiori a questā€™ultimo. OSS mette a disposizione del programmatore dei nomi simbolici per ogni canale; quelli deļ¬niti in soundcard.h versione 3.5.4 si trovano nella tabella della prossima pagina. Ad ogni canale ` associato un int, nella cui rappresentazione in binario (bit- e mask ) ` posto a 1 il bit di posizione corrispondente al numero del canale; le e bitmask sono utili con i comandi di gestione della conļ¬gurazione del mixer. Sempre in soundcard.h sono deļ¬niti dei nomi simbolici da dare ai canali tramite le macro: #define SOUND_DEVICE_LABELS {"Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", "Line1", "Line2", "Line3"} #define SOUND_DEVICE_NAMES {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", "line1", "line2", "line3"} la diļ¬€erenza fra i due ` che il primo formato ` adatto per la stampa dei nomi a e e video quali etichette dei canali, mentre del secondo formato ` pi` adatto lā€™utilizzo e u quando i nomi dei device audio sono forniti sulla riga di comando di una shell. 24
  • 30. CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI 2.2. I CANALI DEL MIXER Nomi dei canali Bitmask associate Descrizione SOUND_MIXER_VOLUME SOUND_MASK_VOLUME Livello volume principale SOUND_MIXER_BASS SOUND_MASK_BASS Regolazione toni bassi principale SOUND_MIXER_TREBLE SOUND_MASK_TREBLE Regolazione toni acuti principale SOUND_MIXER_SYNTH SOUND_MASK_SYNTH Livello di uscita sintetizzatore interno (FM, wavetable); per alcune schede ne controlla anche il livello di campionamento SOUND_MIXER_PCM SOUND_MASK_PCM Livello di uscita di /dev/dsp e /dev/audio SOUND_MIXER_SPEAKER SOUND_MASK_SPEAKER Livello di uscita del segnale allā€™altoparlantino nel PC (se connesso alla scheda audio); su altre schede pu` essere un o generico ingresso mono con qualche altra funzione SOUND_MIXER_LINE SOUND_MASK_LINE Livello di ingresso per Lineā€“In SOUND_MIXER_MIC SOUND_MASK_MIC Livello del segnale microfonico in campionamento o inviato a cuļ¬ƒe e Lineā€“Out; qualche volta il microfono non ` connesso a questo canale, ma e a un line level input della scheda SOUND_MIXER_CD SOUND_MASK_CD Livello del CD Audioā€“In SOUND_MIXER_IMIX SOUND_MASK_IMIX Recording monitor campionamento; durante tale fase, su alcune schede controlla il volume delle cuļ¬ƒe SOUND_MIXER_ALTPCM SOUND_MASK_ALTPCM Livello di un DSP secondario; nella Pro Audio Spectrum 16 ` il canale e dellā€™emulazione della Sound Blaster SOUND_MIXER_RECLEV SOUND_MASK_RECLEV Livello di campionamento per tutti i canali (nella Sound Blaster 16 si hanno solo quattro livelli possibili) SOUND_MIXER_IGAIN SOUND_MASK_IGAIN Livello di guadagno di ingresso SOUND_MIXER_OGAIN SOUND_MASK_OGAIN Livello di guadagno di uscita SOUND_MIXER_LINE1 SOUND_MASK_LINE1 Canale generico 1 (aux1); i codec AD1848 e compatibili hanno tre line level input a cui diversi costruttori assegnano funzioni diverse, per cui tali nomi si usano quando il signiļ¬cato preciso di un canale ļ¬sico ` sconosciuto e SOUND_MIXER_LINE2 SOUND_MASK_LINE2 Canale generico 2 (aux2) SOUND_MIXER_LINE3 SOUND_MASK_LINE3 Canale generico 3 (line) 25
  • 31. 2.2. I CANALI DEL MIXER CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI Se in un programma si eļ¬€ettuano le assegnazioni: const char *nome_canale[] = SOUND_DEVICE_LABELS; const char *nome_cmline[] = SOUND_DEVICE_NAMES; allora, ad esempio, nome_canale[SOUND_MIXER_CD] corrisponde a ā€œCD ā€, men- tre nome_cmline[SOUND_MIXER_CD] corrisponde a ā€œcdā€. Il mixer consente la selezione dei canali da cui eļ¬€ettuare il campionamento, che per buona parte delle schede avviene in mutua esclusione. Il canale di default dopo il boot ` quello del microfono, ma non dovrebbe e essere dato per scontato, poichĀ“ il driver non altera le predisposizioni del mixer e a meno di un comando da programma; un qualche altro processo dopo il boot potrebbe averle modiļ¬cate, con tali modiļ¬che che permangono anche dopo la sua terminazione. Lā€™insieme di canali disponibili non ` ļ¬sso, ma dipende dalla scheda audio; si e pu` veriļ¬care che ai canali dello stesso chip mixer costruttori diversi assegnino o funzioni diverse, per cui bisogner` veriļ¬carne caso per caso il reale signiļ¬cato. a Sarebbe meglio non includere funzionalit` di mixer nei programmi se si vuole a la massima portabilit` del proprio codice, demandandole a programmi specializ- a zati per le varie schede audio. Nel caso si volesse realizzare un tale programma mixer bisogna ben documentare le sue capacit` se ` sviluppato per una precisa a e scheda, altrimenti ` meglio evitare di essere troppo speciļ¬ci nella documentazione e per non trarre in inganno gli utenti: potrebbero credere che la propria scheda audio sia diversa da come ` realmente, basandosi su ci` che il programma fa e o vedere. 2.2.1 Lettura della conļ¬gurazione Come ` stato visto sopra, converrebbe eļ¬€ettuare il controllo sia delle capacit` e a della scheda audio che dellā€™esistenza o meno dei canali di interesse prima di in- traprendere qualsiasi altra azione; unā€™operazione di ioctl() fallita (ad esempio, perchĀ“ il canale non esiste) ritorna -1 e errno==EINVAL. e Per eļ¬€ettuare la lettura della conļ¬gurazione dei canali del mixer il codice ` e simile per tutti i comandi a disposizione: int bitmask; if (ioctl(mixfd, SOUND_MIXER_READ_****, &bitmask) == -1) { /* Il mixer eā€™ mancante - errno==ENXIO */ } ove SOUND_MIXER_READ_**** ` lā€™identiļ¬catore del comando di lettura che ritorna e in bitmask una maschera di bit; questa pu` essere esaminata per determinare le o capacit` di un canale o del mixer in base al comando dato. a 26
  • 32. CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI 2.2. I CANALI DEL MIXER Per i canali il controllo si pu` eļ¬€ettuare con: o if (bitmask & (1 << numero_canale)) { /* Il canale possiede la capacitaā€™ in esame */ } ove numero_canale ` un intero tra 0 e SOUND_MIXER_NRDEVICES-1 o il nome e mnemonico del canale; al posto di (1 << numero_canale) si pu` utilizzare di- o rettamente la bitmask ad esso associata. I comandi a disposizione per la lettura della conļ¬gurazione sono: Comandi Richiesta a OSS SOUND_MIXER_READ_DEVMASK Quali canali sono presenti? SOUND_MIXER_READ_STEREODEVS Quali canali sono stereo? SOUND_MIXER_READ_RECMASK Quali sono i canali campionabili? SOUND_MIXER_READ_RECSRC Qual ` il canale campionabile attivo? e SOUND_MIXER_READ_CAPS Si pu` campionare solo un canale per volta? o Con lā€™ultimo comando si testa se si possono campionare i canali solo in mutua esclusione; il controllo si eļ¬€ettua con: if (bitmask & SOUND_CAP_EXCL_INPUT) { /* Campionamento solo in mutua esclusione */ } La diļ¬€erenza fra SOUND_MIXER_READ_RECMASK e SOUND_MIXER_READ_RECSRC ` che il primo comando ritorna una bitmask con un bit a 1 per ogni canale per e cui la scheda audio possiede la capacit` di campionamento, mentre il secondo a ritorna una bitmask con un bit a 1 per ogni canale attualmente selezionato per il campionamento (se questo ` possibile in mutua esclusione solo un bit in tutta e la bitmask pu` essere a 1). o 2.2.2 Selezione del canale da campionare Per selezionare il canale da cui campionare basta il seguente frammento di codice: int bitmask = SOUND_MASK_****; if (ioctl(mixfd, SOUND_MIXER_WRITE_RECSRC, &bitmask) == -1) { /* Non cā€™eā€™ il mixer o il canale */ /* errno==ENXIO oppure EINVAL */ } ove SOUND_MASK_**** ` la bitmask associata al canale desiderato. e Nel caso fosse possibile campionare da pi` canali contemporaneamente, li si u seleziona ponendo in bitmask un OR aritmetico delle bitmask associate ai canali; ad esempio, per selezionare il campionamento simultaneo da CD e da microfono: 27
  • 33. 2.3. LIVELLI DI VOLUME DEI CANALI CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI bitmask = SOUND_MASK_CD | SOUND_MASK_MIC; Se nessun bit ` posto a 1 (bitmask==0x00000000), il driver seleziona il canale e del microfono. 2.3 Livelli di volume dei canali Le schede audio rappresentano il livello di un canale con un numero di bit vari- abile: 3, 8 e anche 16 bit. Lā€™architettura di OSS svincola il programmatore dalla conoscenza dei livelli assoluti di volume introducendo una rappresentazione in percentuale: il volume di un canale pu` variare fra 0 (spento) e 100 (massimo); o se il canale ` stereo si hanno due di queste percentuali, che possono essere uguali e o meno per realizzare il balance. Per leggere il livello attuale di volume per un canale si sfrutta il seguente frammento di codice: int volume; if ((ioctl(mixfd, MIXER_READ(numero_canale), &volume) == -1) { /* Non cā€™eā€™ il mixer o il canale */ /* errno==ENXIO oppure EINVAL */ } ove numero_canale ` un numero compreso tra 0 e SOUND_MIXER_NRDEVICES-1, e oppure il nome mnemonico del canale. Al posto di MIXER_READ(numero_canale) si pu` utilizzare anche SOUND_MIXER_READ_****, con **** nome del canale; ad o esempio, per il microfono ` SOUND_MIXER_READ_MIC. e Il volume ` codiļ¬cato come in ļ¬gura 2.1: se il dispositivo ` stereo la codiļ¬ca dei e e canali destro e sinistro si trova nella parola meno signiļ¬cativa di volume (intero a 32 bit); i 16 bit della parola pi` signiļ¬cativa sono indeļ¬niti e dovrebbero essere u ignorati. Nel byte pi` signiļ¬cativo della LSW cā€™` il volume del canale destro, nel u e byte meno signiļ¬cativo il volume del canale sinistro; per i canali mono ` valido e solo il byte meno signiļ¬cativo, essendo lā€™MSB posto uguale allā€™LSB dal driver. 31 16 15 8 7 0 XXXXXXXX Destro Sinistro MSW MSB LSB (da ignorare) LSW Figura 2.1: Rappresentazione del volume di un canale stereo 28
  • 34. CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI 2.4. DIPENDENZA DALLā€™HARDWARE Per estrarre il volume dei canali destro e sinistro si possono sfruttare le seguenti linee di codice: int volume, vol_sinistro, vol_destro; vol_sinistro = volume & 0x000000ff; vol_destro = (volume & 0x0000ff00) >> 8; Inversamente, per costituire una parola di volume: int volume; volume = (vol_destro << 8) | vol_sinistro; Per cambiare il volume si utilizza il seguente frammento di codice: int volume = <valore>; if ((ioctl(fd, MIXER_WRITE(numero_canale), &volume) == -1) { /* Non cā€™eā€™ il mixer o il canale */ /* errno==ENXIO oppure EINVAL */ } ove numero_canale ` un numero compreso tra 0 e SOUND_MIXER_NRDEVICES-1, e oppure il nome mnemonico del canale. Al posto di MIXER_WRITE(numero_canale) si pu` utilizzare anche SOUND_MIXER_WRITE_****, con **** nome del canale; ad o esempio, per il CD ` SOUND_MIXER_WRITE_CD. e Dopo il cambiamento bisognerebbe veriļ¬care se il livello ritornato in volume risulta di proprio gradimento, dal momento che ` di solito pi` piccolo di quanto e u richiesto; sequenze di scrittura/lettura ripetute (senza cambiare tale variabile) ` possono portare al suo azzeramento. E conveniente eļ¬€ettuare la predisposizione del volume durante lā€™inizializzazione del programma, ignorando poi il volume ritornato in seguito. 2.4 Dipendenza dallā€™hardware Per ottenere dal mixer il nome della scheda audio si pu` utilizzare il seguente o frammento di codice: mixer_info info; if ((ioctl(fd, SOUND_MIXER_INFO, &info) == -1) { /* Non cā€™eā€™ il mixer - errno==ENXIO */ } ove mixer_info ` una struct cos` composta: e ı char id[16 ] identiļ¬catore della scheda audio (in genere un paio di caratteri) char name[32 ] nome per esteso della scheda Ecco un output di esempio per SOUND_MIXER_INFO con una scheda Sound Blaster 16: SB Sound Blaster 29
  • 35. 2.5. NUOVE CARATTERISTICHE CAPITOLO 2. IL MIXER E LA GESTIONE DEI CANALI 2.5 Nuove caratteristiche In questa Sezione ci si occuper` di descrivere le nuove caratteristiche di OSS a riguardanti il mixer introdotte dalla versione 3.6 in poi. ā€¢ ` stata implementata la possibilit` di gestire dei canali in pi` : e a u Nomi dei canali Bitmask associate Descrizione SOUND_MIXER_DIGITAL1 SOUND_MASK_DIGITAL1 Ingresso digitale 1 SOUND_MIXER_DIGITAL2 SOUND_MASK_DIGITAL2 Ingresso digitale 2 SOUND_MIXER_DIGITAL3 SOUND_MASK_DIGITAL3 Ingresso digitale 3 SOUND_MIXER_PHONEIN SOUND_MASK_PHONEIN Ingresso livello fono SOUND_MIXER_PHONEOUT SOUND_MASK_PHONEOUT Uscita livello fono SOUND_MIXER_VIDEO SOUND_MASK_VIDEO Ingresso audio per video/TV SOUND_MIXER_RADIO SOUND_MASK_RADIO Ingresso radio SOUND_MIXER_MONITOR SOUND_MASK_MONITOR Volume monitor (di solito il microfono) ā€¢ le macro SOUND_DEVICE_LABELS e SOUND_DEVICE_NAMES risultano di con- seguenza arricchite rispettivamente delle etichette e dei nomi da linea di comando dei nuovi canali: #define SOUND_DEVICE_LABELS {"Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", "PhoneIn", "PhoneOut", "Video", "Radio", "Monitor"} #define SOUND_DEVICE_NAMES {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", "line1", "line2", "line3", "dig1", "dig2", "dig3", "phin", "phout", "video", "radio", "monitor"} ā€¢ ` stata modiļ¬cata mixer_info; la sua nuova struttura ` la seguente: e e char id[16 ] identiļ¬catore della scheda audio (in genere un paio di caratteri) char name[32 ] nome per esteso della scheda int modify counter numero di modiļ¬che int ļ¬llers[10 ] ā€œriempitiviā€ per evoluzioni future 30