audio_stream 3.2.0 → 3.3.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: e1bdc59349cd6ef2c49c5cbc140c15037225f32f852a32ca6e951041b7a30711
4
- data.tar.gz: 31694954a02b8920b3da085cba2ac5dfa46c851e44d44f5cf0cefa871b76e1ce
3
+ metadata.gz: 0011df46c8c5a4ca83fac3301ca638940087710da3dd996382a354d9aa19596f
4
+ data.tar.gz: d88cb6715119d98bd02ee980be8cf9446b3a729a8de5003cf77a0dc0f958501a
5
5
  SHA512:
6
- metadata.gz: f88c300ac5d2e45e2c7b8b9d4de0aba54a49b22542478c7ba0ae7408140df727cc6ffb66b68f8d6a1353cea462a678ec2bcd6ed4681684ec2c87cfa71d2404a5
7
- data.tar.gz: b5281f647673f887c4e001e72c29e678614a064be79fc199156774dfeba2a9c9a51da49f4a58fdbd14a05fa339ced998186b54146f1a7d7c26f134c676d2a9a5
6
+ metadata.gz: 7059283b291c17fec85bcd40f194d8312a0f2539fe093a31268c5361f6a00517390a5d5c56df72cedb9dcc8432100a066834dee1fde4872039cf5adc2524c58c
7
+ data.tar.gz: 55340551e2da2ce9dcd87c89261b71868687d30ab65167f05552402c10d2e227337ccc7bba0c5ae9c7ebc737e779fa85952fb3056db3a7b5a1a65423fcffeed2
data/lib/audio_stream.rb CHANGED
@@ -9,6 +9,7 @@ require 'audio_stream/version'
9
9
  require 'audio_stream/error'
10
10
  require 'audio_stream/sound_info'
11
11
  require 'audio_stream/decibel'
12
+ require 'audio_stream/rate'
12
13
  require 'audio_stream/buffer'
13
14
  require 'audio_stream/ring_buffer'
14
15
  require 'audio_stream/sync'
@@ -10,7 +10,7 @@ module AudioStream
10
10
  end
11
11
 
12
12
  def add(observable, gain:, pan:)
13
- if gain && gain!=1.0
13
+ if gain && gain!=0.0
14
14
  observable = observable.fx(Fx::AGain.new(level: gain))
15
15
  end
16
16
 
@@ -100,7 +100,7 @@ module AudioStream
100
100
  dst = buffers.inject(:+)
101
101
 
102
102
  if average
103
- gain = AGain.new(level: 1.0/buffers.length)
103
+ gain = AGain.new(level: Decibel.mag(1.0/buffers.length))
104
104
  dst = gain.process(dst)
105
105
  end
106
106
 
@@ -20,5 +20,13 @@ module AudioStream
20
20
  def self.mag(mag)
21
21
  new(mag: mag)
22
22
  end
23
+
24
+ def self.create(val)
25
+ if self===val
26
+ val
27
+ else
28
+ new(db: val.to_f)
29
+ end
30
+ end
23
31
  end
24
32
  end
@@ -1,8 +1,13 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class AGain
4
- def initialize(level: 1.0)
5
- @level = level
4
+ # @param level [AudioStream::Decibel] Amplification level
5
+ def initialize(level:)
6
+ if Decibel===level
7
+ @level = level.mag
8
+ else
9
+ @level = Decibel.db(level).mag
10
+ end
6
11
  end
7
12
 
8
13
  def process(input)
@@ -19,6 +19,9 @@ module AudioStream
19
19
  }
20
20
  end
21
21
 
22
+ # @param soundinfo [AudioStream::SoundInfo]
23
+ # @param freq [Float] Cutoff frequency
24
+ # @param q [Float] Quality factor
22
25
  def self.create(soundinfo, freq:, q: DEFAULT_Q)
23
26
  filter = new(soundinfo)
24
27
  filter.update_coef(freq: freq, q: q)
@@ -19,6 +19,9 @@ module AudioStream
19
19
  }
20
20
  end
21
21
 
22
+ # @param soundinfo [AudioStream::SoundInfo]
23
+ # @param freq [Float] Center frequency
24
+ # @param bandwidth [Float] bandwidth (octave)
22
25
  def self.create(soundinfo, freq:, bandwidth: 1.0)
