FiberでMML


以前作ったMML再生用のスクリプトをFiberで書き直してみました。

def track(c, mml)
  return Fiber.new {
    ch = c
    dat = mml
    curev = -1

    loop do
      if curev == -1 || curev[1] == 0  then
        curev = dat.getnext()
        if curev == -1 then
          Fiber.yield(-1)
        end
        if curev[0] != -1 then
          tone($t, ch, curev[0])
        end
      elsif curev[0] != -1 && curev[1] == curev[2] then
        $t.write(0x50,0x08+ch,0x00)
        curev[1] -= 1
      else
        curev[1] -= 1
      end
      Fiber.yield(1)
    end
  }
end

# main

$t = BsdIic.new(0)
$t.write(0x50,0x07,0xf8)

if ch0.length != 0 then
  tr0 = track(0, MML.new(ch0))
else
  tr0 = nil
end
if ch1.length != 0 then
  tr1 = track(1, MML.new(ch1))
else
  tr1 = nil
end
if ch2.length != 0 then
  tr2 = track(2, MML.new(ch2))
else
  tr2 = nil
end

while (tr0 || tr1 || tr2)

  if tr0 && tr0.resume == -1 then
    tr0 = nil
  end
  if tr1 && tr1.resume == -1 then
    tr1 = nil
  end
  if tr2 && tr2.resume == -1 then
    tr2 = nil
  end

  tick = (60*1000*1000/(MML::gettempo*120)).to_i
  Sleep::usleep(tick)
end

各トラックをFiberにしてtick毎に処理を動かしています。