Remove dtmf2num - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 3f4572631842f38da7c8020f2632b3238b6ae055
(DIR) parent edcebe28cb22ff7f9e7091638c88bd7c5ea4df84
(HTM) Author: HD Moore <hd_moore@rapid7.com>
Date: Wed, 26 Dec 2012 23:15:36 -0600
Remove dtmf2num
Diffstat:
M Gemfile.lock | 17 +++++++----------
M Makefile | 9 +--------
M app/views/analyze/view.html.erb | 6 ------
M app/views/analyze/view_matches.htm… | 36 +++++++++++---------------------
M bin/verify_install.rb | 7 -------
M config/warvox.conf | 5 ++---
M db/schema.rb | 2 --
M docs/ChangeLog | 1 +
M lib/warvox/jobs/analysis.rb | 22 ----------------------
D src/dtmf2num/Makefile | 16 ----------------
D src/dtmf2num/README | 5 -----
D src/dtmf2num/dsp.c | 502 -------------------------------
D src/dtmf2num/dtmf2num.c | 372 -------------------------------
D src/dtmf2num/mywav.h | 244 -------------------------------
D src/dtmf2num/resample2.c | 342 -------------------------------
15 files changed, 23 insertions(+), 1563 deletions(-)
---
(DIR) diff --git a/Gemfile.lock b/Gemfile.lock
@@ -37,13 +37,10 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.4.0)
- delayed_job (3.0.4)
- activesupport (~> 3.0)
- delayed_job_active_record (0.3.3)
- activerecord (>= 2.1.0, < 4)
- delayed_job (~> 3.0)
+ daemons (1.1.9)
dynamic_form (1.1.4)
erubis (2.7.0)
+ eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
hike (1.2.1)
@@ -88,7 +85,6 @@ GEM
rake (10.0.3)
rdoc (3.12)
json (~> 1.4)
- ref (1.0.2)
sass (3.2.4)
sass-rails (3.2.5)
railties (~> 3.2.0)
@@ -98,8 +94,10 @@ GEM
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
- therubyracer (0.11.0)
- ref
+ thin (1.5.0)
+ daemons (>= 1.0.9)
+ eventmachine (>= 0.12.6)
+ rack (>= 1.0.0)
thor (0.16.0)
tilt (1.3.3)
treetop (1.4.12)
@@ -116,7 +114,6 @@ PLATFORMS
DEPENDENCIES
coffee-rails (~> 3.2.1)
- delayed_job_active_record
dynamic_form
jquery-rails
kissfft
@@ -124,6 +121,6 @@ DEPENDENCIES
pg (= 0.11)
rails (= 3.2.8)
sass-rails (~> 3.2.3)
- therubyracer
+ thin
uglifier (>= 1.0.3)
will_paginate (~> 3.0)
(DIR) diff --git a/Makefile b/Makefile
@@ -3,11 +3,7 @@ all: test
test: install
bin/verify_install.rb
-install: bundler dtmf2num
- cp -a src/dtmf2num/dtmf2num bin/
-
-dtmf2num:
- make -C src/dtmf2num/
+install: bundler
db:
@echo "Checking the database.."
@@ -22,6 +18,3 @@ bundler:
@echo "Installing missing gems as needed.."
bundle install
-
-clean:
- make -C src/dtmf2num/ clean
(DIR) diff --git a/app/views/analyze/view.html.erb b/app/views/analyze/view.html.erb
@@ -38,12 +38,6 @@
Provider: <%=h dial_result.provider.name %><br/>
Audio: <%=h dial_result.seconds %> Seconds<br/>
Ringer: <%=h dial_result.ringtime %> Seconds<br/>
- <% if(dial_result.dtmf and dial_result.dtmf.length > 0) %>
- DTMF: <%=h dial_result.dtmf %><br/>
- <% end %>
- <% if(dial_result.mf and dial_result.mf.length > 0) %>
- MF: <%=h dial_result.mf %><br/>
- <% end %>
</td>
<td align='center'>
<b><%=h dial_result.line_type.upcase %></b><br/>
(DIR) diff --git a/app/views/analyze/view_matches.html.erb b/app/views/analyze/view_matches.html.erb
@@ -10,10 +10,10 @@
<tr>
<td align='center'>
-
+
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
+ data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
width="20"
height="17"
style="margin-bottom: -5px;"
@@ -21,31 +21,25 @@
<param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"></param>
<param name="wmode" value="transparent"></param>
</object>
-
+
<b><%= dial_result.number %></b>
<hr width='100%' size='1'/>
CallerID: <%= dial_result.cid%><br/>
Provider: <%=h dial_result.provider.name %><br/>
Audio: <%=h dial_result.seconds %> Seconds<br/>
Ringer: <%=h dial_result.ringtime %> Seconds<br/>
- <% if(dial_result.dtmf and dial_result.dtmf.length > 0) %>
- DTMF: <%=h dial_result.dtmf %><br/>
- <% end %>
- <% if(dial_result.mf and dial_result.mf.length > 0) %>
- MF: <%=h dial_result.mf %><br/>
- <% end %>
</td>
<td align='center'>
<b><%=h dial_result.line_type.upcase %></b><br/>
<a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_sig_dots")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_sig")%>" /></a>
<a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_freq")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_freq")%>" /></a><br/>
- <% (dial_result.signatures||"").split("\n").each do |s|
+ <% (dial_result.signatures||"").split("\n").each do |s|
sid,mat,name = s.split(':', 3)
str = [mat.to_i * 6.4, 255].min
col = ("%.2x" % (255 - str)) * 3
%>
<div style="color: #<%= col%>;"><%=h name%> (<%=h sid %>@<%=h mat %>)</div>
- <% end %>
+ <% end %>
</td>
</tr>
</table><br/><br/>
@@ -61,12 +55,12 @@
<% @results.each do |dial_result| %>
<tr>
<td align='center'>
-
+
<br/><%= raw(fwd_match_html(dial_result.matchscore)) %><br/><br/>
-
+
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
+ data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
width="20"
height="17"
style="margin-bottom: -5px;"
@@ -74,34 +68,28 @@
<param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"></param>
<param name="wmode" value="transparent"></param>
</object>
-
+
<b><%= dial_result.number %></b>
<hr width='100%' size='1'/>
CallerID: <%= dial_result.cid%><br/>
Provider: <%=h dial_result.provider.name %><br/>
Audio: <%=h dial_result.seconds %> Seconds<br/>
Ringer: <%=h dial_result.ringtime %> Seconds<br/>
- <% if(dial_result.dtmf and dial_result.dtmf.length > 0) %>
- DTMF: <%=h dial_result.dtmf %><br/>
- <% end %>
- <% if(dial_result.mf and dial_result.mf.length > 0) %>
- MF: <%=h dial_result.mf %><br/>
- <% end %>
</td>
<td align='center'>
<b><%=h dial_result.line_type.upcase %></b><br/>
<a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_sig_dots")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_sig")%>" /></a>
<a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_freq")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_freq")%>" /></a><br/>
- <% (dial_result.signatures||"").split("\n").each do |s|
+ <% (dial_result.signatures||"").split("\n").each do |s|
sid,mat,name = s.split(':', 3)
str = [mat.to_i * 6.4, 255].min
col = ("%.2x" % (255 - str)) * 3
%>
<div style="color: #<%= col%>;"><%=h name%> (<%=h sid %>@<%=h mat %>)</div>
- <% end %>
+ <% end %>
<% if dial_result.fprint %>
<a href="<%=view_matches_path(dial_result.id)%>">View Matches</a>
- <% end %>
+ <% end %>
</td>
</tr>
<% end %>
(DIR) diff --git a/bin/verify_install.rb b/bin/verify_install.rb
@@ -56,13 +56,6 @@ end
puts "[*] The LAME binary appears to be available"
-if(not WarVOX::Config.tool_path('dtmf2num'))
- puts "[*] ERROR: The 'dtmf2num' binary could not be installed"
- exit
-end
-puts "[*] The DTMF2NUM binary appears to be available"
-
-
puts " "
puts "[*] Congratulations! You are almost ready to run WarVOX"
puts " "
(DIR) diff --git a/config/warvox.conf b/config/warvox.conf
@@ -24,7 +24,6 @@ tools:
gnuplot: gnuplot
lame: lame
iaxrecord: "%BASE%/bin/iaxrecord.rb"
- dtmf2num: "%BASE%/bin/dtmf2num"
#
# Concurrent processing jobs, change this to
@@ -37,9 +36,9 @@ analysis_threads: 2
#
# Configure the dial blacklist location
#
-blacklist: "%BASE%/etc/blacklist.txt"
+blacklist: "%BASE%/config/blacklist.txt"
#
# Configure the signature directory
#
-signatures: "%BASE%/etc/sigs"
+signatures: "%BASE%/config/sigs"
(DIR) diff --git a/db/schema.rb b/db/schema.rb
@@ -50,8 +50,6 @@ ActiveRecord::Schema.define(:version => 20110801000003) do
t.text "line_type"
t.text "notes"
t.text "signatures"
- t.text "dtmf"
- t.text "mf"
t.string "fprint", :limit => nil
t.binary "audio"
t.binary "mp3"
(DIR) diff --git a/docs/ChangeLog b/docs/ChangeLog
@@ -1,6 +1,7 @@
2012-12-26 HD Moore <hdm[at]rapid7.com>
* overhauled, updated gems, merged directories with web
* swapped in Rapid7-licensed Highcharts for graphics
+ * remove dtmf2num (limited value, too inaccurate)
2011-02-23 HD Moore <hdm[at]rapid7.com>
* bumped the version number to 1.2.0
(DIR) diff --git a/lib/warvox/jobs/analysis.rb b/lib/warvox/jobs/analysis.rb
@@ -323,27 +323,6 @@ class Analysis < Base
[png_big, png_big_dots, png_big_freq, png_sig, png_sig_freq ].map {|x| x.unlink; x.close }
-
- # Detect DTMF and MF tones
- dtmf = ''
- mf = ''
- pfd = IO.popen("#{WarVOX::Config.tool_path('dtmf2num')} -r 8000 1 16 #{rawfile.path} 2>/dev/null")
- pfd.each_line do |line|
- line = line.strip
- if(line.strip =~ /^- MF numbers:\s+(.*)/)
- next if $1 == 'none'
- mf = $1
- end
- if(line.strip =~ /^- DTMF numbers:\s+(.*)/)
- next if $1 == 'none'
- dtmf = $1
- end
- end
- pfd.close
- res[:dtmf] = dtmf
- res[:mf] = mf
-
-
tmp_wav = Tempfile.new("wav")
tmp_mp3 = Tempfile.new("mp3")
@@ -418,4 +397,3 @@ end
end
end
-
(DIR) diff --git a/src/dtmf2num/Makefile b/src/dtmf2num/Makefile
@@ -1,16 +0,0 @@
-EXE = dtmf2num
-CFLAGS += -O2 -s
-BINDIR = $(PREFIX)/bin
-LIBS = -lm
-
-all:
- $(CC) $(CFLAGS) -c dtmf2num.c
- $(CC) $(CFLAGS) -c dsp.c
- $(CC) $(CFLAGS) -c resample2.c
- $(CC) $(CFLAGS) -o $(EXE) dtmf2num.o dsp.o resample2.o $(LIBS)
-
-clean:
- @rm -f *.o $(EXE)
-
-.PHONY:
- install
(DIR) diff --git a/src/dtmf2num/README b/src/dtmf2num/README
@@ -1,5 +0,0 @@
-This is a barely tweaked copy of DTMF2NUM, developed by Luigi Auriemma
- - http://aluigi.org/mytoolz.htm#dtmf2num
-
-This tool is provided under the GPL:
- - http://www.gnu.org/licenses/gpl.txt
(DIR) diff --git a/src/dtmf2num/dsp.c b/src/dtmf2num/dsp.c
@@ -1,502 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
- * DTMF detector.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Convenience Signal Processing routines
- *
- * \author Mark Spencer <markster@digium.com>
- * \author Steve Underwood <steveu@coppice.org>
- */
-
-/* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
-/*
- 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.
-*/
-
-/*
- modifications for decoding also damaged audio by Luigi auriemma "// aluigi work-around"
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <malloc.h>
-
-#define DSP_DIGITMODE_DTMF 0 /*!< Detect DTMF digits */
-#define DSP_DIGITMODE_MF 1 /*!< Detect MF digits */
-
-#define DSP_DIGITMODE_NOQUELCH (1 << 8) /*!< Do not quelch DTMF from in-band */
-#define DSP_DIGITMODE_RELAXDTMF (1 << 11) /*!< "Radio" mode (relaxed DTMF) */
-
-#define MAX_DTMF_DIGITS 1024
-
-/* 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_THRESHOLD 800000000.0 // aluigi work-around
-#define DTMF_NORMAL_TWIST 6.3 /* 8dB */
-#ifdef RADIO_RELAX
-#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5) /* 4dB normal */
-#else
-#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */
-#endif
-#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
-#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
-#define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */
-#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
-#define DTMF_TO_TOTAL_ENERGY 42.0
-
-//#define BELL_MF_THRESHOLD 1.6e9
-#define BELL_MF_THRESHOLD DTMF_THRESHOLD // aluigi work-around
-#define BELL_MF_TWIST 4.0 /* 6dB */
-#define BELL_MF_RELATIVE_PEAK 12.6 /* 11dB */
-
-static int SAMPLE_RATE = 8000;
-
-typedef struct {
- int v2;
- int v3;
- int chunky;
- int fac;
- int samples;
-} goertzel_state_t;
-
-typedef struct {
- int value;
- int power;
-} goertzel_result_t;
-
-typedef struct
-{
- goertzel_state_t row_out[4];
- goertzel_state_t col_out[4];
- int lasthit;
- int current_hit;
- float energy;
- int current_sample;
-} dtmf_detect_state_t;
-
-typedef struct
-{
- goertzel_state_t tone_out[6];
- int current_hit;
- int hits[5];
- int current_sample;
-} mf_detect_state_t;
-
-typedef struct
-{
- char digits[MAX_DTMF_DIGITS + 1];
- int current_digits;
- int detected_digits;
- int lost_digits;
-
- union {
- dtmf_detect_state_t dtmf;
- mf_detect_state_t mf;
- } td;
-} digit_detect_state_t;
-
-static float dtmf_row[] =
-{
- 697.0, 770.0, 852.0, 941.0
-};
-static float dtmf_col[] =
-{
- 1209.0, 1336.0, 1477.0, 1633.0
-};
-
-static float mf_tones[] =
-{
- 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
-};
-
-static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
-
-static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
-
-static inline void goertzel_sample(goertzel_state_t *s, short sample)
-{
- int v1;
-
- v1 = s->v2;
- s->v2 = s->v3;
-
- s->v3 = (s->fac * s->v2) >> 15;
- s->v3 = s->v3 - v1 + (sample >> s->chunky);
- if (abs(s->v3) > 32768) {
- s->chunky++;
- s->v3 = s->v3 >> 1;
- s->v2 = s->v2 >> 1;
- v1 = v1 >> 1;
- }
-}
-
-static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
-{
- int i;
-
- for (i=0;i<count;i++)
- goertzel_sample(s, samps[i]);
-}
-
-static inline float goertzel_result(goertzel_state_t *s)
-{
- goertzel_result_t r;
- r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
- r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
- r.power = s->chunky * 2;
- return (float)r.value * (float)(1 << r.power);
-}
-
-static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
-{
- s->v2 = s->v3 = s->chunky = 0.0;
- s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
- s->samples = samples;
-}
-
-static inline void goertzel_reset(goertzel_state_t *s)
-{
- s->v2 = s->v3 = s->chunky = 0.0;
-}
-
-static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
-{
- int i;
-
- s->lasthit = 0;
- s->current_hit = 0;
- for (i = 0; i < 4; i++) {
- goertzel_init (&s->row_out[i], dtmf_row[i], 102);
- goertzel_init (&s->col_out[i], dtmf_col[i], 102);
- s->energy = 0.0;
- }
- s->current_sample = 0;
-}
-
-static void ast_mf_detect_init (mf_detect_state_t *s)
-{
- int i;
- s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
- for (i = 0; i < 6; i++) {
- goertzel_init (&s->tone_out[i], mf_tones[i], 160);
- }
- s->current_sample = 0;
- s->current_hit = 0;
-}
-
-static void ast_digit_detect_init(digit_detect_state_t *s, int mf)
-{
- s->current_digits = 0;
- s->detected_digits = 0;
- s->lost_digits = 0;
- s->digits[0] = '\0';
-
- if (mf)
- ast_mf_detect_init(&s->td.mf);
- else
- ast_dtmf_detect_init(&s->td.dtmf);
-}
-
-static void store_digit(digit_detect_state_t *s, char digit)
-{
- s->detected_digits++;
- if (s->current_digits < MAX_DTMF_DIGITS) {
- s->digits[s->current_digits++] = digit;
- s->digits[s->current_digits] = '\0';
- } else {
- //ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
- s->lost_digits++;
- }
-}
-
-static int dtmf_detect(digit_detect_state_t *s, int16_t amp[], int samples,
- int digitmode, int *writeback)
-{
- float row_energy[4];
- float col_energy[4];
- float famp;
- int i;
- int j;
- int sample;
- int best_row;
- int best_col;
- int hit;
- int limit;
-
- hit = 0;
- for (sample = 0; sample < samples; sample = limit) {
- /* 102 is optimised to meet the DTMF specs. */
- if ((samples - sample) >= (102 - s->td.dtmf.current_sample))
- limit = sample + (102 - s->td.dtmf.current_sample);
- else
- limit = samples;
- /* The following unrolled loop takes only 35% (rough estimate) of the
- time of a rolled loop on the machine on which it was developed */
- for (j = sample; j < limit; j++) {
- famp = amp[j];
- s->td.dtmf.energy += famp*famp;
- /* With GCC 2.95, the following unrolled code seems to take about 35%
- (rough estimate) as long as a neat little 0-3 loop */
- goertzel_sample(s->td.dtmf.row_out, amp[j]);
- goertzel_sample(s->td.dtmf.col_out, amp[j]);
- goertzel_sample(s->td.dtmf.row_out + 1, amp[j]);
- goertzel_sample(s->td.dtmf.col_out + 1, amp[j]);
- goertzel_sample(s->td.dtmf.row_out + 2, amp[j]);
- goertzel_sample(s->td.dtmf.col_out + 2, amp[j]);
- goertzel_sample(s->td.dtmf.row_out + 3, amp[j]);
- goertzel_sample(s->td.dtmf.col_out + 3, amp[j]);
- }
- s->td.dtmf.current_sample += (limit - sample);
- if (s->td.dtmf.current_sample < 102) {
- if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
- /* If we had a hit last time, go ahead and clear this out since likely it
- will be another hit */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
- continue;
- }
- /* We are at the end of a DTMF detection block */
- /* Find the peak row and the peak column */
- row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
- col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
-
- for (best_row = best_col = 0, i = 1; i < 4; i++) {
- row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
- if (row_energy[i] > row_energy[best_row])
- best_row = i;
- col_energy[i] = goertzel_result (&s->td.dtmf.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 && // aluigi work-around
- col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
- /* Relative peak test */
- for (i = 0; i < 4; 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 fraction of total energy test */
- if (i >= 4 /*&&
- (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->td.dtmf.energy*/) { // aluigi work-around
- /* Got a hit */
- hit = dtmf_positions[(best_row << 2) + best_col];
- if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
- /* Zero out frame data if this is part DTMF */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
- }
- }
-
- /* The logic in the next test is:
- For digits 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 != s->td.dtmf.current_hit) {
- if (hit && s->td.dtmf.lasthit == hit) {
- s->td.dtmf.current_hit = hit;
- store_digit(s, hit);
- } else if (s->td.dtmf.lasthit != s->td.dtmf.current_hit) {
- s->td.dtmf.current_hit = 0;
- }
- }
- s->td.dtmf.lasthit = hit;
-
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 4; i++) {
- goertzel_reset(&s->td.dtmf.row_out[i]);
- goertzel_reset(&s->td.dtmf.col_out[i]);
- }
- s->td.dtmf.energy = 0.0;
- s->td.dtmf.current_sample = 0;
- }
- return (s->td.dtmf.current_hit); /* return the debounced hit */
-}
-
-/* MF goertzel size */
-#define MF_GSIZE 120
-
-static int mf_detect(digit_detect_state_t *s, int16_t amp[],
- int samples, int digitmode, int *writeback)
-{
- float energy[6];
- int best;
- int second_best;
- float famp;
- int i;
- int j;
- int sample;
- int hit;
- int limit;
-
- hit = 0;
- for (sample = 0; sample < samples; sample = limit) {
- /* 80 is optimised to meet the MF specs. */
- if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample))
- limit = sample + (MF_GSIZE - s->td.mf.current_sample);
- else
- limit = samples;
- /* The following unrolled loop takes only 35% (rough estimate) of the
- time of a rolled loop on the machine on which it was developed */
- for (j = sample; j < limit; j++) {
- famp = amp[j];
- /* With GCC 2.95, the following unrolled code seems to take about 35%
- (rough estimate) as long as a neat little 0-3 loop */
- goertzel_sample(s->td.mf.tone_out, amp[j]);
- goertzel_sample(s->td.mf.tone_out + 1, amp[j]);
- goertzel_sample(s->td.mf.tone_out + 2, amp[j]);
- goertzel_sample(s->td.mf.tone_out + 3, amp[j]);
- goertzel_sample(s->td.mf.tone_out + 4, amp[j]);
- goertzel_sample(s->td.mf.tone_out + 5, amp[j]);
- }
- s->td.mf.current_sample += (limit - sample);
- if (s->td.mf.current_sample < MF_GSIZE) {
- if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
- /* If we had a hit last time, go ahead and clear this out since likely it
- will be another hit */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
- continue;
- }
- /* We're at the end of an MF detection block. */
- /* Find the two highest energies. The spec says to look for
- two tones and two tones only. Taking this literally -ie
- only two tones pass the minimum threshold - doesn't work
- well. The sinc function mess, due to rectangular windowing
- ensure that! Find the two highest energies and ensure they
- are considerably stronger than any of the others. */
- energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
- energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
- if (energy[0] > energy[1]) {
- best = 0;
- second_best = 1;
- } else {
- best = 1;
- second_best = 0;
- }
- /*endif*/
- for (i=2;i<6;i++) {
- energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
- if (energy[i] >= energy[best]) {
- second_best = best;
- best = i;
- } else if (energy[i] >= energy[second_best]) {
- second_best = i;
- }
- }
- /* Basic signal level and twist tests */
- hit = 0;
- if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
-// && energy[best] < energy[second_best]*BELL_MF_TWIST // aluigi work-around
- && energy[best]*BELL_MF_TWIST > energy[second_best]) {
- /* Relative peak test */
- hit = -1;
- for (i=0;i<6;i++) {
- if (i != best && i != second_best) {
- if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
- /* The best two are not clearly the best */
- hit = 0;
- break;
- }
- }
- }
- }
- if (hit) {
- /* Get the values into ascending order */
- if (second_best < best) {
- i = best;
- best = second_best;
- second_best = i;
- }
- best = best*5 + second_best - 1;
- hit = bell_mf_positions[best];
- /* Look for two successive similar results */
- /* The logic in the next test is:
- For KP we need 4 successive identical clean detects, with
- two blocks of something different preceeding it. For anything
- else we need two successive identical clean detects, with
- two blocks of something different preceeding it. */
- if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
- ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
- (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] &&
- hit != s->td.mf.hits[0]))) {
- store_digit(s, hit);
- }
- }
-
-
- if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
- /* Two successive block without a hit terminate current digit */
- s->td.mf.current_hit = 0;
- }
-
- s->td.mf.hits[0] = s->td.mf.hits[1];
- s->td.mf.hits[1] = s->td.mf.hits[2];
- s->td.mf.hits[2] = s->td.mf.hits[3];
- s->td.mf.hits[3] = s->td.mf.hits[4];
- s->td.mf.hits[4] = hit;
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 6; i++)
- goertzel_reset(&s->td.mf.tone_out[i]);
- s->td.mf.current_sample = 0;
- }
-
- return (s->td.mf.current_hit); /* return the debounced hit */
-}
(DIR) diff --git a/src/dtmf2num/dtmf2num.c b/src/dtmf2num/dtmf2num.c
@@ -1,372 +0,0 @@
-/*
- Copyright 2008 Luigi Auriemma
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- http://www.gnu.org/licenses/gpl.txt
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <sys/stat.h>
-#include "mywav.h"
-#include "dsp.c"
-//#include "resample2.c"
-
-
-
-typedef int8_t i8;
-typedef uint8_t u8;
-typedef int16_t i16;
-typedef uint16_t u16;
-typedef int32_t i32;
-typedef uint32_t u32;
-
-
-
-#define VER "0.1c"
-
-
-
-int mywav_fri24(FILE *fd, uint32_t *num);
-i16 *do_samples(FILE *fd, int wavsize, int *ret_samples, int bits);
-int do_mono(i16 *smp, int samples, int ch);
-void do_dcbias(i16 *smp, int samples);
-void do_normalize(i16 *smp, int samples);
-int do_8000(i16 *smp, int samples, int *freq);
-void my_err(u8 *err);
-void std_err(void);
-
-
-
-int main(int argc, char *argv[]) {
- digit_detect_state_t dtmf;
- mywav_fmtchunk fmt;
- struct stat xstat;
- FILE *fd;
- int i,
- wavsize,
- samples,
- writeback,
- raw = 0,
- optimize = 1;
- i16 *smp;
- u8 *fname,
- *outfile = NULL;
-
- setbuf(stdin, NULL);
- setbuf(stdout, NULL);
-
- fputs("\n"
- "DTMF2NUM "VER"\n"
- "by Luigi Auriemma\n"
- "e-mail: aluigi@autistici.org\n"
- "web: aluigi.org\n"
- "\n", stderr);
-
- if(argc < 2) {
- printf("\n"
- "Usage: %s [options] <file.WAV>\n"
- "\n"
- "Options:\n"
- "-r F C B consider the file as raw headerless PCM data, you must specify the\n"
- " Frequency, Channels and Bits like -r 44100 2 16\n"
- "-o disable the automatic optimizations: DC bias adjust and normalize.\n"
- " use this option only if your file is already clean and normalized\n"
- "-w FILE debug option for dumping the handled samples from the memory to FILE\n"
- "\n", argv[0]);
- exit(1);
- }
-
- argc--;
- for(i = 1; i < argc; i++) {
- if(((argv[i][0] != '-') && (argv[i][0] != '/')) || (strlen(argv[i]) != 2)) {
- printf("\nError: wrong argument (%s)\n", argv[i]);
- exit(1);
- }
- switch(argv[i][1]) {
- case 'r': {
- memset(&fmt, 0, sizeof(fmt));
- if(!argv[++i]) exit(1);
- fmt.dwSamplesPerSec = atoi(argv[i]);
- if(!argv[++i]) exit(1);
- fmt.wChannels = atoi(argv[i]);
- if(!argv[++i]) exit(1);
- fmt.wBitsPerSample = atoi(argv[i]);
- fmt.wFormatTag = 1;
- raw = 1;
- } break;
- case 'o': {
- optimize = 0;
- } break;
- case 'w': {
- if(!argv[++i]) exit(1);
- outfile = argv[i];
- } break;
- default: {
- printf("\nError: wrong option (%s)\n", argv[i]);
- exit(1);
- }
- }
- }
-
- fname = argv[argc];
-
- if(!strcmp(fname, "-")) {
- printf("- open stdin\n");
- fd = stdin;
- } else {
- printf("- open %s\n", fname);
- fd = fopen(fname, "rb");
- if(!fd) std_err();
- }
-
- if(raw) {
- fstat(fileno(fd), &xstat);
- wavsize = xstat.st_size;
- } else {
- wavsize = mywav_data(fd, &fmt);
- }
- fprintf(stderr,
- " wave size %u\n"
- " format tag %hu\n"
- " channels: %hu\n"
- " samples/sec: %u\n"
- " avg/bytes/sec: %u\n"
- " block align: %hu\n"
- " bits: %hu\n",
- wavsize,
- fmt.wFormatTag,
- fmt.wChannels,
- fmt.dwSamplesPerSec,
- fmt.dwAvgBytesPerSec,
- fmt.wBlockAlign,
- fmt.wBitsPerSample);
-
- if(wavsize <= 0) my_err("corrupted WAVE file");
- if(fmt.wFormatTag != 1) my_err("only the classical PCM WAVE files are supported");
-
- smp = do_samples(fd, wavsize, &samples, fmt.wBitsPerSample);
- fprintf(stderr, " samples: %d\n", samples);
- if(fd != stdin) fclose(fd);
-
- samples = do_mono(smp, samples, fmt.wChannels);
- if(optimize) {
- do_dcbias(smp, samples);
- do_normalize(smp, samples);
- }
- samples = do_8000(smp, samples, &fmt.dwSamplesPerSec);
-
- fmt.wFormatTag = 0x0001;
- fmt.wChannels = 1;
- fmt.wBitsPerSample = 16;
- fmt.wBlockAlign = (fmt.wBitsPerSample >> 3) * fmt.wChannels;
- fmt.dwAvgBytesPerSec = fmt.dwSamplesPerSec * fmt.wBlockAlign;
- wavsize = samples * sizeof(* smp);
-
- if(outfile) {
- fprintf(stderr, "- dump %s\n", outfile);
- fd = fopen(outfile, "wb");
- if(!fd) std_err();
- mywav_writehead(fd, &fmt, wavsize, NULL, 0);
- fwrite(smp, 1, wavsize, fd);
- fclose(fd);
- }
-
- SAMPLE_RATE = fmt.dwSamplesPerSec;
-
- ast_digit_detect_init(&dtmf, DSP_DIGITMODE_MF);
- mf_detect(&dtmf, smp, samples, DSP_DIGITMODE_NOQUELCH, &writeback);
- printf("\n- MF numbers: %s\n", dtmf.digits[0] ? dtmf.digits : "none");
-
- ast_digit_detect_init(&dtmf, DSP_DIGITMODE_DTMF);
- dtmf_detect(&dtmf, smp, samples, DSP_DIGITMODE_NOQUELCH, &writeback);
- printf("\n- DTMF numbers: %s\n", dtmf.digits[0] ? dtmf.digits : "none");
-
- return(0);
-}
-
-
-
-int mywav_fri24(FILE *fd, uint32_t *num) {
- uint32_t ret;
- uint8_t tmp;
-
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret = tmp;
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret |= (tmp << 8);
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret |= (tmp << 16);
- *num = ret;
- return(0);
-}
-
-
-
-i16 *do_samples(FILE *fd, int wavsize, int *ret_samples, int bits) {
- i32 tmp32;
- int i = 0,
- samples;
- i16 *smp;
- i8 tmp8;
-
- samples = wavsize / (bits >> 3);
- smp = malloc(sizeof(* smp) * samples);
- if(!smp) std_err();
-
- if(bits == 8) {
- for(i = 0; i < samples; i++) {
- if(mywav_fri08(fd, &tmp8) < 0) break;
- smp[i] = (tmp8 << 8) - 32768;
- }
-
- } else if(bits == 16) {
- for(i = 0; i < samples; i++) {
- if(mywav_fri16(fd, &smp[i]) < 0) break;
- }
-
- } else if(bits == 24) {
- for(i = 0; i < samples; i++) {
- if(mywav_fri24(fd, &tmp32) < 0) break;
- smp[i] = tmp32 >> 8;
- }
-
- } else if(bits == 32) {
- for(i = 0; i < samples; i++) {
- if(mywav_fri32(fd, &tmp32) < 0) break;
- smp[i] = tmp32 >> 16;
- }
-
- } else {
- my_err("number of bits used in the WAVE file not supported");
- }
- *ret_samples = i;
- return(smp);
-}
-
-
-
-int do_mono(i16 *smp, int samples, int ch) {
- i32 tmp; // max 65535 channels
- int i,
- j;
-
- if(!ch) my_err("the WAVE file doesn't have channels");
- if(ch == 1) return(samples);
-
- for(i = 0; samples > 0; i++) {
- tmp = 0;
- for(j = 0; j < ch; j++) {
- tmp += smp[(i * ch) + j];
- }
- smp[i] = tmp / ch;
- samples -= ch;
- }
- return(i);
-}
-
-
-
-void do_dcbias(i16 *smp, int samples) {
- int i;
- i16 bias,
- maxneg,
- maxpos;
-
- maxneg = 32767;
- maxpos = -32768;
- for(i = 0; i < samples; i++) {
- if(smp[i] < maxneg) {
- maxneg = smp[i];
- } else if(smp[i] > maxpos) {
- maxpos = smp[i];
- }
- }
-
- bias = (maxneg + maxpos) / 2;
- fprintf(stderr, " bias adjust: %d\n", bias);
-
- for(i = 0; i < samples; i++) {
- smp[i] -= bias;
- }
-}
-
-
-
-void do_normalize(i16 *smp, int samples) {
- int i;
- i16 bias,
- maxneg,
- maxpos;
-
- maxneg = 0;
- maxpos = 0;
- for(i = 0; i < samples; i++) {
- if(smp[i] < maxneg) {
- maxneg = smp[i];
- } else if(smp[i] > maxpos) {
- maxpos = smp[i];
- }
- }
-
- fprintf(stderr, " volume peaks: %d %d\n", maxneg, maxpos);
-
- if(maxneg < 0) maxneg = (-maxneg) - 1;
- if(maxneg > maxpos) {
- bias = maxneg;
- } else {
- bias = maxpos;
- }
- if(bias == 32767) return;
-
- fprintf(stderr, " normalize: %d\n", 32767 - bias);
-
- for(i = 0; i < samples; i++) {
- smp[i] = (smp[i] * 32767) / bias;
- }
-}
-
-
-
-int do_8000(i16 *smp, int samples, int *freq) {
- void *res;
- int consumed;
-
- if(*freq <= 8000) return(samples);
-
- fprintf(stderr, " resampling to: 8000hz\n");
- res = av_resample_init(8000, *freq, 16, 10, 0, 0.8);
- samples = av_resample(res, smp, smp, &consumed, samples, samples, 1);
- av_resample_close(res);
-
- *freq = 8000;
- return(samples);
-}
-
-
-
-void my_err(u8 *err) {
- fprintf(stderr, "\nError: %s\n", err);
- exit(1);
-}
-
-
-
-void std_err(void) {
- perror("\nError");
- exit(1);
-}
-
-
(DIR) diff --git a/src/dtmf2num/mywav.h b/src/dtmf2num/mywav.h
@@ -1,244 +0,0 @@
-/*
- MyWAV 0.1.1
- by Luigi Auriemma
- e-mail: aluigi@autistici.org
- web: aluigi.org
-
- Copyright 2005,2006 Luigi Auriemma
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- http://www.gnu.org/licenses/gpl.txt
-*/
-
-#include <string.h>
-#include <stdint.h>
-
-
-
-/*
-the functions return ever 0 if success, other values (-1) if error
-note that these functions have been written with compatibility in mind
-so don't worry if you see useless instructions
-*/
-
-
-
-typedef struct {
- uint8_t id[4];
- uint32_t size;
-} mywav_chunk;
-
-typedef struct {
- int16_t wFormatTag;
- uint16_t wChannels;
- uint32_t dwSamplesPerSec;
- uint32_t dwAvgBytesPerSec;
- uint16_t wBlockAlign;
- uint16_t wBitsPerSample;
-} mywav_fmtchunk;
-
-
-
- /* FILE WRITING */
-
- // 8 bit
-int mywav_fwi08(FILE *fd, int num) {
- if(fputc((num ) & 0xff, fd) < 0) return(-1);
- return(0);
-}
-
-
-
- // 16 bit
-int mywav_fwi16(FILE *fd, int num) {
- if(fputc((num ) & 0xff, fd) < 0) return(-1);
- if(fputc((num >> 8) & 0xff, fd) < 0) return(-1);
- return(0);
-}
-
-
-
- // 32 bit
-int mywav_fwi32(FILE *fd, int num) {
- if(fputc((num ) & 0xff, fd) < 0) return(-1);
- if(fputc((num >> 8) & 0xff, fd) < 0) return(-1);
- if(fputc((num >> 16) & 0xff, fd) < 0) return(-1);
- if(fputc((num >> 24) & 0xff, fd) < 0) return(-1);
- return(0);
-}
-
-
-
- // data
-int mywav_fwmem(FILE *fd, uint8_t *mem, int size) {
- if(size) {
- if(fwrite(mem, size, 1, fd) != 1) return(-1);
- }
- return(0);
-}
-
-
-
- // chunk
-int mywav_fwchunk(FILE *fd, mywav_chunk *chunk) {
- if(mywav_fwmem(fd, chunk->id, 4)) return(-1);
- if(mywav_fwi32(fd, chunk->size)) return(-1);
- return(0);
-}
-
-
-
- // fmtchunk
-int mywav_fwfmtchunk(FILE *fd, mywav_fmtchunk *fmtchunk) {
- if(mywav_fwi16(fd, fmtchunk->wFormatTag)) return(-1);
- if(mywav_fwi16(fd, fmtchunk->wChannels)) return(-1);
- if(mywav_fwi32(fd, fmtchunk->dwSamplesPerSec)) return(-1);
- if(mywav_fwi32(fd, fmtchunk->dwAvgBytesPerSec)) return(-1);
- if(mywav_fwi16(fd, fmtchunk->wBlockAlign)) return(-1);
- if(mywav_fwi16(fd, fmtchunk->wBitsPerSample)) return(-1);
- return(0);
-}
-
-
-
- /* FILE READING */
-
- // 8 bit
-int mywav_fri08(FILE *fd, uint8_t *num) {
- if(fread(num, 1, 1, fd) != 1) return(-1);
- return(0);
-}
-
-
-
- // 16 bit
-int mywav_fri16(FILE *fd, uint16_t *num) {
- uint16_t ret;
- uint8_t tmp;
-
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret = tmp;
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret |= (tmp << 8);
- *num = ret;
- return(0);
-}
-
-
-
- // 32 bit
-int mywav_fri32(FILE *fd, uint32_t *num) {
- uint32_t ret;
- uint8_t tmp;
-
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret = tmp;
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret |= (tmp << 8);
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret |= (tmp << 16);
- if(fread(&tmp, 1, 1, fd) != 1) return(-1); ret |= (tmp << 24);
- *num = ret;
- return(0);
-}
-
-
-
- // data
-int mywav_frmem(FILE *fd, uint8_t *mem, int size) {
- if(size) {
- if(fread(mem, size, 1, fd) != 1) return(-1);
- }
- return(0);
-}
-
-
-
- // chunk
-int mywav_frchunk(FILE *fd, mywav_chunk *chunk) {
- if(mywav_frmem(fd, (void *)&chunk->id, 4)) return(-1);
- if(mywav_fri32(fd, (void *)&chunk->size)) return(-1);
- return(0);
-}
-
-
-
- // fmtchunk
-int mywav_frfmtchunk(FILE *fd, mywav_fmtchunk *fmtchunk) {
- if(mywav_fri16(fd, (void *)&fmtchunk->wFormatTag)) return(-1);
- if(mywav_fri16(fd, (void *)&fmtchunk->wChannels)) return(-1);
- if(mywav_fri32(fd, (void *)&fmtchunk->dwSamplesPerSec)) return(-1);
- if(mywav_fri32(fd, (void *)&fmtchunk->dwAvgBytesPerSec)) return(-1);
- if(mywav_fri16(fd, (void *)&fmtchunk->wBlockAlign)) return(-1);
- if(mywav_fri16(fd, (void *)&fmtchunk->wBitsPerSample)) return(-1);
- return(0);
-}
-
-
- /* MYWAV MAIN FUNCTIONS */
-
-int mywav_seekchunk(FILE *fd, uint8_t *find) {
- mywav_chunk chunk;
-
- if(fseek(fd, sizeof(mywav_chunk) + 4, SEEK_SET) < 0) return(-1);
-
- while(!mywav_frchunk(fd, &chunk)) {
- if(!memcmp(chunk.id, find, 4)) return(chunk.size);
- if(fseek(fd, chunk.size, SEEK_CUR) < 0) break;
- }
- return(-1);
-}
-
-
-
-int mywav_data(FILE *fd, mywav_fmtchunk *fmt) {
- mywav_chunk chunk;
- uint8_t type[4];
-
- if(mywav_frchunk(fd, &chunk) < 0) return(-1);
- if(mywav_frmem(fd, type, 4) < 0) return(-1);
- if(memcmp(type, "WAVE", 4)) return(-1);
-
- if(mywav_seekchunk(fd, "fmt ") < 0) return(-1);
- if(mywav_frfmtchunk(fd, fmt) < 0) return(-1);
-
- return(mywav_seekchunk(fd, "data"));
-}
-
-
-
-int mywav_writehead(FILE *fd, mywav_fmtchunk *fmt, uint32_t data_size, uint8_t *more, int morelen) {
- mywav_chunk chunk;
-
- memcpy(chunk.id, "RIFF", 4);
- chunk.size =
- 4 +
- sizeof(mywav_chunk) +
- sizeof(mywav_fmtchunk) +
- morelen +
- sizeof(mywav_chunk) +
- data_size;
-
- if(mywav_fwchunk(fd, &chunk) < 0) return(-1);
- if(mywav_fwmem(fd, "WAVE", 4) < 0) return(-1);
-
- memcpy(chunk.id, "fmt ", 4);
- chunk.size = sizeof(mywav_fmtchunk) + morelen;
- if(mywav_fwchunk(fd, &chunk) < 0) return(-1);
- if(mywav_fwfmtchunk(fd, fmt) < 0) return(-1);
- if(mywav_fwmem(fd, more, morelen) < 0) return(-1);
-
- memcpy(chunk.id, "data", 4);
- chunk.size = data_size;
- if(mywav_fwchunk(fd, &chunk) < 0) return(-1);
- return(0);
-}
-
(DIR) diff --git a/src/dtmf2num/resample2.c b/src/dtmf2num/resample2.c
@@ -1,342 +0,0 @@
-/*
- * audio resampling
- * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file resample2.c
- * audio resampling
- * @author Michael Niedermayer <michaelni@gmx.at>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <malloc.h>
-
-#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
-#define FFSIGN(a) ((a) > 0 ? 1 : -1)
-#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
-#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
-#define av_mallocz malloc
-#define av_freep free
-
-#ifndef CONFIG_RESAMPLE_HP
-#define FILTER_SHIFT 15
-
-#define FELEM int16_t
-#define FELEM2 int32_t
-#define FELEML int64_t
-#define FELEM_MAX INT16_MAX
-#define FELEM_MIN INT16_MIN
-#define WINDOW_TYPE 9
-#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE)
-#define FILTER_SHIFT 30
-
-#define FELEM int32_t
-#define FELEM2 int64_t
-#define FELEML int64_t
-#define FELEM_MAX INT32_MAX
-#define FELEM_MIN INT32_MIN
-#define WINDOW_TYPE 12
-#else
-#define FILTER_SHIFT 0
-
-#define FELEM double
-#define FELEM2 double
-#define FELEML double
-#define WINDOW_TYPE 24
-#endif
-
-
-typedef struct AVResampleContext{
- FELEM *filter_bank;
- int filter_length;
- int ideal_dst_incr;
- int dst_incr;
- int index;
- int frac;
- int src_incr;
- int compensation_distance;
- int phase_shift;
- int phase_mask;
- int linear;
-}AVResampleContext;
-
-/**
- * 0th order modified bessel function of the first kind.
- */
-static double bessel(double x){
- double v=1;
- double t=1;
- int i;
-
- x= x*x/4;
- for(i=1; i<50; i++){
- t *= x/(i*i);
- v += t;
- }
- return v;
-}
-
-static inline int av_clip(int a, int amin, int amax)
-{
- if (a < amin) return amin;
- else if (a > amax) return amax;
- else return a;
-}
-
-/**
- * builds a polyphase filterbank.
- * @param factor resampling factor
- * @param scale wanted sum of coefficients for each filter
- * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16
- */
-void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){
- int ph, i;
- double x, y, w, tab[tap_count];
- const int center= (tap_count-1)/2;
-
- /* if upsampling, only need to interpolate, no filter */
- if (factor > 1.0)
- factor = 1.0;
-
- for(ph=0;ph<phase_count;ph++) {
- double norm = 0;
- for(i=0;i<tap_count;i++) {
- x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
- if (x == 0) y = 1.0;
- else y = sin(x) / x;
- switch(type){
- case 0:{
- const float d= -0.5; //first order derivative = -0.5
- x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
- if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*( -x*x + x*x*x);
- else y= d*(-4 + 8*x - 5*x*x + x*x*x);
- break;}
- case 1:
- w = 2.0*x / (factor*tap_count) + M_PI;
- y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
- break;
- default:
- w = 2.0*x / (factor*tap_count*M_PI);
- y *= bessel(type*sqrt(FFMAX(1-w*w, 0)));
- break;
- }
-
- tab[i] = y;
- norm += y;
- }
-
- /* normalize so that an uniform color remains the same */
- for(i=0;i<tap_count;i++) {
-#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
- filter[ph * tap_count + i] = tab[i] / norm;
-#else
- filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), FELEM_MIN, FELEM_MAX);
-#endif
- }
- }
-#if 0
- {
-#define LEN 1024
- int j,k;
- double sine[LEN + tap_count];
- double filtered[LEN];
- double maxff=-2, minff=2, maxsf=-2, minsf=2;
- for(i=0; i<LEN; i++){
- double ss=0, sf=0, ff=0;
- for(j=0; j<LEN+tap_count; j++)
- sine[j]= cos(i*j*M_PI/LEN);
- for(j=0; j<LEN; j++){
- double sum=0;
- ph=0;
- for(k=0; k<tap_count; k++)
- sum += filter[ph * tap_count + k] * sine[k+j];
- filtered[j]= sum / (1<<FILTER_SHIFT);
- ss+= sine[j + center] * sine[j + center];
- ff+= filtered[j] * filtered[j];
- sf+= sine[j + center] * filtered[j];
- }
- ss= sqrt(2*ss/LEN);
- ff= sqrt(2*ff/LEN);
- sf= 2*sf/LEN;
- maxff= FFMAX(maxff, ff);
- minff= FFMIN(minff, ff);
- maxsf= FFMAX(maxsf, sf);
- minsf= FFMIN(minsf, sf);
- if(i%11==0){
- //av_log(NULL, AV_LOG_ERROR, "i:%4d ss:%f ff:%13.6e-%13.6e sf:%13.6e-%13.6e\n", i, ss, maxff, minff, maxsf, minsf);
- minff=minsf= 2;
- maxff=maxsf= -2;
- }
- }
- }
-#endif
-}
-
-/**
- * Initializes an audio resampler.
- * Note, if either rate is not an integer then simply scale both rates up so they are.
- */
-AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){
- AVResampleContext *c= av_mallocz(sizeof(AVResampleContext));
- double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
- int phase_count= 1<<phase_shift;
-
- c->phase_shift= phase_shift;
- c->phase_mask= phase_count-1;
- c->linear= linear;
-
- c->filter_length= FFMAX((int)ceil(filter_size/factor), 1);
- c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM));
- av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, WINDOW_TYPE);
- memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM));
- c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1];
-
- c->src_incr= out_rate;
- c->ideal_dst_incr= c->dst_incr= in_rate * phase_count;
- c->index= -phase_count*((c->filter_length-1)/2);
-
- return c;
-}
-
-void av_resample_close(AVResampleContext *c){
- av_freep(&c->filter_bank);
- av_freep(&c);
-}
-
-/**
- * Compensates samplerate/timestamp drift. The compensation is done by changing
- * the resampler parameters, so no audible clicks or similar distortions ocur
- * @param compensation_distance distance in output samples over which the compensation should be performed
- * @param sample_delta number of output samples which should be output less
- *
- * example: av_resample_compensate(c, 10, 500)
- * here instead of 510 samples only 500 samples would be output
- *
- * note, due to rounding the actual compensation might be slightly different,
- * especially if the compensation_distance is large and the in_rate used during init is small
- */
-void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){
-// sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr;
- c->compensation_distance= compensation_distance;
- c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
-}
-
-/**
- * resamples.
- * @param src an array of unconsumed samples
- * @param consumed the number of samples of src which have been consumed are returned here
- * @param src_size the number of unconsumed samples available
- * @param dst_size the amount of space in samples available in dst
- * @param update_ctx if this is 0 then the context wont be modified, that way several channels can be resampled with the same context
- * @return the number of samples written in dst or -1 if an error occured
- */
-int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){
- int dst_index, i;
- int index= c->index;
- int frac= c->frac;
- int dst_incr_frac= c->dst_incr % c->src_incr;
- int dst_incr= c->dst_incr / c->src_incr;
- int compensation_distance= c->compensation_distance;
-
- if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){
- int64_t index2= ((int64_t)index)<<32;
- int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr;
- dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr);
-
- for(dst_index=0; dst_index < dst_size; dst_index++){
- dst[dst_index] = src[index2>>32];
- index2 += incr;
- }
- frac += dst_index * dst_incr_frac;
- index += dst_index * dst_incr;
- index += frac / c->src_incr;
- frac %= c->src_incr;
- }else{
- for(dst_index=0; dst_index < dst_size; dst_index++){
- FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask);
- int sample_index= index >> c->phase_shift;
- FELEM2 val=0;
-
- if(sample_index < 0){
- for(i=0; i<c->filter_length; i++)
- val += src[FFABS(sample_index + i) % src_size] * filter[i];
- }else if(sample_index + c->filter_length > src_size){
- break;
- }else if(c->linear){
- FELEM2 v2=0;
- for(i=0; i<c->filter_length; i++){
- val += src[sample_index + i] * (FELEM2)filter[i];
- v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length];
- }
- val+=(v2-val)*(FELEML)frac / c->src_incr;
- }else{
- for(i=0; i<c->filter_length; i++){
- val += src[sample_index + i] * (FELEM2)filter[i];
- }
- }
-
-#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
- dst[dst_index] = av_clip_int16(lrintf(val));
-#else
- val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
- dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val;
-#endif
-
- frac += dst_incr_frac;
- index += dst_incr;
- if(frac >= c->src_incr){
- frac -= c->src_incr;
- index++;
- }
-
- if(dst_index + 1 == compensation_distance){
- compensation_distance= 0;
- dst_incr_frac= c->ideal_dst_incr % c->src_incr;
- dst_incr= c->ideal_dst_incr / c->src_incr;
- }
- }
- }
- *consumed= FFMAX(index, 0) >> c->phase_shift;
- if(index>=0) index &= c->phase_mask;
-
- if(compensation_distance){
- compensation_distance -= dst_index;
- if(!(compensation_distance > 0)) return(-1);
- }
- if(update_ctx){
- c->frac= frac;
- c->index= index;
- c->dst_incr= dst_incr_frac + c->src_incr*dst_incr;
- c->compensation_distance= compensation_distance;
- }
-#if 0
- if(update_ctx && !c->compensation_distance){
-#undef rand
- av_resample_compensate(c, rand() % (8000*2) - 8000, 8000*2);
-//av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", c->dst_incr, c->ideal_dst_incr, c->compensation_distance);
- }
-#endif
-
- return dst_index;
-}