Page tree
Skip to end of metadata
Go to start of metadata

About

The family of FreeSWITCH™ modules including mod_fax, mod_t38gateway, and the mod_voipcodecs have now been merged into one module called mod_spandsp which takes advantage of all the DSP features found in the spandsp library including T.38 endpoint and gateway functionality.

 Click here to expand Table of Contents

Installation


mod_spandsp is enabled by default in modules.conf and therefore compiled automatically. Its also enabled by default in modules.conf.xml.
* Ensure that you have libtiff development files installed.
** For Debian/Ubuntu you can type

* For CentOS 5.x


If you get a complaint about TIFF library, try the following:

* For FreeBSD

* Compile Errors/Problems
If you get an error about "/usr/bin/ld: cannot find -ljpeg" (FreeBSD) or something similar, then double check to see if you have the tiff library installed, look above for how to install for your OS.


* For SUSE

* General Build Errors

If you get errors loading mod_spandsp try:

to rebuild the spandsp library.

Fax

Status

It's important that you create the config XML file since the spool directory for faxes can be configured only there.

Things to be done:

* Fire out an event on every fax received/sent.
* Fire out an event on every page fax received/sent.

Also, mod_spandsp requires that you use a G.711 (PCMA/PCMU) codec for T.30 fax or it won't work. If you are using txfax for sending and rxfax for receiving, remember to use the same codec at both ends.

Invoking the app from the XML dialplan

You can invoke the rxfax application and use the data option to pass it the TIFF file name. If you do not pass any
information in the data option mod_spandsp will create the file name for you and place the received fax into your spool directory.

(This section need to be completed)

For receiving a fax

If you want each fax have a unique name you can use this variation:

If you want mod_spandsp to send the re-INVITE for T.38 (per the standard) use this:

For transmitting a fax

A PDF file can be converted to TIFF format using ImageMagick, here is an example:

Icon

Be explicit about the units (on my machine it defaulted to the metric system). Also, the exclamation mark forces a specific ratio. You may consider using graphicsmagick, since it's generally faster and supports Group4 compression. Keep in mind that these tools still rely on ghostscript to do conversion from pdf using gs's pnm device. The quality of gm was actually better than that produced by ghostscript which does too much dithering. I was able to successfully use width 2156 with graphicsmagick, even though there are different widths specified here for imagemagick and ghostscript.


You can use Ghostscript for PDF/PS files. Here is an example, producing a standard resolution TIFF file:

Here is an example producing a fine resolution TIFF file:

Icon

Ghostscript won't put your document in the correct orientation. This is not really a problem when sending to a remote paper machine, but can be a nuisance when receiving a fax on a computer.

The use of -g1728x1078 and -g1728x2156 ensures that the resulting TIFF file contains pages of a size compatible with FAX machines. If the PDF file contains bit images, rather than scalable content, the images in resulting TIFF file may not fit the pages.

You can transmit a Fax using the following dialplan:

Manual fax transmission

when sending to a telefax, where a live operator gives you a fax tone, bind_meta_app comes handy.

Execute based on fax session outcome

Channel variables that allow you to take action based on the success or failure of a fax transmission.

Variables available are: execute_on_fax_success, execute_on_fax_result, execute_on_fax_failure, execute_on_fax_detect. Insert as required before your rxfax application call.

Example: run an lua script when mod_spandsp reports a successful transmission.

Example: run a shell command when mod_spandsp reports a failed transmission.

Invoking the app from the CLI

For transmitting a fax

In the CLI, for sending a fax via profile external using gateway 10.10.10.10 and fax machine number 100, you'll have to use this.

Or to specify the gateway to use:

For transmitting a fax over ulaw from a SIP T.38 source

Icon

