Estudiamos el motor VoIP Mediastreamer2. Parte 5

Material del artículo tomado de mi canal zen .



Detector de tono


En el último artículo, creamos un medidor de nivel de señal. En esto aprenderemos cómo detectar un tono.



En los viejos tiempos, cuando no todas las familias tenían un televisor, y la mitad de ellos cambiaban los canales con la ayuda de unos alicates, en las revisiones de la prensa técnica extranjera había noticias interesantes de que uno de los fabricantes de televisores equipaba sus dispositivos con un control remoto inalámbrico. Por los detalles se sabía que el control remoto funciona sin baterías debido al uso de un enfoque inusual: el control remoto era mecánico y era un híbrido de un instrumento musical, un metalófono y un revólver. El tambor del revólver contenía cilindros metálicos de diferentes longitudes, y cuando el golpeador golpeó uno de ellos, el cilindro comenzó a sonar a su propia frecuencia. Presumiblemente en ultrasonido. La electrónica del televisor escuchó esta señal y, habiendo determinado su frecuencia, realizó la acción correspondiente: cambiar el canal, cambiar el volumen,apagar la televisión.


, .


, . , . , 6 , / , , / . :


struct _MSToneDetectorDef{  
     char tone_name[8];     
     int frequency; /**<Expected frequency of the tone*/ 
     int min_duration; /**<Min duration of the tone in milliseconds */ 
     float min_amplitude; /**<Minimum amplitude of the tone, 1.0 corresponding to the normalized 0dbm level */
};

typedef struct _MSToneDetectorDef MSToneDetectorDef;

10 , . . MS_TONE_DETECTOR_ADD_SCAN.


, , , . ms_filter_set_notify_callback(). , , , ( ).


, , , :



/** * Structure carried as argument of the MS_TONE_DETECTOR_EVENT**/
struct _MSToneDetectorEvent{ 
      char tone_name[8];       /*         . */
      uint64_t tone_start_time;   /*   ,    . */
};

typedef struct _MSToneDetectorEvent MSToneDetectorEvent;

.


.


/*  mstest4.c     . */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/msvolume.h>
#include <mediastreamer2/mstonedetector.h>

/*       
 * . */
#include <mediastreamer2/mseventqueue.h>

/*   ,    ,   
 *       . */
static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id,
        MSToneDetectorEvent *ev)
{
    printf("                       : %s\n", ev->tone_name);
}

int main()
{
    ms_init();

    /*   . */
    MSFilter  *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);
    MSFilter  *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
    MSFilter  *volume = ms_filter_new(MS_VOLUME_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);
    MSFilter  *detector = ms_filter_new(MS_TONE_DETECTOR_ID);

    /*      ,  
     *    .*/
    ms_filter_call_method(detector, MS_TONE_DETECTOR_CLEAR_SCANS, 0);

    /*    - . */
    MSTicker *ticker=ms_ticker_new();

    /*    . */
    ms_filter_link(voidsource, 0, dtmfgen, 0);
    ms_filter_link(dtmfgen, 0, volume, 0);
    ms_filter_link(volume, 0, detector, 0);
    ms_filter_link(detector, 0, snd_card_write, 0);

    /*      . */
    ms_filter_set_notify_callback(detector,
            (MSFilterNotifyFunc)tone_detected_cb, NULL);

    /*   . */
    ms_ticker_attach(ticker,voidsource);

    /*  ,     
     *   ,   :  
     *  ,   ,   ,
     *    0,775. */  
    MSToneDetectorDef  scan[6]=
    {
        {"V+",  440, 100, 0.1}, /*  " ". */
        {"V-",  540, 100, 0.1}, /*  " ". */
        {"C+",  640, 100, 0.1}, /*  "  ". */
        {"C-",  740, 100, 0.1}, /*  "  ". */
        {"ON",  840, 100, 0.1}, /*  " ". */
        {"OFF", 940, 100, 0.1}  /*  " ". */
    };

    /*      . */
    int i;
    for (i = 0; i < 6; i++)
    {
        ms_filter_call_method(detector, MS_TONE_DETECTOR_ADD_SCAN,
                &scan[i]);
    }

    /*  ,    .*/
    MSDtmfGenCustomTone dtmf_cfg;
    dtmf_cfg.tone_name[0] = 0;
    dtmf_cfg.duration = 1000;
    dtmf_cfg.frequencies[0] = 440;
    /*    ,      0.*/
    dtmf_cfg.frequencies[1] = 0;
    dtmf_cfg.amplitude = 1.0;
    dtmf_cfg.interval = 0.;
    dtmf_cfg.repeat_count = 0.;

    /*     .   
     *    . */
    char key='9';
    printf("  ,  .\n"
        "    0.\n");
    while(key != '0')
    {
        key = getchar();
        if ((key >= 49) && (key <= 54))
        {
                printf(" : %c\n", key);
            /*      
             *   .*/
            dtmf_cfg.frequencies[0] = 440 + 100*(key-49);

            /*    c  . */
            ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
                    (void*)&dtmf_cfg);
        }
        ms_usleep(20000);
    }
}

Compilamos y ejecutamos el programa. Si todo funciona correctamente, luego de comenzar deberíamos obtener algo como esto:


$ ./mstest4
ALSA lib conf.c:4738:(snd_config_expand) Unknown parameters 0
ALSA lib control.c:954:(snd_ctl_open_noupdate) Invalid CTL default:0
ortp-warning-Could not attach mixer to card: Invalid argument
ALSA lib conf.c:4738:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default:0
ALSA lib conf.c:4738:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default:0
ortp-warning-Strange, sound card Intel 82801AA-ICH does not seems to be capable of anything, retrying with plughw...
  ,  .
    0.
ortp-warning-alsa_set_params: periodsize:256 Using 256
ortp-warning-alsa_set_params: period:8 Using 8

Presione cualquier tecla de "1" a "6", confirmando con la tecla "Enter", debería obtener algo como este listado:



2
 : 2
                       : V-
1
 : 1
                       : V+
3
 : 3
                       : C+
4
 : 4
                       : C-
0
$

Vemos que los tonos de comando se envían con éxito y el detector los detecta.


En el próximo artículo, pasaremos a transmitir una señal de sonido a través de una red Ethernet utilizando el protocolo RTP e inmediatamente la aplicaremos en nuestro control remoto.


All Articles