This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 0e770b2b49
commit 94063e4369
7342 changed files with 1718932 additions and 14 deletions

View File

@@ -0,0 +1,436 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- made by Morten and CapsAdmin
pac.webaudio = pac.webaudio or {}
local webaudio = pac.webaudio
webaudio.Browser = webaudio.Browser or {}
webaudio.Browser.States =
{
Uninitialized = 0,
Initializing = 1,
Initialized = 2
}
if webaudio.Browser.Control and
webaudio.Browser.Control:IsValid () then
webaudio.Browser.Control:Remove ()
webaudio.Browser.Control = nil
end
webaudio.Browser.State = webaudio.Browser.States.Uninitialized
webaudio.Browser.Control = nil
webaudio.Browser.JavascriptQueue = {}
webaudio.Browser.Volume = nil
local CONSOLE_MESSAGE_PREFIX = Color(121, 221, 203)
local CONSOLE_MESSAGE_COLOR = Color(200, 200, 200)
function webaudio.Browser.Initialize()
if webaudio.Browser.State ~= webaudio.Browser.States.Uninitialized then return end
webaudio.Browser.State = webaudio.Browser.States.Initializing
if webaudio.Browser.Control then webaudio.Browser.Control:Remove() end
webaudio.Browser.Control = vgui.Create("DHTML")
webaudio.Browser.Control:SetVisible(false)
webaudio.Browser.Control:SetPos(ScrW(), ScrH())
webaudio.Browser.Control:SetSize(1, 1)
local lastMessage = nil
webaudio.Browser.Control.ConsoleMessage = function(self, message)
-- why does awesomium crash in the first place?
if msg == "Uncaught ReferenceError: lua is not defined" then
webaudio.Browser.State = webaudio.Browser.States.Uninitialized
end
if lastMessage ~= message then
lastMessage = message
pac.Message(CONSOLE_MESSAGE_PREFIX, '[OGG] ', CONSOLE_MESSAGE_COLOR, unpack(pac.RepackMessage(message)))
end
end
webaudio.Browser.Control:AddFunction("lua", "print", webaudio.DebugPrint)
webaudio.Browser.Control:AddFunction("lua", "message", function(messageType, ...)
local args = {...}
webaudio.DebugPrint(messageType, ...)
if messageType == "initialized" then
webaudio.Browser.State = webaudio.Browser.States.Initialized
webaudio.SampleRate = args[1]
elseif messageType == "stream" then
local stream = webaudio.Streams.GetStream(tonumber(args[2]) or 0)
if not stream then return end
local messageType = args[1]
stream:HandleBrowserMessage(messageType, unpack(args, 3, table.maxn(args)))
end
end)
--webaudio.Browser.Control:OpenURL("asset://garrysmod/lua/pac3/core/client/libraries/urlogg.lua")
webaudio.Browser.Control:SetHTML(webaudio.Browser.HTML)
end
function webaudio.Browser.IsInitializing()
return webaudio.Browser.State == webaudio.Browser.States.Initializing
end
function webaudio.Browser.IsInitialized()
return webaudio.Browser.State == webaudio.Browser.States.Initialized
end
-- Javascript
function webaudio.Browser.RunJavascript(code)
if IsValid(webaudio.Browser.Control) then webaudio.Browser.Control:QueueJavascript(code) end
end
function webaudio.Browser.QueueJavascript(code)
webaudio.Browser.JavascriptQueue [#webaudio.Browser.JavascriptQueue + 1] = code
end
function webaudio.Browser.Think()
if #webaudio.Browser.JavascriptQueue == 0 then return end
local code = table.concat(webaudio.Browser.JavascriptQueue, "\n")
webaudio.Browser.RunJavascript(code)
webaudio.Browser.JavascriptQueue = {}
end
-- Audio
function webaudio.Browser.SetVolume (volumeFraction)
if webaudio.Browser.Volume == volumeFraction then return end
webaudio.Browser.Volume = volumeFraction
webaudio.Browser.QueueJavascript(string.format("gain.gain.value = %f", volumeFraction))
end
webaudio.Browser.HTML = [==[
<script>
window.onerror = function(description, url, line)
{
lua.print("Unhandled exception at line " + line + ": " + description)
}
function lerp(x0, x1, t)
{
return x0 * (1 - t) + x1 * t;
}
var audio, gain, processor, analyser, streams = [];
function open()
{
if(audio)
{
audio.destination.disconnect();
delete audio;
delete gain;
}
if(typeof AudioContext != "undefined"){
audio = new AudioContext;
processor = audio.createScriptProcessor(4096, 0, 2);
gain = audio.createGain();
}else{
audio = new webkitAudioContext;
processor = audio.createJavaScriptNode(4096, 0, 1);
gain = audio.createGainNode();
}
processor.onaudioprocess = function(event)
{
var outputLeft = event.outputBuffer.getChannelData(0);
var outputRight = event.outputBuffer.getChannelData(1);
for(var i = 0; i < event.outputBuffer.length; ++i)
{
outputLeft [i] = 0;
outputRight[i] = 0;
}
for(var i in streams)
{
var stream = streams[i];
if(!stream.use_echo && (stream.paused || (stream.vol_left < 0.001 && stream.vol_right < 0.001)))
{
continue;
}
var echol;
var echor;
if (stream.use_echo && stream.echo_buffer)
{
echol = stream.echo_buffer.getChannelData(0);
echor = stream.echo_buffer.getChannelData(1);
}
var inputLength = stream.buffer.length;
var inputLeft = stream.buffer.getChannelData(0);
var inputRight = stream.buffer.numberOfChannels == 1 ? inputLeft : stream.buffer.getChannelData(1);
var sml = 0;
var smr = 0;
for(var j = 0; j < event.outputBuffer.length; ++j)
{
if (stream.use_smoothing)
{
stream.speed_smooth = stream.speed_smooth + (stream.speed - stream.speed_smooth) * 0.001;
stream.vol_left_smooth = stream.vol_left_smooth + (stream.vol_left - stream.vol_left_smooth ) * 0.001;
stream.vol_right_smooth = stream.vol_right_smooth + (stream.vol_right - stream.vol_right_smooth) * 0.001;
}
else
{
stream.speed_smooth = stream.speed;
stream.vol_left_smooth = stream.vol_left_smooth;
stream.vol_right_smooth = stream.vol_right_smooth;
}
if (stream.paused || stream.max_loop > 0 && stream.position > inputLength * stream.max_loop)
{
stream.done_playing = true;
if (!stream.paused)
{
lua.message("stream", "stop", stream.id);
stream.paused = true;
}
if (!stream.use_echo)
{
break;
}
}
else
{
stream.done_playing = false;
}
var index = (stream.position >> 0) % inputLength;
var echo_index = (stream.position >> 0) % stream.echo_delay;
var left = 0;
var right = 0;
if (!stream.done_playing)
{
// filters
if (stream.filter_type == 0)
{
// None
left = inputLeft [index] * stream.vol_left_smooth;
right = inputRight[index] * stream.vol_right_smooth;
}
else
{
sml = sml + (inputLeft [index] - sml) * stream.filter_fraction;
smr = smr + (inputRight[index] - smr) * stream.filter_fraction;
if (stream.filter_type == 1)
{
// Low pass
left = sml * stream.vol_left_smooth;
right = smr * stream.vol_right_smooth;
}
else if (stream.filter_type == 2)
{
// High pass
left = (inputLeft [index] - sml) * stream.vol_left_smooth;
right = (inputRight[index] - smr) * stream.vol_right_smooth;
}
}
}
if (stream.use_echo)
{
echol[echo_index] = echol[echo_index] * stream.echo_feedback + left;
echor[echo_index] = echor[echo_index] * stream.echo_feedback + right;
outputLeft [j] += echol[echo_index];
outputRight[j] += echor[echo_index];
}
else
{
outputLeft [j] += left;
outputRight[j] += right;
}
stream.position += stream.speed_smooth;
}
}
};
processor.connect(gain)
gain.connect(audio.destination)
lua.message("initialized", audio.sampleRate)
}
function close()
{
if(audio)
{
audio.destination.disconnect();
delete audio
audio = null
lua.message("uninitialized")
}
}
var buffer_cache = []
function download_buffer(url, callback, skip_cache, id)
{
if (!skip_cache && buffer_cache[url])
{
callback(buffer_cache[url])
return
}
var request = new XMLHttpRequest
request.open("GET", url)
request.responseType = "arraybuffer"
request.send()
request.onload = function()
{
lua.print("decoding " + url + " " + request.response.byteLength + " ...")
audio.decodeAudioData(request.response,
function(buffer)
{
lua.print("decoded " + url + " successfully")
callback(buffer)
buffer_cache[url] = buffer
},
function(err)
{
lua.print("decoding error " + url + " " + err)
lua.message("stream", "call", id, "OnError", "decoding failed", err)
}
)
}
request.onprogress = function(event)
{
lua.print("downloading " + (event.loaded / event.total) * 100)
}
request.onerror = function()
{
lua.print("downloading " + url + " errored")
lua.message("stream", "call", id, "OnError", "download failed")
};
}
function createStream(url, id, skip_cache)
{
lua.print("Loading " + url)
download_buffer(url, function(buffer)
{
var stream = {}
stream.id = id
stream.position = 0
stream.buffer = buffer
stream.url = url
stream.speed = 1 // 1 = normal pitch
stream.max_loop = 1 // -1 = inf
stream.vol_left = 1
stream.vol_right = 1
stream.filter = audio.createBiquadFilter();
stream.paused = true
stream.use_smoothing = true
stream.echo_volume = 0
stream.filter_type = 0
stream.filter_fraction = 1
stream.done_playing = false
stream.use_echo = false
stream.echo_feedback = 0.75
stream.echo_buffer = false
stream.vol_left_smooth = 0
stream.vol_right_smooth = 0
stream.speed_smooth = stream.speed
stream.play = function(stop, position)
{
if(position !== undefined)
{
stream.position = position
}
stream.paused = !stop
};
stream.usefft = function(enable)
{
// later
}
stream.useEcho = function(b) {
stream.use_echo = b
if (b)
{
stream.setEchoDelay(stream.echo_delay)
}
else
{
stream.echo_buffer = undefined
}
}
stream.setEchoDelay = function(x) {
if(stream.use_echo && (!stream.echo_buffer || (x != stream.echo_buffer.length))) {
var size = 1;
while((size <<= 1) < x);
stream.echo_buffer = audio.createBuffer(2, size, audio.sampleRate);
}
stream.echo_delay = x;
}
streams[id] = stream
lua.message("stream", "loaded", id, buffer.length)
}, skip_cache, id)
}
function destroyStream(id)
{
}
open()
</script>
]==]

View File

@@ -0,0 +1,473 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- made by Morten and CapsAdmin
pac.webaudio = pac.webaudio or {}
local webaudio = pac.webaudio
webaudio.Streams = webaudio.Streams or {}
webaudio.FilterType =
{
None = 0,
LowPass = 1,
HighPass = 2,
}
local listenerPosition, listenerAngle, listenerVelocity = Vector(), Angle(), Vector()
local lastListenerPosition, lastListenerPositionTime
pac.AddHook("RenderScene", "webaudio_3d", function(position, angle)
listenerPosition = position
listenerAngle = angle
lastListenerPosition = lastListenerPosition or listenerPosition
lastListenerPositionTime = lastListenerPositionTime or (CurTime() - FrameTime())
listenerVelocity = (listenerPosition - lastListenerPosition) / (CurTime() - lastListenerPositionTime)
lastListenerPosition = listenerPosition
lastListenerPositionTime = CurTime()
end)
webaudio.Streams.STREAM = {}
local STREAM = webaudio.Streams.STREAM
STREAM.__index = STREAM
-- Identity
STREAM.Id = nil
STREAM.Url = "" -- ??
-- State
STREAM.Loaded = false
-- Audio
STREAM.SampleCount = 0
-- Playback
STREAM.Paused = true
STREAM.SamplePosition = 0
STREAM.MaxLoopCount = nil
-- Playback speed
STREAM.PlaybackSpeed = 1
STREAM.AdditivePitchModifier = 0
-- Volume
STREAM.Panning = 0
STREAM.Volume = 1
STREAM.AdditiveVolumeFraction = 0
-- 3d
STREAM.Use3d = nil
STREAM.UseDoppler = true
STREAM.SourceEntity = NULL
STREAM.SourcePosition = nil
STREAM.LastSourcePosition = nil
STREAM.LastSourcePositionTime = nil
STREAM.SourceVelocity = nil
STREAM.SourceRadius = 1000
STREAM.ListenerOutOfRadius = false
local function DECLARE_PROPERTY(propertyName, javascriptSetterCode, defaultValue, filterFunction)
STREAM[propertyName] = defaultValue
STREAM["Set" .. propertyName] = function(self, value)
if filterFunction then
value = filterFunction(value, self)
end
self[propertyName] = value
self:Call(javascriptSetterCode, value)
end
STREAM["Get" .. propertyName] = function(self, ...)
return self[propertyName]
end
end
-- Identity
function STREAM:GetId()
return self.Id
end
function STREAM:SetId(id)
self.Id = id
return self
end
function STREAM:GetUrl()
return self.Url
end
function STREAM:SetUrl(url)
self.Url = url
return self
end
-- State
function STREAM:IsLoaded()
return self.Loaded
end
function STREAM:IsValid()
return true
end
function STREAM:Remove()
self.IsValid = function() return false end
end
-- Browser
function STREAM:Call(fmt, ...)
if not self.Loaded then return end
local code = string.format("try { streams[%d]%s } catch(e) { lua.print(e.toString()) }", self:GetId(), string.format(fmt, ...))
webaudio.Browser.QueueJavascript(code)
end
function STREAM:CallNow(fmt, ...)
if not self.Loaded then return end
local code = string.format("try { streams[%d]%s } catch(e) { lua.print(e.toString()) }", self:GetId(), string.format(fmt, ...))
webaudio.Browser.RunJavascript(code)
end
function STREAM:HandleBrowserMessage(messageType, ...)
if messageType == "call" then
self:HandleCallBrowserMessage(...)
elseif messageType == "fft" then
self:HandleFFTBrowserMessage(...)
elseif messageType == "stop" then
self.Paused = true
elseif messageType == "return" then
self.ReturnedValues = {...}
elseif messageType == "loaded" then
self:HandleLoadedBrowserMessage(...)
elseif t == "position" then
self:HandlePositionBrowserMessage(...)
end
end
-- Playback
function STREAM:GetMaxLoopCount()
return self.MaxLoopCount
end
function STREAM:SetMaxLoopCount(maxLoopCount)
self:Call(".max_loop = %i", maxLoopCount == true and -1 or maxLoopCount == false and 1 or tonumber(maxLoopCount) or 1)
self.MaxLoopCount = maxLoopCount
end
STREAM.SetLooping = STREAM.SetMaxLoopCount
function STREAM:GetSampleCount()
return self.SampleCount
end
function STREAM:Pause()
self.Paused = true
self:CallNow(".play(false)")
end
function STREAM:Resume()
self.Paused = false
self:UpdatePlaybackSpeed()
self:UpdateVolume()
self:CallNow(".play(true)")
end
function STREAM:Start()
self.Paused = false
self:UpdatePlaybackSpeed()
self:UpdateVolume()
self:CallNow(".play(true, 0)")
end
STREAM.Play = STREAM.Start
function STREAM:Stop()
self.Paused = true
self:CallNow(".play(false, 0)")
end
function STREAM:Restart()
self:SetSamplePosition(0)
end
function STREAM:SetPosition(positionFraction)
self:SetSamplePosition((positionFraction % 1) * self:GetSampleCount())
end
DECLARE_PROPERTY("SamplePosition", ".position = %f", 0)
-- Playback speed
function STREAM:GetPlaybackSpeed()
return self.PlaybackSpeed
end
function STREAM:GetAdditivePitchModifier()
return self.AdditivePitchModifier
end
function STREAM:SetPlaybackSpeed(playbackSpeedMultiplier)
if self.PlaybackSpeed == playbackSpeedMultiplier then return self end
self.PlaybackSpeed = playbackSpeedMultiplier
self:UpdatePlaybackSpeed()
return self
end
function STREAM:SetAdditivePitchModifier(additivePitchModifier)
if self.AdditivePitchModifier == additivePitchModifier then return self end
self.AdditivePitchModifier = additivePitchModifier
self:UpdatePlaybackSpeed()
return self
end
function STREAM:UpdatePlaybackSpeed()
self:Call(".speed = %f", self.PlaybackSpeed + self.AdditivePitchModifier)
end
-- Volume
function STREAM:GetPanning()
return self.Panning
end
function STREAM:GetVolume()
return self.Volume
end
function STREAM:GetAdditiveVolumeModifier()
return self.AdditiveVolumeModifier
end
function STREAM:SetPanning(panning)
if self.Panning == panning then return self end
self.Panning = panning
self:UpdateVolume()
return self
end
function STREAM:SetVolume(volumeFraction)
if self.Volume == volumeFraction then return self end
self.Volume = volumeFraction
self:UpdateVolume()
return self
end
function STREAM:SetAdditiveVolumeModifier (additiveVolumeFraction)
if self.AdditiveVolumeFraction == additiveVolumeFraction then return self end
self.AdditiveVolumeFraction = additiveVolumeFraction
self:UpdateVolume()
return self
end
function STREAM:UpdateSourcePosition()
if not self.SourceEntity:IsValid() then return end
self.SourcePosition = self.SourceEntity:GetPos()
end
function STREAM:UpdateVolume()
if self.Use3d then
self:UpdateVolume3d()
else
self:UpdateVolumeFlat()
end
end
function STREAM:UpdateVolumeFlat()
self:Call(".vol_right = %f", (math.Clamp(1 + self.Panning, 0, 1) * self.Volume) + self.AdditiveVolumeFraction)
self:Call(".vol_left = %f", (math.Clamp(1 - self.Panning, 0, 1) * self.Volume) + self.AdditiveVolumeFraction)
end
function STREAM:UpdateVolume3d()
self:UpdateSourcePosition()
self.SourcePosition = self.SourcePosition or Vector()
self.LastSourcePosition = self.LastSourcePosition or self.SourcePosition
self.LastSourcePositionTime = self.LastSourcePositionTime or (CurTime() - FrameTime())
self.SourceVelocity = (self.SourcePosition - self.LastSourcePosition) / (CurTime() - self.LastSourcePositionTime)
self.LastSourcePosition = self.SourcePosition
self.LastSourcePositionTime = CurTime()
local relativeSourcePosition = self.SourcePosition - listenerPosition
local distanceToSource = relativeSourcePosition:Length()
if distanceToSource < self.SourceRadius then
local pan = relativeSourcePosition:GetNormalized():Dot(listenerAngle:Right())
local volumeFraction = math.Clamp(1 - distanceToSource / self.SourceRadius, 0, 1) ^ 1.5
volumeFraction = volumeFraction * 0.75 * self.Volume
self:Call(".vol_right = %f", (math.Clamp(1 + pan, 0, 1) * volumeFraction) + self.AdditiveVolumeFraction)
self:Call(".vol_left = %f", (math.Clamp(1 - pan, 0, 1) * volumeFraction) + self.AdditiveVolumeFraction)
if self.UseDoppler then
local relativeSourcePosition = self.SourcePosition - listenerPosition
local relativeSourceVelocity = self.SourceVelocity - listenerVelocity
local relativeSourceSpeed = relativeSourcePosition:GetNormalized():Dot(-relativeSourceVelocity) * 0.0254
self:Call(".speed = %f", (self.PlaybackSpeed + (relativeSourceSpeed / webaudio.SpeedOfSound)) + self.AdditivePitchModifier)
end
self.ListenerOutOfRadius = false
else
if not self.ListenerOutOfRadius then
self:Call(".vol_right = 0")
self:Call(".vol_left = 0")
self.ListenerOutOfRadius = true
end
end
end
-- Filtering
DECLARE_PROPERTY("FilterType", ".filter_type = %i")
DECLARE_PROPERTY("FilterFraction", ".filter_fraction = %f", 0, function(num) return math.Clamp(num, 0, 1) end)
DECLARE_PROPERTY("Echo", ".useEcho(%s)", false)
DECLARE_PROPERTY("EchoDelay", ".setEchoDelay(Math.ceil(audio.sampleRate * %f))", 1, function(num) return math.max(num, 0) end)
DECLARE_PROPERTY("EchoFeedback", ".echo_feedback = %f", 0.75)
-- 3D
function STREAM:Enable3D(b)
self.Use3d = b
end
function STREAM:EnableDoppler(b)
self.UseDoppler = b
end
function STREAM:GetSourceEntity()
return self.SourceEntity
end
function STREAM:SetSourceEntity(sourceEntity, doNotRemove)
self.SourceEntity = sourceEntity
if not doNotRemove then
sourceEntity:CallOnRemove("webaudio_remove_stream_" .. tostring(self), function()
if self:IsValid() then
self:Remove()
end
end)
end
end
function STREAM:GetSourcePosition()
return self.SourcePosition
end
function STREAM:SetSourcePosition(vec)
self.SourcePosition = vec
end
function STREAM:GetSourceVelocity()
return self.SourceVelocity
end
function STREAM:SetSourceVelocity(vec)
self.SourceVelocity = vec
end
function STREAM:GetSourceRadius()
return self.SourceRadius
end
function STREAM:SetSourceRadius(sourceRadius)
self.SourceRadius = sourceRadius
end
function STREAM:Think()
if self.Paused then return end
if self.Use3d then
self:UpdateVolume3d() -- updates source position internally
else
self:UpdateSourcePosition()
end
end
function STREAM:__newindex(key, val)
if key == "OnFFT" then
if isfunction(val) then
self:Call(".usefft(true)")
else
self:Call(".usefft(false)")
end
end
rawset(self, key, val)
end
function STREAM:__tostring()
return string.format("stream[%p][%d][%s]", self, self:GetId(), self:GetUrl())
end
-- Internal browser message handlers
function STREAM:HandleCallBrowserMessage(methodName, ...)
if not self[methodName] then return end
self[methodName](self, ...)
end
function STREAM:HandleFFTBrowserMessage(serializeFFTData)
local fftArray = CompileString(serializeFFTData, "stream_fft_data")()
self.OnFFT(fftArray)
end
function STREAM:HandleLoadedBrowserMessage(sampleCount)
self.Loaded = true
self.SampleCount = sampleCount
self:SetFilterType(0)
if not self.Paused then
-- self:Play()
end
self:SetMaxLoopCount(self:GetMaxLoopCount())
self:SetEcho (self:GetEcho ())
self:SetEchoFeedback(self:GetEchoFeedback())
self:SetEchoDelay (self:GetEchoDelay ())
if self.OnLoad then
self:OnLoad()
end
end
function STREAM:HandlePositionBrowserMessage(samplePosition)
self.SamplePosition = samplePosition
end

View File

@@ -0,0 +1,61 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- made by Morten and CapsAdmin
pac.webaudio = pac.webaudio or {}
local webaudio = pac.webaudio
webaudio.Streams = webaudio.Streams or {}
webaudio.Streams.LastStreamId = 0
webaudio.Streams.Streams = {}
function webaudio.Streams.CreateStream(url)
--url = url:gsub("http[s?]://", "http://")
if not url:find("http",1,true) then
url = "asset://garrysmod/sound/" .. url
end
local stream = setmetatable({}, webaudio.Streams.STREAM)
webaudio.Streams.LastStreamId = webaudio.Streams.LastStreamId + 1
stream:SetId(webaudio.Streams.LastStreamId)
stream:SetUrl(url)
webaudio.Streams.Streams[stream:GetId()] = stream
webaudio.Browser.QueueJavascript(string.format("createStream(%q, %d)", stream:GetUrl(), stream:GetId()))
return stream
end
function webaudio.Streams.GetStream(streamId)
return webaudio.Streams.Streams[streamId]
end
function webaudio.Streams.StreamExists(streamId)
return webaudio.Streams.Streams[streamId] ~= nil
end
function webaudio.Streams.Think()
for streamId, stream in pairs(webaudio.Streams.Streams) do
if stream:IsValid() then
stream:Think()
else
stream:Stop()
webaudio.Streams.Streams[streamId] = nil
webaudio.Browser.QueueJavascript(string.format("destroyStream(%i)", stream:GetId()))
setmetatable(stream, getmetatable(NULL))
end
end
end

View File

@@ -0,0 +1,68 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- made by Morten and CapsAdmin
pac.webaudio = pac.webaudio or {}
local webaudio = pac.webaudio
webaudio.Debug = 0
webaudio.SampleRate = nil
webaudio.SpeedOfSound = 340.29 -- metres per second
function webaudio.DebugPrint(str, ...)
if webaudio.Debug == 0 then return end
if webaudio.Debug >= 1 then
if epoe then
-- Why is this even present here?
epoe.MsgC(Color(0, 255, 0), "[WebAudio] ")
epoe.MsgC(Color(255, 255, 255), str)
epoe.Print("")
end
pac.Message(Color(0, 255, 0), "[WebAudio] ", Color(255, 255, 255), str, ...)
end
if webaudio.Debug >= 2 then
if easylua then
easylua.PrintOnServer("[WebAudio] " .. str .. ' ' .. table.concat({...}, ', '))
end
end
end
function webaudio.GetSampleRate ()
return webaudio.SampleRate
end
local volume = GetConVar("volume")
local snd_mute_losefocus = GetConVar("snd_mute_losefocus")
pac.AddHook("Think", "webaudio", function()
if not webaudio.Browser.IsInitialized () then
if not webaudio.Browser.IsInitializing () then
webaudio.Browser.Initialize ()
end
return
end
-- Update volume
if not system.HasFocus() and snd_mute_losefocus:GetBool() then
-- Garry's Mod not in foreground and we're not supposed to be making any sound
webaudio.Browser.SetVolume(0)
else
webaudio.Browser.SetVolume(volume:GetFloat())
end
webaudio.Streams.Think()
webaudio.Browser.Think()
end)