Le contenu de cet article est tiré de ma .
Détecteur de signal tonal
Dans le passé, Nous avons créé un mesureur de niveau de signal. Dans ce document, nous allons apprendre à détecter un signal tonal.
![]()
Dans les temps anciens, quand chaque famille n’avait pas encore de téléviseur et que la moitié d’entre elles changeaient de chaîne avec des pinces, une nouvelle intriguante est apparue dans les revues techniques étrangères : l’un des fabricants de téléviseurs avait équipé ses appareils d’une télécommande sans fil. Les détails mentionnaient que la télécommande fonctionnait sans piles grâce à un concept inhabituel — elle était mécanique et représentait un hybride entre un instrument de musique — un métallophone et un revolver. Dans le barillet du revolver se trouvaient des cylindres métalliques de différentes longueurs, et lorsque le percuteur frappait l'un d'eux, le cylindre commençait à vibrer à sa propre fréquence. Supposément à ultrasons. L’électronique dans le téléviseur recevait ce signal et, ayant déterminé sa fréquence, exécutait l'action correspondante — changer de chaîne, ajuster le volume, éteindre le téléviseur.
Aujourd'hui, nous allons essayer de recréer ce système de transmission de commandes en utilisant nos connaissances en streaming multimédia.
Pour simuler la télécommande, nous allons utiliser le texte de notre exemple de générateur tonal. Nous allons y ajouter le contrôle de la fréquence du générateur via des pressions sur le clavier et un récepteur avec décodeur qui affichera les commandes reçues dans la console. Après modification, le générateur doit émettre des signaux tonals de 6 fréquences que nous allons utiliser pour coder les commandes d'augmentation/diminution du volume, de changement de chaîne, d'allumage/extinction du téléviseur. Pour configurer le détecteur, la structure suivante est utilisée :
struct _MSToneDetectorDef{
char tone_name[8];
int frequency;
/**< Fréquence attendue du ton */
int min_duration;
/**< Durée minimale du ton en millisecondes */
float min_amplitude;
/**< Amplitude minimale du ton, 1.0 correspondant au niveau normalisé de 0dbm */
};
typedef struct _MSToneDetectorDef MSToneDetectorDef;Le détecteur peut recevoir jusqu'à 10 de ces structures, permettant ainsi de configurer un seul détecteur pour détecter dix signaux bitonaux. Mais nous n'utiliserons que six signaux monotones. Pour transmettre les paramètres au détecteur, la méthode MS_TONE_DETECTOR_ADD_SCAN est utilisée.
Pour que le détecteur puisse nous avertir lorsque son entrée reçoit un signal avec les composants de fréquence recherchés, nous devons lui fournir une fonction de rappel qu'il exécutera dans ce cas. Cela se fait à l'aide de la fonction ms_filter_set_notify_callback(). En tant qu'arguments, elle reçoit un pointeur vers le filtre, un pointeur vers la fonction de rappel et un pointeur vers les données que nous souhaitons transmettre à la fonction de rappel (données utilisateur).
Lorsque le détecteur se déclenche, la fonction de rappel recevra les données utilisateur, un pointeur vers le filtre du détecteur, l'identifiant de l'événement et une structure décrivant l'événement :
/** * 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;
Le schéma structurel de traitement du signal est montré dans l'image principale.
Et maintenant, voici le code du programme avec des commentaires.
/* Файл 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);
}
}Nous compilons et exécutons le programme. Si tout fonctionne correctement, après le démarrage, nous devrions obtenir un comportement du programme de ce type :
$ ./mstest4
ALSA lib conf.c:4738:(snd_config_expand) Paramètres inconnus 0
ALSA lib control.c:954:(snd_ctl_open_noupdate) CTL invalide default:0
ortp-avertissement-Impossible de connecter le mélangeur à la carte : Argument invalide
ALSA lib conf.c:4738:(snd_config_expand) Paramètres inconnus 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) PCM inconnu default:0
ALSA lib conf.c:4738:(snd_config_expand) Paramètres inconnus 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) PCM inconnu default:0
ortp-avertissement-Étrange, la carte son Intel 82801AA-ICH ne semble pas capable de quoi que ce soit, réessai avec plughw...
Appuyez sur une touche de commande, puis sur Entrée.
Pour terminer le programme, entrez 0.
ortp-avertissement-alsa_set_params: periodsize:256 Utilisation de 256
ortp-avertissement-alsa_set_params: period:8 Utilisation de 8
Appuyez sur n'importe quelle touche de "1" à "6", en confirmant avec la touche "Entrée", vous devriez obtenir un listing similaire :
2
Commande envoyée : 2
Commande reçue : V-
1
Commande envoyée : 1
Commande reçue : V+
3
Commande envoyée : 3
Commande reçue : C+
4
Commande envoyée : 4
Commande reçue : C-
0
$Nous voyons que les tonalités des commandes sont envoyées avec succès et que le détecteur les détecte.
Dans le prochain article, nous aborderons la transmission du signal sonore sur le réseau Ethernet à l'aide du protocole RTP et l'appliquerons directement dans notre télécommande à distance.
Source : habr.com
