Π˜Π·ΡƒΡ‡Π°Π΅ΠΌ VoIP-Π΄Π²ΠΈΠΆΠΎΠΊ Mediastreamer2. Π§Π°ΡΡ‚ΡŒ 10

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» ΡΡ‚Π°Ρ‚ΡŒΠΈ взят с ΠΌΠΎΠ΅Π³ΠΎ Π΄Π·Π΅Π½-ΠΊΠ°Π½Π°Π»Π°.

Π’ ΠΏΡ€ΠΎΡˆΠ»ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ сдСлали дуплСксноС ΠΏΠ΅Ρ€Π΅Π³ΠΎΠ²ΠΎΡ€Π½ΠΎΠ΅ устройство, Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰Π΅Π΅ ΠΎΠ±ΠΌΠ΅Π½ Π·Π²ΡƒΠΊΠΎΠ²Ρ‹ΠΌ сигналом Ρ‡Π΅Ρ€Π΅Π· Π΄ΡƒΠΏΠ»Π΅ΠΊΡΠ½ΡƒΡŽ RTP-сСссию. Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ научимся ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ сдСланный своими Ρ€ΡƒΠΊΠ°ΠΌΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π² сдСланноС своими Ρ€ΡƒΠΊΠ°ΠΌΠΈ ΠΏΠ΅Ρ€Π΅Π³ΠΎΠ²ΠΎΡ€Π½ΠΎΠ΅ устройство.

Π Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ ΠΏΠ»Π°Π³ΠΈΠ½

Π˜Π·ΡƒΡ‡Π°Π΅ΠΌ VoIP-Π΄Π²ΠΈΠΆΠΎΠΊ Mediastreamer2. Π§Π°ΡΡ‚ΡŒ 10

ΠŸΠ»Π°Π³ΠΈΠ½Ρ‹ Π² мСдиастримСрС, ΠΊΠ°ΠΊ ΠΈ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°Ρ…, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ для Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π° Π±Π΅Π· нСобходимости пСрСкомпиляции самого мСдиастримСра.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ»Π°Π³ΠΈΠ½ Π² своСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅, Π²Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ include Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΏΠ»Π°Π³ΠΈΠ½Π°. Π’ Ρ‚Π΅Π»Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρƒ ms_filter_register() Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Ρ€Π΅Π³ΠΈΡΡ‚Ρ€Π°Ρ†ΠΈΡŽ Π½ΠΎΠ²ΠΎΠ³ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°. ЕстСствСнно, ваша ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΈ ΠΈ исходник ΠΏΠ»Π°Π³ΠΈΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ скомпилированы ΠΈ собраны Π² ΠΎΠ΄Π½ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ обратимся ΠΊ написанию ΠΏΠ»Π°Π³ΠΈΠ½Π°. ВсС Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ мСдиастримСра ΠΈ ΠΏΠ»Π°Π³ΠΈΠ½Ρ‹ ΠΏΠΎΠ΄Ρ‡ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² написании ΠΎΠ±Ρ‰Π΅ΠΌΡƒ ΠΊΠ°Π½ΠΎΠ½Ρƒ, Ρ‡Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ устройства ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹ Π·Π°Ρ…ΠΎΡ‚Π΅Π»ΠΈ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π΄Π°Π»Π΅Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Ρ€Π°Π·ΠΌΠ½ΠΎΠΆΠ°Ρ‚ΡŒ сущности, ΠΏΠ»Π°Π³ΠΈΠ½Ρ‹ Π±ΡƒΠ΄Ρƒ Π½Π°Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°ΠΌΠΈ.

ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ с Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ НАШ_Π€Π˜Π›Π¬Π’Π  (NASH_FILTR). Он Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΡΠ»Π΅ΠΌΠ΅Π½Ρ‚Π°Ρ€Π½ΡƒΡŽ Π²Π΅Ρ‰ΡŒ β€” ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ Π±Π»ΠΎΠΊΠΈ со своСго СдинствСнного Π²Ρ…ΠΎΠ΄Π° ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Π½Π° свои ΠΏΡΡ‚ΡŒ Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠ². А Π΅Ρ‰Π΅ ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ событиС, Π² случаС Ссли Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ ΠΏΡ€ΠΎΠΉΠ΄Π΅Ρ‚ Π±ΠΎΠ»Π΅Π΅ пяти Π±Π»ΠΎΠΊΠΎΠ² с ΡƒΡ€ΠΎΠ²Π½Π΅ΠΌ сигнала Π½ΠΈΠΆΠ΅ Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ€ΠΎΠ³Π° ΠΈ Ссли Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ ΠΏΡ€ΠΎΠΉΠ΄Π΅Ρ‚ Π±ΠΎΠ»Π΅Π΅ пяти Π±Π»ΠΎΠΊΠΎΠ² с ΡƒΡ€ΠΎΠ²Π½Π΅ΠΌ Π²Ρ‹ΡˆΠ΅ ΠΏΠΎΡ€ΠΎΠ³Π°, ΠΎΠ½ Ρ‚ΠΎΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ событиС.

