audio_stream 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcfa4c84415b2d3fce58e09f86e7f7ed93fc6bf57e302580b8b629fea6b98ed9
4
- data.tar.gz: 5e29c910eddfed09ffe952b6e3ab5cfd75f79dfe1072681bfb10ca3a720195d5
3
+ metadata.gz: e0dd181cb0224f6603451bf72f635deaa9d406ba76f8e587de6b512f1483a1c0
4
+ data.tar.gz: b38c9e486e71646a7db650e1c8731d1cb4d8078f7e788bda1897c3ca89334d2d
5
5
  SHA512:
6
- metadata.gz: 3a812266f92786ab35b68ad6b731020525afda6a0d3dfccda2e47ac466696ec30cdaf82475d0bf0fbda15d7527d9f001ea1d98ef0e6ce8d23769a01f966008c9
7
- data.tar.gz: be4a1e89411f6d0d881119750508d50d7099fe2d8c046fb24f6323520ab065d4469b67a9983460f8138b463fc6f5023a67376cb7a38860fcc849b59e9249353d
6
+ metadata.gz: 8d5a04e5334b1786b16578cdca72bb0f9b296453d7293f61700ebb6447c102d7cbe0509b41505edeaff0bdbcd00382bf2a10e7dcb92bd4033e6df76b48d89e27
7
+ data.tar.gz: f013bc564ea68724eae776ba5c37244d0167617bbd42032cfa0399e3a03e0e6a6c089d41aaf6de42e8d440204cb5bf5b340b6ddba3b4ae0428ea4181371f7d86
@@ -30,7 +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
+ spec.add_dependency "vdsp", ">= 1.10.0"
34
34
  spec.add_dependency "ruby-audio", ">= 1.6.1"
35
35
  spec.add_dependency "coreaudio", ">= 0.0.12"
36
36
  spec.add_dependency "ruby-fftw3", ">= 1.0.2"
@@ -17,6 +17,12 @@ module AudioStream
17
17
  end
18
18
 
19
19
  def on_next(input)
20
+ case @soundinfo.channels
21
+ when 1
22
+ input = input.mono
23
+ when 2
24
+ input = input.stereo
25
+ end
20
26
  @sound.write(input.to_rabuffer)
21
27
  end
22
28
 
@@ -100,7 +100,8 @@ module AudioStream
100
100
  dst = buffers.inject(:+)
101
101
 
102
102
  if average
103
- dst /= buffers.length.to_f
103
+ gain = AGain.new(level: 1.0/buffers.length)
104
+ dst = gain.process(dst)
104
105
  end
105
106
 
106
107
  dst
@@ -174,7 +175,7 @@ module AudioStream
174
175
 
175
176
  case channels
176
177
  when 1
177
- @stream0.each {|v|
178
+ @stream0.each_with_index {|v, i|
178
179
  rabuf[i] = v
179
180
  }
180
181
  when 2
@@ -12,13 +12,17 @@ require 'audio_stream/fx/band_pass_filter'
12
12
  require 'audio_stream/fx/low_shelf_filter'
13
13
  require 'audio_stream/fx/high_shelf_filter'
14
14
  require 'audio_stream/fx/peaking_filter'
15
+ require 'audio_stream/fx/all_pass_filter'
15
16
  require 'audio_stream/fx/equalizer_2band'
16
17
  require 'audio_stream/fx/equalizer_3band'
17
18
  require 'audio_stream/fx/graphic_equalizer'
18
19
  require 'audio_stream/fx/tremolo'
19
20
  require 'audio_stream/fx/delay'
20
21
  require 'audio_stream/fx/chorus'
22
+ require 'audio_stream/fx/phaser'
21
23
  require 'audio_stream/fx/convolution_reverb'
24
+ require 'audio_stream/fx/comb_filter'
25
+ require 'audio_stream/fx/schroeder_reverb'
22
26
  require 'audio_stream/fx/hanning_window'
23
27
 
24
28
  require 'audio_stream/fx/tuner'
@@ -0,0 +1,30 @@
1
+ module AudioStream
2
+ module Fx
3
+ class AllPassFilter < BiquadFilter
4
+
5
+ def update_coef(freq:, q:)
6
+ omega = 2.0 * Math::PI * freq / @samplerate
7
+ alpha = Math.sin(omega) / (2.0 * q)
8
+
9
+ a0 = 1.0 + alpha
10
+ a1 = -2.0 * Math.cos(omega)
11
+ a2 = 1.0 - alpha
12
+ b0 = 1.0 - alpha
13
+ b1 = -2.0 * Math.cos(omega)
14
+ b2 = 1.0 + alpha
15
+
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
+ }
20
+ end
21
+
22
+ def self.create(soundinfo, freq:, q: DEFAULT_Q)
23
+ filter = new(soundinfo)
24
+ filter.update_coef(freq: freq, q: q)
25
+
26
+ filter
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ module AudioStream
2
+ module Fx
3
+ class CombFilter
4
+
5
+ def initialize(soundinfo, freq:, q:)
6
+ @window_size = soundinfo.window_size
7
+ @samplerate = soundinfo.samplerate
8
+ @delaysample = (soundinfo.samplerate.to_f / freq).round
9
+ @q = q
10
+
11
+ @delaybufs = [
12
+ Vdsp::DoubleArray.new(soundinfo.window_size + @delaysample),
13
+ Vdsp::DoubleArray.new(soundinfo.window_size + @delaysample),
14
+ ]
15
+ end
16
+
17
+ def process(input)
18
+ window_size = input.window_size
19
+ if @window_size!=window_size
20
+ raise "window size is not match: impulse.size=#{@window_size} input.size=#{window_size}"
21
+ end
22
+
23
+ streams = input.streams.map.with_index {|src, i|
24
+ buf = @delaybufs[i]
25
+
26
+ Vdsp::UnsafeDouble.copy(buf, window_size, 1, buf, 0, 1, @delaysample)
27
+ if @delaysample<window_size
28
+ Vdsp::UnsafeDouble.vclr(buf, window_size, 1, @delaysample)
29
+ end
30
+ Vdsp::UnsafeDouble.vsmsma(src, 0, 1, 1.0, buf, 0, 1, @q, buf, @delaysample, 1, window_size)
31
+ dst = buf[@delaysample, window_size]
32
+
33
+ dst
34
+ }
35
+
36
+ Buffer.new(*streams)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -9,14 +9,19 @@ module AudioStream
9
9
 
