diff --git a/libs/freetdm/src/Makefile b/libs/freetdm/src/Makefile
index ac6a8ffdec..2f7055b09c 100644
--- a/libs/freetdm/src/Makefile
+++ b/libs/freetdm/src/Makefile
@@ -29,7 +29,8 @@
 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-OBJS=hashtable.o hashtable_itr.o openzap.o zap_config.o
+
+OBJS=hashtable.o hashtable_itr.o openzap.o zap_config.o libteletone_detect.o libteletone_generate.o zap_buffer.o
 CFLAGS=$(ZAP_CFLAGS) -Iinclude 
 MYLIB=libopenzap.a
 
@@ -41,6 +42,9 @@ $(MYLIB): $(OBJS)
 	ar rcs $(MYLIB) $(OBJS)
 	ranlib $(MYLIB)
 
+openzap.o: openzap.c
+	$(CC) $(MOD_CFLAGS) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
+
 zap_wanpipe.o: zap_wanpipe.c
 	$(CC) $(CFLAGS) $(ZAP_CFLAGS) $(WP_CFLAGS) -c $< -o $@
 
diff --git a/libs/freetdm/src/include/g711.h b/libs/freetdm/src/include/g711.h
new file mode 100644
index 0000000000..8d1f6bf43a
--- /dev/null
+++ b/libs/freetdm/src/include/g711.h
@@ -0,0 +1,384 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g711.h - In line A-law and u-law conversion routines
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2001 Steve Underwood
+ *
+ *  Despite my general liking of the GPL, I place this code in the
+ *  public domain for the benefit of all mankind - even the slimy
+ *  ones who might try to proprietize my work and use it to my
+ *  detriment.
+ *
+ * $Id: g711.h,v 1.1 2006/06/07 15:46:39 steveu Exp $
+ */
+
+/*! \file */
+
+/*! \page g711_page A-law and mu-law handling
+Lookup tables for A-law and u-law look attractive, until you consider the impact
+on the CPU cache. If it causes a substantial area of your processor cache to get
+hit too often, cache sloshing will severely slow things down. The main reason
+these routines are slow in C, is the lack of direct access to the CPU's "find
+the first 1" instruction. A little in-line assembler fixes that, and the
+conversion routines can be faster than lookup tables, in most real world usage.
+A "find the first 1" instruction is available on most modern CPUs, and is a
+much underused feature. 
+
+If an assembly language method of bit searching is not available, these routines
+revert to a method that can be a little slow, so the cache thrashing might not
+seem so bad :(
+
+Feel free to submit patches to add fast "find the first 1" support for your own
+favourite processor.
+
+Look up tables are used for transcoding between A-law and u-law, since it is
+difficult to achieve the precise transcoding procedure laid down in the G.711
+specification by other means.
+*/
+
+#if !defined(_G711_H_)
+#define _G711_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _MSC_VER
+#ifndef __inline__
+#define __inline__ __inline
+#endif
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef unsigned __int16 uint16_t;
+#else
+#include <stdint.h>
+#endif
+
+#if defined(__i386__)
+/*! \brief Find the bit position of the highest set bit in a word
+    \param bits The word to be searched
+    \return The bit number of the highest set bit, or -1 if the word is zero. */
+static __inline__ int top_bit(unsigned int bits)
+{
+    int res;
+
+    __asm__ __volatile__(" movl $-1,%%edx;\n"
+                         " bsrl %%eax,%%edx;\n"
+                         : "=d" (res)
+                         : "a" (bits));
+    return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Find the bit position of the lowest set bit in a word
+    \param bits The word to be searched
+    \return The bit number of the lowest set bit, or -1 if the word is zero. */
+static __inline__ int bottom_bit(unsigned int bits)
+{
+    int res;
+
+    __asm__ __volatile__(" movl $-1,%%edx;\n"
+                         " bsfl %%eax,%%edx;\n"
+                         : "=d" (res)
+                         : "a" (bits));
+    return res;
+}
+/*- End of function --------------------------------------------------------*/
+#elif defined(__x86_64__)
+static __inline__ int top_bit(unsigned int bits)
+{
+    int res;
+
+    __asm__ __volatile__(" movq $-1,%%rdx;\n"
+                         " bsrq %%rax,%%rdx;\n"
+                         : "=d" (res)
+                         : "a" (bits));
+    return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int bottom_bit(unsigned int bits)
+{
+    int res;
+
+    __asm__ __volatile__(" movq $-1,%%rdx;\n"
+                         " bsfq %%rax,%%rdx;\n"
+                         : "=d" (res)
+                         : "a" (bits));
+    return res;
+}
+/*- End of function --------------------------------------------------------*/
+#else
+static __inline__ int top_bit(unsigned int bits)
+{
+    int i;
+    
+    if (bits == 0)
+        return -1;
+    i = 0;
+    if (bits & 0xFFFF0000)
+    {
+        bits &= 0xFFFF0000;
+        i += 16;
+    }
+    if (bits & 0xFF00FF00)
+    {
+        bits &= 0xFF00FF00;
+        i += 8;
+    }
+    if (bits & 0xF0F0F0F0)
+    {
+        bits &= 0xF0F0F0F0;
+        i += 4;
+    }
+    if (bits & 0xCCCCCCCC)
+    {
+        bits &= 0xCCCCCCCC;
+        i += 2;
+    }
+    if (bits & 0xAAAAAAAA)
+    {
+        bits &= 0xAAAAAAAA;
+        i += 1;
+    }
+    return i;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int bottom_bit(unsigned int bits)
+{
+    int i;
+    
+    if (bits == 0)
+        return -1;
+    i = 32;
+    if (bits & 0x0000FFFF)
+    {
+        bits &= 0x0000FFFF;
+        i -= 16;
+    }
+    if (bits & 0x00FF00FF)
+    {
+        bits &= 0x00FF00FF;
+        i -= 8;
+    }
+    if (bits & 0x0F0F0F0F)
+    {
+        bits &= 0x0F0F0F0F;
+        i -= 4;
+    }
+    if (bits & 0x33333333)
+    {
+        bits &= 0x33333333;
+        i -= 2;
+    }
+    if (bits & 0x55555555)
+    {
+        bits &= 0x55555555;
+        i -= 1;
+    }
+    return i;
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+/* N.B. It is tempting to use look-up tables for A-law and u-law conversion.
+ *      However, you should consider the cache footprint.
+ *
+ *      A 64K byte table for linear to x-law and a 512 byte table for x-law to
+ *      linear sound like peanuts these days, and shouldn't an array lookup be
+ *      real fast? No! When the cache sloshes as badly as this one will, a tight
+ *      calculation may be better. The messiest part is normally finding the
+ *      segment, but a little inline assembly can fix that on an i386, x86_64 and
+ *      many other modern processors.
+ */
+ 
+/*
+ * Mu-law is basically as follows:
+ *
+ *      Biased Linear Input Code        Compressed Code
+ *      ------------------------        ---------------
+ *      00000001wxyza                   000wxyz
+ *      0000001wxyzab                   001wxyz
+ *      000001wxyzabc                   010wxyz
+ *      00001wxyzabcd                   011wxyz
+ *      0001wxyzabcde                   100wxyz
+ *      001wxyzabcdef                   101wxyz
+ *      01wxyzabcdefg                   110wxyz
+ *      1wxyzabcdefgh                   111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz.  * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+
+/*#define ULAW_ZEROTRAP*/                 /* turn on the trap as per the MIL-STD */
+#define ULAW_BIAS        0x84           /* Bias for linear code. */
+
+/*! \brief Encode a linear sample to u-law
+    \param linear The sample to encode.
+    \return The u-law value.
+*/
+static __inline__ uint8_t linear_to_ulaw(int linear)
+{
+    uint8_t u_val;
+    int mask;
+    int seg;
+
+    /* Get the sign and the magnitude of the value. */
+    if (linear < 0)
+    {
+        linear = ULAW_BIAS - linear;
+        mask = 0x7F;
+    }
+    else
+    {
+        linear = ULAW_BIAS + linear;
+        mask = 0xFF;
+    }
+
+    seg = top_bit(linear | 0xFF) - 7;
+
+    /*
+     * Combine the sign, segment, quantization bits,
+     * and complement the code word.
+     */
+    if (seg >= 8)
+        u_val = (uint8_t) (0x7F ^ mask);
+    else
+        u_val = (uint8_t) (((seg << 4) | ((linear >> (seg + 3)) & 0xF)) ^ mask);
+#ifdef ULAW_ZEROTRAP
+    /* Optional ITU trap */
+    if (u_val == 0)
+        u_val = 0x02;
+#endif
+    return  u_val;
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Decode an u-law sample to a linear value.
+    \param ulaw The u-law sample to decode.
+    \return The linear value.
+*/
+static __inline__ int16_t ulaw_to_linear(uint8_t ulaw)
+{
+    int t;
+    
+    /* Complement to obtain normal u-law value. */
+    ulaw = ~ulaw;
+    /*
+     * Extract and bias the quantization bits. Then
+     * shift up by the segment number and subtract out the bias.
+     */
+    t = (((ulaw & 0x0F) << 3) + ULAW_BIAS) << (((int) ulaw & 0x70) >> 4);
+    return  (int16_t) ((ulaw & 0x80)  ?  (ULAW_BIAS - t)  :  (t - ULAW_BIAS));
+}
+/*- End of function --------------------------------------------------------*/
+
+/*
+ * A-law is basically as follows:
+ *
+ *      Linear Input Code        Compressed Code
+ *      -----------------        ---------------
+ *      0000000wxyza             000wxyz
+ *      0000001wxyza             001wxyz
+ *      000001wxyzab             010wxyz
+ *      00001wxyzabc             011wxyz
+ *      0001wxyzabcd             100wxyz
+ *      001wxyzabcde             101wxyz
+ *      01wxyzabcdef             110wxyz
+ *      1wxyzabcdefg             111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+
+#define ALAW_AMI_MASK       0x55
+
+/*! \brief Encode a linear sample to A-law
+    \param linear The sample to encode.
+    \return The A-law value.
+*/
+static __inline__ uint8_t linear_to_alaw(int linear)
+{
+    int mask;
+    int seg;
+    
+    if (linear >= 0)
+    {
+        /* Sign (bit 7) bit = 1 */
+        mask = ALAW_AMI_MASK | 0x80;
+    }
+    else
+    {
+        /* Sign (bit 7) bit = 0 */
+        mask = ALAW_AMI_MASK;
+        linear = -linear - 8;
+    }
+
+    /* Convert the scaled magnitude to segment number. */
+    seg = top_bit(linear | 0xFF) - 7;
+    if (seg >= 8)
+    {
+        if (linear >= 0)
+        {
+            /* Out of range. Return maximum value. */
+            return (uint8_t) (0x7F ^ mask);
+        }
+        /* We must be just a tiny step below zero */
+        return (uint8_t) (0x00 ^ mask);
+    }
+    /* Combine the sign, segment, and quantization bits. */
+    return (uint8_t) (((seg << 4) | ((linear >> ((seg)  ?  (seg + 3)  :  4)) & 0x0F)) ^ mask);
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Decode an A-law sample to a linear value.
+    \param alaw The A-law sample to decode.
+    \return The linear value.
+*/
+static __inline__ int16_t alaw_to_linear(uint8_t alaw)
+{
+    int i;
+    int seg;
+
+    alaw ^= ALAW_AMI_MASK;
+    i = ((alaw & 0x0F) << 4);
+    seg = (((int) alaw & 0x70) >> 4);
+    if (seg)
+        i = (i + 0x108) << (seg - 1);
+    else
+        i += 8;
+    return (int16_t) ((alaw & 0x80)  ?  i  :  -i);
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Transcode from A-law to u-law, using the procedure defined in G.711.
+    \param alaw The A-law sample to transcode.
+    \return The best matching u-law value.
+*/
+uint8_t alaw_to_ulaw(uint8_t alaw);
+
+/*! \brief Transcode from u-law to A-law, using the procedure defined in G.711.
+    \param alaw The u-law sample to transcode.
+    \return The best matching A-law value.
+*/
+uint8_t ulaw_to_alaw(uint8_t ulaw);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/
diff --git a/libs/freetdm/src/include/libteletone.h b/libs/freetdm/src/include/libteletone.h
new file mode 100644
index 0000000000..aaf7b0ed47
--- /dev/null
+++ b/libs/freetdm/src/include/libteletone.h
@@ -0,0 +1,126 @@
+/* 
+ * libteletone
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is libteletone
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * libteletone.h -- Tone Generator/Detector
+ *
+ *
+ *
+ * Exception:
+ * The author hereby grants the use of this source code under the 
+ * following license if and only if the source code is distributed
+ * as part of the openzap library.  Any use or distribution of this
+ * source code outside the scope of the openzap library will nullify the
+ * following license and reinact the MPL 1.1 as stated above.
+ *
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef LIBTELETONE_H
+#define LIBTELETONE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define	TELETONE_MAX_DTMF_DIGITS 128
+#define TELETONE_MAX_TONES 6
+#define TELETONE_TONE_RANGE 127
+
+typedef double teletone_process_t;
+
+/*! \file libteletone.h
+    \brief Top level include file
+
+	This file should be included by applications using the library
+*/
+
+/*! \brief An abstraction to store a tone mapping */
+typedef struct {
+	/*! An array of tone frequencies */
+	teletone_process_t freqs[TELETONE_MAX_TONES];
+} teletone_tone_map_t;
+
+#if !defined(M_PI)
+/* C99 systems may not define M_PI */
+#define M_PI 3.14159265358979323846264338327
+#endif
+
+#ifdef _MSC_VER
+typedef __int16 int16_t;
+#endif
+
+#include <libteletone_generate.h>
+#include <libteletone_detect.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/include/libteletone_detect.h b/libs/freetdm/src/include/libteletone_detect.h
new file mode 100644
index 0000000000..eda4e49514
--- /dev/null
+++ b/libs/freetdm/src/include/libteletone_detect.h
@@ -0,0 +1,280 @@
+/* 
+ * libteletone
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
+ *
+ *
+ * The Initial Developer of the Original Code is
+ * Stephen Underwood <steveu@coppice.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * The the original interface designed by Steve Underwood was preserved to retain 
+ *the optimizations when considering DTMF tones though the names were changed in the interest 
+ * of namespace.
+ *
+ * Much less efficient expansion interface was added to allow for the detection of 
+ * a single arbitrary tone combination which may also exceed 2 simultaneous tones.
+ * (controlled by compile time constant TELETONE_MAX_TONES)
+ *
+ * Copyright (C) 2006 Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * libteletone_detect.c Tone Detection Code
+ *
+ *
+ ********************************************************************************* 
+ *
+ * Derived from tone_detect.h - General telephony tone detection, and specific
+ * detection of DTMF.
+ *
+ * Copyright (C) 2001  Steve Underwood <steveu@coppice.org>
+ *
+ * Despite my general liking of the GPL, I place this code in the
+ * public domain for the benefit of all mankind - even the slimy
+ * ones who might try to proprietize my work and use it to my
+ * detriment.
+ *
+ *
+ * Exception:
+ * The author hereby grants the use of this source code under the 
+ * following license if and only if the source code is distributed
+ * as part of the openzap library.  Any use or distribution of this
+ * source code outside the scope of the openzap library will nullify the
+ * following license and reinact the MPL 1.1 as stated above.
+ *
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBTELETONE_DETECT_H
+#define LIBTELETONE_DETECT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <libteletone.h>
+
+/*! \file libteletone_detect.h
+    \brief Tone Detection Routines
+
+	This module is responsible for tone detection specifics
+*/
+
+#ifndef FALSE
+#define FALSE   0
+#ifndef TRUE
+#define TRUE    (!FALSE)
+#endif
+#endif
+
+/* Basic DTMF specs:
+ *
+ * Minimum tone on = 40ms
+ * Minimum tone off = 50ms
+ * Maximum digit rate = 10 per second
+ * Normal twist <= 8dB accepted
+ * Reverse twist <= 4dB accepted
+ * S/N >= 15dB will detect OK
+ * Attenuation <= 26dB will detect OK
+ * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
+ */
+
+#define DTMF_THRESHOLD              8.0e7
+#define DTMF_NORMAL_TWIST           6.3     /* 8dB */
+#define DTMF_REVERSE_TWIST          2.5     /* 4dB */
+#define DTMF_RELATIVE_PEAK_ROW      6.3     /* 8dB */
+#define DTMF_RELATIVE_PEAK_COL      6.3     /* 8dB */
+#define DTMF_2ND_HARMONIC_ROW       2.5     /* 4dB */
+#define DTMF_2ND_HARMONIC_COL       63.1    /* 18dB */
+#define GRID_FACTOR 4
+#define BLOCK_LEN 102
+#define M_TWO_PI 2.0*M_PI
+
+/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
+typedef struct {
+	teletone_process_t v2;
+	teletone_process_t v3;
+	teletone_process_t fac;
+} teletone_goertzel_state_t;
+	
+/*! \brief A container for a DTMF detection state.*/
+typedef struct {
+    int hit1;
+    int hit2;
+    int hit3;
+    int hit4;
+    int mhit;
+
+    teletone_goertzel_state_t row_out[GRID_FACTOR];
+    teletone_goertzel_state_t col_out[GRID_FACTOR];
+    teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
+    teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
+    teletone_process_t energy;
+    
+    int current_sample;
+    char digits[TELETONE_MAX_DTMF_DIGITS + 1];
+    int current_digits;
+    int detected_digits;
+    int lost_digits;
+    int digit_hits[16];
+} teletone_dtmf_detect_state_t;
+
+/*! \brief An abstraction to store the coefficient of a tone frequency */
+typedef struct {
+    teletone_process_t fac;
+} teletone_detection_descriptor_t;
+
+/*! \brief A container for a single multi-tone detection 
+TELETONE_MAX_TONES dictates the maximum simultaneous tones that can be present
+in a multi-tone representation.
+*/
+typedef struct {
+	int sample_rate;
+
+	teletone_detection_descriptor_t tdd[TELETONE_MAX_TONES];
+	teletone_goertzel_state_t gs[TELETONE_MAX_TONES];
+	teletone_goertzel_state_t gs2[TELETONE_MAX_TONES];
+	int tone_count;
+
+	teletone_process_t energy;
+	int current_sample;
+	
+	int min_samples;
+	int total_samples;
+
+	int positives;
+	int negatives;
+	int hits;
+
+	int positive_factor;
+	int negative_factor;
+	int hit_factor;
+
+} teletone_multi_tone_t;
+
+
+/*! 
+  \brief Initilize a multi-frequency tone detector
+  \param mt the multi-frequency tone descriptor
+  \param map a representation of the multi-frequency tone
+*/
+void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map);
+
+/*! 
+  \brief Check a sample buffer for the presence of the mulit-frequency tone described by mt
+  \param mt the multi-frequency tone descriptor
+  \param sample_buffer an array aof 16 bit signed linear samples
+  \param samples the number of samples present in sample_buffer
+  \return true when the tone was detected or false when it is not
+*/
+int teletone_multi_tone_detect (teletone_multi_tone_t *mt,
+								int16_t sample_buffer[],
+								int samples);
+
+/*! 
+  \brief Initilize a DTMF detection state object
+  \param dtmf_detect_state the DTMF detection state to initilize
+  \param sample_rate the desired sample rate
+*/
+void teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate);
+
+/*! 
+  \brief Check a sample buffer for the presence of DTMF digits
+  \param dtmf_detect_state the detection state object to check
+  \param sample_buffer an array aof 16 bit signed linear samples
+  \param samples the number of samples present in sample_buffer
+  \return true when DTMF was detected or false when it is not
+*/
+int teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
+						  int16_t sample_buffer[],
+						  int samples);
+/*! 
+  \brief retrieve any collected digits into a string buffer
+  \param dtmf_detect_state the detection state object to check
+  \param buf the string buffer to write to
+  \param max the maximum length of buf
+  \return the number of characters written to buf
+*/
+int teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
+					   char *buf,
+					   int max);
+
+/*! 
+  \brief Step through the Goertzel Algorithm for each sample in a buffer
+  \param goertzel_state the goertzel state to step the samples through
+  \param sample_buffer an array aof 16 bit signed linear samples
+  \param samples the number of samples present in sample_buffer
+*/
+void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
+							  int16_t sample_buffer[],
+							  int samples);
+
+/*! 
+  \brief Compute the result of the last applied step of the Goertzel Algorithm
+  \param goertzel_state the goertzel state to retrieve from
+  \return the computed value for consideration in furthur audio tests
+*/
+teletone_process_t teletone_goertzel_result (teletone_goertzel_state_t *goertzel_state);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/include/libteletone_generate.h b/libs/freetdm/src/include/libteletone_generate.h
new file mode 100644
index 0000000000..3d625e8f52
--- /dev/null
+++ b/libs/freetdm/src/include/libteletone_generate.h
@@ -0,0 +1,215 @@
+/* 
+ * libteletone
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is libteletone
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * libteletone.h -- Tone Generator
+ *
+ *
+ *
+ * Exception:
+ * The author hereby grants the use of this source code under the 
+ * following license if and only if the source code is distributed
+ * as part of the openzap library.  Any use or distribution of this
+ * source code outside the scope of the openzap library will nullify the
+ * following license and reinact the MPL 1.1 as stated above.
+ *
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef LIBTELETONE_GENERATE_H
+#define LIBTELETONE_GENERATE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <libteletone.h>
+
+
+
+/*! \file libteletone_generate.h
+    \brief Tone Generation Routines
+
+	This module is responsible for tone generation specifics
+*/
+
+typedef int16_t teletone_audio_t;
+struct teletone_generation_session;
+typedef int (*tone_handler)(struct teletone_generation_session *ts, teletone_tone_map_t *map);
+
+/*! \brief An abstraction to store a tone generation session */
+struct teletone_generation_session {
+	/*! An array of tone mappings to character mappings */
+	teletone_tone_map_t TONES[TELETONE_TONE_RANGE];
+	/*! The number of channels the output audio should be in */
+	int channels;
+	/*! The Rate in hz of the output audio */
+	int rate;
+	/*! The duration (in samples) of the output audio */
+	int duration;
+	/*! The duration of silence to append after the initial audio is generated */
+	int wait;
+	/*! The duration (in samples) of the output audio (takes prescedence over actual duration value) */
+	int tmp_duration;
+	/*! The duration of silence to append after the initial audio is generated (takes prescedence over actual wait value)*/
+	int tmp_wait;
+	/*! Number of loops to repeat a single instruction*/
+	int loops;
+	/*! Number of loops to repeat the entire set of instructions*/
+	int LOOPS;
+	/*! Number to mutiply total samples by to determine when to begin ascent or decent e.g. 0=beginning 4=(last 25%) */
+	int decay_factor;
+	/*! Direction to perform volume increase/decrease 1/-1*/
+	int decay_direction;
+	/*! Number of samples between increase/decrease of volume */
+	int decay_step;
+	/*! Volume factor of the tone */
+	int volume;
+	/*! Debug on/off */
+	int debug;
+	/*! FILE stream to write debug data to */
+	FILE *debug_stream;
+	/*! Extra user data to attach to the session*/
+	void *user_data;
+	/*! Buffer for storing sample data (dynamic) */
+	teletone_audio_t *buffer;
+	/*! Size of the buffer */
+	int datalen;
+	/*! In-Use size of the buffer */
+	int samples;
+	/*! Callback function called during generation */
+	int dynamic;
+	tone_handler handler;
+};
+
+typedef struct teletone_generation_session teletone_generation_session_t;
+
+
+/*! 
+  \brief Assign a set of tones to a tone_session indexed by a paticular index/character
+  \param ts the tone generation session
+  \param index the index to map the tone to
+  \param ... up to TELETONE_MAX_TONES frequencies terminated by 0.0
+  \return 0
+*/
+int teletone_set_tone(teletone_generation_session_t *ts, int index, ...);
+
+/*! 
+  \brief Assign a set of tones to a single tone map
+  \param map the map to assign the tones to
+  \param ... up to TELETONE_MAX_TONES frequencies terminated by 0.0
+  \return 0
+*/
+int teletone_set_map(teletone_tone_map_t *map, ...);
+
+/*! 
+  \brief Initilize a tone generation session
+  \param ts the tone generation session to initilize
+  \param buflen the size of the buffer(in samples) to dynamically allocate
+  \param handler a callback function to execute when a tone generation instruction is complete
+  \param user_data optional user data to send
+  \return 0
+*/
+int teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data);
+
+/*! 
+  \brief Free the buffer allocated by a tone generation session
+  \param ts the tone generation session to destroy
+  \return 0
+*/
+int teletone_destroy_session(teletone_generation_session_t *ts);
+
+/*! 
+  \brief Execute a single tone generation instruction
+  \param ts the tone generation session to consult for parameters
+  \param map the tone mapping to use for the frequencies
+  \return 0
+*/
+int teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map);
+
+/*! 
+  \brief Execute a tone generation script and call callbacks after each instruction
+  \param ts the tone generation session to execute on
+  \param cmd the script to execute
+  \return 0
+*/
+int teletone_run(teletone_generation_session_t *ts, char *cmd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h
index 3424a4ca47..07d0f20f2f 100644
--- a/libs/freetdm/src/include/openzap.h
+++ b/libs/freetdm/src/include/openzap.h
@@ -62,6 +62,8 @@
 #include <assert.h>
 #include "hashtable.h"
 #include "zap_config.h"
+#include "g711.h"
+#include "libteletone.h"
 
 #ifdef  NDEBUG
 #undef assert
@@ -115,7 +117,8 @@ struct zap_software_interface;
 
 typedef enum {
 	ZAP_SUCCESS,
-	ZAP_FAIL
+	ZAP_FAIL,
+	ZAP_MEMERR
 } zap_status_t;
 
 typedef enum {
@@ -205,6 +208,20 @@ typedef zap_status_t (*zint_write_t) ZINT_WRITE_ARGS ;
 #define ZINT_READ_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL)
 #define ZINT_WRITE_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL)
 
+#define ZAP_PRE __FILE__, __FUNCTION__, __LINE__
+#define ZAP_LOG_DEBUG ZAP_PRE, 7
+#define ZAP_LOG_INFO ZAP_PRE, 6
+#define ZAP_LOG_NOTICE ZAP_PRE, 5
+#define ZAP_LOG_WARNING ZAP_PRE, 4
+#define ZAP_LOG_ERROR ZAP_PRE, 3
+#define ZAP_LOG_CRIT ZAP_PRE, 2
+#define ZAP_LOG_ALERT ZAP_PRE, 1
+#define ZAP_LOG_EMERG ZAP_PRE, 0
+
+typedef void (*zap_logger_t)(char *file, const char *func, int line, int level, char *fmt, ...);
+extern zap_logger_t global_logger;
+#define zap_log global_logger;
+
 struct zap_software_interface {
 	const char *name;
 	zint_configure_t configure;
@@ -220,6 +237,7 @@ struct zap_software_interface {
 };
 typedef struct zap_software_interface zap_software_interface_t;
 
+
 zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span);
 zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan);
 zap_status_t zap_span_destroy(zap_span_t **span);
@@ -233,6 +251,8 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
 zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *datalen);
 zap_status_t zap_global_init(void);
 zap_status_t zap_global_destroy(void);
