Index: include/libroardsp/dtmf.h
===================================================================
--- include/libroardsp/dtmf.h	(revision 5546)
+++ include/libroardsp/dtmf.h	(revision 5547)
@@ -41,4 +41,11 @@
 #define ROAR_DTMF_OPTIONS_NONE 0
 
+#define ROAR_DTMF_CHAR_DTMF(x) (((x) & 0xFF) + 0x0000)
+#define ROAR_DTMF_CHAR_ROAR(x) (((x) & 0xFF) + 0x0100)
+#define ROAR_DTMF_CHAR_BYTE(x) (((x) & 0xFF) + 0x0200)
+
+#define ROAR_DTMF_CHAR_NOOP    ROAR_DTMF_CHAR_ROAR(0)
+#define ROAR_DTMF_CHAR_ESCAPE  ROAR_DTMF_CHAR_ROAR(27)
+
 ssize_t roar_dtmf_mus2samples(const int_least32_t t, const uint32_t rate);
 
Index: libroardsp/dtmf.c
===================================================================
--- libroardsp/dtmf.c	(revision 5546)
+++ libroardsp/dtmf.c	(revision 5547)
@@ -53,4 +53,28 @@
  return 0;
 }
+
+#define _FQL0 697
+#define _FQL1 770
+#define _FQL2 852
+#define _FQL3 941
+#define _FQH0 1209
+#define _FQH1 1336
+#define _FQH2 1477
+#define _FQH3 1633
+
+#define _FRL0 571
+#define _FRL1 631
+#define _FRL2 _FQL0
+#define _FRL3 _FQL1
+#define _FRL4 _FQL2
+#define _FRL5 _FQL3
+#define _FRL6 1040
+#define _FRH0 _FQH0
+#define _FRH1 _FQH1
+#define _FRH2 _FQH2
+#define _FRH3 _FQH3
+#define _FRH4 1805
+#define _FRH5 1995
+#define _FRH6 2205
 
 static const struct tone {
@@ -59,23 +83,75 @@
  const float f1;
 } _roardsp_tones[] = {
- {'1', 697, 1209},
- {'2', 697, 1336},
- {'3', 697, 1477},
- {'A', 697, 1633},
-
- {'4', 770, 1209},
- {'5', 770, 1336},
- {'6', 770, 1477},
- {'B', 770, 1633},
-
- {'7', 852, 1209},
- {'8', 852, 1336},
- {'9', 852, 1477},
- {'C', 852, 1633},
-
- {'*', 941, 1209},
- {'0', 941, 1336},
- {'#', 941, 1477},
- {'D', 941, 1633},
+ {ROAR_DTMF_CHAR_DTMF('1'), _FQL0, _FQH0},
+ {ROAR_DTMF_CHAR_DTMF('2'), _FQL0, _FQH1},
+ {ROAR_DTMF_CHAR_DTMF('3'), _FQL0, _FQH2},
+ {ROAR_DTMF_CHAR_DTMF('A'), _FQL0, _FQH3},
+
+ {ROAR_DTMF_CHAR_DTMF('4'), _FQL1, _FQH0},
+ {ROAR_DTMF_CHAR_DTMF('5'), _FQL1, _FQH1},
+ {ROAR_DTMF_CHAR_DTMF('6'), _FQL1, _FQH2},
+ {ROAR_DTMF_CHAR_DTMF('B'), _FQL1, _FQH3},
+
+ {ROAR_DTMF_CHAR_DTMF('7'), _FQL2, _FQH0},
+ {ROAR_DTMF_CHAR_DTMF('8'), _FQL2, _FQH1},
+ {ROAR_DTMF_CHAR_DTMF('9'), _FQL2, _FQH2},
+ {ROAR_DTMF_CHAR_DTMF('C'), _FQL2, _FQH3},
+
+ {ROAR_DTMF_CHAR_DTMF('*'), _FQL3, _FQH0},
+ {ROAR_DTMF_CHAR_DTMF('0'), _FQL3, _FQH1},
+ {ROAR_DTMF_CHAR_DTMF('#'), _FQL3, _FQH2},
+ {ROAR_DTMF_CHAR_DTMF('D'), _FQL3, _FQH3},
+
+
+ {ROAR_DTMF_CHAR_NOOP,   _FRL0, _FRH0},
+ {ROAR_DTMF_CHAR_ESCAPE, _FRL0, _FRH1},
+
+ {ROAR_DTMF_CHAR_ROAR('"'), _FRL0, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR(' '), _FRL0, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('F'), _FRL0, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('M'), _FRL0, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('T'), _FRL0, _FRH6},
+ {ROAR_DTMF_CHAR_ROAR('.'), _FRL1, _FRH0},
+ {ROAR_DTMF_CHAR_ROAR('?'), _FRL1, _FRH1},
+ {ROAR_DTMF_CHAR_ROAR('!'), _FRL1, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR(','), _FRL1, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('G'), _FRL1, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('N'), _FRL1, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('U'), _FRL1, _FRH6},
+ {ROAR_DTMF_CHAR_ROAR('1'), _FRL2, _FRH0},
+ {ROAR_DTMF_CHAR_ROAR('2'), _FRL2, _FRH1},
+ {ROAR_DTMF_CHAR_ROAR('3'), _FRL2, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR('A'), _FRL2, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('H'), _FRL2, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('O'), _FRL2, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('V'), _FRL2, _FRH6},
+ {ROAR_DTMF_CHAR_ROAR('4'), _FRL3, _FRH0},
+ {ROAR_DTMF_CHAR_ROAR('5'), _FRL3, _FRH1},
+ {ROAR_DTMF_CHAR_ROAR('6'), _FRL3, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR('B'), _FRL3, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('I'), _FRL3, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('P'), _FRL3, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('W'), _FRL3, _FRH6},
+ {ROAR_DTMF_CHAR_ROAR('7'), _FRL4, _FRH0},
+ {ROAR_DTMF_CHAR_ROAR('8'), _FRL4, _FRH1},
+ {ROAR_DTMF_CHAR_ROAR('9'), _FRL4, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR('C'), _FRL4, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('J'), _FRL4, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('Q'), _FRL4, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('X'), _FRL4, _FRH6},
+ {ROAR_DTMF_CHAR_ROAR('*'), _FRL5, _FRH0},
+ {ROAR_DTMF_CHAR_ROAR('0'), _FRL5, _FRH1},
+ {ROAR_DTMF_CHAR_ROAR('#'), _FRL5, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR('D'), _FRL5, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('K'), _FRL5, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('R'), _FRL5, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('Y'), _FRL5, _FRH6},
+ {ROAR_DTMF_CHAR_ROAR('@'), _FRL6, _FRH0},
+ {ROAR_DTMF_CHAR_ROAR('+'), _FRL6, _FRH1},
+ {ROAR_DTMF_CHAR_ROAR('-'), _FRL6, _FRH2},
+ {ROAR_DTMF_CHAR_ROAR('E'), _FRL6, _FRH3},
+ {ROAR_DTMF_CHAR_ROAR('L'), _FRL6, _FRH4},
+ {ROAR_DTMF_CHAR_ROAR('S'), _FRL6, _FRH5},
+ {ROAR_DTMF_CHAR_ROAR('Z'), _FRL6, _FRH6},
 
  {0, -1, -1}
Index: roarclients/roardtmf.c
===================================================================
--- roarclients/roardtmf.c	(revision 5546)
+++ roarclients/roardtmf.c	(revision 5547)
@@ -48,4 +48,6 @@
         "  --rate  -R RATE    - Set sample rate\n"
         "  --help             - Show this help\n"
+        "  --mode-dtmf        - Use standard DTMF (default)\n"
+        "  --mode-roar        - Use RoarAudio extended DTMF\n"
        );
 