23
26
  filter = new(soundinfo)
24
27
  filter.update_coef(freq: freq, bandwidth: bandwidth)
@@ -2,10 +2,12 @@ module AudioStream
2
2
  module Fx
3
3
  class CombFilter
4
4
 
5
+ # @param soundinfo [AudioStream::SoundInfo]
6
+ # @param freq [AudioStream::Rate] frequency
7
+ # @param q [Float] Quality factor
5
8
  def initialize(soundinfo, freq:, q:)
6
9
  @window_size = soundinfo.window_size
7
- @samplerate = soundinfo.samplerate
8
- @delaysample = (soundinfo.samplerate.to_f / freq).round
10
+ @delaysample = freq.sample(soundinfo).round
9
11
  @q = q
10
12
 
11
13
  @delaybufs = [
@@ -1,12 +1,15 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class Delay
4
+ # @param soundinfo [AudioStream::SoundInfo]
5
+ # @param time [AudioStream::Rate] delay time
6
+ # @param level [AudioStream::Decibel] wet gain
7
+ # @param feedback [AudioStream::Decibel] feedback level
4
8
  def initialize(soundinfo, time:, level:, feedback:)
5
- @time = time
6
- @level = level
7
- @feedback = feedback
9
+ @level = Decibel.create(level).mag
10
+ @feedback = Decibel.create(feedback).mag
8
11
 
9
- @delaysample = (soundinfo.samplerate * time).round
12
+ @delaysample = time.sample(soundinfo).round
10
13
  @delaybuf0 = Array.new(@delaysample, 0.0)
11
14
  @delaybuf1 = Array.new(@delaysample, 0.0)
12
15
  @seek = 0
@@ -1,9 +1,11 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class Distortion
4
- def initialize(gain: 100, level: 0.1)
5
- @gain = gain
6
- @level = level
4
+ # @param gain [AudioStream::Decibel] input gain
5
+ # @param level [AudioStream::Decibel] output level
6
+ def initialize(gain: 40.0, level: -20.0)
7
+ @gain = Decibel.create(gain).mag
8
+ @level = Decibel.create(level).mag
7
9
  end
8
10
 
9
11
  def process(input)
@@ -1,6 +1,9 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class Equalizer2band
4
+ # @param freq [Float] Cutoff frequency
5
+ # @param q [Float] Quality factor
6
+ # @param gain [AudioStream::Decibel] Amplification level at cutoff frequency
4
7
  def initialize(soundinfo, lowfreq: 400.0, lowgain:, highfreq: 4000.0, highgain:)
5
8
  @low_filter = LowShelfFilter.create(soundinfo, freq: lowfreq, q: BiquadFilter::DEFAULT_Q, gain: lowgain)
6
9
  @high_filter = HighShelfFilter.create(soundinfo, freq: highfreq, q: BiquadFilter::DEFAULT_Q, gain: highgain)
@@ -19,6 +19,9 @@ module AudioStream
19
19
  }
20
20
  end
21
21
 
22
+ # @param soundinfo [AudioStream::SoundInfo]
23
+ # @param freq [Float] Cutoff frequency
24
+ # @param q [Float] Quality factor
22
25
  def self.create(soundinfo, freq:, q: DEFAULT_Q)
23
26
  filter = new(soundinfo)
24
27
  filter.update_coef(freq: freq, q: q)
@@ -3,6 +3,10 @@ module AudioStream
3
3
  class HighShelfFilter < BiquadFilter
4
4
 
5
5
  def update_coef(freq:, q:, gain:)
6
+ if Decibel===gain
7
+ gain = gain.db
8
+ end
9
+
6
10
  omega = 2.0 * Math::PI * freq / @samplerate
7
11
  alpha = Math.sin(omega) / (2.0 * q)
8
12
  a = 10.0 ** (gain / 40.0)
@@ -21,6 +25,10 @@ module AudioStream
21
25
  }
22
26
  end
23
27
 
28
+ # @param soundinfo [AudioStream::SoundInfo]
29
+ # @param freq [Float] Cutoff frequency
30
+ # @param q [Float] Quality factor
31
+ # @param gain [AudioStream::Decibel] Amplification level at cutoff frequency
24
32
  def self.create(soundinfo, freq:, q: DEFAULT_Q, gain: 1.0)
25
33
  filter = new(soundinfo)
