ascii player

Run Settings
LanguageLua
Language Version
Run Command
--// zomg rares --// wav player by alaska and dark local args = {...} local videos = { NotAdvert = { fps = 15; videoSettings = { CanvasSize = Vector2.new(90,50); TextSize = 2; }; Audio = "https://cdn.glitch.global/65fb8114-6418-4a81-8479-5ab02dae65fb/not_advert.wav?v=1737416825383"; Data = "https://raw.githubusercontent.com/typicaalusername/ascii_player/refs/heads/main/not_Advert.lua"; }; jack = { fps = 25; videoSettings = { CanvasSize = Vector2.new(300, 150); TextSize = 2; }; Data = "https://raw.githubusercontent.com/typicaalusername/ascii_player/refs/heads/main/jack"; Audio = "https://cdn.glitch.global/65fb8114-6418-4a81-8479-5ab02dae65fb/jackass.wav?v=1737420184031"; }; y2k = { fps = 7.5; videoSettings = { CanvasSize = Vector2.new(178, 100); TextSize = 2; }; Data = "https://raw.githubusercontent.com/typicaalusername/ascii_player/refs/heads/main/y2k"; Audio = "https://cdn.glitch.global/65fb8114-6418-4a81-8479-5ab02dae65fb/y2k.wav?v=1737427446015"; }; } local video = videos[args[1] or "y2k"] local vidsettings = video.videoSettings local multiplysize = 1 local part = nil; local label = nil local backlabel = nil do local Part = Instance.new("Part") Part.CFrame = (game:GetService("RunService"):IsStudio() and CFrame.new(15,15,5) or owner.Character.HumanoidRootPart.CFrame * CFrame.new(0,5+(.5*multiplysize),-5) * CFrame.Angles(0,math.rad(180),0)) Part.BottomSurface = Enum.SurfaceType.Smooth Part.Transparency = 0.8 Part.TopSurface = Enum.SurfaceType.Smooth Part.Color = Color3.fromRGB(159, 161, 172) Part.Material = Enum.Material.Glass Part.Size = Vector3.new(11.800000190734863, 6.849999904632568, 0.10000000149011612)*multiplysize Part.Anchored = true local SurfaceGui = Instance.new("SurfaceGui") SurfaceGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling SurfaceGui.ClipsDescendants = true SurfaceGui.MaxDistance = 1000 SurfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.FixedSize SurfaceGui.CanvasSize = vidsettings.CanvasSize --SurfaceGui.PixelsPerStud = 8/multiplysize SurfaceGui.Brightness = 5 SurfaceGui.Parent = Part local Frame = Instance.new("Frame") Frame.Size = UDim2.new(1, 0, 1, 0) Frame.BorderColor3 = Color3.fromRGB(0, 0, 0) Frame.BorderSizePixel = 0 Frame.BackgroundColor3 = Color3.fromRGB(0, 0, 0) Frame.Parent = SurfaceGui local TextLabel = Instance.new("TextLabel") TextLabel.Size = UDim2.new(1, 0, 1, 0) TextLabel.BorderColor3 = Color3.fromRGB(0, 0, 0) TextLabel.BackgroundTransparency = 1 TextLabel.BorderSizePixel = 0 TextLabel.TextStrokeTransparency = 0 TextLabel.TextStrokeColor3 = Color3.fromRGB(115, 115, 115) TextLabel.BackgroundColor3 = Color3.fromRGB(255, 255, 255) TextLabel.FontSize = Enum.FontSize.Size14 TextLabel.TextSize = vidsettings.TextSize TextLabel.TextColor3 = Color3.fromRGB(255, 255, 255) TextLabel.Text = " " TextLabel.TextWrapped = true TextLabel.Font = Enum.Font.Code TextLabel.Parent = Frame local back = Instance.new("SurfaceGui") back.Name = "back" back.ZIndexBehavior = Enum.ZIndexBehavior.Sibling back.Face = Enum.NormalId.Back back.ClipsDescendants = true back.MaxDistance = 1000 back.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud back.Parent = Part local TextLabel1 = Instance.new("TextLabel") TextLabel1.Size = UDim2.new(1, 0, 1, 0) TextLabel1.BorderColor3 = Color3.fromRGB(0, 0, 0) TextLabel1.BackgroundTransparency = 1 TextLabel1.BorderSizePixel = 0 TextLabel1.BackgroundColor3 = Color3.fromRGB(255, 255, 255) TextLabel1.FontSize = Enum.FontSize.Size14 TextLabel1.TextSize = 14 TextLabel1.TextColor3 = Color3.fromRGB(255, 255, 255) TextLabel1.Text = "oh mah gah" TextLabel1.TextWrapped = true TextLabel1.TextWrap = true TextLabel1.Font = Enum.Font.Code TextLabel1.TextScaled = true TextLabel1.Parent = back backlabel = TextLabel1 Part.Parent = script part = Part label = TextLabel end local framerate = video.fps local asciidata = loadstring(game:GetService("HttpService"):GetAsync(video.Data))() local frames = asciidata local totalframes = #frames local duration = totalframes / framerate local waveparent = part local timePosition = 0 do local runService = game:GetService("RunService") local conn = {} local data local windowSize = 512 local baseComponentFrequency = 440 local playbackSpeed = 1 local volume = 1 local bitCrush = 1 local playing = false local byteOffset = 16 local formatChunkSize, channels, samplingRate, bitsPerSample local header, dataSize, samples, maxValue local byteOffset = 16 local formatChunkSize, channels, samplingRate, bitsPerSample local header, dataSize, samples, maxValue 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 = waveparent 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 local function getString(length, offset, blob) local str = "" for i = 0, length - 1 do str = str..string.char(buffer.readu8(blob, offset + i)) end return str end local function fft(reals, imaginaries) local inLength = #reals for i = 0, inLength - 1 do local h = i local k = inLength local j = 0 while true do k = bit32.rshift(k, 1) if k > 0 then j = bit32.bor(bit32.lshift(j, 1), bit32.band(h, 1)) h = bit32.rshift(h, 1) else break end end if j > i then local temp = reals[j + 1] reals[j + 1] = reals[i + 1] reals[i + 1] = temp local temp = imaginaries[j + 1] imaginaries[j + 1] = imaginaries[i + 1] imaginaries[i + 1] = temp end end local n = 1 while n * 2 <= inLength do local i = 0 while i < inLength do local j = i while j < i + n do local cos = math.cos(math.pi * (j - i) / n) local sin = math.sin(math.pi * (j - i) / n) local tre = reals[j + n + 1] * cos + imaginaries[j + n + 1] * sin local tim = -reals[j + n + 1] * sin + imaginaries[j + n + 1] * cos reals[j + n + 1] = reals[j + 1] - tre imaginaries[j + n + 1] = imaginaries[j + 1] - tim reals[j + 1] = reals[j + 1] + tre imaginaries[j + 1] = imaginaries[j + 1] + tim j = j + 1 end i = i + n * 2 end n = n * 2 end return reals, imaginaries end function link(arg) playing = false timePosition = 0 if data then buffer.fill(data, 0, 0, buffer.len(data)) end data = buffer.fromstring(arg) byteOffset = 16 formatChunkSize = buffer.readu32(data, byteOffset) byteOffset = 22 channels = buffer.readu16(data, byteOffset) byteOffset = 24 samplingRate = buffer.readu32(data, byteOffset) byteOffset = 34 bitsPerSample = buffer.readu16(data, byteOffset) byteOffset = byteOffset + 2 if formatChunkSize == 18 then byteOffset = byteOffset + 2 elseif formatChunkSize == 40 then byteOffset = byteOffset + 24 elseif formatChunkSize ~= 16 then error("Invalid wav file") elseif channels == 2 then error("File must be mono") end header = "" while header ~= "data" do header = getString(4, byteOffset, data) byteOffset = byteOffset + 1 end byteOffset = byteOffset + 3 dataSize = buffer.readu32(data, byteOffset) samples = dataSize / channels / (bitsPerSample / 8) maxValue = 2 ^ bitsPerSample for i, wave in next, waves do i = i - 1 local frequency = i * samplingRate / windowSize * math.abs(playbackSpeed) local freqPbs = frequency / baseComponentFrequency if freqPbs > 20 then freqPbs = frequency / 1050 wave.SoundId = "rbxassetid://198099744" else wave.SoundId = "rbxassetid://9040512197" end wave.PlaybackSpeed = freqPbs end playing = true end local deltaTime = 0 local previousWaitTime = os.clock() local previousIndex = -1 local reals = {} local imaginaries = {} function play(timepos) if playing then timePosition = (timePosition + deltaTime * playbackSpeed) % (samples / samplingRate) local index = math.floor(timePosition * (samplingRate / windowSize)) * windowSize local previousSample = 0 for i = 1, windowSize do local sample = 0 if bitsPerSample == 8 then sample = buffer.readi8(data, byteOffset + index + (i - 1)) elseif bitsPerSample == 16 then sample = buffer.readi16(data, byteOffset + index * 2 + (i - 1) * 2) elseif bitsPerSample == 32 then sample = buffer.readi32(data, byteOffset + index * 4 + (i - 1) * 4) end if i % (bitCrush or 1) == 0 or i == 1 then reals[i] = sample / maxValue else reals[i] = previousSample end previousSample = reals[i] imaginaries[i] = 0 end reals, imaginaries = fft(reals, imaginaries) 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 ~= waveparent 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 previousIndex = index end deltaTime = os.clock() - previousWaitTime previousWaitTime = os.clock() return timePosition end end link(game:GetService("HttpService"):GetAsync(video.Audio)) function lzw_decompress(compressed_data) local dictionary = {} for i = 0, 255 do dictionary[i] = string.char(i) end local dict_size = 256 local current_code = compressed_data[1] local current_string = dictionary[current_code] local decompressed_data = {current_string} for i = 2, #compressed_data do local code = compressed_data[i] local entry if dictionary[code] then entry = dictionary[code] elseif code == dict_size then entry = current_string .. string.sub(current_string, 1, 1) end table.insert(decompressed_data, entry) dictionary[dict_size] = current_string .. string.sub(entry, 1, 1) dict_size = dict_size + 1 current_string = entry end return table.concat(decompressed_data) end local curframe = 1 local syncing = false local t = os.clock() local more = os.clock() game:GetService("RunService").Heartbeat:Connect(function(dt) local r1 = duration / totalframes local r2 = r1 * curframe backlabel.Text = `server fps: {math.round((1/dt)*100)/100}\nvideo fps: {framerate}\ntimepos desync: {math.round((timePosition - r2)*100)/100}{(syncing and "\nresyncing" or "")}` play() if os.clock()-t >= 1/framerate then t = os.clock() label.Text = lzw_decompress(frames[curframe]) if #frames<curframe+1 then curframe = 1 timePosition = 0 else curframe+=1 end end if os.clock()-more >= 1/144 then more = os.clock() if timePosition - r2 >= .2 then syncing = true timePosition = r2 task.delay(.1,function() syncing = false end) end end end)
Editor Settings
Theme
Key bindings
Full width
Lines