一、SoundPool介绍
SoundPool 一般用来播放密集,急促而又短暂的音效。
SoundPool 对象可以看作是一个可以从 APK 中导入资源 或者从文件系统中载入文件的样本集合。
它利用 MediaPlayer 服务为音频解码为一个原始16位 PCM流。这个特性使得应用程序可以进行流压缩,而无须忍受在播放音频时解压所带来的 CPU 负载和延时。SoundPool 使用音效池的概念来管理多个播放流,如果超过流的最大数目, SoundPool 会基于优先级自动停止先前播放的流,另外,SoundPool 还支持自行设置声音的品质、 音量、 播放比率等参数。
在我们车机能想到的使用场景就是播放beep音和警告音等用户提示音。
二、SoundPool相关类
JAVA类
SoundPool
SoundPool是Android平台上的一个类,用于播放短时、急促、密集的提示音。它适用于需要快速播放音频的场景,比如支付收款的到账通知等。SoundPool支持异步初始化,可以导入本地音频文件并解码。但需要注意的是,如果资源未加载完全时播放,则可能会出现不完整的情况。SoundPool由java类和C++类。
JAVA类
SoundPool代码位于:
frameworks/base/media/java/android/media/SoundPool.java
SoundPool的定义:
public class SoundPool extends PlayerBase {
private final class EventHandler extends Handler {}
public static class Builder {}
}
PlayerBase
PlayerBase是一个Android平台的抽象类,是MediaPlayer和AudioTrack等音视频播放器的基类,提供了部分公共的属性和方法。PlayerBase中封装了播放器的状态以及状态转换的方法,同时提供了一个Handler用于处理内部的消息,保证了内部交互的同步性和可靠性。另外,PlayerBase中也提供了一些常用的变量。子类可以继承并实现PlayerBase的抽象方法,然后使用该类提供的状态的变化来实现相应的逻辑。
PlayerBase代码位于:
frameworks/base/media/java/android/media/PlayerBase.java
PlayerBase的定义:
public abstract class PlayerBase {}
AudioAttributes
AudioAttributes用于描述音频属性,如下为几种常见属性设置:
setAllowedCapturePolicy:设置允许捕获音频的策略
-
public static final int ALLOW_CAPTURE_BY_ALL = 1:Indicates that the audio may be captured by any app.
-
public static final int ALLOW_CAPTURE_BY_SYSTEM = 2:Indicates that the audio may only be captured by system apps.
-
public static final int ALLOW_CAPTURE_BY_NONE = 3:Indicates that the audio is not to be recorded by any app, even if it is a system app.
setContentType:设置内容类型
-
public final static int CONTENT_TYPE_UNKNOWN = 0:Content type value to use when the content type is unknown, or other than the ones defined.
-
public final static int CONTENT_TYPE_SPEECH = 1:Content type value to use when the content type is speech.
-
public final static int CONTENT_TYPE_MUSIC = 2:Content type value to use when the content type is music.
-
public final static int CONTENT_TYPE_MOVIE = 3:Content type value to use when the content type is a soundtrack, typically accompanying a movie or TV program Content type value to use when the content type is a soundtrack, typically accompanying a movie or TV program.
-
public final static int CONTENT_TYPE_SONIFICATION = 4:Content type value to use when the content type is a sound used to accompany a user action, such as a beep or sound effect expressing a key click, or event, such as the type of a sound for a bonus being received in a game. These sounds are mostly synthesized or short Foley sounds.
-
public static final int CONTENT_TYPE_ULTRASOUND = 1997:Content type value to use when the content type is ultrasound.
setFlags:
-
public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0:Flag defining a behavior where the audibility of the sound will be ensured by the system. To ensure sound audibility, the system only uses built-in speakers or wired headphones and specifically excludes wireless audio devices.
-
public final static int FLAG_SECURE = 0x1 << 1:Flag defining a behavior where the playback of the sound is ensured without degradation only when going to a secure sink.
-
public final static int FLAG_SCO = 0x1 << 2:Flag to enable when the stream is associated with SCO usage. Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
-
public final static int FLAG_BEACON = 0x1 << 3:Flag defining a behavior where the system ensures that the playback of the sound will be compatible with its use as a broadcast for surrounding people and/or devices. Ensures audibility with no or minimal post-processing applied.
-
public final static int FLAG_HW_AV_SYNC = 0x1 << 4:Flag requesting the use of an output stream supporting hardware A/V synchronization.
-
public final static int FLAG_HW_HOTWORD = 0x1 << 5:Flag requesting capture from the source used for hardware hotword detection. To be used with capture preset MediaRecorder.AudioSource.HOTWORD or MediaRecorder.AudioSource.VOICE_RECOGNITION.
-
public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6:Flag requesting audible playback even under limited interruptions.
-
public final static int FLAG_BYPASS_MUTE = 0x1 << 7:Flag requesting audible playback even when the underlying stream is muted.
-
public final static int FLAG_LOW_LATENCY = 0x1 << 8:Flag requesting a low latency path when creating an AudioTrack. When using this flag, the sample rate must match the native sample rate of the device. Effects processing is also unavailable.
-
public final static int FLAG_DEEP_BUFFER = 0x1 << 9:Flag requesting a deep buffer path when creating an {@code AudioTrack}. A deep buffer path, if available, may consume less power and is suitable for media playback where latency is not a concern.
-
public static final int FLAG_NO_MEDIA_PROJECTION = 0x1 << 10:Flag specifying that the audio shall not be captured by third-party apps with a MediaProjection.
-
public static final int FLAG_MUTE_HAPTIC = 0x1 << 11:Flag indicating force muting haptic channels. public static final int FLAG_NO_SYSTEM_CAPTURE = 0x1 << 12:Flag specifying that the audio shall not be captured by any apps, not even system apps.
-
public static final int FLAG_CAPTURE_PRIVATE = 0x1 << 13:Flag requesting private audio capture. When set in audio attributes passed to an AudioRecord, this prevents a privileged Assistant from capturing audio while this AudioRecord is active.
-
public static final int FLAG_CONTENT_SPATIALIZED = 0x1 << 14:Flag indicating the audio content has been processed to provide a virtual multichannel audio experience
-
public static final int FLAG_NEVER_SPATIALIZE = 0x1 << 15:Flag indicating the audio content is to never be spatialized
-
public static final int FLAG_CALL_REDIRECTION = 0x1 << 16:Flag indicating the audio is part of a call redirection. Valid for playback and capture.
setUsage:设置使用场景:
-
private static final int USAGE_INVALID = -1: Invalid value, only ever used for an uninitialized usage value
-
public final static int USAGE_UNKNOWN = 0:Usage value to use when the usage is unknown.
-
public final static int USAGE_MEDIA = 1:Usage value to use when the usage is media, such as music, or movie soundtracks.
-
public final static int USAGE_VOICE_COMMUNICATION = 2:Usage value to use when the usage is voice communications, such as telephony or VoIP.
-
public final static int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3:Usage value to use when the usage is in-call signalling, such as with a "busy" beep, or DTMF tones.
-
public final static int USAGE_ALARM = 4:Usage value to use when the usage is an alarm (e.g. wake-up alarm).
-
public final static int USAGE_NOTIFICATION = 5:Usage value to use when the usage is notification. See other notification usages for more specialized uses.
-
public final static int USAGE_NOTIFICATION_RINGTONE = 6:Usage value to use when the usage is telephony ringtone.
-
public final static int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7:Usage value to use when the usage is a request to enter/end a communication, such as a VoIP communication or video-conference.
-
public final static int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8:Usage value to use when the usage is notification for an "instant" communication such as a chat, or SMS.
-
public final static int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9:Usage value to use when the usage is notification for a non-immediate type of communication such as e-mail.
-
public final static int USAGE_NOTIFICATION_EVENT = 10:Usage value to use when the usage is to attract the user's attention, such as a reminder or low battery warning.
-
public final static int USAGE_ASSISTANCE_ACCESSIBILITY = 11:Usage value to use when the usage is for accessibility, such as with a screen reader.
-
public final static int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12:Usage value to use when the usage is driving or navigation directions.
-
public final static int USAGE_ASSISTANCE_SONIFICATION = 13:Usage value to use when the usage is sonification, such as with user interface sounds.
-
public final static int USAGE_GAME = 14:Usage value to use when the usage is for game audio.
-
public final static int USAGE_VIRTUAL_SOURCE = 15:Usage value to use when feeding audio to the platform and replacing "traditional" audio source, such as audio capture devices.
-
public final static int USAGE_ASSISTANT = 16:Usage value to use for audio responses to user queries, audio instructions or help utterances.
-
public static final int USAGE_CALL_ASSISTANT = 17:Usage value to use for assistant voice interaction with remote caller on Cell and VoIP calls.
AudioAttributes代码位于:
frameworks/base/media/java/android/media/AudioAttributes.java
AudioAttributes的定义:
public final class AudioAttributes implements Parcelable {
public static class Builder {}
}
SoundEffectsHelper
一个帮助程序类,用于管理 AudioService 使用的声音效果加载/卸载。当在 AudioService 的消息处理程序线程上调用其方法时,实际工作将卸载到专用线程。
这有助于保持 AudioService 的响应速度。
SoundEffectsHelper代码位于:
frameworks/base/service/java/com/android/server/audio/SoundEffectsHelper.java
SoundEffectsHelper的定义:
class SoundEffectsHelper {
private static final class Resource {}
private class SfxWorker extends Thread {}
private class SfxHandler extends Handler {}
private class SoundPoolLoader implements
android.media.SoundPool.OnLoadCompleteListener {}
}
C++类
SoundPool
SoundPool代码位于:
frameworks/base/media/jni/SoundPool/SoundPool.h
frameworks/base/media/jni/SoundPool/SoundPool.cpp
SoundPool的定义:
class SoundPool {}
StreamManager
StreamManager 用于管理流(由 Java 中的 StreamID 访问)。
StreamManager代码位于:
frameworks/base/media/jni/SoundPool/StreamManager.h
frameworks/base/media/jni/SoundPool/StreamManager.cpp
StreamManager的定义:
class JavaThread {} //JavaThread is used like std::thread but for threads that may call the JVM.
class ThreadPool {} //The ThreadPool manages thread lifetimes of SoundPool worker threads.
class PerfectHash {} //A Perfect HashTable for IDs (key) to pointers (value).
class StreamMap {} //StreamMap contains the all the valid streams available to SoundPool.
class StreamManager : public StreamMap {} //StreamManager is used to manage the streams (accessed by StreamID from Java).
SoundManager
此类管理 SoundPool 的声音。
SoundManager代码位于:
frameworks/base/media/jni/SoundPool/SoundManager.h
frameworks/base/media/jni/SoundPool/SoundManager.cpp
SoundManager的定义:
class SoundPoolEvent {}
class SoundManager {}
class CallbackHandler {}
Sound
Sound是SoundPool使用的资源,由soundID引用。
Sound 代码位于:
frameworks/base/media/jni/SoundPool/Sound.h
frameworks/base/media/jni/SoundPool/Sound.cpp
Sound 的定义:
class Sound {}
Sound 方法:
int32_t getSoundID() const { return mSoundID; }
int32_t getChannelCount() const { return mChannelCount; }
uint32_t getSampleRate() const { return mSampleRate; }
audio_format_t getFormat() const { return mFormat; }
audio_channel_mask_t getChannelMask() const { return mChannelMask; }
size_t getSizeInBytes() const { return mSizeInBytes; }
sound_state getState() const { return mState; }
uint8_t* getData() const { return static_cast<uint8_t*>(mData->unsecurePointer()); }
sp<IMemory> getIMemory() const { return mData; }
SoundDecoder
SoundDecoder处理后台解码任务。
SoundDecoder代码位于:
frameworks/base/media/jni/SoundPool/SoundDecoder.h
frameworks/base/media/jni/SoundPool/SoundDecoder.cpp
SoundDecoder的定义:
class SoundDecoder {}
SoundDecoder方法:
void loadSound(int32_t soundID) NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
void quit();
Stream
soundpool Stream相关处理。
Stream代码位于:
frameworks/base/media/jni/SoundPool/Stream.h
frameworks/base/media/jni/SoundPool/Stream.cpp
Stream的定义:
class Stream : public CSubsystemObject {}
Stream 方法:
bool requestStop(int32_t streamID);
void stop();
void clearAudioTrack();
void pause(int32_t streamID);
void autoPause();
void resume(int32_t streamID);
void autoResume();
void mute(bool muting);
Stream* playPairStream(std::vector<std::any>& garbage);
void setVolume(int32_t streamID, float leftVolume, float rightVolume);
void setRate(int32_t streamID, float rate);
void setPriority(int32_t streamID, int priority);
void setLoop(int32_t streamID, int loop);
void setPlay(int32_t streamID, const std::shared_ptr<Sound> &sound, int32_t soundID float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate);
void setStopTimeNs(int64_t stopTimeNs);
int32_t getPriority();
int32_t getPairPriority();
int64_t getStopTimeNs();
int32_t getStreamID();
int32_t getSoundID();
bool hasSound();
Stream* getPairStream() const;
int getCorrespondingStreamID();
三、SoundPool API
SoundPool(int maxStreams, int streamType, int srcQuality):构造函数
int load(Context context, int resId, int priority):加载声音资源,返回一个声音的ID,后面我们可以通过这个ID来播放指定的声音
int load(String path, int priority):加载声音资源,返回一个声音的ID,后面我们可以通过这个ID来播放指定的声音
int load(FileDescriptor fd, long offset, long length, int priority):加载声音资源,返回一个声音的ID,后面我们可以通过这个ID来播放指定的声音
int load(AssetFileDescriptor afd, int priority):加载声音资源,返回一个声音的ID,后面我们可以通过这个ID来播放指定的声音
int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate):播放
void setVolume(int streamID, float volume):设置音量
void setPriority(int streamID, int priority):设置优先级
void pause(int streamID):暂停
void resume(int streamID):重播
void stop(int streamID):停止
void release() :释放资源
参数介绍:
maxStreams 同时播放流的最大数量,当播放的流的数目大于此值,则会选择性停止优先级较低的流
streamType 流类型,比如 STREAM_MUSIC
srcQuality 采样率转换器质量,目前没有什么作用,默认填充0
context:上下文
resId:资源id
priority:没什么用的一个参数,建议设置为1,保持和未来的兼容性
path:文件路径
FileDescriptor:貌似是流吧,这个我也不知道
AssetFileDescriptor:从asset目录读取某个资源文件,用法: AssetFileDescriptor descriptor = - assetManager.openFd(“biaobiao.mp3”);
soundID:Load()返回的声音ID号
leftVolume:左声道音量设置
rightVolume:右声道音量设置
priority:指定播放声音的优先级,数值越高,优先级越大。
loop:指定是否循环:-1表示无限循环,0表示不循环,其他值表示要重复播放的次数
rate:指定播放速率:1.0的播放率可以使声音按照其原始频率,而2.0的播放速率,可以使声音按照其 原始频率的两倍播放。如果为0.5的播放率,则播放速率是原始频率的一半。播放速率的取值范围是0.5至2.0。
四、SoundPool流程分析
SoundPool 创建流程分析
Android13 SoundPool 创建流程分析-CSDN博客
SoundPool load流程分析
Android13 SoundPool load流程分析-CSDN博客