audio_stream 1.2.4 → 1.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: '00808bca83da43c81bd03e94f420f7ecce53b9211450c76a09d6d1856edf8be2'
4
- data.tar.gz: 64d161eedf393c991fe2692aa7328afceed56e926fed3101f92dbc862b820446
3
+ metadata.gz: e44fc50ce5993f26948cf0429df83eb1dac15556dbc89f7db605fa398a79f928
4
+ data.tar.gz: 8a4f2bcb04ca5d26b2574ac0b960211769d9d8f1f3474dcfb9823780ec0c90d7
5
5
  SHA512:
6
- metadata.gz: 4665c0f70102e40057ec0f799f21a8d422bd9ce395f74b7075f22cad0d7024ed8701e682cf644df55822055cf6720dacbb499de0766958dfa17bc46d6d0039b3
7
- data.tar.gz: 0be2c27573b1918ac6a01ffaa0b678c44338630415c28a3b13c06b432888c8b467f9443ad26b1e326aab9b4d2277eecb5268b8d541189f5827c35109443a93c9
6
+ metadata.gz: e3e1ac2bde745775aa261b02fa130f98720e3c549ed67d0ff1237e7ca5815a74fb3608f87fb020a03ea8af933bd0c3c78488b5d879310e8cd9d0df845b8fc8d3
7
+ data.tar.gz: 79502696e497e3307f35867cbcc8f585a977530b7f2bf1c2223aed6e84323467ee11e9a9e5cdbe4af7e40cbe77aa3a40a3eccfce1fd20cdb8365145389be5703
data/audio_stream.gemspec CHANGED
@@ -33,6 +33,5 @@ Gem::Specification.new do |spec|
33
33
  spec.add_dependency "ruby-audio", ">= 1.6.1"
34
34
  spec.add_dependency "coreaudio", ">= 0.0.12"
35
35
  spec.add_dependency "ruby-fftw3", ">= 1.0.2"
36
- spec.add_dependency "rx", ">= 0.0.3"
37
36
  spec.add_dependency "rbplotly", ">= 0.1.2"
38
37
  end
@@ -51,7 +51,7 @@
51
51
  ],
52
52
  "source": [
53
53
  "$LOAD_PATH << File.dirname(__FILE__) + \"/../lib\"\n",
54
- "require 'audio_stream/core_ext'\n",
54
+ "require 'audio_stream'\n",
55
55
  "\n",
56
56
  "include AudioStream\n",
57
57
  "include AudioStream::Fx\n",
@@ -118,7 +118,7 @@
118
118
  ],
