Class: PicoTune::Phrase

Inherits:
Object
  • Object
show all
Defined in:
lib/picotune.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, tempo, beats, subbeats, melodies) ⇒ Phrase



214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/picotune.rb', line 214

def initialize name, tempo, beats, subbeats, melodies
  @name = name
  @tempo = tempo.to_i
  @beats = beats.to_i
  @subbeats = subbeats.to_i
  @melodies = melodies
  @simultaneous_melodies = @melodies.count

  @melodies.each do |m|
    m.instrument.phrase = self
  end
end

Instance Attribute Details

#beatsObject (readonly)

Returns the value of attribute beats.



211
212
213
# File 'lib/picotune.rb', line 211

def beats
  @beats
end

#melodiesObject (readonly)

Returns the value of attribute melodies.



211
212
213
# File 'lib/picotune.rb', line 211

def melodies
  @melodies
end

#nameObject (readonly)

Returns the value of attribute name.



211
212
213
# File 'lib/picotune.rb', line 211

def name
  @name
end

#simultaneous_melodiesObject (readonly)

Returns the value of attribute simultaneous_melodies.



211
212
213
# File 'lib/picotune.rb', line 211

def simultaneous_melodies
  @simultaneous_melodies
end

#subbeatsObject (readonly)

Returns the value of attribute subbeats.



211
212
213
# File 'lib/picotune.rb', line 211

def subbeats
  @subbeats
end

#tempoObject (readonly)

Returns the value of attribute tempo.



211
212
213
# File 'lib/picotune.rb', line 211

def tempo
  @tempo
end

#tuneObject

Returns the value of attribute tune.



212
213
214
# File 'lib/picotune.rb', line 212

def tune
  @tune
end

Instance Method Details

#bufferObject



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/picotune.rb', line 239

def buffer
  @buffer ||= begin
    samples = Array.new(buffer_size) { PicoTune::Sample.new }

    @melodies.each do |melody|
      temp = Array.new(buffer_size) { PicoTune::Sample.new } if melody.instrument.reverb?
      sub_buffer_size = buffer_size / (@beats * @subbeats)
      last_step_number = -1
      carry_over = 0

      if melody.pattern.steps.count != @beats * @subbeats
        raise "Mismatch between Pattern \"#{melody.pattern.name}\", which has #{melody.pattern.steps.count} steps, and Phrase \"#{@name}\", which has #{@beats} beats and #{subbeats} subbeats (meaning any pattern it uses should have #{@beats * @subbeats} steps). Please check your pattern and phrase definitions to find the discrepancy!"
      end

      melody.pattern.steps.each_with_index do |note, step_number|
        unless note == '.'
          buffer_pointer = step_number * sub_buffer_size
          local_index = 0
          wave_index = 0
          length_offset = (1 - melody.instrument.length_value) * sub_buffer_size

          if step_number == last_step_number + 1
            local_index = carry_over
          end

          carry_over = 0

          while local_index + length_offset < sub_buffer_size || !wave_index.zero?
            current_sample = (temp ? temp : samples)[buffer_pointer + local_index] || PicoTune::Sample.new

            new_sample = melody.instrument.wave wave_index, note

            current_sample.add new_sample

            (temp ? temp : samples)[buffer_pointer + local_index] = current_sample

            wave_index += 1
            local_index += 1
            last_step_number = step_number
            carry_over += 1 if local_index + length_offset >= sub_buffer_size
            wave_index = 0 if wave_index >= melody.instrument.samples_per_wave(note)
          end

          if melody.instrument.reverb?
            i = 0
            while i < temp.size
              if i + melody.instrument.reverb_offset < temp.size
                verb_sample = temp[i + melody.instrument.reverb_offset]
                verb_sample.modify_left :+, temp[i].left * melody.instrument.decay
                verb_sample.modify_right :+, temp[i].right * melody.instrument.decay

                temp[i + melody.instrument.reverb_offset] = verb_sample
              end

              samples[i] = (samples[i] || PicoTune::Sample.new).add temp[i]
              
              i += 1
            end
          end
        end
      end
    end

    samples
  end
end

#buffer_sizeObject



235
236
237
# File 'lib/picotune.rb', line 235

def buffer_size
  (seconds_per_measure * PicoTune::SAMPLE_RATE).to_i
end

#seconds_per_beatObject



227
228
229
# File 'lib/picotune.rb', line 227

def seconds_per_beat
  60.0 / @tempo
end

#seconds_per_measureObject



231
232
233
# File 'lib/picotune.rb', line 231

def seconds_per_measure
  seconds_per_beat * @beats
end