如果需要在通话过程中,播放音效、音乐文件等,而且让房间内的其他成员也听到声音,你需要使用混音功能。例如 ”一起看“,“一起听” 等互动娱乐类应用。混音功能可以将麦克风采集的音频数据与音频文件、PCM 音频数据等合并为一路音频流后,发布到房间内。
初始化引擎后,调用 getAudioMixingManager 获取到 IAudioMixingManager 类, 开始使用混音功能。
| Android | iOS | macOS | Windows | Web |
|---|---|---|---|---|
| getAudioMixingManager | getAudioMixingManager | getAudioMixingManager | getAudioMixingManager | getAudioMixingManager |
参考以下顺序,调用 API 实现此功能:
对同一个音频文件进行操作时,混音 ID 应保持一致
| 步骤 | 调用目标 | 接口 |
|---|---|---|
| 1 | (可选)预加载音乐文件 | preloadAudioMixing |
| 2 | 播放音乐文件 | startAudioMixing |
| 3 | 暂停播放 | pauseAudioMixing |
| 4 | 恢复播放 | resumeAudioMixing |
| 5 | 停止播放 | stopAudioMixing |
除以上功能以外,RTC SDK 还支持调整音频播放音量和声道,设置音乐播放进度等功能。
参考以下顺序,调用 API 实现此功能:
| 步骤 | 调用目标 | Android 接口 |
|---|---|---|
| 1 | 启动 PCM 音频数据混音 | enableAudioMixingFrame |
| 2 | 周期性推送 PCM 音频数据,以开始播放 | pushAudioMixingFrame |
| 3 | 结束 PCM 音频数据混音 | disableAudioMixingFrame |
示例代码以 objective-C 为例,介绍播放 PCM 音频的相关功能。
- (void)startAudioMixing {
ByteRTCAudioMixingManager *manager = [self.rtcKit getAudioMixingManager];
[manager enableAudioMixingFrame:kAudioMixingID type:ByteRTCAudioMixingTypePlayout];
}
objectivec以下示例代码以 ttplayer 的数据为例,说明 SDK 要求的数据处理方式。
/// 处理 PCM 数据
/// @param inouts float 类型 PCM 数据
/// @param samples 采样点数
- (void)processAudio:(float **)inouts samples:(int)samples {
// 声道数。如果声道数超过 2 个,需要先将音频进行减声道处理后再传给 SDK。
int channelsCount = _channels;
// 采样率
int samplerate = _samplerate;
int length = samples * channelsCount;
if (self.length < length) {
if (self.length > 0) {
self.length = 0;
delete [] (buffer);
}
// buffer 成员变量
buffer = new int16_t[length*2];
self.length = length*2;
}
// 如果数据为非交织格式,需要转换为交织格式
for (int i = 0; i < channelsCount; i++) {
int offset = i;
float *dataList = inouts[i];
for (int j = 0; j < samples; j++) {
float data = dataList[j];
// 转换为 int16 类型
int value = data * INT16_MAX;
if(value > INT16_MAX){
value = INT16_MAX;
} else if(value < INT16_MIN){
value = INT16_MIN;
}
buffer[offset] = value;
offset += _channels;
}
}
ByteRTCAudioFrame *frame = [[ByteRTCAudioFrame alloc] init];
frame.buffer = [NSData dataWithBytes:buffer length:length*2]; // 用类方法,不参与 buffer 生命周期管理
frame.samples = samples;
frame.channel = (ByteRTCAudioChannel)channelsCount;
frame.sampleRate = (ByteRTCAudioSampleRate)samplerate;
ByteRTCAudioMixingManager *manager = [self.rtcKit getAudioMixingManager];
[manager pushAudioMixingFrame:kAudioMixingID audioFrame:frame];
}
objectivec - (void)setAudioMixingVolume:(CGFloat)audioMixingVolume {
ByteRTCAudioMixingManager *audioMixingManager = [self.rtcKit getAudioMixingManager];
[audioMixingManager setAudioMixingVolume:kAudioMixingID volume:volume type:ByteRTCAudioMixingTypePlayout];
}
objectivec - (void)stopAudioMixing {
ByteRTCAudioMixingManager *manager = [self.rtcKit getAudioMixingManager];
[manager disableAudioMixingFrame:kAudioMixingID];
}
objectivec