audio_stream 2.0.0 → 3.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b2b4231db7c1e5aeed85c42c10f9071cbd7bea36a7b286d72c712645a4b4a74
4
- data.tar.gz: 170ebe1b6acef7cd7816dd971a7539cd2a321bdb826ab6455d8764e5127eeb9d
3
+ metadata.gz: b66dd6e651e9b7e179c17382ecfe8a18a1a35181a4df247a1ad960c1314d723b
4
+ data.tar.gz: 49019f9eeb61ab81f10277f931afb6e5f9e2710294dd43d9c20ac1c70d907d60
5
5
  SHA512:
6
- metadata.gz: 2913207ae700123f3fe2ad297894d9167220aac59da9cba1c5086ee3304bd1cc2fa7f5a19ffccdcc8ddd20affd6846955245453502b4f8984444effdd5a5d9de
7
- data.tar.gz: c03e01db92754fd39ad397073641d50519928463a73d0727bd71300075f18eef45dc0d18e068e6135925d6ef7613b8d372ea696fbe432170ff805659995099a7
6
+ metadata.gz: 2e1da05fe284fc2bf71fab340b605ccc7354461497163ec36638304b8602ab431dacab37e2aa6d5184adc1fb28884e5b67a4f989733890aa9ed7e9753bc268d5
7
+ data.tar.gz: 2ac60347cf0f12750be2006fdf91721ea7e4982bfda46096dbf5ef94ddeb64a344a11452814a3645688b3ef3c5af02a08973c67f1196dcb179c3f3b77e6fb454
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "rake", "~> 12.0"
31
31
  spec.add_development_dependency "minitest", "~> 5.0"
32
32
 
33
+ spec.add_dependency "vdsp", ">= 1.6.0"
33
34
  spec.add_dependency "ruby-audio", ">= 1.6.1"
34
35
  spec.add_dependency "coreaudio", ">= 0.0.12"
35
36
  spec.add_dependency "ruby-fftw3", ">= 1.0.2"
@@ -1,5 +1,6 @@
1
1
  require 'ruby-audio'
2
2
  require 'coreaudio'
3
+ require 'vdsp'
3
4
  require 'numru/fftw3'
4
5
  require 'rbplotly'
5
6
  require 'singleton'
@@ -6,6 +6,13 @@ module AudioStream
6
6
  attr_reader :window_size
7
7
 
8
8
  def initialize(stream0, stream1=nil)
9
+ if Array===stream0
10
+ stream0 = Vdsp::DoubleArray.create(stream0)
11
+ end
12
+ if Array===stream1
13
+ stream1 = Vdsp::DoubleArray.create(stream1)
14
+ end
15
+
9
16
  @stream0 = stream0
10
17
  @stream1 = stream1
11
18
 
@@ -58,53 +65,45 @@ module AudioStream
58
65
  end
59
66
 
60
67
  def +(other)
61
- self.class.merge([self, other])
62
- end
68
+ if self.window_size!=other.window_size
69
+ raise Error, "Buffer.window_size is not match: self.window_size=#{self.window_size} other.window_size=#{other.window_size}"
70
+ end
63
71
 
64
- def self.merge(buffers, average: false)
65
- if buffers.length==0
66
- raise Error, "argument is empty"
67
- elsif buffers.length==1
68
- return buffers.first.clone
72
+ channels = [self.channels, other.channels].max
73
+ case channels
74
+ when 1
75
+ stream0 = self.streams[0] + other.streams[0]
76
+ self.class.new(stream0)
77
+ when 2
78
+ st_self = self.stereo
79
+ st_other = other.stereo
80
+
81
+ stream0 = st_self.streams[0] + st_other.streams[0]
82
+ stream1 = st_self.streams[1] + st_other.streams[1]
83
+ self.class.new(stream0, stream1)
69
84
  end
85
+ end
70
86
 
