文章资料取自我的禅宗频道。

音调检测器
在上一篇文章中,我们创建了一个信号电平表。在此我们将学习如何检测音调。

在过去,并不是每个家庭都拥有电视,其中有一半是在用钳子的帮助下切换频道的。在外国技术媒体的评论中,有一个有趣的消息,其中一家电视制造商为他们的设备配备了无线遥控器。从细节上可以知道,由于使用了一种不寻常的方法,遥控器无需电池即可工作-遥控器是机械的,是乐器的混合体-金属电话和左轮手枪。左轮手枪的鼓中装有不同长度的金属圆筒,当撞针撞上其中一个时,圆筒开始以自己的频率响动。大概在超声检查中。电视中的电子设备会听到此信号,并确定其频率后,会执行相应的操作-切换频道,更改音量,关掉电视。
, .
, . , . , 6 , / , , / . :
struct _MSToneDetectorDef{
char tone_name[8];
int frequency;
int min_duration;
float min_amplitude;
};
typedef struct _MSToneDetectorDef MSToneDetectorDef;
10 , . . MS_TONE_DETECTOR_ADD_SCAN.
, , , . ms_filter_set_notify_callback(). , , , ( ).
, , , :
struct _MSToneDetectorEvent{
char tone_name[8];
uint64_t tone_start_time;
};
typedef struct _MSToneDetectorEvent MSToneDetectorEvent;
.
.
#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);
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;
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);
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
(void*)&dtmf_cfg);
}
ms_usleep(20000);
}
}
我们编译并运行该程序。如果一切正常,那么在启动后,我们应该得到以下内容:
$ ./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
按从“ 1”到“ 6”的任意键,并按“ Enter”键确认,您应该会看到类似以下内容的清单:
2
: 2
: V-
1
: 1
: V+
3
: 3
: C+
4
: 4
: C-
0
$
我们看到命令音已成功发送,并且检测器检测到它们。
在下一篇文章中,我们将转向使用RTP协议在以太网上传输声音信号,并将其立即应用到我们的遥控器中。