audio_stream 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/examples/bench_fx.rb +89 -0
  4. data/examples/canon.wav +0 -0
  5. data/examples/example_options.rb +2 -0
  6. data/examples/{chorus.rb → fx_chorus.rb} +2 -7
  7. data/examples/fx_compressor.rb +34 -0
  8. data/examples/fx_convolution_reverb.rb +37 -0
  9. data/examples/fx_delay.rb +33 -0
  10. data/examples/{distortion.rb → fx_distortion.rb} +4 -8
  11. data/examples/fx_noise_gate.rb +33 -0
  12. data/examples/fx_phaser.rb +36 -0
  13. data/examples/fx_schroeder_reverb.rb +34 -0
  14. data/examples/fx_vocoder.rb +44 -0
  15. data/examples/impulse_shaker.wav +0 -0
  16. data/examples/impulse_shaker_bigroom.wav +0 -0
  17. data/examples/impulse_shaker_smallhall.wav +0 -0
  18. data/examples/tuner.rb +4 -3
  19. data/jupyter/band_pass_filter.ipynb +117 -0
  20. data/jupyter/biquad.ipynb +372 -0
  21. data/jupyter/equalizer.ipynb +198 -0
  22. data/lib/audio_stream/audio_input_device.rb +20 -3
  23. data/lib/audio_stream/audio_observable.rb +5 -0
  24. data/lib/audio_stream/audio_output_device.rb +20 -3
  25. data/lib/audio_stream/buffer.rb +22 -0
  26. data/lib/audio_stream/decibel.rb +8 -8
  27. data/lib/audio_stream/fx/a_gain.rb +2 -6
  28. data/lib/audio_stream/fx/all_pass_filter.rb +4 -2
  29. data/lib/audio_stream/fx/band_pass_filter.rb +4 -2
  30. data/lib/audio_stream/fx/biquad_filter.rb +8 -3
  31. data/lib/audio_stream/fx/chorus.rb +6 -5
  32. data/lib/audio_stream/fx/comb_filter.rb +4 -2
  33. data/lib/audio_stream/fx/convolution_reverb.rb +8 -5
  34. data/lib/audio_stream/fx/delay.rb +6 -5
  35. data/lib/audio_stream/fx/distortion.rb +4 -4
  36. data/lib/audio_stream/fx/equalizer_2band.rb +5 -3
  37. data/lib/audio_stream/fx/equalizer_3band.rb +7 -0
  38. data/lib/audio_stream/fx/graphic_equalizer.rb +4 -0
  39. data/lib/audio_stream/fx/hanning_window.rb +0 -9
  40. data/lib/audio_stream/fx/high_pass_filter.rb +4 -2
  41. data/lib/audio_stream/fx/high_shelf_filter.rb +6 -7
  42. data/lib/audio_stream/fx/low_pass_filter.rb +4 -2
  43. data/lib/audio_stream/fx/low_shelf_filter.rb +6 -7
  44. data/lib/audio_stream/fx/noise_gate.rb +5 -4
  45. data/lib/audio_stream/fx/panning.rb +2 -1
  46. data/lib/audio_stream/fx/peaking_filter.rb +6 -7
  47. data/lib/audio_stream/fx/phaser.rb +7 -6
  48. data/lib/audio_stream/fx/schroeder_reverb.rb +12 -13
  49. data/lib/audio_stream/fx/tremolo.rb +7 -5
  50. data/lib/audio_stream/rate.rb +89 -38
  51. data/lib/audio_stream/version.rb +1 -1
  52. metadata +23 -10
  53. data/examples/biquad.ipynb +0 -428
  54. data/examples/equalizer.ipynb +0 -233
@@ -2,21 +2,24 @@ module AudioStream
2
2
  module Fx
3
3
  class SchroederReverb
4
4
 
5
- def initialize(soundinfo, time:, dry: 1.0, wet: 0.7)
5
+ # @param soundinfo [AudioStream::SoundInfo]
6
+ # @param dry [AudioStream::Decibel | Float] dry gain
7
+ # @param wet [AudioStream::Decibel | Float] wet gain
8
+ def initialize(soundinfo, dry: -1.0, wet: -20.0)
6
9
  @window_size = soundinfo.window_size
7
10
  @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),