119
119
  "source": [
120
120
  "$LOAD_PATH << File.dirname(__FILE__) + \"/../lib\"\n",
121
- "require 'audio_stream/core_ext'\n",
121
+ "require 'audio_stream'\n",
122
122
  "\n",
123
123
  "include AudioStream\n",
124
124
  "include AudioStream::Fx\n",
data/examples/chorus.rb CHANGED
@@ -22,8 +22,7 @@ stereo_out = AudioOutput.device(soundinfo: $soundinfo)
22
22
  # Mixer
23
23
 
24
24
  track1
25
- .stream
26
- .fx(MonoToStereo.new)
25
+ .fx(MonoToStereo.instance)
27
26
  .fx(chorus)
28
27
  .send_to(bus1, gain: 1.0, pan: 0.0)
29
28
 
@@ -23,7 +23,6 @@ stereo_out = AudioOutput.device(soundinfo: $soundinfo)
23
23
  # Mixer
24
24
 
25
25
  track1
26
- .stream
27
26
  .fx(noise_gate)
28
27
  .fx(compressor)
29
28
  .fx(distortion)
@@ -1,4 +1,4 @@
1
- require 'audio_stream/core_ext'
1
+ require 'audio_stream'
2
2
  require 'optparse'
3
3
 
4
4
  include AudioStream
@@ -6,7 +6,7 @@ include AudioStream::Fx
6
6
 
7
7
 
8
8
  $soundinfo = SoundInfo.new(
9
- channels: 1,
9
+ channels: 2,
10
10
  samplerate: 44100,
11
11
  window_size: 1024,
12
12
  format: RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
data/examples/lpf.rb CHANGED
@@ -24,8 +24,7 @@ stereo_out = AudioOutput.device(soundinfo: $soundinfo)
24
24
  # Mixer
25
25
 
26
26
  track1
27
- .stream
28
- .fx(StereoToMono.new)
27
+ .fx(StereoToMono.instance)
29
28
  .fx(lpf)
30
29
  .send_to(stereo_out)
31
30
 
data/examples/rec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'audio_stream/core_ext'
1
+ require 'audio_stream'
2
2
 
3
3
  include AudioStream
4
4
  include AudioStream::Fx
@@ -6,7 +6,7 @@ include AudioStream::Fx
6
6
  soundinfo = SoundInfo.new(
7
7
  channels: 2,
8
8
  samplerate: 44100,
9
- window_size: 1024
9
+ window_size: 1024,
10
10
  format: RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
11
11
  )
12
12
 
@@ -31,7 +31,6 @@ stereo_out = AudioOutput.device(soundinfo: soundinfo)
31
31
  # Mixer
32
32
 
33
33
  track1
34
- .stream
35
34
  .send_to(file_out)
36
35
  .send_to(bus1)
37
36
 
@@ -39,7 +38,6 @@ bus1
39
38
  .send_to(stereo_out, gain: 0.5)
40
39
 
41
40
  track2
42
- .stream
43
41
  .send_to(stereo_out)
44
42
 
45
43
 
data/examples/tuner.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'audio_stream/core_ext'
1
+ require 'audio_stream'
2
2
 
3
3
  include AudioStream
4
4
  include AudioStream::Fx
data/lib/audio_stream.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'ruby-audio'
2
2
  require 'coreaudio'
3
3
  require 'numru/fftw3'
4
- require 'rx'
5
4
  require 'rbplotly'
5
+ require 'singleton'
6
6
 
7
7
  require 'audio_stream/version'
8
8
  require 'audio_stream/error'
@@ -11,6 +11,10 @@ require 'audio_stream/buffer'
11
11
  require 'audio_stream/ring_buffer'
12
12
  require 'audio_stream/sync'
13
13
  require 'audio_stream/conductor'
14
+ require 'audio_stream/audio_observer'
15
+ require 'audio_stream/audio_observable'
16
+ require 'audio_stream/audio_observable_fx'
17
+ require 'audio_stream/audio_notification'
14
18
  require 'audio_stream/audio_input'
15
19
  require 'audio_stream/audio_input_file'
16
20
  require 'audio_stream/audio_input_device'
@@ -1,28 +1,68 @@
1
1
  module AudioStream
2
- class AudioBus < Rx::Subject
2
+ class AudioBus
3
+ include AudioObserver
4
+ include AudioObservable
5
+
3
6
  def initialize
4
- super
5
- @observables = []
6
- @zip_observable = nil
7
- @detach = nil
7
+ @mutex = Mutex.new
8
+ @callers = Set[]
9
+ @notifications = {}
8
10
  end
9
11
 
10
12
  def add(observable, gain:, pan:)
11
13
  if gain && gain!=1.0
12
- observable = observable.map(&Fx::AGain.new(level: gain).method(:process))
14
+ observable = observable.fx(Fx::AGain.new(level: gain))
13
15
  end
14
16
 
15
17
  if pan && pan!=0.0
16
- observable = observable.map(&Fx::Panning.new(pan: pan).method(:process))
18
+ observable = observable.fx(Fx::Panning.new(pan: pan))
17
19
  end
18
20
 
19
- @observables << observable
20
- if @detach
21
- @detach.unsubscribe
21
+ @mutex.synchronize {
22
+ @callers << observable
23
+ observable.add_observer(self)
24
+ }
25
+ end
26
+
27
+ def update(notification)
28
+ do_notify = false
29
+ next_notifications = nil
30
+
31
+ @mutex.synchronize {
32
+ @notifications[notification.caller_obj] = notification
33
+
34
+ if @callers.length==@notifications.length
35
+ next_notifications = []
36
+ @notifications.each {|caller_obj, notification|
37
+ case notification.stat
38
+ when AudioNotification::STAT_NEXT
39
+ next_notifications << notification
40
+ when AudioNotification::STAT_COMPLETE
41
+ @callers.delete(caller_obj)
42
+ end
43
+ }
44
+
45
+ do_notify = true
46
+ @notifications.clear
47
+ end
48
+ }
49
+
50
+ if do_notify
51
+ if 0<next_notifications.length
52
+ output = next_notifications.map(&:input).inject(:+)
53
+ on_next(output)
54
+ else
55
+ on_complete
56
+ end
22
57
  end
58
+ end
59
+
60
+ def on_next(input)
61
+ notify_next(input)
62
+ end
23
63
 
24
- @zip_observable = Rx::Observable.zip(*@observables).map{|a| a.inject(:+)}
25
- @detach = @zip_observable.subscribe(self)
64
+ def on_complete
65
+ notify_complete
26
66
  end
27
67
  end
28
68
  end
@@ -2,6 +2,7 @@ module AudioStream
2
2
 
3
3
  module AudioInput
4
4
  include Enumerable
5
+ include AudioObservable
5
6
 
6
7
  attr_reader :connection
7
8
 
@@ -9,13 +10,24 @@ module AudioStream
9
10
  @sync ||= Sync.new
10
11
  end
11
12
 
12
- def connect
13
+ def publish
13
14
  @connection = Thread.start {
14
- stream.connect
15
+ each {|input|
16
+ sync.resume_wait
17
+ notify_next(input)
18
+ sync.yield
19
+ }
20
+ sync.resume_wait
21
+ notify_complete
22
+ sync.finish
15
23
  }
16
24
  self
17
25
  end
18
26
 
27
+ def connect
28
+ nil
29
+ end
30
+
19
31
  def disconnect
20
32
  if @connection
21
33
  @connection.kill
@@ -24,17 +36,12 @@ module AudioStream
24
36
  self
25
37
  end
26
38
 
27
- def stream
28
- @stream ||= Rx::Observable.create do |observer|
29
- each {|buf|
30
- sync.resume_wait
31
- observer.on_next(buf)
32
- sync.yield
33
- }
34
- sync.resume_wait
35
- sync.finish
36
- observer.on_completed
37
- end.publish
39
+ def connected?
40
+ nil
41
+ end
42
+
43
+ def published?
44
+ !!@connection
38
45
  end
39
46
 
40
47
 
@@ -6,6 +6,18 @@ module AudioStream
6
6
  @buffers = [buffers].flatten.compact
7
7
  end
8
8
 
9
+ def connect
10
+ self
11
+ end
12
+
13
+ def disconnect
14
+ self
15
+ end
16
+
17
+ def connected?
18
+ true
19
+ end
20
+
9
21
  def each(&block)
10
22
  Enumerator.new do |y|
11
23
  @buffers.each {|buf|
@@ -14,22 +14,28 @@ module AudioStream
14
14
  end
15
15
 
16
16
  def connect
17
- @inbuf = @dev.input_buffer(@soundinfo.window_size)
18
- @inbuf.start
19
- super
17
+ if !connected?
18
+ @inbuf = @dev.input_buffer(@soundinfo.window_size)
19
+ @inbuf.start
20
+ end
21
+ self
20
22
  end
21
23
 
22
24
  def disconnect
23
- if @inbuf
25
+ if connected?
24
26
  @inbuf.stop
25
27
  @inbuf = nil
26
28
  end
27
29
  super
28
30
  end
29
31
 
32
+ def connected?
33
+ !!@inbuf
34
+ end
35
+
30
36
  def each(&block)
31
37
  Enumerator.new do |y|
32
- if !@inbuf
38
+ if !connected?
33
39
  raise Error, "Device is not connected. You need to exec #{self.class.name}.connect: #{name}"
34
40
  end
35
41
 
@@ -10,25 +10,35 @@ module AudioStream
10
10
  end
11
11
 
12
12
  def connect
13
- @sound = RubyAudio::Sound.open(@path)
14
- super
13
+ if !connected?
14
+ @sound = RubyAudio::Sound.open(@path)
15
+ end
16
+ self
15
17
  end
16
18
 
17
19
  def disconnect
18
- if @sound && !@sound.closed?
20
+ if connected?
19
21
  @sound.close
20
22
  end
21
23
  super
22
24
  end
23
25
 
26
+ def connected?
27
+ @sound && !@sound.closed?
28
+ end
29
+
24
30
  def seek(frames, whence=IO::SEEK_SET)
31
+ if !connected?
32
+ raise Error, "File is not opened. You need to exec #{self.class.name}.connect: #{@path}"
33
+ end
34
+
25
35
  @sound.seek(frames, whence)
26
36
  self
27
37
  end
28
38
 
29
39
  def each(&block)
30
40
  Enumerator.new do |y|
31
- if !@sound || @sound.closed?
41
+ if !connected?
32
42
  raise Error, "File is not opened. You need to exec #{self.class.name}.connect: #{@path}"
33
43
  end
34
44
 
@@ -0,0 +1,17 @@
1
+ module AudioStream
2
+
3
+ class AudioNotification
4
+ STAT_NEXT = :next
5
+ STAT_COMPLETE = :complete
6
+
7
+ attr_reader :stat
8
+ attr_reader :input
9
+ attr_reader :caller_obj
10
+
11
+ def initialize(stat, input, caller_obj)
12
+ @stat = stat
13
+ @input = input
14
+ @caller_obj = caller_obj
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ require 'observer'
2
+
3
+ module AudioStream
4
+
5
+ module AudioObservable
6
+ include Observable
7
+
8
+ def notify_next(input)
9
+ changed
10
+ notify_observers(AudioNotification.new(AudioNotification::STAT_NEXT, input, self))
11
+ end
12
+
13
+ def notify_complete
14
+ changed
15
+ notify_observers(AudioNotification.new(AudioNotification::STAT_COMPLETE, nil, self))
16
+ end
17
+
18
+ def fx(effector)
19
+ observer = AudioObservableFx.new(effector)
20
+ add_observer(observer)
21
+ observer
22
+ end
23
+
24
+ def send_to(bus, gain: nil, pan: nil)
25
+ bus.add(self, gain: gain, pan: pan)
26
+ self
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ module AudioStream
2
+
3
+ class AudioObservableFx
4
+ include AudioObserver
5
+ include AudioObservable
6
+
7
+ def initialize(effector)
8
+ @effector = effector
9
+ end
10
+
11
+ def on_next(input)
12
+ if Fx::BangProcess===input
13
+ @effector.process!(input)
14
+ output = input
15
+ else
16
+ output = @effector.process(input)
17
+ end
18
+ notify_next(output)
19
+ end
20
+
21
+ def on_complete
22
+ notify_complete
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module AudioStream
2
+
3
+ module AudioObserver
4
+ def update(notification)
5
+ case notification.stat
6
+ when AudioNotification::STAT_NEXT
7
+ on_next(notification.input)
8
+ when AudioNotification::STAT_COMPLETE
9
+ on_complete
10
+ end
11
+ end
12
+ end
13
+ end
@@ -23,9 +23,9 @@ module AudioStream
23
23
 
24
24
  case @channels
25
25
  when 1
26
- input = Fx::StereoToMono.new.process(input)
26
+ input = Fx::StereoToMono.instance.process(input)
27
27
  when 2
28
- input = Fx::MonoToStereo.new.process(input)
28
+ input = Fx::MonoToStereo.instance.process(input)
29
29
  end
30
30
 
31
31
  sint_a = input.to_a.flatten.map{|f| (f*0x7FFF).round}
@@ -25,7 +25,7 @@ module AudioStream
25
25
  }
26
26
  }
27
27
  when 2
28
- m2s = Fx::MonoToStereo.new
28
+ m2s = Fx::MonoToStereo.instance
29
29
  a = [
30
30
  m2s.process(self),
31
31
  m2s.process(other),
@@ -8,18 +8,20 @@ module AudioStream
8
8
  def connect
9
9
  @outputs.map(&:connect)
10
10
  @inputs.map(&:connect)
11
+ @inputs.map(&:publish)
11
12
 
12
13
  @sync_thread = Thread.start {
13
14
  catch :break do
14
15
  loop {
15
- @inputs.each {|t|
16
- t.sync.resume
16
+ @inputs.each {|input|
17
+ input.sync.resume
17
18
  }
18
19
 
19
- @inputs.each {|t|
20
- stat = t.sync.yield_wait
20
+ @inputs.each {|input|
21
+ stat = input.sync.yield_wait
21
22
  if stat==Sync::COMPLETED
22
- throw :break
23
+ @inputs.delete(input)
24
+ #throw :break
23
25
  end
24
26
  }
25
27
 
@@ -1,6 +1,7 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class HanningWindow
4
+ include Singleton
4
5
  include BangProcess
5
6
 
6
7
  def process!(input)
@@ -1,6 +1,8 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class MonoToStereo
4
+ include Singleton
5
+
4
6
  def process(input)
5
7
  case input.channels
6
8
  when 1
@@ -5,7 +5,7 @@ module AudioStream
5
5
 
6
6
  def initialize(threshold: 0.01)
7
7
  @threshold = threshold
8
- @window = HanningWindow.new
8
+ @window = HanningWindow.instance
9
9
  end
10
10
 
11
11
  def process!(input)
@@ -1,6 +1,8 @@
1
1
  module AudioStream
2
2
  module Fx
3
3
  class StereoToMono
4
+ include Singleton
5
+
4
6
  def process(input)
5
7
  case input.channels
6
8
  when 1
@@ -15,14 +15,14 @@ module AudioStream
15
15
 
16
16
  def initialize(soundinfo, window: nil)
17
17
  @samplerate = soundinfo.samplerate.to_f
18
- @window = window || HanningWindow.new
18
+ @window = window || HanningWindow.instance
19
19
  end
20
20
 
21
21
  def process(input)
22
22
  window_size = input.size
23
23
 
24
24
  # mono window
25
- input = StereoToMono.new.process(input)
25
+ input = StereoToMono.instance.process(input)
26
26
  @window.process!(input)
27
27
 
28
28
  gain = input.to_a.flatten.max
@@ -12,7 +12,7 @@ module AudioStream
12
12
  end
13
13
 
14
14
  def fft(window=nil)
15
- window ||= HanningWindow.new
15
+ window ||= HanningWindow.instance
16
16
 
17
17
  na = window.process(@input).to_na
18
18
  fft = FFTW3.fft(na, FFTW3::FORWARD) / na.length
@@ -1,3 +1,3 @@
1
1
  module AudioStream
2
- VERSION = "1.2.4"
2
+ VERSION = "1.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: 1.2.4
4
+ version: 1.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-07-22 00:00:00.000000000 Z
11
+ date: 2019-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,20 +94,6 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: 1.0.2
97
- - !ruby/object:Gem::Dependency
98
- name: rx
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: 0.0.3
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: 0.0.3
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rbplotly
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -152,12 +138,15 @@ files:
152
138
  - lib/audio_stream/audio_input_buffer.rb
153
139
  - lib/audio_stream/audio_input_device.rb
154
140
  - lib/audio_stream/audio_input_file.rb
141
+ - lib/audio_stream/audio_notification.rb
142
+ - lib/audio_stream/audio_observable.rb
143
+ - lib/audio_stream/audio_observable_fx.rb
144
+ - lib/audio_stream/audio_observer.rb
155
145
  - lib/audio_stream/audio_output.rb
156
146
  - lib/audio_stream/audio_output_device.rb
157
147
  - lib/audio_stream/audio_output_file.rb
158
148
  - lib/audio_stream/buffer.rb
159
149
  - lib/audio_stream/conductor.rb
160
- - lib/audio_stream/core_ext.rb
161
150
  - lib/audio_stream/error.rb
162
151
  - lib/audio_stream/fx.rb
163
152
  - lib/audio_stream/fx/a_gain.rb
@@ -1,13 +0,0 @@
1
- require 'audio_stream'
2
-
3
- module Rx::Observable
4
- def fx(effector)
5
- #map(&effector.:process)
6
- map(&effector.method(:process))
7
- end
8
-
9
- def send_to(bus, gain: nil, pan: nil)
10
- bus.add(self, gain: gain, pan: pan)
11
- self
12
- end
13
- end