Il materiale dell'articolo è tratto dal mio .

Creiamo un generatore di toni
Nella parte precedente abbiamo installato la libreria del media streamer, gli strumenti di sviluppo e abbiamo verificato il loro funzionamento, creando un'app di prova.
Oggi creeremo un'applicazione che potrà generare un segnale tonale sulla scheda audio. Per risolvere questo compito, dobbiamo collegare i filtri nello schema del generatore di suoni riportato di seguito:
![]()
Leggiamo lo schema da sinistra a destra, ed è in questa direzione che fluisce il flusso di dati. Anche le frecce lo suggeriscono. I rettangoli rappresentano i filtri che elaborano i blocchi di dati e producono il risultato in output. All'interno del rettangolo è indicato il suo ruolo e subito sotto, in maiuscolo, il tipo di filtro. Le frecce che collegano i rettangoli sono code di dati lungo le quali i blocchi di dati vengono trasferiti da un filtro all'altro. In generale, un filtro può avere diversi ingressi e uscite.
Tutto inizia con una sorgente di clock, che stabilisce il ritmo in cui avviene l'elaborazione dei dati nei filtri. Al suo impulso, ogni filtro elabora tutti i blocchi di dati che ha in ingresso. E produce blocchi con i risultati in output — nella coda. Per prima cosa, elabora il filtro più vicino alla sorgente di clock, poi i filtri collegati alle sue uscite (che possono essere molte) e così via. Dopo che l'ultimo filtro nella catena ha terminato l'elaborazione, l'esecuzione si ferma fino a quando non arriva un nuovo impulso. Gli impulsi, per impostazione predefinita, seguono un intervallo di 10 millisecondi.
Torniamo al nostro schema. I segnali vengono inviati all'ingresso della sorgente di silenzio, che è un filtro dedicato a generare per ogni impulso un blocco di dati contenente zeri. Se consideriamo questo blocco come un blocco di campioni audio, non è altro che silenzio. A prima vista può sembrare strano generare blocchi di dati con silenzio — dopo tutto, non è possibile sentirlo, ma questi blocchi sono necessari per il funzionamento del generatore di segnali audio. Il generatore utilizza questi blocchi come un foglio bianco, scrivendo in essi i campioni audio. Nella sua normale condizione, il generatore è spento e semplicemente manda i blocchi di ingresso all'uscita. In questo modo, i blocchi di silenzio passano senza modifiche attraverso tutto lo schema da sinistra a destra, arrivando alla scheda audio, che silenziosamente preleva i blocchi dalla coda collegata al suo ingresso.
Ma tutto cambia se al generatore viene dato il comando di riprodurre il suono, inizierà a generare campioni audio e a sostituirli nei blocchi di ingresso, quindi invierà i blocchi modificati all'uscita. La scheda audio inizia a riprodurre il suono. Di seguito è riportato il programma che implementa lo schema di lavoro sopra descritto:
/* Файл 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 del media streamer, vengono creati tre filtri: voidsource, dtmfgen, snd_card_write. Viene creato un sorgente di impulso.
Poi è necessario connettere i filtri secondo il nostro schema, e l'originario dell'impulso deve essere collegato per ultimo, poiché dopo di ciò inizierà immediatamente il funzionamento dello schema. Se si collega l'origine dell'impulso a un schema non completato, può succedere che il media streamer si chiuda in modo anomalo se rileva nella catena almeno un filtro con tutti gli ingressi o tutte le uscite "in sospeso" (non collegati).
La connessione 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 dell'uscita della sorgente (notare che gli ingressi e le uscite sono numerati a partire da zero). Il terzo argomento è un puntatore al filtro ricevente, il quarto è il numero dell'ingresso del ricevente.
Tutti i filtri sono collegati e l'ultima sorgente a essere connessa è quella del segnale di clock (d'ora in poi la chiameremo semplicemente ticker). Dopo di che, il nostro schema sonoro viene messo in funzione, ma dagli altoparlanti del computer non si sente ancora nulla: il generatore audio è spento e passa semplicemente attraverso di sé i blocchi di dati in ingresso con silenzio. Per avviare la generazione del segnale tonale, è necessario eseguire il metodo del filtro del generatore.
Genereremo un segnale dual-tone (DTMF) corrispondente alla pressione del tasto "1" sul telefono. Per questo utilizzeremo la funzione ms_filter_call_method() per invocare il metodo MS_DTMF_GEN_PLAY, passando come argomento un puntatore al codice che deve corrispondere al segnale riprodotto.
Restiamo da compilare il programma:
$ gcc mstest2.c -o mstest2 `pkg-config mediastreamer --libs --cflags`E avviarlo:
$ ./mstest2Dopo aver avviato il programma, sentirai negli altoparlanti del computer un breve segnale acustico composto da due toni.
Abbiamo creato e avviato il nostro primo schema sonoro. Abbiamo visto come creare istanze di filtri, come collegarli e come invocare i loro metodi. Dopo aver festeggiato il nostro primo successo, dobbiamo però prestare attenzione al fatto che il nostro programma non libera la memoria allocata prima della chiusura. Nella prossima impareremo a fare ordine.
Fonte: habr.com
