Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local function mread(amm)
- local str = ""
- for i = 1, amm do
- str = str .. string.char(file:read())
- end
- return str
- end
- function readVarLen()
- value = 0
- c = 0
- value = string.byte(mread(1))
- totalRead = totalRead + 1
- if math.floor(value / 2 ^ 7) == 1 then
- value = value - 128
- repeat
- c1 = string.byte(mread(1))
- totalRead = totalRead + 1
- c = math.floor( c1 / 2 ^ 7)
- if c == 1 then c1 = c1 -128 end
- value = value * 2 ^ 7 + c1
- until c == 0
- end
- return value
- end
- function round(num, idp)
- local mult = 10^(idp or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- function readEvent()
- totalRead = totalRead + 1
- data = string.byte(mread(1))
- if data ~= 0xFF then
- event = math.floor(data / 2 ^ 4)
- channel = data - event * 2 ^ 4
- else
- event = 0xFF
- channel = -1
- end
- return event,channel
- end
- function readMetaEvent(deltaTime)
- --for now we only care about set tempo events
- eventType = string.byte(mread(1))
- totalRead = totalRead + 1
- if eventType == 81 then -- Tempo type event
- local length = string.byte(mread(1))
- Mpqn = readShortInt()
- MpM = 60000000
- totalRead = totalRead + 1
- miliseconds_Per_quarter_note = MpM / currentTempo
- microseconds_per_deltaUnit = math.floor(Mpqn / timeDev)
- --print("before BPM: "..currentTempo)
- currentTempo = math.floor(MpM / Mpqn)
- --print("after BPM: "..currentTempo)
- --print("microseconds from last event "..deltaTime * microseconds_per_deltaUnit)
- --print("seconds from last event "..(deltaTime * microseconds_per_deltaUnit)/ 1000000)
- --print("microseconds_per_deltaUnit "..microseconds_per_deltaUnit)
- --print("microseconds_Per_quarter_note "..Mpqn)
- --use total delta time and then when reading the notes from file
- --use the table to expand notes to seconds time
- --the table will store how long a delta unit will last in microseconds
- if not tempo[0] then tempo[1] = microseconds_per_deltaUnit end
- for i = 1,deltaTime do
- tempo[i+deltaTimeTempo] = microseconds_per_deltaUnit
- end
- deltaTimeTempo = deltaTimeTempo + deltaTime
- --print("deltaTime: "..deltaTimeTempo)
- else
- local length = readVarLen()
- --print("skipping: "..eventType.." by: "..length)
- mread(length)
- totalRead = totalRead + length
- end
- end
- function readNormEvent(dt, channel)
- if event == 9 then
- --note on event 2 bytes
- time = 0
- for i = 1,dt do
- if #tempo > i+totalTime then
- time = time + tempo[i+totalTime]/1000000-- if there is a value for it add it
- else
- time = time + tempo[#tempo]/1000000-- else add the last value (for after the last tempo event)
- end
- end
- local note = string.byte(mread(1))
- local velocity = string.byte(mread(1))
- totalRead = totalRead + 2
- totalRealTime = totalRealTime + time
- --print("starts at: "..totalRealTime)
- --print("deltaTime: "..totalTime)
- curnotes[note] = {totalRealTime,velocity}
- --print("Note on "..note.." velocity "..velocity)
- elseif event == 8 then
- time = 0
- for i = 1,dt do
- if #tempo > i+totalTime then
- time = time + tempo[i+totalTime]/1000000-- if there is a value for it add it
- else
- time = time + tempo[#tempo]/1000000-- else add the last value (for after the last tempo event)
- end
- end
- totalRealTime = totalRealTime + time
- ----print the time the note has lasted
- local note = string.byte(mread(1))
- local velocity = string.byte(mread(1))
- if curnotes[note] then
- if type(curnotes[note]) == "table" then
- --print("time lasted: "..totalRealTime - curnotes[note][1])--this also should be where the notes are added to the table for display
- notes[#notes+1] = {curnotes[note][1],totalRealTime,note,curnotes[note][2],CurTrack,channel}
- curnotes[note] = nil
- end
- end
- totalRead = totalRead + 2
- elseif event == 12 or event == 13 then
- time = 0
- for i = 1,dt do
- if #tempo > i+totalTime then
- time = time + tempo[i+totalTime]/1000000-- if there is a value for it add it
- else
- time = time + tempo[#tempo]/1000000-- else add the last value (for after the last tempo event)
- end
- end
- totalRealTime = totalRealTime + time
- --ignore by reading 1 byte
- mread(1)
- totalRead = totalRead + 1
- else
- time = 0
- for i = 1,dt do
- if #tempo > i+totalTime then
- time = time + tempo[i+totalTime]/1000000-- if there is a value for it add it
- else
- time = time + tempo[#tempo]/1000000-- else add the last value (for after the last tempo event)
- end
- end
- totalRealTime = totalRealTime + time
- mread(2)
- totalRead = totalRead + 2
- end
- end
- function bytes_to_int(a,b,c,d)--big Endian
- sum = 0
- sum = sum + a * 2 ^ 24
- sum = sum + b * 2 ^ 16
- sum = sum + c * 2 ^ 8
- sum = sum + d
- return sum
- end
- function readInt()
- e = string.byte(mread(1))
- f = string.byte(mread(1))
- g = string.byte(mread(1))
- h = string.byte(mread(1))
- totalRead = totalRead + 4
- return bytes_to_int(e,f,g,h)
- end
- function readShortInt()
- f = string.byte(mread(1))
- g = string.byte(mread(1))
- h = string.byte(mread(1))
- e = 0
- totalRead = totalRead + 3
- return bytes_to_int(e,f,g,h)
- end
- function readShort()
- g = string.byte(mread(1))
- h = string.byte(mread(1))
- e = 0
- f = 0
- totalRead = totalRead + 2
- return bytes_to_int(e,f,g,h)
- end
- function load()
- currentTempo = 120 -- BPM
- totalRead = 0
- totalTime = 0
- totalRealTime = 0
- deltaTimeTempo = 0
- curnotes = {}
- notes = {}
- num = 2
- CurTrack = 1
- TrackColors = {}
- for i = 0,127 do
- curnotes[i] = 0-- this will be the time that the midi note started
- end
- music = {}--table of note on/off events with ms delta time
- file = io.open("ar.mid","rb")
- readHeader()
- tempo = {500000/timeDev}
- for i = 1,tracks do
- TrackColors[i] = {math.random(0,255),math.random(0,255),math.random(0,255)}
- CurTrack = i
- readTrack(i)
- end
- timeTable = {}
- findTimeTable()
- --[[
- for i,k in pairs(timeTable) do
- print(i)
- for l,m in pairs(k) do
- print (l,m)
- end
- end
- ]]
- for j = 1,1000 do
- i = (j*0.005)
- print(i)
- if timeTable[i] then
- for l,m in pairs(timeTable[i]) do
- print (l,m)
- end
- end
- end
- --print(timeDev)
- --love.event.push("quit")
- timeElapsed = 0
- --print(notes[1][1],notes[1][2])
- local d = fs.open("/new", "w")
- d.write(textutils.serialize(notes))
- d.close()
- end
- function comp(a,b)
- end
- function draw()
- local scalar = 2/100
- for i = 1,#notes do
- love.graphics.setColor(TrackColors[notes[i][5]][1],TrackColors[notes[i][5]][2],TrackColors[notes[i][5]][3])
- if notes[i][1] < timeElapsed and notes[i][2] > timeElapsed then
- --love.graphics.rectangle("fill",0,(love.graphics.getHeight()/120)*notes[i][3],notes[i][4],math.floor(love.graphics.getHeight()/120))
- local FadeAmmount = notes[i][2] - notes[i][1]
- local faded = math.abs((timeElapsed - notes[i][2]) / FadeAmmount)
- --if notes[i][3] % 10 == 0 then --print(faded,notes[i][3]) end
- love.graphics.circle("fill",400,(love.graphics.getHeight()/120)*(120-notes[i][3]),(notes[i][4]/5)*faded,30)--(timeElapsed-notes[i][2])*50,30)
- end
- for j = 1,100 do
- if notes[i][1] < timeElapsed+(scalar*j) and notes[i][2] > timeElapsed+(scalar*j) then
- love.graphics.rectangle("fill",j*4+400,(love.graphics.getHeight()/120)*(120-notes[i][3]),4,math.floor(love.graphics.getHeight()/120))
- end
- end
- end
- --[[
- start = round(timeElapsed,2)
- if start > timeElapsed then
- start = start - 0.005
- elseif start < timeElapsed then
- start = start + 0.005
- end
- for i = 1,400 do
- --print(start+(0.005*i))
- if timeTable[start+(0.005*i)] then
- for j = 1,#timeTable[start+(0.005*i)] do
- --print("note: "..start+(0.005*i))
- --if start > 23 and start < 27 then print(start,timeTable[start+(0.005*i)][1],timeTable[start+(0.005*i)][2],timeTable[start+(0.005*i)][3],timeTable[start+(0.005*i)][4]) ; print("hi") end
- love.graphics.rectangle("fill",400+i,(love.graphics.getHeight()/120)*(120-timeTable[start+(0.005*i)][j]),1,600/120)
- end
- if start > 24.5 and start < 26 then print(start+(0.005*i),timeTable[start+(0.005*i)][1],timeTable[start+(0.005*i)][2],timeTable[start+(0.005*i)][3],timeTable[start+(0.005*i)][4]) ; print("hi") end
- end
- end
- ]]
- love.graphics.setColor(255,255,255,255)
- --peering into the futurbe
- --[[
- local scalar = 5/400
- for j = 1,400 do
- for i = 1,#notes do
- if notes[i][1] < timeElapsed+(scalar*j) and notes[i][2] > timeElapsed+(scalar*j) then
- love.graphics.rectangle("fill",j+400,(love.graphics.getHeight()/120)*notes[i][3],1,math.floor(love.graphics.getHeight()/120))
- end
- end
- end
- ]]
- love.graphics.print(timeElapsed,0,0)
- love.graphics.print("FPS: "..love.timer.getFPS(),200,0)
- end
- function update(timChange)
- timeElapsed = timeElapsed + timChange
- end
- function keypressed(key)
- if key == " " then
- bgm = love.audio.newSource("Ximares - Cohens Masterpiece Transcription.wav", "stream")
- love.audio.play(bgm)
- timeElapsed = 0
- elseif key == "backspace" then
- love.audio.stop()
- end
- end
- function readHeader()
- local Test = mread(4)
- if Test ~= "MThd" then error("Not a valid midi file") end
- local size = readInt()-- always gonna be 6
- format = readShort()
- --print("format "..format)
- tracks = readShort()
- --print("tracks "..tracks)
- timeDev = readShort()
- end
- function readTrack(tra)
- local evenType = mread(4)
- ----print(type)
- deltaTimeTempo = 0
- totalRealTime = 0
- totalRead = 0
- totalTime = 0
- --print("first four "..evenType)
- if evenType ~= "MTrk" then
- if mread(4) ~= "MTrk" then
- error("Missing or corrupted track")
- end
- end
- local size = readInt()
- while size > totalRead do
- local dt = readVarLen()
- ----print(dt)
- ----print(totalRead+ 0x16)
- local event,channel = readEvent()
- --print(event,channel)
- ----print(totalRead+ 0x16)
- if event == 255 then
- readMetaEvent(dt)
- else --its a normal event read it accordingly
- readNormEvent(dt, channel)--nothing yet
- end
- totalTime = totalTime + dt
- --print(totalTime)
- end
- --garbage = mread(size)
- end
- function findTimeTable()
- timeTable = {}
- for i = 1,#notes do
- start = round(notes[i][1],2)
- if start > notes[i][1] then
- start = start - 0.005
- elseif start < notes[i][1] then
- start = start + 0.005
- end
- --print(notes[i][1],notes[i][2])
- k = 0
- --print(start,notes[i][1],notes[i][3])
- for j = start,notes[i][2],0.005 do
- --print("j: "..j.." N: "..i)
- if not timeTable[j] then
- timeTable[j] = {notes[i][3]}
- --print("Insterted: "..notes[i][3].." into: "..j)
- else
- timeTable[j][#timeTable[j]+1] = notes[i][3]
- end
- k = k + 1
- --print(j)
- end
- pr = false
- --print(k.." "..notes[i][2])
- end
- end
- load()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement