Class: Ruck::Generators::WavIn

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

Overview

plays sound stored in a RIFF WAV file

Instance Attribute Summary collapse

Attributes included from UGen

#name

Instance Method Summary collapse

Methods included from MultiChannelSource

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

Methods included from UGen

#to_s

Constructor Details

#initialize(attrs = {}) ⇒ WavIn

Returns a new instance of WavIn.



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

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.



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

def filename
  @filename
end

Instance Method Details

#attr_namesObject



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

def attr_names
  [:filename, :rate]
end

#durationObject



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

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

#init_wavObject



115
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
# File 'lib/ruck/ugen/wav.rb', line 115

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



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

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



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

def play; @playing = true; end

#resetObject



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

def reset
  @offset = 0
end

#stopObject



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

def stop; @playing = false; end