Author |
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: August 29 2008 at 7:39pm | IP Logged
|
|
|
Hi,
I hope you can really help me with DTMF issue.
I am doing a basic recognition of DTMF on an outbound call in C#. I can make the call no problem.
When I use the DTMF recogniser it doesn't work. So I recorded the outbound call to a file using the API StartPhoneLineRecording().
The voice is fine "testing 123 ", but when I type DTMF on my phone I get distorted buzzes. I have uploaded the file here:
http://ftp.enjector.com/temp/DTMFTest1.wav
I initialise using the following:
StartParams.AudioRecordBandWidth = VoipMediaEngine.AUDIO_BANDWIDTH.AUDIO_BW_ALAW_8K;
StartParams.AudioPlaybackBandWidth = VoipMediaEngine.AUDIO_BANDWIDTH.AUDIO_BW_ALAW_8K;
I turned of DTMF recognition and just recorded directly to file.
Nothing complicated.
Please help, I can continue with my project this weekend.
Many thanks
Ajay
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: August 29 2008 at 7:51pm | IP Logged
|
|
|
Hi,
Just did another test on another machine but using the SingleLine Phone.exe (C++). I got the same issue:
I have uploaded the recording here:
http://ftp.enjector.com/temp/SingLinePhoneTest1.wav
All tests were done with alaw and ulaw. Same issue.
I'm connecting via asterisk to an outside PSTN trunk. The box accepts alaw and ulaw enabled.
Thanks
Ajay
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: August 29 2008 at 8:00pm | IP Logged
|
|
|
Hi,
Sorry for posting again. I just did a test with xlite directly to the same asterisk box and I can hear the DTMFs perfectly.
Thanks
Ajay
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: August 30 2008 at 2:19am | IP Logged
|
|
|
Hi,
I looked through the forum board and got something working well using RTP analysis in C#. I would like to share this to anyone having the same problem.
NOTE: You must set dtmfmode=rfc2833 in your asterisk sip.conf to get this to work.
static void RtpPacketAccessCallbackProc(VoipMediaEngine.RAW_RTP_DATA RawRtpData)
{
MyMediaEngine MediaEngine;
// Access the user defined parameter.
MediaEngine = (MyMediaEngine)RawRtpData.UserData;
// Can't access RTP hearder to see if audio - let's assume audio anyway
//if((RawRtpData.RtpPacketBuffer pRtpHeader.PayloadType == 101)
//{
//}
if (RawRtpData.TransmittingPacket == false)
{
// Access the DTMF payload as a 32 bit value
uint NumDtmfPayloads = (RawRtpData.RtpPacketLengthInBytes - RawRtpData.RtpHeaderLengthInBytes) / 4;
if (NumDtmfPayloads == 1)
{
byte[] array = RawRtpData.RtpPacketBuffer;
if (BitConverter.IsLittleEndian)
{
Array.Reverse(array);
}
uint DtmfPayload = BitConverter.ToUInt32(array, 0);
// Parse the DTMF payload values.
// the DTMF key pressed or released.
uint DTMF_Event = DtmfPayload >> 24;
// the "end" bit.
uint DTMF_E = (DtmfPayload >> 23) & 0x01;
// reserved bit - not used.
uint DTMF_R = (DtmfPayload >> 22) & 0x01;
// the DTMF power level (volume).
uint DTMF_Volume = (DtmfPayload >> 16) & 0x3f;
// tone duration.
uint DTMF_Duration = DtmfPayload & 0xffff;
Console.WriteLine(DTMF_Event + " " + DTMF_E + " " + DTMF_R + " " + DTMF_Volume + " " + DTMF_Duration);
RawRtpData.ProcessRtpPacket = false;
// tell the media enigne to ignore this RTP DTMF packet.
// if you don't do this, the RTP receiver logic will try
// to interpret the DTMF payload as encoded audio.
RawRtpData.ProcessRtpPacket = false;
}
}
}
static VoipMediaEngine.RtpPacketAccess RtpPacketAccess;
public static void EnableRTP(int PhoneLine)
{
VoipMediaEngine.TELEPHONY_RETURN_VALUE status;
RtpPacketAccess = new VoipMediaEngine.RtpPacketAccess();
status = RtpPacketAccess.EnableRawRtpPacketAccess(
MediaEngine,
PhoneLine,
true,
RtpPacketAccessCallbackProc,
MediaEngine
);
}
Have fun!
Ajay Soni
Enjector Software Ltd.
|
Back to Top |
|
|
support Administrator
Joined: January 26 2005 Location: United States Posts: 1666
|
Posted: September 02 2008 at 9:07am | IP Logged
|
|
|
Hi Ajay,
Good job. At least you came to some solution by the power of your own investigation. Thanks also for taking the time to post your solution and your findings. That really helps everyone down the road.
Just to be sure:
1)
You are now using the RFC2833 integrated DTMF capability in the media engine right?
Note: The media engine can handle RFC2833 DTMF detection and generation automatically for your C# app. You can still use the “RtpPacketAccessCallbackProc” method as you posted but that technique is duplicating the functionality already built into the media engine. We are assuming you used the “RtpPacketAccessCallbackProc” method just to perform DTMF debugging and trouble shooting– which is good.
2)
If you use the fully integrated RFC2833 dtmf detection/generation of the media engine in your C# app, you will have “rock solid” DTMF capability between your C# .NET VOIP app and Asterisk.
Support
|
Back to Top |
|
|
support Administrator
Joined: January 26 2005 Location: United States Posts: 1666
|
Posted: September 02 2008 at 9:08am | IP Logged
|
|
|
Ajay,
By the way, don’t worry about posting too much. Its all good…..
Support
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: September 02 2008 at 9:55am | IP Logged
|
|
|
Hi,
Thanks for your post. Where/how can I access this DTMF information from the media engine?
I can't seem to find a way of doing this.
My engine version is 5.12.8.1
Thanks
Ajay
|
Back to Top |
|
|
support Administrator
Joined: January 26 2005 Location: United States Posts: 1666
|
Posted: September 02 2008 at 10:35am | IP Logged
|
|
|
Ajay,
Your support FTP account contains an engineering release (v5.12.8.7) of the media engine that contains the fully integrated DTMF capability. This version contains capabilities that will be released in the v6 media engine product that will be made available shortly. You will automatically be receiving a new product image as soon as v6 is made available. Please see the “Engineering Update v5.12.8.7” directory.
Simply take the following files from the engineering release and manually update your installed product image:
LanScape_Software_Developer's_Reference.chm (optional)
LMEVoip.dll
LMEVoip.lib
LMEVoipManaged.dll
SipTelephonyApi.h
Then make sure to rebuild your VOIP app.
If using the engineering release, make sure to use the updated C# license file from the “Engineering Update v5.12.8.7\License Files” directory of your support FTP account.
This engineering release is good until the end of this year (12-31-08), then it will no longer function.
See the updated Software Developer’s Reference for the “DTMF Generation and Detection” section. It will give you all the APIs that are now available to have the media engine perform fully integrated in-band and RFC2833 DTMF generation and detection for your app. Post your questions to a new forum thread if you run into problems.
The nice thing about this new DTMF capability is that when the media engine detects in-band and/or RFC2833 DTMF being received on a phone line, it sends your app a DTMF ON/OFF event. All your app needs to do is enable the proper type of DTMF on a per phone line basis and then process DTMF detection events when they are sent to your app. Nice and simple.
Let us know if we have forgotten something.
Support
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: September 02 2008 at 11:51am | IP Logged
|
|
|
Hi,
Thanks for that. Great addition but not working:
When I look at the DTMF digits (VoipMediaEngine.DTMF_DETECT_DATA.DtmfTone) I always get:
DTMF Detected: 6
DTMF Detected: 1
DTMF Detected: 1
DTMF Detected: 6
DTMF Detected: 6
DTMF Detected: 1
DTMF Detected: 1
DTMF Detected: 6
DTMF Detected: 6
DTMF Detected: 1
DTMF Detected: 1
This output comes from this code I put together from your samples:
(Sorry for the size)
Code:
static VoipMediaEngine.DtmfDecoder DtmfDecoder;
public static void DTMFEnableDetection()
{
VoipMediaEngine.TELEPHONY_RETURN_VALUE status;
// 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,511868275,80885942,390186326,3874642,19991392,300,138363),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(99486517,492838380,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,291167037,88328883,454033006,2937,1401190,569,325576),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(67983788,311361964,82167593,426290134,267340,3775872,2,378513),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(74958663,296326136,71113935,248650135,4598403,29679080,801,452758),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(68035984,291050178,74458607,340819931,3457677,16775569,284,357010),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(99100032,492246061,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,490116500,77690299,321257598,4215483,21956753,1457,134067),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(93170491,459011273,93448825,459611558,2526,147707,354,50236),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(97704284,482497568,90082863,399339125,15371,716030,828,241350),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(93728174,453863426,62869872,235221759,56773,1405407,16,286438),
new VoipMediaEngine.FREQUENCY_MAGNITUDE_TABLE_ELEMENT(91761953,443736883,79158506,334015678,201584,2309188,467,230855)
};
DtmfDecoder = new VoipMediaEngine.DtmfDecoder();
// create the decoder.
status = DtmfDecoder.CreateDtmfDecoder(
MediaEngine,
false, // I'm using ULAW
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.
);
}
static void PhoneLineReceiveAudioCallback(VoipMediaEngine.IVR_RECOGNITION_DATA pIvrRecognitionData)
{
bool result = DtmfDecoder.DtmfDecoderWrite(pIvrRecognitionData.SampleBuffer);
if (result == false)
{
Console.Write("x");
}
}
public static void ListenForDTMF(int PhoneLine)
{
DTMFEnableDetection();
VoipMediaEngine.TELEPHONY_RETURN_VALUE status;
VoipMediaEngine.RxIvrChannel RxIvrChannel = new VoipMediaEngine.RxIvrChannel();
int ChannelNumber = 0;
int BytesPerIvrBuffer = 0;
bool SamplesInByteArray = false;
status = RxIvrChannel.OpenRxIvrChannel(
MediaEngine,
PhoneLine,
PhoneLineReceiveAudioCallback,
MediaEngine,
true,
VoipMediaEngine.AUDIO_BANDWIDTH.AUDIO_BW_ULAW_8K,
ref ChannelNumber,
ref BytesPerIvrBuffer,
ref SamplesInByteArray);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
string CurStateStr = MediaEngine.GetTelephonyStatusString(status);
Console.WriteLine("error listening to DTMF " + CurStateStr);
}
}
static void DtmfDecoderCallbackProc(VoipMediaEngine.DTMF_DETECT_DATA DtmfDetectData)
{
string digitPressed = null;
switch (DtmfDetectData.DtmfTone)
{
case VoipMediaEngine.DTMF_TONE.DtmfTone0:
digitPressed = "0";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone1:
digitPressed = "1";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone2:
digitPressed = "2";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone3:
digitPressed = "3";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone4:
digitPressed = "4";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone5:
digitPressed = "5";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone6:
digitPressed = "6";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone7:
digitPressed = "7";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTone8:
digitPressed = "8";
break;
case VoipMediaEngine.DTMF_TONE.DtmfToneAsterisk:
digitPressed = "*";
break;
case VoipMediaEngine.DTMF_TONE.DtmfTonePound:
digitPressed = "#";
break;
default:
digitPressed = "?";
break;
}
Console.WriteLine("DTMF Detected: " + digitPressed);
}
|
|
|
Any ideas?
Thanks
Ajay
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: September 02 2008 at 12:13pm | IP Logged
|
|
|
Hi,
Oh sweet. I realised I'm still doing inband analysis! I stripped the code and used your new RFC2833 API.
For anyone else having problems do this.
1) Do this on startup:
StartParams.DtmfEnabled = true;
2) Create a new event handler in your main SIP handler:
Code:
case VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipDtmfDigitEvent:
VoipMediaEngine.DTMF_EVENT_DATA ev = (VoipMediaEngine.DTMF_EVENT_DATA) EventData;
Console.WriteLine("Got digit: " + ev.PhoneLine + " " + ev.DtmfTone + " " + ev.StateOn);
break;
|
|
|
3) Simply enable DTMF detection by doing the following:
Code:
VoipMediaEngine.TELEPHONY_RETURN_VALUE status;
status = MediaEngine.InitializeRfc2833DtmfDecoder(PhoneLine);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
Console.WriteLine("Error listening to DTMF " + status.ToString());
return;
}
status = MediaEngine.SetRfc2833DtmfDecoderEnableState(PhoneLine, true);
if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
{
Console.WriteLine("Error listening to DTMF " + status.ToString());
return;
}
|
|
|
Thanks Support.
Ajay
|
Back to Top |
|
|
support Administrator
Joined: January 26 2005 Location: United States Posts: 1666
|
Posted: September 02 2008 at 12:25pm | IP Logged
|
|
|
Ajay,
Your last post is right on. Good job. You should now have rock solid RFC2833 DTMF detection from your Asterisk (PSTN gateway) box to your IVR server app.
Support
|
Back to Top |
|
|
ajay__soni Intermediate
Joined: December 01 2007 Location: United Kingdom Posts: 19
|
Posted: December 17 2008 at 4:35am | IP Logged
|
|
|
Hi,
The engineering release you gave me with the DTMF fix is about to expire on v5.12.8.7.
Can i have an updated version that won't expire?
Thanks
Ajay
|
Back to Top |
|
|
support Administrator
Joined: January 26 2005 Location: United States Posts: 1666
|
Posted: December 17 2008 at 9:21am | IP Logged
|
|
|
Hi Ajay,
I’m glad you posted. Yes we have on record that you need an update. I will send you an email with additional information.
Thanks,
Randal
|
Back to Top |
|
|
|
|