re
Paste
Login
JavaScript needs to be enabled for the correct display of the page.
local gp3 = (function() local gp3 = {} local dfpwmSecond = 6000 local pcmSecond = dfpwmSecond * 8 local padChar = "\0" local pcmFormat = string.rep("b", pcmSecond) local packedPcmFormat = "c48000" local firstFormat = "> c48000 c4" local secondFormat = "> s2 H H B s1" local checksumFormat = "> I4" local firstFormatSize = string.packsize(firstFormat) local POLY = 0xEDB88320 local crc32_table = {} for i = 0, 255 do local crc = i for _ = 1, 8 do if bit32.band(crc, 1) ~= 0 then crc = bit32.bnot(bit32.rshift(crc, 1), POLY) else crc = bit32.rshift(crc, 1) end end crc32_table[i] = bit32.band(crc, 0xFFFFFFFF) end local function crc32(data) local sbyte = string.byte local band, xor, rshift, bnot = bit32.band, bit32.bxor, bit32.rshift, bit32.bnot local crc = 0xFFFFFFFF for i = 1, #data do local byte = sbyte(data, i) local idx = band(xor(crc, byte), 0xFF) crc = xor(rshift(crc, 8), crc32_table[idx]) end return bnot(crc) % 0x100000000 end local function unpackPcm(pcm) if #pcm < pcmSecond then local pad = pcmSecond - #pcm pcm = pcm .. string.rep(padChar, pad) end return { string.unpack(pcmFormat, pcm) } end local function splitLayout(str) local layout = {} for ch in str:gmatch("[^|]+") do table.insert(layout, ch) end return layout end function gp3.decode(packet) local output = { channels = {}, layout = {} } if #packet < firstFormatSize then local track = packet:sub(1, pcmSecond) return nil, unpackPcm(track) end local track, checksum, pos = string.unpack(firstFormat, packet) local calcChecksum = crc32(track) local firstPcm = unpackPcm(track) if calcChecksum ~= string.unpack(checksumFormat, checksum) then return nil, firstPcm end local details, total, current, extraChannels, layout, pos = string.unpack(secondFormat, packet:sub(pos)) output.details = details output.totalSeconds = total output.currentSeconds = current output.channelCount = extraChannels + 1 output.layout = splitLayout(layout) table.insert(output.channels, firstPcm) local pos, track = pos, nil for i = 1, extraChannels do track, pos = string.unpack(packedPcmFormat, packet, pos) table.insert(output.channels, unpackPcm(track)) end return output end return gp3 end)() local args = {...} local radio = peripheral.find("radio_tower") local frequency = tonumber(args[1]) or 5555 radio.setFrequency(frequency) local pcmSecond = 48000 local formats = {} formats.pcm = string.rep("b", pcmSecond) formats.track = "c" .. pcmSecond -- 1 second of PCM -- big endian, track, crc32, track details, total seconds, current seconds (from 0), extra channels, channels layout formats.packet = "> " .. formats.track .. " c4 s2 H H B s1" local speaker = peripheral.find("speaker") speaker.stop() local buffer = {} local tryPlay = true local function decode(packet) local ok, track, details = pcall(function() local track, checksum, details, total, current, extraChannels, layout, pos = string.unpack(formats.packet, packet) local buffer = { string.unpack(formats.pcm, track) } return buffer, details end) if not ok then return nil, track end return track, details end local function submitNext() local chunk = table.remove(buffer, 1) if chunk then speaker.playAudio(chunk) tryPlay = false end if not chunk then tryPlay = true end end local function queue(chunk) table.insert(buffer, chunk) print(os.clock(), "Buffer Size:", #buffer) if tryPlay then print("Buffering...") if #buffer > 2 then submitNext() end end end parallel.waitForAny(function() while true do local _, _, data = os.pullEvent("radio_message") local track, fallback = gp3.decode(data) --local buffer, details = decode(data) if track then queue(track.channels[1]) print(track.details) else printError("Could not decode. fallback") queue(fallback) end end end, function() while true do os.pullEvent("speaker_audio_empty") submitNext() end end)
Syntax
Auto Detect
Apache Access Log
Apache config
Arduino
ARM Assembly
AsciiDoc
AutoHotkey
Bash
BASIC
Brainfuck
C
Clojure
CMake
CoffeeScript
C++
C#
CSS
D
Dart
Delphi
Diff
Django
DNS Zone
Dockerfile
Batch file (DOS)
dsconfig
Dust
Erlang
Excel formulae
Fortran
F#
G-code (ISO 6983)
GLSL
GML
Go
Gradle
Groovy
Handlebars
Haskell
Haxe
HTML
HTMLbars
HTTP
INI
Java
Javascript
JSON
Julia
Kotlin
Lasso
LaTeX
Leaf
Less
Lisp
Lua
Makefile
Markdown
Mathematica
Matlab
MoonScript
Nginx config
Objective-C
OpenSCAD
Perl
PostgreSQL
php
PHP template
Plain text
PowerShell
.properties
Python
Q
QML
R
Ruby
Rust
Scala
Scheme
SCSS
Shell Session
SQL
Swift
TypeScript
Visual Basic .NET
VBScript
VBScript in HTML
VHDL
Vim Script
Intel x86 Assembly
XML
YAML
Exposure
Public
Unlisted
Folder
No folder
Create Paste
Create as guest