26
34
  filter.update_coef(freq: freq, q: q, gain: gain)
@@ -19,6 +19,9 @@ module AudioStream
19
19
  }
20
20
  end
21
21
 
22
+ # @param soundinfo [AudioStream::SoundInfo]
23
+ # @param freq [Float] Cutoff frequency
24
+ # @param q [Float] Quality factor
22
25
  def self.create(soundinfo, freq:, q: DEFAULT_Q)
23
26
  filter = new(soundinfo)
24
27
  filter.update_coef(freq: freq, q: q)
@@ -3,6 +3,10 @@ module AudioStream
3
3
  class LowShelfFilter < BiquadFilter
4
4
 
5
5
  def update_coef(freq:, q:, gain:)
6
+ if Decibel===gain
7
+ gain = gain.db
8
+ end
9
+
6
10
  omega = 2.0 * Math::PI * freq / @samplerate
7
11
  alpha = Math.sin(omega) / (2.0 * q)
8
12
  a = 10.0 ** (gain / 40.0)
@@ -21,6 +25,10 @@ module AudioStream
21
25
  }
22
26
  end
23
27
 
28
+ # @param soundinfo [AudioStream::SoundInfo]
29
+ # @param freq [Float] Cutoff frequency
30
+ # @param q [Float] Quality factor
31
+ # @param gain [AudioStream::Decibel] Amplification level at cutoff frequency
24
32
  def self.create(soundinfo, freq:, q: DEFAULT_Q, gain: 1.0)
25
33
  filter = new(soundinfo)
26
34
  filter.update_coef(freq: freq, q: q, gain: gain)
@@ -3,6 +3,10 @@ module AudioStream
3
3
  class PeakingFilter < BiquadFilter
4
4
 
5
5
  def update_coef(freq:, bandwidth:, gain:)
6
+ if Decibel===gain
7
+ gain = gain.db
8
+ end
9
+
6
10
  omega = 2.0 * Math::PI * freq / @samplerate
7
11
  alpha = Math.sin(omega) * Math.sinh(Math.log(2.0) / 2.0 * bandwidth * omega / Math.sin(omega))
8
12
  a = 10.0 ** (gain / 40.0)
@@ -20,6 +24,10 @@ module AudioStream
20
24
  }
21
25
  end
22
26
 
27
+ # @param soundinfo [AudioStream::SoundInfo]
28
+ # @param freq [Float] Cutoff frequency
29
+ # @param bandwidth [Float] bandwidth (octave)
30
+ # @param gain [AudioStream::Decibel] Amplification level at cutoff frequency
23
31
  def self.create(soundinfo, freq:, bandwidth: 1.0, gain: 40.0)
24
32
  filter = new(soundinfo)
25
33
  filter.update_coef(freq: freq, bandwidth: bandwidth, gain: gain)
@@ -2,7 +2,13 @@ module AudioStream
2
2
  module Fx
3
3
  class Phaser
4
4
 
5
- def initialize(soundinfo, rate:, depth:, freq:, dry: 0.5, wet: 0.5)
5
+ # @param soundinfo [AudioStream::SoundInfo]
6
+ # @param rate [AudioStream::Rate] modulation speed
7
+ # @param depth [Float] frequency modulation depth
8
+ # @param freq [Float] Base cutoff frequency
9
+ # @param dry [AudioStream::Decibel] dry gain
10
+ # @param wet [AudioStream::Decibel] wet gain
11
+ def initialize(soundinfo, rate:, depth:, freq:, dry: -6.0, wet: -6.0)
6
12
  @soundinfo = soundinfo
7
13
 
8
14
  @filters = [
@@ -10,19 +16,19 @@ module AudioStream
10
16
  AllPassFilter.new(soundinfo),
11
17
  ]
12
18
 
13
- @speed = 2.0 * Math::PI * rate / @soundinfo.samplerate
19
+ @speed = rate.frame_phase(soundinfo)
14
20
  @phase = 0
15
21
 
16
22
  @depth = depth
17
23
  @freq = freq
18
24
 
19
- @dry = dry
20
- @wet = wet
25
+ @dry = Decibel.create(dry).mag
26
+ @wet = Decibel.create(wet).mag
21
27
  end
22
28
 
23
29
  def process(input)
24
30
  window_size = input.window_size
