1# Using SoundPool for Audio Playback 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/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 (playback rate, loop mode, and 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 let soundPool: media.SoundPool; 21 media.createSoundPool(5, audioRendererInfo).then((soundpool_: media.SoundPool) => { 22 if (soundpool_ != null) { 23 soundPool = soundpool_; 24 console.info('create SoundPool success'); 25 } else { 26 console.error('create SoundPool fail'); 27 } 28 }).catch((error) => { 29 console.error(`soundpool catchCallback, error message:${error.message}`); 30 }); 31 ``` 32 332. Call **load()** to load a sound. 34 35 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/js-apis-inner-multimedia-soundPool.md#load). 36 37 ```ts 38 let soundID: number; 39 await fs.open('/test_01.mp3', fs.OpenMode.READ_ONLY).then((file: fs.File) => { 40 console.info("file fd: " + file.fd); 41 uri = 'fd://' + (file.fd).toString() 42 }); // '/test_01.mp3' here is only an example. You need to pass in the actual URI. 43 soundPool.load(uri).then((soundId: number) => { 44 console.info('soundPool load uri success'); 45 soundID = soundId; 46 }).catch((err) => { 47 console.error('soundPool load failed and catch error is ' + err.message); 48 }); 49 ``` 50 513. Call **on('loadComplete')** to listen for the completion of sound loading. 52 53 ```ts 54 soundPool.on('loadComplete', (soundId_: number) => { 55 console.info('loadComplete, soundId: ' + soundId_); 56 }) 57 ``` 58 594. Call **on('playFinished')** to listen for the completion of sound playing. 60 61 ```ts 62 soundPool.on('playFinished', () => { 63 console.info("recive play finished message"); 64 }) 65 ``` 66 675. Call **on('error')** to listen for errors that may occur. 68 69 ```ts 70 soundPool.on('error', (error) => { 71 console.info('error happened,message is :' + error.message); 72 }) 73 ``` 74 756. 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. 76 77 ```ts 78 let soundID: number; 79 let streamID: number; 80 let PlayParameters: media.PlayParameters = { 81 loop: number = 0, // The sound does not loop. It is played once. 82 rate: AudioRendererRate = 2, // The sound is played at twice its original frequency. 83 leftVolume: number = 0.5, // range = 0.0-1.0 84 rightVolume: number = 0.5, // range = 0.0-1.0 85 priority: number = 0 // The sound playback has the lowest priority. 86 parallelPlayFlag: boolean = false // The sound is not played in parallel with other active audio streams. 87 } 88 soundPool.play(soundID, PlayParameters, (error, streamId: number) => { 89 if (error) { 90 console.info(`play sound Error: errCode is ${error.code}, errMessage is ${error.message}`) 91 } else { 92 streamID = streamId; 93 console.info('play success soundid:' + streamId); 94 } 95 }) 96 ``` 97 987. Call **setLoop()** to set the number of loops. 99 100 ```ts 101 let streamID: number; 102 soundPool.setLoop(streamID, 1).then(() => { 103 console.info('setLoop success streamID:' + streamID); 104 }).catch((err) => { 105 console.error('soundpool setLoop failed and catch error is ' + err.message); 106 }); 107 ``` 108 1098. Call **setPriority()** to set the playback priority. 110 111 ```ts 112 let streamID: number; 113 soundPool.setPriority(streamID, 1); 114 ``` 115 1169. Call **setRate()** to set the playback rate. 117 118 ```ts 119 let streamID: number; 120 let selectedAudioRendererRate: audio.AudioRendererRate = audio.AudioRendererRate.RENDER_RATE_NORMAL; // The sound is played at the original frequency. 121 // Call play() to obtain the stream ID. 122 123 soundPool.setRate(streamID, selectedAudioRendererRate).then(() => { 124 console.info('setRate success'); 125 }).catch((err) => { 126 console.error('soundpool setRate failed and catch error is ' + err.message); 127 }); 128 ``` 129 13010. Call **setVolume()** to set the playback volume. 131 132 ```ts 133 let streamID: number; 134 // Call play() to obtain the stream ID. 135 136 soundPool.setVolume(streamID, 0.5, 0.5).then(() => { 137 console.info('setVolume success'); 138 }).catch((err) => { 139 console.error('soundpool setVolume failed and catch error is ' + err.message); 140 }); 141 ``` 142 14311. Call **stop()** to stop the playback. 144 145 ```ts 146 let streamID: number; 147 // Call play() to obtain the stream ID. 148 149 soundPool.stop(streamID).then(() => { 150 console.info('stop success'); 151 }).catch((err) => { 152 console.error('soundpool load stop and catch error is ' + err.message); 153 }); 154 ``` 155 15612. Call **unload()** to unload a sound. 157 158 ```ts 159 let soundID: number; 160 // Call load() to obtain the sound ID. 161 162 soundPool.unload(soundID).then(() => { 163 console.info('unload success'); 164 }).catch((err) => { 165 console.error('soundpool unload failed and catch error is ' + err.message); 166 }); 167 ``` 168 16913. Call **off('loadComplete')** to stop listening for the completion of sound loading. 170 171 ```ts 172 soundPool.off('loadComplete'); 173 ``` 174 17514. Call **off('playFinished')** to stop listening for the completion of sound playing. 176 177 ```ts 178 soundPool.off('playFinished'); 179 ``` 180 18115. Call **off('error')** to stop listening for errors. 182 183 ```ts 184 soundPool.off('error'); 185 ``` 186 18716. Call **release()** to release the **SoundPool** instance. 188 189 ```ts 190 soundPool.release().then(() => { 191 console.info('release success'); 192 }).catch((err) => { 193 console.error('soundpool release failed and catch error is ' + err.message); 194 }); 195 ``` 196 197### Sample Code 198 199The following sample code implements low-latency playback using **SoundPool**. 200 201```ts 202 203import audio from '@ohos.multimedia.audio'; 204import media from '@ohos.multimedia.media'; 205import fs from '@ohos.file.fs' 206struct Soundpool { 207 private soundPool: media.SoundPool; 208 private streamId: number = 0; 209 private soundId: number = 0; 210 private audioRendererInfo: audio.AudioRendererInfo = { 211 content: audio.ContentType.CONTENT_TYPE_SPEECH, 212 usage: audio.StreamUsage.STREAM_USAGE_MEDIA, 213 rendererFlags: 1 214 } 215 private PlayParameters: media.PlayParameters = { 216 loop: number = 3, // The sound is played four times (three loops). 217 rate: audio.AudioRendererRate = audio.AudioRendererRate.RENDER_RATE_NORMAL, // The sound is played at the original frequency. 218 leftVolume: number = 0.5, // range = 0.0-1.0 219 rightVolume: number = 0.5, // range = 0.0-1.0 220 priority: number = 0 // The sound playback has the lowest priority. 221 parallelPlayFlag: boolean = false // The sound is not played in parallel with other active audio streams. 222 } 223 private uri: string = ""; 224 async create(): Promise<void> { 225 // Create a SoundPool instance. 226 this.soundPool = await media.createSoundPool(5, this.audioRendererInfo); 227 // Register listeners. 228 this.loadCallback(); 229 this.finishPlayCallback(); 230 this.setErrorCallback(); 231 // Load a sound. 232 await fs.open('/test_01.mp3', fs.OpenMode.READ_ONLY).then((file: fs.File) => { 233 console.info("file fd: " + file.fd); 234 uri = 'fd://' + (file.fd).toString() 235 }); // '/test_01.mp3' here is only an example. You need to pass in the actual URI. 236 this.soundId = await this.soundPool.load(this.uri); 237 } 238 async loadCallback(): Promise<void> { 239 // Callback invoked when the sound finishes loading. 240 this.soundPool.on('loadComplete', (soundId_: number) => { 241 console.info('loadComplete, soundId: ' + soundId_); 242 }) 243 } 244 // Set the listener when the sound finishes playing. 245 async finishPlayCallback(): Promise<void> { 246 // Callback invoked when the sound finishes playing. 247 this.soundPool.on('playFinished', () => { 248 console.info("recive play finished message"); 249 // The sound can be played again. 250 }) 251 } 252 // Set the listener for errors. 253 setErrorCallback(): void { 254 this.soundPool.on('error', (error) => { 255 console.info('error happened,message is :' + error.message); 256 }) 257 } 258 async PlaySoundPool(): Promise<void> { 259 // Start playback. PlayParameters can be carried in the play() API. 260 this.streamId = await this.soundPool.play(this.soundId); 261 // Set the number of loops. 262 this.soundPool.setLoop (this.streamId, 2); // The sound is played three times (two loops). 263 // Set the priority. 264 this.soundPool.setPriority(this.streamId, 1); 265 // Set the playback rate. 266 this.soundPool.setRate(this.streamId, audio.AudioRendererRate.RENDER_RATE_HALF); // The sound is played at half its original frequency. 267 // Set the volume. 268 this.soundPool.setVolume(this.streamId, 0.5, 0.5); 269 } 270 async release(): Promise<void> { 271 // Stop the playback of the stream. 272 this.soundPool.stop(this.streamId); 273 // Unload the sound. 274 await this.soundPool.unload(this.soundId); 275 // Unregister the listeners. 276 this.setOffCallback(); 277 // Release the SoundPool instance. 278 await this.soundPool.release(); 279 } 280 // Unregister the listeners. 281 setOffCallback() { 282 this.soundPool.off('loadComplete'); 283 this.soundPool.off('playFinished'); 284 this.soundPool.off('error'); 285 } 286} 287``` 288