react-native-audiosprites 0.3.1 → 0.4.1
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 +1056 -0
- package/lib/module/index.js +75 -6
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.tsx +78 -6
package/lib/module/index.js
CHANGED
|
@@ -11,6 +11,9 @@ export class AudioSpritePlayer {
|
|
|
11
11
|
// Cache for the small, pre-split AudioBuffers used by mobile's QueueSourceNode
|
|
12
12
|
spriteBufferCache = {};
|
|
13
13
|
loopingSource = null;
|
|
14
|
+
sourcePool = []; // NEW: Pool for non-looping sources
|
|
15
|
+
maxPoolSize = 5; // Adjust this based on testing (5 is a good start)
|
|
16
|
+
|
|
14
17
|
constructor({
|
|
15
18
|
audioContext,
|
|
16
19
|
fetch,
|
|
@@ -67,7 +70,7 @@ export class AudioSpritePlayer {
|
|
|
67
70
|
*/
|
|
68
71
|
_cacheSpriteBuffers() {
|
|
69
72
|
if (!this.audioBuffer || !this.manifest) {
|
|
70
|
-
return;
|
|
73
|
+
return;
|
|
71
74
|
}
|
|
72
75
|
const sampleRate = this.audioBuffer.sampleRate;
|
|
73
76
|
const numChannels = this.audioBuffer.numberOfChannels;
|
|
@@ -100,6 +103,59 @@ export class AudioSpritePlayer {
|
|
|
100
103
|
// console.log(`Cached sprite buffer for ${soundName}, frames: ${durationFrames}`);
|
|
101
104
|
}
|
|
102
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Retrieves a source node from the pool or creates a new one if the pool is under capacity.
|
|
109
|
+
*/
|
|
110
|
+
_getOrCreateSourceNode() {
|
|
111
|
+
if (this.platform === 'web') {
|
|
112
|
+
// Web logic remains simple: always create a standard AudioBufferSourceNode
|
|
113
|
+
const source = this.audioContext.createBufferSource();
|
|
114
|
+
source.connect(this.audioContext.destination);
|
|
115
|
+
return source;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Mobile/QueueSourceNode logic
|
|
119
|
+
let source;
|
|
120
|
+
if (this.sourcePool.length > 0) {
|
|
121
|
+
source = this.sourcePool.pop(); // Reuse an available source
|
|
122
|
+
// Disconnect the previous onEnded handler if it had one
|
|
123
|
+
source.onEnded = null;
|
|
124
|
+
// console.log('Reusing source from pool. Pool size:', this.sourcePool.length);
|
|
125
|
+
} else if (this.sourcePool.length < this.maxPoolSize) {
|
|
126
|
+
// Create a new source if pool is not full
|
|
127
|
+
if (!this.audioContext.createBufferQueueSource) {
|
|
128
|
+
console.error('RNAS Error: createBufferQueueSource is not available. Cannot create pool.');
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
source = this.audioContext.createBufferQueueSource();
|
|
132
|
+
source.connect(this.audioContext.destination);
|
|
133
|
+
// console.log('Created new source. Pool size:', this.sourcePool.length);
|
|
134
|
+
} else {
|
|
135
|
+
// If pool is full, we might have to block or fail.
|
|
136
|
+
// For simplicity, we'll return null and warn, but a robust system
|
|
137
|
+
// might implement a "wait-and-retry" mechanism.
|
|
138
|
+
console.warn('RNAS Warning: Source pool is full. Dropping non-looping sound.');
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Define the cleanup/recycling function
|
|
143
|
+
const cleanupAndRecycle = () => {
|
|
144
|
+
// Only recycle if we are under maxPoolSize and it's not the looping source
|
|
145
|
+
if (this.sourcePool.length < this.maxPoolSize) {
|
|
146
|
+
this.sourcePool.push(source);
|
|
147
|
+
// console.log('Recycled source. Pool size:', this.sourcePool.length);
|
|
148
|
+
} else {
|
|
149
|
+
// If pool is full, let it be garbage collected
|
|
150
|
+
source.disconnect();
|
|
151
|
+
// console.log('Source disconnected (GC candidate).');
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Assign the cleanup function to run when the sound finishes playing
|
|
156
|
+
source.onEnded = cleanupAndRecycle;
|
|
157
|
+
return source;
|
|
158
|
+
}
|
|
103
159
|
async load(json, audio) {
|
|
104
160
|
try {
|
|
105
161
|
let decodedBuffer;
|
|
@@ -209,15 +265,23 @@ export class AudioSpritePlayer {
|
|
|
209
265
|
}
|
|
210
266
|
};
|
|
211
267
|
source.onEnded = loopHandler;
|
|
268
|
+
|
|
269
|
+
// Stop any currently playing looping source before starting a new one
|
|
270
|
+
if (this.loopingSource) {
|
|
271
|
+
this.loopingSource.stop();
|
|
272
|
+
}
|
|
212
273
|
source.start(0); // Start immediately
|
|
213
274
|
this.loopingSource = source; // Store reference to looping source
|
|
214
275
|
} else {
|
|
215
|
-
//
|
|
216
|
-
source = this.
|
|
276
|
+
// **NEW: USE POOL FOR NON-LOOPING MOBILE SOUNDS**
|
|
277
|
+
source = this._getOrCreateSourceNode();
|
|
278
|
+
if (!source) return; // Dropped sound because pool was full
|
|
279
|
+
|
|
280
|
+
// Must re-enqueue the buffer since the source was reused
|
|
217
281
|
source.enqueueBuffer(spriteBuffer);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
282
|
+
|
|
283
|
+
// Start immediately (start time 0 for BufferQueueSourceNode means "as soon as possible")
|
|
284
|
+
source.start(0);
|
|
221
285
|
}
|
|
222
286
|
} else {
|
|
223
287
|
// 🌐 WEB LOGIC (Standard Web Audio API)
|
|
@@ -233,6 +297,11 @@ export class AudioSpritePlayer {
|
|
|
233
297
|
source.loop = true;
|
|
234
298
|
source.loopStart = 0; // Relative to the spriteBuffer
|
|
235
299
|
source.loopEnd = sound[1] / 1000; // Duration of the spriteBuffer
|
|
300
|
+
|
|
301
|
+
// Stop any currently playing looping source before starting a new one
|
|
302
|
+
if (this.loopingSource) {
|
|
303
|
+
this.loopingSource.stop();
|
|
304
|
+
}
|
|
236
305
|
source.start(0); // Start immediately, no offset for the individual spriteBuffer
|
|
237
306
|
this.loopingSource = source; // Store reference to looping source
|
|
238
307
|
} else {
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AudioSpritePlayer","spriteBufferCache","loopingSource","constructor","audioContext","fetch","platform","AudioContext","Error","audioBuffer","manifest","createBufferSource","name","console","log","_cacheSpriteBuffers","sampleRate","numChannels","numberOfChannels","soundName","sprite","sound","startFrame","Math","floor","endFrame","ceil","durationFrames","warn","spriteBuffer","createBuffer","i","sourceData","getChannelData","destinationData","segment","subarray","set","load","json","audio","decodedBuffer","response","ok","statusText","urls","audioFileName","audioUrl","URL","url","href","audioResponse","arrayBuffer","decodeAudioData","typedArrayView","Uint8Array","buffer","
|
|
1
|
+
{"version":3,"names":["AudioSpritePlayer","spriteBufferCache","loopingSource","sourcePool","maxPoolSize","constructor","audioContext","fetch","platform","AudioContext","Error","audioBuffer","manifest","createBufferSource","name","console","log","_cacheSpriteBuffers","sampleRate","numChannels","numberOfChannels","soundName","sprite","sound","startFrame","Math","floor","endFrame","ceil","durationFrames","warn","spriteBuffer","createBuffer","i","sourceData","getChannelData","destinationData","segment","subarray","set","_getOrCreateSourceNode","source","connect","destination","length","pop","onEnded","createBufferQueueSource","error","cleanupAndRecycle","push","disconnect","load","json","audio","decodedBuffer","response","ok","statusText","urls","audioFileName","audioUrl","URL","url","href","audioResponse","arrayBuffer","decodeAudioData","typedArrayView","Uint8Array","buffer","play","state","resume","catch","e","duration","loop","enqueueBuffer","loopHandler","start","stop","loopStart","loopEnd","getManifest","getAudioBuffer"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -11,6 +11,8 @@ export declare class AudioSpritePlayer {
|
|
|
11
11
|
platform: string;
|
|
12
12
|
private spriteBufferCache;
|
|
13
13
|
private loopingSource;
|
|
14
|
+
private sourcePool;
|
|
15
|
+
private maxPoolSize;
|
|
14
16
|
constructor({ audioContext, fetch, platform, }: {
|
|
15
17
|
audioContext: any | null;
|
|
16
18
|
fetch: any;
|
|
@@ -40,6 +42,10 @@ export declare class AudioSpritePlayer {
|
|
|
40
42
|
* }
|
|
41
43
|
*/
|
|
42
44
|
private _cacheSpriteBuffers;
|
|
45
|
+
/**
|
|
46
|
+
* Retrieves a source node from the pool or creates a new one if the pool is under capacity.
|
|
47
|
+
*/
|
|
48
|
+
private _getOrCreateSourceNode;
|
|
43
49
|
load(json: any, audio?: any): Promise<void>;
|
|
44
50
|
play(soundName: string): void;
|
|
45
51
|
getManifest(): any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,YAAY,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,GAAG,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,aAAa,CAAoB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,YAAY,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,GAAG,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAa;gBAEpB,EACV,YAAY,EACZ,KAAK,EACL,QAAQ,GACT,EAAE;QACD,YAAY,EAAE,GAAG,GAAG,IAAI,CAAC;QACzB,KAAK,EAAE,GAAG,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;KAClB;IAkCD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,mBAAmB;IA8C3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAuDxB,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,GAAG;IA0EjC,IAAI,CAAC,SAAS,EAAE,MAAM;IAuHtB,WAAW;IAIX,cAAc;IAId;;;OAGG;IACH,IAAI;CASL"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audiosprites",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "audio sprites ",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "audio sprites for react native ios, android and web",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
7
7
|
"exports": {
|
package/src/index.tsx
CHANGED
|
@@ -12,6 +12,8 @@ export class AudioSpritePlayer {
|
|
|
12
12
|
// Cache for the small, pre-split AudioBuffers used by mobile's QueueSourceNode
|
|
13
13
|
private spriteBufferCache: Record<string, any> = {};
|
|
14
14
|
private loopingSource: any | null = null;
|
|
15
|
+
private sourcePool: any[] = []; // NEW: Pool for non-looping sources
|
|
16
|
+
private maxPoolSize: number = 5; // Adjust this based on testing (5 is a good start)
|
|
15
17
|
|
|
16
18
|
constructor({
|
|
17
19
|
audioContext,
|
|
@@ -80,7 +82,7 @@ export class AudioSpritePlayer {
|
|
|
80
82
|
*/
|
|
81
83
|
private _cacheSpriteBuffers() {
|
|
82
84
|
if (!this.audioBuffer || !this.manifest) {
|
|
83
|
-
return;
|
|
85
|
+
return;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
const sampleRate = this.audioBuffer.sampleRate;
|
|
@@ -124,6 +126,64 @@ export class AudioSpritePlayer {
|
|
|
124
126
|
}
|
|
125
127
|
}
|
|
126
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Retrieves a source node from the pool or creates a new one if the pool is under capacity.
|
|
131
|
+
*/
|
|
132
|
+
private _getOrCreateSourceNode(): any {
|
|
133
|
+
if (this.platform === 'web') {
|
|
134
|
+
// Web logic remains simple: always create a standard AudioBufferSourceNode
|
|
135
|
+
const source = this.audioContext.createBufferSource();
|
|
136
|
+
source.connect(this.audioContext.destination);
|
|
137
|
+
return source;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Mobile/QueueSourceNode logic
|
|
141
|
+
let source;
|
|
142
|
+
if (this.sourcePool.length > 0) {
|
|
143
|
+
source = this.sourcePool.pop(); // Reuse an available source
|
|
144
|
+
// Disconnect the previous onEnded handler if it had one
|
|
145
|
+
source.onEnded = null;
|
|
146
|
+
// console.log('Reusing source from pool. Pool size:', this.sourcePool.length);
|
|
147
|
+
} else if (this.sourcePool.length < this.maxPoolSize) {
|
|
148
|
+
// Create a new source if pool is not full
|
|
149
|
+
if (!this.audioContext.createBufferQueueSource) {
|
|
150
|
+
console.error(
|
|
151
|
+
'RNAS Error: createBufferQueueSource is not available. Cannot create pool.'
|
|
152
|
+
);
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
source = this.audioContext.createBufferQueueSource();
|
|
156
|
+
source.connect(this.audioContext.destination);
|
|
157
|
+
// console.log('Created new source. Pool size:', this.sourcePool.length);
|
|
158
|
+
} else {
|
|
159
|
+
// If pool is full, we might have to block or fail.
|
|
160
|
+
// For simplicity, we'll return null and warn, but a robust system
|
|
161
|
+
// might implement a "wait-and-retry" mechanism.
|
|
162
|
+
console.warn(
|
|
163
|
+
'RNAS Warning: Source pool is full. Dropping non-looping sound.'
|
|
164
|
+
);
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Define the cleanup/recycling function
|
|
169
|
+
const cleanupAndRecycle = () => {
|
|
170
|
+
// Only recycle if we are under maxPoolSize and it's not the looping source
|
|
171
|
+
if (this.sourcePool.length < this.maxPoolSize) {
|
|
172
|
+
this.sourcePool.push(source);
|
|
173
|
+
// console.log('Recycled source. Pool size:', this.sourcePool.length);
|
|
174
|
+
} else {
|
|
175
|
+
// If pool is full, let it be garbage collected
|
|
176
|
+
source.disconnect();
|
|
177
|
+
// console.log('Source disconnected (GC candidate).');
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Assign the cleanup function to run when the sound finishes playing
|
|
182
|
+
source.onEnded = cleanupAndRecycle;
|
|
183
|
+
|
|
184
|
+
return source;
|
|
185
|
+
}
|
|
186
|
+
|
|
127
187
|
async load(json: any, audio?: any) {
|
|
128
188
|
try {
|
|
129
189
|
let decodedBuffer: any;
|
|
@@ -261,15 +321,22 @@ export class AudioSpritePlayer {
|
|
|
261
321
|
};
|
|
262
322
|
source.onEnded = loopHandler;
|
|
263
323
|
|
|
324
|
+
// Stop any currently playing looping source before starting a new one
|
|
325
|
+
if (this.loopingSource) {
|
|
326
|
+
this.loopingSource.stop();
|
|
327
|
+
}
|
|
264
328
|
source.start(0); // Start immediately
|
|
265
329
|
this.loopingSource = source; // Store reference to looping source
|
|
266
330
|
} else {
|
|
267
|
-
//
|
|
268
|
-
source = this.
|
|
331
|
+
// **NEW: USE POOL FOR NON-LOOPING MOBILE SOUNDS**
|
|
332
|
+
source = this._getOrCreateSourceNode();
|
|
333
|
+
if (!source) return; // Dropped sound because pool was full
|
|
334
|
+
|
|
335
|
+
// Must re-enqueue the buffer since the source was reused
|
|
269
336
|
source.enqueueBuffer(spriteBuffer);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
337
|
+
|
|
338
|
+
// Start immediately (start time 0 for BufferQueueSourceNode means "as soon as possible")
|
|
339
|
+
source.start(0);
|
|
273
340
|
}
|
|
274
341
|
} else {
|
|
275
342
|
// 🌐 WEB LOGIC (Standard Web Audio API)
|
|
@@ -290,6 +357,11 @@ export class AudioSpritePlayer {
|
|
|
290
357
|
source.loop = true;
|
|
291
358
|
source.loopStart = 0; // Relative to the spriteBuffer
|
|
292
359
|
source.loopEnd = sound[1] / 1000; // Duration of the spriteBuffer
|
|
360
|
+
|
|
361
|
+
// Stop any currently playing looping source before starting a new one
|
|
362
|
+
if (this.loopingSource) {
|
|
363
|
+
this.loopingSource.stop();
|
|
364
|
+
}
|
|
293
365
|
source.start(0); // Start immediately, no offset for the individual spriteBuffer
|
|
294
366
|
this.loopingSource = source; // Store reference to looping source
|
|
295
367
|
} else {
|