Advertisement
aynoblo

musique?

Apr 7th, 2020
609
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.29 KB | None | 0 0
  1. local wave = { }
  2. wave.version = "0.1.4"
  3.  
  4. wave._oldSoundMap = {"harp", "bassattack", "bd", "snare", "hat"}
  5. wave._newSoundMap = {"harp", "bass", "basedrum", "snare", "hat"}
  6. wave._defaultThrottle = 99
  7. wave._defaultClipMode = 1
  8. wave._maxInterval = 1
  9. wave._isNewSystem = false
  10. if _HOST then
  11.     wave._isNewSystem = _HOST:sub(15, #_HOST) >= "1.80"
  12. end
  13.  
  14. wave.context = { }
  15. wave.output = { }
  16. wave.track = { }
  17. wave.instance = { }
  18.  
  19. function wave.createContext(clock, volume)
  20.     clock = clock or os.clock()
  21.     volume = volume or 1.0
  22.  
  23.     local context = setmetatable({ }, {__index = wave.context})
  24.     context.outputs = { }
  25.     context.instances = { }
  26.     context.vs = {0, 0, 0, 0, 0}
  27.     context.prevClock = clock
  28.     context.volume = volume
  29.     return context
  30. end
  31.  
  32. function wave.context:addOutput(...)
  33.     local output = wave.createOutput(...)
  34.     self.outputs[#self.outputs + 1] = output
  35.     return output
  36. end
  37.  
  38. function wave.context:addOutputs(...)
  39.     local outs = {...}
  40.     if #outs == 1 then
  41.         if not getmetatable(outs) then
  42.             outs = outs[1]
  43.         else
  44.             if getmetatable(outs).__index ~= wave.outputs then
  45.                 outs = outs[1]
  46.             end
  47.         end
  48.     end
  49.     for i = 1, #outs do
  50.         self:addOutput(outs[i])
  51.     end
  52. end
  53.  
  54. function wave.context:removeOutput(out)
  55.     if type(out) == "number" then
  56.         table.remove(self.outputs, out)
  57.         return
  58.     elseif type(out) == "table" then
  59.         if getmetatable(out).__index == wave.output then
  60.             for i = 1, #self.outputs do
  61.                 if out == self.outputs[i] then
  62.                     table.remove(self.outputs, i)
  63.                     return
  64.                 end
  65.             end
  66.             return
  67.         end
  68.     end
  69.     for i = 1, #self.outputs do
  70.         if out == self.outputs[i].native then
  71.             table.remove(self.outputs, i)
  72.             return
  73.         end
  74.     end
  75. end
  76.  
  77. function wave.context:addInstance(...)
  78.     local instance = wave.createInstance(...)
  79.     self.instances[#self.instances + 1] = instance
  80.     return instance
  81. end
  82.  
  83. function wave.context:removeInstance(instance)
  84.     if type(instance) == "number" then
  85.         table.remove(self.instances, instance)
  86.     else
  87.         for i = 1, #self.instances do
  88.             if self.instances == instance then
  89.                 table.remove(self.instances, i)
  90.                 return
  91.             end
  92.         end
  93.     end
  94. end
  95.  
  96. function wave.context:playNote(note, pitch, volume)
  97.     volume = volume or 1.0
  98.  
  99.     self.vs[note] = self.vs[note] + volume
  100.     for i = 1, #self.outputs do
  101.         self.outputs[i]:playNote(note, pitch, volume * self.volume)
  102.     end
  103. end
  104.  
  105. function wave.context:update(interval)
  106.     local clock = os.clock()
  107.     interval = interval or (clock - self.prevClock)
  108.  
  109.     self.prevClock = clock
  110.     if interval > wave._maxInterval then
  111.         interval = wave._maxInterval
  112.     end
  113.     for i = 1, #self.outputs do
  114.         self.outputs[i].notes = 0
  115.     end
  116.     for i = 1, 5 do
  117.         self.vs[i] = 0
  118.     end
  119.     if interval > 0 then
  120.         for i = 1, #self.instances do
  121.             local notes = self.instances[i]:update(interval)
  122.             for j = 1, #notes / 3 do
  123.                 self:playNote(notes[j * 3 - 2], notes[j * 3 - 1], notes[j * 3])
  124.             end
  125.         end
  126.     end
  127. end
  128.  
  129.  
  130.  
  131. function wave.createOutput(out, volume, filter, throttle, clipMode)
  132.     volume = volume or 1.0
  133.     filter = filter or {true, true, true, true, true}
  134.     throttle = throttle or wave._defaultThrottle
  135.     clipMode = clipMode or wave._defaultClipMode
  136.  
  137.     local output = setmetatable({ }, {__index = wave.output})
  138.     output.native = out
  139.     output.volume = volume
  140.     output.filter = filter
  141.     output.notes = 0
  142.     output.throttle = throttle
  143.     output.clipMode = clipMode
  144.     if type(out) == "function" then
  145.         output.nativePlayNote = out
  146.         output.type = "custom"
  147.         return output
  148.     elseif type(out) == "string" then
  149.         if peripheral.getType(out) == "iron_noteblock" then
  150.             if wave._isNewSystem then
  151.                 local nb = peripheral.wrap(out)
  152.                 output.type = "iron_noteblock"
  153.                 function output.nativePlayNote(note, pitch, volume)
  154.                     if output.volume * volume > 0 then
  155.                         nb.playSound("minecraft:block.note."..wave._newSoundMap[note], volume, math.pow(2, (pitch - 12) / 12))
  156.                     end
  157.                 end
  158.                 return output
  159.             end
  160.         end
  161.     elseif type(out) == "table" then
  162.         if out.execAsync then
  163.             output.type = "commands"
  164.             if wave._isNewSystem then
  165.                 function output.nativePlayNote(note, pitch, volume)
  166.                     out.execAsync("playsound minecraft:block.note."..wave._newSoundMap[note].." record @a ~ ~ ~ "..tostring(volume).." "..tostring(math.pow(2, (pitch - 12) / 12)))
  167.                 end
  168.             else
  169.                 function output.nativePlayNote(note, pitch, volume)
  170.                     out.execAsync("playsound note."..wave._oldSoundMap[note].." @a ~ ~ ~ "..tostring(volume).." "..tostring(math.pow(2, (pitch - 12) / 12)))
  171.                 end
  172.             end
  173.             return output
  174.         elseif getmetatable(out) then
  175.             if getmetatable(out).__index == wave.output then
  176.                 return out
  177.             end
  178.         end
  179.     end
  180. end
  181.  
  182. function wave.scanOutputs()
  183.     local outs = { }
  184.     if commands then
  185.         outs[#outs + 1] = wave.createOutput(commands)
  186.     end
  187.     local sides = peripheral.getNames()
  188.     for i = 1, #sides do
  189.         if peripheral.getType(sides[i]) == "iron_noteblock" then
  190.             outs[#outs + 1] = wave.createOutput(sides[i])
  191.         end
  192.     end
  193.     return outs
  194. end
  195.  
  196. function wave.output:playNote(note, pitch, volume)
  197.     volume = volume or 1.0
  198.  
  199.     if self.clipMode == 1 then
  200.         if pitch < 0 then
  201.             pitch = 0
  202.         elseif pitch > 24 then
  203.             pitch = 24
  204.         end
  205.     elseif self.clipMode == 2 then
  206.         if pitch < 0 then
  207.             while pitch < 0 do
  208.                 pitch = pitch + 12
  209.             end
  210.         elseif pitch > 24 then
  211.             while pitch > 24 do
  212.                 pitch = pitch - 12
  213.             end
  214.         end
  215.     end
  216.     if self.filter[note] and self.notes < self.throttle then
  217.         self.nativePlayNote(note, pitch, volume * self.volume)
  218.         self.notes = self.notes + 1
  219.     end
  220. end
  221.  
  222.  
  223.  
  224. function wave.loadTrack(path)
  225.     local track = setmetatable({ }, {__index = wave.track})
  226.     local handle = fs.open(path, "rb")
  227.     if not handle then return end
  228.  
  229.     local function readInt(size)
  230.         local num = 0
  231.         for i = 0, size - 1 do
  232.             local byte = handle.read()
  233.             if not byte then -- dont leave open file handles no matter what
  234.                 handle.close()
  235.                 return
  236.             end
  237.             num = num + byte * (256 ^ i)
  238.         end
  239.         return num
  240.     end
  241.     local function readStr()
  242.         local length = readInt(4)
  243.         if not length then return end
  244.         local data = { }
  245.         for i = 1, length do
  246.             data[i] = string.char(handle.read())
  247.         end
  248.         return table.concat(data)
  249.     end
  250.  
  251.     -- Part #1: Metadata
  252.     track.length = readInt(2) -- song length (ticks)
  253.     track.height = readInt(2) -- song height
  254.     track.name = readStr() -- song name
  255.     track.author = readStr() -- song author
  256.     track.originalAuthor = readStr() -- original song author
  257.     track.description = readStr() -- song description
  258.     track.tempo = readInt(2) / 100 -- tempo (ticks per second)
  259.     track.autoSaving = readInt(1) == 0 and true or false -- auto-saving
  260.     track.autoSavingDuration = readInt(1) -- auto-saving duration
  261.     track.timeSignature = readInt(1) -- time signature (3 = 3/4)
  262.     track.minutesSpent = readInt(4) -- minutes spent
  263.     track.leftClicks = readInt(4) -- left clicks
  264.     track.rightClicks = readInt(4) -- right clicks
  265.     track.blocksAdded = readInt(4) -- blocks added
  266.     track.blocksRemoved = readInt(4) -- blocks removed
  267.     track.schematicFileName = readStr() -- midi/schematic file name
  268.  
  269.     -- Part #2: Notes
  270.     track.layers = { }
  271.     for i = 1, track.height do
  272.         track.layers[i] = {name = "Layer "..i, volume = 1.0}
  273.         track.layers[i].notes = { }
  274.     end
  275.  
  276.     local tick = 0
  277.     while true do
  278.         local tickJumps = readInt(2)
  279.         if tickJumps == 0 then break end
  280.         tick = tick + tickJumps
  281.         local layer = 0
  282.         while true do
  283.             local layerJumps = readInt(2)
  284.             if layerJumps == 0 then break end
  285.             layer = layer + layerJumps
  286.             if layer > track.height then -- nbs can be buggy
  287.                 for i = track.height + 1, layer do
  288.                     track.layers[i] = {name = "Layer "..i, volume = 1.0}
  289.                     track.layers[i].notes = { }
  290.                 end
  291.                 track.height = layer
  292.             end
  293.             local instrument = readInt(1)
  294.             local key = readInt(1)
  295.             if instrument <= 4 then -- nbs can be buggy
  296.                 track.layers[layer].notes[tick * 2 - 1] = instrument + 1
  297.                 track.layers[layer].notes[tick * 2] = key - 33
  298.             end
  299.         end
  300.     end
  301.  
  302.     -- Part #3: Layers
  303.     for i = 1, track.height do
  304.         local name = readStr()
  305.         if not name then break end -- if layer data doesnt exist, abort
  306.         track.layers[i].name = name
  307.         track.layers[i].volume = readInt(1) / 100
  308.     end
  309.  
  310.     handle.close()
  311.     return track
  312. end
  313.  
  314.  
  315.  
  316. function wave.createInstance(track, volume, playing, loop)
  317.     volume = volume or 1.0
  318.     playing = (playing == nil) or playing
  319.     loop = (loop ~=  nil) and loop
  320.  
  321.     if getmetatable(track).__index == wave.instance then
  322.         return track
  323.     end
  324.     local instance = setmetatable({ }, {__index = wave.instance})
  325.     instance.track = track
  326.     instance.volume = volume or 1.0
  327.     instance.playing = playing
  328.     instance.loop = loop
  329.     instance.tick = 1
  330.     return instance
  331. end
  332.  
  333. function wave.instance:update(interval)
  334.     local notes = { }
  335.     if self.playing then
  336.         local dticks = interval * self.track.tempo
  337.         local starttick = self.tick
  338.         local endtick = starttick + dticks
  339.         local istarttick = math.ceil(starttick)
  340.         local iendtick = math.ceil(endtick) - 1
  341.         for i = istarttick, iendtick do
  342.             for j = 1, self.track.height do
  343.                 if self.track.layers[j].notes[i * 2 - 1] then
  344.                     notes[#notes + 1] = self.track.layers[j].notes[i * 2 - 1]
  345.                     notes[#notes + 1] = self.track.layers[j].notes[i * 2]
  346.                     notes[#notes + 1] = self.track.layers[j].volume
  347.                 end
  348.             end
  349.         end
  350.         self.tick = self.tick + dticks
  351.  
  352.         if endtick > self.track.length then
  353.             self.tick = 1
  354.             self.playing = self.loop
  355.         end
  356.     end
  357.     return notes
  358. end
  359.  
  360.  
  361.  
  362. return wave
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement