@rbxts/sound-manager 2.1.0 β†’ 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,48 @@
1
- # Sound Manager
1
+ <h1 align="center">
2
+ <a href="https://www.npmjs.com/package/@rbxts/sound-manager">
3
+ <img src="public/logo.png" alt="Sound-Manager" width="200" />
4
+ </a>
5
+ <br />
6
+ <b>Sound Manager</b>
7
+
8
+ </h1>
2
9
 
3
- A Roblox sound management library built with Roblox-TS
10
+ <div align="center">
11
+
12
+ ![npm](https://img.shields.io/npm/dt/@rbxts/sound-manager?style=flat-square) ![npm](https://img.shields.io/npm/v/@rbxts/sound-manager?style=flat-square) ![GitHub](https://img.shields.io/github/license/dev-lukas0/Sound-Manager?style=flat-square)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ &nbsp;
19
+
20
+
21
+ ## πŸ”‰ Sound Manager
22
+
23
+ **Sound Manager** is a roblox sound-management library built with Roblox-TS, designed to simplify sound handling in your roblox projects.
24
+
25
+ &nbsp;
26
+
27
+ ## πŸ“¦ Installation
4
28
 
5
- ## Getting Started
6
29
  To use the Sound Manager library in your Roblox-TS project, install it via npm:
30
+
7
31
  ```bash
8
32
  npm install @rbxts/sound-manager
9
33
  ```
10
34
 
11
- Example usage:
12
- ```typescript
35
+ &nbsp;
36
+
37
+ ## πŸš€ Quick Start
38
+
39
+ [See the Documentation ->](https://dev-lukas0.github.io/Sound-Manager-Docs/)
40
+
41
+ ### ⚑ Starting with Sound Manager
42
+
43
+ Sound-Manager uses [`createSoundRegistry`]() and [`createSoundCategoryRegistry`]() to create sounds and categories.
44
+
45
+ ```ts
13
46
  import { createSoundRegistry } from "@rbxts/sound-manager";
14
47
 
15
48
  const Sounds = createSoundRegistry({
@@ -17,51 +50,37 @@ const Sounds = createSoundRegistry({
17
50
  id: "rbxassetid://4714389545",
18
51
  volume: 1,
19
52
  loop: false,
20
- }
53
+ },
54
+
55
+ Test: {
56
+ id: "rbxassetid://17771398985",
57
+ volume: 1,
58
+ loop: true,
59
+ }
21
60
  });
61
+ ```
22
62
 
23
- Sounds.preloadAll();
63
+ ### 🎡 Playing Sounds
24
64
 
65
+ To play a sound, you can use the [`play`](https://dev-lukas0.github.io/Sound-Manager-Docs/docs/API/play) method on the sound registry:
66
+
67
+ ```ts
25
68
  Sounds.play("SCP096");
26
69
  ```
27
70
 
28
- ## Roadmap
29
-
30
- ### Core API
31
- - [x] load
32
- - [x] play
33
- - [x] stop / stopAll
34
- - [x] preload / preloadAll
35
- - [x] fadeIn / fadeOut
36
- - [x] reset / resetAll
37
- - [x] setTimePosition
38
- - [x] setVolume / setGlobalVolume
39
- - [x] onEnd
40
- - [x] isPlaying
41
-
42
- ### Development Utilities
43
- - [ ] Total Sound Count function
44
- - [ ] Currently Playing Sounds function
45
- - [ ] Sound Instance Getter function
46
- - [ ] Sound Properties Getter function
47
-
48
- ### Category API
49
- - [x] playCategory
50
- - [x] stopCategory / stopAllCategories
51
- - [x] setCategoryVolume / setGlobalCategoryVolume
52
- - [x] fadeInCategory / fadeOutCategory
53
- - [x] preloadCategory / preloadAllCategories
54
- - [x] isCategoryPlaying
55
- - [x] onCategoryEnd
56
- - [x] resetCategory / resetAllCategories
57
- - [x] playSoundFromCategory
58
-
59
- ### Features
60
- - [x] Sound Autocompletion
61
- - [ ] Sound Categories
62
- - [ ] Sound Creation functions
63
- - [ ] Sound Priority
71
+ &nbsp;
72
+
73
+ ## πŸ—ΊοΈ Roadmap
74
+ -------
75
+ See the [Roadmap](./Roadmap.md) for planned features and current progress.
76
+
77
+ &nbsp;
78
+
79
+ ## πŸ“ License
80
+
81
+ **Sound Manager** is licensed under the [MIT LICENSE](./LICENSE).
64
82
 
83
+ &nbsp;
65
84
 
66
85
  For more Details:
67
86
  https://dev-lukas0.github.io/Sound-Manager-Docs/
@@ -1,11 +1,14 @@
1
1
  import { CategoryOptions } from "./options";
2
+ import { SoundHandle } from "./options";
2
3
  /**
3
4
  * Create a sound category Registry
4
5
  * @param definitions Define the Categorys
5
6
  */
6
7
  export declare function createSoundCategoryRegistry<T extends Record<string, CategoryOptions>>(definitions: T): {
7
8
  loadCategory: (name: keyof T) => void;
8
- playCategory: <C extends keyof T>(name: C) => void;
9
+ playCategory: <C extends keyof T>(name: C, spatial?: {
10
+ emitters: BasePart[];
11
+ }) => Map<string, SoundHandle> | undefined;
9
12
  stopCategory: <C extends keyof T>(name: C) => void;
10
13
  stopAllCategories: () => void;
11
14
  setCategoryVolume: <C extends keyof T>(category: C, volume: number) => void;
@@ -1,4 +1,6 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local createSpatialHandle = TS.import(script, script.Parent, "createSpatialHandle").createSpatialHandle
2
4
  --[[
3
5
  *
4
6
  * Create a sound category Registry
@@ -6,6 +8,7 @@
6
8
 
7
9
  ]]
8
10
  local function createSoundCategoryRegistry(definitions)
11
+ local spatialHandles = {}
9
12
  local ReplicatedStorage = game:GetService("ReplicatedStorage")
10
13
  local folder = ReplicatedStorage:FindFirstChild("Sounds")
11
14
  if not folder then
@@ -53,31 +56,27 @@ local function createSoundCategoryRegistry(definitions)
53
56
  * @param name Sound Category
54
57
 
55
58
  ]]
56
- local function playCategory(name)
59
+ local function playCategory(name, spatial)
57
60
  loadCategory(name)
58
61
  local config = definitions[name]
59
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
60
- local soundsFolder = ReplicatedStorage:FindFirstChild("Sounds")
61
- if not soundsFolder then
62
- return nil
63
- end
64
- local categoryFolder = soundsFolder:FindFirstChild(config.category)
62
+ local categoryFolder = folder:FindFirstChild(config.category)
65
63
  if not categoryFolder then
66
64
  return nil
67
65
  end
68
- for sound in pairs(config.sounds) do
69
- local _sound = categoryFolder:FindFirstChild(sound)
70
- if not _sound then
66
+ for _, sound in categoryFolder:GetChildren() do
67
+ if not sound:IsA("Sound") then
71
68
  continue
72
69
  end
73
- local _result = _sound
74
- if _result ~= nil then
75
- _result = _result:IsA("Sound")
76
- end
77
- if _result then
78
- _sound:Play()
70
+ if spatial and #spatial.emitters > 0 then
71
+ local handle = createSpatialHandle(sound.SoundId, spatial.emitters, sound.Volume)
72
+ local _name = sound.Name
73
+ spatialHandles[_name] = handle
74
+ handle:play()
75
+ else
76
+ sound:Play()
79
77
  end
80
78
  end
79
+ return spatialHandles
81
80
  end
82
81
  --[[
83
82
  *
@@ -1,21 +1,31 @@
1
- import { SoundOptions } from "./options";
1
+ import { SoundHandle, SoundOptions } from "./options";
2
2
  /**
3
3
  * Create a sound Registry
4
4
  * @param definitions Define the Sounds
5
5
  */
6
6
  export declare function createSoundRegistry<T extends Record<string, SoundOptions>>(definitions: T): {
7
- play: (name: keyof T) => void;
8
- stop: (name: keyof T) => void;
7
+ play: (name: keyof T, spatial?: {
8
+ emitters: BasePart[];
9
+ }) => SoundHandle | undefined;
10
+ stop: (name: keyof T, spatial?: {
11
+ emitters: BasePart[];
12
+ }) => void;
9
13
  preloadAll: () => void;
10
14
  load: (name: keyof T) => void;
11
- fadeIn: (soundName: keyof T, duration: number, volume: number) => void;
12
- fadeOut: (soundName: keyof T, duration: number, targetVolume?: number) => void;
15
+ fadeIn: (soundName: keyof T, duration: number, volume: number, spatial?: {
16
+ emitters: BasePart[];
17
+ }) => void;
18
+ fadeOut: (soundName: keyof T, duration: number, targetVolume?: number, spatial?: {
19
+ emitters: BasePart[];
20
+ }) => void;
13
21
  reset: (sound: keyof T) => void;
14
22
  setTimePosition: (sound: keyof T, timePosition: number) => void;
15
23
  stopAll: (reset?: true) => void;
16
24
  preload: (sound: keyof T) => void;
17
25
  setGlobalVolume: (volume: number) => void;
18
- setVolume: (sound: keyof T, volume: number) => void;
26
+ setVolume: (sound: keyof T, volume: number, spatial?: {
27
+ emitters: BasePart[];
28
+ }) => void;
19
29
  resetAll: (sound: keyof T) => void;
20
30
  onEnd: (sound: keyof T, callback: () => void) => void;
21
31
  isPlaying: (sound: keyof T) => boolean;
@@ -1,4 +1,6 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local createSpatialHandle = TS.import(script, script.Parent, "createSpatialHandle").createSpatialHandle
2
4
  --[[
3
5
  *
4
6
  * Create a sound Registry
@@ -6,6 +8,7 @@
6
8
 
7
9
  ]]
8
10
  local function createSoundRegistry(definitions)
11
+ local spatialHandles = {}
9
12
  local ReplicatedStorage = game:GetService("ReplicatedStorage")
10
13
  local folder = ReplicatedStorage:FindFirstChild("Sounds")
11
14
  if not folder then
@@ -43,28 +46,58 @@ local function createSoundRegistry(definitions)
43
46
  *
44
47
  * Plays a Sound
45
48
  * @param name Define which Sound should be played
49
+ * @param spatial Array of Baseparts
46
50
 
47
51
  ]]
48
- local function play(name)
49
- load(name)
50
- local sound = folder:FindFirstChild(name)
51
- local _result = sound
52
- if _result ~= nil then
53
- _result:Play()
52
+ local function play(name, spatial)
53
+ local config = definitions[name]
54
+ if not spatial or not spatial.emitters then
55
+ load(name)
56
+ local sound = folder:FindFirstChild(name)
57
+ local _result = sound
58
+ if _result ~= nil then
59
+ _result:Play()
60
+ end
61
+ return nil
62
+ else
63
+ local emittersArray = spatial.emitters
64
+ local _exp = config.id
65
+ local _condition = config.volume
66
+ if _condition == nil then
67
+ _condition = 1
68
+ end
69
+ local handle = createSpatialHandle(_exp, emittersArray, _condition)
70
+ local _name = name
71
+ spatialHandles[_name] = handle
72
+ handle:play()
73
+ return handle
54
74
  end
55
75
  end
56
76
  --[[
57
77
  *
58
78
  * Stops a Sound
59
79
  * @param name Define which Sound should be stopped
80
+ * @param spatial Array of Baseparts
60
81
 
61
82
  ]]
62
- local function stop(name)
63
- local sound = folder:FindFirstChild(name)
64
- local _result = sound
65
- if _result ~= nil then
66
- _result:Stop()
83
+ local function stop(name, spatial)
84
+ if not spatial then
85
+ local sound = folder:FindFirstChild(name)
86
+ local _result = sound
87
+ if _result ~= nil then
88
+ _result:Stop()
89
+ end
90
+ return nil
91
+ end
92
+ local _name = name
93
+ local handle = spatialHandles[_name]
94
+ if not handle then
95
+ return nil
67
96
  end
97
+ handle:stop()
98
+ handle:destroy()
99
+ local _name_1 = name
100
+ spatialHandles[_name_1] = nil
68
101
  end
69
102
  --[[
70
103
  *
@@ -82,22 +115,44 @@ local function createSoundRegistry(definitions)
82
115
  * @param soundName Sound Instance
83
116
  * @param duration Time in Seconds
84
117
  * @param volume Volume
118
+ * @param spatial Array of Baseparts
85
119
 
86
120
  ]]
87
- local function fadeIn(soundName, duration, volume)
88
- local sound = folder:FindFirstChild(soundName)
89
- sound.Volume = 0
90
- sound:Play()
91
- local step = 0.05
92
- local interval = duration * step
93
- task.spawn(function()
94
- local vol = 0
95
- while vol < volume do
96
- vol += step
97
- sound.Volume = math.clamp(vol, 0, volume)
98
- task.wait(interval)
121
+ local function fadeIn(soundName, duration, volume, spatial)
122
+ local config = definitions[soundName]
123
+ if not spatial or not spatial.emitters then
124
+ local sound = folder:FindFirstChild(soundName)
125
+ sound.Volume = 0
126
+ sound:Play()
127
+ local step = 0.05
128
+ local interval = duration * step
129
+ task.spawn(function()
130
+ local vol = 0
131
+ while vol < volume do
132
+ vol += step
133
+ sound.Volume = math.clamp(vol, 0, volume)
134
+ task.wait(interval)
135
+ end
136
+ end)
137
+ else
138
+ local emittersArray = spatial.emitters
139
+ local _exp = config.id
140
+ local _condition = config.volume
141
+ if _condition == nil then
142
+ _condition = 1
99
143
  end
100
- end)
144
+ local handle = createSpatialHandle(_exp, emittersArray, _condition)
145
+ local _self = handle
146
+ local _result = _self.fadeIn
147
+ if _result ~= nil then
148
+ _result(_self, duration, volume)
149
+ end
150
+ if not config.loop == true then
151
+ handle:played(function()
152
+ handle:destroy()
153
+ end)
154
+ end
155
+ end
101
156
  end
102
157
  --[[
103
158
  *
@@ -105,33 +160,55 @@ local function createSoundRegistry(definitions)
105
160
  * @param soundName Sound name from Registry
106
161
  * @param duration Time in seconds
107
162
  * @param targetVolume Optional target volume (default 0)
163
+ * @param spatial Array of Baseparts
108
164
 
109
165
  ]]
110
- local function fadeOut(soundName, duration, targetVolume)
111
- local sound = folder:FindFirstChild(soundName)
112
- if not sound then
113
- return nil
114
- end
115
- local startVolume = sound.Volume
116
- local _condition = targetVolume
117
- if _condition == nil then
118
- _condition = 0
119
- end
120
- local endVolume = _condition
121
- local step = 0.05
122
- local interval = duration * step
123
- task.spawn(function()
124
- local vol = startVolume
125
- while vol > endVolume do
126
- vol = math.clamp(vol - step, endVolume, startVolume)
127
- sound.Volume = vol
128
- task.wait(interval)
166
+ local function fadeOut(soundName, duration, targetVolume, spatial)
167
+ local config = definitions[soundName]
168
+ if not spatial or not spatial.emitters then
169
+ local sound = folder:FindFirstChild(soundName)
170
+ if not sound then
171
+ return nil
172
+ end
173
+ local startVolume = sound.Volume
174
+ local _condition = targetVolume
175
+ if _condition == nil then
176
+ _condition = 0
177
+ end
178
+ local endVolume = _condition
179
+ local step = 0.05
180
+ local interval = duration * step
181
+ task.spawn(function()
182
+ local vol = startVolume
183
+ while vol > endVolume do
184
+ vol = math.clamp(vol - step, endVolume, startVolume)
185
+ sound.Volume = vol
186
+ task.wait(interval)
187
+ end
188
+ sound.Volume = endVolume
189
+ if endVolume == 0 then
190
+ sound:Stop()
191
+ end
192
+ end)
193
+ else
194
+ local emittersArray = spatial.emitters
195
+ local _exp = config.id
196
+ local _condition = config.volume
197
+ if _condition == nil then
198
+ _condition = 1
129
199
  end
130
- sound.Volume = endVolume
131
- if endVolume == 0 then
132
- sound:Stop()
200
+ local handle = createSpatialHandle(_exp, emittersArray, _condition)
201
+ local _self = handle
202
+ local _result = _self.fadeOut
203
+ if _result ~= nil then
204
+ _result(_self, duration)
133
205
  end
134
- end)
206
+ if not config.loop == true then
207
+ handle:played(function()
208
+ handle:destroy()
209
+ end)
210
+ end
211
+ end
135
212
  end
136
213
  --[[
137
214
  *
@@ -195,14 +272,21 @@ local function createSoundRegistry(definitions)
195
272
  * Set Sound Volume
196
273
  * @param sound Sound Instance
197
274
  * @param volume Sound Volume
275
+ * @param spatial Array of Baseparts
198
276
 
199
277
  ]]
200
- local function setVolume(sound, volume)
201
- local _sound = folder:FindFirstChild(sound)
202
- if not (sound ~= 0 and sound == sound and sound ~= "" and sound) then
203
- return nil
278
+ local function setVolume(sound, volume, spatial)
279
+ local config = definitions[sound]
280
+ if not spatial or spatial.emitters then
281
+ local _sound = folder:FindFirstChild(sound)
282
+ if not (sound ~= 0 and sound == sound and sound ~= "" and sound) then
283
+ return nil
284
+ end
285
+ _sound.Volume = volume
286
+ else
287
+ local emittersArray = spatial.emitters
288
+ local handle = createSpatialHandle(config.id, emittersArray, volume)
204
289
  end
205
- _sound.Volume = volume
206
290
  end
207
291
  --[[
208
292
  *
@@ -0,0 +1,7 @@
1
+ import { SoundHandle } from "./options";
2
+ /**
3
+ * Create a Spatial Handle
4
+ * @param assetId Asset ID
5
+ * @param emitters Emitter
6
+ */
7
+ export declare function createSpatialHandle(assetId: string, emitters: BasePart[], volume: number): SoundHandle;
@@ -0,0 +1,59 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _functions = TS.import(script, script.Parent.Parent, "utils", "functions")
4
+ local fadeIn = _functions.fadeIn
5
+ local fadeOut = _functions.fadeOut
6
+ --[[
7
+ *
8
+ * Create a Spatial Handle
9
+ * @param assetId Asset ID
10
+ * @param emitters Emitter
11
+
12
+ ]]
13
+ local function createSpatialHandle(assetId, emitters, volume)
14
+ local player = Instance.new("AudioPlayer")
15
+ player.Asset = assetId
16
+ player.Volume = volume
17
+ player.Parent = game:GetService("ReplicatedStorage")
18
+ local emitterInstances = {}
19
+ for _, part in emitters do
20
+ local emitter = Instance.new("AudioEmitter")
21
+ emitter.Parent = part
22
+ local wire = Instance.new("Wire")
23
+ wire.SourceInstance = player
24
+ wire.TargetInstance = emitter
25
+ wire.Parent = emitter
26
+ table.insert(emitterInstances, emitter)
27
+ end
28
+ return {
29
+ play = function(self)
30
+ player:Play()
31
+ end,
32
+ stop = function(self)
33
+ player:Stop()
34
+ end,
35
+ fadeIn = function(self, duration, volume)
36
+ fadeIn(player, volume, duration)
37
+ end,
38
+ fadeOut = function(self, duration)
39
+ fadeOut(player, duration)
40
+ end,
41
+ destroy = function(self)
42
+ player:Destroy()
43
+ -- β–Ό ReadonlyArray.forEach β–Ό
44
+ local _callback = function(e)
45
+ return e:Destroy()
46
+ end
47
+ for _k, _v in emitterInstances do
48
+ _callback(_v, _k - 1, emitterInstances)
49
+ end
50
+ -- β–² ReadonlyArray.forEach β–²
51
+ end,
52
+ played = function(self, callback)
53
+ player.Ended:Connect(callback)
54
+ end,
55
+ }
56
+ end
57
+ return {
58
+ createSpatialHandle = createSpatialHandle,
59
+ }
@@ -2,6 +2,18 @@ export interface SoundOptions {
2
2
  volume?: number;
3
3
  loop?: boolean;
4
4
  id: string;
5
+ spatial?: {
6
+ attenuation?: number;
7
+ directional?: boolean;
8
+ };
9
+ }
10
+ export interface SoundHandle {
11
+ play(): void;
12
+ stop(): void;
13
+ fadeIn?(duration: number, volume: number): void;
14
+ fadeOut?(duration: number): void;
15
+ destroy(): void;
16
+ played(callback: () => void): void;
5
17
  }
6
18
  interface SoundDefinition {
7
19
  id: string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fades in a Sound
3
+ * @param player AudioPlayer
4
+ * @param targetVolume Target volume
5
+ * @param duration Duration
6
+ */
7
+ export declare function fadeIn(player: AudioPlayer, targetVolume: number, duration: number): void;
8
+ /**
9
+ * Smoothly fades out a Sound
10
+ * @param player AudioPlayer
11
+ * @param duration Duration
12
+ */
13
+ export declare function fadeOut(player: AudioPlayer, duration: number): void;
@@ -0,0 +1,47 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --[[
3
+ *
4
+ * Fades in a Sound
5
+ * @param player AudioPlayer
6
+ * @param targetVolume Target volume
7
+ * @param duration Duration
8
+
9
+ ]]
10
+ local function fadeIn(player, targetVolume, duration)
11
+ player.Volume = 0
12
+ player:Play()
13
+ local steps = 20
14
+ task.spawn(function()
15
+ for i = 0, steps do
16
+ player.Volume = (i / steps) * targetVolume
17
+ task.wait(duration / steps)
18
+ end
19
+ end)
20
+ end
21
+ --[[
22
+ *
23
+ * Smoothly fades out a Sound
24
+ * @param player AudioPlayer
25
+ * @param duration Duration
26
+
27
+ ]]
28
+ local function fadeOut(player, duration)
29
+ local _condition = player.Volume
30
+ if _condition == nil then
31
+ _condition = 1
32
+ end
33
+ local startVolume = _condition
34
+ local steps = 20
35
+ local interval = duration / steps
36
+ task.spawn(function()
37
+ for i = steps, 0, -1 do
38
+ player.Volume = (i / steps) * startVolume
39
+ task.wait(interval)
40
+ end
41
+ player:Stop()
42
+ end)
43
+ end
44
+ return {
45
+ fadeIn = fadeIn,
46
+ fadeOut = fadeOut,
47
+ }
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@rbxts/sound-manager",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "A sound manager for Roblox-Typescript projects.",
5
5
  "main": "out/init.lua",
6
6
  "scripts": {
7
7
  "build": "rbxtsc",
8
8
  "watch": "rbxtsc -w",
9
- "prepublishOnly": "npm run build"
9
+ "prepublishOnly": "npm run build",
10
+ "start": "npm pack && npm run watch"
10
11
  },
11
12
  "keywords": [],
12
13
  "author": "Easy-Build-Studio",