Android 中的 A2DP Sink
A2DP Sink 在 Android 系统中主要用于 接收 其他蓝牙设备(如手机、平板、电脑等)发送过来的 高质量的立体声音频。简单来说,它让你的 Android 设备可以充当一个 蓝牙音箱 或 耳机 的角色。
核心功能:
- 接收音频流: 通过蓝牙协议接收来自其他设备的音频数据。
- 解码音频: 将接收到的音频数据解码成可播放的音频格式。
- 播放音频: 通过设备的扬声器或耳机输出解码后的音频。
应用场景:
- 无线音箱: 将 Android 设备连接到蓝牙音箱,实现无线音乐播放。
- 车载蓝牙: 将手机连接到车载蓝牙系统,通过车载音响播放音乐。
- 蓝牙耳机: 将 Android 设备连接到蓝牙耳机,进行通话或听音乐。
技术实现:
- BluetoothA2dpSink: Android 提供了
BluetoothA2dpSink
类来实现 A2DP Sink 功能。开发者可以通过这个类来管理 A2DP 连接、控制音频播放等。 - 蓝牙配置文件: A2DP(Advanced Audio Distribution Profile)是一种蓝牙配置文件,专门用于高质量立体声音频的无线传输。
如何获取音频数据并生成音频频谱?
什么是音乐频谱?
音乐频谱是声音频率的分布图。声音是由不同频率的声波组成的,这些声波的振幅(强度)不同,就形成了不同的音色。频谱图就是将这些频率和振幅的关系用图形表示出来。
频谱图的组成
- 横轴: 表示频率,通常以赫兹(Hz)为单位。频率越高,音调越高。
- 纵轴: 表示振幅,也就是声音的强度。振幅越大,声音越响。
- 颜色或灰度: 表示不同频率的振幅大小。颜色越深或灰度越高,表示该频率的振幅越大。
频谱图的种类
- 线性频谱图: 频率轴按线性比例分布,适用于分析整个音频频段。
- 对数频谱图: 频率轴按对数比例分布,更适合显示低频部分的细节,常用于音频分析。
- 时频图: 显示声音频率随时间的变化情况,可以直观地看到声音的动态变化。
总的来说
音乐频谱是了解声音的重要工具,它不仅能帮助我们更好地理解声音的本质,还能在音乐创作、音频处理等领域发挥重要作用。
在蓝牙音箱的模式下, 如何生成音频频谱?
在打上RK提供的A2dpSink补丁后, 手机等设备可以通过蓝牙连接播放音乐, RK3568充当蓝牙音箱的角色. 在这种状态下, 系统播放音频并不是采用android上层的MediaPlayer 或 AudioTrack, 所以无法采用常规的方式来生成, 若需要获取播放器的音频频谱, 首先, 需要获得音频的PCM数据.
在蓝牙音箱模式下, 音频的播放器的位置处于android 源码的 system目录下
system/bt/btif/src/btif_avrcp_audio_track.cc
/*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_NDEBUG 1
#define LOG_TAG "bt_btif_avrcp_audio_track"
#include "btif_avrcp_audio_track.h"
#include <aaudio/AAudio.h>
#include <base/logging.h>
#include <utils/StrongPointer.h>
#include "bt_target.h"
#include "osi/include/log.h"
using namespace android;
typedef struct {
AAudioStream* stream;
int bitsPerSample;
int channelCount;
float* buffer;
size_t bufferLength;
} BtifAvrcpAudioTrack;
#if (DUMP_PCM_DATA == TRUE)
FILE* outputPcmSampleFile;
char outputFilename[50] = "/data/misc/bluedroid/output_sample.pcm";
#endif
void* BtifAvrcpAudioTrackCreate(int trackFreq, int bitsPerSample,
int channelCount) {
LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btCreateTrack freq %d bps %d channel %d ",
__func__, trackFreq, bitsPerSample, channelCount);
AAudioStreamBuilder* builder;
AAudioStream* stream;
aaudio_result_t result = AAudio_createStreamBuilder(&builder);
AAudioStreamBuilder_setSampleRate(builder, trackFreq);
AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
AAudioStreamBuilder_setChannelCount(builder, channelCount)