87
+ def self.merge(buffers, average: false)
71
88
  buffers.each {|buf|
72
89
  unless Buffer===buf
73
90
  raise Error, "argument is not Buffer: #{buf}"
74
91
  end
75
- if buffers[0].window_size!=buf.window_size
76
- i = buffers.index(buf)
77
- raise Error, "Buffer.window_size is not match: buffers[0].window_size=#{buffers[0].window_size} buffers[#{i}].window_size=#{buf.window_size}"
78
- end
79
92
  }
80
93
 
81
- channels = buffers.map(&:channels).max
82
- window_size = buffers[0].window_size
83
- avg = average ? buffers.size.to_f : 1.0
94
+ if buffers.length==0
95
+ raise Error, "argument is empty"
96
+ elsif buffers.length==1
97
+ return buffers[0]
98
+ end
84
99
 
85
- case channels
86
- when 1
87
- result0 = Array.new(window_size, 0.0)
88
- buffers.each {|buf|
89
- buf.streams[0].each_with_index {|f, i|
90
- result0[i] += f / avg
91
- }
92
- }
93
- self.class.new(result0)
94
- when 2
95
- result0 = Array.new(window_size, 0.0)
96
- result1 = Array.new(window_size, 0.0)
97
- buffers.each {|buf|
98
- buf = buf.stereo
99
- src0 = buf.streams[0]
100
- src1 = buf.streams[1]
101
- window_size.times {|i|
102
- result0[i] += src0[i] / avg
103
- result1[i] += src1[i] / avg
104
- }
105
- }
106
- self.new(result0, result1)
100
+ dst = buffers.inject(:+)
101
+
102
+ if average
103
+ dst /= buffers.length.to_f
107
104
  end
105
+
106
+ dst
108
107
  end
109
108
 
110
109
  def plot
@@ -147,10 +146,10 @@ module AudioStream
147
146
 
148
147
  case channels
149
148
  when 1
150
- na[(0+offset)...(window_size+offset)] = @stream0
149
+ na[(0+offset)...(window_size+offset)] = @stream0.to_a
151
150
  when 2
152
- na[window_size.times.map{|i| i*2+offset}] = @stream0
153
- na[window_size.times.map{|i| i*2+1+offset}] = @stream1
151
+ na[window_size.times.map{|i| i*2+offset}] = @stream0.to_a
152
+ na[window_size.times.map{|i| i*2+1+offset}] = @stream1.to_a
154
153
  end
155
154
 
156
155
  na
@@ -175,12 +174,14 @@ module AudioStream
175
174
 
176
175
  case channels
177
176
  when 1
