> > A few month ago, I wrote a mprDecodeInbandDtmf.cpp that works quite
well.
> >
> > I can try to post it here if you are interested.
>
> I believe we all would be interested. So, please, post it to issue tracker
too.
>
> I suppose, it detect DTMF, mixed with audio stream, right? Does it use
> some third-party library for this?

No it doesn't use any third party library. I wrote everything from scratch.

However, it was for a test many months ago, and it's built against an old
rev of
sipxtapi-media-update. It's very hard to make a diff with current version.

---------------------------------------------
mprDecodeInbandDtmf.h
---------------------------------------------

#ifndef _MprDecodeInBandDtmf_h_

#define _MprDecodeInBandDtmf_h_

// APPLICATION INCLUDES

#include "mp/MpFlowGraphMsg.h"

#include "mp/MpAudioResource.h"

// DEFINES

// MACROS

// EXTERNAL FUNCTIONS

// EXTERNAL VARIABLES

// CONSTANTS

// STRUCTS

// TYPEDEFS

// FORWARD DECLARATIONS

/**

* @brief The "Audio from file" media processing resource

*/

class MprDecodeInBandDtmf : public MpAudioResource

{

/* //////////////////////////// PUBLIC ////////////////////////////////////
*/

public:

friend class MpConnection;

/* ============================ CREATORS ==================================
*/

///@name Creators

//@{

//:Constructor

MprDecodeInBandDtmf(const UtlString& rName, MpConnection* pConn, int
samplesPerFrame, int samplesPerSec);

//:Destructor

virtual

~MprDecodeInBandDtmf();

//@}

/* ============================ MANIPULATORS ==============================
*/

///@name Manipulators

//@{

//@}

/* ============================ ACCESSORS =================================
*/

///@name Accessors

//@{

//@}

/* ============================ INQUIRY ===================================
*/

///@name Inquiry

//@{

//@}

/* //////////////////////////// PROTECTED /////////////////////////////////
*/

protected:

/* //////////////////////////// PRIVATE ///////////////////////////////////
*/

private:

OsNotification* mpNotify;

MpConnection* mpConnection; ///< Link to the parent Connection.

int m_dtmfLastDigit;

int m_sameDtmfDigitCount;

int m_dtmfRound;

virtual UtlBoolean doProcessFrame(MpBufPtr inBufs[],

MpBufPtr outBufs[],

int inBufsSize,

int outBufsSize,

UtlBoolean isEnabled,

int samplesPerFrame=80,

int samplesPerSecond=8000);

/// Goertzel

double Goertzel( MpAudioSample *input, int numsamples, double frequency,
double samplerate);



/// Handle messages for this resource.

virtual UtlBoolean handleMessage(MpFlowGraphMsg& rMsg);

/// Copy constructor (not implemented for this class)

MprDecodeInBandDtmf(const MprDecodeInBandDtmf& rMprDecodeInBandDtmf);

/// Assignment operator (not implemented for this class)

MprDecodeInBandDtmf& operator=(const MprDecodeInBandDtmf& rhs);

};

/* ============================ INLINE METHODS ============================
*/

#endif // _MprDecodeInBandDtmf_h_


---------------------------------------------
mprDecodeInbandDtmf.cpp
---------------------------------------------

// SYSTEM INCLUDES

#include <assert.h>

#include <stdio.h>

#include <math.h>

#ifdef __pingtel_on_posix__

#include <stdlib.h>

#endif

// APPLICATION INCLUDES

#include "os/OsDefs.h"

#include "os/OsEvent.h"

#include "mp/MpCallFlowGraph.h"

#include "mp/MpBuf.h"

#include "mp/MprDecodeInBandDtmf.h"

#include "os/OsSysLog.h"

#include "../../sipXmediaAdapterLib\interface\mi\CpMediaInterface.h"

#define PI 3.1415926

#define PIt2 (2.0 * PI)

#define TwoPI PIt2



// EXTERNAL FUNCTIONS

// EXTERNAL VARIABLES

static const int NO_WAIT = 0;

// STATIC VARIABLE INITIALIZATIONS

/* //////////////////////////// PUBLIC ////////////////////////////////////
*/

/* ============================ CREATORS ==================================
*/

// Constructor

MprDecodeInBandDtmf::MprDecodeInBandDtmf(const UtlString& rName,

MpConnection* pConn,

int samplesPerFrame,

int samplesPerSec)

: MpAudioResource(rName, 0, 1, 1, 1, samplesPerFrame, samplesPerSec),

mpNotify(NULL), mpConnection(pConn),m_dtmfLastDigit(1000),

m_dtmfRound(0), m_sameDtmfDigitCount(0)

{

}

// Destructor

MprDecodeInBandDtmf::~MprDecodeInBandDtmf()

{

}

/* ============================ MANIPULATORS ==============================
*/

/* ============================ ACCESSORS =================================
*/

/* ============================ INQUIRY ===================================
*/

/* //////////////////////////// PROTECTED /////////////////////////////////
*/

