Author |
|
ajdiaz Junior
Joined: December 10 2007 Location: United States Posts: 76
|
Posted: December 19 2007 at 2:07pm | IP Logged
|
|
|
Any ideas why my DtmfDecoderCallbackProcedure() is being called twice.
I have a very simple app that displays in a message box the DTMF digit that is detected. The message box is displayed twice because the media engine is calling the callback procedure twice. I am only registering 1 line.
Lanscape Media Engine v5.12
Using .Net C#
Code:
Code:
static void SetDtmfDecoder()
{
int PhoneLine = 0;
DtmfDecoder = new VoipMediaEngine.DtmfDecoder();
// create the decoder.
status = DtmfDecoder.CreateDtmfDecoder(
MediaEngine,
true, // use PCM samples.
8000, // sample rate.
160, // number of samples per input block.
160, // filter block N size. generally set to the same as the num samples per block.
false, // immediate mode.
DtmfDecoderCallbackProc, // handler proc.
MediaEngine // handler proc instance data.
);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "CreateDtmfDecoder() Error.");
DtmfDecoder.DestroyDtmfDecoder();
}
RxIvrChannel0 = new VoipMediaEngine.RxIvrChannel();
int RxIvrSamplesPerIvrBuffer0 = 0;
int RxIvrBytesPerIvrBuffer0 = 0;
bool SamplesInByteArray0 = false;
// tell the LanScape VOIP Media engine that we want to receive
// streaming phone line audio data when the phone line is active.
status = RxIvrChannel0.OpenRxIvrChannel(
MediaEngine,
PhoneLine,
IvrCallbackProc0,
MediaEngine,
true, // Perform conversion.
// Receive Ivr Data Type.
VoipMediaEngine.AUDIO_BANDWIDTH.AUDIO_BW_PCM_8K,
ref RxIvrSamplesPerIvrBuffer0,
ref RxIvrBytesPerIvrBuffer0,
ref SamplesInByteArray0
);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "OpenRxIvrChannel() Error.");
}
}
static void DtmfDecoderCallbackProc(VoipMediaEngine.DTMF_DETECT_DATA DtmfDetectData)
{
VoipMediaEngine.DTMF_TONE DtmfTone = (VoipMediaEngine.DTMF_TONE)DtmfDetectData.DtmfTone;
MessageBox.Show("You entered " + DtmfTone.ToString());
}
|
|
|
|
Back to Top |
|
|
ajdiaz Junior
Joined: December 10 2007 Location: United States Posts: 76
|
Posted: December 19 2007 at 2:18pm | IP Logged
|
|
|
Please ignore code above. It is incomplete.
Code:
Code:
//User clicks on button to handle dtmf example
private void buttonWaitCallHandleDTMF_Click(object sender, EventArgs e)
{
//star t the engine
MyMediaEngine MediaEngine = InitializeMyMediaEngineByAlex();
VoipMediaEngine.TELEPHONY_RETURN_VALUE status;
// The phone line we want to use
int PhoneLine = 0;
status = MediaEngine.DisableSipRegisterServer();
status = MediaEngine.EnableSipDomain(DomainName);
status = MediaEngine.EnableSipProxyServer(SipProxy, SipProxyPort);
status = MediaEngine.SetCallTerminateTimeout(2000);
// start SIP registration functions.
status = MediaEngine.EnableSipRegisterServer(
PhoneDisplayName,
false,
false,
SipProxy,
SipProxyPort,
36000,
36000,
2000,
false
);
status = MediaEngine.TriggerRegistration();
status = MediaEngine.RegistationErrorRetryTime(2000);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "EnableSipRegisterServer() Error.");
}
// Frequency ratio table for inclusion into source code.
// Used to tune the DTMF detector.
//
VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT [] DtmfDecoderRatioTuningTable = new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT[16]
{
// Low Freq Ratio,High Freq Ratio
// ------------------------------------------------------
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(62,709),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(15,1033),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(17,1201),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(117,869),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(118,786),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(67,838),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(9,549),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(12,935),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(219,617),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(182,705),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(135,1015),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(15,820),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(783,2376),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(306,794),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(222,757),
new VoipMediaEngine.FREQUENCY_RATIO_TABLE_ELEMENT(123,861)
};
// Frequency magnitude table for inclusion into source code.
// Used to tune the DTMF detector.
//
VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ ELEMENT[] DtmfDecoderMagnitudeTuningTable = new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT[16]
{
// MinMagF1,MaxMagF1,MinMagF2,MaxMagF2,MinMag2ndHarmF1,MaxMag2ndHarmF1,MinMag2ndHarmF2,MaxMag2ndHarmF2
// -----------------------------------------------------------------------------------------------------
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(107608188, 496445004,103411194,443717266,411197,2195591,1522,178031),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(98703977,5 11868275,80885942,390186326,3874642,19991392,300,138363),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(99486517,4 92838380,61407098,230404150,4516086,21626116,390,184719),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(101966309, 486157921,78254689,330155114,184132,2186855,1868,154810),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(72738722,2 91167037,88328883,454033006,2937,1401190,569,325576),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(67983788,3 11361964,82167593,426290134,267340,3775872,2,378513),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(74958663,2 96326136,71113935,248650135,4598403,29679080,801,452758),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(68035984,2 91050178,74458607,340819931,3457677,16775569,284,357010),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(99100032,4 92246061,89302963,434986397,24948,657561,1210,204680),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(105367119, 489576272,86913068,394091723,68566,848058,1767,197661),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(101971486, 489633999,60985442,228926806,273346,2854382,307,156896),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(98562873,4 90116500,77690299,321257598,4215483,21956753,1457,134067),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(93170491,4 59011273,93448825,459611558,2526,147707,354,50236),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(97704284,4 82497568,90082863,399339125,15371,716030,828,241350),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(93728174,4 53863426,62869872,235221759,56773,1405407,16,286438),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(91761953,4 43736883,79158506,334015678,201584,2309188,467,230855)
};
DtmfDecoder = new VoipMediaEngine.DtmfDecoder();
MyCALLBACK_DATAClass mycb = new MyCALLBACK_DATAClass();
mycb.MediaEngine = MediaEngine;
mycb.PhoneLine = 0;
// create the decoder.
status = DtmfDecoder.CreateDtmfDecoder(
MediaEngine,
true, // use PCM samples.
8000, // sample rate.
160, // number of samples per input block.
160, // filter block N size. generally set to the same as the num samples per block.
false, // immediate mode.
DtmfDecoderCallbackProc, // handler proc.
mycb // handler proc instance data.
);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "CreateDtmfDecoder() Error.");
DtmfDecoder.DestroyDtmfDecoder();
}
RxIvrChannel0 = new VoipMediaEngine.RxIvrChannel();
int RxIvrSamplesPerIvrBuffer0 = 0;
int RxIvrBytesPerIvrBuffer0 = 0;
bool SamplesInByteArray0 = false;
mycb.DtmfDecoder = DtmfDecoder;
// tell the LanScape VOIP Media engine that we want to receive
// streaming phone line audio data when the phone line is active.
status = RxIvrChannel0.OpenRxIvrChannel(
MediaEngine,
PhoneLine,
IvrCallbackProc0,
mycb, //MediaEngine,
true, // Perform conversion.
// Receive Ivr Data Type.
VoipMediaEngine.AUDIO_BANDWIDTH.AUDIO_BW_PCM_8K,
ref RxIvrSamplesPerIvrBuffer0,
ref RxIvrBytesPerIvrBuffer0,
ref SamplesInByteArray0
);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "OpenRxIvrChannel() Error.");
}
//Read y to answer a call
WaitForOkToAnswerCall(MediaEngine, PhoneLine);
VoipMediaEngine.LINE_STATE LineState = new VoipMediaEngine.LINE_STATE();
status = MediaEngine.GetLineStatus(PhoneLine, LineState);
String CurStateStr = MediaEngine.GetTelephonyStatusString(LineState.State);
status = MediaEngine.GoOffHook(PhoneLine);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "GoOffHook() Error.");
}
WaitForInCall(MediaEngine, PhoneLine);
status = MediaEngine.GetLineStatus(PhoneLine, LineState);
CurStateStr = MediaEngine.GetTelephonyStatusString(LineState.State);
VoipMediaEngine.SIP_INCOMING_CALL_INFO IncomingCallInfo = new VoipMediaEngine.SIP_INCOMING_CALL_INFO();
status = MediaEngine.GetIncomingCallInfo(PhoneLine, IncomingCallInfo);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "GetIncomingCallInfo() Error.");
}
VoipMediaEngine.SIP_ACTIVE_CALL_INFO ActiveCallInfo = new VoipMediaEngine.SIP_ACTIVE_CALL_INFO();
status = MediaEngine.GetActiveCallInfo(PhoneLine, ActiveCallInfo);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
LogErrorMessage(MediaEngine, status, "GetActiveCallInfo() Error.");
}
}
static void DtmfDecoderCallbackProc(VoipMediaEngine.DTMF_DETECT_DATA DtmfDetectData)
{
VoipMediaEngine.DTMF_TONE DtmfTone = (VoipMediaEngine.DTMF_TONE)DtmfDetectData.DtmfTone;
MessageBox.Show("You entered " + DtmfTone.ToString());
}
static void IvrCallbackProc0(VoipMediaEngine.IVR_RECOGNITION_DATA IvrRecognitionData)
{
MyMediaEngine MediaEngine;
MyCALLBACK_DATAClass mycb;
bool status;
//// access the user defined parameter.
mycb = (MyCALLBACK_DATAClass)IvrRecognitionData.UserData;
MediaEngine = mycb.MediaEngine;
VoipMediaEngine.DtmfDecoder pDtmfDecoder = mycb.DtmfDecoder;
status = pDtmfDecoder.DtmfDecoderWrite(IvrRecognitionData.SampleBuffe r);
}
|
|
|
|
Back to Top |
|
|
juice Vetran
Joined: December 05 2006 Location: United States Posts: 139
|
Posted: December 19 2007 at 2:39pm | IP Logged
|
|
|
Sorry, I didn't much read your code.
Couple suggestions:
* You get a callback for pressed and released. Maybe that is why you see it twice?
* Non PCMU or lots of packet loss, or other Rtp issues can result in bad detection of dtmf from what I've seen.
|
Back to Top |
|
|
ajdiaz Junior
Joined: December 10 2007 Location: United States Posts: 76
|
Posted: December 19 2007 at 2:55pm | IP Logged
|
|
|
That was it! You get a callback for key pressed and another for key released.
Thanks.
-Alex
|
Back to Top |
|
|
support Administrator
Joined: January 26 2005 Location: United States Posts: 1666
|
Posted: December 20 2007 at 10:17am | IP Logged
|
|
|
Hi aj,
One other item, you do not have to bother with specifying your own DtmfDecoderRatioTuningTable or DtmfDecoderMagnitudeTuningTable objects unless you want to re-tune the in-band DTMF decoder. The DTMF decoder is already tuned to specs.
Also, thanks juice for your post.
We are having a bit of a POP3 email server issue here so we are not currently getting automated post updates via email. Hopefully this gets fixed shortly. We will manually continue to monitor this forum throughout today.
Support
|
Back to Top |
|
|
|
|