local owner = owner or game.Players:WaitForChild("Synarx")
local https = game:GetService("HttpService")
function get_cover_art(song)
local got_recording_data, recording_data = pcall(function()
return https:GetAsync(string.format("https://musicbrainz.org/ws/2/recording?query=%s&fmt=json", https:UrlEncode(song)))
end)
if not got_recording_data then return end
recording_data = https:JSONDecode(recording_data)
local releases = recording_data.recordings[1].releases
local latest_release = releases[#releases]
local got_cover_art, cover_art = pcall(function()
return https:GetAsync("http://coverartarchive.org/release/" .. latest_release.id)
end)
if not got_cover_art then return end
return https:JSONDecode(cover_art).images
end
local JPEG = require(110533939037567) --loadstring(https:GetAsync("https://sbin.wya.rip/lib/JPEG.luau"))()
local CanvasDraw = loadstring(https:GetAsync("https://sbin.wya.rip/lib/CanvasDraw.luau"))()
local billboardGui = Instance.new("BillboardGui")
billboardGui.Name = "BillboardGui"
billboardGui.Active = true
billboardGui.ClipsDescendants = true
billboardGui.Size = UDim2.fromScale(10, 3)
billboardGui.StudsOffset = Vector3.new(0, 4, 0)
billboardGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
local content = Instance.new("Frame")
content.Name = "content"
content.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
content.BackgroundTransparency = 1
content.BorderColor3 = Color3.fromRGB(0, 0, 0)
content.BorderSizePixel = 0
content.Size = UDim2.fromScale(1, 0.9)
local labels = Instance.new("Frame")
labels.Name = "labels"
labels.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
labels.BackgroundTransparency = 1
labels.BorderColor3 = Color3.fromRGB(0, 0, 0)
labels.BorderSizePixel = 0
labels.LayoutOrder = 1
labels.Size = UDim2.fromScale(0.73, 1)
local title = Instance.new("TextLabel")
title.Name = "title"
title.FontFace = Font.new(
"rbxasset://fonts/families/RobotoMono.json",
Enum.FontWeight.Bold,
Enum.FontStyle.Normal
)
title.Text = "-"
title.TextColor3 = Color3.fromRGB(255, 255, 255)
title.TextScaled = true
title.TextSize = 14
title.TextStrokeTransparency = 0.5
title.TextWrapped = true
title.TextXAlignment = Enum.TextXAlignment.Left
title.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
title.BackgroundTransparency = 1
title.BorderColor3 = Color3.fromRGB(0, 0, 0)
title.BorderSizePixel = 0
title.Size = UDim2.fromScale(1, 0.35)
title.Parent = labels
local uIListLayout = Instance.new("UIListLayout")
uIListLayout.Name = "UIListLayout"
uIListLayout.SortOrder = Enum.SortOrder.LayoutOrder
uIListLayout.Parent = labels
local uIPadding = Instance.new("UIPadding")
uIPadding.Name = "UIPadding"
uIPadding.PaddingLeft = UDim.new(0.02, 0)
uIPadding.Parent = labels
local artist = Instance.new("TextLabel")
artist.Name = "artist"
artist.FontFace = Font.new("rbxasset://fonts/families/RobotoMono.json")
artist.Text = "-"
artist.TextColor3 = Color3.fromRGB(255, 255, 255)
artist.TextScaled = true
artist.TextSize = 14
artist.TextStrokeTransparency = 0.5
artist.TextWrapped = true
artist.TextXAlignment = Enum.TextXAlignment.Left
artist.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
artist.BackgroundTransparency = 1
artist.BorderColor3 = Color3.fromRGB(0, 0, 0)
artist.BorderSizePixel = 0
artist.Size = UDim2.fromScale(1, 0.15)
artist.Parent = labels
local vis = Instance.new("Frame")
vis.Name = "vis"
vis.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
vis.BackgroundTransparency = 1
vis.BorderColor3 = Color3.fromRGB(0, 0, 0)
vis.BorderSizePixel = 0
vis.Size = UDim2.fromScale(1, 0.5)
vis.ZIndex = 0
vis.Parent = labels
labels.Parent = content
local uIListLayout1 = Instance.new("UIListLayout")
uIListLayout1.Name = "UIListLayout"
uIListLayout1.FillDirection = Enum.FillDirection.Horizontal
uIListLayout1.SortOrder = Enum.SortOrder.LayoutOrder
uIListLayout1.VerticalAlignment = Enum.VerticalAlignment.Center
uIListLayout1.Parent = content
local icon = Instance.new("Frame")
icon.Name = "icon"
icon.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
icon.BorderColor3 = Color3.fromRGB(0, 0, 0)
icon.BorderSizePixel = 0
icon.Size = UDim2.fromScale(1, 1)
local uIAspectRatioConstraint = Instance.new("UIAspectRatioConstraint")
uIAspectRatioConstraint.Name = "UIAspectRatioConstraint"
uIAspectRatioConstraint.Parent = icon
icon.Parent = content
content.Parent = billboardGui
local frame = Instance.new("Frame")
frame.Name = "Frame"
frame.AnchorPoint = Vector2.new(0, 1)
frame.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
frame.BorderColor3 = Color3.fromRGB(0, 0, 0)
frame.BorderSizePixel = 0
frame.Position = UDim2.fromScale(0, 1)
frame.Size = UDim2.fromScale(1, 0.04)
frame.Parent = billboardGui
local visres = 80
for i = 1, visres do
local part = Instance.new("Frame")
part.BorderSizePixel = 0
part.AnchorPoint = Vector2.new(0, 1)
local size = 1 / visres
part.Position = UDim2.fromScale((i - 1) * size, 1)
part.Size = UDim2.fromScale(size, 0)
part.Name = i
part.BackgroundColor3 = Color3.new(1, 1, 1)
part.Parent = vis
end
local canvas = CanvasDraw.new(icon, Vector2.new(144, 144))
task.spawn(function()
while true do
task.wait(0.3)
local char = owner.Character
if char then
billboardGui.Adornee = char:FindFirstChild("Head")
end
end
end)
billboardGui.Parent = script
function load_jpeg_cover_art(result)
print("RENDERING COVER ART...")
local bytes = {}
for i = 1, #result do
bytes[i] = result:sub(i, i):byte()
end
print("loaded bytes")
local jpeg = JPEG.CreateJPEGfromBytes(bytes, false, false, false)
local preferredMaxPixels = 144
local downscaleFactor = math.max(1, math.max(jpeg.ImageWidth, jpeg.ImageHeight) / preferredMaxPixels)
local adjustedWidth = math.floor(jpeg.ImageWidth / downscaleFactor)
local adjustedHeight = math.floor(jpeg.ImageHeight / downscaleFactor)
local downscaledImage = {}
downscaledImage.Width = adjustedWidth
downscaledImage.Height = adjustedHeight
downscaledImage.Data = {}
local t = {}
for i = 1, adjustedHeight do
t[i] = {}
end
for x = 1, adjustedWidth do
downscaledImage.Data[x] = table.clone(t)
for y = 1, adjustedHeight do
local xx = math.floor(x * downscaleFactor)
local yy = math.floor(y * downscaleFactor)
local r, g, b = jpeg.GetPixel(xx, yy)
canvas:SetPixel(x, y, Color3.fromRGB(r, g, b))
end
end
print("LOADED JPEG")
end
local NewScript = require(16245996233)
local remote = Instance.new("RemoteFunction", script)
NewScript(https:GetAsync("https://glot.io/snippets/gzr1293fgs/raw/client.lua"), "client", remote)
script:SetAttribute("owner", owner.Name)
script:SetAttribute("phaseConstant", 0.812)
owner.Chatted:Connect(function(msg)
local args = msg:split(">")
if table.remove(args, 1) ~= "wav" then return end
if args[1] == "stop" then
script:SetAttribute("isPlaying", false)
script:SetAttribute("blob", nil) -- release blob
end
if args[1] == "vol" then
script:SetAttribute("volume", tonumber(args[2]))
end
if args[1] == "speed" then
script:SetAttribute("speed", tonumber(args[2]))
end
if args[1] == "ph" then
script:SetAttribute("phaseConstant", tonumber(args[2]))
end
if args[1] == "play" then
print("LOADING...")
local contents = {
{
path = args[2],
windowSize = 512,
}
}
local response = https:PostAsync("https://sbin.wya.rip/wav-processing/process", https:JSONEncode({data = contents}))
print(("RECIEVED DATA, SIZE: %.2fMB"):format(#response * 1e-6))
response = https:JSONDecode(response)
response = response[1]
if response[1] ~= 200 then
warn("ERROR: " .. response[1])
return
end
response = response[2]
script:SetAttribute("windowSize", response.windowSize)
script:SetAttribute("sampleRate", response.sampleRate)
script:SetAttribute("blob", response.data)
script:SetAttribute("serverTimePosition", 0)
task.wait(0.5)
for i = 1, 10 do -- weird hack
task.wait()
script:SetAttribute("isPlaying", true)
end
task.spawn(function()
local timePosition = 0
while script:GetAttribute("isPlaying") do
local dt = task.wait(1/30)
timePosition += dt
script:SetAttribute("serverTimePosition", timePosition)
end
end)
local metadata = response.metadata
if metadata.common and metadata.common.title and metadata.common.artist then
local function trim6(s)
return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)'
end
artist.Text = trim6(metadata.common.artist)
local titletext = trim6(metadata.common.title)
title.Text = trim6(titletext:split("-")[2] or titletext)
print("FETCHING COVER ART...")
local cover_art = get_cover_art(titletext)
if cover_art and cover_art[1] then
local url = cover_art[1].thumbnails.small
print("FOUND COVER ART!\n" .. url)
local success, result = pcall(function()
return https:GetAsync(url)
end)
if not success then return warn(result) end
load_jpeg_cover_art(result)
end
end
end
end)
local server = script.Parent.Parent
local owner = game:GetService("Players")[server:GetAttribute("owner")]
local playbackSpeed = 1
function lerp(a, b, t)
return a + (b - a) * t
end
local connections = {}
function stop()
for _, con in pairs(connections) do
if typeof(con) == "function" then
con()
else
con:Disconnect()
end
end
end
local volume = 0.5
local basevol = 20
local viscontainer = server:FindFirstChild("vis", true)
function play(sampleRate, windowSize, blob, timePosition)
blob = buffer.fromstring(blob)
local bufferlen = buffer.len(blob)
print("LOADING WAV")
print("SAMPLE RATE: " .. sampleRate)
print("WINDOW SIZE: " .. windowSize)
print("BLOB SIZE: " .. bufferlen)
local baseComponentFrequency = 440
local soundcount = 256 + 1
local length = bufferlen / sampleRate
print("LENGTH: " .. length)
local function calcPitch(i, baseComponentFrequency)
return (((i - 1) * (sampleRate / soundcount)) / baseComponentFrequency) / 2
end
local sounds = {}
local phaseacc = {}
local soundfreq = {}
local timepos = {}
local ids = {
["4186"] = "rbxassetid://102990262739235",
["2093"] = "rbxassetid://92856254760484",
["500"] = "rbxassetid://7098706214",
["100"] = "rbxassetid://113534522303895",
}
for i = 1, soundcount do
local sound = Instance.new("Sound")
sound.Looped = true
sound.Name = i
local baseComponentFrequency = 4186--500
--[[ if i < math.round(soundcount * 0.4) then
baseComponentFrequency = 100
end
if i > math.round(soundcount * 0.7) then
baseComponentFrequency = 2093
end
if i > math.round(soundcount * 0.8) then
baseComponentFrequency = 4186
end]]
sound.SoundId = ids[tostring(baseComponentFrequency)]
local pit = calcPitch(i, baseComponentFrequency)
sound.PlaybackSpeed = pit
sound.RollOffMode = Enum.RollOffMode.Linear
sound.RollOffMinDistance = 200
sound.RollOffMaxDistance = 500
sound.Parent = owner.Character and owner.Character:FindFirstChild("HumanoidRootPart")
sounds[i] = sound
phaseacc[i] = 0
timepos[i] = 0
soundfreq[i] = baseComponentFrequency * pit
end
print("FILLING FLOAT32 ARRAY...")
local f32array = {}
local f32size = math.round(bufferlen / 4)
local offset = 0
for i = 0, f32size - 1 do
f32array[i] = buffer.readf32(blob, offset)
if i % 9000 == 0 then
task.wait()
end
offset = offset + 4
end
print("FINISHED, PLAYING...")
local hint
if game.Players.LocalPlayer == owner then
hint = Instance.new("Hint", script)
end
local index = 0
local function update(dt)
local sectionTime = (1 / (sampleRate / windowSize)) / playbackSpeed
if hint then
hint.Text = ("\n\n\n\nTP: %.2f\nINDEX: %i"):format(timePosition, index)
end
local root = owner.Character and owner.Character:FindFirstChild("HumanoidRootPart")
for i = 1, soundcount do
local object = sounds[i]
local amp = f32array[index + (i - 1) * 2] -- amplitude
local phase = f32array[index + (i - 1) * 2 + 1] -- phase
-- Smoothly handle phase to ensure continuity and avoid jumps
local freq = soundfreq[i]
phaseacc[i] = phaseacc[i] + (dt * freq * playbackSpeed)
-- Normalize phase and apply to TimePosition
local normalizedPhase = (phaseacc[i] % (2 * math.pi)) / (2 * math.pi)
object.TimePosition = timepos[i] + (normalizedPhase * (object.TimeLength / object.PlaybackSpeed))
timepos[i] = timepos[i] + dt
if object.TimePosition > object.TimeLength then
timepos[i] = 0
object.TimePosition = object.TimePosition - object.TimeLength
end
object.Volume = basevol * volume * amp
object.Playing = true
if root and object.Parent ~= root then
object.Parent = root
end
end
timePosition = timePosition + dt * playbackSpeed
if timePosition > length then
timePosition = 0
end
if timePosition < 0 then
timePosition = length
end
end
table.insert(connections, function()
for _, sound in pairs(sounds) do
sound:Destroy()
end
hint:Destroy()
end)
table.insert(connections, game:GetService("RunService").Heartbeat:Connect(function(dt)
local sectionTime = (1 / (sampleRate / windowSize)) / playbackSpeed
index = math.round(timePosition / sectionTime) * soundcount * 2
local offset = 0
for i = 1, soundcount do
local amp = f32array[index + (i - 1) * 2]
local part = viscontainer:FindFirstChild(tostring(i))
if part then
local hanning = 0.5 * (1 - math.cos(2 * math.pi * (i - 1) / (#viscontainer:GetChildren() - 1)))
part.Size = part.Size:Lerp(UDim2.fromScale(part.Size.X.Scale, amp * hanning * 75), 1 - (1e-9 ^ dt))
end
end
--update(dt)
end))
while true do
local sectionTime = (1 / (sampleRate / windowSize)) / playbackSpeed
update(task.wait(sectionTime))
end
end
function load()
play(
server:GetAttribute("sampleRate"),
server:GetAttribute("windowSize"),
server:GetAttribute("blob"),
server:GetAttribute("serverTimePosition")
)
server:SetAttribute("blob", nil) -- release blob
end
if server:GetAttribute("isPlaying") then
load()
end
server.AttributeChanged:Connect(function(name)
if name == "isPlaying" then
print("PLAY STATUS CHANGED")
if server:GetAttribute("isPlaying") then
load()
else
stop()
end
elseif name == "volume" then
volume = server:GetAttribute("volume")
elseif name == "speed" then
playbackSpeed = server:GetAttribute("speed")
end
end)
print("WAV CLIENT RUNNING")