Android音频开发

1,019 阅读2分钟

开源音视频播放器

非音视频相关知识点

音视频相关知识点

1. Android 音频系统播放延迟时间获取(latency)

<br>
getLatency得到的ms值,就是AudioTrack.write写入的byte总量对应的'播放时长',和人耳实际听到的'当前播放时间'的差值.
```
public static int getLatencyByReflect() {
    //set default:80ms
    int latencys = 80;
    if(mAudioTrack != null ) {
        try {
            Class<?> classAudioTrack = mAudioTrack.getClass();
            Method getLatencyMethod = classAudioTrack.getDeclaredMethod("getLatency");
            getLatencyMethod.setAccessible(true);
            latencys = (int) getLatencyMethod.invoke(mAudioTrack);
            latencys = Math.max(latencys, 80);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    return latencys;
}
```
![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9903cf7b3f86416bbb5382a8eb492741~tplv-k3u1fbpfcp-zoom-1.image)

2. Android多媒体分析-通过MediaStore获取Audio信息

```
//歌曲名  
String title = cursor.getString(cursor  
        .getColumnIndex(MediaStore.Audio.Media.TITLE));  
  
//歌手  
String singer = cursor.getString(cursor  
        .getColumnIndex(MediaStore.Audio.Media.ARTIST));  
  
//专辑  
String album = cursor.getString(cursor  
        .getColumnIndex(MediaStore.Audio.Media.ALBUM));  
  
//长度  
long size = cursor.getLong(cursor  
        .getColumnIndex(MediaStore.Audio.Media.SIZE));  
  
//时长  
int duration = cursor.getInt(cursor  
        .getColumnIndex(MediaStore.Audio.Media.DURATION));  
  
//路径  
String url = cursor.getString(cursor  
        .getColumnIndex(MediaStore.Audio.Media.DATA));  
  
//文件名
String _display_name = cursor.getString(cursor  
        .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
```

3. Audio Audio:AudioTrack()中write()函数梳理过程

4. Android Audio:AudioTrack构造函数分析

5. AudioRecord的getMinBufferSize函数的分析

![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0063cbcfa5634cf282da4cce02dab715~tplv-k3u1fbpfcp-zoom-1.image)

6. DamonRen 有一些音频文章很好

7. Android 解读开源项目UniversalMusicPlayer(数据管理)

8. AnliaLee

- [Android 媒体播放框架MediaSession分析与实践](https://juejin.cn/post/6844903575814930439)
- [Android 解读开源项目UniversalMusicPlayer(播放控制层)](https://juejin.cn/post/6844903583557615629)
- [Android 解读开源项目UniversalMusicPlayer(数据管理)](https://juejin.cn/post/6844903586392981518)
- [UniversalMusicPlayer](https://github.com/android/uamp)

9. 多声道/立体声

- [Android立体声pcm的数据结构,左右声道拆分、左右声道反转](https://blog.csdn.net/hi_ugly/article/details/80977850)
- [Android 分离PCM中每个Channel的数据](https://blog.csdn.net/zchy198799/article/details/98882894)
- [使用Java分离音频左右声道](https://www.jianshu.com/p/cc9e0ee2661d)
- [视音频数据处理入门:PCM音频采样数据处理](https://blog.csdn.net/leixiaohua1020/article/details/50534316)

10. AudioTrack创建失败

/**
 * Builds an {@link AudioTrack} instance initialized with all the parameters set
 * on this <code>Builder</code>.
 * @return a new successfully initialized {@link AudioTrack} instance.
 * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
 *     were incompatible, or if they are not supported by the device,
 *     or if the device was not available.
 */
public @NonNull AudioTrack build() throws UnsupportedOperationException {
    if (mAttributes == null) {
        mAttributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .build();
    }
    switch (mPerformanceMode) {
    case PERFORMANCE_MODE_LOW_LATENCY:
        mAttributes = new AudioAttributes.Builder(mAttributes)
            .replaceFlags((mAttributes.getAllFlags()
                    | AudioAttributes.FLAG_LOW_LATENCY)
                    & ~AudioAttributes.FLAG_DEEP_BUFFER)
            .build();
        break;
    case PERFORMANCE_MODE_NONE:
        if (!shouldEnablePowerSaving(mAttributes, mFormat, mBufferSizeInBytes, mMode)) {
            break; // do not enable deep buffer mode.
        }
        // permitted to fall through to enable deep buffer
    case PERFORMANCE_MODE_POWER_SAVING:
        mAttributes = new AudioAttributes.Builder(mAttributes)
        .replaceFlags((mAttributes.getAllFlags()
                | AudioAttributes.FLAG_DEEP_BUFFER)
                & ~AudioAttributes.FLAG_LOW_LATENCY)
        .build();
        break;
    }

    if (mFormat == null) {
        mFormat = new AudioFormat.Builder()
                .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
                //.setSampleRate(AudioFormat.SAMPLE_RATE_UNSPECIFIED)
                .setEncoding(AudioFormat.ENCODING_DEFAULT)
                .build();
    }

    if (mOffload) {
        if (mPerformanceMode == PERFORMANCE_MODE_LOW_LATENCY) {
            throw new UnsupportedOperationException(
                    "Offload and low latency modes are incompatible");
        }
        if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) {
            throw new UnsupportedOperationException(
                    "Cannot create AudioTrack, offload format / attributes not supported");
        }
    }

    // TODO: Check mEncapsulationMode compatibility with MODE_STATIC, etc?

    try {
        // If the buffer size is not specified in streaming mode,
        // use a single frame for the buffer size and let the
        // native code figure out the minimum buffer size.
        if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) {
            mBufferSizeInBytes = mFormat.getChannelCount()
                    * mFormat.getBytesPerSample(mFormat.getEncoding());
        }
        final AudioTrack track = new AudioTrack(
                mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload,
                mEncapsulationMode, mTunerConfiguration);
        if (track.getState() == STATE_UNINITIALIZED) {
            // release is not necessary
            throw new UnsupportedOperationException("Cannot create AudioTrack");
        }
        return track;
    } catch (IllegalArgumentException e) {
        throw new UnsupportedOperationException(e.getMessage());
    }
}
}
  1. 其中一种创建失败,抛出异常: throw new UnsupportedOperationException("Cannot create AudioTrack");
    • 搜索log会发现:无法创建更多
      *** E AF::Track: Track(17330): no more tracks available
      *** E AF::Track: Track(17331): no more tracks available
      *** E AF::Track: Track(17332): no more tracks available
      *** E AF::Track: Track(17333): no more tracks available
      *** E AF::Track: Track(17335): no more tracks available
      
    • 这种情况属于audioTrack泄漏,大概率是系统代码本身有问题.