class SMF::Sequence::RS
Public Class Methods
new(s, cb)
click to toggle source
# File lib/smf/io.rb, line 76 def initialize(s, cb) @s, @cb = s, cb end
Public Instance Methods
read()
click to toggle source
# File lib/smf/io.rb, line 259 def read begin rs = RS::PO.new(get_from_macbin || get_from_rmid || @s) ckid = rs.getn(4) unless ckid == 'MThd' @cb.error('not an SMF') end rs.skip(-4) until rs.eof? ckid = rs.getn(4) leng = rs.geti32 body = rs.getn(leng) case ckid when 'MThd' read_header(body) when 'MTrk' read_track(body) else @cb.unknownchunk(ckid, body) end end rescue EOFError @cb.error('unexpected EOF') end @cb.result end
Private Instance Methods
get_from_macbin()
click to toggle source
# File lib/smf/io.rb, line 238 def get_from_macbin begin if @s[0, 1] == "\000" && @s[74,1] == "\000" && @s[82,1] == "\000" && @s[65,4] == 'Midi' @s[128,@s[83,4].unpack('N')[0]] end rescue end end
get_from_rmid()
click to toggle source
# File lib/smf/io.rb, line 248 def get_from_rmid begin if @s[0,4] == 'RIFF' && @s[8,4] == 'RMID' @s[20,@s[16,4].unpack('V')[0]] end rescue end end
read_header(s)
click to toggle source
# File lib/smf/io.rb, line 78 def read_header(s) rs = RS::PO.new(s) format = rs.geti16 ntrks = rs.geti16 div1 = rs.getc div2 = rs.getc if (div1 & 0x80) == 0 tc = nil division = div1 << 8 | div2 else tc = 0x100 - div1 division = div2 end @cb.header(format, ntrks, division, tc) end
read_meta(type, data)
click to toggle source
# File lib/smf/io.rb, line 94 def read_meta(type, data) case type when 0x0 rs = RS::PO.new(data) num = rs.geti16 @cb.sequencenumber(num) when 0x1..0xf case type when 0x1; @cb.generalpurposetext(data) when 0x2; @cb.copyrightnotice(data) when 0x3; @cb.trackname(data) when 0x4; @cb.instrumentname(data) when 0x5; @cb.lyric(data) when 0x6; @cb.marker(data) when 0x7; @cb.cuepoint(data) when 0x8; @cb.programname(data) when 0x9; @cb.devicename(data) when 0xa; @cb.text0a(data) when 0xb; @cb.text0b(data) when 0xc; @cb.text0c(data) when 0xd; @cb.text0d(data) when 0xe; @cb.text0e(data) when 0xf; @cb.text0f(data) end when 0x20 rs = RS::PO.new(data) ch = rs.getc @cb.channelprefix(ch) when 0x21 rs = RS::PO.new(data) num = rs.getc @cb.midiport(num) when 0x2f @cb.endoftrack when 0x51 rs = RS::PO.new(data) tempo = rs.geti24 @cb.settempo(tempo) when 0x54 rs = RS::PO.new(data) hr = rs.getc tc = [24, 25, 29, 30][(hr >> 5) & 0x3] hr &= 0x1f mn = rs.getc se = rs.getc fr = rs.getc ff = rs.getc @cb.smpteoffset(hr, mn, se, fr, ff, tc) when 0x58 rs = RS::PO.new(data) nn = rs.getc dd = rs.getc cc = rs.getc bb = rs.getc @cb.timesignature(nn, dd, cc, bb) when 0x59 rs = RS::PO.new(data) sf = rs.getc mi = rs.getc sf = RS::PO.u2s(sf, 8) @cb.keysignature(sf, mi) when 0x7f @cb.sequencerspecific(data) else @cb.unknownmeta(type, data) end end
read_track(s)
click to toggle source
# File lib/smf/io.rb, line 162 def read_track(s) @cb.track_start rs = RS::PO.new(s) running = 0 until rs.eof? @cb.delta(rs.getl) stat = rs.getc if (stat & 0x80) == 0 rs.skip(-1) stat = running else case stat when 0x80..0xef; running = stat when 0xf0..0xf7; running = 0 end end case stat when 0x80..0x8f @cb.noteoff(stat & 0xf, rs.getc, rs.getc) when 0x90..0x9f @cb.noteon(stat & 0xf, rs.getc, rs.getc) when 0xa0..0xaf @cb.polyphonickeypressure(stat & 0xf, rs.getc, rs.getc) when 0xb0..0xbf n = rs.getc v = rs.getc if n < 0x78 @cb.controlchange(stat & 0xf, n, v) else case n when 0x78; @cb.allsoundoff(stat & 0xf) when 0x79; @cb.resetallcontrollers(stat & 0xf) when 0x7a; @cb.localcontrol(stat & 0xf, v) when 0x7b; @cb.allnotesoff(stat & 0xf) when 0x7c; @cb.omnioff(stat & 0xf) when 0x7d; @cb.omnion(stat & 0xf) when 0x7e; @cb.monomode(stat & 0xf, v) when 0x7f; @cb.polymode(stat & 0xf) end end when 0xc0..0xcf @cb.programchange(stat & 0xf, rs.getc) when 0xd0..0xdf @cb.channelpressure(stat & 0xf, rs.getc) when 0xe0..0xef lsb = rs.getc msb = rs.getc val = (lsb | msb << 7) - 0x2000 @cb.pitchbendchange(stat & 0xf, val) when 0xf0, 0xf7 len = rs.getl data = rs.getn(len) if stat == 0xf0 @cb.exclusivef0(data) else @cb.exclusivef7(data) end when 0xff type = rs.getc len = rs.getl data = rs.getn(len) read_meta(type, data) else until rs.eof? unless (rs.getc & 0x80) == 0 rs.skip(-1) break end end end end @cb.track_end end