[BioRuby-cvs] bioruby/lib/bio/shell/plugin midi.rb,NONE,1.1
Katayama Toshiaki
k at pub.open-bio.org
Wed Oct 5 03:09:04 EDT 2005
Update of /home/repository/bioruby/bioruby/lib/bio/shell/plugin
In directory pub.open-bio.org:/tmp/cvs-serv32752
Added Files:
midi.rb
Log Message:
* sequence to midi converter contributed by Natsuhiro Ichinose
http://www.genome.ist.i.kyoto-u.ac.jp/~ichinose/bio/biomidi/
--- NEW FILE: midi.rb ---
#
# bio/shell/plugin/midi.rb - Sequence to MIDI converter
#
# Copyright (C) 2004 Natsuhiro Ichinose <ichinose at genome.ist.i.kyoto-u.ac.jp>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id: midi.rb,v 1.1 2005/10/05 07:09:02 k Exp $
#
require 'bio/sequence'
module Bio
class Sequence
class NA
class MidiTrack
def initialize(channel=0,program=0,base=60,range=2,scale=[0,2,4,5,7,9,11])
@base=base
@code=[]
@tune=0
@time=0
@tunes=[]
@channel=channel&0xff
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, at tunes[@tune]+ at base,vel]
@code.concat rcode(240*d)
@code.concat [0x80|@channel, at tunes[@tune]+ at 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
def to_midi(tempo=120,track_info=[[9,60,2],[13,48,2],[41,48,2],[44,36,2]],
drum=false,scale=[0,2,4,5,7,9,11])
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
track.push(MidiTrack.new(9,0,35,2,[0,1,2,3,4,5,6,7,8,9,10,11])) if drum
cur=0
window_search(4) do |s|
track[cur%track.length].push(s)
cur+=1
end
track.each do |t|
t.push_silent(12)
end
ans=track[0].header(track.length,tempo)
track.each do |t|
ans+=t.encode
end
ans
end
end
end
end
if $0==__FILE__
require 'bio/io/flatfile'
ff=Bio::FlatFile.open(nil,ARGV[0])
ff.each do |f|
puts f.naseq[1..1000].to_midi
end
end
More information about the bioruby-cvs
mailing list