PLEASE reformat this info, it just raw information:

 

  • Make sure you have at least FreeSWITCH Git dating after 25 May 2010.
  • You also need mod_spandsp loaded.
  • Add param enable-t38 to true in conf/autoload_configs/spandsp.conf.xml.
  • NOTE: older versions of FreeSWITCH used fax.conf.xml instead. Newer versions only use fax.conf.xml if they don't find spandsp.conf.xml.
  • Just before executing bridge, execute: t38_gateway with argument equal 'self'. This will monitor for the FAX tone generated so it can switch to T.38 if needed.

 


I tested it using a Linksys SPA3102, You need to have T.38 mode to be in ReInvite.

fax2mail: Emailing the fax upon receipt

* In recent versions of FreeSWITCH, the dialplan ends once rxfax completes, api_hangup_hook executes the script in this case. It is of utmost importance to set api_hangup_hook before rxfax in dialplan. Also if you use any fax vars for the system script, you have to escape them with \\\ (example: \\\${fax_image_size})
** This dialplan also illustrates some possible regex's for specific UAs that only have dedicated fax's attached so they send they fax as an email attachment to the online fax service.

 

* Uuencode is no longer well supported or as good a format as mime. Using mutt to send the attachments solves this but presents some configuration hurdles to format the email. This solution presents a way to deal with every such case. Edit the paths and domain to match your fax service. Create the ${base_dir}/scripts/emailfax.sh file as follows:

* Now create the muttrc file. This configuration allows the sending of mail without a local mailbox which the user running freeswitch probably doesn't have (you can add more config to tune the headers of your email as needed):