10
10
  def process(input)
11
11
  streams = input.streams.map {|stream|
12
- stream.map {|f|
13
- sign = f.negative? ? -1 : 1
14
- f = f.abs
15
- if @threshold<f
16
- f = (f - @threshold) * @ratio + @threshold
17
- end
18
- @zoom * f * sign
19
- }
12
+ sign = Vdsp::DoubleArray.new(input.window_size)
13
+ Vdsp::UnsafeDouble.vlim(stream, 0, 1, 0.0, @zoom, sign, 0, 1, input.window_size)
14
+
15
+ abs = stream.abs
16
+
17
+ under = Vdsp::DoubleArray.new(input.window_size)
18
+ Vdsp::UnsafeDouble.vclip(abs, 0, 1, 0.0, @threshold, under, 0, 1, input.window_size)
19
+
20
+ over = Vdsp::DoubleArray.new(input.window_size)
21
+ Vdsp::UnsafeDouble.vthr(abs, 0, 1, @threshold, over, 0, 1, input.window_size)
22
+ over = (over - @threshold) * @ratio
23
+
24
+ (under + over) * sign
20
25
  }
21
26
  Buffer.new(*streams)
22
27
  end
@@ -8,15 +8,9 @@ module AudioStream
8
8
 
9
9
  def process(input)
10
10
  streams = input.streams.map {|stream|
11
- stream.map {|f|
12
- val = f * @gain
13
- if 1.0 < val
14
- val = 1.0
15
- elsif val < -1.0
16
- val = -1.0
17
- end
18
- val * @level
19
- }
11
+ dst = Vdsp::DoubleArray.new(input.window_size)
12
+ Vdsp::UnsafeDouble.vclip(stream * @gain, 0, 1, -1.0, 1.0, dst, 0, 1, input.window_size)
13
+ dst * @level
20
14
  }
21
15
  Buffer.new(*streams)
22
16
  end
@@ -4,20 +4,26 @@ module AudioStream
4
4
  include Singleton
5
5
 
6
6
  def process(input)
7
- window_size = input.window_size
8
- window_max = input.window_size - 1
9
- channels = input.channels
7
+ #window_size = input.window_size
8
+ #window_max = input.window_size - 1
9
+ #channels = input.channels
10
10
 
11
- period = 2 * Math::PI / window_max
11
+ #period = 2 * Math::PI / window_max
12
12
 
13
13
  streams = input.streams.map {|stream|
14
- stream.map.with_index {|f, i|
15
- f * (0.5 - 0.5 * Math.cos(i * period))
16
- }
14
+ #stream.map.with_index {|f, i|
15
+ # f * (0.5 - 0.5 * Math.cos(i * period))
16
+ #}
17
+ stream * self.window(input.window_size)
17
18
  }
18
19
 
19
20
  Buffer.new(*streams)
20
21
  end
22
+
23
+ def window(size)
24
+ @window ||= {}
25
+ @window[size] ||= Vdsp::DoubleArray.hann_window(size, Vdsp::FULL_WINDOW)
26
+ end
21
27
  end
22
28
  end
23
29
  end
