This commit is contained in:
2026-01-21 17:59:12 +08:00
parent 36c0b0b210
commit 06a572c08a
4 changed files with 93 additions and 2 deletions

View File

@@ -14,6 +14,7 @@ const int kAudioChannels = 1;
const NSUInteger kAudioFrameDuration = 20; // ms
const NSUInteger kAudioFrameSamples = 320; // 16000 * 0.02
const NSUInteger kAudioFrameBytes = 640; // 320 * 2 (Int16)
static const float kAudioSoftwareGain = 2.5f;
@interface AudioCaptureManager ()
@@ -24,6 +25,7 @@ const NSUInteger kAudioFrameBytes = 640; // 320 * 2 (Int16)
// Ring buffer for accumulating samples to form 20ms frames
@property(nonatomic, strong) NSMutableData *ringBuffer;
@property(nonatomic, assign) NSUInteger ringBufferWriteIndex;
@property(nonatomic, assign) NSTimeInterval lastStatsLogTime;
@end
@@ -39,6 +41,7 @@ const NSUInteger kAudioFrameBytes = 640; // 320 * 2 (Int16)
initWithLength:kAudioFrameBytes * 4]; // Buffer for multiple frames
_ringBufferWriteIndex = 0;
_capturing = NO;
_lastStatsLogTime = 0;
}
return self;
}
@@ -180,8 +183,11 @@ const NSUInteger kAudioFrameBytes = 640; // 320 * 2 (Int16)
NSUInteger sampleCount = outputBuffer.frameLength;
NSUInteger byteCount = sampleCount * sizeof(int16_t);
[self applySoftwareGainIfNeeded:samples sampleCount:sampleCount];
// RMS
[self calculateAndReportRMS:samples sampleCount:sampleCount];
[self logAudioStatsIfNeeded:samples sampleCount:sampleCount];
// ring buffer
dispatch_async(self.audioQueue, ^{
@@ -266,4 +272,53 @@ const NSUInteger kAudioFrameBytes = 640; // 320 * 2 (Int16)
});
}
- (void)applySoftwareGainIfNeeded:(int16_t *)samples
sampleCount:(NSUInteger)sampleCount {
if (kAudioSoftwareGain <= 1.0f || sampleCount == 0) {
return;
}
for (NSUInteger i = 0; i < sampleCount; i++) {
float scaled = (float)samples[i] * kAudioSoftwareGain;
if (scaled > 32767.0f) {
samples[i] = 32767;
} else if (scaled < -32768.0f) {
samples[i] = -32768;
} else {
samples[i] = (int16_t)scaled;
}
}
}
- (void)logAudioStatsIfNeeded:(int16_t *)samples
sampleCount:(NSUInteger)sampleCount {
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
if (now - self.lastStatsLogTime < 1.0) {
return;
}
self.lastStatsLogTime = now;
if (sampleCount == 0) {
return;
}
NSUInteger nonZeroCount = 0;
int16_t peak = 0;
for (NSUInteger i = 0; i < sampleCount; i++) {
int16_t value = samples[i];
if (value != 0) {
nonZeroCount++;
}
int16_t absValue = (int16_t)abs(value);
if (absValue > peak) {
peak = absValue;
}
}
double nonZeroRatio = (double)nonZeroCount / (double)sampleCount;
double peakNormalized = (double)peak / 32768.0;
NSLog(@"[AudioCaptureManager] Stats: peak=%.3f nonZero=%.2f%%",
peakNormalized, nonZeroRatio * 100.0);
}
@end

View File

@@ -141,7 +141,7 @@
// +
// Category: PlayAndRecord -
// Mode: VoiceChat -
// Mode: VoiceChat - AGC/
// Options:
// - DefaultToSpeaker: 使
// - AllowBluetooth:
@@ -162,6 +162,31 @@
return NO;
}
// 使
NSError *sampleRateError = nil;
[session setPreferredSampleRate:16000 error:&sampleRateError];
if (sampleRateError) {
NSLog(@"[AudioSessionManager] Failed to set sample rate: %@",
sampleRateError.localizedDescription);
}
NSError *bufferError = nil;
[session setPreferredIOBufferDuration:0.02 error:&bufferError];
if (bufferError) {
NSLog(@"[AudioSessionManager] Failed to set IO buffer: %@",
bufferError.localizedDescription);
}
if ([session respondsToSelector:@selector(setPreferredInputNumberOfChannels:
error:)]) {
NSError *channelsError = nil;
[session setPreferredInputNumberOfChannels:1 error:&channelsError];
if (channelsError) {
NSLog(@"[AudioSessionManager] Failed to set input channels: %@",
channelsError.localizedDescription);
}
}
return YES;
}
@@ -206,6 +231,15 @@
return NO;
}
if (session.isInputGainSettable) {
NSError *gainError = nil;
[session setInputGain:1.0 error:&gainError];
if (gainError) {
NSLog(@"[AudioSessionManager] Failed to set input gain: %@",
gainError.localizedDescription);
}
}
self.isSessionActive = YES;
return YES;
}

View File

@@ -96,6 +96,8 @@ static NSString *const kVoiceChatWebSocketClientErrorDomain =
message[@"config"] = config;
}
NSLog(@"[VoiceChatWebSocketClient] Sending session_start: %@",
message);
[self sendJSON:message];
}