Introduction
Introduction Statistics Contact Development Disclaimer Help
Remove dtmf2num - warvox - VoIP based wardialing tool, forked from rapid7/warvo…
Log
Files
Refs
README
---
commit 3f4572631842f38da7c8020f2632b3238b6ae055
parent edcebe28cb22ff7f9e7091638c88bd7c5ea4df84
Author: HD Moore <[email protected]>
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(-)
---
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)
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
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/>
diff --git a/app/views/analyze/view_matches.html.erb b/app/views/analyze/view_m…
@@ -10,10 +10,10 @@
<tr>
<td align='center'>
-
+
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_ana…
+ data="/assets/musicplayer.swf?song_url=<%=resource_ana…
width="20"
height="17"
style="margin-bottom: -5px;"
@@ -21,31 +21,25 @@
<param name="movie" value="/assets/musicplayer.swf?son…
<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, "bi…
<a href="<%=resource_analyze_path(@job_id, dial_result.id, "bi…
- <% (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 …
- <% 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/><b…
-
+
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_ana…
+ data="/assets/musicplayer.swf?song_url=<%=resource_ana…
width="20"
height="17"
style="margin-bottom: -5px;"
@@ -74,34 +68,28 @@
<param name="movie" value="/assets/musicplayer.swf?son…
<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, "bi…
<a href="<%=resource_analyze_path(@job_id, dial_result.id, "bi…
- <% (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 …
- <% end %>
+ <% end %>
<% if dial_result.fprint %>
<a href="<%=view_matches_path(dial_result.id)%>">View …
- <% end %>
+ <% end %>
</td>
</tr>
<% end %>
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 " "
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"
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"
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
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 ].…
-
- # Detect DTMF and MF tones
- dtmf = ''
- mf = ''
- pfd = IO.popen("#{WarVOX::Config.tool_path('dtmf2num')} -r 800…
- 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
-
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
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
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 <[email protected]>
- *
- * 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 <[email protected]>
- * \author Steve Underwood <[email protected]>
- */
-
-/* Some routines from tone_detect.c by Steven Underwood as published under the…
-/*
- tone_detect.c - General telephony tone detection, and specific
- detection of DTMF.
-
- Copyright (C) 2001 Steve Underwood <[email protected]>
-
- 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 w…
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <malloc.h>
-
-#define DSP_DIGITMODE_DTMF 0 …
-#define DSP_DIGITMODE_MF 1 …
-
-#define DSP_DIGITMODE_NOQUELCH (1 << 8) /*!< Do …
-#define DSP_DIGITMODE_RELAXDTMF (1 << 11) /*!< "…
-
-#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…
-#else
-#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4…
-#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…
-#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 coun…
-{
- 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)…
- time of a rolled loop on the machine on which it was develo…
- 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…
- (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 cle…
- 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_REVERS…
- col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_r…
- /* Relative peak test */
- for (i = 0; i < 4; i++) {
- if ((i != best_col &&
- col_energy[i]*DTMF_RELATIVE_PEAK_COL > col…
- (i != best_row
- && row_energy[i]*DTMF_RELATIVE_PEAK_ROW >…
- break;
- }
- }
- /* ... and fraction of total energy test */
- if (i >= 4 /*&&
- (row_energy[best_row] + col_energy[best_col]) > DT…
- /* Got a hit */
- hit = dtmf_positions[(best_row << 2) + best_co…
- if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
- /* Zero out frame data if this is part…
- 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, …
- 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_hi…
- 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)…
- time of a rolled loop on the machine on which it was develo…
- for (j = sample; j < limit; j++) {
- famp = amp[j];
- /* With GCC 2.95, the following unrolled code seems to…
- (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 cle…
- 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] >…
-// && energy[best] < energy[second_best]*BELL_MF_TWIST …
- && 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 >=…
- /* The best two are not clearl…
- 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…
- two blocks of something different preceeding it. Fo…
- else we need two successive identical clean detects…
- 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…
- (hit == '*' && hit == s->td.mf.hits[2] && hit != s…
- 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 curren…
- 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 */
-}
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: [email protected]\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 …
- " Frequency, Channels and Bits like -r 44100 2 16\n"
- "-o disable the automatic optimizations: DC bias adjust and…
- " use this option only if your file is already clean and …
- "-w FILE debug option for dumping the handled samples from the m…
- "\n", argv[0]);
- exit(1);
- }
-
- argc--;
- for(i = 1; i < argc; i++) {
- if(((argv[i][0] != '-') && (argv[i][0] != '/')) || (strlen(argv[i]) !=…
- 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 supp…
-
- 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);
-}
-
-
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: [email protected]
- 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…
- 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);
-}
-
diff --git a/src/dtmf2num/resample2.c b/src/dtmf2num/resample2.c
@@ -1,342 +0,0 @@
-/*
- * audio resampling
- * Copyright (c) 2004 Michael Niedermayer <[email protected]>
- *
- * 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 <[email protected]>
- */
-
-#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 wind…
- */
-void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_co…
- 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) * fac…
- 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) * f…
- 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…
- 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)…
-#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:…
- 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 t…
- */
-AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size…
- 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<<…
- memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c…
- c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_len…
-
- 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 comp…
- * @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 durin…
- */
-void av_resample_compensate(AVResampleContext *c, int sample_delta, int compen…
-// sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensati…
- c->compensation_distance= compensation_distance;
- c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delt…
-}
-
-/**
- * resamples.
- * @param src an array of unconsumed samples
- * @param consumed the number of samples of src which have been consumed are r…
- * @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 …
- * @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, i…
- 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 / …
-
- 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_mas…
- 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_le…
- }
- 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 :…
-#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->…
- }
-#endif
-
- return dst_index;
-}
You are viewing proxied material from jay.scot. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.