Merge branch 'systemAudioEngineTest' into Integration
This commit is contained in:
commit
e050c914bb
3 files changed
+116
-18
No files matched your search
@@ -185,11 +185,11 @@ public class MicHandler: NSObject {
|
|||||||
|
|
||||||
private func configureSession() throws {
|
private func configureSession() throws {
|
||||||
let session = AVAudioSession.sharedInstance()
|
let session = AVAudioSession.sharedInstance()
|
||||||
try session.setCategory(.playAndRecord, mode: .videoRecording, options: [.mixWithOthers, .defaultToSpeaker, .allowBluetooth])
|
let bluetoothAudioOption = self.useBuiltinMic ? AVAudioSession.CategoryOptions.allowBluetoothA2DP : AVAudioSession.CategoryOptions.allowBluetooth
|
||||||
|
try session.setCategory(.playAndRecord, mode: .videoRecording, options: [.mixWithOthers, .defaultToSpeaker, bluetoothAudioOption])
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
try session.setAllowHapticsAndSystemSoundsDuringRecording(true)
|
try session.setAllowHapticsAndSystemSoundsDuringRecording(true)
|
||||||
}
|
}
|
||||||
try session.setActive(true)
|
|
||||||
|
|
||||||
// 列出所有可用输入
|
// 列出所有可用输入
|
||||||
if self.useBuiltinMic, let inputs = session.availableInputs {
|
if self.useBuiltinMic, let inputs = session.availableInputs {
|
||||||
@@ -201,6 +201,7 @@ public class MicHandler: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try session.setActive(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendOpusFrameFromDequeBuffer() {
|
private func sendOpusFrameFromDequeBuffer() {
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
// Created by Diego Waxemberg on 1/19/14.
|
// Created by Diego Waxemberg on 1/19/14.
|
||||||
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
//
|
//
|
||||||
|
// Modified by True砖家 since 2025.9
|
||||||
|
// Copyright © 2025 True砖家 on Bilibili. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
#import "ConnectionCallbacks.h"
|
#import "ConnectionCallbacks.h"
|
||||||
#import "VideoDecoderRenderer.h"
|
#import "VideoDecoderRenderer.h"
|
||||||
@@ -23,5 +27,6 @@
|
|||||||
-(BOOL) getVideoStats:(video_stats_t*)stats;
|
-(BOOL) getVideoStats:(video_stats_t*)stats;
|
||||||
-(NSString*) getActiveCodecName;
|
-(NSString*) getActiveCodecName;
|
||||||
+ (void)setVolume:(float)newVolume;
|
+ (void)setVolume:(float)newVolume;
|
||||||
|
+ (void)setUseSystemAudioEngine:(bool)useSysAudioEngine;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
+108
-16
@@ -5,6 +5,9 @@
|
|||||||
// Created by Diego Waxemberg on 1/19/14.
|
// Created by Diego Waxemberg on 1/19/14.
|
||||||
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
|
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
|
||||||
//
|
//
|
||||||
|
// Modified by True砖家 since 2025.9
|
||||||
|
// Copyright © 2025 True砖家 on Bilibili. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
#import "Connection.h"
|
#import "Connection.h"
|
||||||
#import "Plot.h"
|
#import "Plot.h"
|
||||||
@@ -47,6 +50,12 @@ static void* audioBuffer;
|
|||||||
static float volume = 1.0;
|
static float volume = 1.0;
|
||||||
static int audioFrameSize;
|
static int audioFrameSize;
|
||||||
|
|
||||||
|
static bool useSystemAudioEngine;
|
||||||
|
static AVAudioEngine *audioEngine;
|
||||||
|
static AVAudioPlayerNode *audioPlayerNode;
|
||||||
|
static AVAudioPCMBuffer *pcmBuffer;
|
||||||
|
static AVAudioFormat *audioFormat;
|
||||||
|
|
||||||
static VideoDecoderRenderer* renderer;
|
static VideoDecoderRenderer* renderer;
|
||||||
|
|
||||||
static BandwidthTracker *bwTracker;
|
static BandwidthTracker *bwTracker;
|
||||||
@@ -276,10 +285,20 @@ int ArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig, v
|
|||||||
SDL_PauseAudioDevice(audioDevice, 0);
|
SDL_PauseAudioDevice(audioDevice, 0);
|
||||||
|
|
||||||
// Disable lowering volume of other audio streams (SDL sets AVAudioSessionCategoryOptionDuckOthers by default)
|
// Disable lowering volume of other audio streams (SDL sets AVAudioSessionCategoryOptionDuckOthers by default)
|
||||||
|
// AVAudioSessionCategoryOptionAllowBluetoothA2DP
|
||||||
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
|
// AVAudioSessionCategoryOptionAllowBluetooth
|
||||||
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
|
TemporarySettings* tempSettings = [dataMan getSettings];
|
||||||
|
bool useBluetoothD2P = tempSettings.useBuiltinMic || !tempSettings.redirectMic;
|
||||||
|
AVAudioSessionCategoryOptions bluetoothAudioOption = useBluetoothD2P ? AVAudioSessionCategoryOptionAllowBluetoothA2DP : AVAudioSessionCategoryOptionAllowBluetooth;
|
||||||
|
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||||
|
[session setCategory:AVAudioSessionCategoryPlayAndRecord
|
||||||
|
withOptions:AVAudioSessionCategoryOptionMixWithOthers|AVAudioSessionCategoryOptionDefaultToSpeaker|bluetoothAudioOption
|
||||||
|
error:nil];
|
||||||
|
[session setActive:YES error:nil];
|
||||||
|
|
||||||
|
AudioEngineInit(audioConfig.sampleRate, audioConfig.channelCount);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,6 +329,57 @@ void ArCleanup(void)
|
|||||||
volume = powf(linearVolume, exponent);
|
volume = powf(linearVolume, exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)setUseSystemAudioEngine:(bool)useSysAudioEngine{
|
||||||
|
useSystemAudioEngine = useSysAudioEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioEngineInit(int sampleRate, int channelCount) {
|
||||||
|
|
||||||
|
audioEngine = [[AVAudioEngine alloc] init];
|
||||||
|
audioPlayerNode = [[AVAudioPlayerNode alloc] init];
|
||||||
|
|
||||||
|
[audioEngine attachNode:audioPlayerNode];
|
||||||
|
|
||||||
|
AVAudioChannelLayout *layout;
|
||||||
|
|
||||||
|
switch (channelCount) {
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
audioFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
|
||||||
|
sampleRate:sampleRate
|
||||||
|
channels:channelCount
|
||||||
|
interleaved:NO];
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
layout =
|
||||||
|
[[AVAudioChannelLayout alloc] initWithLayoutTag:kAudioChannelLayoutTag_MPEG_5_1_A];
|
||||||
|
audioFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
|
||||||
|
sampleRate:sampleRate
|
||||||
|
interleaved:NO
|
||||||
|
channelLayout:layout];
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
layout =
|
||||||
|
[[AVAudioChannelLayout alloc] initWithLayoutTag:kAudioChannelLayoutTag_MPEG_7_1_A];
|
||||||
|
audioFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
|
||||||
|
sampleRate:sampleRate
|
||||||
|
interleaved:NO
|
||||||
|
channelLayout:layout];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!audioFormat) return;
|
||||||
|
|
||||||
|
[audioEngine connect:audioPlayerNode to:audioEngine.mainMixerNode format:audioFormat];
|
||||||
|
|
||||||
|
NSError *err = nil;
|
||||||
|
if (![audioEngine startAndReturnError:&err]) {
|
||||||
|
NSLog(@"AudioEngine start error: %@", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
[audioPlayerNode play];
|
||||||
|
}
|
||||||
|
|
||||||
void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
|
void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
|
||||||
{
|
{
|
||||||
int decodeLen;
|
int decodeLen;
|
||||||
@@ -333,21 +403,41 @@ void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
|
|||||||
|
|
||||||
float* fbuf = (float*)audioBuffer;
|
float* fbuf = (float*)audioBuffer;
|
||||||
|
|
||||||
if(volume != 1.0){
|
// if(useSystemAudioEngine && false) {
|
||||||
int totalSamples = decodeLen * audioConfig.channelCount;
|
if(true){
|
||||||
for (int i = 0; i < totalSamples; i++) {
|
// 创建 AVAudioPCMBuffer
|
||||||
fbuf[i] *= volume;
|
AVAudioFrameCount frameCount = decodeLen;
|
||||||
|
AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFormat frameCapacity:frameCount];
|
||||||
|
buffer.frameLength = frameCount;
|
||||||
|
|
||||||
|
// 拷贝数据到 buffer
|
||||||
|
for (int ch = 0; ch < audioConfig.channelCount; ch++) {
|
||||||
|
float *dst = buffer.floatChannelData[ch];
|
||||||
|
for (int i = 0; i < decodeLen; i++) {
|
||||||
|
dst[i] = fbuf[i * audioConfig.channelCount + ch] * volume; // 非交错数据
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// 播放
|
||||||
|
[audioPlayerNode scheduleBuffer:buffer completionHandler:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
while (SDL_GetQueuedAudioSize(audioDevice) / audioFrameSize > 10) {
|
else{
|
||||||
[NSThread sleepForTimeInterval:0.001f];
|
if(volume != 1.0){
|
||||||
}
|
int totalSamples = decodeLen * audioConfig.channelCount;
|
||||||
|
for (int i = 0; i < totalSamples; i++) {
|
||||||
if (SDL_QueueAudio(audioDevice,
|
fbuf[i] *= volume;
|
||||||
audioBuffer,
|
}
|
||||||
sizeof(float) * decodeLen * audioConfig.channelCount) < 0) {
|
}
|
||||||
Log(LOG_E, @"Failed to queue audio sample: %s\n", SDL_GetError());
|
|
||||||
|
while (SDL_GetQueuedAudioSize(audioDevice) / audioFrameSize > 10) {
|
||||||
|
[NSThread sleepForTimeInterval:0.001f];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_QueueAudio(audioDevice,
|
||||||
|
audioBuffer,
|
||||||
|
sizeof(float) * decodeLen * audioConfig.channelCount) < 0) {
|
||||||
|
Log(LOG_E, @"Failed to queue audio sample: %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,7 +513,9 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t
|
|||||||
// won't be able to acquire it if LiStartConnection is in
|
// won't be able to acquire it if LiStartConnection is in
|
||||||
// progress.
|
// progress.
|
||||||
LiInterruptConnection();
|
LiInterruptConnection();
|
||||||
|
[audioPlayerNode stop];
|
||||||
|
[audioEngine stop];
|
||||||
|
|
||||||
// We dispatch this async to get out because this can be invoked
|
// We dispatch this async to get out because this can be invoked
|
||||||
// on a thread inside common and we don't want to deadlock. It also avoids
|
// on a thread inside common and we don't want to deadlock. It also avoids
|
||||||
// blocking on the caller's thread waiting to acquire initLock.
|
// blocking on the caller's thread waiting to acquire initLock.
|
||||||
|
|||||||
Reference in new issue
Block a user