Audiotext APICross-Platform Audiotext API

Custom-designed voice dialogue made easy

The ISDN audiotext platform CapiCall is a Windows-based voice mailbox software which includes an application program interface for developers of custom-designed special applications processing DTMF input, going far beyond the built-in standard functions of voice mailboxes and information menus. The concept even allows the caller to interact with a webserver or database program running on a different computer and under a different operating system. We present a sample program showing how to use the API.


File-based API

It may be surprising for a Windows application developer to see that the CapiCall API does not use a DLL. Instead, a file EXTERNx.JOB (with x = channel number) is written when the caller enters DTMF digits (dual-tone multiple frequency, as used for dialling by touch-tone telephones). Every second or so, an external application can check if this file exists, read its content, and answer by creating either an EXTERNx.TXT with the node name of the next voice menu item, or a voice file EXTERNx.PCM which is played to the caller.

The reason for this file-based interface is that it is platform-independent, and the application can even run on a different computer than the CapiCall system. For instance, a web server can access the CapiCall folder over a local-area network, process the DTMF file, and then create an appropriate PCM answer file. Due to the good file caching of modern operating systems, the file-based API does not cause timing problems, even on a 60-channel multiplex system.

Job file format

The file EXTERNx.JOB consists of a single line:
Called MSN, caller number, user number, info menu PCM file, key sequence
The caller number is empty if no telephone number is available. The user number is empty if the caller was not identified by his/her number, and also did not log-in for checking voicemails. (In the user number field a P and the prepaid number is added if the prepaid function is in use.) The info menu PCM file is the one which was played right before this action. Example:
42,5882,,CUSTMR,79356

This means that the called number was 42, the caller's telephone number (CLIP) is 5882, the caller has not been identified yet as a registered user (empty user number field), the PCM file played before the DTMF entry is CUSTMR.PCM, and the caller entered the digits 79356. (You will find more details in the chapter "Special applications" of the CapiCall manual.)

Sample program

The following external program for CapiCall, written in Visual Basic 4.0, waits until a caller enters an number, e.g. 1234567, and then plays a PCM file with this number (1234567.PCM in this case). If there is no such file, ERROR.PCM will be played instead.

To use the code in VB, create a form with a timer (Timer1) and four labels named Tim, CLI, Phone and Stat, then paste the following text into the form code editor. Since the CapiCall path is detected automatically, the program can run in any path, even over a network if the CapiCall Log program has been started before on the same PC. Even if you do not program in Visual Basic, the way the program works should be quite obvious and reproducible in any other language.

'External program for CapiCall-Pro/S2M

Option Explicit
DefLng A-Z
Const maxch = 60 'For up to two S2M/T2 lines
Dim a$(4), answ$(maxch), telno$(maxch)
Dim ccpath$

'Field numbers in EXTERNx.TXT
Const MSN = 0, CALLER = 1, USER = 2, MENU = 3, KEYS = 4

'Windows API function to read Win.ini
Private Declare Function GetProfileString Lib "kernel32" _
 Alias "GetProfileStringA" (ByVal lpAppName As String, _
  ByVal lpKeyName As String, ByVal lpDefault As String, _
  ByVal lpReturnedString As String, ByVal nSize As Long) As Long

Private Sub Form_Load()
 'Executed when the form is loaded
 ccpath$ = GetWinIni("Shamrock", "CCall32")
 If ccpath$ = "" Then
  MsgBox "CapiCall is not installed!", vbOKOnly, "Error": End
 Else
  If Right$(ccpath$, 1) <> "\" Then ccpath$ = ccpath$ + "\"
  Timer1.Interval = 2000' Check for EXTERN*.JOB everey 2 s
 End If
End Sub