11
+ CombFilter.new(soundinfo, freq: Rate.msec(39.85), q: 0.871402),
12
+ CombFilter.new(soundinfo, freq: Rate.msec(36.10), q: 0.882762),
13
+ CombFilter.new(soundinfo, freq: Rate.msec(33.27), q: 0.891443),
14
+ CombFilter.new(soundinfo, freq: Rate.msec(30.15), q: 0.901117),
12
15
  ]
13
16
  @allpasss = [
14
- AllPassFilter.create(soundinfo, freq: ms2freq(5.0), q: 0.7),
15
- AllPassFilter.create(soundinfo, freq: ms2freq(1.7), q: 0.7),
17
+ AllPassFilter.create(soundinfo, freq: Rate.msec(5.0).freq(soundinfo), q: BiquadFilter::DEFAULT_Q),
18
+ AllPassFilter.create(soundinfo, freq: Rate.msec(1.7).freq(soundinfo), q: BiquadFilter::DEFAULT_Q),
16
19
  ]
17
20
 
18
- @dry = dry.to_f
19
- @wet = wet.to_f
21
+ @dry = Decibel.db(dry).mag
22
+ @wet = Decibel.db(wet).mag
20
23
  end
21
24
 
22
25
  def process(input)
@@ -43,10 +46,6 @@ module AudioStream
43
46
 
44
47
  Buffer.new(*streams)
45
48
  end
46
-
47
- def ms2freq(ms)
48
- 1.0 / (ms / 1000.0)
49
- end
50
49
  end
51
50
  end
52
51
  end
@@ -1,23 +1,25 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class Tremolo
4
+ # @param soundinfo [AudioStream::SoundInfo]
5
+ # @param freq [AudioStream::Rate | Float] Tremolo speed (0.0~)
6
+ # @param depth [Float] Tremolo depth (0.0~)
4
7
  def initialize(soundinfo, freq:, depth:)
5
- @samplerate = soundinfo.samplerate
6
- @freq = freq.to_f
8
+ @freq = Rate.freq(freq)
7
9
  @depth = depth.to_f
8
10
  @phase = 0
11
+ @period = @freq.sample_phase(soundinfo)
9
12
  end
10
13
 
11
14
  def process(input)
12
15
  window_size = input.window_size
13
- period = 2 * Math::PI * @freq / @samplerate
14
16
 
15
17
  streams = input.streams.map {|stream|
16
18
  stream.map.with_index {|f, i|
17
- f * (1.0 + @depth * Math.sin((i + @phase) * period))
19
+ f * (1.0 + @depth * Math.sin((i + @phase) * @period))
18
20
  }
19
21
  }
20
- @phase = (@phase + window_size) % (window_size / period)
22
+ @phase = (@phase + window_size) % (window_size / @period)
21
23
 
22
24
  Buffer.new(*streams)
23
25
  end
@@ -8,6 +8,7 @@ module AudioStream
8
8
  end
9
9
 
10
10
  def sec(soundinfo)
11
+ return @sec if @sec
11
12
  sample(soundinfo).to_f / soundinfo.samplerate
12
13
  end
13
14
 
@@ -33,6 +34,11 @@ module AudioStream
33
34
  end
34
35
  end
35
36
 
37
+ def freq(soundinfo)
38
+ return @freq if @freq
39
+ soundinfo.samplerate.to_f / sample(soundinfo)
40
+ end
41
+
36
42
  def frame_phase(soundinfo)
37
43
  sample_phase(soundinfo) * soundinfo.window_size
38
44
  end
@@ -41,58 +47,103 @@ module AudioStream
41
47
  2.0 * Math::PI / sample(soundinfo)
42
48
  end
43
49
 
50
+ def add(other, soundinfo)
51
+ other = self.class.sec(other)
52
+ self.class.new(sec: self.sec(soundinfo) + other.sec(soundinfo))
53
+ end
54
+
55
+ def *(other)
56
+ other = other.to_f
57
+
58
+ if @sample
59
+ return self.class.new(sample: @sample * other)
60
+ end
61
+
62
+ if @sec
63
+ return self.class.new(sec: @sec * other)
64
+ end
65
+
66
+ if @freq
67
+ return self.class.new(freq: @freq / other)
68
+ end
69
+
70
+ if @sync
71
+ return self.class.new(sync: @sync * other)
72
+ end
73
+ end
74
+
44
75
  def self.sec(v)
