Class: SPCore::DiscreteResampling

Inherits:
Object
  • Object
show all
Defined in:
lib/spcore/resampling/discrete_resampling.rb

Overview

discrete filtering.

Class Method Summary collapse

Class Method Details

.downsample(input, sample_rate, downsample_factor, filter_order) ⇒ Object

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/spcore/resampling/discrete_resampling.rb', line 27

def self.downsample input, sample_rate, downsample_factor, filter_order
  raise ArgumentError, "input.size is less than four" unless input.size >= 4
  raise ArgumentError, "downsample_factor is not a Fixnum" unless downsample_factor.is_a?(Fixnum)
  raise ArgumentError, "downsample_factor is not greater than 1" unless downsample_factor > 1
  raise ArgumentError, "sample_rate is not greater than 0" unless sample_rate > 0
  
  needed_samples = input.size % downsample_factor
  if needed_samples == 0
    input += Array.new(needed_samples, 0.0)
  end

  filter = SincFilter.new(
    :sample_rate => sample_rate, :order => filter_order,
    :cutoff_freq => ((sample_rate.to_f / downsample_factor) / 2.0),
    :window_class => NuttallWindow
  )
  
  filtered = filter.lowpass(input)
  return Array.new(filtered.size / downsample_factor) { |i| filtered[i * downsample_factor] }
end

.resample(input, sample_rate, upsample_factor, downsample_factor, filter_order) ⇒ Object

Raises:

  • (ArgumentError)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/spcore/resampling/discrete_resampling.rb', line 48

def self.resample input, sample_rate, upsample_factor, downsample_factor, filter_order
  raise ArgumentError, "input.size is less than four" unless input.size >= 4
  raise ArgumentError, "upsample_factor is not a Fixnum" unless upsample_factor.is_a?(Fixnum)
  raise ArgumentError, "upsample_factor is not greater than 1" unless upsample_factor > 1
  raise ArgumentError, "downsample_factor is not a Fixnum" unless downsample_factor.is_a?(Fixnum)
  raise ArgumentError, "downsample_factor is not greater than 1" unless downsample_factor > 1
  raise ArgumentError, "sample_rate is not greater than 0" unless sample_rate > 0
  
  upsampled = Array.new((upsample_factor * input.size).to_i, 0.0)
  input.each_index do |i|
    upsampled[i * upsample_factor] = input[i] * upsample_factor
  end

  needed_samples = upsampled.size % downsample_factor
  if needed_samples == 0
    upsampled += Array.new(needed_samples, 0.0)
  end
  
  target_rate = sample_rate * upsample_factor / downsample_factor
  cutoff = (target_rate < sample_rate) ? (target_rate / 2.0) : (sample_rate / 2.0)
  
  filter = SincFilter.new(
    :sample_rate => (sample_rate * upsample_factor), :order => filter_order,
    :cutoff_freq => cutoff, :window_class => NuttallWindow
  )
  filtered = filter.lowpass(upsampled)
  return Array.new(filtered.size / downsample_factor){ |i| filtered[i * downsample_factor] }
end

.upsample(input, sample_rate, upsample_factor, filter_order) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/spcore/resampling/discrete_resampling.rb', line 6

def self.upsample input, sample_rate, upsample_factor, filter_order
  raise ArgumentError, "input.size is less than four" unless input.size >= 4
  raise ArgumentError, "upsample_factor is not a Fixnum" unless upsample_factor.is_a?(Fixnum)
  raise ArgumentError, "upsample_factor is not greater than 1" unless upsample_factor > 1
  raise ArgumentError, "sample_rate is not greater than 0" unless sample_rate > 0
  
  output = Array.new((upsample_factor * input.size).to_i, 0.0)
  input.each_index do |i|
    output[i * upsample_factor] = input[i] * upsample_factor
  end
  
  filter = SincFilter.new(
    :sample_rate => (sample_rate * upsample_factor),
    :order => filter_order,
    :cutoff_freq => (sample_rate / 2.0),
    :window_class => NuttallWindow
  )
  
  return filter.lowpass(output)
end