Class: Bio::Sequence::NA::MidiTrack

Inherits:
Object
  • Object
show all
Defined in:
lib/bio/shell/plugin/midi.rb

Constant Summary collapse

MidiProg =
[
  "Acoustic Grand Piano",
  "Bright Acoustic Piano",
  "Electric grand Piano",
  "Honky Tonk Piano",
  "Eiectric Piano 1",
  "Electric Piano 2",
  "Harpsichord",
  "Clavinet",
  "Celesra",
  "Glockenspiel",
  "Music Box",
  "Vibraphone",
  "Marimba",
  "Xylophone",
  "Tubular bells",
  "Dulcimer",
  "Drawbar Organ",
  "Percussive Organ",
  "Rock Organ",
  "Church Organ",
  "Reed Organ",
  "Accordion",
  "Harmonica",
  "Tango Accordion",
  "Nylon Accustic Guitar",
  "Steel Acoustic Guitar",
  "Jazz Electric Guitar",
  "Ciean Electric Guitar",
  "Muted Electric Guitar",
  "Overdrive Guitar",
  "Distorted Guitar",
  "Guitar Harmonics",
  "Acoustic Bass",
  "Electric Fingered Bass",
  "Electric Picked Bass",
  "Fretless Bass",
  "Slap Bass 1",
  "Slap Bass 2",
  "Syn Bass 1",
  "Syn Bass 2",
  "Violin",
  "Viola",
  "Cello",
  "Contrabass",
  "Tremolo Strings",
  "Pizzicato Strings",
  "Orchestral Harp",
  "Timpani",
  "String Ensemble 1",
  "String Ensemble 2 (Slow)",
  "Syn Strings 1",
  "Syn Strings 2",
  "Choir Aahs",
  "Voice Oohs",
  "Syn Choir",
  "Orchestral Hit",
  "Trumpet",
  "Trombone",
  "Tuba",
  "Muted Trumpet",
  "French Horn",
  "Brass Section",
  "Syn Brass 1",
  "Syn Brass 2",
  "Soprano Sax",
  "Alto Sax",
  "Tenor Sax",
  "Baritone Sax",
  "Oboe",
  "English Horn",
  "Bassoon",
  "Clarinet",
  "Piccolo",
  "Flute",
  "Recorder",
  "Pan Flute",
  "Bottle Blow",
  "Shakuhachi",
  "Whistle",
  "Ocarina",
  "Syn Square Wave",
  "Syn Sawtooth Wave",
  "Syn Calliope",
  "Syn Chiff",
  "Syn Charang",
  "Syn Voice",
  "Syn Fifths Sawtooth Wave",
  "Syn Brass & Lead",
  "New Age Syn Pad",
  "Warm Syn Pad",
  "Polysynth Syn Pad",
  "Choir Syn Pad",
  "Bowed Syn Pad",
  "Metal Syn Pad",
  "Halo Syn Pad",
  "Sweep Syn Pad",
  "SFX Rain",
  "SFX Soundtrack",
  "SFX Crystal",
  "SFX Atmosphere",
  "SFX Brightness",
  "SFX Goblins",
  "SFX Echoes",
  "SFX Sci-fi",
  "Sitar",
  "Banjo",
  "Shamisen",
  "Koto",
  "Kalimba",
  "Bag Pipe",
  "Fiddle",
  "Shanai",
  "Tinkle Bell",
  "Agogo",
  "Steel Drums",
  "Woodblock",
  "Taiko Drum",
  "Melodic Tom",
  "Syn Drum",
  "Reverse Cymbal",
  "Guitar Fret Noise",
  "Breath Noise",
  "Seashore",
  "Bird Tweet",
  "Telephone Ring",
  "Helicopter",
  "Applause",
  "Gun Shot"
]
Styles =
{
  #    "Ohno" => {
  #      # http://home.hiroshima-u.ac.jp/cato/bunkakoryuron.html
  #    },
  "Ichinose" => {
    :tempo => 120,
    :scale => [0, 2, 4, 5, 7, 9, 11],
    :tones => [
      {:prog =>  9, :base => 60, :range => 2},
      {:prog => 13, :base => 48, :range => 2},
      {:prog => 41, :base => 48, :range => 2},
      {:prog => 44, :base => 36, :range => 2},
    ]
  },
  "Okinawan" => {
    :tempo => 180,
    :scale => [0,4,5,7,11],
    :tones => [
      {:prog => MidiProg.index("Harpsichord"),   :base => 60, :range => 2},
      {:prog => MidiProg.index("Dulcimer"),      :base => 48, :range => 2},
      {:prog => MidiProg.index("Fretless Base"), :base => 36, :range => 1},
    ]
  },
  "Major" => {
    :scale => [0,2,4,5,7,9,11],
  },
  "Minor" => {
    :scale => [0,2,3,5,7,9,10],
  },
  "Harmonic minor" => {
    :scale => [0,2,3,5,7,9,11],
  },
  "Whole tone" => {
    :scale => [0,2,4,6,8,10],
  },
  "Half tone" => {
    :scale => [0,1,2,3,4,5,6,7,8,9,10,11],
  },
  "Indian" => {
    :scale => [0,1,4,5,7,8,11],
  },
  "Arabic" => {
    :scale => [0,2,3,6,7,8,11],
  },
  "Spanish" => {
    :scale => [0,1,3,4,5,7,8,10],
  },
  "Japanese" => {
    :scale => [0,2,5,7,9],
  },
}

Instance Method Summary collapse

Constructor Details

#initialize(channel = 0, program = nil, base = nil, range = nil, scale = nil) ⇒ MidiTrack