45
- new(sec: v)
76
+ if self===v
77
+ v
78
+ else
79
+ new(sec: v)
80
+ end
46
81
  end
47
82
 
48
- def self.millisec(v)
49
- new(sec: v*0.001)
83
+ def self.msec(v)
84
+ if self===v
85
+ v
86
+ else
87
+ new(sec: v*0.001)
88
+ end
50
89
  end
51
90
 
52
91
  def self.sample(v)
53
- new(sample: v)
92
+ if self===v
93
+ v
94
+ else
95
+ new(sample: v)
96
+ end
54
97
  end
55
98
 
56
99
  def self.freq(v)
57
- new(freq: v)
100
+ if self===v
101
+ v
102
+ else
103
+ new(freq: v)
104
+ end
58
105
  end
59
106
 
60
107
  def self.sync(v)
61
- new(sync: v)
108
+ if self===v
109
+ v
110
+ else
111
+ new(sync: v)
112
+ end
62
113
  end
63
114
 
64
115
 
65
- SYNC_64 = sync(480 * 64)
66
- SYNC_32 = sync(480 * 32)
67
- SYNC_16 = sync(480 * 16)
68
- SYNC_8 = sync(480 * 8)
69
- SYNC_6 = sync(480 * 6)
70
- SYNC_4 = sync(480 * 4)
71
- SYNC_3 = sync(480 * 3)
72
- SYNC_2 = sync(480 * 2)
73
- SYNC_7_4 = sync(480 * 7 / 4)
74
- SYNC_6_4 = sync(480 * 6 / 4)
75
- SYNC_5_4 = sync(480 * 5 / 4)
76
- SYNC_1 = sync(480 * 1)
77
- SYNC_3_4 = sync(480 * 3 / 4)
78
- SYNC_1_2 = sync(480 * 1 / 2)
79
- SYNC_1_4D = sync(480 * 1 / 4 * 3 / 2)
80
- SYNC_1_4 = sync(480 * 1 / 4)
81
- SYNC_1_4T = sync(480 * 1 / 4 * 2 / 3)
82
- SYNC_1_8D = sync(480 * 1 / 8 * 3 / 2)
83
- SYNC_1_8 = sync(480 * 1 / 8)
84
- SYNC_1_8T = sync(480 * 1 / 8 * 2 / 3)
85
- SYNC_1_16D = sync(480 * 1 / 16 * 3 / 2)
86
- SYNC_1_16 = sync(480 * 1 / 16)
87
- SYNC_1_16T = sync(480 * 1 / 16 * 2 / 3)
88
- SYNC_1_32D = sync(480 * 1 / 32 * 3 / 2)
89
- SYNC_1_32 = sync(480 * 1 / 32)
90
- SYNC_1_32T = sync(480 * 1 / 32 * 2 / 3)
91
- SYNC_1_64D = sync(480 * 1 / 64 * 3 / 2)
92
- SYNC_1_64 = sync(480 * 1 / 64)
93
- SYNC_1_64T = sync(480 * 1 / 64 * 2 / 3)
94
- SYNC_1_128D = sync(480 * 1 / 128 * 3 / 2)
95
- SYNC_1_128 = sync(480 * 1 / 128)
96
- SYNC_1_128T = sync(480 * 1 / 128 * 2 / 3)
116
+ SYNC_64 = sync(480 * 4 * 64)
117
+ SYNC_32 = sync(480 * 4 * 32)
118
+ SYNC_16 = sync(480 * 4 * 16)
119
+ SYNC_8 = sync(480 * 4 * 8)
120
+ SYNC_6 = sync(480 * 4 * 6)
121
+ SYNC_4 = sync(480 * 4 * 4)
122
+ SYNC_3 = sync(480 * 4 * 3)
123
+ SYNC_2 = sync(480 * 4 * 2)
124
+ SYNC_7_4 = sync(480 * 4 * 7 / 4)
125
+ SYNC_6_4 = sync(480 * 4 * 6 / 4)
126
+ SYNC_5_4 = sync(480 * 4 * 5 / 4)
127
+ SYNC_1 = sync(480 * 4 * 1)
128
+ SYNC_3_4 = sync(480 * 4 * 3 / 4)
129
+ SYNC_1_2 = sync(480 * 4 * 1 / 2)
130
+ SYNC_1_4D = sync(480 * 4 * 1 / 4 * 3 / 2)
131
+ SYNC_1_4 = sync(480 * 4 * 1 / 4)
132
+ SYNC_1_4T = sync(480 * 4 * 1 / 4 * 2 / 3)
133
+ SYNC_1_8D = sync(480 * 4 * 1 / 8 * 3 / 2)
134
+ SYNC_1_8 = sync(480 * 4 * 1 / 8)
135
+ SYNC_1_8T = sync(480 * 4 * 1 / 8 * 2 / 3)
136
+ SYNC_1_16D = sync(480 * 4 * 1 / 16 * 3 / 2)
137
+ SYNC_1_16 = sync(480 * 4 * 1 / 16)
138
+ SYNC_1_16T = sync(480 * 4 * 1 / 16 * 2 / 3)
139
+ SYNC_1_32D = sync(480 * 4 * 1 / 32 * 3 / 2)
140
+ SYNC_1_32 = sync(480 * 4 * 1 / 32)
141
+ SYNC_1_32T = sync(480 * 4 * 1 / 32 * 2 / 3)
142
+ SYNC_1_64D = sync(480 * 4 * 1 / 64 * 3 / 2)
143
+ SYNC_1_64 = sync(480 * 4 * 1 / 64)
144
+ SYNC_1_64T = sync(480 * 4 * 1 / 64 * 2 / 3)
145
+ SYNC_1_128D = sync(480 * 4 * 1 / 128 * 3 / 2)
146
+ SYNC_1_128 = sync(480 * 4 * 1 / 128)
147
+ SYNC_1_128T = sync(480 * 4 * 1 / 128 * 2 / 3)
97
148
  end
