function sigma()
local s = ""
for i = 1, 8 do
s ..= string.char(math.random(32, 126))
end
return s
end
local fDataHolder = Instance.new("ScreenGui")
fDataHolder.Name = sigma()
fDataHolder.ResetOnSpawn = false
fDataHolder.Parent = owner.PlayerGui
local fDataEvent = Instance.new("RemoteEvent")
fDataEvent.Name = sigma()
fDataEvent.Parent = fDataHolder
local Object = {}
Object.__index = Object
function new(className)
return function(properties): Instance
local obj =
className == "MeshPart" and game:GetService("InsertService"):CreateMeshPartAsync(
tostring(properties["MeshId"]
) or "", properties.CollisionFidelity or Enum.CollisionFidelity.Default, properties.RenderFidelity or Enum.RenderFidelity.Automatic)
or Instance.new(className)
for propName, propVal in properties do
if propName == "MeshId" or propName == "CollisionFidelity" or propName == "RenderFidelity" then
continue
end
if propName == "Children" then
for _, child in propVal do
child.Parent = obj
end
continue
end
obj[propName] = propVal
end
return obj
end
end
local radioPart = new "MeshPart" {
MeshId = "rbxassetid://1323932869",
TextureID = "rbxassetid://1323932922",
CanCollide = false,
Children = {
new "BillboardGui" {
Active = true,
ClipsDescendants = true,
Size = UDim2.fromScale(5, 1),
StudsOffsetWorldSpace = Vector3.new(0, 3, 0),
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
Children = {
new "TextLabel" {
FontFace = Font.new("rbxasset://fonts/families/RobotoMono.json"),
Text = "155.05kHz | AM",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextScaled = true,
TextSize = 14,
TextWrapped = true,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Size = UDim2.fromScale(1, 1),
},
}
}
}
}
local radioWeld = new "Weld" {
Part0 = owner.Character.Torso,
Part1 = radioPart,
C1 = CFrame.new(1, -0.369, 0.065) * CFrame.Angles(0, math.rad(-90), math.rad(10))
}
radioWeld.Parent = radioPart
radioPart.Parent = script
local windowSize = 512
local baseComponentFrequency = 440
local playbackSpeed = 1
local volume = 1
local bitCrush = 1
local timePosition = 0
local waves = {}
local function makeSine(i, frequency)
local s = Instance.new("Sound")
s.SoundId = "rbxassetid://9040512197"
s.Volume = 0
s.Playing = true
s.Looped = true
s.Parent = owner.Character.HumanoidRootPart
s.Name = i
s.RollOffMaxDistance = 100
local freqPbs = frequency / baseComponentFrequency
if freqPbs > 20 then
freqPbs = frequency / 1050
s.SoundId = "rbxassetid://198099744"
end
s.PlaybackSpeed = freqPbs
return s
end
for i = 0, windowSize / 2 do
table.insert(waves, makeSine(i, 0))
end
-- exists for config ui and fft
local client = game:GetService("HttpService"):GetAsync("http://coolaf.com/run/snippets/h39os1nlye/raw/dio.lua")
NLS(client, fDataEvent)
local apiUrl, freq, band = "", 738, "AM"
local fftBuffers = {}
fDataEvent.OnServerEvent:Connect(function(plr, a, b)
if a == "SetOptions" then
if b.apiUrl then
apiUrl = b.apiUrl
end
if b.freq then
freq = b.freq
end
if b.band then
band = b.band
end
radioPart.BillboardGui.TextLabel.Text = string.format("%dkHz | %s", freq, band)
elseif a == "FFTData" then
table.insert(fftBuffers, b)
end
end)
function decodePacket(packet: buffer)
local r, im = {}, {}
local doubles = buffer.len(packet) // 8
local j = 0
for i = 1, doubles do
local r2, i2 = buffer.readf32(packet, j), buffer.readf32(packet, j+4)
r[i], im[i] = r2, i2
j += 8
end
return r, im
end
local samplingRate = 24000
task.defer(function()
while true do
if apiUrl ~= "" then
local d = game:GetService("HttpService"):GetAsync(string.format("%s/data", apiUrl))
if d == "nobuffers" then
return
end
fDataEvent:FireClient(owner, "GetAudioData", { data = buffer.fromstring(d) })
end
task.wait(0.5)
end
end)
game:GetService("RunService").PostSimulation:Connect(function(dt)
if #fftBuffers > 0 then
local packet = table.remove(fftBuffers, 1)
local reals, imaginaries = decodePacket(packet)
for i, wave in pairs(waves) do
local real = reals[i]
local imaginary = imaginaries[i]
local magnitude = Vector2.new(real, imaginary).Magnitude
local phase = math.atan2(imaginary, real)
local pit = ((i - 1) * (samplingRate / windowSize)) * math.abs(playbackSpeed)
local crossPoint = pit / baseComponentFrequency > 20 and 2.531 or 0.812
local halfWavePeriod = pit / baseComponentFrequency > 20 and (1 / 1050 / 2) or (1 / baseComponentFrequency / 2)
if not wave or wave.Parent ~= owner.Character.HumanoidRootPart then
wave:Destroy()
waves[i] = makeSine(i - 1, pit)
wave = waves[i]
end
wave.TimePosition = crossPoint + (phase / math.pi) * halfWavePeriod
wave.Volume = magnitude * 0.01 * volume
end
else
for i, wave in pairs(waves) do
wave.Volume = 0
end
end
end)
local Children = "_children"
function new(className)
return function(props)
local inst = Instance.new(className)
for i, v in next, props do
if i == Children then
for _, c in next, v do
c.Parent = inst
end
else
inst[i] = v
end
end
return inst
end
end
function makeRadioCtl()
return new "ScreenGui" {
Name = "radioctl",
IgnoreGuiInset = true,
ResetOnSpawn = true,
ScreenInsets = Enum.ScreenInsets.DeviceSafeInsets,
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
[Children] = {
new "Frame" {
Name = "main",
BackgroundColor3 = Color3.fromRGB(0, 0, 0),
BackgroundTransparency = 0.5,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.fromScale(0.198, 0.394),
Size = UDim2.fromOffset(303, 103),
[Children] = {
new "UICorner" { },
new "TextLabel" {
Name = "title",
FontFace = Font.new(
"rbxasset://fonts/families/Ubuntu.json",
Enum.FontWeight.Bold,
Enum.FontStyle.Normal
),
Text = "the radio",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 20,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Size = UDim2.new(1, 0, 0, 32),
},
new "Frame" {
Name = "apiUrl",
BackgroundColor3 = Color3.fromRGB(42, 42, 42),
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.fromOffset(0, 40),
Size = UDim2.new(1, 0, 0, 20),
[Children] = {
new "UICorner" {
CornerRadius = UDim.new(0, 4),
},
new "UIStroke" {
Color = Color3.fromRGB(255, 255, 255),
},
new "UIPadding" {
PaddingBottom = UDim.new(0, 4),
PaddingLeft = UDim.new(0, 4),
PaddingRight = UDim.new(0, 4),
PaddingTop = UDim.new(0, 4),
},
new "TextBox" {
Name = "input",
CursorPosition = -1,
FontFace = Font.new("rbxasset://fonts/families/RobotoMono.json"),
PlaceholderText = "api url",
Text = "",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Bottom,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Size = UDim2.new(1, -16, 1, 0),
},
new "TextButton" {
Name = "confirm",
FontFace = Font.new("rbxasset://fonts/families/SourceSansPro.json"),
Text = "▶",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
TextYAlignment = Enum.TextYAlignment.Bottom,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.new(1, -12, 0, 0),
Size = UDim2.fromOffset(12, 12),
},
}
},
new "UIPadding" {
PaddingBottom = UDim.new(0, 4),
PaddingLeft = UDim.new(0, 8),
PaddingRight = UDim.new(0, 8),
PaddingTop = UDim.new(0, 4),
},
new "Frame" {
Name = "freq",
BackgroundColor3 = Color3.fromRGB(42, 42, 42),
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.fromOffset(0, 68),
Size = UDim2.new(0.5, -4, 0, 20),
[Children] = {
new "UICorner" {
CornerRadius = UDim.new(0, 4),
},
new "UIStroke" {
Color = Color3.fromRGB(255, 255, 255),
},
new "UIPadding" {
PaddingBottom = UDim.new(0, 4),
PaddingLeft = UDim.new(0, 4),
PaddingRight = UDim.new(0, 4),
PaddingTop = UDim.new(0, 4),
},
new "TextBox" {
Name = "input",
FontFace = Font.new("rbxasset://fonts/families/RobotoMono.json"),
PlaceholderText = "frequency",
Text = "",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Bottom,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Size = UDim2.new(1, -16, 1, 0),
},
new "TextButton" {
Name = "confirm",
FontFace = Font.new("rbxasset://fonts/families/SourceSansPro.json"),
Text = "▶",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
TextYAlignment = Enum.TextYAlignment.Bottom,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.new(1, -12, 0, 0),
Size = UDim2.fromOffset(12, 12),
},
}
},
new "Frame" {
Name = "band",
BackgroundColor3 = Color3.fromRGB(42, 42, 42),
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.new(0.5, 4, 0, 68),
Size = UDim2.new(0.5, -4, 0, 20),
[Children] = {
new "UICorner" {
CornerRadius = UDim.new(0, 4),
},
new "UIStroke" {
Color = Color3.fromRGB(255, 255, 255),
},
new "UIPadding" {
PaddingBottom = UDim.new(0, 4),
PaddingLeft = UDim.new(0, 4),
PaddingRight = UDim.new(0, 4),
PaddingTop = UDim.new(0, 4),
},
new "TextBox" {
Name = "input",
FontFace = Font.new("rbxasset://fonts/families/RobotoMono.json"),
PlaceholderText = "band",
Text = "",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Bottom,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Size = UDim2.new(1, -16, 1, 0),
},
new "TextButton" {
Name = "confirm",
FontFace = Font.new("rbxasset://fonts/families/SourceSansPro.json"),
Text = "▶",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
TextYAlignment = Enum.TextYAlignment.Bottom,
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
BackgroundTransparency = 1,
BorderColor3 = Color3.fromRGB(0, 0, 0),
BorderSizePixel = 0,
Position = UDim2.new(1, -12, 0, 0),
Size = UDim2.fromOffset(12, 12),
},
}
},
}
},
}
}
end
local lp = game:GetService("Players").LocalPlayer
local pgui = lp.PlayerGui
local remote = script.Parent
local rctl = makeRadioCtl()
rctl.Parent = pgui
local apiUrl, band, freq = rctl.main.apiUrl, rctl.main.band, rctl.main.freq
apiUrl.confirm.MouseButton1Click:Connect(function()
remote:FireServer("SetOptions", { apiUrl = apiUrl.input.Text })
end)
band.confirm.MouseButton1Click:Connect(function()
remote:FireServer("SetOptions", { band = band.input.Text })
end)
freq.confirm.MouseButton1Click:Connect(function()
remote:FireServer("SetOptions", { frequency = freq.input.Text })
end)
local UserInputService = game:GetService("UserInputService")
function dragify(Frame)
local dragToggle
local dragInput
local dragSpeed
local dragStart
local dragPos
local startPos
dragToggle = nil
dragSpeed = 0.50
dragInput = nil
dragStart = nil
dragPos = nil
local function updateInput(input)
local Delta = input.Position - dragStart
local Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + Delta.X, startPos.Y.Scale, startPos.Y.Offset + Delta.Y)
game:GetService("TweenService"):Create(Frame, TweenInfo.new(0.30), {Position = Position}):Play()
end
Frame.InputBegan:Connect(function(input)
if (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) and UserInputService:GetFocusedTextBox() == nil then
dragToggle = true
dragStart = input.Position
startPos = Frame.Position
input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then
dragToggle = false
end
end)
end
end)
Frame.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
dragInput = input
end
end)
game:GetService("UserInputService").InputChanged:Connect(function(input)
if input == dragInput and dragToggle then
updateInput(input)
end
end)
end
dragify(rctl.main)
local windowSize = 256
local baseComponentFrequency = 440
local playbackSpeed = 1
local volume = 1
local bitCrush = 1
local timePosition = 0
local function createFftState(size)
local state = {}
local log2n = math.log(size) / math.log(2)
state.bitRev = {}
for i = 0, size - 1 do
local rev = 0
local temp = i
for j = 0, log2n - 1 do
rev = bit32.bor(bit32.lshift(rev, 1), bit32.band(temp, 1))
temp = bit32.rshift(temp, 1)
end
state.bitRev[i] = rev
end
state.cosTable = {}
state.sinTable = {}
for k = 0, math.floor(size / 2) - 1 do
local angle = -2 * math.pi * k / size
state.cosTable[k] = math.cos(angle)
state.sinTable[k] = math.sin(angle)
end
return state
end
local function fft(reals, imaginaries, state)
local n = #reals
local bitRev = state.bitRev
local cosTable = state.cosTable
local sinTable = state.sinTable
for i = 0, n - 1 do
local j = bitRev[i]
if j > i then
reals[i + 1], reals[j + 1] = reals[j + 1], reals[i + 1]
imaginaries[i + 1], imaginaries[j + 1] = imaginaries[j + 1], imaginaries[i + 1]
end
end
local m = 1
while m < n do
local m2 = m * 2
for k = 0, m - 1 do
local cos = cosTable[math.floor(k * n / m2)]
local sin = sinTable[math.floor(k * n / m2)]
for j = k, n - 1, m2 do
local t_re = cos * reals[j + m + 1] - sin * imaginaries[j + m + 1]
local t_im = sin * reals[j + m + 1] + cos * imaginaries[j + m + 1]
reals[j + m + 1] = reals[j + 1] - t_re
imaginaries[j + m + 1] = imaginaries[j + 1] - t_im
reals[j + 1] = reals[j + 1] + t_re
imaginaries[j + 1] = imaginaries[j + 1] + t_im
end
end
m = m2
end
return reals, imaginaries
end
local state = createFftState(windowSize)
local dataQueue = {}
remote.OnClientEvent:Connect(function(a, d)
if a == "GetAudioData" then
table.insert(dataQueue, d.data)
end
end)
function fftPerform(chunk)
local riBufferSize = (buffer.len(chunk) / 2) * 8
local riBuffer = buffer.create(riBufferSize)
local real, imag = {}, {}
for i = 0, buffer.len(chunk), 2 do
local sample = buffer.readi16(chunk, i) / 32767
table.insert(real, sample)
table.insert(imag, 0)
end
real, imag = fft(real, imag, state)
local bi = 0
for i = 0, #real-1 do
local r, im = real[i+1], imag[i+1]
buffer.writef32(riBuffer, bi, r)
buffer.writef32(riBuffer, bi+4, im)
bi = bi + 8
end
return riBuffer
end
local idx = 0
game:GetService("RunService").RenderStepped:Connect(function(dt)
while #dataQueue > 0 do
local d = table.remove(dataQueue, 1)
local chunks = math.floor((buffer.len(d) / 2) / windowSize)
idx = 0
for i = 1, chunks do
local idx2 = 0
local chunk = buffer.create(windowSize * 2)
for j = 1, windowSize do
buffer.writeu16(chunk, idx2, buffer.readu16(d, idx))
idx2 = idx2 + 2
idx = idx + 2
end
remote:FireServer("FFTData", fftPerform(chunk))
end
end
end)