25
- @phase = (@phase + @speed * window_size) % (window_size / @speed)
31
+ @phase = (@phase + @speed) % (2.0 * Math::PI)
26
32
 
27
33
  a = Math.sin(@phase) * 0.5 + 0.5
28
34
  apf_freq = @freq * (1.0 + a * @depth)
@@ -3,6 +3,9 @@ module AudioStream
3
3
  class Vocoder
4
4
  include MultiAudioInputtable
5
5
 
6
+ # @param soundinfo [AudioStream::SoundInfo]
7
+ # @param shift [Float] modulator pitch shift. 1.0=1semitone
8
+ # @param bandwidth [Float] bandwidth (octave)
6
9
  def initialize(soundinfo, shift: 0, bandwidth: 0.2)
7
10
  regist_audio_input(:main)
8
11
  regist_audio_input(:side)
@@ -0,0 +1,98 @@
1
+ module AudioStream
2
+ class Rate
3
+ def initialize(sec: nil, sample: nil, freq: nil, sync: nil)
4
+ @sec = sec
5
+ @sample = sample
6
+ @freq = freq
7
+ @sync = sync
8
+ end
9
+
10
+ def sec(soundinfo)
11
+ sample(soundinfo).to_f / soundinfo.samplerate
12
+ end
13
+
14
+ def frame(soundinfo)
15
+ sample(soundinfo).to_f / soundinfo.window_size
16
+ end
17
+
18
+ def sample(soundinfo)
19
+ if @sample
20
+ return @sample
21
+ end
22
+
23
+ if @sec
24
+ return @sec.to_f * soundinfo.samplerate
25
+ end
26
+
27
+ if @freq
28
+ return soundinfo.samplerate.to_f / @freq
29
+ end
30
+
31
+ if @sync
32
+ return @sync / 480.0 * soundinfo.sync_rate
33
+ end
34
+ end
35
+
36
+ def frame_phase(soundinfo)
37
+ sample_phase(soundinfo) * soundinfo.window_size
38
+ end
39
+
40
+ def sample_phase(soundinfo)
41
+ 2.0 * Math::PI / sample(soundinfo)
42
+ end
43
+
44
+ def self.sec(v)
45
+ new(sec: v)
46
+ end
47
+
48
+ def self.millisec(v)
49
+ new(sec: v*0.001)
50
+ end
51
+
52
+ def self.sample(v)
53
+ new(sample: v)
54
+ end
55
+
56
+ def self.freq(v)
57
+ new(freq: v)
58
+ end
59
+
60
+ def self.sync(v)
61
+ new(sync: v)
62
+ end
63
+
64
+
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)
97
+ end
98
+ end
@@ -1,13 +1,24 @@
1
1
  module AudioStream
2
2
  class SoundInfo < RubyAudio::SoundInfo
3
3
  attr_accessor :window_size
4
+ attr_reader :bpm
5
+ attr_reader :bps
4
6
 
5
7
  def framerate
6
8
  self.samplerate.to_f / self.window_size
7
9
  end
8
10
 
11
+ def bpm=(bpm)
12
+ @bpm = bpm.to_f
13
+ @bps = @bpm / 60.0
14
+ end
15
+
16
+ def sync_rate
17
+ self.samplerate.to_f / self.bps
18
+ end
19
+
9
20
  def clone
10
- SoundInfo.new(channels: channels, samplerate: samplerate, format: format, window_size: window_size)
21
+ SoundInfo.new(channels: channels, samplerate: samplerate, format: format, window_size: window_size, bpm: bpm)
11
22
  end
12
23
  end
13
24
  end
@@ -1,3 +1,3 @@
1
1
  module AudioStream
2
- VERSION = "3.2.0"
2
+ VERSION = "3.3.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.2.0
4
+ version: 3.3.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-11-17 00:00:00.000000000 Z
11
+ date: 2019-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -196,6 +196,7 @@ files:
196
196
  - lib/audio_stream/fx/tremolo.rb
197
197
  - lib/audio_stream/fx/tuner.rb
198
198
  - lib/audio_stream/fx/vocoder.rb
199
+ - lib/audio_stream/rate.rb
199
200
  - lib/audio_stream/ring_buffer.rb
200
201
  - lib/audio_stream/sound_info.rb
201
202
  - lib/audio_stream/sync.rb