Here is another example, using a python script called [http://steffler.info/wp-content/uploads/2009/06/process-rxfax.py process-rxfax.py], via Dialplan XML:

[http://steffler.info/wp-content/uploads/2009/06/process-rxfax.py This python script] gets put into your FreeSWITCH's mod_python path, and will launch mod_spandsp to receive the fax and then convert it to a PDF and email it. The script requires that you have the ps2pdf utility (from Ghostscript) and tiff2ps installed. In FreeBSD these are in Ports and are also available under most Linux distributions via package management (apt-get, yum, rpm etc). This python script also requires a working mod_python and mod_spandsp installation. More information [http://steffler.info/my-first-python-script-receive-a-fax-via-freeswitch-spandsp/ here].

mail2fax: Faxing a received mail

There are several pieces:
* Tell the MTA to run a script when a mail is received to special addresses (example faxnumber@fax.domain.org) :
** examples at http://hylafax.sourceforge.net/howto/faxing.php#ss5.4
* Create a script email2fax:
** guess From: fax number from the email
** run [http://fisheye.freeswitch.org/browse/freeswitch-contrib.git/sathieu/email2pdf email2pdf]
** convert PDF to tiff
** call txfax within FS

Install email2pdf into /usr/local/email2pdf. Link the main script into the path of the email user (/usr/local/bin is used in the script below). Edit header.html to be however you want it.

Create the file /usr/local/email2pdf/emails and put the authorized originating emails you want into it.

If using postfix, you can setup the fax delivery agent by adding these lines into /etc/postfix/master.cf:

Then add this line to /etc/aliases and run postalias:

Then configure your email server to forward a new domain (fax.mydomain.com, for example) to the mail2fax alias. In postfix this will probably involve adding a transport map (transport_maps) as well as a relay recipient (relay_recipient_maps). How you do it will depend on your mail server configuration.

The script email2fax may look like this:

Configuring the app

App can be controlled globally using spandsp.conf.xml:

Controlling the app

You can set the following channel's variables to control the behavior of the mod application:

VariableDescription
t38_gateway_detect_timeout 
FAX_DISABLE_ECMDisabling ECM
fax_disable_v17Disable V17 modem that is: use lower speed modems (lower speeds are auto-negotiated with the remote party and cannot be forced. That's a work that the spandsp modem handles on its own.)
fax_enable_t38Enable T.38 on a per call basis
fax_enable_t38_insist 
fax_enable_t38_requestSend a T.38-ReINVITE when a fax was detected by tone detection
fax_end_pageA sent or receives document will end at specified page
fax_force_callerForce to act as caller or receiver; Mode: Tx=1 or Rx=0''
fax_identThe FAX identity should be set to the telephone number to be used within the FAX exchange. This will typically appear on an LCD display at the far end. In theory it should be limited to digits, spaces, + and one or two other characters appropriate to telephone numbers. In practice FAX machines are usually happy with any text, up to 20 characters long. This string may also play a part in page headers. To disable this header showing at all, put this to "_undef_" NB the underscores
fax_headerIf fax_header is set to a non-null string, a header line will be inserted at the start of each page, just like a typical FAX machine does. The fax_ident, fax_header and the page number will be used to form the text of this line. If you are forwarding FAXes, you probably don't want to add a header line, as there will already be one that was inserted by the original source. If you are sending a locally generated FAX, you probably do want to add header lines to each page. To disable this header showing at all, put this to "_undef_" NB the underscores
fax_prefixPrefix added to the file name for received faxes.
fax_start_pageA sent document will start at the specified page
fax_use_ecmForces the use of ECM if globally disabled, on a per call basis
fax_v17_disabledSame as fax_disable_v17??? This seems to be for T.30 fax mode
fax_verboseBe verbose when printing logs (per call basis)
t38_peer 
t38_trace 

Checking the results

Rx/Tx fax will set the following channel variables when it terminates:

====By mod_spandsp.c====
* '''t38_leg''' - N/A

====By mod_spandsp_fax.c====
* '''fax_bad_rows''' - N/A
* '''fax_document_total_pages''' - N/A
* '''fax_document_transferred_pages''' - N/A
* '''fax_ecm_requested''' - 0/1
* '''fax_ecm_used''' - "on" or "off";
* '''fax_filename''' - File name of the received fax
* '''fax_image_resolution''' - XxY
* '''fax_image_size'''
* '''fax_local_station_id'''
* '''fax_result_code''' - 0 on error otherwise >= 1;
* '''fax_result_text''' - fax error string, provide info where an error has happened;
* '''fax_remote_station_id''' - N/A
* '''fax_success''' - 0 on error, 1 on success;
* '''fax_transfer_rate''' - speed expressed in bauds (bit per seconds) like 14.400, 9.600, etc.;
* '''fax_v17_disabled''' - 0/1 for T.30 mode?
* '''jitterbuffer_msec''' - Always 0
* '''rtp_autoflush_during_bridge''' - N/A
* '''t38_gateway_format''' - "audio" or "udptl"
* '''t38_peer''' - "self" or "peer"
* '''t38_trace_read''' - N/A

====fax-result-code====


[[Variable_fax_result_code|Fax Result Codes]]

==t38_gateway==

t38_gateway app will allow freeswitch to transcode audio<->t.38. It converts to T38 Gateway if tones are heard.

<pre>
<extension name="audio_aleg_t38_bleg">
<condition>
<action application="set" data="fax_enable_t38=true"/>
<action application="set" data="execute_on_answer=t38_gateway peer"/>
<action application="bridge" data="sofia/external/1234@host"/>
</condition>
</extension>
</pre>

You can also make freeswitch listen in and send a reinvite back to the a-leg or forward to the b-leg with the t38_gateway app.
For example, this will transcode incoming T.38 on A-leg to ULAW on b-leg. (e.g. send incoming T.38 fax to Hylafax on Asterisk)

<pre>
<extension name="t38_reinvite">
<condition>
<action application="set" data="fax_enable_t38=true"/> <!-- Enable t.38 for this call -->
<action application="set" data="fax_enable_t38_request=true"/> <!-- Enable t38_gateway to send a t.38 reinvite when a fax tone is detected. If using t38_gateway peer then you need to export this variable instead of set -->
<action application="set" data="execute_on_answer=t38_gateway self"/> <!--Execute t38_gateway on answer. self or peer. self: send a reinvite back to the a-leg. peer reinvite forward to the b-leg -->
<action application="bridge" data="sofia/external/1234@host"/>
</condition>
</extension>
</pre>

If you want to transcode T.38 on the A-leg to T.30 audio on the B-leg, but you want to react to an incoming T.38 invite/re-invite on A-leg instead of detecting cng tones:
Note, you may have to increase FaxT2Timer on hylafax to make this reliable
<pre>
<extension name="t38_transcode">
<condition>
<action application="set" data="fax_enable_t38=true"/>
<action application="set" data="sip_execute_on_image=t38_gateway peer nocng"/> <!--Execute t38_gateway on t.38 invite on A-leg. "nocng" means don't detect the CNG tones. Just start transcoding to the b-leg -->
<action application="bridge" data="sofia/external/1234@host"/>
</condition>
</extension>
</pre>

If you want to transcode audio on the A-leg to T.38 on the B-leg, from a T.38 invite on the B-leg:
<pre>
<extension name="t38_transcode">
<condition>
<action application="set" data="fax_enable_t38=true"/>
<action application="bridge" data="{sip_execute_on_image='t38_gateway self nocng'}sofia/internal/ext@host"/> <!-- "nocng" means don't detect the CNG tones. Just start transcoding -->
</condition>
</extension>
</pre>

If you want to transcode t.38 on leg a to audio on leg B when leg a invites t.38, but refuse all t.38 offers from leg b :

<extension name="t38_test" continue="true">
<action application="set" data="sip_execute_on_image=t38_gateway self nocng"/>
<action application="bridge" data="{refuse_t38=true},sofia/gateway/external/$1" />
</extension>

Allow t.38 between leg A and leg B, but only if the t.38 re-invite comes from leg a

<extension name="passthrough">
<!-- Allow T.38 reinvites from Leg A -->
<action application="set" data="t38_passthru=true"/>
<!-- but not from leg B -->
<action application="bridge" data="{refuse_t38=true},sofia/gateway/external/$1"/>
</extension>

==rxfax==

Fax receive application

Syntax:
<pre>
rxfax [filename]
</pre>

If filename is missing, a default name is created by as:

spool/prefix-number-timestamp.tif

where
* spool is set by the "spool-dir" configuration
* prefix is set by the "fax_prefix" channel variable or the "file-prefix" configuration
* number is a count of number of received faxes
* timestamp is the current time in microseconds

Example usage:
<pre>
<action application="set" data="fax_prefix=${uuid}"/>
<action application="rxfax" data=""/>
</pre>

==txfax==

Fax transmit application. It is recommended to have ignore_early_media set to true to avoid some packet reordering issues.

Syntax:
<pre>
txfax <filename>
</pre>

Example usage:
<pre>
<action application="txfax" data="/tmp/test.tif"/>
</pre>

==spandsp_start_fax_detect==

<pre><action application="spandsp_start_fax_detect" data="<app> [<arg>][ <timeout>][ <tone_type>]"/></pre>

Uses the spandsp code to detect fax tones which should be more reliable than using tone_detect. By default, the application detects CNG tones (sending side).

tone_type can be set to "ced" to detect CED tones (receiving side).

Example usage:
<pre>
<action application="spandsp_start_fax_detect" data="transfer 'fax XML default' 3"/>
</pre>

This will listen for 3 seconds after the application is invoked and if heard, will transfer the call to the "fax" extension found in the "XML" dial plan in the "default" context. (see the Samples section below for an example dialplan for the "fax" extension)

Example usage:
<pre>
<action application="set" data="execute_on_answer=spandsp_start_fax_detect transfer 'fax XML default' 3"/>
</pre>

This will listen for 3 seconds after extension is answered (by user or by other application such as voicemail) and if heard, will transfer the call to the "fax" extension found in the "XML" dial plan in the "default" context. This is closest in setup to "fax machine on same analog line as regular phone".

Full Example:<br />
We need to answer the call to let FreeSwitch receive the audio to start detecting FAX tones. Because a bridge after an answer is actually a transfer, the Ringback sent to the caller is now defined by transfer_ringback
<pre>
<extension name="group_dial_sales">
<condition field="destination_number" expression="^sales$">
<action application="answer"/>
<action application="set" data="transfer_ringback=${us-ring}"/>
<action application="spandsp_start_fax_detect" data="transfer 'FAX XML default' 6"/>
<action application="bridge" data="${group_call(sales@${domain_name})}"/>
</condition>
</extension>
</pre>

==spandsp_stop_fax_detect==

Stop fax detect


===Samples===
Here is a working example using FreeSWITCH as a T.38-gateway.

I used the following software and devices:

* FAX_B: Infotec IF2100e
* ATA_B: Cisco 186 v3.2.1
* FAX_A: RICOH FAX2000L (Super G3, 14.400 Baud)
* ATA_A: Grandstream HandyTone 502
** Product model: HT-502 V1.2A
** Firmware: Program-- 1.0.3.10 Bootloader-- 1.0.0.9 Core-- 1.0.3.6 Base-- 1.0.3.8
* FreeSWITCH: git head of 2010-11-19
* PRI E1-Stack: openzap
* Sangoma-Wanpipe: version 3.5.17
* TDM-Card: Sangoma A104d

====Grandstream====
FXS-Port 1
* Fax Mode: T.38 (Auto Detect)
* Fax tone detection mode: "Callee or Caller"
* Preferred Vocoder: PCMA
* Disable Line Echo Canceller (LEC): Yes
* Jitter Buffer: High
* Gain: Tx=0dB, Rx=0dB

====spandsp.conf.xml====
<pre>
<configuration name="spandsp.conf" description="Fax example">
<fax-settings>
<param name="use-ecm" value="true"/>
<param name="verbose" value="true"/>
<param name="disable-v17" value="false"/>
<param name="enable-t38" value="false"/>
<param name="enable-t38-request" value="false"/>
<param name="ident" value="SpanDSP Fax Ident"/>
<param name="header" value="SpanDSP Fax Header"/>
<param name="spool-dir" value="/tmp"/>
<param name="file-prefix" value="faxrx"/>
</fax-settings>
</configuration>
</pre>

====Outbound Direction: T.38->TDM====
<pre>
Fax_A->ATA_B->SIP->t38_gateway->FreeSWITCH->mod_openzap->ISDN/PRI E1->Fax
</pre>

I used a XML dialplan here. In opposite to the documentation above I have to answer the call and then starting calling the t38_gateway app in dialplan instead of putting it into "execute_on_answer" didn't worked for me.
<pre>
<extension name="Fax_test2">
<condition field="caller_id_number" expression="^(4919)$"/>
<condition field="destination_number" expression="^(.*)$"/>
<action application="set" data="absolute_codec_string=PCMA"/>
<action application="set" data="fax_enable_t38=true"/>
<action application="set" data="fax_enable_t38_request=true"/>
<action application="answer"/>
<action application="t38_gateway" data="self"/>
<action application="bridge" data="openzap/1/a/$1"/>
<action application="hangup"/>
</condition>
</extension>
</pre>

====Inbound Direction: TDM->T.38====
I used a Lua dialplan here. In opposite to the documentation above "peer" mode doesn't work.
<pre>
Fax_B->ISDN/PRI E1->mod_openzap->FreeSWITCH->t38_gateway->SIP->ATA_A->Fax_A (4919)
</pre>

<pre>
if (dialed_ext == "4919") then
session:setAutoHangup(false)
session:execute("export", "nolocal:fax_enable_t38=true")
session:execute("export", "nolocal:fax_enable_t38_request=true")
session:execute("export", "nolocal:execute_on_answer=t38_gateway self")
session:execute("export", "nolocal:absolute_codec_string=PCMA")
session:execute("bridge", "user/".."4919@"..sip_domain)
return
end
</pre>

"dialed_ext" contains the destination number of the ATA resp Fax.
"sip_domain" contains FreeSWITCH's SIP-Domain.

====Internal T.38 to T.38====
I used t38 passthrough here. So FS has only to act as a rtp/udptl proxy.
<pre>
Fax_A (4919)->ATA_A->SIP->FreeSWITCH->SIP->ATA (same as ATA_A)->Fax_B (2799)
</pre>

<pre>
<extension name="Fax_test t.38 to t.38 via t38-passthru">
<condition field="caller_id_number" expression="^(4919)$"/ break="on-true"/>
<condition field="destination_number" expression="^(2799)$">
<action application="set" data="absolute_codec_string=PCMA"/>
<action application="set" data="proxy_media=true"/>
<action application="set" data="bypass_media=false"/>
<action application="bridge" data="user/2799@<sipdoamin>"/>
<action application="hangup"/>
</condition>
</extension>
</pre>

====Results====
I've sent an 8-page fax successfully in both directions. The complete transport way was this:
<pre>
Fax_A <-> ATA_A <-> SIP/UDP <-> t38_gateway <-> FreeSWITCH <-> mod_openzap <----> ISDN/PRI E1 --|
---------------------------- |
/ \ Ayaya-PBX
/ \ |
Fax_B <-> ATA_B <-> SIP/UDP/G711a <-----/ \<-> ISDN/PRI E1 --|
</pre>

 


Questions I got during testing are:
*Where is the difference between "peer" and "self" mode and why does "peer" not work?

*Why does in T.38->TDM direction calling "t38_gateway self" via execute_on_answer not work? t38_gateway is called, it sets a media BUG but seems to hang listening for a tone and aborting after a 20 seconds timeout.


==Events==
===spandsp::rxfaxpageresult===
===spandsp::txfaxpageresult===
===spandsp::rxfaxnegociateresult===
===spandsp::txfaxnegociateresult===

===spandsp::txfaxresult===

This event is fired when a fax finishes sending (either when it succeeds or when it fails). A header indicates whether the fax was successful.

In addition to the sessions headers it contains:
fax-document-transferred-pages
fax-document-total-pages
fax-image-resolution
fax-image-size
fax-bad-rows
fax-transfer-rate
fax-result-code
fax-result-text
fax-ecm-used
fax-local-station-id
fax-remote-station-id

These are [[Mod_spandsp#By_mod_spandsp_fax.c_2|documented above]].

===spandsp::rxfaxresult===

This event is fired when a fax finishes being received (either when it succeeds or when it fails). A header indicates whether the fax was successful.

In addition to the sessions headers it contains:
fax-document-transferred-pages
fax-document-total-pages
fax-image-resolution
fax-image-size
fax-bad-rows
fax-transfer-rate
fax-result-code
fax-result-text
fax-ecm-used
fax-local-station-id
fax-remote-station-id

These are [[Mod_spandsp#By_mod_spandsp_fax.c_2|documented above]].

==Troubleshooting==
Faxing can be a big pain over VOIP and despites FS's great attempt its hard to match the reliability of a PSTN line. Using the methods outlined below with a decent T38 supporting provider I can get somewhere in the 90-95% range with a bit higher with multiple retries. If the remote fax machine supports T38 there is a better chance it will work fine.

===Common Issues===
*Remote machine doesn't support T38 (properly or at all), this is going to make things worse and is obviously common with PSTN machines.
*A T38 gateway (or multiple) end up inbetween each transcode is going to hurt the chances of success
*Carrier/Provider doesn't support T38 well or is poor quality for standard codecs - Some carriers end up using several other carriers and the more carriers a call goes through or the lower the quality of carrier/route the harder (and sometimes much harder) faxing can be. A quality carrier is extremely important.
*Some remote fax machines and PSTN lines can also be of low quality so while you may eventually be able to get good success overall some machines may prove to always be a challenge.
*Make sure your tiff is at the right size, there are many sizes supported by fax machines but 1728x1078 is probably the most common (and is at standard resolution). Its roughly 204x98dpi, "super fine" faxes are at higher resolutions. Ensuring the proper resolution and size is an important step to working with many remote fax machines.
*Ensure you have ignore_early_media enabled, without it random/out of order media can screw things up
*For your codecs you generally want to force PCMU/PCMA unless you know of success with something else better thats generally going to give you the best results.
*Requesting T38 can sometimes hurt your chances by things that don't properly handle or understand T38 causing it to drop.

===Suggested Process===
*First try the optimal methods, t38 enabled and requested, ECM on
*Second if that fails lets turn t38 requests off and ecm off and try again
*If that still fails lets leave T38 and ecm off and just try again, if still failing chance of future success is low.

===Example===
An example to start a fax from the command line:
originate {ignore_early_media=true,absolute_codec_string='PCMU,PCMA',fax_enable_t38=true,fax_verbose=true,fax_use_ecm=true,fax_enable_t38_request=true}sofia/gateway/default/1231231234 &txfax('test_fax.tif')
And if this fails further retries with:
originate {ignore_early_media=true,absolute_codec_string='PCMU,PCMA',fax_enable_t38=true,fax_verbose=true,fax_use_ecm=false,fax_enable_t38_request=false}sofia/gateway/default/1231231234 &txfax('test_fax.tif')

===Further debugging===
setting fax_verbose to true will dump a lot of data about faxes, make sure to go through it carefully as there can always be just one line that has the issue. Console debug logging can also be helpful like normal.

=Tone Detection=
mod_spandsp offers better tone detection than what is provided by default in the FreeSWITCH core.

==DTMF==
Inband DTMF detectors in mod_spandsp can detect duration in addition to frequency. The teletone detector in FS core is based on an old version of spandsp and should be replaced with this detector.

===Channel Variables===

==== [[Variable_dtmf_verbose | dtmf_verbose]] ====
{{:Variable_dtmf_verbose}}

==== [[Variable_min_dup_digit_spacing_ms | min_dup_digit_spacing_ms]] ====
{{:Variable_min_dup_digit_spacing_ms}}

==== [[Variable_spandsp_dtmf_rx_threshold | spandsp_dtmf_rx_threshold]] ====
{{:Variable_spandsp_dtmf_rx_threshold}}

==== [[Variable_spandsp_dtmf_rx_twist | spandsp_dtmf_rx_twist]] ====
{{:Variable_spandsp_dtmf_rx_twist}}

==== [[Variable_spandsp_dtmf_rx_reverse_twist | spandsp_dtmf_rx_reverse_twist]] ====
{{:Variable_spandsp_dtmf_rx_reverse_twist}}

==== [[Variable_spandsp_dtmf_rx_filter_dialtone | spandsp_dtmf_rx_filter_dialtone]] ====
{{:Variable_spandsp_dtmf_rx_filter_dialtone}}

===Dialplan Applications===

====spandsp_start_dtmf====
Detect inband dtmf on the session
<action application="spandsp_start_dtmf"/>

====spandsp_stop_dtmf====
Stop detecting inband dtmf
<action application="spandsp_stop_dtmf"/>

==Call Progress==
mod_spandsp provides the tools to create a call progress tone detector. By accounting for cadence in addition to frequency, this call progress detector can distinguish between North American BUSY and REORDER, which only differ in cadence.

===Configuration===
conf/autoload_configs/spandsp.conf.xml defines the tone detector descriptors. Each descriptor defines a named grouping of tones to detect. When starting the tone detector, you specify the group of tones you wish to detect.

This is a sample configuration for detecting some call progress tones in North America:

<pre>
<configuration name="spandsp.conf" description="Tone detector descriptors">
<descriptors debug-level="0">
<!-- These tones are defined in Annex to ITU Operational Bulletin No. 781 - 1.II.2003 -->
<!-- Various Tones Used in National Networks (According to ITU-T Recommendation E.180)(03/1998) -->

<!-- North America -->
<descriptor name="1">
<tone name="CED_TONE" description="ANS / ANSam">
<element freq1="2100" freq2="0" min="700" max="0"/>
</tone>

<tone name="SIT" description="Special Information Tone">
<element freq1="950" freq2="0" min="256" max="400"/>
<element freq1="1400" freq2="0" min="256" max="400"/>
<element freq1="1800" freq2="0" min="256" max="400"/>
</tone>

<tone name="RING_TONE" description="North America ring">
<element freq1="440" freq2="480" min="1200" max="0"/>
</tone>

<tone name="REORDER_TONE" description="North America reorder">
<element freq1="480" freq2="620" min="224" max="316"/>
<element freq1="0" freq2="0" min="168" max="352"/>
<element freq1="480" freq2="620" min="224" max="316"/>
</tone>

<tone name="BUSY_TONE" description="North America busy">
<element freq1="480" freq2="620" min="464" max="536"/>
<element freq1="0" freq2="0" min="464" max="572"/>
<element freq1="480" freq2="620" min="464" max="536"/>
</tone>
</descriptor>
</descriptors>
</configuration>
</pre>

Each descriptor defines the tones to detect. Each tone is composed of elements defining the frequencies and cadence of the tone. The tone name will be reported in the DETECTED_TONE event. Each element can be composed of 0 (silence), 1, or 2 frequencies. min and max define the minimum and maximum element durations in milliseconds.
====Tuning the detector====
It takes much trial and error to figure out the tone configuration that works well without introducing talk-off. Debug level be increased by changing the debug-level param in the descriptors tag of spandsp.conf.xml. Set the level to 2 to report additional detection information to assist in this process.

The "Tone report" log will tell you when a tone was detected.
The "Tone segment" log will tell you each segment that is detected. The f1 and f2 values identify which frequencies were matched in that segment.

=== Dialplan Applications ===
====start_tone_detect====
Start background tone detection with cadence
<pre>
<!-- start detection for North American call progress tones -->
<action application="start_tone_detect" data="1"/>
</pre>

====stop_tone_detect====
Stop background tone detection with cadence
<action application="stop_tone_detect"/>

===APIs===
====start_tone_detect====
Start background tone detection with cadence
<pre>
start_tone_detect <uuid> <descriptor name>
</pre>

====stop_tone_detect====
Stop background tone detection with cadence
<pre>
stop_tone_detect <uuid>
</pre>

===Events===
====DETECTED_TONE====

This event is fired when the tone detector detects a tone.

The following headers are set:
Detected-Tone
Unique-ID

The Detected-Tone header will contain the name of the tone, as specified in the configuration file. The Unique-ID will contain the session UUID.

=Codecs=
Spandsp implements the following codecs:

* ADPCM (IMA)
* G.726
* G.722
* G.711
* GSM
* LPC-10
=Software Modem=
SpanDSP can also act as a softmodem. To enable the softmodem feature, see the [[HylaFax]] integration page. Setup should be identical, but you can send commands to it as if it was a regular dial up modem.
==COM Port Setting for Windows==
SpanDSP uses COM ports starting from COM4. To loopback the COM ports to an application, an external piece of software such as [http://com0com.sourceforge.net/ com0com] may be required.
=See also=
[http://www.soft-switch.org/t38/index.html Here] are some more informations about T.38

[http://www.itu.int/pub/T-SP-OB.781-2003 Various Tones Used in National Networks]

[[fax on AudioCodes Mediant]]
[[Category:Fax]]
[[Category:Modules]]