So I’ve been making a script to play music, but with the options for the player to ‘mute’ or ‘mute copyrighted’ songs within a moduleScript.
When the script starts, it generates a number for each of the songs, and then shuffles them in the appropriate order.
The ‘Mute Copyrighted’ setting is merely used for songs that I’m unsure would get content creators videos flagged or not. Just a safety precaution basically.
The problem that I’m running into is that when you uncheck/enable this setting multiple times, especially in quick succession, the songs seem to overlap for some reason.
I’ve tried yielding the script until the song had Ended/Stopped via Sound.Ended and Sound.Stopped, but no success there.
The ‘Mute’ setting works fine, but the ‘mute copyrighted’ is the issue here.
You may use them if you have the license(s) required, problem is those licenses might not cover recordings of your game, or more commonly, automated systems (Content ID) claiming videos regardless, which is a major headache for content creators.
Well they’re probably from the creator marketplace; post audio update, it’s more likely they do have the license required. Still, automated systems can’t really tell (AFAIK) the difference, so they still get claims.
But back to solving OP’s problem:
High chance they’re running into a race condition, but I can’t tell exactly what it is, might want to consider rewriting it to be simpler, you don’t need to make everything a complicated OOP module!
It’s as Nowoshire stated. Basically even though some of the audio’s that have been uploaded to Roblox via those sound libraries are licensed for game-use, it doesn’t necessarily mean that we have the license to use those in videos on Youtube and the like.
The ‘Sound’ object doesn’t seem to have a definitive “The sound has finished, whether it was done via :Stop() or it’s playback concluded”, so I’ve had to account for both scenarios, which is why I am using a boolean value to yield until one of those conditions is met.
@nowodev Hey I managed to fix it finally. The issue was that I had been relying on a “Holding” variable at the top of the script. At times, especially when switching the flag on and off, the while holding do loop wouldn’t always turn off.
I solved it by instead of relying on said loop, I created a bool each time the start function is called, and when it is destroyed, the loop breaks.
Nevertheless, I really appreciate you for taking the time to look over the script
--// Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
--// Variables
local Player : Player = Players.LocalPlayer
local Shared = ReplicatedStorage.Shared
--// Tables
local OST = script.OST:GetChildren()
--// Modules
local Assistant = require(Shared.Assistant)
local Music = {}
--// Functions
function Music:Start()
Music:StopAll()
local Listener = Instance.new("BoolValue")
Listener:SetAttribute("Start", DateTime.now().UnixTimestampMillis)
Listener.Parent = script.Holder
local Holding = true
Listener.Destroying:Once(function()
Holding = false
end)
task.spawn(function()
while Holding do
if not Holding then
break
end
Music:Shuffle()
for _, sound : Sound in OST do
if not Holding then
break
end
if Player:GetAttribute("Video") then
if sound:GetAttribute("IsCopyright") then
continue
end
end
sound:Play()
local _Ended = coroutine.create(function() -- For when the song finishes playback, open val 'gate'
sound.Ended:Wait()
print("ENDED")
Music.OnFinished()
end)
local _Stopped = coroutine.create(function() -- For when the song is forcefully stopped, open val 'gate'
sound.Stopped:Wait()
print("STOPPED")
Music.OnFinished()
end)
coroutine.resume(_Ended)
coroutine.resume(_Stopped)
script:GetAttributeChangedSignal("SongFinished"):Wait() -- Value to wait for. i.e. the 'gate'
sound:Stop()
if coroutine.running(_Ended) then
coroutine.close(_Ended)
end
if coroutine.running(_Stopped) then
coroutine.close(_Stopped)
end
end
task.wait(1)
end
end)
end
function Music.OnFinished()
Assistant:SwitchFlag(script, "SongFinished")
end
function Music:StopAll()
for _, sound in OST do
if sound:IsA("Sound") then
sound:Stop()
sound.TimePosition = 0
end
end
end
function Music:Stop()
Music:StopAll()
for _, v in pairs(script.Holder:GetChildren()) do
local started = v:GetAttribute("Start") or 0
if DateTime.now().UnixTimestampMillis > started then
v:Destroy()
end
end
end
function Music:Shuffle()
local Places = {}
for looping = 1, #OST do
table.insert(Places, looping)
end
for _, sound in OST do
if sound:IsA("Sound") then
local randomIndex = math.random(1, #Places)
sound:SetAttribute("Order", Places[randomIndex])
table.remove(Places, randomIndex)
end
end
table.sort(OST, function(a, b)
return a:GetAttribute("Order") < b:GetAttribute("Order")
end)
Places = nil
end
--// Script
return Music