Class: AudioStream::Buffer
- Inherits:
-
Object
- Object
- AudioStream::Buffer
- Defined in:
- lib/audio_stream/buffer.rb
Instance Attribute Summary collapse
-
#channels ⇒ Object
readonly
Returns the value of attribute channels.
-
#streams ⇒ Object
readonly
Returns the value of attribute streams.
-
#window_size ⇒ Object
readonly
Returns the value of attribute window_size.
Class Method Summary collapse
- .create(window_size, channels) ⇒ Object
- .create_mono(window_size) ⇒ Object
- .create_stereo(window_size) ⇒ Object
- .from_na(na) ⇒ Object
- .from_rabuffer(rabuf) ⇒ Object
- .merge(buffers, average: false) ⇒ Object
Instance Method Summary collapse
- #+(other) ⇒ Object
- #fft_plot(samplerate = 44100, window = nil) ⇒ Object
-
#initialize(stream0, stream1 = nil) ⇒ Buffer
constructor
A new instance of Buffer.
- #mono(deep_copy: false) ⇒ Object
- #plot ⇒ Object
- #stereo(deep_copy: false) ⇒ Object
- #to_float_na(dst = nil, offset = 0) ⇒ Object
- #to_rabuffer ⇒ Object
- #to_sint_na ⇒ Object
Constructor Details
#initialize(stream0, stream1 = nil) ⇒ Buffer
Returns a new instance of Buffer.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/audio_stream/buffer.rb', line 8 def initialize(stream0, stream1=nil) if Array===stream0 stream0 = Vdsp::DoubleArray.create(stream0) end if Array===stream1 stream1 = Vdsp::DoubleArray.create(stream1) end @stream0 = stream0 @stream1 = stream1 if !stream1 @streams = [stream0] @channels = 1 @window_size = stream0.size else @streams = [stream0, stream1] @channels = 2 @window_size = stream0.size if stream0.size!=stream1.size raise Error, "stream size is not match: stream0.size=#{stream0.size}, stream1.size=#{stream1.size}" end end end |
Instance Attribute Details
#channels ⇒ Object (readonly)
Returns the value of attribute channels.
5 6 7 |
# File 'lib/audio_stream/buffer.rb', line 5 def channels @channels end |
#streams ⇒ Object (readonly)
Returns the value of attribute streams.
4 5 6 |
# File 'lib/audio_stream/buffer.rb', line 4 def streams @streams end |
#window_size ⇒ Object (readonly)
Returns the value of attribute window_size.
6 7 8 |
# File 'lib/audio_stream/buffer.rb', line 6 def window_size @window_size end |
Class Method Details
.create(window_size, channels) ⇒ Object
192 193 194 195 196 197 198 199 |
# File 'lib/audio_stream/buffer.rb', line 192 def self.create(window_size, channels) case channels when 1 create_mono(window_size) when 2 create_stereo(window_size) end end |
.create_mono(window_size) ⇒ Object
201 202 203 204 |
# File 'lib/audio_stream/buffer.rb', line 201 def self.create_mono(window_size) stream0 = Vdsp::DoubleArray.new(window_size) new(stream0) end |
.create_stereo(window_size) ⇒ Object
206 207 208 209 210 |
# File 'lib/audio_stream/buffer.rb', line 206 def self.create_stereo(window_size) stream0 = Vdsp::DoubleArray.new(window_size) stream1 = Vdsp::DoubleArray.new(window_size) new(stream0, stream1) end |
.from_na(na) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/audio_stream/buffer.rb', line 212 def self.from_na(na) channels = na.shape[0] window_size = na.size / channels case na.typecode when NArray::SINT max = 0x7FFF.to_f when NArray::FLOAT max = 1.0 end case channels when 1 stream0 = [] window_size.times {|i| stream0 << na[i].real / max } self.new(stream0) when 2 stream0 = [] stream1 = [] window_size.times {|i| stream0 << na[i*2].real / max stream1 << na[(i*2)+1].real / max } self.new(stream0, stream1) end end |
.from_rabuffer(rabuf) ⇒ Object
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/audio_stream/buffer.rb', line 241 def self.from_rabuffer(rabuf) channels = rabuf.channels window_size = rabuf.size case channels when 1 stream0 = rabuf.to_a while stream0.size<window_size stream0 << 0.0 end self.new(stream0) when 2 stream0 = Array.new(window_size, 0.0) stream1 = Array.new(window_size, 0.0) rabuf.each_with_index {|fa, i| stream0[i] = fa[0] stream1[i] = fa[1] } self.new(stream0, stream1) end end |
.merge(buffers, average: false) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/audio_stream/buffer.rb', line 87 def self.merge(buffers, average: false) buffers.each {|buf| unless Buffer===buf raise Error, "argument is not Buffer: #{buf}" end } if buffers.length==0 raise Error, "argument is empty" elsif buffers.length==1 return buffers[0] end dst = buffers.inject(:+) if average gain = AGain.new(level: Decibel.mag(1.0/buffers.length)) dst = gain.process(dst) end dst end |
Instance Method Details
#+(other) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/audio_stream/buffer.rb', line 67 def +(other) if self.window_size!=other.window_size raise Error, "Buffer.window_size is not match: self.window_size=#{self.window_size} other.window_size=#{other.window_size}" end channels = [self.channels, other.channels].max case channels when 1 stream0 = self.streams[0] + other.streams[0] self.class.new(stream0) when 2 st_self = self.stereo st_other = other.stereo stream0 = st_self.streams[0] + st_other.streams[0] stream1 = st_self.streams[1] + st_other.streams[1] self.class.new(stream0, stream1) end end |
#fft_plot(samplerate = 44100, window = nil) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/audio_stream/buffer.rb', line 119 def fft_plot(samplerate=44100, window=nil) window ||= HanningWindow.instance na = window.process(self).to_float_na fft = FFTW3.fft(na, FFTW3::FORWARD) / na.length buf = Buffer.from_na(fft) xs = window_size.times.map{|i| i.to_f * samplerate / window_size} traces = buf.streams.map {|stream| {x: xs, y: stream} } Plotly::Plot.new( data: traces, xaxis: {title: 'Frequency (Hz)', type: 'log'} ) end |
#mono(deep_copy: false) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/audio_stream/buffer.rb', line 51 def mono(deep_copy: false) case self.channels when 1 if deep_copy self.class.new(@stream0.clone) else self end when 2 mono_stream = window_size.times.map {|i| (@stream0[i] + @stream1[i]) * 0.5 } self.class.new(mono_stream) end end |
#plot ⇒ Object
110 111 112 113 114 115 116 117 |
# File 'lib/audio_stream/buffer.rb', line 110 def plot xs = window_size.times.to_a traces = @streams.map {|stream| {x: xs, y: stream} } Plotly::Plot.new(data: traces) end |
#stereo(deep_copy: false) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/audio_stream/buffer.rb', line 34 def stereo(deep_copy: false) case self.channels when 1 if deep_copy self.class.new(@stream0.clone, @stream0.clone) else self.class.new(@stream0, @stream0) end when 2 if deep_copy self.class.new(@stream0.clone, @stream1.clone) else self end end end |
#to_float_na(dst = nil, offset = 0) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/audio_stream/buffer.rb', line 137 def to_float_na(dst=nil, offset=0) if dst if channels!=dst.shape[0] raise Error, "channels is not match: buffer.channels=#{channels} na.shape[0]=#{dst.shape[0]}" end if dst.typecode!=NArray::FLOAT raise Error, "typecode is not match: na.typecode=#{dst.typecode}" end end na = dst || NArray.float(channels, window_size) case channels when 1 na[(0+offset)...(window_size+offset)] = @stream0.to_a when 2 na[window_size.times.map{|i| i*2+offset}] = @stream0.to_a na[window_size.times.map{|i| i*2+1+offset}] = @stream1.to_a end na end |
#to_rabuffer ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/audio_stream/buffer.rb', line 173 def to_rabuffer rabuf = RubyAudio::Buffer.float(window_size, channels) case channels when 1 @stream0.each_with_index {|v, i| rabuf[i] = v } when 2 stream0 = @stream0.to_a stream1 = @stream1.to_a window_size.times {|i| rabuf[i] = [stream0[i], stream1[i]] } end rabuf end |
#to_sint_na ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/audio_stream/buffer.rb', line 159 def to_sint_na na = NArray.sint(channels, window_size) case channels when 1 na[0...window_size] = @stream0.map {|f| (f * 0x7FFF).round} when 2 na[window_size.times.map{|i| i*2}] = @stream0.map {|f| (f * 0x7FFF).round} na[window_size.times.map{|i| i*2+1}] = @stream1.map {|f| (f * 0x7FFF).round} end na end |