Class: Ruck::UGen::Generators::WavIn

Inherits:
Object
  • Object
show all
Includes:
MultiChannelSource, UGenBase
Defined in:
lib/ruck/ugen/wav.rb

Overview

plays sound stored in a RIFF WAV file

Instance Attribute Summary collapse

Attributes included from UGenBase

#name

Instance Method Summary collapse

Methods included from MultiChannelSource

#<<, #>>, #last, #out, #out_channels

Methods included from UGenBase

#to_s

Constructor Details

#initialize(attrs = {}) ⇒ WavIn

Returns a new instance of WavIn.



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ruck/ugen/wav.rb', line 103

def initialize(attrs = {})
  require_attrs attrs, [:filename]
  @rate = 1.0
  @gain = 1.0
  @filename = attrs.delete(:filename)
  parse_attrs attrs

  @loaded = false
  @playing = true

  init_wav
end

Instance Attribute Details

#filenameObject (readonly)

Returns the value of attribute filename.



101
102
103
# File 'lib/ruck/ugen/wav.rb', line 101

def filename
  @filename
end

Instance Method Details

#attr_namesObject



153
154
155
# File 'lib/ruck/ugen/wav.rb', line 153

def attr_names
  [:filename, :rate]
end

#durationObject



149
150
151
# File 'lib/ruck/ugen/wav.rb', line 149

def duration
  @loaded ? @wav.size / @block_align / @rate_adjust : 0
end

#init_wavObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/ruck/ugen/wav.rb', line 116

def init_wav
  riff = Riff::RiffReader.new(@filename).chunks.first
  unless riff.type == "RIFF"
    LOG.error "#{@filename}: Not RIFF!"
    return
  end
  unless riff[0..3] == "WAVE"
    LOG.error "#{@filename}: Not WAVE!"
    return
  end

  riff.data_skip = 4 # skip "WAVE"
  fmt = riff.chunks.first
  @wav = riff.chunks.find { |c| c.type == "data" }
  unless fmt[0..1].unpack("s1").first == 1
    LOG.error "#{@filename}: Not PCM!"
    return
  end

  @num_channels, @sample_rate, @byte_rate,
    @block_align, @bits_per_sample =
    fmt[2..15].unpack("s1i1i1s1s1")
  @range = (2 ** (@bits_per_sample - 1)).to_f

  @out_channels = (0..@num_channels-1).map { |chan| OutChannel.new self, chan }
  @sample = [0.0] * @num_channels
  @last = [0.0] * @num_channels
  @now = [nil] * @num_channels
  @rate_adjust = @sample_rate / SAMPLE_RATE

  @loaded = true
end

#next(now, chan = 0) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ruck/ugen/wav.rb', line 157

def next(now, chan = 0)
  return @last[chan] if @now[chan] == now
  @now[chan] = now

  return @last[chan] unless @loaded && @playing

  offset = @sample[chan].to_i * @block_align
  chan_offset = (chan * @bits_per_sample) / 8

  if offset + @block_align > @wav.size
    @playing = false
    return @last[chan]
  end

  @last[chan] = @wav[offset + chan_offset, @bits_per_sample].unpack("s1").first / @range * gain
  @sample[chan] += rate * @rate_adjust
  @last[chan]
end

#playObject



176
# File 'lib/ruck/ugen/wav.rb', line 176

def play; @playing = true; end

#resetObject



179
180
181
# File 'lib/ruck/ugen/wav.rb', line 179

def reset
  @offset = 0
end

#stopObject



177
# File 'lib/ruck/ugen/wav.rb', line 177

def stop; @playing = false; end