Private Sub Timer1_Timer()
 'This timer event is called every 2 seconds
 Dim e$, f$, ch, anspcm$, ready As Boolean
 On Error GoTo failed
 While Not ready
  f$ = Dir(ccpath$ + "EXTERN*.JOB")
  If f$ = "" Then
   ready = True
  Else
   ch = Val(Mid$(f$, 7, 2)) 'Channel no.
   If ch < 0 Or ch > maxch Then ch = 0
   f$ = ccpath$ + f$ 'EXTERNx.JOB
   anspcm$ = Left$(f$, Len(f$) - 4) + ".PCM" 'EXTERNx.PCM
   If Dir(anspcm$) > "" Then Kill anspcm$
   Open f$ For Input Shared As 1 'Read EXTERNx.JOB
   If Not EOF(1) Then Line Input #1, e$ Else e$ = ""
   Close 1: Kill f$: Split e$
   If a$(MENU) = "+HANGUP" Then
    answ$(ch) = "": telno$(ch) = ""
    Exit Sub
   End If
   Tim.Caption = Time
   Phone.Caption = a$(KEYS): CLI.Caption = a$(CALLER)
   f$ = ccpath$ + a$(KEYS) + ".PCM"
   If Dir(f$) = "" Then f$ = ccpath$ + "ERROR.PCM"
   FileCopy f$, anspcm$
  End If
 Wend: Exit Sub
failed: 'Errors go here
 Stat.Caption = Err.Description: Close
End Sub

Private Function GetWinIni$(f$, g$)
 'Reads Win.ini below [f$], line g$=...
 Dim x&, buffer As String * 255, e$
 x = GetProfileString(f$, g$, vbNullString, buffer, 255)
 GetWinIni$ = Left(buffer, x)
End Function

Private Sub Split(e$)
'Splits comma-delimited string e$ into array a$()
 Dim i, j, k
 j = 1: Erase a$()
 Do
  i = InStr(j, e$, ",")
  If i Then
   a$(k) = Mid$(e$, j, i - j): j = i + 1: k = k + 1
  Else
   a$(k) = Mid$(e$, j)
  End If
 Loop Until i = 0 Or k > UBound(a$())
End Sub

How to concatenate PCM files

Private Sub CopyFile(f1$, f2$, f3$)
 'Copies the two files f1 + f2 into a file f3
 Dim e$, p&, l1&, ln&
 If Dir(f1$) > "" Then
  Open f3$ For Binary Access Write Shared As 2
  Open f1$ For Binary Access Read Shared As 1
  l1 = LOF(1): p = 0
  While p < l1' Copy file f1
   ln = l1 - p: If ln > 1024 Then ln = 1024
   e$ = Space$(ln) 'Used as buffer
   Get 1, , e$: p = p + ln: Put 2, , e$
  Wend: Close 1
  Open f2$ For Binary Access Read Shared As 1
  l1 = LOF(1): p = 0
  While p < l1' Copy file f2
   ln = l1 - p: If ln > 1024 Then ln = 1024
   e$ = Space$(ln)
   Get 1, , e$: p = p + ln: Put 2, , e$
  Wend: Close 1: Close 2
 End If
End Sub  

CapiCall does not use WAV files internally (though you can import and export them in different formats), but PCM files which match the raw ISDN speech data format (64000 bit/s, 8 bits CCITT A-law encoded). This avoids converting voice files while playing them and reduces the CPU load for multi-channel systems.

But there is still one more advantage. Since WAV files have a header and PCM files do not, it is no problem at all to copy several PCM files together (concatenate them). This makes it fairly easy for an external application to create an API answer PCM file out of several shorter PCM files, e.g. to form a sentence from isolated words. For test purposes or within batch files, this is even possible at the command prompt. To combine 1.pcm and 2.pcm into a file answer.pcm, you might enter this (note that /b forces a binary copy to avoid a stop at an EOF = hex 1A character!):
copy /b 1.pcm+2.pcm answer.pcm

Our sample code snippet shows how an application program can combine two binary files f1 and f2 into one file f3; again, we are using a Visual Basic subroutine. Of course, the principle is not at all limited to two source files only.


09/2004 Shamrock Software GmbH