+void zap_global_set_logger(zap_logger_t logger);
+void zap_global_set_default_logger(void);
 
 typedef struct hashtable zap_hash_t;
 
diff --git a/libs/freetdm/src/include/zap_buffer.h b/libs/freetdm/src/include/zap_buffer.h
new file mode 100644
index 0000000000..cd16825787
--- /dev/null
+++ b/libs/freetdm/src/include/zap_buffer.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ZAP_BUFFER_H
+#define ZAP_BUFFER_H
+
+#include "openzap.h"
+
+/**
+ * @defgroup zap_buffer Buffer Routines
+ * @ingroup buffer
+ * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers
+ * throughout the application.
+ * @{
+ */
+struct zap_buffer;
+typedef struct zap_buffer zap_buffer_t;
+
+/*! \brief Allocate a new dynamic zap_buffer 
+ * \param buffer returned pointer to the new buffer
+ * \param blocksize length to realloc by as data is added
+ * \param start_len ammount of memory to reserve initially
+ * \param max_len length the buffer is allowed to grow to
+ * \return status
+ */
+zap_status_t zap_buffer_create(zap_buffer_t **buffer, zap_size_t blocksize, zap_size_t start_len, zap_size_t max_len);
+
+/*! \brief Get the length of a zap_buffer_t 
+ * \param buffer any buffer of type zap_buffer_t
+ * \return int size of the buffer.
+ */
+zap_size_t zap_buffer_len(zap_buffer_t *buffer);
+
+/*! \brief Get the freespace of a zap_buffer_t 
+ * \param buffer any buffer of type zap_buffer_t
+ * \return int freespace in the buffer.
+ */
+zap_size_t zap_buffer_freespace(zap_buffer_t *buffer);
+
+/*! \brief Get the in use amount of a zap_buffer_t 
+ * \param buffer any buffer of type zap_buffer_t
+ * \return int ammount of buffer curently in use
+ */
+zap_size_t zap_buffer_inuse(zap_buffer_t *buffer);
+
+/*! \brief Read data from a zap_buffer_t up to the ammount of datalen if it is available.  Remove read data from buffer. 
+ * \param buffer any buffer of type zap_buffer_t
+ * \param data pointer to the read data to be returned
+ * \param datalen amount of data to be returned
+ * \return int ammount of data actually read
+ */
+zap_size_t zap_buffer_read(zap_buffer_t *buffer, void *data, zap_size_t datalen);
+
+/*! \brief Read data endlessly from a zap_buffer_t 
+ * \param buffer any buffer of type zap_buffer_t
+ * \param data pointer to the read data to be returned
+ * \param datalen amount of data to be returned
+ * \return int ammount of data actually read
+ * \note Once you have read all the data from the buffer it will loop around.
+ */
+zap_size_t zap_buffer_read_loop(zap_buffer_t *buffer, void *data, zap_size_t datalen);
+
+/*! \brief Assign a number of loops to read
+ * \param buffer any buffer of type zap_buffer_t
+ * \param loops the number of loops (-1 for infinite)
+ */
+void zap_buffer_set_loops(zap_buffer_t *buffer, int32_t loops);
+
+/*! \brief Write data into a zap_buffer_t up to the length of datalen
+ * \param buffer any buffer of type zap_buffer_t
+ * \param data pointer to the data to be written
+ * \param datalen amount of data to be written
+ * \return int amount of buffer used after the write, or 0 if no space available
+ */
+zap_size_t zap_buffer_write(zap_buffer_t *buffer, const void *data, zap_size_t datalen);
+
+/*! \brief Remove data from the buffer
+ * \param buffer any buffer of type zap_buffer_t
+ * \param datalen amount of data to be removed
+ * \return int size of buffer, or 0 if unable to toss that much data
+ */
+zap_size_t zap_buffer_toss(zap_buffer_t *buffer, zap_size_t datalen);
+
+/*! \brief Remove all data from the buffer
+ * \param buffer any buffer of type zap_buffer_t
+ */
+void zap_buffer_zero(zap_buffer_t *buffer);
+
+/*! \brief Destroy the buffer
+ * \param buffer buffer to destroy
+ * \note only neccessary on dynamic buffers (noop on pooled ones)
+ */
+void zap_buffer_destroy(zap_buffer_t **buffer);
+
+/** @} */
+
+
+#endif
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/libteletone_detect.c b/libs/freetdm/src/libteletone_detect.c
new file mode 100644
index 0000000000..8df7d569a4
--- /dev/null
+++ b/libs/freetdm/src/libteletone_detect.c
@@ -0,0 +1,453 @@
+/* 
+ * libteletone
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
+ *
+ *
+ * The Initial Developer of the Original Code is
+ * Stephen Underwood <steveu@coppice.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * The the original interface designed by Steve Underwood was preserved to retain 
+ *the optimizations when considering DTMF tones though the names were changed in the interest 
+ * of namespace.
+ *
+ * Much less efficient expansion interface was added to allow for the detection of 
+ * a single arbitrary tone combination which may also exceed 2 simultaneous tones.
+ * (controlled by compile time constant TELETONE_MAX_TONES)
+ *
+ * Copyright (C) 2006 Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * libteletone_detect.c Tone Detection Code
+ *
+ *
+ ********************************************************************************* 
+ *
+ * Derived from tone_detect.c - General telephony tone detection, and specific
+ * detection of DTMF.
+ *
+ * Copyright (C) 2001  Steve Underwood <steveu@coppice.org>
+ *
+ * Despite my general liking of the GPL, I place this code in the
+ * public domain for the benefit of all mankind - even the slimy
+ * ones who might try to proprietize my work and use it to my
+ * detriment.
+ *
+ *
+ * Exception:
+ * The author hereby grants the use of this source code under the 
+ * following license if and only if the source code is distributed
+ * as part of the openzap library.  Any use or distribution of this
+ * source code outside the scope of the openzap library will nullify the
+ * following license and reinact the MPL 1.1 as stated above.
+ *
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <math.h>
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <fcntl.h>
+#include <libteletone_detect.h>
+
+static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
+static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
+static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
+static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR];
+
+static teletone_process_t dtmf_row[] = {697.0,  770.0,  852.0,  941.0};
+static teletone_process_t dtmf_col[] = {1209.0, 1336.0, 1477.0, 1633.0};
+
+
+static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
+
+static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) {
+    goertzel_state->v2 = goertzel_state->v3 = 0.0;
+    goertzel_state->fac = tdesc->fac;
+}
+
+void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
+							  int16_t sample_buffer[],
+							  int samples)
+{
+    int i;
+    teletone_process_t v1;
+    
+    for (i = 0;  i < samples;  i++) {
+        v1 = goertzel_state->v2;
+        goertzel_state->v2 = goertzel_state->v3;
+        goertzel_state->v3 = goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i];
+    }
+}
+
+teletone_process_t teletone_goertzel_result (teletone_goertzel_state_t *goertzel_state)
+{
+    return goertzel_state->v3 * goertzel_state->v3 + goertzel_state->v2 * goertzel_state->v2 - goertzel_state->v2 * goertzel_state->v3 * goertzel_state->fac;
+}
+
+void teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
+{
+    int i;
+    teletone_process_t theta;
+
+    dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
+
+    for (i = 0;  i < GRID_FACTOR;  i++) {
+        theta = M_TWO_PI*(dtmf_row[i]/(teletone_process_t)sample_rate);
+        dtmf_detect_row[i].fac = 2.0*cos(theta);
+
+        theta = M_TWO_PI*(dtmf_col[i]/(teletone_process_t)sample_rate);
+        dtmf_detect_col[i].fac = 2.0*cos(theta);
+    
+        theta = M_TWO_PI*(dtmf_row[i]*2.0/(teletone_process_t)sample_rate);
+        dtmf_detect_row_2nd[i].fac = 2.0*cos(theta);
+
+        theta = M_TWO_PI*(dtmf_col[i]*2.0/(teletone_process_t)sample_rate);
+        dtmf_detect_col_2nd[i].fac = 2.0*cos(theta);
+    
+		goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
+    	goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
+    	goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
+    	goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
+	
+		dtmf_detect_state->energy = 0.0;
+    }
+    dtmf_detect_state->current_sample = 0;
+    dtmf_detect_state->detected_digits = 0;
+    dtmf_detect_state->lost_digits = 0;
+    dtmf_detect_state->digits[0] = '\0';
+    dtmf_detect_state->mhit = 0;
+}
+
+void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
+{
+	teletone_process_t theta = 0;
+	int x = 0;
+
+	if(!mt->min_samples) {
+		mt->min_samples = 102;
+	}
+
+	if (!mt->positive_factor) {
+		mt->positive_factor = 2;
+	}
+
+	if(!mt->negative_factor) {
+		mt->negative_factor = 10;
+	}
+
+	if (!mt->hit_factor) {
+		mt->hit_factor = 2;
+	}
+
+	if (!mt->sample_rate) {
+		mt->sample_rate = 8000;
+	}
+
+	for(x = 0; x < TELETONE_MAX_TONES; x++) {
+		if ((int) map->freqs[x] == 0) {
+			break;
+		}
+		mt->tone_count++;
+		theta = M_TWO_PI*(map->freqs[x]/(teletone_process_t)mt->sample_rate);
+		mt->tdd[x].fac = 2.0 * cos(theta);
+		goertzel_init (&mt->gs[x], &mt->tdd[x]);
+		goertzel_init (&mt->gs2[x], &mt->tdd[x]);
+	}
+
+}
+
+int teletone_multi_tone_detect (teletone_multi_tone_t *mt,
+					   int16_t sample_buffer[],
+					   int samples)
+{
+	int sample, limit, j, x = 0;
+	teletone_process_t v1, famp;
+	teletone_process_t eng_sum = 0, eng_all[TELETONE_MAX_TONES];
+	int gtest = 0, see_hit = 0;
+
+    for (sample = 0;  sample < samples;  sample = limit) {
+		mt->total_samples++;
+
+        if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
+            limit = sample + (mt->min_samples - mt->current_sample);
+		} else {
+            limit = samples;
+		}
+
+        for (j = sample;  j < limit;  j++) {
+            famp = sample_buffer[j];
+			
+			mt->energy += famp*famp;
+
+			for(x = 0; x < mt->tone_count; x++) {
+				v1 = mt->gs[x].v2;
+				mt->gs[x].v2 = mt->gs[x].v3;
+				mt->gs[x].v3 = mt->gs[x].fac * mt->gs[x].v2 - v1 + famp;
+    
+				v1 = mt->gs2[x].v2;
+				mt->gs2[x].v2 = mt->gs2[x].v3;
+				mt->gs2[x].v3 = mt->gs2[x].fac*mt->gs2[x].v2 - v1 + famp;
+			}
+		}
+
+        mt->current_sample += (limit - sample);
+        if (mt->current_sample < mt->min_samples) {
+            continue;
+		}
+
+		eng_sum = 0;
+		for(x = 0; x < mt->tone_count; x++) {
+			eng_all[x] = teletone_goertzel_result (&mt->gs[x]);
+			eng_sum += eng_all[x];
+		}
+
+		gtest = 0;
+		for(x = 0; x < mt->tone_count; x++) {
+			gtest += teletone_goertzel_result (&mt->gs2[x]) < eng_all[x] ? 1 : 0;
+		}
+
+		if ((gtest >= 2 || gtest == mt->tone_count) && eng_sum > 42.0 * mt->energy) {
+			if(mt->negatives) {
+				mt->negatives--;
+			}
+			mt->positives++;
+
+			if(mt->positives >= mt->positive_factor) {
+				mt->hits++;
+			}
+			if (mt->hits >= mt->hit_factor) {
+				see_hit++;
+				mt->positives = mt->negatives = mt->hits = 0;
+			}
+		} else {
+			mt->negatives++;
+			if(mt->positives) {
+				mt->positives--;
+			}
+			if(mt->negatives > mt->negative_factor) {
+				mt->positives = mt->hits = 0;
+			}
+		}
+
+        /* Reinitialise the detector for the next block */
+		for(x = 0; x < mt->tone_count; x++) {
+			goertzel_init (&mt->gs[x], &mt->tdd[x]);
+			goertzel_init (&mt->gs2[x], &mt->tdd[x]);
+		}
+
+		mt->energy = 0.0;
+        mt->current_sample = 0;
+    }
+
+	return see_hit;
+}
+
+
+int teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
+                 int16_t sample_buffer[],
+                 int samples)
+{
+    teletone_process_t row_energy[GRID_FACTOR];
+    teletone_process_t col_energy[GRID_FACTOR];
+    teletone_process_t famp;
+    teletone_process_t v1;
+    int i;
+    int j;
+    int sample;
+    int best_row;
+    int best_col;
+    char hit;
+    int limit;
+
+    hit = 0;
+    for (sample = 0;  sample < samples;  sample = limit) {
+        /* BLOCK_LEN is optimised to meet the DTMF specs. */
+        if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
+            limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample);
+		} else {
+            limit = samples;
+		}
+
+        for (j = sample;  j < limit;  j++) {
+			int x = 0;
+            famp = sample_buffer[j];
+			
+			dtmf_detect_state->energy += famp*famp;
+
+			for(x = 0; x < GRID_FACTOR; x++) {
+				v1 = dtmf_detect_state->row_out[x].v2;
+				dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3;
+				dtmf_detect_state->row_out[x].v3 = dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp;
+    
+				v1 = dtmf_detect_state->col_out[x].v2;
+				dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3;
+				dtmf_detect_state->col_out[x].v3 = dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp;
+
+				v1 = dtmf_detect_state->col_out2nd[x].v2;
+				dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3;
+				dtmf_detect_state->col_out2nd[x].v3 = dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp;
+        
+				v1 = dtmf_detect_state->row_out2nd[x].v2;
+				dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3;
+				dtmf_detect_state->row_out2nd[x].v3 = dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp;
+			}
+
+        }
+
+        dtmf_detect_state->current_sample += (limit - sample);
+        if (dtmf_detect_state->current_sample < BLOCK_LEN) {
+            continue;
+		}
+        /* We are at the end of a DTMF detection block */
+        /* Find the peak row and the peak column */
+        row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]);
+        col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]);
+
+		for (best_row = best_col = 0, i = 1;  i < GRID_FACTOR;  i++) {
+    	    row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]);
+            if (row_energy[i] > row_energy[best_row]) {
+                best_row = i;
+			}
+    	    col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]);
+            if (col_energy[i] > col_energy[best_col]) {
+                best_col = i;
+			}
+    	}
+        hit = 0;
+        /* Basic signal level test and the twist test */
+        if (row_energy[best_row] >= DTMF_THRESHOLD &&
+			col_energy[best_col] >= DTMF_THRESHOLD &&
+            col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
+            col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
+            /* Relative peak test */
+            for (i = 0;  i < GRID_FACTOR;  i++) {
+                if ((i != best_col  &&  col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
+                    (i != best_row  &&  row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
+                    break;
+                }
+            }
+            /* ... and second harmonic test */
+            if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
+                teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
+                teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
+                hit = dtmf_positions[(best_row << 2) + best_col];
+                /* Look for two successive similar results */
+                /* The logic in the next test is:
+                   We need two successive identical clean detects, with
+				   something different preceeding it. This can work with
+				   back to back differing digits. More importantly, it
+				   can work with nasty phones that give a very wobbly start
+				   to a digit. */
+                if (hit == dtmf_detect_state->hit3  &&  dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
+					dtmf_detect_state->mhit = hit;
+					dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
+					dtmf_detect_state->detected_digits++;
+					if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
+						dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
+						dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
+					}
+					else
+						{
+							dtmf_detect_state->lost_digits++;
+						}
+				}
+            }
+        }
+        dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
+        dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
+        dtmf_detect_state->hit3 = hit;
+        /* Reinitialise the detector for the next block */
+        for (i = 0;  i < GRID_FACTOR;  i++) {
+       	    goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
+            goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
+    	    goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
+    	    goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
+        }
+		dtmf_detect_state->energy = 0.0;
+        dtmf_detect_state->current_sample = 0;
+    }
+    if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
+		dtmf_detect_state->mhit = 0;
+		return(0);
+    }
+    return (hit);
+}
+
+
+int teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
+              char *buf,
+              int max)
+{
+    if (max > dtmf_detect_state->current_digits) {
+        max = dtmf_detect_state->current_digits;
+	}
+    if (max > 0) {
+        memcpy (buf, dtmf_detect_state->digits, max);
+        memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
+        dtmf_detect_state->current_digits -= max;
+    }
+    buf[max] = '\0';
+    return  max;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/libteletone_generate.c b/libs/freetdm/src/libteletone_generate.c
new file mode 100644
index 0000000000..4e388c8d3b
--- /dev/null
+++ b/libs/freetdm/src/libteletone_generate.c
@@ -0,0 +1,467 @@
+/* 
+ * libteletone
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is libteletone
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * libteletone.c -- Tone Generator
+ *
+ *
+ *
+ * Exception:
+ * The author hereby grants the use of this source code under the 
+ * following license if and only if the source code is distributed
+ * as part of the openzap library.  Any use or distribution of this
+ * source code outside the scope of the openzap library will nullify the
+ * following license and reinact the MPL 1.1 as stated above.
+ *
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libteletone.h>
+#define SMAX 32767
+#define SMIN -32768
+#define normalize_to_16bit(n) if (n > SMAX) n = SMAX; else if (n < SMIN) n = SMIN;
+
+#ifdef _MSC_VER
+#pragma warning(disable:4706)
+#endif
+
+
+int teletone_set_tone(teletone_generation_session_t *ts, int index, ...)
+{
+	va_list ap;
+	int i = 0;
+	teletone_process_t x = 0;
+
+	va_start(ap, index);
+	while (i <= TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) {
+		ts->TONES[index].freqs[i++] = x;
+	}
+	va_end(ap);
+
+	return (i > TELETONE_MAX_TONES) ? -1 : 0;
+	
+}
+
+int teletone_set_map(teletone_tone_map_t *map, ...)
+{
+	va_list ap;
+	int i = 0;
+	teletone_process_t x = 0;
+
+	va_start(ap, map);
+	while (i <= TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) {
+		map->freqs[i++] = x;
+	}
+	va_end(ap);
+
+	return (i > TELETONE_MAX_TONES) ? -1 : 0;
+	
+}
+
+int teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
+{
+	memset(ts, 0, sizeof(*ts));
+	ts->rate = 8000;
+	ts->channels = 1;
+	ts->duration = 2000;
+	ts->wait = 500;
+	ts->tmp_duration = -1;
+	ts->tmp_wait = -1;
+	ts->handler = handler;
+	ts->user_data = user_data;
+	ts->volume = 1500;
+	ts->decay_step = 0;
+	if (buflen) {
+		if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) {
+			return -1;
+		}
+		ts->datalen = buflen;
+	} else {
+		ts->dynamic = 1024;
+	}
+	/* Add Standard DTMF Tones */
+	teletone_set_tone(ts, '1', 697.0, 1209.0, 0.0);
+	teletone_set_tone(ts, '2', 697.0, 1336.0, 0.0);
+	teletone_set_tone(ts, '3', 697.0, 1477.0, 0.0);
+	teletone_set_tone(ts, 'A', 697.0, 1633.0, 0.0);
+	teletone_set_tone(ts, '4', 770.0, 1209.0, 0.0);
+	teletone_set_tone(ts, '5', 770.0, 1336.0, 0.0);
+	teletone_set_tone(ts, '6', 770.0, 1477.0, 0.0);
+	teletone_set_tone(ts, 'B', 770.0, 1633.0, 0.0);
+	teletone_set_tone(ts, '7', 859.0, 1209.0, 0.0);
+	teletone_set_tone(ts, '8', 859.0, 1336.0, 0.0);
+	teletone_set_tone(ts, '9', 859.0, 1477.0, 0.0);
+	teletone_set_tone(ts, 'C', 859.0, 1633.0, 0.0);
+	teletone_set_tone(ts, '*', 941.0, 1209.0, 0.0);
+	teletone_set_tone(ts, '0', 941.0, 1336.0, 0.0);
+	teletone_set_tone(ts, '#', 941.0, 1477.0, 0.0);
+	teletone_set_tone(ts, 'D', 941.0, 1633.0, 0.0);
+	
+	return 0;
+}
+
+int teletone_destroy_session(teletone_generation_session_t *ts)
+{
+	if (ts->buffer) {
+		free(ts->buffer);
+		ts->buffer = NULL;
+		ts->samples = 0;
+	}
+	return 0;
+}
+
+static int ensure_buffer(teletone_generation_session_t *ts, int need)
+{
+	need += ts->samples;
+	need *= sizeof(teletone_audio_t);
+	need *= ts->channels;
+
+	if (need > ts->datalen) {
+		ts->datalen = need + ts->dynamic;
+		if (!(ts->buffer = realloc(ts->buffer, ts->datalen))) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map)
+{
+	teletone_process_t period = (1.0 / ts->rate) / ts->channels;
+	int i, c;
+	int freqlen = 0;
+	teletone_process_t tones[TELETONE_MAX_TONES];
+	int decay = 0;
+	int duration;
+	int wait = 0;
+	teletone_process_t sample;
+	
+	ts->samples = 0;
+
+	duration = (ts->tmp_duration > -1) ? ts->tmp_duration : ts->duration;
+	wait = (ts->tmp_wait > -1) ? ts->tmp_wait : ts->wait;
+
+	if (map->freqs[0] > 0) {
+		if (ts->decay_step) {
+			if (ts->decay_factor) {
+				decay = (duration - (duration / ts->decay_factor));
+			} else {
+				decay = 0;
+			}
+		}
+		if (ts->volume < 0) {
+			ts->volume = 0;
+		}
+	
+		for (freqlen = 0; map->freqs[freqlen] && freqlen < TELETONE_MAX_TONES; freqlen++) {
+			tones[freqlen] = (teletone_process_t) map->freqs[freqlen] * (2 * M_PI);
+		}
+	
+		if (ts->channels > 1) {
+			duration *= ts->channels;
+		}
+
+		if (ts->dynamic) {
+			if (ensure_buffer(ts, duration)) {
+				return -1;
+			}
+		}
+		for (ts->samples = 0; ts->samples < ts->datalen && ts->samples < duration; ts->samples++) {
+			if (ts->decay_step && !(ts->samples % ts->decay_step) && ts->volume > 0 && ts->samples > decay) {
+				ts->volume += ts->decay_direction;
+			}
+
+			sample = (teletone_process_t) 128;
+
+			for (i = 0; i < freqlen; i++) {
+				sample += ((teletone_process_t) 2 * (ts->volume > 0 ? ts->volume : 1) * cos(tones[i] * ts->samples * period));
+			}
+			normalize_to_16bit(sample);
+			ts->buffer[ts->samples] = (teletone_audio_t)sample;
+			
+			for (c = 1; c < ts->channels; c++) {
+				ts->buffer[ts->samples+1] = ts->buffer[ts->samples];
+				ts->samples++;
+			}
+			
+		}
+	}
+	if (ts->dynamic) {
+		if (ensure_buffer(ts, wait)) {
+			return -1;
+		}
+	}
+	for (c = 0; c < ts->channels; c++) {
+		for (i = 0; i < wait && ts->samples < ts->datalen; i++) {
+			ts->buffer[ts->samples++] = 0;
+		}
+	}
+
+	if (ts->debug && ts->debug_stream) {
+		if (map->freqs[0] <= 0) {
+			fprintf(ts->debug_stream, "wait %d (%dms)\n", wait, wait / (ts->rate / 1000));
+		} else {
+			fprintf(ts->debug_stream, "Generate: (");
+
+			for (i = 0; i < TELETONE_MAX_TONES && map->freqs[i]; i++) {
+				fprintf(ts->debug_stream, "%s%0.2f", i == 0 ? "" : "+",map->freqs[i]);
+			}
+			 
+			fprintf(ts->debug_stream, ") [volume %d; samples %d(%dms) x %d channel%s; wait %d(%dms); decay_factor %d; decay_step %d; wrote %d bytes]\n",
+					ts->volume,
+					duration,
+					duration / (ts->rate / 1000), 
+					ts->channels,
+					ts->channels == 1 ? "" : "s",
+					wait,
+					wait / (ts->rate / 1000),
+					ts->decay_factor,
+					ts->decay_step,
+					ts->samples * 2);
+		}
+	}	
+	return ts->samples;
+}
+
+/* don't ask */
+static char *my_strdup (const char *s)
+{
+	size_t len = strlen (s) + 1;
+	void *new = malloc (len);
+	
+	if (new == NULL) {
+		return NULL;
+	}
+
+	return (char *) memcpy (new, s, len);
+}
+
+int teletone_run(teletone_generation_session_t *ts, char *cmd)
+{
+	char *data = NULL, *cur = NULL, *end = NULL;
+	int var = 0, LOOPING = 0;
+	
+	if (!cmd) {
+		return -1;
+	}
+
+	do {
+		if (!(data = my_strdup(cmd))) {
+			return -1;
+		}
+
+		cur = data;
+
+		while (*cur) {
+			var = 0;
+			if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
+				cur++;
+				continue;
+			}
+
+			if ((end = strchr(cur, ';')) != 0) {
+				*end++ = '\0';
+			}
+			
+			if (*(cur + 1) == '=') {
+				var = 1;
+				switch(*cur) {
+				case 'c':
+					ts->channels = atoi(cur + 2);
+					break;
+				case 'r':
+					ts->rate = atoi(cur + 2);
+					break;
+				case 'd':
+					ts->duration = atoi(cur + 2) * (ts->rate / 1000);
+					break;
+				case 'v':
+					ts->volume = atoi(cur + 2);
+					break;
+				case '>':
+					ts->decay_factor = atoi(cur + 2);
+					ts->decay_direction = -1;
+					break;
+				case '<':
+					ts->decay_factor = atoi(cur + 2);
+					ts->decay_direction = 1;
+					break;
+				case '+':
+					ts->decay_step = atoi(cur + 2);
+					break;
+				case 'w':
+					ts->wait = atoi(cur + 2) * (ts->rate / 1000);
+					break;
+				case 'l':
+					ts->loops = atoi(cur + 2); 
+					break;
+				case 'L':
+					if (!LOOPING) {
+						ts->LOOPS = atoi(cur + 2); 
+					}
+					LOOPING++;
+					break;
+				}
+			} else {
+				while (*cur) {
+					char *p = NULL, *e = NULL;
+					teletone_tone_map_t mymap, *mapp = NULL;
+
+					if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
+						cur++;
+						continue;
+					}
+					
+					ts->tmp_duration = -1;
+					ts->tmp_wait = -1;
+
+					memset(&mymap, 0, sizeof(mymap));
+
+					if (*(cur + 1) == '(') {
+						p = cur + 2;
+						if (*cur) {
+							char *next;
+							int i = 0;
+							if ((e = strchr(p, ')')) != 0) {
+								*e++ = '\0';
+							}
+							do {
+								if ((next = strchr(p, ',')) != 0) {
+									*next++ = '\0';
+								}
+								if (i == 0) {
+									ts->tmp_duration = atoi(p) * (ts->rate / 1000);
+									i++;
+								} else if (i == 1) {
+									ts->tmp_wait = atoi(p) * (ts->rate / 1000);
+									i++;
+								} else {
+									mymap.freqs[i++ - 2] = atof(p);
+								}
+								p = next;
+
+							} while (next && (i-2) < TELETONE_MAX_TONES);
+							if (i > 2 && *cur == '%') {
+								mapp = &mymap;
+							} else if ((i != 2 || *cur == '%')) { 
+								if (ts->debug && ts->debug_stream) {
+									fprintf(ts->debug_stream, "Syntax Error!\n");
+								}
+								goto bottom;
+							}
+						} 
+					}
+
+					if (*cur && !mapp) {
+						if (*cur > 0 && *cur < TELETONE_TONE_RANGE) { 
+							mapp = &ts->TONES[(int)*cur];
+						} else if (ts->debug && ts->debug_stream) {
+							fprintf(ts->debug_stream, "Map [%c] Out Of Range!\n", *cur);
+						}
+					}
+
+					if (mapp) {
+						if (mapp->freqs[0]) {
+							if (ts->handler) {
+								do {
+									ts->handler(ts, mapp);
+									if (ts->loops > 0) {
+										ts->loops--;
+									}
+								} while (ts->loops);
+							}
+						} else if (ts->debug && ts->debug_stream) {
+							fprintf(ts->debug_stream, "Ignoring Empty Map [%c]!\n", *cur);
+						}
+					}
+					
+					if (e) {
+						cur = e;
+					} else {
+						cur++;
+					}
+				}
+			}
+
+			if (end) {
+				cur = end;
+			} else if (*cur){
+				cur++;
+			}
+		}
+	bottom:
+		free(data);
+		data = NULL;
+		if (ts->LOOPS > 0) {
+			ts->LOOPS--;
+		}
+
+	} while (ts->LOOPS);
+
+	return 0;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/openzap.c b/libs/freetdm/src/openzap.c
index 40c3173975..acf21e14f2 100644
--- a/libs/freetdm/src/openzap.c
+++ b/libs/freetdm/src/openzap.c
@@ -33,6 +33,7 @@
 
 
 #include "openzap.h"