178
- window_size.times {|i|
179
- rabuf[i] = @stream0[i]
177
+ @stream0.each {|v|
178
+ rabuf[i] = v
180
179
  }
181
180
  when 2
181
+ stream0 = @stream0.to_a
182
+ stream1 = @stream1.to_a
182
183
  window_size.times {|i|
183
- rabuf[i] = [@stream0[i], @stream0[i]]
184
+ rabuf[i] = [stream0[i], stream1[i]]
184
185
  }
185
186
  end
186
187
 
@@ -197,13 +198,13 @@ module AudioStream
197
198
  end
198
199
 
199
200
  def self.create_mono(window_size)
200
- stream0 = Array.new(window_size, 0.0)
201
+ stream0 = Vdsp::DoubleArray.new(window_size)
201
202
  new(stream0)
202
203
  end
203
204
 
204
205
  def self.create_stereo(window_size)
205
- stream0 = Array.new(window_size, 0.0)
206
- stream1 = Array.new(window_size, 0.0)
206
+ stream0 = Vdsp::DoubleArray.new(window_size)
207
+ stream1 = Vdsp::DoubleArray.new(window_size)
207
208
  new(stream0, stream1)
208
209
  end
209
210
 
@@ -220,17 +221,17 @@ module AudioStream
220
221
 
221
222
  case channels
222
223
  when 1
223
- stream0 = Array.new(window_size, 0.0)
224
+ stream0 = []
224
225
  window_size.times {|i|
225
- stream0[i] = na[i].real / max
226
+ stream0 << na[i].real / max
226
227
  }
227
228
  self.new(stream0)
228
229
  when 2
229
- stream0 = Array.new(window_size, 0.0)
230
- stream1 = Array.new(window_size, 0.0)
230
+ stream0 = []
231
+ stream1 = []
231
232
  window_size.times {|i|
232
- stream0[i] = na[i*2].real / max
233
- stream1[i] = na[(i*2)+1].real / max
233
+ stream0 << na[i*2].real / max
234
+ stream1 << na[(i*2)+1].real / max
234
235
  }
235
236
  self.new(stream0, stream1)
236
237
  end
@@ -242,17 +243,14 @@ module AudioStream
242
243
 
243
244
  case channels
244
245
  when 1
245
- stream0 = Array.new(window_size, 0.0)
246
- rabuf.each_with_index {|f, i|
247
- stream0[i] = f
248
- }
246
+ stream0 = rabuf.to_a
249
247
  self.new(stream0)
250
248
  when 2
251
- stream0 = Array.new(window_size, 0.0)
252
- stream1 = Array.new(window_size, 0.0)
249
+ stream0 = []
250
+ stream1 = []
253
251
  rabuf.each_with_index {|fa, i|
254
- stream0[i] = fa[0]
255
- stream1[i] = fa[1]
252
+ stream0 << fa[0]
253
+ stream1 << fa[1]
256
254
  }
257
255
  self.new(stream0, stream1)
258
256
  end
@@ -9,9 +9,7 @@ module AudioStream
9
9
  return input if @level==1.0
10
10
 
11
11
  streams = input.streams.map {|stream|
12
- stream.map {|f|
13
- f * @level
14
- }
12
+ stream * @level
15
13
  }
16
14
  Buffer.new(*streams)
17
15
  end
@@ -13,7 +13,10 @@ module AudioStream
13
13
  b1 = 0.0
14
14
  b2 = -alpha
15
15
 
16
- @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
16
+ @coef = Vdsp::Biquad::Coefficient.new(b0/a0, b1/a0, b2/a0, a1/a0, a2/a0)
17
+ @biquads.each {|biquad|
18
+ biquad.coefficients = @coef
19
+ }
17
20
  end
18
21
 
19
22
  def self.create(soundinfo, freq:, bandwidth: 1.0)
@@ -1,23 +1,14 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class BiquadFilter
4
- FilterBuffer = Struct.new("FilterBuffer", :in1, :in2, :out1, :out2) do
5
- def self.create
6
- new(0.0, 0.0, 0.0, 0.0)
7
- end
8
- end
9
-
10
- FilterCoef = Struct.new("FilterCoef", :a0, :a1, :a2, :b0, :b1, :b2)
11
-
12
4
  DEFAULT_Q = 1.0 / Math.sqrt(2.0)
13
5
 
14
6
  def initialize(soundinfo)
15
7
  @samplerate = soundinfo.samplerate.to_f
16
- init_buffer
17
- end
18
-
19
- def init_buffer
20
- @filter_bufs = [FilterBuffer.create, FilterBuffer.create]
8
+ @biquads = [
9
+ Vdsp::DoubleBiquad.new(1),
10
+ Vdsp::DoubleBiquad.new(1),
11
+ ]
21
12
  end
22
13
 
23
14
  def update_coef(*args, **kwargs)
@@ -25,49 +16,25 @@ module AudioStream
25
16
  end
26
17
 
27
18
  def process(input)
28
- window_size = input.window_size
29
19
  channels = input.channels
30
20
 
31
- streams = input.streams.map.with_index {|stream, i|
32
- b = @filter_bufs[i]
33
- stream.map {|f|
34
- process_one(f, b)
35
- }
36
- }
37
- Buffer.new(*streams)
38
- end
39
-
40
- def process_mono(in0)
41
- process_one(in0, @filter_bufs[0])
42
- end
43
-
44
- def process_stereo(in0, in1)
45
- [
46
- process_one(in0, @filter_bufs[0]),
47
- process_one(in1, @filter_bufs[1])
48
- ]
49
- end
50
-
51
- def process_one(in0, b)
52
- c = @filter_coef
53
- out0 = c.b0/c.a0 * in0 + c.b1/c.a0 * b.in1 + c.b2/c.a0 * b.in2 - c.a1/c.a0 * b.out1 - c.a2/c.a0 * b.out2
54
-
55
- b.in2 = b.in1
56
- b.in1 = in0
57
- b.out2 = b.out1
58
- b.out1 = out0
59
-
60
- out0
21
+ case channels
22
+ when 1
23
+ dst0 = @biquads[0].apply(input.streams[0])
24
+ Buffer.new(dst0)
25
+ when 2
26
+ dst0 = @biquads[0].apply(input.streams[0])
27
+ dst1 = @biquads[1].apply(input.streams[1])
28
+ Buffer.new(dst0, dst1)
29
+ end
61
30
  end
62
31
 
63
32
  def plot_data(width=500)
64
- c = @filter_coef
65
-
66
- b0 = c.b0 / c.a0
67
- b1 = c.b1 / c.a0
68
- b2 = c.b2 / c.a0
69
- a1 = c.a1 / c.a0
70
- a2 = c.a2 / c.a0
33
+ b0 = @coef.b0
34
+ b1 = @coef.b1
35
+ b2 = @coef.b2
36
+ a1 = @coef.a1
37
+ a2 = @coef.a2
71
38
 
72
39
  noctaves = 10
73
40
  nyquist = @samplerate * 0.5
@@ -13,7 +13,10 @@ module AudioStream
13
13
  b1 = -(1.0 + Math.cos(omega))
14
14
  b2 = (1.0 + Math.cos(omega)) / 2.0
15
15
 
16
- @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
16
+ @coef = Vdsp::Biquad::Coefficient.new(b0/a0, b1/a0, b2/a0, a1/a0, a2/a0)
17
+ @biquads.each {|biquad|
18
+ biquad.coefficients = @coef
19
+ }
17
20
  end
18
21
 
19
22
  def self.create(soundinfo, freq:, q: DEFAULT_Q)
@@ -15,7 +15,10 @@ module AudioStream
15
15
  b1 = -2.0 * a * ((a-1) + (a+1) * Math.cos(omega))
16
16
  b2 = a * ((a+1) + (a-1) * Math.cos(omega) - beta * Math.sin(omega))
17
17
 
18
- @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
18
+ @coef = Vdsp::Biquad::Coefficient.new(b0/a0, b1/a0, b2/a0, a1/a0, a2/a0)
19
+ @biquads.each {|biquad|
20
+ biquad.coefficients = @coef
21
+ }
19
22
  end
20
23
 
21
24
  def self.create(soundinfo, freq:, q: DEFAULT_Q, gain: 1.0)
@@ -13,7 +13,10 @@ module AudioStream
13
13
  b1 = 1.0 - Math.cos(omega)
14
14
  b2 = (1.0 - Math.cos(omega)) / 2.0
15
15
 
16
- @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
16
+ @coef = Vdsp::Biquad::Coefficient.new(b0/a0, b1/a0, b2/a0, a1/a0, a2/a0)
17
+ @biquads.each {|biquad|
18
+ biquad.coefficients = @coef
19
+ }
17
20
  end
18
21
 
19
22
  def self.create(soundinfo, freq:, q: DEFAULT_Q)
@@ -15,7 +15,10 @@ module AudioStream
15
15
  b1 = 2.0 * a * ((a-1) - (a+1) * Math.cos(omega))
16
16
  b2 = a * ((a+1) - (a-1) * Math.cos(omega) - beta * Math.sin(omega))
17
17
 
18
- @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
18
+ @coef = Vdsp::Biquad::Coefficient.new(b0/a0, b1/a0, b2/a0, a1/a0, a2/a0)
19
+ @biquads.each {|biquad|
20
+ biquad.coefficients = @coef
21
+ }
19
22
  end
20
23
 
21
24
  def self.create(soundinfo, freq:, q: DEFAULT_Q, gain: 1.0)
@@ -4,43 +4,42 @@ module AudioStream
4
4
  def initialize(pan: 0.0)
5
5
  @pan = pan
6
6
 
7
- @l_gain = 1.0 - pan
8
- @lr_gain = 0.0
9
- if 1.0<@l_gain
10
- @lr_gain = @l_gain - 1.0
11
- @l_gain = 1.0
7
+ l_gain = 1.0 - pan
8
+ lr_gain = 0.0
9
+ if 1.0<l_gain
10
+ lr_gain = l_gain - 1.0
11
+ l_gain = 1.0
12
12
  end
13
13
 
14
- @r_gain = 1.0 + pan
15
- @rl_gain = 0.0
16
- if 1.0<@r_gain
17
- @rl_gain = @r_gain - 1.0
18
- @r_gain = 1.0
14
+ r_gain = 1.0 + pan
15
+ rl_gain = 0.0
16
+ if 1.0<r_gain
17
+ rl_gain = r_gain - 1.0
18
+ r_gain = 1.0
19
19
  end
20
20
 
21
- @normalize = [1.0 - pan, 1.0 + pan].max
21
+ normalize = [1.0 - pan, 1.0 + pan].max
22
+
23
+ @r_gain = r_gain / normalize
24
+ @rl_gain = rl_gain / normalize
25
+ @l_gain = l_gain / normalize
26
+ @lr_gain = lr_gain / normalize
22
27
  end
23
28
 
24
29
  def process(input)
25
30
  return input if @pan==0.0
26
31
 
27
- input = input.stereo
28
- src = input.streams
32
+ src = input.stereo.streams
29
33
  src0 = src[0]
30
34
  src1 = src[1]
31
35
 
32
- output = Buffer.create_stereo(input.window_size)
33
- dst = output.streams
34
- dst0 = dst[0]
35
- dst1 = dst[1]
36
-
37
- input.window_size.times {|i|
38
- l = (src0[i] * @l_gain + src1[i] * @lr_gain) / @normalize
39
- r = (src1[i] * @r_gain + src0[i] * @rl_gain) / @normalize
40
- dst0[i] = l
41
- dst1[i] = r
42
- }
43
- output
36
+ dst0 = Vdsp::DoubleArray.new(src0.length)
37
+ Vdsp::UnsafeDouble.vsmsma(src0, 0, 1, @l_gain, src1, 0, 1, @lr_gain, dst0, 0, 1, src0.length)
38
+
39
+ dst1 = Vdsp::DoubleArray.new(src1.length)
40
+ Vdsp::UnsafeDouble.vsmsma(src0, 0, 1, @rl_gain, src1, 0, 1, @r_gain, dst1, 0, 1, src1.length)
41
+
42
+ Buffer.new(dst0, dst1)
44
43
  end
45
44
  end
46
45
  end
@@ -14,7 +14,10 @@ module AudioStream
14
14
  b1 = -2.0 * Math.cos(omega)
15
15
  b2 = 1.0 - alpha * a
16
16
 
17
- @filter_coef = FilterCoef.new(a0, a1, a2, b0, b1, b2)
17
+ @coef = Vdsp::Biquad::Coefficient.new(b0/a0, b1/a0, b2/a0, a1/a0, a2/a0)
18
+ @biquads.each {|biquad|
19
+ biquad.coefficients = @coef
20
+ }
18
21
  end
19
22
 
20
23
  def self.create(soundinfo, freq:, bandwidth: 1.0, gain: 40.0)
@@ -1,3 +1,3 @@
1
1
  module AudioStream
2
- VERSION = "2.0.0"
2
+ VERSION = "3.0.0"
3
3
  end
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: 2.0.0
4
+ version: 3.0.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-08-11 00:00:00.000000000 Z
11
+ date: 2019-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: vdsp
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.6.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.6.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: ruby-audio
57
71
  requirement: !ruby/object:Gem::Requirement