рдореЗрд░реЗ рдЬрд╝реЗрди рдЪреИрдирд▓ рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд▓реЗрдЦ рд╕рд╛рдордЧреНрд░реА ред

рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рд╣рдордиреЗ рдПрдХ рдбреБрдкреНрд▓реЗрдХреНрд╕ рдЗрдВрдЯрд░рдХреЙрдо рдмрдирд╛рдпрд╛ рдЬреЛ рдПрдХ рдбреБрдкреНрд▓реЗрдХреНрд╕ рдЖрд░рдЯреАрдкреА рд╕рддреНрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдСрдбрд┐рдпреЛ рд╕рд┐рдЧреНрдирд▓ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ рдФрд░ рдбреВ-рдЗрдЯ-рдЦреБрдж рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рдбреВ-рдЗрдЯ-рдЦреБрдж рдЗрдВрдЯрд░рдХреЙрдо рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред
рд╣рдо рдПрдХ рдкреНрд▓рдЧрдЗрди рд╡рд┐рдХрд╕рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ

, , .
, include . , ms_filter_register() . , .
. , , . , , .
, _ (NASH_FILTR). тАФ . , , .
. / .
. . msfilter.h, MS_FILTER_METHOD ( ), ( ) MSFilterDesc . :
struct _MSFilterDesc{
MSFilterId id;
const char *name;
const char *text;
MSFilterCategory category;
const char *enc_fmt;
int ninputs;
int noutputs;
MSFilterFunc init;
MSFilterFunc preprocess;
MSFilterFunc process;
MSFilterFunc postprocess;
MSFilterFunc uninit;
MSFilterMethod *methods;
unsigned int flags;
};
typedef struct _MSFilterDesc MSFilterDesc;
, msfilter.h. :
#ifndef myfilter_h
#define myfilter_h
#include <mediastreamer2/msticker.h>
#define NASH_FILTER_ID 4000
#define NASH_FILTER_SET_TRESHOLD MS_FILTER_METHOD(NASH_FILTER_ID , 0, float)
#define NASH_FILTER_TUNE_OFF MS_FILTER_METHOD_NO_ARG(NASH_FILTER_ID ,1)
#define NASH_FILTER_TUNE_ON MS_FILTER_METHOD_NO_ARG(NASH_FILTER_ID ,2)
struct _NASHFilterEvent
{
char state;
uint64_t time;
};
typedef struct _NASHFilterEvent NASHFilterEvent;
#define NASH_FILTER_EVENT MS_FILTER_EVENT(MS_RTP_RECV_ID, 0, NASHFilterEvent)
extern MSFilterDesc nash_filter_desc;
#endif
. . , . nash_filter_desc. " " .
#include "nash_filter.h"
#include <math.h>
#define NASH_FILTER_NOUTPUTS 5
typedef struct _nash_filterData
{
bool_t disable_out;
int last_state;
char zero_count;
char lag;
char n_count;
float skz_level;
} nash_filterData;
static void nash_filter_init(MSFilter *f)
{
nash_filterData *d=ms_new0(nash_filterData, 1);
d->lag=5;
f->data=d;
}
static void nash_filter_uninit(MSFilter *f)
{
ms_free(f->data);
}
char zero_array[1024]={0};
NASHFilterEvent event;
static void send_event(MSFilter *f, int state)
{
nash_filterData *d =( nash_filterData* ) f->data;
d->last_state = state;
event.time=f -> ticker -> time;
event.state=state;
ms_filter_notify(f, NASH_FILTER_EVENT, &event);
}
static float calc_skz(nash_filterData *d, int16_t *signal, int numsamples)
{
int i;
float acc = 0;
for (i=0; i<numsamples; i++)
{
int s=signal[i];
acc = acc + s * s;
}
float skz = (float)sqrt(acc / numsamples);
return skz;
}
static void nash_filter_process(MSFilter *f)
{
nash_filterData *d=(nash_filterData*)f->data;
mblk_t *im;
int i;
int state;
while((im=ms_queue_get(f->inputs[0]))!=NULL)
{
if ( d -> disable_out)
{
freemsg(im);
continue;
}
float skz = calc_skz(d, (int16_t*)im->b_rptr, msgdsize(im));
state = (skz > d->skz_level) ? 1 : 0;
if (state)
{
d->n_count++;
d->zero_count = 0;
}
else
{
d->n_count = 0;
d->zero_count++;
}
if (((d->zero_count > d->lag) || (d->n_count > d->lag))
&& (d->last_state != state)) send_event(f, state);
int output_count = 0;
mblk_t *outm;
for(i=0; i < f->desc->noutputs; i++)
{
if (f->outputs[i]!=NULL)
{
if (output_count == 0)
{
outm = im;
}
else
{
outm = dupmsg(im);
}
ms_queue_put(f->outputs[i], outm);
output_count++;
}
}
}
}
static int nash_filter_set_treshold(MSFilter *f, void *arg)
{
nash_filterData *d=(nash_filterData*)f->data;
d->skz_level=*(float*)arg;
return 0;
}
static int nash_filter_tune_off(MSFilter *f, void *arg)
{
nash_filterData *d=(nash_filterData*)f->data;
d->disable_out=TRUE;
return 0;
}
static int nash_filter_tune_on(MSFilter *f, void *arg)
{
nash_filterData *d=(nash_filterData*)f->data;
d->disable_out=FALSE;
return 0;
}
static MSFilterMethod nash_filter_methods[]={
{ NASH_FILTER_SET_TRESHOLD, nash_filter_set_treshold },
{ NASH_FILTER_TUNE_OFF, nash_filter_tune_off },
{ NASH_FILTER_TUNE_ON, nash_filter_tune_on },
{ 0 , NULL }
};
MSFilterDesc nash_filter_desc=
{
NASH_FILTER_ID,
"NASH_FILTER",
"A filter with noise gate that reads from input and copy to it's five outputs.",
MS_FILTER_OTHER,
NULL,
1,
NASH_FILTER_NOUTPUTS,
nash_filter_init,
NULL,
nash_filter_process,
NULL,
nash_filter_uninit,
nash_filter_methods,
0
};
MS_FILTER_DESC_EXPORT(nash_filter_desc)
, , . .
- - . .
-, wav. , . .
. , . "0", . "1" .
: --ng
, --rec
, record.wav.
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/msrtp.h>
#include <mediastreamer2/msfilerec.h>
#include "nash_filter.h"
#include "mstest_common.c"
struct _app_vars
{
int local_port;
int remote_port;
char remote_addr[128];
MSDtmfGenCustomTone dtmf_cfg;
MSFilter* recorder;
bool_t file_is_open;
float treshold;
bool_t en_rec;
};
typedef struct _app_vars app_vars;
RtpSession* create_duplex_rtp_session(app_vars v)
{
RtpSession *session = create_rtpsession (v.local_port, v.local_port + 1,
FALSE, RTP_SESSION_SENDRECV);
rtp_session_set_remote_addr_and_port(session, v.remote_addr, v.remote_port,
v.remote_port + 1);
rtp_session_set_send_payload_type(session, PCMU);
return session;
}
void scan_args(int argc, char *argv[], app_vars *v)
{
char i;
for (i=0; i<argc; i++)
{
if (!strcmp(argv[i], "--help"))
{
char *p=argv[0]; p=p + 2;
printf(" %s walkie talkie\n\n", p);
printf("--help List of options.\n");
printf("--version Version of application.\n");
printf("--addr Remote abonent IP address string.\n");
printf("--port Remote abonent port number.\n");
printf("--lport Local port number.\n");
printf("--gen Generator frequency.\n");
printf("--ng Noise gate treshold level from 0. to 1.0\n");
printf("--rec record to file 'record.wav'.\n");
exit(0);
}
if (!strcmp(argv[i], "--version"))
{
printf("0.1\n");
exit(0);
}
if (!strcmp(argv[i], "--addr"))
{
strncpy(v->remote_addr, argv[i+1], 16);
v->remote_addr[16]=0;
printf("remote addr: %s\n", v->remote_addr);
}
if (!strcmp(argv[i], "--port"))
{
v->remote_port=atoi(argv[i+1]);
printf("remote port: %i\n", v->remote_port);
}
if (!strcmp(argv[i], "--lport"))
{
v->local_port=atoi(argv[i+1]);
printf("local port : %i\n", v->local_port);
}
if (!strcmp(argv[i], "--gen"))
{
v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
printf("gen freq : %i\n", v -> dtmf_cfg.frequencies[0]);
}
if (!strcmp(argv[i], "--ng"))
{
v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
printf("noise gate treshold: %f\n", v -> treshold);
}
if (!strcmp(argv[i], "--rec"))
{
v -> en_rec = TRUE;
printf("enable recording: %i\n", v -> en_rec);
}
}
}
static void change_detected_cb(void *data, MSFilter *f, unsigned int event_id,
NASHFilterEvent *ev)
{
app_vars *vars = (app_vars*) data;
if (! vars -> en_rec) return;
if (ev -> state)
{
if(!vars->file_is_open)
{
ms_filter_call_method(vars->recorder, MS_FILE_REC_OPEN, "record.wav");
vars->file_is_open = 1;
}
ms_filter_call_method(vars->recorder, MS_FILE_REC_START, 0);
printf("Recording...\n");
}
else
{
ms_filter_call_method(vars->recorder, MS_FILE_REC_STOP, 0);
printf("Pause...\n");
}
}
int main(int argc, char *argv[])
{
app_vars vars={5004, 7010, "127.0.0.1", {0}, 0, 0, 0.01, 0};
scan_args(argc, argv, &vars);
ms_init();
MSSndCard *snd_card =
ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
MSFilter *snd_card_read = ms_snd_card_create_reader(snd_card);
MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
MSFilter *rtpsend = ms_filter_new(MS_RTP_SEND_ID);
MSFilter *encoder = ms_filter_create_encoder("PCMU");
register_payloads();
RtpSession* rtp_session = create_duplex_rtp_session(vars);
ms_filter_call_method(rtpsend, MS_RTP_SEND_SET_SESSION, rtp_session);
ms_filter_link(snd_card_read, 0, dtmfgen, 0);
ms_filter_link(dtmfgen, 0, encoder, 0);
ms_filter_link(encoder, 0, rtpsend, 0);
MSFilter *rtprecv = ms_filter_new(MS_RTP_RECV_ID);
ms_filter_call_method(rtprecv, MS_RTP_RECV_SET_SESSION, rtp_session);
MSFilter *decoder=ms_filter_create_decoder("PCMU");
ms_filter_register(&nash_filter_desc);
MSFilter *nash = ms_filter_new(NASH_FILTER_ID);
MSFilter *snd_card_write = ms_snd_card_create_writer(snd_card);
MSFilter *recorder=ms_filter_new(MS_FILE_REC_ID);
vars.recorder = recorder;
ms_filter_link(rtprecv, 0, decoder, 0);
ms_filter_link(decoder, 0, nash, 0);
ms_filter_link(nash, 0, snd_card_write, 0);
ms_filter_link(nash, 1, recorder, 0);
ms_filter_set_notify_callback(nash,
(MSFilterNotifyFunc)change_detected_cb, &vars);
ms_filter_call_method(nash,NASH_FILTER_SET_TRESHOLD, &vars.treshold);
MSTicker *ticker = ms_ticker_new();
ms_ticker_attach(ticker, snd_card_read);
ms_ticker_attach(ticker, rtprecv);
if (vars.dtmf_cfg.frequencies[0])
{
vars.dtmf_cfg.duration = 10000;
vars.dtmf_cfg.amplitude = 1.0;
}
printf("Press ENTER to exit.\n ");
char c=getchar();
while(c != '\n')
{
if(vars.dtmf_cfg.frequencies[0])
{
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
(void*)&vars.dtmf_cfg);
}
char c=getchar();
printf("--\n");
}
if (vars.en_rec ) ms_filter_call_method(recorder, MS_FILE_REC_CLOSE, 0);
}
- , math, , , :
$ gcc mstest9.c nash_filter.c -o mstest9 `pkg-config mediastreamer --libs --cflags` -lm
, :
$ ./mstest9 --lport 7010 --port 8010 --addr < > --rec
:
$ ./mstest9 --lport 8010 --port 7010 --addr < >
, . "Recording...". "Pause...". .
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдордиреЗ рд╕реАрдЦрд╛ рдХрд┐ рдХреИрд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рд▓рд┐рдЦрдирд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рджреЗрдЦрд╛ рд╣реЛрдЧрд╛, nash_filter_process () рдлрд╝рдВрдХреНрд╢рди рдбреЗрдЯрд╛ рдмреНрд▓реЙрдХ рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдЙрджрд╛рд╣рд░рдг рдПрдХ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдЙрджрд╛рд╣рд░рдг рд╣реИ, рдЗрд╕рд▓рд┐рдП рдбреЗрдЯрд╛ рдмреНрд▓реЙрдХ рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХреЗ рд▓рд┐рдП рдиреНрдпреВрдирддрдо рдореАрдбрд┐рдпрд╛ рд╕реНрдЯреНрд░реАрдорд░ рдХреНрд╖рдорддрд╛рдПрдВ рд╢рд╛рдорд┐рд▓ рдереАрдВред
рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рдФрд░ рд╕рдВрджреЗрд╢ рдкреНрд░рдмрдВрдзрди рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗред рдЬреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╕реВрдЪрдирд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдлрд┐рд▓реНрдЯрд░ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред