Search the Community
Showing results for tags 'dtmf'.
-
hi, I made a software for managing dtmf tones. For the moment the pc audio output is connected to an Arduino with an mt8870 module which decodes the tone and returns the correct value via serial. I wanted to make sure not to use external hardware and so I tried with the bass.dll library to read the microphone input. I can read the volume and interpret the data, but I haven't found a way to handle the dtmfs. Searching the internet I found a project with source in Delphi and C++ with examples to import a library called DTMFScanner.dll (https://www.3delite.hu/Object Pascal Developer Resources/download.html#dtmf) the DTMFScannerLibrary.h file is attached to this post. There are examples on how to use the external library with Delphi too I tried to modify an example of the bass library to integrate the request for the DTMFScanner.dll library but it always returns the value 0. I'm afraid I'm using the wrong library recall method This is my script: #include 'Bass.au3' #include <WinAPICOM.au3> #include <WinAPIConv.au3> #include <Array.au3> Global $hStream, $iLong, $nLeft, $nRight, $iColor Global $ID_GUI = GUICreate('BASS Audio Levels', 190, 200, -1, -1, Default, 0x00000008) GUICtrlCreateLabel('L', 52, 20, 34, 22) GUICtrlCreateLabel('R', 82, 20, 34, 22) Global $ProgressBarL = GUICtrlCreateProgress(50, 40, 14, 100, 0x04) Global $ProgressBarR = GUICtrlCreateProgress(80, 40, 14, 100, 0x04) Global $InputL = GUICtrlCreateLabel('', 50, 150, 34, 22) Global $InputR = GUICtrlCreateLabel('', 80, 150, 34, 22) Global $DtmlDLL Global $parameters = DllStructCreate("ptr FileName; dword Channel; float Treshold; int Thread; int64 User; ptr DetectCallback") Global $inputChannel = 3 ;<------- my mic input Global $result1 GUISetOnEvent(-3, '_Exit') Opt('GUIOnEventMode', 1) GUISetState(@SW_SHOW, $ID_GUI) _BASS_Startup(@ScriptDir & '\Bass.dll') If @error Then Exit MsgBox(16, 'BASS Function Error', 'EC1') _BASS_Init(16, -1, 44100, 0, 'NULL') If @error Then Exit MsgBox(16, 'BASS Function Error', 'EC2') _BASS_RecordInit(-1) If @error Then Exit MsgBox(16, 'BASS Function Error', 'EC3') ; choose input. I use n.3 in this moment _BASS_RecordSetInput($inputChannel, $BASS_INPUT_TYPE_WAVE, 1) ;~ Global $hStream = _BASS_RecordStart(44100, 2, 0, 0) Global $hStream = _BASS_RecordStart(44100, 2, $BASS_SAMPLE_FLOAT);_WinAPI_MakeLong(0, 10)) If @error Then Exit MsgBox(16, 'BASS Function Error', 'EC4') _BASS_ChannelPlay($hStream, True) If @error Then Exit MsgBox(16, 'BASS Function Error', 'EC5') While _BASS_ChannelIsActive($hStream) ;********************************* VUMETER WITH BASS.DLL ******************************************************* $iLong = _BASS_ChannelGetLevel($hStream) $nLeft = _BASS_LoWord($iLong) / 32768 * 100 $nRight = _BASS_HiWord($iLong) / 32768 * 100 $nLeft = Round($nLeft) $nRight = Round($nRight) ; $iColor = 0xFFFFFF If $nLeft > 99 Then $iColor = 0xFF0000 GUICtrlSetColor($ProgressBarL, $iColor) $iColor = 0xFFFFFF If $nRight > 99 Then $iColor = 0xFF0000 GUICtrlSetColor($ProgressBarR, $iColor) ; GUICtrlSetData($ProgressBarL, $nLeft) GUICtrlSetData($ProgressBarR, $nRight) GUICtrlSetData($InputL, $nLeft); <-- Left numeric audio level GUICtrlSetData($InputR, $nRight); <-- Right numeric audio level ; Sleep(10) ;********************************* LOAD EXTERNAL DTMFScanner.dll ******************************************************* $DtmlDLL = DllOpen("DTMFScanner.dll") if @error then ConsoleWrite("DTMFScanner.dll Load Error!!" & @CRLF) Else ConsoleWrite("DTMFScanner external Funcion ok" & @CRLF) $parameters = DllStructCreate("ptr FileName; dword Channel; float Treshold; int Thread; int64 User; ptr DetectCallback") DllStructSetData($parameters, "FileName", DllStructCreate("wchar[260]")) DllStructSetData($parameters, "Channel", $inputChannel) DllStructSetData($parameters, "Treshold", 0.5) DllStructSetData($parameters, "Thread", 0) DllStructSetData($parameters, "User", 0) DllStructSetData($parameters, "DetectCallback", "DetectCallback") $result = DllCall($DtmlDLL, "int", "DTMFScan", "ptr", DllStructGetPtr($parameters)) if @error then ConsoleWrite("error = " & @error & @CRLF) DllClose($DtmlDLL) ConsoleWrite("DTMF = " & $result[0] & " - other returned values (I don't know which ones): " & ($result[1]) & @CRLF) EndIf Sleep(40) WEnd Func _Exit() _BASS_RecordFree() _BASS_Free() GUIDelete($ID_GUI) Exit EndFunc DTMFScannerLibrary.h: //******************************************************************************************************************************** //* * //* DTMF Scanner Library 1.0.4.25 © 3delite 2023 * //* See DTMF Scanner Library ReadMe.txt for details. * //* * //* Licenses available for usege of this library: * //* Freeeware License: €15 * //* http://www.shareit.com/product.html?productid=301011183 * //* Shareware License: €25 * //* http://www.shareit.com/product.html?productid=301011182 * //* Commercial License: €125 * //* http://www.shareit.com/product.html?productid=301011181 * //* * //* https://www.3delite.hu/Object%20Pascal%20Developer%20Resources/DTMFScannerLibrary.html * //* * //* If you have any questions or enquiries please mail: 3delite@3delite.hu * //* * //* Good coding! :) * //* 3delite * //******************************************************************************************************************************** #pragma once #ifdef _WIN32 // Windows //* .dll file name #define FILENAME_DLL_DTMF_SCANNER_LIBRARY "DTMFScanner.dll" #define DTMFSLIBCALL __stdcall //* Exported function names (Windows) #define NAME_DTMFScan "DTMFScan" #endif //* Error codes #define DTMFSL_OK = 0 #define DTMFSL_ERROR = 1 #ifdef _WIN32 #include <wtypes.h> typedef unsigned __int64 QWORD; #else #include <stdint.h> #define WINAPI #define CALLBACK typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; typedef uint64_t QWORD; typedef void* HANDLE; #ifndef __OBJC__ typedef int BOOL; #endif #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #endif typedef enum { dtetStart = 0, dtetContinuing = 1, dtetEnd = 2 } TDTElementType; //* Callback typedef int(DTMFSLIBCALL *TDetectCallback)(int DTMF, TDTElementType Status, float Position, QWORD User); typedef struct { LPWSTR FileName; DWORD Channel; float Treshold; BOOL Thread; QWORD User; TDetectCallback DetectCallback; } *PDTMFScannerParameters, TDTMFScannerParameters; //* Exported functions typedef int(DTMFSLIBCALL* t_DTMFScan)(TDTMFScannerParameters* Parameters); #ifdef __cplusplus extern "C" { #endif static HMODULE DTMFScannerLibraryDLLHandle = NULL; BOOL DTMFScannerLibraryDLLLoaded = FALSE; t_DTMFScan DTMFScan = NULL; #ifdef __cplusplus } #endif BOOL InitDTMFScannerLibrary() { DTMFScannerLibraryDLLHandle = LoadLibrary(FILENAME_DLL_DTMF_SCANNER_LIBRARY); if (NULL != DTMFScannerLibraryDLLHandle) { DTMFScan = (t_DTMFScan)GetProcAddress(DTMFScannerLibraryDLLHandle, NAME_DTMFScan); if (NULL == DTMFScan) { DTMFScannerLibraryDLLLoaded = FALSE; } else { DTMFScannerLibraryDLLLoaded = TRUE; } } return DTMFScannerLibraryDLLLoaded; } BOOL FreeDTMFScannerLibrary() { if (NULL != DTMFScannerLibraryDLLHandle) { DTMFScannerLibraryDLLLoaded = !FreeLibrary(DTMFScannerLibraryDLLHandle); } return !DTMFScannerLibraryDLLLoaded; } DTMFScannerLibrary.pas: //******************************************************************************************************************************** //* * //* DTMF Scanner Library 1.0.4.25 © 3delite 2023 * //* See DTMF Scanner Library ReadMe.txt for details. * //* * //* Licenses available for usege of this library: * //* Freeeware License: €15 * //* http://www.shareit.com/product.html?productid=301011183 * //* Shareware License: €25 * //* http://www.shareit.com/product.html?productid=301011182 * //* Commercial License: €125 * //* http://www.shareit.com/product.html?productid=301011181 * //* * //* https://www.3delite.hu/Object%20Pascal%20Developer%20Resources/DTMFScannerLibrary.html * //* * //* If you have any questions or enquiries please mail: 3delite@3delite.hu * //* * //* Good coding! :) * //* 3delite * //******************************************************************************************************************************** unit DTMFScannerLibrary; interface type TDTElementType = (dtetStart, dtetContinuing, dtetEnd); type TDetectCallback = function(DTMF: Integer; Status: TDTElementType; Position: Single; User: UInt64): Integer; stdcall; type PDTMFScannerParameters = ^TDTMFScannerParameters; TDTMFScannerParameters = record FileName: PChar; Channel: Cardinal; Treshold: Single; Thread: LongBool; User: Int64; DetectCallback: TDetectCallback; end; function DTMFScan(var Parameters: TDTMFScannerParameters): Integer; stdcall; external 'DTMFScanner.dll'; implementation end. Delphi Example: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, bass, Vcl.StdCtrls, DTMFScannerLibrary; type TForm1 = class(TForm) Memo1: TMemo; Button2: TButton; Label2: TLabel; Edit2: TEdit; ComboBoxInput: TComboBox; Label1: TLabel; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } protected procedure WndProc(var Message: TMessage); override; public { Public declarations } procedure ListDevices; end; Const MSG_DTMF_DETECTED = WM_USER * 4 + 111; var Form1: TForm1; Counter: Integer; implementation {$R *.dfm} procedure TForm1.ListDevices; var Device: AnsiString; Count: Integer; Info: BASS_DEVICEINFO; begin ComboBoxInput.Items.Clear; Count := 0; while BASS_RecordGetDeviceInfo(count, Info) do begin Device := Info.name; ComboBoxInput.Items.Add(String(Device)); Inc(Count); end; ComboBoxInput.ItemIndex := - 1; ComboBoxInput.Text := 'Select...'; end; procedure TForm1.FormCreate(Sender: TObject); begin BASS_Init(- 1, 44100, 0, Handle, nil); ListDevices; end; procedure TForm1.FormDestroy(Sender: TObject); begin BASS_Free; end; procedure TForm1.WndProc(var Message: TMessage); begin case Message.Msg of MSG_DTMF_DETECTED: begin Form1.Memo1.Lines.Append('Tone detected: ' + Char(Message.WParam)); end; else inherited WndProc(Message); end; end; function DetectCallback(DTMF: Integer; Status: TDTElementType; Position: Single; User: UInt64): Integer; stdcall; begin //* List only new detections if Status = dtetStart then begin //* This callback is called from a thread, no UI access is allowed in threads so send the params to the main thread PostMessage(Form1.Handle, MSG_DTMF_DETECTED, wParam(DTMF), 0); Inc(Counter); end; Result := 0; end; procedure TForm1.Button1Click(Sender: TObject); begin //* Freeing the channel handle automatically terminates the scanning thread BASS_RecordFree; end; procedure TForm1.Button2Click(Sender: TObject); var Parameters: TDTMFScannerParameters; ChannelInput: HRecord; begin //StopProcessing := False; BASS_RecordFree; BASS_RecordInit(ComboBoxInput.ItemIndex); //* Always use BASS_SAMPLE_FLOAT flag ChannelInput := BASS_RecordStart(11025, 1, BASS_SAMPLE_FLOAT, nil, nil); Counter := 0; Parameters.FileName := nil; Parameters.Channel := ChannelInput; Parameters.Treshold := StrToFloat(Edit2.Text); Parameters.Thread := True; Parameters.User := 0; Parameters.DetectCallback := DetectCallback; DTMFScan(Parameters); end; end. the return in debug is always 0 and another values that change: DTMFScanner external Funcion ok DTMF = 0 - other returned values (I don't know which ones): 0x02642090 DTMFScanner external Funcion ok DTMF = 0 - other returned values (I don't know which ones): 0x02642748 DTMFScanner external Funcion ok DTMF = 0 - other returned values (I don't know which ones): 0x02643A58 DTMFScanner external Funcion ok DTMF = 0 - other returned values (I don't know which ones): 0x02642860 DTMFScanner external Funcion ok DTMF = 0 - other returned values (I don't know which ones): 0x02642748 DTMFScanner external Funcion ok DTMF = 0 - other returned values (I don't know which ones): 0x02643BE8 Any idea to implement the DTMFScanner.dll? Thankyou very much! Marco DTMF_dialing.ogg bass.dll DTMFScanner.dll Bass.au3 DTMFScannerLibrary.h Unit1.pas DTMFScannerLibrary.pas