Materi artikel dijupuk saka sandi
Detektor nada
Ing pungkasan
Ing jaman biyen, nalika ora saben kulawarga duwe TV, lan setengah saka wong-wong mau ngalih saluran nggunakake tang, kabar sing nyenengake muncul ing review saka pers teknis manca sing siji produsen TV dilengkapi piranti karo remot kontrol nirkabel. Saka rincian dikenal sing remot kontrol dilakokno tanpa baterei amarga nggunakake pendekatan mboten umum - remot kontrol mechanical lan Sato saka piranti musik - metallophone lan revolver. Drum revolver ngemot silinder logam kanthi dawa sing beda-beda, lan nalika pin tembak kena salah sijine, silinder kasebut wiwit muni kanthi frekuensi dhewe. Mesthine ing ultrasonik. Elektronik ing TV krungu sinyal kasebut lan, sawise nemtokake frekuensi, nindakake tumindak sing cocog - ngalih saluran, ngganti volume, mateni TV.
Dina iki kita bakal nyoba kanggo mbangun maneh sistem transmisi printah iki, nggunakake kawruh saka streamer media.
Kanggo simulasi remot kontrol, kita bakal nggunakake teks conto generator nada kita. Kita bakal nambah kontrol frekuensi generator saka keystrokes lan panrima karo decoder sing bakal output printah ditampa kanggo console. Sawise owah-owahan, generator kudu ngasilake nada 6 frekuensi, sing bakal kita encode perintah kanggo nambah / nyuda volume, ngganti saluran, nguripake / mateni TV. Kanggo ngatur detektor, struktur ing ngisor iki digunakake:
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;
Detektor bisa diwenehi 10 saka struktur kasebut, mula siji detektor bisa dikonfigurasi kanggo ndeteksi sepuluh sinyal rong nada. Nanging kita bakal nggunakake mung enem sinyal siji-nada. Kanggo nransfer setelan menyang detektor, metode MS_TONE_DETECTOR_ADD_SCAN digunakake.
Supaya detektor menehi kabar yen sinyal karo komponen frekuensi sing dikarepake wis teka ing input, kita kudu menehi fungsi callback sing bakal diluncurake ing kasus iki. Iki ditindakake kanthi nggunakake fungsi kasebut ms_filter_set_notify_callback(). Minangka argumen, iku nampa pointer menyang Filter, pointer menyang fungsi callback, lan pointer menyang data sing kita arep kanggo pass menyang fungsi callback (data pangguna).
Nalika detektor dipicu, fungsi callback bakal nampa data pangguna, pointer menyang filter detektor, pengenal acara, lan struktur sing nggambarake acara kasebut:
/** * 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;
Diagram blok pangolahan sinyal ditampilake ing gambar judhul.
Inggih, saiki kode program dhewe karo komentar.
/* Π€Π°ΠΉΠ» 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);
}
}
Kita ngumpulake lan mbukak program kasebut. Yen kabeh bisa mlaku kanthi bener, banjur sawise diluncurake, kita kudu njaluk kaya prilaku program iki:
$ ./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
Pencet sembarang tombol saka "1" kanggo "6", konfirmasi karo tombol "Ketik", sampeyan kudu njaluk kaya dhaftar iki:
2
ΠΡΠΏΡΠ°Π²Π»Π΅Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°: 2
ΠΡΠΈΠ½ΡΡΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π°: V-
1
ΠΡΠΏΡΠ°Π²Π»Π΅Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°: 1
ΠΡΠΈΠ½ΡΡΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π°: V+
3
ΠΡΠΏΡΠ°Π²Π»Π΅Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°: 3
ΠΡΠΈΠ½ΡΡΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π°: C+
4
ΠΡΠΏΡΠ°Π²Π»Π΅Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°: 4
ΠΡΠΈΠ½ΡΡΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π°: C-
0
$
Kita weruh yen nada printah kasil dikirim lan detektor ndeteksi.
Ing artikel sabanjure kita bakal nguripake kanggo ngirim sinyal audio liwat jaringan Ethernet nggunakake protokol RTP lan langsung aplikasi ing remot kontrol.
Source: www.habr.com