• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using SoundPool for Audio Playback (ArkTS)
2
3The **SoundPool** class provides APIs to implement low-latency playback of short sounds.
4
5Short sound effects (such as the camera shutter sound effect and system notification sound effect) are often required during application development. You can call the APIs provided by **SoundPool** to implement one-time loading of short sounds and multiple times of low-latency playback.
6
7Currently, the **SoundPool** APIs can be used to play an audio file that is less than 1 MB. If the size of an audio file exceeds 1 MB, 1 MB data is captured and played.
8
9This topic walks you through on how to use the **SoundPool** APIs to implement low-latency playback. For details about the API, see [SoundPool](../reference/apis-media-kit/js-apis-inner-multimedia-soundPool.md).
10
11The full process includes creating a **SoundPool** instance, loading a sound (including decapsulation and decoding), setting playback parameters (loop mode, and playback priority), playing the sound, stopping the playback, and releasing the instance. (For details about the decoding formats, see [Audio Decoding](audio-decoding.md).)
12
13During application development, you must subscribe to playback state changes and call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur.
14
15## How to Develop
16
171. Call **createSoundPool()** to create a **SoundPool** instance.
18
19    ```ts
20    import media from '@ohos.multimedia.media';
21    import audio from '@ohos.multimedia.audio';
22    import { BusinessError } from '@ohos.base';
23
24    let soundPool: media.SoundPool;
25    let audioRendererInfo: audio.AudioRendererInfo = {
26      usage : audio.StreamUsage.STREAM_USAGE_MUSIC,
27      rendererFlags : 0
28    }
29
30    media.createSoundPool(5, audioRendererInfo).then((soundpool_: media.SoundPool) => {
31      if (soundpool_ != null) {
32        soundPool = soundpool_;
33        console.info('create SoundPool success');
34      } else {
35        console.error('create SoundPool fail');
36      }
37    }).catch((error: BusinessError) => {
38      console.error(`soundpool catchCallback, error message:${error.message}`);
39    });
40    ```
41
422. Call **load()** to load a sound.
43    You can pass in a URI or an FD to load the sound. The following uses the URI as an example. For more methods, see [SoundPool](../reference/apis-media-kit/js-apis-inner-multimedia-soundPool.md#load).
44
45    ```ts
46    import { BusinessError } from '@ohos.base';
47    import fs from '@ohos.file.fs';
48
49    let soundID: number;
50    let uri: string;
51    async function load() {
52      await fs.open('/test_01.mp3', fs.OpenMode.READ_ONLY).then((file: fs.File) => {
53        console.info("file fd: " + file.fd);
54        uri = 'fd://' + (file.fd).toString()
55      }); // '/test_01.mp3' here is only an example. You need to pass in the actual URI.
56      soundPool.load(uri).then((soundId: number) => {
57        console.info('soundPool load uri success');
58        soundID = soundId;
59      }).catch((err: BusinessError) => {
60        console.error('soundPool load failed and catch error is ' + err.message);
61      })
62    }
63    ```
64
653. Call **on('loadComplete')** to listen for the completion of sound loading.
66
67    ```ts
68    soundPool.on('loadComplete', (soundId: number) => {
69      console.info('loadComplete, soundId: ' + soundId);
70    });
71    ```
72
734. Call **on('playFinished')** to listen for the completion of sound playing.
74
75    ```ts
76    soundPool.on('playFinished', () => {
77      console.info("receive play finished message");
78    });
79    ```
80
815. Call **on('error')** to listen for errors that may occur.
82
83    ```ts
84    soundPool.on('error', (error) => {
85      console.info('error happened,message is :' + error.message);
86    });
87    ```
88
896. Set the playback parameters and call **play()** to play the sound. If **play()** with the same sound ID passed in is called for multiple times, the sound is played only once.
90
91    ```ts
92    let soundID: number;
93    let streamID: number;
94    let playParameters: media.PlayParameters = {
95        loop: 0, // The sound does not loop. It is played once.
96        rate: 2, // The sound is played at twice its original frequency.
97        leftVolume: 0.5, // range = 0.0-1.0
98        rightVolume: 0.5, // range = 0.0-1.0
99        priority: 0, // The sound playback has the lowest priority.
100      }
101    soundPool.play(soundID, playParameters, (error, streamId: number) => {
102      if (error) {
103        console.info(`play sound Error: errCode is ${error.code}, errMessage is ${error.message}`)
104      } else {
105        streamID = streamId;
106        console.info('play success soundid:' + streamId);
107      }
108    });
109    ```
110
1117. Call **setLoop()** to set the number of loops.
112
113    ```ts
114    import { BusinessError } from '@ohos.base';
115
116    let streamID: number;
117    soundPool.setLoop(streamID, 1).then(() => {
118      console.info('setLoop success streamID:' + streamID);
119    }).catch((err: BusinessError) => {
120      console.error('soundpool setLoop failed and catch error is ' + err.message);
121    });
122    ```
123
1248. Call **setPriority()** to set the playback priority.
125
126    ```ts
127    let streamID: number;
128    soundPool.setPriority(streamID, 1);
129    ```
130
1319. Call **setVolume()** to set the playback volume.
132
133    ```ts
134    import { BusinessError } from '@ohos.base';
135
136    let streamID: number;
137    // Call play() to obtain the stream ID.
138
139    soundPool.setVolume(streamID, 0.5, 0.5).then(() => {
140      console.info('setVolume success');
141    }).catch((err: BusinessError) => {
142      console.error('soundpool setVolume failed and catch error is ' + err.message);
143    });
144    ```
145
14610. Call **stop()** to stop the playback.
147
148    ```ts
149    import { BusinessError } from '@ohos.base';
150
151    let streamID: number;
152    // Call play() to obtain the stream ID.
153
154    soundPool.stop(streamID).then(() => {
155      console.info('stop success');
156    }).catch((err: BusinessError) => {
157      console.error('soundpool load stop and catch error is ' + err.message);
158    });
159    ```
160
16111. Call **unload()** to unload a sound.
162
163    ```ts
164    import { BusinessError } from '@ohos.base';
165
166    let soundID: number;
167    // Call load() to obtain the sound ID.
168
169    soundPool.unload(soundID).then(() => {
170      console.info('unload success');
171    }).catch((err: BusinessError) => {
172      console.error('soundpool unload failed and catch error is ' + err.message);
173    });
174    ```
175
17612. Call **off('loadComplete')** to stop listening for the completion of sound loading.
177
178    ```ts
179    soundPool.off('loadComplete');
180    ```
181
18213. Call **off('playFinished')** to stop listening for the completion of sound playing.
183
184    ```ts
185    soundPool.off('playFinished');
186    ```
187
18814. Call **off('error')** to stop listening for errors.
189
190    ```ts
191    soundPool.off('error');
192    ```
193
19415. Call **release()** to release the **SoundPool** instance.
195
196    ```ts
197    import { BusinessError } from '@ohos.base';
198
199    soundPool.release().then(() => {
200      console.info('release success');
201    }).catch((err: BusinessError) => {
202      console.error('soundpool release failed and catch error is ' + err.message);
203    });
204    ```
205
206## Sample Code
207
208The following sample code implements low-latency playback using **SoundPool**.
209
210```ts
211import audio from '@ohos.multimedia.audio';
212import media from '@ohos.multimedia.media';
213import fs from '@ohos.file.fs'
214
215let soundPool: media.SoundPool;
216let streamId: number = 0;
217let soundId: number = 0;
218let audioRendererInfo: audio.AudioRendererInfo = {
219  usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
220  rendererFlags: 1
221}
222let PlayParameters: media.PlayParameters = {
223  loop: 3, // The sound is played four times (three loops).
224  rate: audio.AudioRendererRate.RENDER_RATE_NORMAL, // The sound is played at the original frequency.
225  leftVolume: 0.5, // range = 0.0-1.0
226  rightVolume: 0.5, // range = 0.0-1.0
227  priority: 0, // The sound playback has the lowest priority.
228}
229let uri: string = "";
230async function create() {
231  // Create a SoundPool instance.
232  soundPool = await media.createSoundPool(5, audioRendererInfo);
233  // Register listeners.
234  loadCallback();
235  finishPlayCallback();
236  setErrorCallback();
237  // Load a sound.
238  await fs.open('/test_01.mp3', fs.OpenMode.READ_ONLY).then((file: fs.File) => {
239    console.info("file fd: " + file.fd);
240    uri = 'fd://' + (file.fd).toString()
241  }); // '/test_01.mp3' here is only an example. You need to pass in the actual URI.
242  soundId = await soundPool.load(uri);
243}
244async function loadCallback() {
245  // Callback invoked when the sound finishes loading.
246  soundPool.on('loadComplete', (soundId_: number) => {
247    console.info('loadComplete, soundId: ' + soundId_);
248  })
249}
250// Set the listener when the sound finishes playing.
251async function finishPlayCallback() {
252  // Callback invoked when the sound finishes playing.
253  soundPool.on('playFinished', () => {
254    console.info("recive play finished message");
255    // The sound can be played again.
256  })
257}
258// Set the listener for errors.
259function setErrorCallback() {
260  soundPool.on('error', (error) => {
261    console.info('error happened,message is :' + error.message);
262  })
263}
264async function PlaySoundPool() {
265  // Start playback. PlayParameters can be carried in the play() API.
266  streamId = await soundPool.play(soundId);
267  // Set the number of loops.
268  soundPool.setLoop (streamId, 2); // The sound is played three times (two loops).
269  // Set the priority.
270  soundPool.setPriority(streamId, 1);
271  // Set the volume.
272  soundPool.setVolume(streamId, 0.5, 0.5);
273}
274async function release() {
275  // Stop the playback of the stream.
276  soundPool.stop(streamId);
277  // Unload the sound.
278  await soundPool.unload(soundId);
279  // Unregister the listeners.
280  setOffCallback();
281  // Release the SoundPool instance.
282  await soundPool.release();
283}
284// Unregister the listeners.
285function setOffCallback() {
286  soundPool.off('loadComplete');
287  soundPool.off('playFinished');
288  soundPool.off('error');
289}
290```
291