Advertisement
GitHubUser

soundApiOC

Mar 29th, 2022
485
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.41 KB | None | 0 0
  1. --[[Runs notes inside a table or a string (notes seperated by free spaces, then) using special syntax, the Note API and computer.beep
  2.   Examples:
  3.   "E5": Plays the note "E5" for the duration specified in the second parameter (default 0.125, equaling 120 bpm)
  4.   "-E5": Plays the note "E5" with double the specified duration
  5.   "E5_4": Plays the note "E5" with 4 times the specified duration, change "4" to any number x to play the note x times the duration specified
  6.   "P_4": Plays a pause with 4 times the specified duration, change "4" to any number x to play the note x times the duration specified
  7.   For note names, use the syntax of the strings of the Note API
  8.  
  9.   if you set the third parameter to true, you may insert a table containing tables or strings looking the same as explained above.
  10.   This will allow you to play multiple channels of a song simultaneously, up to 8 at a time.
  11.   This mode requires the mod Computronics to be present and the computer to contain a Beep Card from that mod.
  12. ]]
  13.  
  14. local n = require("note")
  15. local song = {}
  16.  
  17. local function insertSynchronized(tMain, tInsert)
  18.   tMain = tMain or {}
  19.   if not tInsert then
  20.     error("Error during song parsing, found nil insert table", 2)
  21.   elseif #tInsert == 0 then
  22.     return tMain
  23.   end
  24.   if #tMain == 0 then
  25.     for i,j in ipairs(tInsert) do
  26.       table.insert(tMain, {j[1], {j[2]}})
  27.     end
  28.     return tMain
  29.   end
  30.  
  31.   --now the fun begins
  32.  
  33.   for i,j in ipairs(tInsert) do
  34.     for k,v in ipairs(tMain) do
  35.       --is the time frame already there?
  36.       if v[1] == j[1] then
  37.         table.insert(v[2], j[2])
  38.         break
  39.       elseif  v[1] > j[1] then
  40.        --it is not.
  41.        table.insert(tMain, k, {j[1], {j[2]}})
  42.        break
  43.       end
  44.     end
  45.   end
  46.   return tMain
  47. end
  48.  
  49. function song.play(notes, shortest, multi)
  50.   if not shortest then shortest = 0.125 end
  51.   if type(shortest)~="number" then
  52.     shortest = 0.125
  53.   end
  54.   if shortest < 0.05 then
  55.     error("Error: Shortest note must not be smaller than 0.05", 2)
  56.   end
  57.   multi = multi or false
  58.   if type(multi)~="boolean" then
  59.     multi = false
  60.   end
  61.   if not multi then
  62.     local tNotes = notes
  63.     if type(tNotes) == "string" then
  64.         local tB = {}
  65.         for j in string.gmatch(notes,"%S+") do
  66.           table.insert(tB, j)
  67.         end
  68.         tNotes = tB
  69.     end
  70.     if type(tNotes) ~= "table" then
  71.       error("Wrong input given, song.play requires a table or a string as first parameter", 2)
  72.     end
  73.     local noteMap = {}
  74.     do
  75.       local duration
  76.       for i,j in ipairs(tNotes) do
  77.         if string.find(j,"P") then
  78.           duration = 0
  79.         elseif string.find(j,"%-") then
  80.           duration = 2
  81.         elseif string.find(j,"_") then
  82.           duration = tonumber(string.match(j,".*_(%d+)"))
  83.         else
  84.           duration = 1
  85.         end
  86.         if duration ~= 0 then
  87.           table.insert(noteMap, i, {string.match(j,"(%a.?%d)_?%d*"),shortest*duration})
  88.         else
  89.           table.insert(noteMap, i, {-1, shortest*tonumber(string.match(j,"P_(%d+)"))})
  90.         end
  91.       end
  92.     end
  93.     for i,j in ipairs(noteMap) do
  94.       if type(j[1]) == "number" then
  95.         os.sleep(j[2])
  96.       else
  97.         n.play(j[1], j[2])
  98.       end
  99.     end
  100.   else
  101.     --beep card mode
  102.     local component = require("component")
  103.     if not component.isAvailable("beep") then
  104.       error("No beep card found, not possible to have multiple sound channels")
  105.     end
  106.     local beep = component.beep
  107.     local freqMap = {}
  108.    
  109.     if not type(notes) == "table" then
  110.       error("Wrong input given, song.play in multi mode requires a table as first parameter", 2)
  111.     end
  112.     --parsing start
  113.    
  114.     for k,v in ipairs(notes) do
  115.       local duration
  116.       local timeMap = {}
  117.       local timecount = 0
  118.       local pause = -1
  119.       if(type(v) == "string") then
  120.         local tB = {}
  121.         for j in string.gmatch(notes,"%S+") do
  122.           table.insert(tB, j)
  123.         end
  124.         v = tB
  125.       end
  126.       for i,j in ipairs(v) do
  127.         if string.find(j,"P") then
  128.           --os.sleep(shortest*tonumber(string.match(j,"P_(%d+)")))
  129.           duration = 0
  130.         elseif string.find(j,"%-") then
  131.           duration = 2
  132.         elseif string.find(j,"_") then
  133.           duration = tonumber(string.match(j,".*_(%d+)"))
  134.         else
  135.           duration = 1
  136.         end
  137.         if duration ~= 0 then
  138.           table.insert(timeMap, {timecount, {n.freq(string.match(j,"(%a.?%d)_?%d*")), shortest*duration}})
  139.           timecount = timecount + duration
  140.         else
  141.           table.insert(timeMap, {timecount, {pause, shortest*tonumber(string.match(j,"P_(%d+)"))}})
  142.           timecount = timecount + tonumber(string.match(j,"P_(%d+)"))
  143.           pause = pause - 1
  144.         end
  145.       end
  146.       --timeMap: {{time, {freq, duration}}, {time2, freq2, duration2}}}
  147.       insertSynchronized(freqMap, timeMap)
  148.     end
  149.     --freqMap: {{time, {channel={freq, duration}, channel2={freq2, duration2}}}, {time3, {channel3={freq3, duration3}, channel4={freq4, duration4}}}}
  150.    
  151.     --parsing end
  152.    
  153.     for k,v in ipairs(freqMap) do
  154.       local fMap = {}
  155.       for i,j in pairs(v[2]) do
  156.         if type(j[1]) == "number" and j[1] >= 0 then
  157.           fMap[j[1]] = j[2]
  158.         else
  159.           --pause here
  160.         end
  161.       end
  162.       beep.beep(fMap)
  163.       if k < #freqMap then
  164.         os.sleep((freqMap[k+1][1] - v[1]) * shortest)
  165.       end
  166.     end
  167.   end
  168. end
  169.  
  170. return song
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement