Khám phá công cụ VoIP Mediastreamer2. Phần 5

Tài liệu của bài viết được lấy từ tài liệu của tôi kênh thiền.

Máy dò giai điệu

Cuối cùng Bài viết Chúng tôi đã tạo ra một máy đo mức tín hiệu. Trong phần này chúng ta sẽ học cách phát hiện tín hiệu âm thanh.

Khám phá công cụ VoIP Mediastreamer2. Phần 5

Ngày xưa, khi không phải gia đình nào cũng có TV và một nửa trong số họ chuyển kênh bằng kìm, một tin tức hấp dẫn đã xuất hiện trên các bài đánh giá của báo chí kỹ thuật nước ngoài rằng một nhà sản xuất TV đã trang bị cho thiết bị của họ một điều khiển từ xa không dây. Từ thông tin chi tiết, người ta biết rằng điều khiển từ xa hoạt động không cần pin nhờ sử dụng một phương pháp khác thường - điều khiển từ xa là cơ khí và là sự kết hợp giữa một nhạc cụ - máy luyện kim và súng lục ổ quay. Trống ổ quay chứa các ống trụ kim loại có chiều dài khác nhau, và khi chốt bắn chạm vào một trong số chúng, ống trụ bắt đầu kêu theo tần số riêng của nó. Có lẽ là trên siêu âm. Các thiết bị điện tử trong TV đã nghe thấy tín hiệu này và sau khi xác định tần số của nó, thực hiện hành động thích hợp - chuyển kênh, thay đổi âm lượng, tắt TV.

Hôm nay chúng ta sẽ cố gắng xây dựng lại hệ thống truyền lệnh này bằng cách sử dụng kiến ​​thức của chúng ta về bộ truyền phát phương tiện.

Để mô phỏng một điều khiển từ xa, chúng tôi sẽ sử dụng văn bản của ví dụ về trình tạo âm báo. Chúng tôi sẽ thêm vào đó khả năng kiểm soát tần số máy phát từ các lần nhấn phím và một bộ thu có bộ giải mã sẽ xuất các lệnh nhận được tới bảng điều khiển. Sau khi thay đổi, bộ tạo sẽ tạo ra âm thanh gồm 6 tần số, trong đó chúng tôi sẽ mã hóa các lệnh tăng/giảm âm lượng, chuyển kênh, bật/tắt TV. Để cấu hình máy dò, cấu trúc sau được sử dụng:

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;

Một máy dò có thể có 10 cấu trúc như vậy, do đó, một máy dò có thể được cấu hình để phát hiện XNUMX tín hiệu hai âm. Nhưng chúng ta sẽ chỉ sử dụng sáu tín hiệu đơn âm. Để chuyển cài đặt sang máy dò, phương pháp MS_TONE_DETECTOR_ADD_SCAN được sử dụng.

Để máy dò thông báo cho chúng tôi rằng tín hiệu có các thành phần tần số mong muốn đã đến đầu vào của nó, chúng tôi phải cung cấp cho nó chức năng gọi lại mà nó sẽ khởi chạy trong trường hợp này. Việc này được thực hiện bằng cách sử dụng hàm ms_filter_set_notify_callback(). Với tư cách là đối số, nó nhận được một con trỏ tới bộ lọc, một con trỏ tới hàm gọi lại và một con trỏ tới dữ liệu mà chúng ta muốn chuyển đến hàm gọi lại (dữ liệu người dùng).

Khi trình phát hiện được kích hoạt, chức năng gọi lại sẽ nhận dữ liệu người dùng, một con trỏ tới bộ lọc trình phát hiện, mã định danh sự kiện và cấu trúc mô tả sự kiện:


/** * 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;

Sơ đồ khối xử lý tín hiệu được hiển thị trong hình tiêu đề.

Vâng, bây giờ chương trình tự mã hóa với các nhận xét.

/* Файл 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("                      Принята команда: %sn", 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("Отправлена команда: %cn", 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);
    }
}

Chúng tôi biên dịch và chạy chương trình. Nếu mọi thứ hoạt động chính xác thì sau khi khởi chạy, chúng ta sẽ nhận được một cái gì đó giống như hành vi của chương trình này:

$ ./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

Nhấn bất kỳ phím nào từ “1” đến “6”, xác nhận bằng phím “Enter”, bạn sẽ nhận được kết quả giống như danh sách này:


2
Отправлена команда: 2
                      Принята команда: V-
1
Отправлена команда: 1
                      Принята команда: V+
3
Отправлена команда: 3
                      Принята команда: C+
4
Отправлена команда: 4
                      Принята команда: C-
0
$

Chúng tôi thấy rằng âm lệnh đã được gửi thành công và trình phát hiện đã phát hiện ra chúng.

Trong bài viết tiếp theo, chúng ta sẽ chuyển sang truyền tín hiệu âm thanh qua mạng Ethernet bằng giao thức RTP và áp dụng ngay vào điều khiển từ xa của mình.

Nguồn: www.habr.com

Thêm một lời nhận xét