Advertisement
Hardy

OC Nbs music player fixed

Aug 1st, 2016
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.19 KB | None | 0 0
  1.  
  2.  
  3. --[[
  4.    nbs music player
  5.    Простая программка для проигрывания музыки формата nbs, использующая музыкальные блоки из Computronics.
  6.    Музыку и редактор для нее можно найти, загуглив Minecraft Note Block Studio.
  7.  
  8.    Для использования подключите к компьютеру кабелем железные музыкальные блоки. Рекомендуемое количество - 8, можно больше или меньше.
  9.  
  10.    TxN, 2016  
  11. ]]
  12.  
  13. local component = require("component")
  14. local fs = require("filesystem")
  15. local shell = require("shell")
  16. local computer = require("computer")
  17. local speedoverride = 1
  18. local players_list = {}
  19.  
  20. local song = {}
  21.  
  22. local NBS_MC_inst = {
  23.   [1] = 0,
  24.   [2] = 4,
  25.   [3] = 1,
  26.   [4] = 2,
  27.   [5] = 3,
  28.   [6] = 5,
  29.   [7] = 6
  30. }
  31.  
  32. player = {}
  33.  
  34. function player.upd(self)
  35.     --curtime = computer.uptime()
  36.     curtime = os.time() / 60
  37.     if curtime >= self.next_tick_time then
  38.         -- Достаем информацию о нотах из текущего тика, настраиваем музыкальные блоки
  39.         self.block_position = song:set_tick(players_list, self.current_tick, self.block_position)
  40.  
  41.         -- Играем аккорд
  42.         players_list:play_chord()
  43.         players_list:clear_players()
  44.         -- Инкрементим тик
  45.         self.current_tick = self.current_tick + 1
  46.         self.next_tick_time  = curtime + 1/song.tempo/speedoverride
  47.        
  48.         if self.current_tick == song.length then
  49.            self.play_complete = true
  50.         end
  51.     end
  52. end
  53.  
  54.  
  55. function get_players()
  56.   local i = 1
  57.   for k,v in pairs(component.list("iron_noteblock")) do
  58.     local pl = {}
  59.     pl.index = i
  60.     pl.instrument = 0
  61.     pl.note = 0
  62.     pl.interface =  component.proxy(k)
  63.     pl.busy = false
  64.     table.insert(players_list,pl)
  65.     i = i + 1
  66.   end
  67. end
  68.  
  69. function set_player(player,instr, nt)
  70.    player.instrument = instr
  71.    player.note = nt
  72.    player.busy = true
  73. end
  74.  
  75. function players_list:get_free_player()
  76.     for k,v in pairs (self) do
  77.       if v.busy == false then
  78.           return v
  79.       end
  80.     end
  81.    
  82.     return nil
  83. end
  84.  
  85. function players_list:clear_players()
  86.     for k,v in pairs (self) do
  87.       if (type(v) == "table") then
  88.         v.busy = false
  89.         v.instrument = 0
  90.         v.note = 0
  91.       end
  92.     end  
  93. end
  94.  
  95. function players_list:play_chord()
  96.     for k,v in pairs (self) do
  97.       if (type(v) == "table") then
  98.         if v.busy == true then
  99.            v.interface.playNote(v.instrument, v.note)
  100.         end
  101.       end
  102.     end  
  103. end
  104.  
  105. function song:loadSong(path)
  106.     --Кинуть ошибку, если такого файла не существует
  107.     if not fs.exists(path) then error("File \""..path.."\" does not exist.\n") end
  108.     local file = io.open(path, "rb")
  109.     self.length = get_int_16(getByte(file),getByte(file))
  110.    
  111.     self.height = get_int_16(getByte(file),getByte(file))
  112.     self.name = readString(file)
  113.     self.author = readString(file)
  114.     self.org_author = readString(file)
  115.     self.description = readString(file)
  116.    
  117.     self.tempo =  get_int_16(getByte(file),getByte(file))
  118.     self.tempo = self.tempo * 0.01
  119.     local tmp = file:read(23) -- тут ненужная информация, ну совсем ненужная
  120.     tmp = readString(file) -- тут тоже, но это строка вдобавок
  121.    
  122.     print(self.name)
  123.     print(self.description)
  124.     print("Length in ticks: "..self.length)
  125.    
  126.     self.song_ticks = {}
  127.    
  128.     local tick = -1
  129.     local jumps = 0
  130.    
  131.     local counter = 1
  132.     while (true) do
  133.      
  134.       jumps = get_int_16(getByte(file),getByte(file))
  135.       if jumps == 0 then
  136.         break
  137.       end
  138.      
  139.       tick = tick + jumps
  140.       local layer = -1
  141.      
  142.      
  143.       while (true) do
  144.         self.song_ticks[counter] = {}
  145.         jumps = get_int_16(getByte(file),getByte(file))
  146.         if jumps == 0 then
  147.           break
  148.         end
  149.         layer = layer + jumps
  150.         self.song_ticks[counter].instrument = NBS_MC_inst[getByte(file)+1]
  151.         --if(self.song_ticks[counter].instrument==1) then
  152.         --  self.song_ticks[counter].instrument=4
  153.         --end
  154.         self.song_ticks[counter].note = getByte(file) - 33
  155.         self.song_ticks[counter].layer = layer
  156.         self.song_ticks[counter].tick = tick
  157.         counter = counter + 1
  158.       end
  159.     end
  160.    
  161.     self.blocks_num = counter -1
  162.    
  163.     print("Load complete") 
  164.     file:close()
  165. end
  166.  
  167.  
  168. function song:set_tick(players, cur_tick, position)
  169.     while (true) do
  170.      if self.song_ticks[position].tick == cur_tick then
  171.        freeplayer = players:get_free_player()
  172.        if (freeplayer ~= nil) then
  173.          set_player(freeplayer,self.song_ticks[position].instrument,self.song_ticks[position].note)
  174.        end
  175.        position = position + 1
  176.      else
  177.        break
  178.      end
  179.     end
  180.    
  181.     return position
  182. end
  183.  
  184. function getByte(f)
  185.   return string.byte(f:read(1))
  186. end
  187.  
  188. function readString(file)
  189.   local strln = get_int_32(getByte(file),getByte(file),getByte(file),getByte(file))
  190.   local str = ""
  191.   str = file:read(strln)
  192.   return str
  193.  end
  194.  
  195. function get_int_16(b1, b2)
  196.     local n = b1 + 256 * b2
  197.     n = (n > 32767) and (n - 32768) or n
  198.     return n
  199. end  
  200.  
  201. function get_int_32(b1, b2, b3, b4)
  202.       if not b4 then error("need four bytes to convert to int",2) end
  203.       local n = b1 + b2*256 + b3*65536 + b4*16777216
  204.       n = (n > 2147483647) and (n - 4294967296) or n
  205.       return n
  206. end
  207.  
  208.  
  209. function player:init(songPath)
  210. -- находим подключенные к компьютеру музыкальные блоки
  211.     get_players()
  212. -- Задаем начальные параметры
  213.     self.play_complete = false
  214.     self.current_tick = 0
  215.     self.block_position = 1
  216.     self.next_tick_time = computer.uptime()
  217.     -- Загружаем песню из файла
  218.     song:loadSong(songPath)
  219. end
  220.  
  221.  
  222. --------
  223. -- Тут собственно точка входа программы
  224. --------
  225.  
  226. local args = shell.parse(...)
  227. if #args == 0 then
  228.   io.write("Usage: musicPlayer <path_to_song_file>\n")
  229.   return 1
  230. end
  231. if args[2] then
  232.     speedoverride=tonumber(args[2])
  233.     print(speedoverride)
  234. end
  235.  
  236. local path = args[1]
  237.  
  238. player:init(path)
  239.  
  240. --Играем песню пока не кончится
  241. while not player.play_complete do
  242.     player.upd(player)
  243.     os.sleep(0.0001)
  244. end
  245. print("Song played successfully")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement