| Store various call info into the database, determine whether the call is fax/mo… | |
| Log | |
| Files | |
| Refs | |
| README | |
| --- | |
| commit 6389d305a83d6a5384d3332e5ca69cf6d35a8abf | |
| parent 76fc65ae7c8b0a944971cfcdbdf4dae3bb1cd3ec | |
| Author: HD Moore <[email protected]> | |
| Date: Wed, 4 Mar 2009 03:57:08 +0000 | |
| Store various call info into the database, determine whether the call is fax/mo… | |
| Diffstat: | |
| M lib/warvox/jobs/analysis.rb | 82 +++++++++++++++++++++++++++--… | |
| M web/app/controllers/analyze_contro… | 19 +++++++++++++++++++ | |
| M web/app/views/analyze/view.html.erb | 21 +++++++++++++-------- | |
| A web/db/migrate/20090304013815_add_… | 9 +++++++++ | |
| A web/db/migrate/20090304013839_add_… | 9 +++++++++ | |
| A web/db/migrate/20090304013909_add_… | 9 +++++++++ | |
| A web/db/migrate/20090304014018_add_… | 9 +++++++++ | |
| A web/db/migrate/20090304014033_add_… | 9 +++++++++ | |
| M web/db/schema.rb | 7 ++++++- | |
| R web/public/images/overlay.png -> w… | 0 | |
| 10 files changed, 156 insertions(+), 18 deletions(-) | |
| --- | |
| diff --git a/lib/warvox/jobs/analysis.rb b/lib/warvox/jobs/analysis.rb | |
| @@ -7,7 +7,7 @@ class Analysis < Base | |
| @@kissfft_loaded = false | |
| begin | |
| require 'kissfft' | |
| - @kissfft_loaded = true | |
| + @@kissfft_loaded = true | |
| rescue ::LoadError | |
| end | |
| @@ -62,11 +62,16 @@ class Analysis < Base | |
| # | |
| # Create the signature database | |
| # | |
| - raw = WarVOX::Audio::Raw.from_file(r.rawfile) | |
| - fd = File.new("#{bname}.sig", "wb") | |
| - fd.write raw.to_flow | |
| + | |
| + raw = WarVOX::Audio::Raw.from_file(r.rawfile) | |
| + flow = raw.to_flow | |
| + fd = File.new("#{bname}.sig", "wb") | |
| + fd.write flow | |
| fd.close | |
| + # Save the signature data | |
| + r.sig_data = flow | |
| + | |
| # | |
| # Create a raw decompressed file | |
| # | |
| @@ -108,6 +113,9 @@ class Analysis < Base | |
| end | |
| end | |
| + # Save the peak frequency | |
| + r.peak_freq = maxf | |
| + | |
| # Calculate average frequency and peaks over time | |
| avg = {} | |
| pks = [] | |
| @@ -118,17 +126,73 @@ class Analysis < Base | |
| avg[ freq[0] ] += freq[1] | |
| end | |
| end | |
| + | |
| + # Save the peak frequencies over time | |
| + r.peak_freq_data = pks.map{|f| "#{f[0]}-#{f[1]}" }.joi… | |
| + | |
| + # Generate the frequency file | |
| avg.keys.sort.each do |k| | |
| avg[k] = avg[k] / res.length | |
| frefile.write("#{k} #{avg[k]}\n") | |
| end | |
| frefile.flush | |
| - # XXX: Store all frequency information | |
| - # maxf == peak frequency | |
| - # avg == averages over whole sample | |
| - # pks == peaks over time | |
| - # tones == significant frequencies | |
| + # | |
| + # XXX: store significant frequencies somewhere (tones) | |
| + # | |
| + | |
| + # Make a guess as to what kind of phone number we found | |
| + line_type = nil | |
| + while(not line_type) | |
| + | |
| + # Look for modems by detecting 2250hz tones | |
| + f_2250 = 0 | |
| + pks.each{|f| f_2250 += 1 if(f[0] > 2240 and f[… | |
| + if(f_2250 > 2) | |
| + line_type = 'modem' | |
| + break | |
| + end | |
| + | |
| + # Look for the 1000hz voicemail BEEP | |
| + if(r.peak_freq > 990 and r.peak_freq < 1010) | |
| + line_type = 'voicemail' | |
| + break | |
| + end | |
| + | |
| + # Most faxes have at least two of the followin… | |
| + f_1625 = f_1660 = f_1825 = f_2100 = false | |
| + pks.each do |f| | |
| + # $stderr.puts "#{r.number} #{f.inspec… | |
| + f_1625 = true if(f[0] > 1620 and f[0] … | |
| + f_1660 = true if(f[0] > 1655 and f[0] … | |
| + f_1825 = true if(f[0] > 1820 and f[0] … | |
| + f_2100 = true if(f[0] > 2090 and f[0] … | |
| + end | |
| + if([ f_1625, f_1660, f_1825, f_2100 ].grep(tru… | |
| + line_type = 'fax' | |
| + break | |
| + end | |
| + | |
| + # Dial tone detection | |
| + f_440 = false | |
| + f_350 = false | |
| + pks.each do |f| | |
| + f_440 = true if(f[0] > 435 and f[0] < … | |
| + f_345 = true if(f[0] > 345 and f[0] < … | |
| + end | |
| + if(f_440 and f_350) | |
| + line_type = 'dialtone' | |
| + break | |
| + end | |
| + | |
| + # Detect humans based on long pauses | |
| + | |
| + # Default to voice | |
| + line_type = 'voice' | |
| + end | |
| + | |
| + # Save the guessed line type | |
| + r.line_type = line_type | |
| # Plot samples to a graph | |
| plotter = Tempfile.new("gnuplot") | |
| diff --git a/web/app/controllers/analyze_controller.rb b/web/app/controllers/an… | |
| @@ -19,6 +19,25 @@ class AnalyzeController < ApplicationController | |
| :per_page => 10, | |
| :conditions => [ 'completed = ? and processed = ? and busy = ?… | |
| ) | |
| + | |
| + @g1 = Ezgraphix::Graphic.new(:c_type => 'pie2d', :div_name => 'calls_p… | |
| + @g1.render_options(:caption => 'Line Types') | |
| + | |
| + @g2 = Ezgraphix::Graphic.new(:c_type => 'pie2d', :div_name => 'calls_p… | |
| + @g2.render_options(:caption => 'Ring Time') | |
| + | |
| + res_types = {} | |
| + res_rings = {} | |
| + | |
| + @results.each do |r| | |
| + res_rings[ r.ringtime ] ||= 0 | |
| + res_rings[ r.ringtime ] += 1 | |
| + res_types[ r.line_type.capitalize.to_sym ] ||= 0 | |
| + res_types[ r.line_type.capitalize.to_sym ] += 1 … | |
| + end | |
| + | |
| + @g1.data = res_types | |
| + @g2.data = res_rings | |
| end | |
| # GET /dial_results/1/resource?id=XXX&type=YYY | |
| diff --git a/web/app/views/analyze/view.html.erb b/web/app/views/analyze/view.h… | |
| @@ -2,8 +2,8 @@ | |
| <table width='100%' align='center' border=0 cellspacing=0 cellpadding=6> | |
| <tr> | |
| - <td align='center'> </td> | |
| - <td align='center'> </td> | |
| + <td align='center'><%= render_ezgraphix @g1 %></td> | |
| + <td align='center'><%= render_ezgraphix @g2 %></td> | |
| </tr> | |
| </table> | |
| @@ -11,11 +11,13 @@ | |
| <table class='table_scaffold' width='100%'> | |
| <tr> | |
| - <th>ID</th> | |
| + <th>ID</th> | |
| + <th>Number</th> | |
| + <th>Type</th> | |
| + <th>Peak Freq</th> | |
| <th>Signal</th> | |
| <th>Spectrum</th> | |
| - <th>Number</th> | |
| - <th>CallerID</th> | |
| + <th>CID</th> | |
| <th>Provider</th> | |
| <th>Call Time</th> | |
| <th>Ring Time</th> | |
| @@ -24,15 +26,18 @@ | |
| <% @results.each do |dial_result| %> | |
| <tr> | |
| <td><%=h dial_result.id %></td> | |
| + <td> | |
| + <a href="<%=resource_analyze_path(@job_id)%>?result_id=<%= dia… | |
| + </td> | |
| + <td><%=h dial_result.line_type %></td> | |
| + <td><%=h dial_result.peak_freq.to_i %></td> | |
| <td> | |
| <a href="<%=resource_analyze_path(@job_id)%>?result_id=<%= dia… | |
| </td> | |
| <td> | |
| <a href="<%=resource_analyze_path(@job_id)%>?result_id=<%= dia… | |
| </td> | |
| - <td> | |
| - <a href="<%=resource_analyze_path(@job_id)%>?result_id=<%= dia… | |
| - </td> | |
| + | |
| <td><%=h dial_result.cid %></td> | |
| <td><%=h dial_result.provider.name %></td> | |
| <td><%=h dial_result.seconds %></td> | |
| diff --git a/web/db/migrate/20090304013815_add_peak_freq_to_dial_results.rb b/w… | |
| @@ -0,0 +1,9 @@ | |
| +class AddPeakFreqToDialResults < ActiveRecord::Migration | |
| + def self.up | |
| + add_column :dial_results, :peak_freq, :number | |
| + end | |
| + | |
| + def self.down | |
| + remove_column :dial_results, :peak_freq | |
| + end | |
| +end | |
| diff --git a/web/db/migrate/20090304013839_add_peak_freq_data_to_dial_results.r… | |
| @@ -0,0 +1,9 @@ | |
| +class AddPeakFreqDataToDialResults < ActiveRecord::Migration | |
| + def self.up | |
| + add_column :dial_results, :peak_freq_data, :string | |
| + end | |
| + | |
| + def self.down | |
| + remove_column :dial_results, :peak_freq_data | |
| + end | |
| +end | |
| diff --git a/web/db/migrate/20090304013909_add_sig_data_to_dial_results.rb b/we… | |
| @@ -0,0 +1,9 @@ | |
| +class AddSigDataToDialResults < ActiveRecord::Migration | |
| + def self.up | |
| + add_column :dial_results, :sig_data, :string | |
| + end | |
| + | |
| + def self.down | |
| + remove_column :dial_results, :sig_data | |
| + end | |
| +end | |
| diff --git a/web/db/migrate/20090304014018_add_line_type_to_dial_results.rb b/w… | |
| @@ -0,0 +1,9 @@ | |
| +class AddLineTypeToDialResults < ActiveRecord::Migration | |
| + def self.up | |
| + add_column :dial_results, :line_type, :string | |
| + end | |
| + | |
| + def self.down | |
| + remove_column :dial_results, :line_type | |
| + end | |
| +end | |
| diff --git a/web/db/migrate/20090304014033_add_notes_to_dial_results.rb b/web/d… | |
| @@ -0,0 +1,9 @@ | |
| +class AddNotesToDialResults < ActiveRecord::Migration | |
| + def self.up | |
| + add_column :dial_results, :notes, :string | |
| + end | |
| + | |
| + def self.down | |
| + remove_column :dial_results, :notes | |
| + end | |
| +end | |
| diff --git a/web/db/schema.rb b/web/db/schema.rb | |
| @@ -9,7 +9,7 @@ | |
| # | |
| # It's strongly recommended to check this file into your version control syste… | |
| -ActiveRecord::Schema.define(:version => 20090303225838) do | |
| +ActiveRecord::Schema.define(:version => 20090304014033) do | |
| create_table "dial_jobs", :force => true do |t| | |
| t.string "range" | |
| @@ -39,6 +39,11 @@ ActiveRecord::Schema.define(:version => 20090303225838) do | |
| t.datetime "updated_at" | |
| t.datetime "processed_at" | |
| t.string "cid" | |
| + t.decimal "peak_freq" | |
| + t.string "peak_freq_data" | |
| + t.string "sig_data" | |
| + t.string "line_type" | |
| + t.string "notes" | |
| end | |
| create_table "providers", :force => true do |t| | |
| diff --git a/web/public/images/overlay.png b/web/public/stylesheets/overlay.png | |
| Binary files differ. |