react-native-audiosprites 0.4.1 → 0.5.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
@@ -27,6 +27,20 @@ audiosprite --output src/__tests__/sounds/mygameaudio --format howler --loop "bg
27
27
 
28
28
  This command will generate `mygameaudio.json`, `mygameaudio.mp3`, `mygameaudio.ogg`, `mygameaudio.m4a`, and `mygameaudio.ac3` in the `src/__tests__/sounds/` directory.
29
29
 
30
+ /**
31
+ * ⚠️ ANDROID RESOURCE CONFLICT FIX ⚠️
32
+ * * Android's build system (Gradle) generates resource IDs based on filenames WITHOUT extensions.
33
+ * If we generate "game_go_v2.mp3" and "game_go_v2.json", Android sees them both
34
+ * as the resource ID `R.raw.game_go_v2`, causing a "Duplicate resources" build error.
35
+ * * To fix this, make a script to automatically rename the generated JSON file to:
36
+ * `${outputFileName}_data.json`
37
+ * * Result:
38
+ * - game_go_v2.mp3 -> R.raw.game_go_v2
39
+ * - game_go_v2_data.json -> R.raw.game_go_v2_data
40
+ */
41
+
42
+ ![Example Demo](example_demo.png)
43
+
30
44
  ### Looping Sounds
31
45
 
32
46
  You can create looping sounds by using the `--loop` option with the `audiosprite` command. The value of the `--loop` option should be the name of the sound you want to loop.
@@ -41,6 +55,40 @@ When you play a looping sound, it will play continuously until you stop it using
41
55
 
42
56
  Then, you can use the `AudioSpritePlayer` to play the sounds from the sprite.
43
57
 
58
+ ### Type Safety for Native Audio Extensions
59
+
60
+ This library includes robust type definitions for `react-native-audio-api` extensions, such as `createBufferQueueSource`. These types are automatically generated and synchronized with the native audio library version `0.10.1`.
61
+
62
+ ### Audio Routing and Volume Control (Mixer Graph)
63
+
64
+ The library features a mixer graph that allows you to control the volume of Sound Effects (SFX) and Music separately, as well as a global Master volume.
65
+
66
+ - `sfx`: Short sound effects (coins, jumps, UI). High priority.
67
+ - `music`: Background tracks. Lower priority.
68
+
69
+ You can specify the channel when playing a sound:
70
+
71
+ ```typescript
72
+ // Play on 'sfx' channel (default)
73
+ player.play('coin_sound');
74
+
75
+ // Play on 'music' channel
76
+ player.play('bg_music', { channel: 'music' });
77
+ ```
78
+
79
+ You can control the volume dynamically:
80
+
81
+ ```typescript
82
+ // Set Music Volume (0.0 to 1.0)
83
+ player.setMusicVolume(0.5);
84
+
85
+ // Set SFX Volume (0.0 to 1.0)
86
+ player.setSFXVolume(0.8);
87
+
88
+ // Set Master Volume (affects both)
89
+ player.volume = 1.0;
90
+ ```
91
+
44
92
  ### Browser Environment
45
93
 
