[BioRuby-cvs] bioruby/lib/bio/shell/plugin midi.rb,1.2,1.3

Katayama Toshiaki k at pub.open-bio.org
Sat Nov 5 03:38:15 EST 2005


Update of /home/repository/bioruby/bioruby/lib/bio/shell/plugin
In directory pub.open-bio.org:/tmp/cvs-serv30047/lib/bio/shell/plugin

Modified Files:
	midi.rb 
Log Message:
* converted to RDoc
* mechanism to select musical styles are incorpolated (scales are also
  contributed by Natsuhiro Ichinose)


Index: midi.rb
===================================================================
RCS file: /home/repository/bioruby/bioruby/lib/bio/shell/plugin/midi.rb,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** midi.rb	5 Oct 2005 08:58:33 -0000	1.2
--- midi.rb	5 Nov 2005 08:38:13 -0000	1.3
***************
*** 1,6 ****
  #
! #  bio/shell/plugin/midi.rb - Sequence to MIDI converter
  #
! #   Copyright (C) 2003 Natsuhiro Ichinose <ichinose at genome.ist.i.kyoto-u.ac.jp>
  #
  #  This library is free software; you can redistribute it and/or
--- 1,13 ----
  #
! # = bio/shell/plugin/midi.rb - Sequence to MIDI converter
  #
! # Copyright::	Copyright (C) 2003, 2005
! #		Natsuhiro Ichinose <ichinose at genome.ist.i.kyoto-u.ac.jp>,
! #		Toshiaki Katayama <k at bioruby.org>
! # License::	LGPL
! #
! # $Id$
! #
! #--
  #
  #  This library is free software; you can redistribute it and/or
***************
*** 18,183 ****
  #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  #
! #  $Id$
  #
  
! class Bio::Sequence::NA
! 
!   class MidiTrack
! 
!     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
  
!     def icode(num, n)
!       code = []
!       n.times do |i|
!         code.push num & 0xff
!         num >>= 8
        end
-       code.reverse
      end
  
!     def rcode(num)
!       code = []
!       code.push num & 0x7f
!       while num > 0x7f
!         num >>= 7
!         code.push num & 0x7f | 0x80
!       end
!       code.reverse
      end
  
!     def c2s(code)
!       ans = ""
!       code.each do |c|
!         ans += c.chr
!       end
!       ans
      end
  
!     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
  
!     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
  
!     def get_time
!       @time
!     end
  
!     def encode
!       ans ="MTrk"
!       ans += c2s(icode(@code.length + 4, 4))
!       ans += c2s(@code)
!       ans += c2s([0x00, 0xff, 0x2f, 0x00])
!       ans
!     end
  
!     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
  
!   end # MidiTrack
  
  
  
!   # drum:
!   #   true (with rhythm part), false (without rhythm part)
    # scale:
    #   C  C# D  D# E  F  F# G  G# A  A#  B
    #   0  1  2  3  4  5  6  7  8  9  10  11
!   def to_midi(tempo = 120, drum = true, scale = nil, track_info = nil)
!     scale      ||= [0, 2, 4, 5, 7, 9, 11]
!     track_info ||= [[9, 60, 2], [13, 48, 2], [41, 48, 2], [44, 36, 2]]
  
      track = []
  
!     track_info.each_with_index do |i, j|
!       k = j
!       k += 1 if j >= 9
!       track.push MidiTrack.new(k, i[0], i[1], i[2], scale)
      end
  
--- 25,385 ----
  #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  #
! #++
  #
  
! #--
! # *TODO*
! #   - add "Ohno" style
! #   - add a accessor to drum pattern
! #   - add a new feature to select music style (pop, trans, ryukyu, ...)
! #   - what is the base?
! #++
  
! class MidiTrack
  
!   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],
+     },
+   }
  
!   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
! 
!   def icode(num, n)
!     code = []
!     n.times do |i|
!       code.push num & 0xff
!       num >>= 8
      end
+     code.reverse
+   end
  
!   def rcode(num)
!     code = []
!     code.push num & 0x7f
!     while num > 0x7f
!       num >>= 7
!       code.push num & 0x7f | 0x80
      end
+     code.reverse
+   end
  
!   def c2s(code)
!     ans = ""
!     code.each do |c|
!       ans += c.chr
      end
+     ans
+   end
  
!   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
  
!   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
  
!   def encode
!     ans ="MTrk"
!     ans += c2s(icode(@code.length + 4, 4))
!     ans += c2s(@code)
!     ans += c2s([0x00, 0xff, 0x2f, 0x00])
!     ans
!   end
  
!   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
  
! end # MidiTrack
  
  
+ class Bio::Sequence::NA
  
!   # style:
!   #   Hash of :tempo, :scale, :tones
    # scale:
    #   C  C# D  D# E  F  F# G  G# A  A#  B
    #   0  1  2  3  4  5  6  7  8  9  10  11
!   # tones:
!   #   Hash of :prog, :base, :range -- tone, vol? or len?, octaves
!   # drum:
!   #   true (with rhythm part), false (without rhythm part)
!   def to_midi(style = {}, drum = true)
!     default = MidiTrack::Styles["Ichinose"]
!     if style.is_a?(String)
!       style = MidiTrack::Styles[style] || default
!     end
!     tempo = style[:tempo] || default[:tempo]
!     scale = style[:scale] || default[:scale]
!     tones = style[:tones] || default[:tones]
  
      track = []
  
!     tones.each_with_index do |tone, i|
!       ch = i
!       ch += 1 if i >= 9         # skip rythm track
!       track.push MidiTrack.new(ch, tone[:prog], tone[:base], tone[:range], scale)
      end
  
***************
*** 209,212 ****
--- 411,416 ----
  module Bio::Shell
  
+   private
+ 
    def midi(seq, filename, *args)
      begin
***************
*** 225,236 ****
  
  if $0 == __FILE__
    include Bio::Shell
  
    seq_file = ARGV.shift
    mid_file = ARGV.shift
  
!   ff = Bio::FlatFile.auto(seq_file)
!   ff.each do |f|
!     midi(f.naseq[1..1000], save_file)
    end
  end
--- 429,448 ----
  
  if $0 == __FILE__
+ 
+   # % for i in file*
+   # do
+   #   ruby -r bio bio/shell/plugin/midi.rb $i ${i}.mid
+   # done
+ 
    include Bio::Shell
  
    seq_file = ARGV.shift
    mid_file = ARGV.shift
+   style    = ARGV.shift
  
!   Bio::FlatFile.auto(seq_file) do |ff|
!     ff.each do |f|
!       midi(f.naseq[0..1000], mid_file, style)
!     end
    end
  end



More information about the bioruby-cvs mailing list