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 +4 -4
- data/audio_stream.gemspec +1 -1
- data/lib/audio_stream/audio_output_file.rb +6 -0
- data/lib/audio_stream/buffer.rb +3 -2
- data/lib/audio_stream/fx.rb +4 -0
- data/lib/audio_stream/fx/all_pass_filter.rb +30 -0
- data/lib/audio_stream/fx/comb_filter.rb +40 -0
- data/lib/audio_stream/fx/compressor.rb +13 -8
- data/lib/audio_stream/fx/distortion.rb +3 -9
- data/lib/audio_stream/fx/hanning_window.rb +13 -7
- data/lib/audio_stream/fx/phaser.rb +45 -0
- data/lib/audio_stream/fx/schroeder_reverb.rb +52 -0
- data/lib/audio_stream/version.rb +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0dd181cb0224f6603451bf72f635deaa9d406ba76f8e587de6b512f1483a1c0
|
4
|
+
data.tar.gz: b38c9e486e71646a7db650e1c8731d1cb4d8078f7e788bda1897c3ca89334d2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d5a04e5334b1786b16578cdca72bb0f9b296453d7293f61700ebb6447c102d7cbe0509b41505edeaff0bdbcd00382bf2a10e7dcb92bd4033e6df76b48d89e27
|
7
|
+
data.tar.gz: f013bc564ea68724eae776ba5c37244d0167617bbd42032cfa0399e3a03e0e6a6c089d41aaf6de42e8d440204cb5bf5b340b6ddba3b4ae0428ea4181371f7d86
|
data/audio_stream.gemspec
CHANGED
@@ -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.
|
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"
|
data/lib/audio_stream/buffer.rb
CHANGED
@@ -100,7 +100,8 @@ module AudioStream
|
|
100
100
|
dst = buffers.inject(:+)
|
101
101
|
|
102
102
|
if average
|
103
|
-
|
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.
|
178
|
+
@stream0.each_with_index {|v, i|
|
178
179
|
rabuf[i] = v
|
179
180
|
}
|
180
181
|
when 2
|
data/lib/audio_stream/fx.rb
CHANGED
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
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
|
data/lib/audio_stream/version.rb
CHANGED
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
|
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-
|
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.
|
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.
|
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
|