46
94
  ```typescript
@@ -159,7 +207,12 @@ export default function App() {
159
207
  const playSound = (soundName: string) => {
160
208
  const player = playerRef.current;
161
209
  if (player && isLoaded) {
162
- player.play(soundName);
210
+ // Play on music channel
211
+ if (soundName === 'bg_loop') {
212
+ player.play(soundName, { channel: 'music' });
213
+ } else {
214
+ player.play(soundName);
215
+ }
163
216
  console.log(`Playing sound: ${soundName}`);
164
217
  } else {
165
218
  console.warn('Player not loaded yet.');
@@ -263,6 +316,315 @@ Made with [create-react-native-library](https://github.com/callstack/react-nativ
263
316
 
264
317
  # Translations
265
318
 
319
+ ## Telugu
320
+
321
+ ![react-native-audiosprites_poster](react-native-audiosprites_poster.jpg)
322
+
323
+ # react-native-audiosprites
324
+
325
+ 'audiosprite' టూల్ ద్వారా రూపొందించబడిన ఆడియో స్ప్రైట్‌ల కోసం ఒక యూనివర్సల్ ప్లేయర్.
326
+ ఒకే సమయంలో అనేక శబ్దాలను ప్లే చేయడానికి మద్దతు ఇస్తుంది!
327
+
328
+ ## ఇన్‌స్టాలేషన్
329
+
330
+ ```sh
331
+ npm install react-native-audiosprites
332
+ ```
333
+
334
+ ```sh
335
+ yarn add react-native-audiosprites
336
+ ```
337
+
338
+ ## వినియోగం
339
+
340
+ ముందుగా, మీరు `audiosprite` టూల్‌ను ఉపయోగించి ఆడియో స్ప్రైట్ మరియు JSON మానిఫెస్ట్ ఫైల్‌ను రూపొందించాలి.
341
+
342
+ మీరు [`audiosprite`](https://www.npmjs.com/package/audiosprite)ని గ్లోబల్‌గా ఇన్‌స్టాల్ చేశారని అనుకుందాం:
343
+
344
+ ```sh
345
+ audiosprite --output src/__tests__/sounds/mygameaudio --format howler --loop "bg_loop" src/__tests__/sounds/bg_loop.wav src/__tests__/sounds/Sound_1.m4a src/__tests__/sounds/Sound_2.m4a src/__tests__/sounds/Sound_3.m4a src/__tests__/sounds/Sound_4.m4a
346
+ ```
347
+
348
+ ఈ కమాండ్ `src/__tests__/sounds/` డైరెక్టరీలో `mygameaudio.json`, `mygameaudio.mp3`, `mygameaudio.ogg`, `mygameaudio.m4a`, మరియు `mygameaudio.ac3` ఫైళ్లను సృష్టిస్తుంది.
349
+
350
+ /**
351
+ * ⚠️ ANDROID వనరుల సంఘర్షణ పరిష్కారం ⚠️
352
+ * * Android బిల్డ్ సిస్టమ్ (Gradle) ఎక్స్‌టెన్షన్‌లు లేకుండా ఫైల్‌నేమ్‌ల ఆధారంగా వనరుల IDలను సృష్టిస్తుంది.
353
+ * ఒకవేళ మనం "game_go_v2.mp3" మరియు "game_go_v2.json"ను రూపొందిస్తే, Android రెండింటినీ
354
+ * `R.raw.game_go_v2` అనే ఒకే వనరు IDగా చూస్తుంది, దీనివల్ల "డూప్లికేట్ వనరులు" బిల్డ్ ఎర్రర్ వస్తుంది.
355
+ * * దీన్ని పరిష్కరించడానికి, రూపొందించిన JSON ఫైల్ పేరును ఈ విధంగా మార్చాలి:
356
+ * `${outputFileName}_data.json`
357
+ * * ఫలితం:
358
+ * - game_go_v2.mp3 -> R.raw.game_go_v2
359
+ * - game_go_v2_data.json -> R.raw.game_go_v2_data
360
+ */
361
+
362
+ ### లూపింగ్ సౌండ్స్ (Looping Sounds)
363
+
364
+ మీరు `audiosprite` కమాండ్‌తో `--loop` ఎంపికను ఉపయోగించి లూపింగ్ శబ్దాలను సృష్టించవచ్చు. `--loop` ఎంపిక యొక్క విలువ మీరు లూప్ చేయాలనుకుంటున్న శబ్దం పేరు అయి ఉండాలి.
365
+
366
+ ఉదాహరణకు, `bg_music` శబ్దాన్ని లూప్ చేయడానికి, మీరు ఈ కింది కమాండ్‌ను ఉపయోగిస్తారు:
367
+
368
+ ```sh
369
+ audiosprite --output audiosprite --format howler --loop "bg_music" --path ./src/__tests__/ Sound_1.m4a Sound_2.m4a Sound_3.m4a Sound_4.m4a bg_music.wav
370
+ ```
371
+
372
+ మీరు లూపింగ్ శబ్దాన్ని ప్లే చేసినప్పుడు, మీరు `player.stop()` పద్ధతిని ఉపయోగించి దాన్ని ఆపే వరకు అది నిరంతరాయంగా ప్లే అవుతూనే ఉంటుంది. వెబ్ మరియు మొబైల్ ప్లాట్‌ఫారమ్‌లలో లూపింగ్ ఫంక్షనాలిటీకి మద్దతు ఉంది.
373
+
374
+ తరువాత, మీరు స్ప్రైట్ నుండి శబ్దాలను ప్లే చేయడానికి `AudioSpritePlayer`ని ఉపయోగించవచ్చు.
375
+
376
+ ### ఆడియో రూటింగ్ మరియు వాల్యూమ్ నియంత్రణ (మిక్సర్ గ్రాఫ్)
377
+
378
+ ఈ లైబ్రరీ మిక్సర్ గ్రాఫ్ ఫీచర్‌ను కలిగి ఉంది, ఇది సౌండ్ ఎఫెక్ట్స్ (SFX) మరియు మ్యూజిక్ వాల్యూమ్‌లను విడివిడిగా, అలాగే గ్లోబల్ మాస్టర్ వాల్యూమ్‌ను నియంత్రించడానికి మిమ్మల్ని అనుమతిస్తుంది.
379
+
380
+ - `sfx`: చిన్న సౌండ్ ఎఫెక్ట్స్ (కాయిన్స్, జంప్స్, UI). అధిక ప్రాధాన్యత.
381
+ - `music`: నేపథ్య ట్రాక్‌లు (Background tracks). తక్కువ ప్రాధాన్యత.
382
+
383
+ శబ్దాన్ని ప్లే చేస్తున్నప్పుడు మీరు ఛానెల్‌ని పేర్కొనవచ్చు:
384
+
385
+ ```typescript
386
+ // 'sfx' ఛానెల్‌లో ప్లే చేయండి (డిఫాల్ట్)
387
+ player.play('coin_sound');
388
+
389
+ // 'music' ఛానెల్‌లో ప్లే చేయండి
390
+ player.play('bg_music', { channel: 'music' });
391
+ ```
392
+
393
+ మీరు వాల్యూమ్‌ను డైనమిక్‌గా నియంత్రించవచ్చు:
394
+
395
+ ```typescript
396
+ // మ్యూజిక్ వాల్యూమ్‌ను సెట్ చేయండి (0.0 నుండి 1.0)
397
+ player.setMusicVolume(0.5);
398
+
399
+ // SFX వాల్యూమ్‌ను సెట్ చేయండి (0.0 నుండి 1.0)
400
+ player.setSFXVolume(0.8);
401
+
402
+ // మాస్టర్ వాల్యూమ్‌ను సెట్ చేయండి (రెండింటినీ ప్రభావితం చేస్తుంది)
403
+ player.volume = 1.0;
404
+ ```
405
+
406
+ ### బ్రౌజర్ ఎన్విరాన్మెంట్ (Browser Environment)
407
+
408
+ ```typescript
409
+ import { AudioSpritePlayer } from 'react-native-audiosprites';
410
+
411
+ const player = new AudioSpritePlayer({
412
+ platform: 'web',
413
+ });
414
+
415
+ async function playSound(soundName: string) {
416
+ try {
417
+ // ఆడియో స్ప్రైట్ మానిఫెస్ట్ మరియు ఆడియో ఫైళ్లను లోడ్ చేయండి
418
+ // మీ audiosprite.json ఫైల్ పాత్‌ను సరిచూసుకోండి
419
+ await player.load('./src/__tests__/sounds/mygameaudio.json');
420
+ console.log('ఆడియో స్ప్రైట్ విజయవంతంగా లోడ్ అయింది.');
421
+
422
+ // స్ప్రైట్‌మ్యాప్ నుండి శబ్దాన్ని ప్లే చేయండి
423
+ player.play(soundName);
424
+ console.log(`శబ్దాన్ని ప్లే చేస్తోంది: ${soundName}`);
425
+ } catch (error) {
426
+ console.error('శబ్దాన్ని ప్లే చేయడంలో లోపం:', error);
427
+ }
428
+ }
429
+
430
+ function stopSound() {
431
+ player.stop();
432
+ console.log('లూపింగ్ శబ్దం ఆగిపోయింది.');
433
+ }
434
+
435
+ // వినియోగ ఉదాహరణ:
436
+ playSound('Sound_1');
437
+ // playSound('Sound_2');
438
+ // లూపింగ్ శబ్దాన్ని ఆపడానికి:
439
+ // stopSound();
440
+ ```
441
+
442
+ ### రియాక్ట్ నేటివ్ ఎన్విరాన్మెంట్ (React Native Environment)
443
+
444
+ రియాక్ట్ నేటివ్ కోసం, ఆడియో ప్లేబ్యాక్ మరియు అసెట్ లోడింగ్‌ను నిర్వహించడానికి మీకు `react-native-audio-api` మరియు `expo-asset` అవసరం.
445
+
446
+ ముందుగా, డిపెండెన్సీలను ఇన్‌స్టాల్ చేయండి:
447
+
448
+ ```sh
449
+ npm install react-native-audio-api expo-asset expo-file-system
450
+ # లేదా
451
+ yarn add react-native-audio-api expo-asset expo-file-system
452
+ ```
453
+
454
+ `react-native-audio-api` డాక్యుమెంటేషన్ ప్రకారం `metro.config.js`ని మార్చండి: https://docs.swmansion.com/react-native-audio-api/docs/fundamentals/getting-started
455
+
456
+ ```js
457
+ module.exports = wrapWithAudioAPIMetroConfig(config);
458
+ ```
459
+
460
+ తరువాత, మీరు దీన్ని మీ కాంపోనెంట్‌లో ఉపయోగించవచ్చు:
461
+
462
+ ```typescript
463
+ import { StyleSheet, View, Text, Platform, TouchableOpacity } from 'react-native';
464
+ import { AudioSpritePlayer } from 'react-native-audiosprites';
465
+ import { AudioManager, AudioContext } from 'react-native-audio-api';
466
+ import { useEffect, useState, useRef } from 'react';
467
+ import { Asset } from 'expo-asset';
468
+ import { fetch } from 'expo/fetch';
469
+ import manifest from '../assets/mygameaudio.json';
470
+
471
+ // ఆడియో అసెట్‌ను ఇంపోర్ట్ చేయండి
472
+ const audioAsset = require('../assets/mygameaudio.mp3');
473
+
474
+ export default function App() {
475
+ const [isLoaded, setIsLoaded] = useState(false);
476
+ const playerRef = useRef<AudioSpritePlayer | null>(null);
477
+
478
+ useEffect(() => {
479
+ const loadPlayer = async () => {
480
+ const asset = Asset.fromModule(audioAsset);
481
+ await asset.downloadAsync();
482
+ const audioUri = asset.localUri || asset.uri;
483
+
484
+ if (!audioUri) {
485
+ console.error('ఆడియో URIని పొందడంలో విఫలమైంది.');
486
+ return;
487
+ }
488
+
489
+ if (Platform.OS === 'ios') {
490
+ try {
491
+ await AudioManager.setAudioSessionOptions({
492
+ iosCategory: 'playback',
493
+ iosOptions: ['mixWithOthers'],
494
+ });
495
+ await AudioManager.setAudioSessionActivity(true);
496
+ } catch (e) {
497
+ console.error('AudioSession ఎంపికలను కాన్ఫిగర్ చేయడంలో విఫలమైంది:', e);
498
+ }
499
+ }
500
+
501
+ const audioContext = new AudioContext();
502
+ const audioPlayer = new AudioSpritePlayer({
503
+ audioContext,
504
+ fetch: fetch.bind(globalThis),
505
+ platform: Platform.OS,
506
+ });
507
+
508
+ try {
509
+ await audioPlayer.load(manifest, audioUri);
510
+ playerRef.current = audioPlayer;
511
+ setIsLoaded(true);
512
+ console.log('ఆడియో స్ప్రైట్ విజయవంతంగా లోడ్ అయింది.');
513
+ } catch (error) {
514
+ console.error('ఆడియో స్ప్రైట్‌ను లోడ్ చేయడంలో విఫలమైంది:', error);
515
+ }
516
+ };
517
+
518
+ loadPlayer();
519
+ }, []);
520
+
521
+ const playSound = (soundName: string) => {
522
+ const player = playerRef.current;
523
+ if (player && isLoaded) {
524
+ if (soundName === 'bg_loop') {
525
+ player.play(soundName, { channel: 'music' });
526
+ } else {
527
+ player.play(soundName);
528
+ }
529
+ console.log(`శబ్దాన్ని ప్లే చేస్తోంది: ${soundName}`);
530
+ } else {
531
+ console.warn('ప్లేయర్ ఇంకా లోడ్ కాలేదు.');
532
+ }
533
+ };
534
+
535
+ const stopBGM = () => {
536
+ const player = playerRef.current;
537
+ if (player) {
538
+ player.stop();
539
+ }
540
+ };
541
+
542
+ return (
543
+ <View style={styles.container}>
544
+ <Text>AudioSprite Player ఉదాహరణ</Text>
545
+ <TouchableOpacity
546
+ onPress={() => loadPlayer()}
547
+ style={styles.button}
548
+ disabled={!isLoaded}
549
+ >
550
+ <Text style={styles.buttonText}>ప్లేయర్‌ని లోడ్ చేయండి</Text>
551
+ </TouchableOpacity>
552
+ <TouchableOpacity
553
+ onPress={() => playSound('Sound_1')}
554
+ style={styles.button}
555
+ disabled={!isLoaded}
556
+ >
557
+ <Text style={styles.buttonText}>Sound 1 ప్లే చేయండి</Text>
558
+ </TouchableOpacity>
559
+ <TouchableOpacity
560
+ onPress={() => playSound('Sound_2')}
561
+ style={styles.button}
562
+ disabled={!isLoaded}
563
+ >
564
+ <Text style={styles.buttonText}>Sound 2 ప్లే చేయండి</Text>
565
+ </TouchableOpacity>
566
+ <TouchableOpacity
567
+ onPress={() => playSound('bg_loop')}
568
+ style={styles.button}
569
+ disabled={!isLoaded}
570
+ >
571
+ <Text style={styles.buttonText}>బ్యాక్‌గ్రౌండ్ లూప్‌ను ప్లే చేయండి</Text>
572
+ </TouchableOpacity>
573
+ <TouchableOpacity
574
+ onPress={stopBGM}
575
+ style={styles.button}
576
+ disabled={!isLoaded}
577
+ >
578
+ <Text style={styles.buttonText}>BGM ఆపు</Text>
579
+ </TouchableOpacity>
580
+ </View>
581
+ );
582
+ }
583
+
584
+ const styles = StyleSheet.create({
585
+ container: {
586
+ flex: 1,
587
+ alignItems: 'center',
588
+ justifyContent: 'center',
589
+ },
590
+ button: {
591
+ backgroundColor: '#DDDDDD',
592
+ padding: 10,
593
+ marginVertical: 5,
594
+ borderRadius: 5,
595
+ },
596
+ buttonText: {
597
+ color: '#000000',
598
+ textAlign: 'center',
599
+ },
600
+ });
601
+ ```
602
+
603
+ ## స్ఫూర్తి (Inspiration)
604
+
605
+ https://github.com/goldfire/howler.js
606
+ జనరేట్ చేయబడిన json new Howl({
607
+ sprite: {
608
+ key1: [offset, duration, (loop)]
609
+ },
610
+ }); తో కూడా పనిచేస్తుంది.
611
+
612
+ ## సహకారం (Contributing)
613
+
614
+ - [డెవలప్‌మెంట్ వర్క్‌ఫ్లో](CONTRIBUTING.md#development-workflow)
615
+ - [పుల్ రిక్వెస్ట్ పంపడం](CONTRIBUTING.md#sending-a-pull-request)
616
+ - [ప్రవర్తనా నియమావళి](CODE_OF_CONDUCT.md)
617
+
618
+ ## లైసెన్స్ (License)
619
+
620
+ MIT
621
+
622
+ ## క్రెడిట్స్ (Credits)
623
+
624
+ [Shaker, Woda, Conga, Bongo, Templeblock.wav](https://freesound.org/people/kwazi/sounds/34115/) by [kwazi](https://freesound.org/people/kwazi/) | లైసెన్స్: [అట్రిబ్యూషన్ 3.0](http://creativecommons.org/licenses/by/3.0/)
625
+
626
+ [create-react-native-library](https://github.com/callstack/react-native-builder-bob)తో తయారు చేయబడింది
627
+
266
628
  ## Spanish
267
629
 
268
630
  ![react-native-audiosprites_poster](react-native-audiosprites_poster.jpg)
@@ -294,6 +656,18 @@ audiosprite --output src/__tests__/sounds/mygameaudio --format howler --loop "bg
294
656
 
295
657
  Este comando generará `mygameaudio.json`, `mygameaudio.mp3`, `mygameaudio.ogg`, `mygameaudio.m4a` y `mygameaudio.ac3` en el directorio `src/__tests__/sounds/`.
296
658
 
659
+ /**
660
+ * ⚠️ SOLUCIÓN DE CONFLICTO DE RECURSOS DE ANDROID ⚠️
661
+ * * El sistema de compilación de Android (Gradle) genera ID de recursos basados en nombres de archivo SIN extensiones.
662
+ * Si generamos "game_go_v2.mp3" y "game_go_v2.json", Android los ve a ambos
663
+ * como el ID de recurso `R.raw.game_go_v2`, lo que causa un error de compilación de "Recursos duplicados".
664
+ * * Para solucionar esto, renombre el archivo JSON generado a:
665
+ * `${outputFileName}_data.json`
666
+ * * Resultado:
667
+ * - game_go_v2.mp3 -> R.raw.game_go_v2
668
+ * - game_go_v2_data.json -> R.raw.game_go_v2_data
669
+ */
670
+
297
671
  ### Sonidos en Bucle
298
672
 
299
673
  Puedes crear sonidos en bucle usando la opción `--loop` con el comando `audiosprite`. El valor de la opción `--loop` debe ser el nombre del sonido que deseas repetir.
@@ -426,7 +800,11 @@ export default function App() {
426
800
  const playSound = (soundName: string) => {
427
801
  const player = playerRef.current;
428
802
  if (player && isLoaded) {
429
- player.play(soundName);
803
+ if (soundName === 'bg_loop') {
804
+ player.play(soundName, { channel: 'music' });
805
+ } else {
806
+ player.play(soundName);
807
+ }
430
808
  console.log(`Reproduciendo sonido: ${soundName}`);
431
809
  } else {
432
810
  console.warn('El reproductor aún no se ha cargado.');
@@ -557,6 +935,18 @@ audiosprite --output src/__tests__/sounds/mygameaudio --format howler --loop "bg
557
935
 
558
936
  Эта команда создаст `mygameaudio.json`, `mygameaudio.mp3`, `mygameaudio.ogg`, `mygameaudio.m4a` и `mygameaudio.ac3` в каталоге `src/__tests__/sounds/`.
559
937
 
938
+ /**
939
+ * ⚠️ ИСПРАВЛЕНИЕ КОНФЛИКТА РЕСУРСОВ ANDROID ⚠️
940
+ * * Система сборки Android (Gradle) генерирует идентификаторы ресурсов на основе имен файлов БЕЗ расширений.
941
+ * Если мы сгенерируем "game_go_v2.mp3" и "game_go_v2.json", Android увидит их обоих
942
+ * как идентификатор ресурса `R.raw.game_go_v2`, что вызовет ошибку сборки "Дублирующиеся ресурсы".
943
+ * * Чтобы исправить это, переименуйте сгенерированный файл JSON в:
944
+ * `${outputFileName}_data.json`
945
+ * * Результат:
946
+ * - game_go_v2.mp3 -> R.raw.game_go_v2
947
+ * - game_go_v2_data.json -> R.raw.game_go_v2_data
948
+ */
949
+
560
950
  ### Зацикленные звуки
561
951
 
562
952
  Вы можете создавать зацикленные звуки, используя опцию `--loop` с командой `audiosprite`. Значением опции `--loop` должно быть имя звука, который вы хотите зациклить.
@@ -689,7 +1079,11 @@ export default function App() {
689
1079
  const playSound = (soundName: string) => {
690
1080
  const player = playerRef.current;
691
1081
  if (player && isLoaded) {
692
- player.play(soundName);
1082
+ if (soundName === 'bg_loop') {
1083
+ player.play(soundName, { channel: 'music' });
1084
+ } else {
1085
+ player.play(soundName);
1086
+ }
693
1087
  console.log(`Воспроизведение звука: ${soundName}`);
694
1088
  } else {
695
1089
  console.warn('Проигрыватель еще не загружен.');
@@ -820,6 +1214,18 @@ audiosprite --output src/__tests__/sounds/mygameaudio --format howler --loop "bg
820
1214
 
821
1215
  यह कमांड `src/__tests__/sounds/` डायरेक्टरी में `mygameaudio.json`, `mygameaudio.mp3`, `mygameaudio.ogg`, `mygameaudio.m4a`, और `mygameaudio.ac3` उत्पन्न करेगा।
822
1216
 
1217
+ /**
1218
+ * ⚠️ Android संसाधन संघर्ष सुधार ⚠️
1219
+ * * Android की बिल्ड सिस्टम (Gradle) फ़ाइल नामों के आधार पर संसाधन ID उत्पन्न करती है बिना एक्सटेंशन के।
1220
+ * यदि हम "game_go_v2.mp3" और "game_go_v2.json" उत्पन्न करते हैं, तो Android उन दोनों को
1221
+ * `R.raw.game_go_v2` संसाधन ID के रूप में देखता है, जिससे "डुप्लिकेट संसाधन" बिल्ड त्रुटि होती है।
1222
+ * * इसे ठीक करने के लिए, उत्पन्न JSON फ़ाइल का नाम बदलकर यह करें:
1223
+ * `${outputFileName}_data.json`
1224
+ * * परिणाम:
1225
+ * - game_go_v2.mp3 -> R.raw.game_go_v2
1226
+ * - game_go_v2_data.json -> R.raw.game_go_v2_data
1227
+ */
1228
+
823
1229
  ### लूपिंग ध्वनियाँ
824
1230
 
825
1231
  आप `audiosprite` कमांड के साथ `--loop` विकल्प का उपयोग करके लूपिंग ध्वनियाँ बना सकते हैं। `--loop` विकल्प का मान उस ध्वनि का नाम होना चाहिए जिसे आप लूप करना चाहते हैं।
@@ -952,7 +1358,11 @@ export default function App() {
952
1358
  const playSound = (soundName: string) => {
953
1359
  const player = playerRef.current;
954
1360
  if (player && isLoaded) {
955
- player.play(soundName);
1361
+ if (soundName === 'bg_loop') {
1362
+ player.play(soundName, { channel: 'music' });
1363
+ } else {
1364
+ player.play(soundName);
1365
+ }
956
1366
  console.log(`ध्वनि बज रही है: ${soundName}`);
957
1367
  } else {
958
1368
  console.warn('खिलाड़ी अभी तक लोड नहीं हुआ है।');
@@ -1083,6 +1493,18 @@ audiosprite --output src/__tests__/sounds/mygameaudio --format howler --loop "bg
1083
1493
 
1084
1494
  此命令将在 `src/__tests__/sounds/` 目录中生成 `mygameaudio.json`、`mygameaudio.mp3`、`mygameaudio.ogg`、`mygameaudio.m4a` 和 `mygameaudio.ac3`。
1085
1495
 
1496
+ /**
1497
+ * ⚠️ ANDROID 资源冲突修复 ⚠️
1498
+ * * Android 的构建系统 (Gradle) 基于不带扩展名的文件名生成资源 ID。
1499
+ * 如果我们生成 "game_go_v2.mp3" 和 "game_go_v2.json",Android 会将它们都视为
1500
+ * 资源 ID `R.raw.game_go_v2`,从而导致“重复资源”构建错误。
1501
+ * * 要修复此问题,请将生成的 JSON 文件重命名为:
1502
+ * `${outputFileName}_data.json`
1503
+ * * 结果:
1504
+ * - game_go_v2.mp3 -> R.raw.game_go_v2
1505
+ * - game_go_v2_data.json -> R.raw.game_go_v2_data
1506
+ */
1507
+
1086
1508
  ### 循环声音
1087
1509
 
1088
1510
  您可以使用 `audiosprite` 命令的 `--loop` 选项创建循环声音。`--loop` 选项的值应该是您想要循环的声音的名称。
@@ -1215,7 +1637,11 @@ export default function App() {
1215
1637
  const playSound = (soundName: string) => {
1216
1638
  const player = playerRef.current;
1217
1639
  if (player && isLoaded) {
1218
- player.play(soundName);
1640
+ if (soundName === 'bg_loop') {
1641
+ player.play(soundName, { channel: 'music' });
1642
+ } else {
1643
+ player.play(soundName);
1644
+ }
1219
1645
  console.log(`正在播放声音: ${soundName}`);
1220
1646
  } else {
1221
1647
  console.warn('播放器尚未加载。');
@@ -1313,4 +1739,4 @@ key1: [offset, duration, (loop)]
1313
1739
 
1314
1740
  [Shaker, Woda, Conga, Bongo, Templeblock.wav](https://freesound.org/people/kwazi/sounds/34115/) by [kwazi](https://freesound.org/people/kwazi/) | 执照: [署名 3.0](http://creativecommons.org/licenses/by/3.0/)
1315
1741
 
1316
- 使用 [create-react-native-library](https://github.com/callstack/react-native-builder-bob) 制作
1742
+ 使用 [create-react-native-library](https://github.com/callstack/react-native-builder-bob) 制作
@@ -5,6 +5,17 @@
5
5
  * Requires an AudioContext and fetch to be injected.
6
6
  * Uses AudioBufferQueueSourceNode and buffer splitting for mobile stability.
7
7
  */
8
+
9
+ /**
10
+ * Defines the available audio routing channels.
11
+ * - 'sfx': Short sound effects (coins, jumps, UI). High priority, usually usually non-looping.
12
+ * - 'music': Background tracks. Lower priority, usually looping, separate volume control.
13
+ */
14
+
15
+ /**
16
+ * Configuration options for playing a specific sound sprite.
17
+ */
18
+
8
19
  export class AudioSpritePlayer {
9
20
  // The full audio buffer
10
21
 
@@ -14,6 +25,8 @@ export class AudioSpritePlayer {
14
25
  sourcePool = []; // NEW: Pool for non-looping sources
15
26
  maxPoolSize = 5; // Adjust this based on testing (5 is a good start)
16
27
 
28
+ // NEW: The Mixer
29
+
17
30
  constructor({
18
31
  audioContext,
19
32
  fetch,
@@ -43,6 +56,20 @@ export class AudioSpritePlayer {
43
56
  // @ts-ignore
44
57
  this.audioContext = new AudioContext();
45
58
  }
59
+
60
+ // 1. Create Master Output
61
+ this.masterGain = this.audioContext.createGain();
62
+ this.masterGain.gain.value = 1.0;
63
+ this.masterGain.connect(this.audioContext.destination);
64
+
65
+ // 2. Create Channels
66
+ this.sfxGain = this.audioContext.createGain();
67
+ this.sfxGain.gain.value = 1.0;
68
+ this.sfxGain.connect(this.masterGain); // Connect to Master
69
+
70
+ this.musicGain = this.audioContext.createGain();
71
+ this.musicGain.gain.value = 1.0;
72
+ this.musicGain.connect(this.masterGain); // Connect to Master
46
73
  }
47
74
 
48
75
  /**
@@ -111,7 +138,7 @@ export class AudioSpritePlayer {
111
138
  if (this.platform === 'web') {
112
139
  // Web logic remains simple: always create a standard AudioBufferSourceNode
113
140
  const source = this.audioContext.createBufferSource();
114
- source.connect(this.audioContext.destination);
141
+ // source.connect(this.audioContext.destination);
115
142
  return source;
116
143
  }
117
144
 
@@ -129,7 +156,7 @@ export class AudioSpritePlayer {
129
156
  return null;
130
157
  }
131
158
  source = this.audioContext.createBufferQueueSource();
132
- source.connect(this.audioContext.destination);
159
+ // source.connect(this.audioContext.destination);
133
160
  // console.log('Created new source. Pool size:', this.sourcePool.length);
134
161
  } else {
135
162
  // If pool is full, we might have to block or fail.
@@ -213,7 +240,7 @@ export class AudioSpritePlayer {
213
240
  throw error; // Re-throw for user to catch
214
241
  }
215
242
  }
216
- play(soundName) {
243
+ play(soundName, options) {
217
244
  if (!this.audioBuffer || !this.manifest) {
218
245
  console.warn('Audio sprite not loaded. Call load() first.');
219
246
  return;
@@ -235,6 +262,15 @@ export class AudioSpritePlayer {
235
262
  console.warn(`Sound "${soundName}" has invalid duration.`);
236
263
  return;
237
264
  }
265
+
266
+ // 1. Determine Channel (Default to 'sfx')
267
+ const channel = options?.channel || 'sfx';
268
+ const targetNode = channel === 'music' ? this.musicGain : this.sfxGain;
269
+
270
+ // 2. Determine Loop (Options override Manifest)
271
+ // defined in your existing code as: const sound = this.manifest.sprite[soundName];
272
+ // const manifestLoop = sound[2];
273
+ const loop = options?.loop !== undefined ? options.loop : sound[2];
238
274
  let source;
239
275
  const spriteBuffer = this.spriteBufferCache[soundName];
240
276
 
@@ -248,12 +284,12 @@ export class AudioSpritePlayer {
248
284
  console.error('RNAS Error: createBufferQueueSource is not available on this native platform.');
249
285
  return;
250
286
  }
251
- const loop = sound[2];
252
287
  if (loop) {
253
288
  // Always use AudioBufferQueueSourceNode
254
289
  source = this.audioContext.createBufferQueueSource();
255
290
  source.enqueueBuffer(spriteBuffer);
256
- source.connect(this.audioContext.destination);
291
+ // source.connect(this.audioContext.destination);
292
+ source.connect(targetNode);
257
293
 
258
294
  // Manual looping using onEnded
259
295
  const loopHandler = () => {
@@ -277,6 +313,10 @@ export class AudioSpritePlayer {
277
313
  source = this._getOrCreateSourceNode();
278
314
  if (!source) return; // Dropped sound because pool was full
279
315
 
316
+ // Reconnect to the correct channel (since pooled nodes might have been connected elsewhere)
317
+ source.disconnect();
318
+ source.connect(targetNode);
319
+
280
320
  // Must re-enqueue the buffer since the source was reused
281
321
  source.enqueueBuffer(spriteBuffer);
282
322
 
@@ -291,8 +331,10 @@ export class AudioSpritePlayer {
291
331
  return;
292
332
  }
293
333
  source.buffer = spriteBuffer;
294
- source.connect(this.audioContext.destination);
295
- const loop = sound[2]; // audiosprite stores loop as the third element in the array
334
+ // source.connect(this.audioContext.destination);
335
+ source.connect(targetNode);
336
+
337
+ // const loop = sound[2]; // audiosprite stores loop as the third element in the array
296
338
  if (loop) {
297
339
  source.loop = true;
298
340
  source.loopStart = 0; // Relative to the spriteBuffer
@@ -336,5 +378,41 @@ export class AudioSpritePlayer {
336
378
  console.log('RNAS: No looping audio to stop.');
337
379
  }
338
380
  }
381
+
382
+ /**
383
+ * Sets the volume for background music only.
384
+ * @param value 0.0 to 1.0
385
+ */
386
+ setMusicVolume(value) {
387
+ if (this.musicGain) {
388
+ // secure against uninitialized context
389
+ this.musicGain.gain.setTargetAtTime(value, this.audioContext.currentTime, 0.02);
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Sets the volume for sound effects only.
395
+ * @param value 0.0 to 1.0
396
+ */
397
+ setSFXVolume(value) {
398
+ if (this.sfxGain) {
399
+ this.sfxGain.gain.setTargetAtTime(value, this.audioContext.currentTime, 0.02);
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Sets the Global Master Volume (affects both Music and SFX).
405
+ * @param value 0.0 to 1.0
406
+ */
407
+ set volume(value) {
408
+ if (this.masterGain) {
409
+ this.masterGain.gain.setTargetAtTime(value, this.audioContext.currentTime, 0.02);
410
+ }
411
+ }
412
+
413
+ // Master Volume getter
414
+ get volume() {
415
+ return this.masterGain?.gain?.value ?? 1.0;
416
+ }
339
417
  }
340
418
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"names":["AudioSpritePlayer","spriteBufferCache","loopingSource","sourcePool","maxPoolSize","constructor","audioContext","fetch","platform","AudioContext","Error","audioBuffer","manifest","createBufferSource","name","console","log","masterGain","createGain","gain","value","connect","destination","sfxGain","musicGain","_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","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","options","state","resume","catch","e","duration","channel","targetNode","loop","undefined","enqueueBuffer","loopHandler","start","stop","loopStart","loopEnd","getManifest","getAudioBuffer","setMusicVolume","setTargetAtTime","currentTime","setSFXVolume","volume"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -3,6 +3,28 @@
3
3
  * Requires an AudioContext and fetch to be injected.
4
4
  * Uses AudioBufferQueueSourceNode and buffer splitting for mobile stability.
5
5
  */
6
+ /**
7
+ * Defines the available audio routing channels.
8
+ * - 'sfx': Short sound effects (coins, jumps, UI). High priority, usually usually non-looping.
9
+ * - 'music': Background tracks. Lower priority, usually looping, separate volume control.
10
+ */
11
+ export type AudioChannel = 'sfx' | 'music';
12
+ /**
13
+ * Configuration options for playing a specific sound sprite.
14
+ */
15
+ export interface PlayOptions {
16
+ /**
17
+ * Specifies which mixer channel to route the audio through.
18
+ * Use 'music' for BGM to ensure it responds to music volume settings.
19
+ * @default 'sfx'
20
+ */
21
+ channel?: AudioChannel;
22
+ /**
23
+ * Force the sound to loop (or not), overriding the setting
24
+ * defined in the original audiosprite JSON manifest.
25
+ */
26
+ loop?: boolean;
27
+ }
6
28
  export declare class AudioSpritePlayer {
7
29
  audioContext: any | null;
8
30
  fetch: any | null;
@@ -13,6 +35,9 @@ export declare class AudioSpritePlayer {
13
35
  private loopingSource;
14
36
  private sourcePool;
15
37
  private maxPoolSize;
38
+ masterGain: any;
39
+ sfxGain: any;
40
+ musicGain: any;
16
41
  constructor({ audioContext, fetch, platform, }: {
17
42
  audioContext: any | null;
18
43
  fetch: any;
@@ -47,7 +72,7 @@ export declare class AudioSpritePlayer {
47
72
  */
48
73
  private _getOrCreateSourceNode;
49
74
  load(json: any, audio?: any): Promise<void>;
50
- play(soundName: string): void;
75
+ play(soundName: string, options?: PlayOptions): void;
51
76
  getManifest(): any;
52
77
  getAudioBuffer(): any;
53
78
  /**
@@ -55,5 +80,21 @@ export declare class AudioSpritePlayer {
55
80
  * If a looping sound is playing, it will be stopped immediately.
56
81
  */
57
82
  stop(): void;
83
+ /**
84
+ * Sets the volume for background music only.
85
+ * @param value 0.0 to 1.0
86
+ */
87
+ setMusicVolume(value: number): void;
88
+ /**
89
+ * Sets the volume for sound effects only.
90
+ * @param value 0.0 to 1.0
91
+ */
92
+ setSFXVolume(value: number): void;
93
+ /**
94
+ * Sets the Global Master Volume (affects both Music and SFX).
95
+ * @param value 0.0 to 1.0
96
+ */
97
+ set volume(value: number);
98
+ get volume(): number;
58
99
  }
59
100
  //# sourceMappingURL=index.d.ts.map
@@ -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;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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,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;IAGzB,UAAU,EAAE,GAAG,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,EAAE,GAAG,CAAC;gBAEV,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;IAgDD;;;;;;;;;;;;;;;;;;;;;;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,EAAE,OAAO,CAAC,EAAE,WAAW;IAoI7C,WAAW;IAIX,cAAc;IAId;;;OAGG;IACH,IAAI;IAUJ;;;OAGG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM;IAW5B;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM;IAU1B;;;OAGG;IACH,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAQvB;IAGD,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-audiosprites",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
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",
@@ -36,6 +36,8 @@
36
36
  "typecheck": "tsc",
37
37
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
38
38
  "clean": "del-cli lib",
39
+ "types:sync": "node scripts/generate-audio-types.mjs",
40
+ "prebuild": "npm run types:sync",
39
41
  "prepare": "bob build",
40
42
  "release:alpha": "release-it --preRelease=alpha",
41
43
  "release": "release-it --only-version",
@@ -81,11 +83,13 @@
81
83
  "@eslint/eslintrc": "^3.3.1",
82
84
  "@eslint/js": "^9.35.0",
83
85
  "@evilmartians/lefthook": "^1.12.3",
86
+ "@react-native-community/slider": "^5.1.1",
84
87
  "@react-native/babel-preset": "0.81.1",
85
88
  "@react-native/eslint-config": "^0.81.1",
86
89
  "@release-it/conventional-changelog": "^10.0.1",
87
90
  "@types/jest": "^29.5.14",
88
91
  "@types/react": "^19.1.12",
92
+ "arktype": "^2.1.29",
89
93
  "commitlint": "^19.8.1",
90
94
  "del-cli": "^6.0.0",
91
95
  "eslint": "^9.35.0",
@@ -95,9 +99,10 @@
95
99
  "prettier": "^3.6.2",
96
100
  "react": "19.1.0",
97
101
  "react-native": "0.81.5",
98
- "react-native-audio-api": "^0.9.3",
102
+ "react-native-audio-api": "0.10.1",
99
103
  "react-native-builder-bob": "^0.40.13",
100
104
  "release-it": "^19.0.4",
105
+ "ts-morph": "^27.0.2",
101
106
  "typescript": "^5.9.2"
102
107
  },
103
108
  "peerDependencies": {
package/src/index.tsx CHANGED
@@ -3,6 +3,32 @@
3
3
  * Requires an AudioContext and fetch to be injected.
4
4
  * Uses AudioBufferQueueSourceNode and buffer splitting for mobile stability.
5
5
  */
6
+
7
+ /**
8
+ * Defines the available audio routing channels.
9
+ * - 'sfx': Short sound effects (coins, jumps, UI). High priority, usually usually non-looping.
10
+ * - 'music': Background tracks. Lower priority, usually looping, separate volume control.
11
+ */
12
+ export type AudioChannel = 'sfx' | 'music';
13
+
14
+ /**
15
+ * Configuration options for playing a specific sound sprite.
16
+ */
17
+ export interface PlayOptions {
18
+ /**
19
+ * Specifies which mixer channel to route the audio through.
20
+ * Use 'music' for BGM to ensure it responds to music volume settings.
21
+ * @default 'sfx'
22
+ */
23
+ channel?: AudioChannel;
24
+
25
+ /**
26
+ * Force the sound to loop (or not), overriding the setting
27
+ * defined in the original audiosprite JSON manifest.
28
+ */
29
+ loop?: boolean;
30
+ }
31
+
6
32
  export class AudioSpritePlayer {
7
33
  audioContext: any | null;
8
34
  fetch: any | null;
@@ -15,6 +41,11 @@ export class AudioSpritePlayer {
15
41
  private sourcePool: any[] = []; // NEW: Pool for non-looping sources
16
42
  private maxPoolSize: number = 5; // Adjust this based on testing (5 is a good start)
17
43
 
44
+ // NEW: The Mixer
45
+ public masterGain: any;
46
+ public sfxGain: any;
47
+ public musicGain: any;
48
+
18
49
  constructor({
19
50
  audioContext,
20
51
  fetch,
@@ -55,6 +86,20 @@ export class AudioSpritePlayer {
55
86
  // @ts-ignore
56
87
  this.audioContext = new AudioContext();
57
88
  }
89
+
90
+ // 1. Create Master Output
91
+ this.masterGain = this.audioContext.createGain();
92
+ this.masterGain.gain.value = 1.0;
93
+ this.masterGain.connect(this.audioContext.destination);
94
+
95
+ // 2. Create Channels
96
+ this.sfxGain = this.audioContext.createGain();
97
+ this.sfxGain.gain.value = 1.0;
98
+ this.sfxGain.connect(this.masterGain); // Connect to Master
99
+
100
+ this.musicGain = this.audioContext.createGain();
101
+ this.musicGain.gain.value = 1.0;
102
+ this.musicGain.connect(this.masterGain); // Connect to Master
58
103
  }
59
104
 
60
105
  /**
@@ -133,7 +178,7 @@ export class AudioSpritePlayer {
133
178
  if (this.platform === 'web') {
134
179
  // Web logic remains simple: always create a standard AudioBufferSourceNode
135
180
  const source = this.audioContext.createBufferSource();
136
- source.connect(this.audioContext.destination);
181
+ // source.connect(this.audioContext.destination);
137
182
  return source;
138
183
  }
139
184
 
@@ -153,7 +198,7 @@ export class AudioSpritePlayer {
153
198
  return null;
154
199
  }
155
200
  source = this.audioContext.createBufferQueueSource();
156
- source.connect(this.audioContext.destination);
201
+ // source.connect(this.audioContext.destination);
157
202
  // console.log('Created new source. Pool size:', this.sourcePool.length);
158
203
  } else {
159
204
  // If pool is full, we might have to block or fail.
@@ -258,7 +303,7 @@ export class AudioSpritePlayer {
258
303
  }
259
304
  }
260
305
 
261
- play(soundName: string) {
306
+ play(soundName: string, options?: PlayOptions) {
262
307
  if (!this.audioBuffer || !this.manifest) {
263
308
  console.warn('Audio sprite not loaded. Call load() first.');
264
309
  return;
@@ -283,6 +328,15 @@ export class AudioSpritePlayer {
283
328
  return;
284
329
  }
285
330
 
331
+ // 1. Determine Channel (Default to 'sfx')
332
+ const channel = options?.channel || 'sfx';
333
+ const targetNode = channel === 'music' ? this.musicGain : this.sfxGain;
334
+
335
+ // 2. Determine Loop (Options override Manifest)
336
+ // defined in your existing code as: const sound = this.manifest.sprite[soundName];
337
+ // const manifestLoop = sound[2];
338
+ const loop = options?.loop !== undefined ? options.loop : sound[2];
339
+
286
340
  let source: any;
287
341
  const spriteBuffer = this.spriteBufferCache[soundName];
288
342
 
@@ -302,13 +356,12 @@ export class AudioSpritePlayer {
302
356
  return;
303
357
  }
304
358
 
305
- const loop = sound[2];
306
-
307
359
  if (loop) {
308
360
  // Always use AudioBufferQueueSourceNode
309
361
  source = this.audioContext.createBufferQueueSource();
310
362
  source.enqueueBuffer(spriteBuffer);
311
- source.connect(this.audioContext.destination);
363
+ // source.connect(this.audioContext.destination);
364
+ source.connect(targetNode);
312
365
 
313
366
  // Manual looping using onEnded
314
367
  const loopHandler = () => {
@@ -332,6 +385,10 @@ export class AudioSpritePlayer {
332
385
  source = this._getOrCreateSourceNode();
333
386
  if (!source) return; // Dropped sound because pool was full
334
387
 
388
+ // Reconnect to the correct channel (since pooled nodes might have been connected elsewhere)
389
+ source.disconnect();
390
+ source.connect(targetNode);
391
+
335
392
  // Must re-enqueue the buffer since the source was reused
336
393
  source.enqueueBuffer(spriteBuffer);
337
394
 
@@ -350,9 +407,10 @@ export class AudioSpritePlayer {
350
407
  }
351
408
 
352
409
  source.buffer = spriteBuffer;
353
- source.connect(this.audioContext.destination);
410
+ // source.connect(this.audioContext.destination);
411
+ source.connect(targetNode);
354
412
 
355
- const loop = sound[2]; // audiosprite stores loop as the third element in the array
413
+ // const loop = sound[2]; // audiosprite stores loop as the third element in the array
356
414
  if (loop) {
357
415
  source.loop = true;
358
416
  source.loopStart = 0; // Relative to the spriteBuffer
@@ -398,4 +456,52 @@ export class AudioSpritePlayer {
398
456
  console.log('RNAS: No looping audio to stop.');
399
457
  }
400
458
  }
459
+
460
+ /**
461
+ * Sets the volume for background music only.
462
+ * @param value 0.0 to 1.0
463
+ */
464
+ setMusicVolume(value: number) {
465
+ if (this.musicGain) {
466
+ // secure against uninitialized context
467
+ this.musicGain.gain.setTargetAtTime(
468
+ value,
469
+ this.audioContext.currentTime,
470
+ 0.02
471
+ );
472
+ }
473
+ }
474
+
475
+ /**
476
+ * Sets the volume for sound effects only.
477
+ * @param value 0.0 to 1.0
478
+ */
479
+ setSFXVolume(value: number) {
480
+ if (this.sfxGain) {
481
+ this.sfxGain.gain.setTargetAtTime(
482
+ value,
483
+ this.audioContext.currentTime,
484
+ 0.02
485
+ );
486
+ }
487
+ }
488
+
489
+ /**
490
+ * Sets the Global Master Volume (affects both Music and SFX).
491
+ * @param value 0.0 to 1.0
492
+ */
493
+ set volume(value: number) {
494
+ if (this.masterGain) {
495
+ this.masterGain.gain.setTargetAtTime(
496
+ value,
497
+ this.audioContext.currentTime,
498
+ 0.02
499
+ );
500
+ }
501
+ }
502
+
503
+ // Master Volume getter
504
+ get volume(): number {
505
+ return this.masterGain?.gain?.value ?? 1.0;
506
+ }
401
507
  }