【发布时间】:2016-06-26 13:12:22
【问题描述】:
我已使用ExtAudioFileRead 函数将音频文件读入AudioBufferList。
这是音频的 ASBD:
AudioStreamBasicDescription importFormat;
importFormat.mFormatID = kAudioFormatLinearPCM;
importFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
importFormat.mBytesPerPacket = 4;
importFormat.mFramesPerPacket = 1;
importFormat.mBytesPerFrame = 4;
importFormat.mChannelsPerFrame = 2;
importFormat.mBitsPerChannel = 16;
importFormat.mSampleRate = [[AVAudioSession sharedInstance] sampleRate];
所以我们得到并交错了 2 个通道的音频,每个通道有 16 位有符号 intAudioBufferList init:
UInt32 *audioData = (UInt32 *) calloc (totalFramesInFile, sizeof (UInt32));
AudioBufferList *bufferList;
bufferList = (AudioBufferList *) malloc (sizeof (AudioBufferList));
// buffers amount is 1 because audio is interleaved
bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mNumberChannels = 2;
bufferList->mBuffers[0].mDataByteSize = totalFramesInFile * sizeof(UInt32);
bufferList->mBuffers[0].mData = audioData;
并读入缓冲区:
CheckError(ExtAudioFileRead (
audioFileObject,
&numberOfPacketsToRead,
bufferList), "error ExtAudioFileRead");
audioFileObject 是 ExtAudioFileRef 的实例,它是在前面的代码中启动的,为了节省空间我没有粘贴到这里。
我想要完成的是在我的渲染回调中修改音频样本。
OSStatus MyCallback (void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData){
ViewController *view = (__bridge ViewController *) inRefCon;
soundStruct *soundStruct = (soundStruct *) &view->mys;
SInt64 frameTotalForSound = soundStruct->frameCount;
soundStruct->isPlaying = true;
UInt32 *audioData = soundStruct->audioData;
UInt32 sampleNumber = soundStruct->sampleNumber;
for( int i = 0; i < ioData->mNumberBuffers; i++){
AudioBuffer buffer = ioData->mBuffers[i];
UInt32 *frameBuffer = buffer.mData;
for(UInt32 frame = 0; frame < inNumberFrames; frame++) {
// here I fill the buffer with my audio data.
// i need to get left and right channel samples
// from audioData[sampleNumber], modify them
// and write into frameBuffer
frameBuffer[frame] = audioData[sampleNumber];
sampleNumber++;
if(sampleNumber > frameTotalForSound) {
soundStruct->isPlaying = false;
AudioOutputUnitStop(soundStruct->outputUnit);
}
}
}
soundStruct->sampleNumber = sampleNumber;
return noErr;
}
是否可以从 UInt32 音频数据数组中获取 Sint16 左右声道样本?
【问题讨论】:
-
我不确定我是否理解您的问题:您的程序正在生成交错式
UInt32格式的音频数据,并希望将其实时转换为非交错式SInt16播放? -
@user3078414,不完全是。我根本不想转换。我有一个音频文件,其中包含交错音频和每个通道的
SInt16值。目标是将其写入AudioBufferList并保存在内存中。当 RemoteIO AudioUnit 请求新的声音部分时会触发此渲染回调,并且我希望实时修改每个通道的样本。因为有 2 个通道 - 我将样本存储在UInt32数组中。我不确定这是否是正确的调用,因为我不知道如何在稍后的回调中提取样本。 -
这是我的answer 与类似但略有不同的问题:输出 - 写入文件需要单个交错缓冲区,而 AU 产生非交错缓冲区。我也看到了您的问题的答案 - 对最里面的实时循环中的索引乘法要小心……
[2*(n-1)+1]有利于演示清晰 - 我宁愿使用[n+n-1]代替。 (-:
标签: ios core-audio audiobuffer