首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ios核心音频:如何从带有交错音频的AudioBuffer中获取示例

ios核心音频:如何从带有交错音频的AudioBuffer中获取示例
EN

Stack Overflow用户
提问于 2016-06-26 13:12:22
回答 2查看 1.9K关注 0票数 2

我用AudioBufferList函数将一个音频文件读取到ExtAudioFileRead中。

这是和ASBD的音频:

代码语言:javascript
复制
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];

因此,我们得到并交织了两个通道的音频,每个通道有16位签名int。

AudioBufferList init:

代码语言:javascript
复制
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;

读入缓冲器:

代码语言:javascript
复制
CheckError(ExtAudioFileRead (
                             audioFileObject,
                             &numberOfPacketsToRead,
                             bufferList), "error ExtAudioFileRead");

audioFileObject是和ExtAudioFileRef的实例,它是在前面的代码中启动的,我在这里没有粘贴它以节省空间。

我试图完成的是修改我的呈现回调中的音频示例。

代码语言:javascript
复制
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;

}

是否有可能从音频数据的Sint16数组中获取UInt32左右通道的样本?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-26 21:57:25

audioDataframeBuffer都是SInt16的:

代码语言:javascript
复制
SInt16 *audioData;
// ...
SInt16 *frameBuffer;

您的缓冲区大小计算应该是n * 2 * sizeof(SInt16) and you'll either need to change照管结构或添加类型转换。

然后,您可以访问交错样本,如下所示:

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2016-06-26 23:37:44

@有节奏的Fistman,非常感谢--这很有帮助。

不过,我无法设置frameBuffer以这样的方式工作。声音在输出时失真了。

我想这是因为AudioUnit希望将两个通道数据放在一个帧中。或许还有别的解释。

下面是我修改的代码,希望它能帮助到某人:

audioData init:

代码语言:javascript
复制
SInt16 *audioData = (SInt16 *) malloc (sizeof(SInt16) * totalFramesInFile * 2);

修改后的呈现回调:

代码语言:javascript
复制
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;

    SInt16 *audioData   = soundStruct->audioData;

    UInt32 sampleNumber = soundStruct->sampleNumber;

    for( int i = 0; i < ioData->mNumberBuffers; i++){
        AudioBuffer buffer = ioData->mBuffers[i];
        SInt16 *frameBuffer = (SInt16*) ioData->mBuffers[0].mData;

        for(UInt32 frame = 0; frame < inNumberFrames * 2; frame+=2) {

            /* .. some samples modification code .. */

            // left channel
            frameBuffer[frame] = audioData[sampleNumber];
            // right channel
            frameBuffer[frame + 1] = audioData[sampleNumber + 1];

            sampleNumber +=2;

            if(sampleNumber > frameTotalForSound * 2) {
                soundStruct->isPlaying = false;
                AudioOutputUnitStop(soundStruct->outputUnit);
            }
        }
    }

    soundStruct->sampleNumber = sampleNumber;
    return noErr;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38038822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档