TxN

Untitled

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