ΠŸΠΎΡ€ΠΎΠ³ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒΡΡ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°. Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΈ Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ/Π²ΠΎΡΠΏΡ€Π΅Ρ‰Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ…ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΎΠ² Π½Π° Π²Ρ‹Ρ…ΠΎΠ΄Ρ‹.

ΠŸΡ€ΠΈΡΡ‚ΡƒΠΏΠ°Π΅ΠΌ. НаписаниС Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° Π½ΡƒΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒ с Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°. Он Π² ΠΏΠ΅Ρ€Π²Ρ‹Ρ… строках Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Ρ„Π°ΠΉΠ» msfilter.h, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ макроса MS_FILTER_METHOD ΠΎΠ±ΡŠΡΠ²ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π½ΠΎΠ²ΠΎΠ³ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° (Ссли ΠΎΠ½ΠΈ Π΅ΡΡ‚ΡŒ), ΠΎΠ±ΡŠΡΠ²ΠΈΡ‚ΡŒ события Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠΌ (Ссли ΠΎΠ½ΠΈ Π΅ΡΡ‚ΡŒ) ΠΈ ΠΎΠ±ΡŠΡΠ²ΠΈΡ‚ΡŒ ΡΠΊΡΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌΡƒΡŽ структуру Ρ‚ΠΈΠΏΠ° MSFilterDesc с описаниСм ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°:

/* Π€Π°ΠΉΠ» nash_filter.h, описываСт Ρ„ΠΈΠ»ΡŒΡ‚Ρ€-Ρ€Π°Π·Π²Π΅Ρ‚Π²ΠΈΡ‚Π΅Π»ΡŒ ΠΈ Π½ΠΎΠΉΠ·Π³Π΅ΠΉΡ‚. */

#ifndef myfilter_h
#define myfilter_h

/* ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» с пСрСчислСниСм Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² мСдиастримСра. */
#include <mediastreamer2/msticker.h>

/* 
   Π—Π°Π΄Π°Π΅ΠΌ числовой ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π½ΠΎΠ²ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°.  Π­Ρ‚ΠΎ число Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
   ΡΠΎΠ²ΠΏΠ°Π΄Π°Ρ‚ΡŒ Π½ΠΈ с ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ².  Π’ мСдиастримСрС  Π² Ρ„Π°ΠΉΠ»Π΅ allfilters.h
   Π΅ΡΡ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ пСрСчислСниС enum MSFilterId. К соТалСнию, нСпонятно
   ΠΊΠ°ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ максимальноС занятоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΡ€ΠΎΠΌΠ΅ ΠΊΠ°ΠΊ Π·Π°Π³Π»ΡΠ½ΡƒΡ‚ΡŒ Π² этот
   Ρ„Π°ΠΉΠ». Но ΠΌΡ‹ возьмСм Π² качСствС id для нашСго Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° Π·Π°Π²Π΅Π΄ΠΎΠΌΠΎ большСС
   Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅: 4000.  Π‘ΡƒΠ΄Π΅ΠΌ ΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ добавляя Π½ΠΎΠ²Ρ‹Π΅ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹, Π½Π΅
   скоро добСрутся Π΄ΠΎ этого Π½ΠΎΠΌΠ΅Ρ€Π°.  
   */
#define NASH_FILTER_ID 4000

/* 
   ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ нашСго Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°. Π’Ρ‚ΠΎΡ€Ρ‹ΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ макроса Π΄ΠΎΠ»ΠΆΠ΅Π½
   порядковый Π½ΠΎΠΌΠ΅Ρ€ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, число ΠΎΡ‚ 0.  Π’Ρ€Π΅Ρ‚ΠΈΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ это Ρ‚ΠΈΠΏ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°
   ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒΡΡ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅. Π£ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ²
   Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈ Π½Π΅ Π±Ρ‹Ρ‚ΡŒ, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½ΠΈΠΆΠ΅. 
   */
#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
{
    /* Π­Ρ‚ΠΎ ΠΏΠΎΠ»Π΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Ρ€ΠΎΠ»ΡŒ Ρ„Π»Π°Π³Π°,
       0 - появились Π½ΡƒΠ»ΠΈ, 1 - появился сигнал.*/
    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 /* myfilter_h */

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π½ΡΡ‚ΡŒΡΡ исходным Ρ„Π°ΠΉΠ»ΠΎΠΌ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° с коммСнтариями ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅. Π—Π΄Π΅ΡΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°, ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°. Π—Π°Ρ‚Π΅ΠΌ ссылки Π½Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ порядкС ΠΏΠΎΠΌΠ΅Ρ‰Π°ΡŽΡ‚ΡΡ Π² ΡΠΊΡΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌΡƒΡŽ структуру nash_filter_desc. ΠšΠΎΡ‚ΠΎΡ€Π°Ρ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ мСдиастримСром для "вТивлСния " Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Π² Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ процСсс ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ….

/* Π€Π°ΠΉΠ» nash_filter.с, описываСт Ρ„ΠΈΠ»ΡŒΡ‚Ρ€-Ρ€Π°Π·Π²Π΅Ρ‚Π²ΠΈΡ‚Π΅Π»ΡŒ ΠΈ Π½ΠΎΠΉΠ·Π³Π΅ΠΉΡ‚. */

#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);

        /* ΠŸΡ€ΠΈΡΡ‚ΡƒΠΏΠ°Π΅ΠΌ ΠΊ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ сообщСния ΠΈ раскладкС ΠΏΠΎ Π²Ρ‹Ρ…ΠΎΠ΄Π°ΠΌ. Но
         * Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ Ρ‚Π΅ΠΌ, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Π° Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠ°. ΠžΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ΅ сообщСниС
         * ΡƒΠΉΠ΄Π΅Ρ‚ Π½Π° Π²Ρ‹Ρ…ΠΎΠ΄ с индСксом 0, Π° Π΅Π³ΠΎ ΠΊΠΎΠΏΠΈΠΈ ΠΏΠΎΠΏΠ°Π΄ΡƒΡ‚ Π½Π° ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
         * Π²Ρ‹Ρ…ΠΎΠ΄Ρ‹. */ 
        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++;
            }
        }
    }
}

/*----------------------------------------------------------*/
/* Ѐункция-ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° NASH_FILTER_SET_LAG. */
static int nash_filter_set_treshold(MSFilter *f, void *arg)
{
    nash_filterData *d=(nash_filterData*)f->data;
    d->skz_level=*(float*)arg;
    return 0;
}

/*----------------------------------------------------------*/
/* Ѐункция-ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° NASH_FILTER_TUNE_OFF. */
static int nash_filter_tune_off(MSFilter *f, void *arg)
{
    nash_filterData *d=(nash_filterData*)f->data;
    d->disable_out=TRUE;
    return 0;
}

/*----------------------------------------------------------*/
/* Ѐункция-ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° NASH_FILTER_TUNE_ON. */
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
};

MS_FILTER_DESC_EXPORT(nash_filter_desc)

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, Π½Π΅ откладывая Π² Π΄ΠΎΠ»Π³ΠΈΠΉ ящик, ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ наш Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π² сдСланном Ρ€Π°Π½Π΅Π΅ ΠΏΠ΅Ρ€Π΅Π³ΠΎΠ²ΠΎΡ€Π½ΠΎΠΌ устройствС. На Π·Π°Π³Π»Π°Π²Π½ΠΎΠΉ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π½Π° схСма Π²ΠΈΠ΄ΠΎΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ΅Ρ€Π΅Π³ΠΎΠ²ΠΎΡ€Π½ΠΎΠ³ΠΎ устройства.
Наш собствСнноручный Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ ΠΈΠ·ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ΡŒ ΠΊΠ°ΠΊ-Ρ‚ΠΎ ΠΏΠΎ-особСнному ярко. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π²Ρ‹ сразу Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° схСмС наш Ρ„ΠΈΠ»ΡŒΡ‚Ρ€.

Π’ схСму добавился Ρ„ΠΈΠ»ΡŒΡ‚Ρ€-рСгистратор, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΈΡˆΠ΅Ρ‚ Π²Ρ…ΠΎΠ΄Π½ΠΎΠΉ сигнал Π² Ρ„Π°ΠΉΠ» Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° wav. По замыслу, наш Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Π½Π΅ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π² Ρ„Π°ΠΉΠ» ΠΏΠ°ΡƒΠ·Ρ‹ Π² Ρ€Π΅Ρ‡ΠΈ. Π’Π΅ΠΌ самым сокращая Π΅Π³ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€.
Π’ Π½Π°Ρ‡Π°Π»Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ ΠΌΡ‹ описали Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ дСйствий Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°. Π’ основном ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ выполняСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° событий, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ½ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚. Если событиС содСрТит Ρ„Π»Π°Π³ "0", Ρ‚ΠΎ основноС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ приостанавливаСт запись. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΠ΄Π΅Ρ‚ событиС с Ρ„Π»Π°Π³ΠΎΠΌ "1" запись возобновляСтся.

