Il materiale dell'articolo è tratto dal mio .

Creiamo un generatore di tonalità
Nella precedente Abbiamo installato la libreria di streaming multimediale, gli strumenti di sviluppo e verificato il loro funzionamento, creando un'app di prova.
Oggi creeremo un'applicazione in grado di generare un segnale tonale attraverso la scheda audio. Per risolvere questo compito, dobbiamo collegare i filtri secondo lo schema mostrato di seguito del generatore di suoni:
![]()
Leggiamo lo schema da sinistra a destra, poiché in questa direzione fluisce il flusso di dati. Le frecce lo suggeriscono. I rettangoli rappresentano i filtri, che elaborano i blocchi di dati e producono il risultato in uscita. All'interno del rettangolo è indicato il suo ruolo e un po' più in basso il tipo di filtro in lettere maiuscole. Le frecce che collegano i rettangoli rappresentano le code di dati, attraverso le quali i blocchi di dati vengono trasportati da un filtro all'altro. In generale, un filtro può avere molti ingressi e uscite.
Tutto inizia con la sorgente del clock, che stabilisce il ritmo con cui avviene il calcolo dei dati nei filtri. Seguendo il suo tempo, ogni filtro elabora tutti i blocchi di dati in ingresso. E produce i blocchi con il risultato in uscita — in coda. Prima viene eseguito il calcolo del filtro più vicino alla sorgente del clock, poi i filtri collegati alle sue uscite (che possono essere molte) e così via. Dopo che l'ultimo filtro nella catena ha completato il calcolo, l'esecuzione si interrompe fino a quando non arriva un nuovo impulso. Gli impulsi, per impostazione predefinita, seguono con un intervallo di 10 millisecondi.
Torniamo al nostro schema. I campioni vengono immessi da una sorgente di silenzio, un filtro che genera, a ogni campione, un blocco di dati contenente zeri in uscita. Se consideriamo questo blocco come un blocco di campionamenti sonori, in effetti non è altro che silenzio. A prima vista sembra strano generare blocchi di dati silenziosi, perché non possono essere uditi, ma questi blocchi sono necessari per il funzionamento del generatore del segnale audio. Il generatore utilizza questi blocchi come un foglio di carta vuoto, scrivendo in essi i campionamenti sonori. In condizioni normali, il generatore è spento e semplicemente inoltra i blocchi in ingresso all'uscita. In questo modo, i blocchi di silenzio passano inalterati attraverso tutto lo schema da sinistra a destra, finendo nella scheda audio. Quest'ultima preleva silenziosamente i blocchi dalla coda collegata al suo ingresso.
Ma tutto cambia se al generatore viene dato il comando di riprodurre il suono; inizia a generare campionamenti sonori e li sostituisce all'interno dei blocchi in ingresso, esponendo i blocchi modificati all'uscita. La scheda audio inizia a riprodurre il suono. Di seguito è riportato il programma che implementa lo schema di funzionamento descritto sopra:
/* Файл mstest2.c */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
int main()
{
ms_init();
/* Создаем экземпляры фильтров. */
MSFilter *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);
MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
MSSndCard *card_playback = ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
MSFilter *snd_card_write = ms_snd_card_create_writer(card_playback);
/* Создаем тикер. */
MSTicker *ticker = ms_ticker_new();
/* Соединяем фильтры в цепочку. */
ms_filter_link(voidsource, 0, dtmfgen, 0);
ms_filter_link(dtmfgen, 0, snd_card_write, 0);
/* Подключаем источник тактов. */
ms_ticker_attach(ticker, voidsource);
/* Включаем звуковой генератор. */
char key='1';
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY, (void*)&key);
/* Даем, время, чтобы все блоки данных были получены звуковой картой.*/
ms_sleep(2);
}Dopo l'inizializzazione dello stream media, vengono creati tre filtri: voidsource, dtmfgen, snd_card_write. Viene creato un generatore di clock.
Successivamente, è necessario collegare i filtri secondo il nostro schema, con il generatore di clock da collegare per ultimo, poiché dopo questo la schematica inizierà a funzionare immediatamente. Se il generatore di clock viene collegato a uno schema incompleto, può succedere che lo stream media si arresti in modo anomalo se rileva nella catena almeno un filtro i cui ingressi o uscite "pendono nel vuoto" (non collegati).
Il collegamento dei filtri avviene tramite la funzione
ms_filter_link(src, src_out, dst, dst_in)dove il primo argomento è un puntatore al filtro sorgente, il secondo argomento è il numero di uscita della sorgente (si noti che gli ingressi e le uscite sono numerati a partire da zero). Il terzo argomento è un puntatore al filtro di destinazione, il quarto è il numero dell'ingresso del destinatario.
Tutti i filtri sono collegati e l'ultimo a connettersi è la sorgente del clock (d'ora in poi lo chiameremo semplicemente ticker). Dopodiché, il nostro schema audio inizia a funzionare, ma dal lato del computer non si sente ancora nulla — il generatore audio è spento e semplicemente trasmette i blocchi di dati d'ingresso silenziosi. Per avviare la generazione del segnale tonale, è necessario eseguire il metodo del filtro del generatore.
Genereremo un segnale a doppia tonalità (DTMF) corrispondente alla pressione del tasto "1" sul telefono. A tal fine, utilizziamo la funzione ms_filter_call_method() richiamando il metodo MS_DTMF_GEN_PLAY, passando come argomento un puntatore al codice corrispondente al segnale da riprodurre.
Rimane da compilare il programma:
$ gcc mstest2.c -o mstest2 `pkg-config mediastreamer --libs --cflags`E avviarlo:
$ ./mstest2Dopo l'avvio del programma, sentirai nel computer un breve segnale audio composto da due toni.
Abbiamo costruito e messo in funzione il nostro primo schema sonoro. Abbiamo visto come creare istanze di filtri, come collegarli e come chiamare i loro metodi. Dopo aver festeggiato il primo successo, dobbiamo comunque prestare attenzione al fatto che il nostro programma non libera la memoria allocata prima di terminare. Nella prossima impareremo a mettere in ordine.
Fonte: habr.com
