audio_stream 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,11 +36,11 @@ module AudioStream
36
36
  }
37
37
  when 2
38
38
  window_size.times {|i|
39
- input[i] = channels.times.map {|j|
40
- b = @filter_bufs[j]
41
- in0 = input[i][j]
42
- process_one(in0, b)
43
- }
39
+ input_i = input[i]
40
+ input[i] = [
41
+ process_one(input_i[0], @filter_bufs[0]),
42
+ process_one(input_i[1], @filter_bufs[1]),
43
+ ]
44
44
  }
45
45
  end
46
46
 
@@ -69,6 +69,57 @@ module AudioStream
69
69
 
70
70
  out0
71
71
  end
72
+
73
+ def plot_data(width=1000)
74
+ c = @filter_coef
75
+
76
+ b0 = c.b0 / c.a0
77
+ b1 = c.b1 / c.a0
78
+ b2 = c.b2 / c.a0
79
+ a1 = c.a1 / c.a0
80
+ a2 = c.a2 / c.a0
81
+
82
+ noctaves = 10
83
+ nyquist = @samplerate * 0.5
84
+
85
+ freq = []
86
+ x = []
87
+ width.times {|i|
88
+ f = i.to_f / width
89
+ f = 2.0 ** (noctaves * (f - 1.0))
90
+ freq << f
91
+ x << (f * nyquist)
92
+ }
93
+
94
+ mag_res = []
95
+ phase_res = []
96
+ width.times {|i|
97
+ omega = -Math::PI * freq[i]
98
+ z = Complex(Math.cos(omega), Math.sin(omega))
99
+ num = b0 + (b1 + b2 * z) * z
100
+ den = 1 + (a1 + a2 * z) * z
101
+ res = num / den
102
+
103
+ mag_res << Decibel.mag(res.abs).db
104
+ phase_res << 180 / Math::PI * Math.atan2(res.imag, res.real)
105
+ }
106
+
107
+ {x: x, magnitude: mag_res, phase: phase_res}
108
+ end
109
+
110
+ def plot(width=1000)
111
+ data = plot_data(width)
112
+
113
+ Plotly::Plot.new(
114
+ data: [{x: data[:x], y: data[:magnitude], name: 'Magnitude', yaxis: 'y1'}, {x: data[:x], y: data[:phase], name: 'Phase', yaxis: 'y2'}],
115
+ layout: {
116
+ xaxis: {title: 'Frequency (Hz)', type: 'log'},
117
+ yaxis: {side: 'left', title: 'Magnitude (dB)', showgrid: false},
118
+ yaxis2: {side: 'right', title: 'Phase (deg)', showgrid: false, overlaying: 'y'}
119
+ }
120
+ )
121
+ end
122
+
72
123
  end
73
124
  end
74
125
  end
@@ -10,7 +10,7 @@ module AudioStream
10
10
  @window_size = impulse_bufs[0].size
11
11
  @dry_gain = dry
12
12
  @wet_gain = wet
13
- @window = window || HanningWindow.new
13
+ @window = window || HanningWindow.instance
14
14
 
15
15
  zero_buf = Buffer.float(@window_size, @channels)
16
16
  if @channels==1
@@ -3,21 +3,35 @@ module AudioStream
3
3
  class Equalizer2band
4
4
  include BangProcess
5
5
 
6
- def initialize(soundinfo, lowgain:, highgain:)
7
- @lowfreq = 400.0
8
- @lowgain = lowgain
9
-
10
- @highfreq = 4000.0
11
- @highgain = highgain
12
-
13
- @low_filter = LowShelfFilter.create(soundinfo, freq: @lowfreq, q: 1.0/Math.sqrt(2.0), gain: @lowgain)
14
- @high_filter = HighShelfFilter.create(soundinfo, freq: @highfreq, q: 1.0/Math.sqrt(2.0), gain: @highgain)
6
+ def initialize(soundinfo, lowfreq: 400.0, lowgain:, highfreq: 4000.0, highgain:)
7
+ @low_filter = LowShelfFilter.create(soundinfo, freq: lowfreq, q: 1.0/Math.sqrt(2.0), gain: lowgain)
8
+ @high_filter = HighShelfFilter.create(soundinfo, freq: highfreq, q: 1.0/Math.sqrt(2.0), gain: highgain)
15
9
  end
16
10
 
17
11
  def process!(input)
18
12
  @low_filter.process!(input)
19
13
  @high_filter.process!(input)
20
14
  end
15
+
16
+ def plot(width=1000)
17
+ data1 = @low_filter.plot_data(width)
18
+ data2 = @high_filter.plot_data(width)
19
+
20
+ data = {
21
+ x: data1[:x],
22
+ magnitude: [data1[:magnitude], data2[:magnitude]].transpose.map {|a| a[0] + a[1]},
23
+ phase: [data1[:phase], data2[:phase]].transpose.map {|a| a[0] + a[1]},
24
+ }
25
+
26
+ Plotly::Plot.new(
27
+ data: [{x: data[:x], y: data[:magnitude], name: 'Magnitude', yaxis: 'y1'}, {x: data[:x], y: data[:phase], name: 'Phase', yaxis: 'y2'}],
28
+ layout: {
29
+ xaxis: {title: 'Frequency (Hz)', type: 'log'},
30
+ yaxis: {side: 'left', title: 'Magnitude (dB)', showgrid: false},
31
+ yaxis2: {side: 'right', title: 'Phase (deg)', showgrid: false, overlaying: 'y'}
32
+ }
33
+ )
34
+ end
21
35
  end