98
149
  end
@@ -1,3 +1,3 @@
1
1
  module AudioStream
2
- VERSION = "3.3.0"
2
+ VERSION = "3.4.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.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshida Tetsuya
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-02 00:00:00.000000000 Z
11
+ date: 2021-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -138,15 +138,28 @@ files:
138
138
  - audio_stream.gemspec
139
139
  - bin/console
140
140
  - bin/setup
141
- - examples/biquad.ipynb
142
- - examples/chorus.rb
143
- - examples/distortion.rb
144
- - examples/equalizer.ipynb
141
+ - examples/bench_fx.rb
142
+ - examples/canon.wav
145
143
  - examples/example_options.rb
144
+ - examples/fx_chorus.rb
145
+ - examples/fx_compressor.rb
146
+ - examples/fx_convolution_reverb.rb
147
+ - examples/fx_delay.rb
148
+ - examples/fx_distortion.rb
149
+ - examples/fx_noise_gate.rb
150
+ - examples/fx_phaser.rb
151
+ - examples/fx_schroeder_reverb.rb
152
+ - examples/fx_vocoder.rb
153
+ - examples/impulse_shaker.wav
154
+ - examples/impulse_shaker_bigroom.wav
155
+ - examples/impulse_shaker_smallhall.wav
146
156
  - examples/lpf.rb
147
157
  - examples/rec.rb
148
158
  - examples/tremolo.rb
149
159
  - examples/tuner.rb
160
+ - jupyter/band_pass_filter.ipynb
161
+ - jupyter/biquad.ipynb
162
+ - jupyter/equalizer.ipynb
150
163
  - lib/audio_stream.rb
151
164
  - lib/audio_stream/audio_bus.rb
152
165
  - lib/audio_stream/audio_input.rb
@@ -208,7 +221,7 @@ metadata:
208
221
  homepage_uri: https://github.com/yoshida-eth0/ruby-audio_stream
209
222
  source_code_uri: https://github.com/yoshida-eth0/ruby-audio_stream
210
223
  changelog_uri: https://github.com/yoshida-eth0/ruby-audio_stream
211
- post_install_message:
224
+ post_install_message:
212
225
  rdoc_options: []
213
226
  require_paths:
214
227
  - lib
@@ -223,8 +236,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
236
  - !ruby/object:Gem::Version
224
237
  version: '0'
225
238
  requirements: []
226
- rubygems_version: 3.0.3
227
- signing_key:
239
+ rubygems_version: 3.2.3
240
+ signing_key:
228
241
  specification_version: 4
229
242
  summary: AudioStream is a Digital Audio Workstation for CLI
230
243
  test_files: []