К ΠΏΡ€Π΅ΠΆΠ½ΠΈΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки добавились Π΅Ρ‰Π΅ Π΄Π²Π°: --ng, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π·Π°Π΄Π°Π΅Ρ‚ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ ΠΏΠΎΡ€ΠΎΠ³Π° срабатывания Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° ΠΈ --rec, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ запускаСт запись Π² Ρ„Π°ΠΉΠ» с ΠΈΠΌΠ΅Π½Π΅ΠΌ record.wav.

/* Π€Π°ΠΉΠ» mstest9.c Π˜ΠΌΠΈΡ‚Π°Ρ‚ΠΎΡ€ ΠΏΠ΅Ρ€Π΅Π³ΠΎΠ²ΠΎΡ€Π½ΠΎΠ³ΠΎ устройства c рСгистратором ΠΈ
* Π½ΠΎΠΉΠ·Π³Π΅ΠΉΡ‚ΠΎΠΌ. */
#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];        /* IP-адрСс ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°. */
MSDtmfGenCustomTone dtmf_cfg; /* Настройки тСстового сигнала Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π°. */
MSFilter* recorder;           /* Π£ΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ рСгистратор. */
bool_t file_is_open;          /* Π€Π»Π°Π³ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Ρ„Π°ΠΉΠ» для записи ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚. */
/* ΠŸΠΎΡ€ΠΎΠ³, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ прСкращаСтся запись ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌΠΎΠ³ΠΎ сигнала Π² Ρ„Π°ΠΉΠ». */
float treshold; 
bool_t en_rec;                /*Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ запись Π² Ρ„Π°ΠΉΠ».*/    
};
typedef struct _app_vars app_vars;
/*----------------------------------------------------------*/
/* Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ Π΄ΡƒΠΏΠ»Π΅ΠΊΡΠ½ΡƒΡŽ RTP-сСссию. */
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 talkienn", 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.0n");
printf("--rec       record to file 'record.wav'.n");
exit(0);
}
if (!strcmp(argv[i], "--version"))
{
printf("0.1n");
exit(0);
}
if (!strcmp(argv[i], "--addr"))
{
strncpy(v->remote_addr, argv[i+1], 16);
v->remote_addr[16]=0;
printf("remote addr: %sn", v->remote_addr);
}
if (!strcmp(argv[i], "--port"))
{
v->remote_port=atoi(argv[i+1]);
printf("remote port: %in", v->remote_port);
}
if (!strcmp(argv[i], "--lport"))
{
v->local_port=atoi(argv[i+1]);
printf("local port : %in", v->local_port);
}
if (!strcmp(argv[i], "--gen"))
{
v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
printf("gen freq : %in", v -> dtmf_cfg.frequencies[0]);
}
if (!strcmp(argv[i], "--ng"))
{
v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
printf("noise gate treshold: %fn", v -> treshold);
}
if (!strcmp(argv[i], "--rec"))
{
v -> en_rec = TRUE;
printf("enable recording: %in", 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();
/* Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ Π΄ΡƒΠΏΠ»Π΅ΠΊΡΠ½ΡƒΡŽ RTP-сСссию. */
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_FILE_REC_ID
/* РСгистрируСм наш Ρ„ΠΈΠ»ΡŒΡ‚Ρ€. */
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() Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ манипуляции с Π±Π»ΠΎΠΊΠ°ΠΌΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΡ‡Π΅Π±Π½Ρ‹ΠΉ, Ρ‚ΠΎ Ρ‚Π°ΠΌ Π±Ρ‹Π» задСйствован ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ возмоТностСй мСдиастримСра ΠΏΠΎ манипуляциям с Π±Π»ΠΎΠΊΠ°ΠΌΠΈ Π΄Π°Π½Π½Ρ‹Ρ….

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ рассмотрим ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄Π΅ΠΉ сообщСний ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ управлСния сообщСниями. Π§Ρ‚ΠΎ Π² дальнСйшСм ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ с Π±ΠΎΠ»Π΅Π΅ слоТной ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com