Pier Luca Montessoro, University of Udine 1
FONDAMENTI DI INFORMATICA
Prof. PIER LUCA MONTESSORO Università degli Studi di Udine
Scrittura di programmi applicativi per audio real-time: la libreria portaudio
Il segnale audio
amplificatore
microfono: converte il suono in variazioni di una tensione o corrente elettrica suono: successione di
compressioni e rarefazioni dell’aria
amplificatore: amplifica il livello della tensione/corrente
segnale audio analogico (elettrico) t V
Il segnale audio
• È continuo:
– nel tempo – nelle ampiezze
• Per la codifica digitale è necessario rendere discreto il segnale:
– per il tempo campionamento – per le ampiezze quantizzazione
Campionamento
t V
“CAMPIONAMENTO”
Campionamento Teorema del campionamento (Shannon,
Nyquist)
• Si applica a segnali reali limitati in banda (potenza nulla al di sopra di una frequenza massima B)
• Permette di rappresentare completamente un segnale continuo nel tempo mediante una sequenza discreta di valori campionati a frequenza Fc
• Vincolo:
F
c2B
Pier Luca Montessoro, University of Udine 2
Quantizzazione
• Il campionamento produce dei numeri reali di precisione virtualmente infinita
• Per la rappresentazione digitale è necessario utilizzare un numero finito di bit
• La quantizzazione arrotonda i valori dei campioni introducendo irreversibilmente una perdita di informazione detta “rumore di quantizzazione”
Quantizzazione
t V
t V
t V
campionamento quantizzazione
Alcuni esempi
• Voce per telefonia digitale PCM (Pulse Code Modulation) – B 3400 Hz (il canale telefonico ha banda 300-3400 Hz) – Fc = 8 kHz
– Quantizzazione: 8 bit/campione
– 64 kb/s – 1 minuto: 480 kB
Alcuni esempi
• Musica su CD audio
– B 20 kHz (l’insieme di frequenze udibili dall’orecchio umano è 20-20000 Hz)
– Fc = 44.1 kHz
– Quantizzazione: 16 bit/campione (per ognuno dei due canali: il CD è stereo)
– 1.411 Mb/s – 1 minuto: circa 10 MB
In linguaggio C, file WAV
• I campioni da 16 bit sono rappresentati da valori di tipo signed short int
• La sequenza di campioni è memorizzata in un vettore in cui i valori del canale destro e canale sinistro sono alternati
signed short int buffer[88200]
Interfaccia audio
driver software dispositivo
hardware
programma applicativo
qui tocca a noi!
qui ci pensa il costruttore…
Pier Luca Montessoro, University of Udine 3
Libreria portaudio
• http://www.portaudio.com/
“Portable cross-platform Audio API”
• Compatibile con cygwin/gcc
• Wrapper per le esercitazioni di “Architettura dei calcolatori”:
rtalib (real-time audio library)
Un piccolo problema
Il driver software esiste già. Come fa a chiamare una funzione della nostra applicazione?
Funzioni di CALLBACK!!!
Callback function
driver software
programma applicativo f_inizializzazione (indirizzo_fz_appl)
chiamata di (*indirizzo_fz_appl)()
rtalib
• Limitata al formato CD audio (44.1 KHz, 16 bit, stereo)
• Richiede i file cygportaudio-2.dll e libportaudio.dll.a (Windows) o libportaudio.so (Linux), portaudio.h, rtalib.c, rtalib.h, wav.c, wav.h, (sul sito
www.montessoro.it)
• per compilare:
cc_rta <nome programma> (Windows) ./cc_rta <nome programma> (Linux)
rtalib: funzioni di inizializzazione
int init_stream_for_input (void) int init_stream_for_output (void)
int init_stream_for_input_and_output (void)
rtalib: funzioni di callback
void write_buffer_to_play
(signed short int *buffer, int buffer_size) void read_recorded_buffer
(signed short int *buffer, int buffer_size) void read_and_write_buffer
(signed short int *input_buffer, signed short int *output_buffer, int buffer_size)
Pier Luca Montessoro, University of Udine 4
rtalib: temporizzazione e chiusura
void sleep_while_stream_is_running (double seconds) int close_stream (void)
Esempio: wire
void wire (void) {
if (init_stream_for_input_and_output() == -1) {
printf ("error opening output stream\n");
exit (EXIT_FAILURE);
}
printf ("Playing... 'X' to terminate.\n");
while (toupper(getchar()) != 'X');
return;
}
Esempio: wire
void read_and_write_buffer (signed short int *input_buffer,
signed short int *output_buffer, int buffer_size) {
int i;
for (i = 0; i < buffer_size; i++) {
*output_buffer++ = *input_buffer++; /* left */
*output_buffer++ = *input_buffer++; /* right */
} return;
}