Returns a new instance of MidiTrack.



207
208
209
210
211
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/bio/shell/plugin/midi.rb', line 207

def initialize(channel = 0, program = nil, base = nil, range = nil, scale = nil)
  @channel = channel & 0xff
  @program = program || 0
  @base    = base    || 60
  @range   = range   || 2
  @scale   = scale   || [0, 2, 4, 5, 7, 9, 11]

  @tunes   = []
  @tune    = 0
  @code    = []
  @time    = 0

  @range.times do |i|
    @scale.each do |c|
      @tunes.push c + i * 12
    end
  end

  @ttype = {
    'aa' =>  1, 'at' =>  0, 'ac' => 3, 'ag' => -1,
    'ta' =>  0, 'tt' => -1, 'tc' => 1, 'tg' => -2,
    'ca' =>  2, 'ct' =>  1, 'cc' => 2, 'cg' =>  6,
    'ga' => -1, 'gt' => -3, 'gc' => 0, 'gg' => -2,
  }
  @dtype = [
    { 'aa' => 2, 'at' => 4, 'ac' => 4, 'ag' => 2,
      'ta' => 2, 'tt' => 4, 'tc' => 4, 'tg' => 2,
      'ca' => 2, 'ct' => 3, 'cc' => 1, 'cg' => 2,
      'ga' => 1, 'gt' => 2, 'gc' => 2, 'gg' => 3,
    },
    { 'aa' => 3, 'at' => 3, 'ac' => 2, 'ag' => 3,
      'ta' => 3, 'tt' => 3, 'tc' => 2, 'tg' => 2,
      'ca' => 3, 'ct' => 2, 'cc' => 1, 'cg' => 1,
      'ga' => 1, 'gt' => 1, 'gc' => 1, 'gg' => 1,
    },
    { 'aa' => 2, 'at' => 2, 'ac' => 2, 'ag' => 2,
      'ta' => 1, 'tt' => 1, 'tc' => 2, 'tg' => 2,
      'ca' => 2, 'ct' => 2, 'cc' => 2, 'cg' => 3,
      'ga' => 2, 'gt' => 2, 'gc' => 3, 'gg' => 1,
    },
    { 'aa' => 1, 'at' => 1, 'ac' => 1, 'ag' => 1,
      'ta' => 1, 'tt' => 1, 'tc' => 1, 'tg' => 1,
      'ca' => 1, 'ct' => 1, 'cc' => 1, 'cg' => 3,
      'ga' => 1, 'gt' => 1, 'gc' => 1, 'gg' => 1,
    },
  ]

  @code.concat [0x00, 0xc0 | (@channel & 0xff)]
  @code.concat icode(@program & 0xff, 1)
end

Instance Method Details

#c2s(code) ⇒ Object



277
278
279
280
281
282
283
# File 'lib/bio/shell/plugin/midi.rb', line 277

def c2s(code)
  ans = ""
  code.each do |c|
    ans += c.chr
  end
  ans
end

#encodeObject



317
318
319
320
321
322
323
# File 'lib/bio/shell/plugin/midi.rb', line 317

def encode
  ans ="MTrk"
  ans += c2s(icode(@code.length + 4, 4))
  ans += c2s(@code)
  ans += c2s([0x00, 0xff, 0x2f, 0x00])
  ans
end

#header(num, tempo = 120) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/bio/shell/plugin/midi.rb', line 325

def header(num, tempo = 120)
  ans = "MThd"
  ans += c2s(icode(6, 4))
  ans += c2s(icode(1, 2))
  ans += c2s(icode(num + 1, 2))
  ans += c2s(icode(480, 2))
  ans += "MTrk"
  ans += c2s(icode(11, 4))
  ans += c2s([0x00, 0xff, 0x51, 0x03])
  ans += c2s(icode(60000000 / tempo, 3))
  ans += c2s([0x00, 0xff, 0x2f, 0x00])
  ans
end

#icode(num, n) ⇒ Object



258
259
260
261
262
263
264
265
# File 'lib/bio/shell/plugin/midi.rb', line 258

def icode(num, n)
  code = []
  n.times do |i|
    code.push num & 0xff
    num >>= 8
  end
  code.reverse
end

#push(s) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/bio/shell/plugin/midi.rb', line 285

def push(s)
  tt = @time % 4
  t = @ttype[s[0, 2]]
  d = @dtype[tt][s[2, 2]]
  if !t.nil? && !d.nil?
    @tune += t
    @tune %= @tunes.length
    if tt == 0
      vel = 90
    elsif tt == 1 && d > 1
      vel = 100
    elsif tt == 2
      vel = 60
    else
      vel = 50
    end
    @code.concat rcode(1)
    @code.concat [0x90 | @channel, @tunes[@tune] + @base, vel]
    @code.concat rcode(240 * d)
    @code.concat [0x80 | @channel, @tunes[@tune] + @base, 0]
    @time += d
  end
end

#push_silent(d) ⇒ Object



309
310
311
312
313
314
315
# File 'lib/bio/shell/plugin/midi.rb', line 309

def push_silent(d)
  @code.concat rcode(1)
  @code.concat [0x90 | @channel, 0, 0]
  @code.concat rcode(240 * d)
  @code.concat [0x80 | @channel, 0, 0]
  @time += d;
end

#rcode(num) ⇒ Object



267
268
269
270
271
272
273
274
275
# File 'lib/bio/shell/plugin/midi.rb', line 267

def rcode(num)
  code = []
  code.push num & 0x7f
  while num > 0x7f
    num >>= 7
    code.push num & 0x7f | 0x80
  end
  code.reverse
end