@@ -53,4 +55,8 @@
 
 int main (int argc, char * argv[]) {
+ enum {
+  MODE_DTMF,
+  MODE_ROAR
+ } mode = MODE_DTMF;
  int    rate     = ROAR_RATE_DEFAULT;
  const char * server   = NULL;
@@ -65,5 +71,5 @@
  size_t samples;
  size_t len;
- char   c;
+ uint16_t c;
  int err;
 
@@ -75,4 +81,8 @@
   } else if ( !strcmp(k, "--rate") || !strcmp(k, "-r") || !strcmp(k, "-R") ) {
    rate = roar_str2rate(argv[++i]);
+  } else if ( !strcmp(k, "--mode-dtmf") ) {
+   mode = MODE_DTMF;
+  } else if ( !strcmp(k, "--mode-roar") ) {
+   mode = MODE_ROAR;
   } else if ( !strcmp(k, "--help") ) {
    usage();
@@ -95,6 +105,6 @@
  samples = len_break + len_tone;
 
+/*
  printf("samples=%llu\n", (long long unsigned int)samples);
-/*
  return 0;
 */
@@ -112,8 +122,12 @@
   tones++;
 
-  if ( c == '+' || c == '.' || c == '_' )
-   continue;
+  if ( mode == MODE_DTMF ) {
+   if ( c == '+' || c == '.' || c == '_' )
+    continue;
+  } else if ( mode == MODE_ROAR ) {
+   c = ROAR_DTMF_CHAR_ROAR(c);
+  }
 
-  if ( c == ' ' ) {
+  if ( mode == MODE_DTMF && c == ' ' ) {
    roar_dtmf_break(buf, len_tone, rate, ROAR_DTMF_OPTIONS_NONE);
   } else {
