gpt4 book ai didi

ios - AudioConverter包数错误

转载 作者:行者123 更新时间:2023-11-29 04:15:55 25 4
gpt4 key购买 nike

我已经设置了一个类,根据给定的输入和输出 AudioStreamBasicDescription 将音频从一种格式转换为另一种格式。当我将 Linear PCM 从麦克风转换为 iLBC 时,它可以工作,当我从 AudioUnitRender 函数给它 1024 个数据包时,它会给我 6 个数据包。然后,我通过 UDP 将这 226 字节发送到在不同设备上运行的同一应用程序。问题是,当我使用相同的类转换回线性 PCM 以提供给音频单元输入时,AudioConverterFillComplexBuffer 函数不会提供 1024 个数据包,而是提供 960 个数据包...这意味着音频单元输入预计为 4096 字节(立体声为 2048 x 2),但我只能给它 3190 左右,因此听起来确实很破裂且失真......

如果我给 AudioConverter 1024 个 LinearPCM 数据包,转换为 iLBC,再转换回 LinearPCM,我肯定会再次得到 1024 个数据包吗?

音频转换器功能:

-(void) doConvert {

// Start converting
if (converting) return;
converting = YES;

while (true) {

// Get next buffer
id bfr = [buffers getNextBuffer];
if (!bfr) {
converting = NO;
return;
}

// Get info
NSArray* bfrs = ([bfr isKindOfClass:[NSArray class]] ? bfr : @[bfr]);
int bfrSize = 0;
for (NSData* dat in bfrs) bfrSize += dat.length;

int inputPackets = bfrSize / self.inputFormat.mBytesPerPacket;
int outputPackets = (inputPackets * self.inputFormat.mFramesPerPacket) / self.outputFormat.mFramesPerPacket;

// Create output buffer
AudioBufferList* bufferList = (AudioBufferList*) malloc(sizeof(AudioBufferList) * self.outputFormat.mChannelsPerFrame);
bufferList -> mNumberBuffers = self.outputFormat.mChannelsPerFrame;
for (int i = 0 ; i < self.outputFormat.mChannelsPerFrame ; i++) {
bufferList -> mBuffers[i].mNumberChannels = 1;
bufferList -> mBuffers[i].mDataByteSize = 4*1024;
bufferList -> mBuffers[i].mData = malloc(bufferList -> mBuffers[i].mDataByteSize);
}

// Create input buffer
AudioBufferList* inputBufferList = (AudioBufferList*) malloc(sizeof(AudioBufferList) * bfrs.count);
inputBufferList -> mNumberBuffers = bfrs.count;
for (int i = 0 ; i < bfrs.count ; i++) {
inputBufferList -> mBuffers[i].mNumberChannels = 1;
inputBufferList -> mBuffers[i].mDataByteSize = [[bfrs objectAtIndex:i] length];
inputBufferList -> mBuffers[i].mData = (void*) [[bfrs objectAtIndex:i] bytes];
}

// Create sound data payload
struct SoundDataPayload payload;
payload.data = inputBufferList;
payload.numPackets = inputPackets;
payload.packetDescriptions = NULL;
payload.used = NO;

// Convert data
UInt32 numPackets = outputPackets;
OSStatus err = AudioConverterFillComplexBuffer(converter, acvConverterComplexInput, &payload, &numPackets, bufferList, NULL);
if (err)
continue;

// Check how to output
if (bufferList -> mNumberBuffers > 1) {

// Output as array
NSMutableArray* array = [NSMutableArray arrayWithCapacity:bufferList -> mNumberBuffers];
for (int i = 0 ; i < bufferList -> mNumberBuffers ; i++)
[array addObject:[NSData dataWithBytes:bufferList -> mBuffers[i].mData length:bufferList -> mBuffers[i].mDataByteSize]];

// Save
[convertedBuffers addBuffer:array];

} else {

// Output as data
NSData* newData = [NSData dataWithBytes:bufferList -> mBuffers[0].mData length:bufferList -> mBuffers[0].mDataByteSize];

// Save
[convertedBuffers addBuffer:newData];

}

// Free memory
for (int i = 0 ; i < bufferList -> mNumberBuffers ; i++)
free(bufferList -> mBuffers[i].mData);

free(inputBufferList);
free(bufferList);

// Tell delegate
if (self.convertHandler)
//dispatch_async(dispatch_get_main_queue(), self.convertHandler);
self.convertHandler();

}

}

转换为 iLBC 时的格式:

// Get input format from mic
UInt32 size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription inputDesc;
AudioUnitGetProperty(self.ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &inputDesc, &size);

// Set output stream description
size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription outputDescription;
memset(&outputDescription, 0, size);
outputDescription.mFormatID = kAudioFormatiLBC;
OSStatus err = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputDescription);

从 iLBC 转换时的格式:

// Set input stream description
size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription inputDescription;
memset(&inputDescription, 0, size);
inputDescription.mFormatID = kAudioFormatiLBC;
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &inputDescription);

// Set output stream description
UInt32 size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription outputDesc;
AudioUnitGetProperty(unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outputDesc, &size);

最佳答案

您必须使用中间缓冲区从足够的传入数据包中保存足够的字节,以与音频单元输入请求的数量完全匹配。依靠任何一个压缩格式的 UDP 数据包来获得完全正确的大小是行不通的。

AudioConverter 可以缓冲样本并根据压缩格式更改数据包大小。

关于ios - AudioConverter包数错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13723384/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com