+#include <stdarg.h>
 #ifdef ZAP_WANPIPE_SUPPORT
 #include "zap_wanpipe.h"
 #endif
@@ -44,6 +45,78 @@ static struct {
 	zap_hash_t *interface_hash;
 } globals;
 
+static char *LEVEL_NAMES[] = {
+	"EMERG",
+	"ALERT",
+	"CRIT",
+	"ERROR",
+	"WARNING",
+	"NOTICE",
+	"INFO",
+	"DEBUG",
+	NULL
+};
+
+static char *cut_path(char *in)
+{
+	char *p, *ret = in;
+	char delims[] = "/\\";
+	char *i;
+
+	for (i = delims; *i; i++) {
+		p = in;
+		while ((p = strchr(p, *i)) != 0) {
+			ret = ++p;
+		}
+	}
+	return ret;
+}
+
+static void null_logger(char *file, const char *func, int line, int level, char *fmt, ...)
+{
+	if (0) {
+		null_logger(file, func, line, level, fmt);
+	}
+}
+
+static void default_logger(char *file, const char *func, int line, int level, char *fmt, ...)
+{
+	char *fp;
+	char data[1024];
+
+	va_list ap;
+	
+	fp = cut_path(file);
+
+	va_start(ap, fmt);
+
+	vsnprintf(data, sizeof(data), fmt, ap);
+
+	if (level < 0 || level > 7) {
+		level = 7;
+	}
+
+	fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
+
+	va_end(ap);
+
+}
+
+zap_logger_t global_logger = null_logger;
+
+void zap_global_set_logger(zap_logger_t logger)
+{
+	if (logger) {
+		global_logger = logger;
+	} else {
+		global_logger = null_logger;
+	}
+}
+
+void zap_global_set_default_logger(void)
+{
+	global_logger = default_logger;
+}
 
 static int equalkeys(const void *k1, const void *k2)
 {
diff --git a/libs/freetdm/src/wanpipe b/libs/freetdm/src/wanpipe
index 4f410a083b..917220c04e 100644
--- a/libs/freetdm/src/wanpipe
+++ b/libs/freetdm/src/wanpipe
@@ -1,7 +1,6 @@
-CFLAGS +=-DZAP_WANPIPE_SUPPORT
+MOD_CFLAGS +=-DZAP_WANPIPE_SUPPORT
 OBJS += zap_wanpipe.o
 WANPIPE_INCLUDE=/usr/include/wanpipe
-#WANPIPE_INCLUDE=../../wanpipe-3.1.0.p18/patches/kdrivers/include
 
 WP_CFLAGS =-I$(WANPIPE_INCLUDE) -I/usr/local/include -I/usr/src/linux/include -I. -I/usr/include 
 WP_CFLAGS +=-D__LINUX__ -D_REENTRANT -D_GNU_SOURCE -DAFT_A104 -DWANPIPE_TDM_API -D_GNUC_ -DWANPIPE_TDM_API
diff --git a/libs/freetdm/src/zap_buffer.c b/libs/freetdm/src/zap_buffer.c
new file mode 100644
index 0000000000..b3df9ba0ab
--- /dev/null
+++ b/libs/freetdm/src/zap_buffer.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "openzap.h"
+#include "zap_buffer.h"
+
+static unsigned buffer_id = 0;
+
+struct zap_buffer {
+	unsigned char *data;
+	unsigned char *head;
+	zap_size_t used;
+	zap_size_t actually_used;
+	zap_size_t datalen;
+	zap_size_t max_len;
+	zap_size_t blocksize;
+	unsigned id;
+	int loops;
+};
+
+
+zap_status_t zap_buffer_create(zap_buffer_t **buffer, zap_size_t blocksize, zap_size_t start_len, zap_size_t max_len)
+{
+	zap_buffer_t *new_buffer;
+
+	if ((new_buffer = malloc(sizeof(*new_buffer)))) {
+		memset(new_buffer, 0, sizeof(*new_buffer));
+
+		if (start_len) {
+			if (!(new_buffer->data = malloc(start_len))) {
+				free(new_buffer);
+				return ZAP_MEMERR;
+			}
+			memset(new_buffer->data, 0, start_len);
+		}
+
+		new_buffer->max_len = max_len;
+		new_buffer->datalen = start_len;
+		new_buffer->id = buffer_id++;
+		new_buffer->blocksize = blocksize;
+		new_buffer->head = new_buffer->data;
+
+		*buffer = new_buffer;
+		return ZAP_SUCCESS;
+	}
+
+	return ZAP_MEMERR;
+}
+
+zap_size_t zap_buffer_len(zap_buffer_t *buffer)
+{
+
+	assert(buffer != NULL);
+
+	return buffer->datalen;
+
+}
+
+
+zap_size_t zap_buffer_freespace(zap_buffer_t *buffer)
+{
+	assert(buffer != NULL);
+
+
+	if (buffer->max_len) {
+		return (zap_size_t) (buffer->max_len - buffer->used);
+	}
+	return 1000000;
+
+}
+
+zap_size_t zap_buffer_inuse(zap_buffer_t *buffer)
+{
+	assert(buffer != NULL);
+
+	return buffer->used;
+}
+
+zap_size_t zap_buffer_toss(zap_buffer_t *buffer, zap_size_t datalen)
+{
+	zap_size_t reading = 0;
+
+	assert(buffer != NULL);
+
+	if (buffer->used < 1) {
+		buffer->used = 0;
+		return 0;
+	} else if (buffer->used >= datalen) {
+		reading = datalen;
+	} else {
+		reading = buffer->used;
+	}
+
+	buffer->used -= reading;
+	buffer->head += reading;
+
+	return buffer->used;
+}
+
+void zap_buffer_set_loops(zap_buffer_t *buffer, int loops)
+{
+	buffer->loops = loops;
+}
+
+zap_size_t zap_buffer_read_loop(zap_buffer_t *buffer, void *data, zap_size_t datalen)
+{
+	zap_size_t len;
+	if ((len = zap_buffer_read(buffer, data, datalen)) == 0) {
+		if (buffer->loops == 0) {
+			return 0;
+		}
+		buffer->head = buffer->data;
+		buffer->used = buffer->actually_used;
+		len = zap_buffer_read(buffer, data, datalen);
+		buffer->loops--;
+	}
+	return len;
+}
+
+zap_size_t zap_buffer_read(zap_buffer_t *buffer, void *data, zap_size_t datalen)
+{
+	zap_size_t reading = 0;
+
+	assert(buffer != NULL);
+	assert(data != NULL);
+
+
+	if (buffer->used < 1) {
+		buffer->used = 0;
+		return 0;
+	} else if (buffer->used >= datalen) {
+		reading = datalen;
+	} else {
+		reading = buffer->used;
+	}
+
+	memcpy(data, buffer->head, reading);
+	buffer->used -= reading;
+	buffer->head += reading;
+
+	/* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */
+	return reading;
+}
+
+zap_size_t zap_buffer_write(zap_buffer_t *buffer, const void *data, zap_size_t datalen)
+{
+	zap_size_t freespace, actual_freespace;
+
+	assert(buffer != NULL);
+	assert(data != NULL);
+	assert(buffer->data != NULL);
+
+	if (!datalen) {
+		return buffer->used;
+	}
+
+	actual_freespace = buffer->datalen - buffer->actually_used;
+
+	if (actual_freespace < datalen) {
+		memmove(buffer->data, buffer->head, buffer->used);
+		buffer->head = buffer->data;
+		buffer->actually_used = buffer->used;
+	}
+
+	freespace = buffer->datalen - buffer->used;
+
+	/*
+	   if (buffer->data != buffer->head) {
+	   memmove(buffer->data, buffer->head, buffer->used);
+	   buffer->head = buffer->data;
+	   }
+	 */
+	
+	if (freespace < datalen) {
+		zap_size_t new_size, new_block_size;
+		
+		new_size = buffer->datalen + datalen;
+		new_block_size = buffer->datalen + buffer->blocksize;
+
+		if (new_block_size > new_size) {
+			new_size = new_block_size;
+		}
+		buffer->head = buffer->data;
+		if (!(buffer->data = realloc(buffer->data, new_size))) {
+			return 0;
+		}
+		buffer->head = buffer->data;
+		buffer->datalen = new_size;
+	}
+	
+
+	freespace = buffer->datalen - buffer->used;
+
+	if (freespace < datalen) {
+		return 0;
+	} else {
+		memcpy(buffer->head + buffer->used, data, datalen);
+		buffer->used += datalen;
+		buffer->actually_used += datalen;
+	}
+	/* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */
+
+	return buffer->used;
+}
+
+void zap_buffer_zero(zap_buffer_t *buffer)
+{
+	assert(buffer != NULL);
+	assert(buffer->data != NULL);
+
+	buffer->used = 0;
+	buffer->head = buffer->data;
+}
+
+void zap_buffer_destroy(zap_buffer_t **buffer)
+{
+	if (*buffer) {
+		free((*buffer)->data);
+		free(*buffer);
+	}
+
+	*buffer = NULL;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
diff --git a/libs/freetdm/src/zt b/libs/freetdm/src/zt
index d23da58c15..9e0f14d57c 100644
--- a/libs/freetdm/src/zt
+++ b/libs/freetdm/src/zt
@@ -1,2 +1,2 @@
-CFLAGS +=-DZAP_ZT_SUPPORT
+MOD_CFLAGS +=-DZAP_ZT_SUPPORT
 OBJS += zap_zt.o