@@ -0,0 +1,45 @@
1
+ module AudioStream
2
+ module Fx
3
+ class Phaser
4
+
5
+ def initialize(soundinfo, rate:, depth:, freq:, dry: 0.5, wet: 0.5)
6
+ @soundinfo = soundinfo
7
+
8
+ @filters = [
9
+ AllPassFilter.new(soundinfo),
10
+ AllPassFilter.new(soundinfo),
11
+ ]
12
+
13
+ @speed = 2.0 * Math::PI * rate / @soundinfo.samplerate
14
+ @phase = 0
15
+
16
+ @depth = depth
17
+ @freq = freq
18
+
19
+ @dry = dry
20
+ @wet = wet
21
+ end
22
+
23
+ def process(input)
24
+ window_size = input.window_size
25
+ @phase = (@phase + @speed * window_size) % (window_size / @speed)
26
+
27
+ a = Math.sin(@phase) * 0.5 + 0.5
28
+ apf_freq = @freq * (1.0 + a * @depth)
29
+
30
+ wet = input
31
+ @filters.each {|filter|
32
+ filter.update_coef(freq: apf_freq, q: BiquadFilter::DEFAULT_Q)
33
+ wet = filter.process(wet)
34
+ }
35
+
36
+ streams = wet.streams.map.with_index {|wet_stream, i|
37
+ dry_stream = input.streams[i]
38
+ dry_stream * @dry + wet_stream * @wet
39
+ }
40
+
41
+ Buffer.new(*streams)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,52 @@
1
+ module AudioStream
2
+ module Fx
3
+ class SchroederReverb
4
+
5
+ def initialize(soundinfo, time:, dry: 1.0, wet: 0.7)
6
+ @window_size = soundinfo.window_size
7
+ @combs = [
8
+ CombFilter.new(soundinfo, freq: ms2freq(39.85 / 2.0 * time), q: 0.871402),
9
+ CombFilter.new(soundinfo, freq: ms2freq(36.10 / 2.0 * time), q: 0.882762),
10
+ CombFilter.new(soundinfo, freq: ms2freq(33.27 / 2.0 * time), q: 0.891443),
11
+ CombFilter.new(soundinfo, freq: ms2freq(30.15 / 2.0 * time), q: 0.901117),
12
+ ]
13
+ @allpasss = [
14
+ AllPassFilter.create(soundinfo, freq: ms2freq(5.0), q: 0.7),
15
+ AllPassFilter.create(soundinfo, freq: ms2freq(1.7), q: 0.7),
16
+ ]
17
+
18
+ @dry = dry.to_f
19
+ @wet = wet.to_f
20
+ end
21
+
22
+ def process(input)
23
+ window_size = input.window_size
24
+ if @window_size!=window_size
25
+ raise "window size is not match: impulse.size=#{@window_size} input.size=#{window_size}"
26
+ end
27
+
28
+ wets = @combs.map {|comb|
29
+ comb.process(input)
30
+ }
31
+ wet = Buffer.merge(wets, average: true)
32
+
33
+ @allpasss.each {|allpass|
34
+ wet = allpass.process(wet)
35
+ }
36
+
37
+ streams = wet.streams.map.with_index {|wet_stream, i|
38
+ dry_stream = input.streams[i]
39
+ dst = Vdsp::DoubleArray.new(window_size)
40
+ Vdsp::UnsafeDouble.vsmsma(dry_stream, 0, 1, @dry, wet_stream, 0, 1, @wet, dst, 0, 1, window_size)
41
+ dst
42
+ }
43
+
44
+ Buffer.new(*streams)
45
+ end
46
+
47
+ def ms2freq(ms)
48
+ 1.0 / (ms / 1000.0)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module AudioStream
2
- VERSION = "3.0.1"
2
+ VERSION = "3.1.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: 3.0.1
4
+ version: 3.1.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-10-04 00:00:00.000000000 Z
11
+ date: 2019-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 1.6.0
61
+ version: 1.10.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 1.6.0
68
+ version: 1.10.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ruby-audio
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -168,10 +168,12 @@ files:
168
168
  - lib/audio_stream/error.rb
169
169
  - lib/audio_stream/fx.rb
170
170
  - lib/audio_stream/fx/a_gain.rb
171
+ - lib/audio_stream/fx/all_pass_filter.rb
171
172
  - lib/audio_stream/fx/band_pass_filter.rb
172
173
  - lib/audio_stream/fx/bang_process.rb
173
174
  - lib/audio_stream/fx/biquad_filter.rb
174
175
  - lib/audio_stream/fx/chorus.rb
176
+ - lib/audio_stream/fx/comb_filter.rb
175
177
  - lib/audio_stream/fx/compressor.rb
176
178
  - lib/audio_stream/fx/convolution_reverb.rb
177
179
  - lib/audio_stream/fx/delay.rb
@@ -187,6 +189,8 @@ files:
187
189
  - lib/audio_stream/fx/noise_gate.rb
188
190
  - lib/audio_stream/fx/panning.rb
189
191
  - lib/audio_stream/fx/peaking_filter.rb
192
+ - lib/audio_stream/fx/phaser.rb
193
+ - lib/audio_stream/fx/schroeder_reverb.rb
190
194
  - lib/audio_stream/fx/tremolo.rb
191
195
  - lib/audio_stream/fx/tuner.rb
192
196
  - lib/audio_stream/ring_buffer.rb