22
36
  end
23
37
  end
@@ -3,19 +3,10 @@ module AudioStream
3
3
  class Equalizer3band
4
4
  include BangProcess
5
5
 
6
- def initialize(soundinfo, lowgain:, midgain:, highgain:)
7
- @lowfreq = 400.0
8
- @lowgain = lowgain
9
-
10
- @midfreq = 1000.0
11
- @midgain = midgain
12
-
13
- @highfreq = 4000.0
14
- @highgain = highgain
15
-
16
- @low_filter = LowShelfFilter.create(soundinfo, freq: @lowfreq, q: 1.0/Math.sqrt(2.0), gain: @lowgain)
17
- @mid_filter = PeakingFilter.create(soundinfo, freq: @midfreq, bandwidth: 1.0/Math.sqrt(2.0), gain: @midgain)
18
- @high_filter = HighShelfFilter.create(soundinfo, freq: @highfreq, q: 1.0/Math.sqrt(2.0), gain: @highgain)
6
+ def initialize(soundinfo, lowfreq: 400.0, lowgain:, midfreq: 1000.0, midgain:, highfreq: 4000.0, highgain:)
7
+ @low_filter = LowShelfFilter.create(soundinfo, freq: lowfreq, q: 1.0/Math.sqrt(2.0), gain: lowgain)
8
+ @mid_filter = PeakingFilter.create(soundinfo, freq: midfreq, bandwidth: 1.0/Math.sqrt(2.0), gain: midgain)
9
+ @high_filter = HighShelfFilter.create(soundinfo, freq: highfreq, q: 1.0/Math.sqrt(2.0), gain: highgain)
19
10
  end
20
11
 
21
12
  def process!(input)
@@ -23,6 +14,27 @@ module AudioStream
23
14
  @mid_filter.process!(input)
24
15
  @high_filter.process!(input)
25
16
  end
17
+
18
+ def plot(width=1000)
19
+ data1 = @low_filter.plot_data(width)
20
+ data2 = @mid_filter.plot_data(width)
21
+ data3 = @high_filter.plot_data(width)
22
+
23
+ data = {
24
+ x: data1[:x],
25
+ magnitude: [data1[:magnitude], data2[:magnitude], data3[:magnitude]].transpose.map {|a| a[0] + a[1] + a[2]},
26
+ phase: [data1[:phase], data2[:phase], data3[:phase]].transpose.map {|a| a[0] + a[1] + a[2]},
27
+ }
28
+
29
+ Plotly::Plot.new(
30
+ data: [{x: data[:x], y: data[:magnitude], name: 'Magnitude', yaxis: 'y1'}, {x: data[:x], y: data[:phase], name: 'Phase', yaxis: 'y2'}],
31
+ layout: {
32
+ xaxis: {title: 'Frequency (Hz)', type: 'log'},
33
+ yaxis: {side: 'left', title: 'Magnitude (dB)', showgrid: false},
34
+ yaxis2: {side: 'right', title: 'Phase (deg)', showgrid: false, overlaying: 'y'}
35
+ }
36
+ )
37
+ end
26
38
  end
27
39
  end
28
40
  end
@@ -12,7 +12,7 @@ module AudioStream
12
12
  a2 = 1.0 - alpha / a
13
13
  b0 = 1.0 + alpha * a
14
14
  b1 = -2.0 * Math.cos(omega)
15
- b2 = 1.0 + alpha * a
15
+ b2 = 1.0 - alpha * a
16
16
 
17
17
  @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
18
18
  end
@@ -1,3 +1,3 @@
1
1
  module AudioStream
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
data/lib/audio_stream.rb CHANGED
@@ -7,6 +7,7 @@ require 'singleton'
7
7
  require 'audio_stream/version'
8
8
  require 'audio_stream/error'
9
9
  require 'audio_stream/sound_info'
10
+ require 'audio_stream/decibel'
10
11
  require 'audio_stream/buffer'
11
12
  require 'audio_stream/ring_buffer'
12
13
  require 'audio_stream/sync'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: audio_stream
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshida Tetsuya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-27 00:00:00.000000000 Z
11
+ date: 2019-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -124,9 +124,10 @@ files:
124
124
  - audio_stream.gemspec
125
125
  - bin/console
126
126
  - bin/setup
127
- - examples/buffer.ipynb
127
+ - examples/biquad.ipynb
128
128
  - examples/chorus.rb
129
129
  - examples/distortion.rb
130
+ - examples/equalizer.ipynb
130
131
  - examples/example_options.rb
131
132
  - examples/lpf.rb
132
133
  - examples/rec.rb
@@ -147,6 +148,7 @@ files:
147
148
  - lib/audio_stream/audio_output_file.rb
148
149
  - lib/audio_stream/buffer.rb
149
150
  - lib/audio_stream/conductor.rb
151
+ - lib/audio_stream/decibel.rb
150
152
  - lib/audio_stream/error.rb
151
153
  - lib/audio_stream/fx.rb
152
154
  - lib/audio_stream/fx/a_gain.rb