hi, i tried making something easier to make audio using code and theres type checking too
heres how to use:
Tutorial
AudioEmitter with DiffractionEnabled set to Enabled and parented to workspace.
local audioEmitter = AudioService.newAudioEmitter({
DiffractionEnabled = Enum.SimulationMode.Enabled
}, workspace)
Fader → Distortion → Echo → AudioEmitter
local fader = audioEmitter:AddEffect("Fader")
local distortion = audioEmitter:AddEffect("Distortion")
local echo = audioEmitter:AddEffect("Echo")
AudioPlayer → Fader → Distortion → Echo → AudioEmitter
local audio = AudioService.newAudioPlayer(1234567890, nil, audioEmitter.instance)
AudioPlayer → Echo → Fader → Distortion → Echo → AudioEmitter
local echo = audio:AddEffect("Echo", nil, audioEmitter)
AudioPlayer → Echo → Reverb → Fader → Distortion → Echo → AudioEmitter
AudioPlayer → Echo → Reverb → AudioEmitter2
local reverb = audio:AddEffect("Reverb", nil, {audioEmitter, audioEmitter2})
AudioPlayer → Reverb → Fader → Distortion → Echo → AudioEmitter
AudioPlayer → Reverb → AudioEmitter2
audio:RemoveEffect(echo)
AudioPlayer → Fader → Distortion → Echo → AudioEmitter
AudioPlayer → AudioEmitter2
audio:ClearEffects()
AudioPlayer → AudioEmitter
AudioPlayer → AudioEmitter2
audioEmitter:ClearEffects()
Inserts an attachment in workspace at the position, copies audioplayer, wires, and audioemitters and puts it inside the attachment and plays the audio
audio:PlayAtPosition(Vector3.new(0, 10, 0))
Code
AudioService
local AudioPlayerController = require("@self/AudioPlayerController")
local AudioEmitterController = require("@self/AudioEmitterController")
return {
newAudioPlayer = AudioPlayerController.new,
newAudioEmitter = AudioEmitterController.new,
}
AudioUtils
local AudioTypes = require("./AudioTypes")
local AudioUtils = {}
function AudioUtils.writeProperty(instance: Instance, property: string, value: any)
instance[property] = value
end
function AudioUtils.writePropertySafe(instance: Instance, property: string, value: any): boolean
local success, err = pcall(AudioUtils.writeProperty, instance, property, value)
if not success then
warn(`Error while setting property {property} on {instance.ClassName}: {err}`)
return false
end
return true
end
function AudioUtils.writeProperties(instance: Instance, properties: {[string]: any})
for property, value in properties do
AudioUtils.writePropertySafe(instance, property, value)
end
end
function AudioUtils.createEffect(effect: string | AudioTypes.Effect, properties: {[string]: any}?, parent: Instance): Instance
local effectInstance = Instance.new("Audio"..effect)
if properties then
AudioUtils.writeProperties(effectInstance, properties)
end
effectInstance.Parent = parent
return effectInstance
end
return AudioUtils
AudioPlayerController
local AudioTypes = require("./AudioTypes")
local AudioUtils = require("./AudioUtils")
local AudioWiresController = require("./AudioWiresController")
local AudioPlayerController = {}
AudioPlayerController.__index = AudioPlayerController
export type AudioPlayerController = AudioTypes.AudioPlayerController
type AudioPlayerControllerType = AudioPlayerController
function AudioPlayerController.new(audioId: number, properties: {[string]: any}?, parent: Instance?): AudioPlayerController
local audioPlayer = Instance.new("AudioPlayer")
audioPlayer.Asset = "rbxassetid://"..audioId
if properties then
AudioUtils.writeProperties(audioPlayer, properties)
end
if parent then
audioPlayer.Parent = parent
end
local self = {
instance = audioPlayer,
audioEmitterControllers = {},
effects = {},
} :: AudioPlayerController
self.audioWiresController = AudioWiresController.new(self)
setmetatable(self, AudioPlayerController)
return self :: any
end
function AudioPlayerController.ChangeAudioId(self: AudioPlayerController, audioId: number): AudioPlayerController
self.instance.Asset = "rbxassetid://"..audioId
return self
end
function AudioPlayerController.AddEffect(self: AudioPlayerController, effect: string, properties: {[string]: any}?, channel: AudioTypes.Channel?): Instance
local effectInstance = AudioUtils.createEffect(effect, properties, self.instance)
self:AddEffectFromInstance(effectInstance, channel)
return effectInstance
end
function AudioPlayerController.AddEffectFromInstance(self: AudioPlayerController, effectInstance: Instance | {Instance}, channel: AudioTypes.Channel?)
if type(effectInstance) == "table" then
table.move(self.effects, 1, #effectInstance, #self.effects + 1, effectInstance)
for _, effect in effectInstance do
self.audioWiresController:ConnectWireToChannel(effect, channel)
end
else
table.insert(self.effects, effectInstance)
self.audioWiresController:ConnectWireToChannel(effectInstance, channel)
end
end
function AudioPlayerController.RemoveEffect(self: AudioPlayerController, effectInstance: Instance | {Instance}, channel: AudioTypes.Channel?): boolean
if type(effectInstance) == "table" then
for _, effect in effectInstance do
self:RemoveEffect(effect, channel)
end
return true
end
local index = table.find(self.effects, effectInstance)
if not index then
return false
end
table.remove(self.effects, index)
self.audioWiresController:DisconnectWireFromChannel(effectInstance, channel)
effectInstance:Destroy()
return true
end
function AudioPlayerController.ClearEffects(self: AudioPlayerController)
self.audioWiresController:DisconnectAllWires()
for _, effectInstance in self.effects do
effectInstance:Destroy()
end
table.clear(self.effects)
end
function AudioPlayerController.PlayAtPosition(self: AudioPlayerController, position: Vector3 | vector, atTime: number?)
local attachment = Instance.new("Attachment")
attachment.WorldPosition = position
local newPlayer = Instance.fromExisting(self.instance)
local newEmitter: AudioEmitter
local newEffect: Instance
local mainWire: Wire
local wire: Wire
local targetInstance: Instance
for audioEmitterController, chain in self.audioWiresController.channels do
if #chain == 0 then
continue
end
newEmitter = Instance.fromExisting(audioEmitterController.instance)
mainWire = Instance.new("Wire")
mainWire.SourceInstance = newPlayer
for i, effectInstance in chain do
newEffect = Instance.fromExisting(effectInstance)
if i == 1 then
mainWire.TargetInstance = newEffect
end
if wire then
wire.TargetInstance = newEffect
wire.Parent = newEmitter
end
wire = Instance.new("Wire")
wire.SourceInstance = newEffect
newEffect.Parent = newPlayer
end
if wire then
wire.TargetInstance = newEmitter
wire.Parent = newEmitter
end
mainWire.Parent = newEmitter
newEmitter.Parent = attachment
end
newPlayer.Parent = attachment
attachment.Parent = workspace
local cleaned = false
local function cleanup()
if cleaned then
return
end
cleaned = true
attachment:Destroy()
end
newPlayer.Ended:Once(cleanup)
newPlayer.Destroying:Once(cleanup)
newPlayer:Play(atTime)
end
function AudioPlayerController.Destroy(self: AudioPlayerController)
self.audioWiresController:Destroy()
self.instance:Destroy()
for _, effectInstance in self.effects do
effectInstance:Destroy()
end
table.clear(self.effects)
setmetatable(self, nil)
end
return AudioPlayerController :: {
new: (audioId: number, properties: AudioTypes.GetProperties<AudioPlayer>?, parent: Instance?) -> AudioPlayerController,
}
AudioEmitterController
local AudioTypes = require("./AudioTypes")
local AudioUtils = require("./AudioUtils")
local AudioChannelWiresController = require("./AudioChannelWiresController")
local AudioEmitterController = {}
AudioEmitterController.__index = AudioEmitterController
export type AudioEmitterController = AudioTypes.AudioEmitterController
function AudioEmitterController.new(properties: {[string]: any}?, parent: Instance?): AudioEmitterController
local audioEmitter = Instance.new("AudioEmitter")
if properties then
AudioUtils.writeProperties(audioEmitter, properties)
end
if parent then
audioEmitter.Parent = parent
end
local self = {
instance = audioEmitter,
audioPlayerControllers = {},
effects = {},
} :: AudioEmitterController
self.audioChannelWiresController = AudioChannelWiresController.new(self)
setmetatable(self, AudioEmitterController)
return self :: any
end
function AudioEmitterController.GetInputInstance(self: AudioEmitterController): Instance
return self.effects[1] or self.instance
end
function AudioEmitterController.AddEffect(self: AudioEmitterController, effect: string, properties: {[string]: any}?): Instance
local effectInstance = AudioUtils.createEffect(effect, properties, self.instance)
self:AddEffectFromInstance(effectInstance)
return effectInstance
end
function AudioEmitterController.AddEffectFromInstance(self: AudioEmitterController, effectInstance: Instance | {Instance})
if type(effectInstance) == "table" then
table.move(self.effects, 1, #effectInstance, #self.effects + 1, effectInstance)
for _, effect in effectInstance do
self.audioChannelWiresController:ConnectWire(effect)
end
else
table.insert(self.effects, effectInstance)
self.audioChannelWiresController:ConnectWire(effectInstance)
end
end
function AudioEmitterController.RemoveEffect(self: AudioEmitterController, effectInstance: Instance | {Instance}): boolean
if type(effectInstance) == "table" then
for _, effect in effectInstance do
self:RemoveEffect(effect)
end
return true
end
local index = table.find(self.effects, effectInstance)
if not index then
return false
end
table.remove(self.effects, index)
self.audioChannelWiresController:DisconnectWire(effectInstance)
effectInstance:Destroy()
return true
end
function AudioEmitterController.ClearEffects(self: AudioEmitterController)
self.audioChannelWiresController:DisconnectAllWires()
for _, effectInstance in self.effects do
effectInstance:Destroy()
end
table.clear(self.effects)
end
function AudioEmitterController.Destroy(self: AudioEmitterController)
self.audioChannelWiresController:Destroy()
self.instance:Destroy()
for _, effectInstance in self.effects do
effectInstance:Destroy()
end
table.clear(self.effects)
setmetatable(self, nil)
end
return AudioEmitterController :: {
new: (properties: AudioTypes.GetProperties<AudioEmitter>?, parent: Instance?) -> AudioEmitterController,
}
AudioWiresController
local AudioTypes = require("./AudioTypes")
local AudioUtils = require("./AudioUtils")
local AudioWiresController = {}
AudioWiresController.__index = AudioWiresController
export type AudioWiresController = AudioTypes.AudioWiresController
function AudioWiresController.new(audioPlayerController: AudioTypes.AudioPlayerController): AudioWiresController
return setmetatable({
audioPlayerController = audioPlayerController,
channels = {},
wiresPool = {},
activeWires = {},
}, AudioWiresController) :: any
end
function AudioWiresController._pullWire(self: AudioWiresController, sourceInstance: Instance, targetInstance: Instance): Wire
local wire = table.remove(self.wiresPool) or Instance.new("Wire")
wire.SourceInstance = sourceInstance
wire.TargetInstance = targetInstance
wire.Parent = self.audioPlayerController.instance
return wire
end
function AudioWiresController._pushWireToPool(self: AudioWiresController, sourceInstance: Instance, targetInstance: Instance): boolean
local activeWiresSource = self.activeWires[sourceInstance]
if not activeWiresSource then
return false
end
local wire = activeWiresSource[targetInstance]
if not wire then
return false
end
activeWiresSource[targetInstance] = nil
wire.Parent = nil
wire.SourceInstance = nil
wire.TargetInstance = nil
table.insert(self.wiresPool, wire)
if not next(activeWiresSource) then
self.activeWires[sourceInstance] = nil
end
return true
end
function AudioWiresController._connectWireToChannel(self: AudioWiresController, targetInstance: Instance, singleChannel: AudioTypes.SingleChannel)
local chain = self.channels[singleChannel]
if not chain then
chain = {}
self.channels[singleChannel] = chain
end
local activeWiresSource = self.activeWires[singleChannel.instance]
local previousEffectInstance = chain[#chain]
if previousEffectInstance then
local previousWire = activeWiresSource[previousEffectInstance]
previousWire.TargetInstance = targetInstance
else
if not activeWiresSource then
local wire = self:_pullWire(self.audioPlayerController.instance, targetInstance)
activeWiresSource = {[self.audioPlayerController.instance :: Instance] = wire}
self.activeWires[singleChannel.instance] = activeWiresSource
else
local wire = activeWiresSource[self.audioPlayerController.instance]
wire.TargetInstance = targetInstance
end
end
local channelInstance = singleChannel:GetInputInstance()
local wire = self:_pullWire(targetInstance, channelInstance)
activeWiresSource[targetInstance] = wire
table.insert(chain, targetInstance)
self.audioPlayerController.audioEmitterControllers[singleChannel] = true
singleChannel.audioPlayerControllers[self.audioPlayerController] = true
end
function AudioWiresController.ConnectWireToChannel(self: AudioWiresController, targetInstance: Instance, channel: AudioTypes.Channel?)
if not channel then
local copy = {}
for singleChannel in self.channels do
table.insert(copy, singleChannel)
end
for _, singleChannel in copy do
self:_connectWireToChannel(targetInstance, singleChannel)
end
elseif type(channel) == "table" and not channel.instance then
for _, singleChannel in channel do
self:_connectWireToChannel(targetInstance, singleChannel)
end
else
self:_connectWireToChannel(targetInstance, channel)
end
end
function AudioWiresController._disconnectWireFromChannel(self: AudioWiresController, targetInstance: Instance, singleChannel: AudioTypes.SingleChannel): boolean
local chain = self.channels[singleChannel]
if not chain then
return false
end
local index = table.find(chain, targetInstance)
if not index then
return false
end
table.remove(chain, index)
local previousSourceInstance = chain[index - 1] or self.audioPlayerController.instance
local nextTargetInstance = chain[index] or singleChannel.instance
local activeWiresSource = self.activeWires[singleChannel.instance]
local previousWire = activeWiresSource[previousSourceInstance]
previousWire.TargetInstance = nextTargetInstance
self:_pushWireToPool(singleChannel.instance, targetInstance)
if #chain == 0 then
self.channels[singleChannel] = nil
end
self.audioPlayerController.audioEmitterControllers[singleChannel] = nil
singleChannel.audioPlayerControllers[self.audioPlayerController] = nil
return true
end
function AudioWiresController.DisconnectWireFromChannel(self: AudioWiresController, targetInstance: Instance, channel: AudioTypes.Channel?): boolean
local removedAny = false
if not channel then
local copy = {}
for singleChannel in self.channels do
table.insert(copy, singleChannel)
end
for _, singleChannel in copy do
local removed = self:_disconnectWireFromChannel(targetInstance, singleChannel)
if removed then
removedAny = true
end
end
elseif type(channel) == "table" and not channel.instance then
for _, singleChannel in channel do
local removed = self:_disconnectWireFromChannel(targetInstance, singleChannel)
if removed then
removedAny = true
end
end
else
removedAny = self:_disconnectWireFromChannel(targetInstance, channel)
end
return removedAny
end
function AudioWiresController.DisconnectAllWires(self: AudioWiresController)
for singleChannel, chain in self.channels do
local activeWiresSource = self.activeWires[singleChannel.instance]
if not activeWiresSource then
continue
end
local wire = activeWiresSource[self.audioPlayerController.instance]
wire.TargetInstance = singleChannel:GetInputInstance()
for _, targetInstance in chain do
self:_pushWireToPool(singleChannel.instance, targetInstance)
end
table.clear(chain)
self.audioPlayerController.audioEmitterControllers[singleChannel] = nil
singleChannel.audioPlayerControllers[self.audioPlayerController] = nil
end
end
function AudioWiresController.DestroyAllWires(self: AudioWiresController)
for singleChannel in self.channels do
local activeWiresSource = self.activeWires[singleChannel.instance]
if not activeWiresSource then
continue
end
for _, wire in activeWiresSource do
wire:Destroy()
end
self.audioPlayerController.audioEmitterControllers[singleChannel] = nil
singleChannel.audioPlayerControllers[self.audioPlayerController] = nil
end
table.clear(self.channels)
table.clear(self.activeWires)
for _, wire in self.wiresPool do
wire:Destroy()
end
table.clear(self.wiresPool)
end
function AudioWiresController.Destroy(self: AudioWiresController)
self:DestroyAllWires()
setmetatable(self, nil)
end
return AudioWiresController :: {
new: (audioPlayerController: AudioTypes.AudioPlayerController) -> AudioWiresController,
}
AudioChannelWiresController
local AudioTypes = require("./AudioTypes")
local AudioUtils = require("./AudioUtils")
local AudioChannelWiresController = {}
AudioChannelWiresController.__index = AudioChannelWiresController
export type AudioChannelWiresController = AudioTypes.AudioChannelWiresController
function AudioChannelWiresController.new(channel: AudioTypes.SingleChannel): AudioChannelWiresController
return setmetatable({
channel = channel,
wiresPool = {},
activeWires = {},
chain = {},
}, AudioChannelWiresController) :: any
end
function AudioChannelWiresController._pullWire(self: AudioChannelWiresController, sourceInstance: Instance, targetInstance: Instance): Wire
local wire = table.remove(self.wiresPool) or Instance.new("Wire")
wire.SourceInstance = sourceInstance
wire.TargetInstance = targetInstance
wire.Parent = self.channel.instance
return wire
end
function AudioChannelWiresController._pushWireToPool(self: AudioChannelWiresController, targetInstance: Instance): boolean
local wire = self.activeWires[targetInstance]
if not wire then
return false
end
self.activeWires[targetInstance] = nil
wire.Parent = nil
wire.SourceInstance = nil
wire.TargetInstance = nil
table.insert(self.wiresPool, wire)
return true
end
function AudioChannelWiresController.ConnectWire(self: AudioChannelWiresController, targetInstance: Instance)
local previousEffectInstance = self.chain[#self.chain]
if previousEffectInstance then
local previousWire = self.activeWires[previousEffectInstance]
previousWire.TargetInstance = targetInstance
end
self.activeWires[targetInstance] = self:_pullWire(targetInstance, self.channel.instance)
table.insert(self.chain, targetInstance)
end
function AudioChannelWiresController.DisconnectWire(self: AudioChannelWiresController, targetInstance: Instance): boolean
local index = table.find(self.chain, targetInstance)
if not index then
return false
end
table.remove(self.chain, index)
local previousEffect = self.chain[index - 1]
if previousEffect then
local previousWire = self.activeWires[previousEffect]
local nextTarget = self.chain[index] or self.channel.instance
previousWire.TargetInstance = nextTarget
end
if index == 1 then
self:ReattachWires()
end
return self:_pushWireToPool(targetInstance)
end
function AudioChannelWiresController.DisconnectAllWires(self: AudioChannelWiresController)
for _, effectInstance in self.chain do
self:_pushWireToPool(effectInstance)
end
table.clear(self.chain)
self:ReattachWires()
end
function AudioChannelWiresController.DestroyAllWires(self: AudioChannelWiresController)
for _, effectInstance in self.chain do
self.activeWires[effectInstance]:Destroy()
end
table.clear(self.chain)
table.clear(self.activeWires)
for _, wire in self.wiresPool do
wire:Destroy()
end
table.clear(self.wiresPool)
self:ReattachWires()
end
function AudioChannelWiresController.ReattachWires(self: AudioChannelWiresController)
local inputInstance = self.channel:GetInputInstance()
for audioPlayerController in self.channel.audioPlayerControllers do
local activeWiresSource = audioPlayerController.audioWiresController.activeWires[self.channel.instance]
local chain = audioPlayerController.audioWiresController.channels[self.channel]
local effectInstance = chain[#chain]
local wire = activeWiresSource[effectInstance]
wire.TargetInstance = inputInstance
end
end
function AudioChannelWiresController.Destroy(self: AudioChannelWiresController)
self:DestroyAllWires()
setmetatable(self, nil)
end
return AudioChannelWiresController :: {
new: (channel: AudioTypes.SingleChannel) -> AudioChannelWiresController,
}
AudioTypes
export type AudioPlayerController = setmetatable<{
instance: AudioPlayer,
audioEmitterControllers: {[AudioEmitterController]: boolean},
attachment: Attachment?,
audioWiresController: AudioWiresController,
effects: {Instance},
ChangeAudioId: (self: AudioPlayerController, audioId: number) -> AudioPlayerController,
AddEffect: <T>(self: AudioPlayerController, effect: T | Effect, properties: GetEffectProperties<T>?, channel: Channel?) -> GetEffectInstance<T>,
AddEffectFromInstance: (self: AudioPlayerController, effectInstance: Instance | {Instance}, channel: Channel?) -> (),
RemoveEffect: <T>(self: AudioPlayerController, effectInstance: Instance | {Instance}, channel: Channel?) -> boolean,
ClearEffects: (self: AudioPlayerController) -> (),
PlayAtPosition: (self: AudioPlayerController, position: Vector3 | vector, atTime: number?) -> (),
Destroy: (self: AudioPlayerController) -> ()
}, {
__index: AudioPlayerController
}>
export type AudioEmitterController = setmetatable<{
instance: AudioEmitter,
audioPlayerControllers: {[AudioPlayerController]: boolean},
audioChannelWiresController: AudioChannelWiresController,
effects: {Instance},
GetInputInstance: (self: AudioEmitterController) -> Instance,
AddEffect: <T>(self: AudioEmitterController, effect: T | Effect, properties: GetEffectProperties<T>?) -> GetEffectInstance<T>,
AddEffectFromInstance: (self: AudioEmitterController, effectInstance: Instance | {Instance}) -> (),
RemoveEffect: <T>(self: AudioEmitterController, effectInstance: Instance | {Instance}) -> boolean,
ClearEffects: (self: AudioEmitterController) -> (),
Destroy: (self: AudioEmitterController) -> (),
}, {
__index: AudioEmitterController
}>
export type AudioWiresController = setmetatable<{
audioPlayerController: AudioPlayerController,
channels: {[AudioEmitterController]: {Instance}},
wiresPool: {Wire},
activeWires: {[Instance]: {[Instance]: Wire}},
_pullWire: (self: AudioWiresController, sourceInstance: Instance, targetInstance: Instance) -> Wire,
_pushWireToPool: (self: AudioWiresController, sourceInstance: Instance, targetInstance: Instance) -> boolean,
_connectWireToChannel: (self: AudioWiresController, targetInstance: Instance, channel: AudioEmitterController) -> (),
ConnectWireToChannel: (self: AudioWiresController, targetInstance: Instance, channel: Channel?) -> (),
_disconnectWireFromChannel: (self: AudioWiresController, targetInstance: Instance, channel: AudioEmitterController) -> boolean,
DisconnectWireFromChannel: (self: AudioWiresController, targetInstance: Instance, channel: Channel?) -> boolean,
DisconnectAllWires: (self: AudioWiresController) -> (),
DestroyAllWires: (self: AudioWiresController) -> (),
Destroy: (self: AudioWiresController) -> (),
}, {
__index: AudioWiresController
}>
export type AudioChannelWiresController = setmetatable<{
channel: SingleChannel,
wiresPool: {Wire},
activeWires: {[Instance]: Wire},
chain: {Instance},
_pullWire: (self: AudioChannelWiresController, sourceInstance: Instance, targetInstance: Instance) -> Wire,
_pushWireToPool: (self: AudioChannelWiresController, targetInstance: Instance) -> boolean,
ConnectWire: (self: AudioChannelWiresController, targetInstance: Instance) -> (),
DisconnectWire: (self: AudioChannelWiresController, targetInstance: Instance) -> boolean,
DisconnectAllWires: (self: AudioChannelWiresController) -> (),
DestroyAllWires: (self: AudioChannelWiresController) -> (),
ReattachWires: (self: AudioChannelWiresController) -> (),
Destroy: (self: AudioChannelWiresController) -> (),
}, {
__index: AudioChannelWiresController
}>
export type function GetProperties(T: type)
local result = types.newtable()
for key, property in T:properties() do
if not property.write then
continue
end
if property.write:is("function") then
continue
end
result:setproperty(key, types.optional(property.write))
end
return result
end
type rawIndex<T, U> = rawget<T, U>
export type function GetEffectProperties(T: type)
if not T:is("singleton") then
return types.any
end
local result = rawIndex(AudioProperties, T)
return if result ~= types.singleton(nil) then result else types.singleton(nil)
end
export type function GetEffectInstance(T: type)
if not T:is("singleton") then
return types.any
end
local result = rawIndex(AudioInstances, T)
return if result ~= types.singleton(nil) then result else types.singleton(nil)
end
export type SingleChannel = AudioEmitterController
export type Channel = SingleChannel | {SingleChannel}
export type Effect = keyof<AudioInstances>
export type AudioInstances = {
Equalizer: AudioReverb,
Compressor: AudioCompressor,
Reverb: AudioReverb,
Chorus: AudioChorus,
Distortion: AudioDistortion,
Echo: AudioEcho,
Flanger: AudioFlanger,
PitchShifter: AudioPitchShifter,
Tremolo: AudioTremolo,
Fader: AudioFader,
}
export type AudioProperties = {
Equalizer: GetProperties<AudioReverb>,
Compressor: GetProperties<AudioCompressor>,
Reverb: GetProperties<AudioReverb>,
Chorus: GetProperties<AudioChorus>,
Distortion: GetProperties<AudioDistortion>,
Echo: GetProperties<AudioEcho>,
Flanger: GetProperties<AudioFlanger>,
PitchShifter: GetProperties<AudioPitchShifter>,
Tremolo: GetProperties<AudioTremolo>,
Fader: GetProperties<AudioFader>,
}
return true
if there are any bugs, please tell me so that i can fix it. it only just learned about it a few days ago