/* //////////////////////////// PRIVATE ///////////////////////////////////
*/

UtlBoolean MprDecodeInBandDtmf::doProcessFrame(MpBufPtr inBufs[],

MpBufPtr outBufs[],

int inBufsSize,

int outBufsSize,

UtlBoolean isEnabled,

int samplesPerFrame,

int samplesPerSecond)

{

MpAudioBufPtr in;

MpAudioSample* input;

int numSamples = 0;

// try to pass along first input

if (inBufsSize > 0)

in.swap(inBufs[0]);

if (numOutputs() > 0)

outBufs[0] = in;

if (!isEnabled) {

return TRUE;

}

if( ! in.isValid()) {

return TRUE;

}

// GET SAMPLES

input = in->getSamples();

numSamples = in->getSamplesNumber();

int dtmfDigit = 1000;

double d697 = Goertzel(input, numSamples, 697, 8000);

double d770 = Goertzel(input, numSamples, 770, 8000);

double d852 = Goertzel(input, numSamples, 852, 8000);

double d941 = Goertzel(input, numSamples, 941, 8000);

double d1209 = Goertzel(input, numSamples, 1209, 8000);

double d1336 = Goertzel(input, numSamples, 1336, 8000);

double d1477 = Goertzel(input, numSamples, 1477, 8000);

double d1633 = Goertzel(input, numSamples, 1633, 8000);


int seuilInt = 150000;


if (d697 > seuilInt && d1209 > seuilInt)

dtmfDigit = 1;

else if (d697 > seuilInt && d1336 > seuilInt)

dtmfDigit = 2;

else if (d697 > seuilInt && d1477 > seuilInt)

dtmfDigit = 3;

else if (d697 > seuilInt && d1633 > seuilInt)

dtmfDigit = 12; //'A';

else if (d770 > seuilInt && d1209 > seuilInt)

dtmfDigit = 4;

else if (d770 > seuilInt && d1336 > seuilInt)

dtmfDigit = 5;

else if (d770 > seuilInt && d1477 > seuilInt)

dtmfDigit = 6;

else if (d770 > seuilInt && d1633 > seuilInt)

dtmfDigit = 13; // 'B';

else if (d852 > seuilInt && d1209 > seuilInt)

dtmfDigit = 7;

else if (d852 > seuilInt && d1336 > seuilInt)

dtmfDigit = 8;

else if (d852 > seuilInt && d1477 > seuilInt)

dtmfDigit = 9;

else if (d852 > seuilInt && d1633 > seuilInt)

dtmfDigit = 14; // 'C';

else if (d941 > seuilInt && d1209 > seuilInt)

dtmfDigit = 10; // '*';

else if (d941 > seuilInt && d1336 > seuilInt)

dtmfDigit = 0;

else if (d941 > seuilInt && d1477 > seuilInt)

dtmfDigit = 11; // '#';

else if (d941 > seuilInt && d1633 > seuilInt)

dtmfDigit = 15; //'D';



if( m_dtmfLastDigit == dtmfDigit )

{

m_sameDtmfDigitCount++;

if( m_sameDtmfDigitCount==4 && dtmfDigit != 1000 )

{

((MpCallFlowGraph*)mpFlowGraph)->mpMediaEventListener->onInBandDtmf(IDevice_
Audio, dtmfDigit );

}

}

else

{

if( dtmfDigit == 1000 )

{

if( m_sameDtmfDigitCount >= 4 )

{

m_sameDtmfDigitCount++;

}

else

{

m_sameDtmfDigitCount=0;

}


if( m_sameDtmfDigitCount >= 30 )

{

m_dtmfLastDigit = dtmfDigit;

m_sameDtmfDigitCount=0;

}

}

else

{

m_dtmfLastDigit = dtmfDigit;

m_sameDtmfDigitCount=0;

}

}

return TRUE;

}

double MprDecodeInBandDtmf::Goertzel( MpAudioSample *input, int numsamples,
double frequency, double samplerate)

{

double Qkn = 0;

double Qkn1 = 0;

double Qkn2, Wkn, Mk;

Wkn = TwoPI * frequency / samplerate;

Mk = 2 * cos(Wkn);

for(int i=0; i<numsamples ; i++ )

{

Qkn2 = Qkn1; Qkn1 = Qkn;

Qkn = input[i] + Mk * Qkn1 - Qkn2;

}

return sqrt(Qkn * Qkn + Qkn1 * Qkn1 - Mk * Qkn * Qkn1);

}



UtlBoolean MprDecodeInBandDtmf::handleMessage(MpFlowGraphMsg& rMsg)

{

switch (rMsg.getMsg()) {

default:

return MpAudioResource::handleMessage(rMsg);

break;

}

return TRUE;

}

/* ============================ FUNCTIONS =================================
*/

_______________________________________________
sipxtapi-dev mailing list
[email protected]
List Archive: http://list.sipfoundry.org/archive/sipxtapi-dev/

Reply via email to