OGeek|极客世界-中国程序员成长平台

标题: ios核心音频: how to get samples from AudioBuffer with interleaved audio [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-12 20:51
标题: ios核心音频: how to get samples from AudioBuffer with interleaved audio

我已使用 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 个 channel 的交错音频,每个 channel 有 16 位有符号整数
AudioBufferList 初始化:

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");

audioFileObjectExtAudioFileRef 的实例,它在前面的代码中启动,我没有粘贴到这里以节省空间。
我想要完成的是在我的渲染回调中修改音频样本。

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 左右声道样本?



Best Answer-推荐答案


audioDataframeBuffer都是SInt16s:

SInt16 *audioData;
// ...
SInt16 *frameBuffer;

您的缓冲区大小计算应该是 n * 2 * sizeof(SInt16) 并且您需要更改soundStruct` 或添加类型转换。

然后你可以像这样访问交错的样本:

frameBuffer[0] = modify(audioData[0]);    // left sample 1
frameBuffer[1] = modify(audioData[1]);    // right sample 1
frameBuffer[2] = modify(audioData[2]);    // left sample 2
frameBuffer[3] = modify(audioData[3]);    // right sample 2
// ...
frameBuffer[2*(n-1)] = modify(audioData[2*(n-1)]);    // left sample n
frameBuffer[2*(n-1)+1] = modify(audioData[2*(n-1)+1]); // right sample n

关于ios核心音频: how to get samples from AudioBuffer with interleaved audio,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38038822/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://sqlite.in/) Powered by Discuz! X3.4