how to properly fill a stereo AudioBuffer

核能气质少年 提交于 2019-12-23 01:46:05

问题


so i'm using Apple's MixerHost sample code to do a basic audiograph setup for stereo synthesis. I have some trouble figuring out how i have to fill the buffer slice. Specifically, i get audio out only in the left channel, the right channel is silent:

AudioUnitSampleType *buffer = (AudioUnitSampleType *)ioData->mBuffers[0].mData;    
SInt16 sampleValue;

for(UInt32 i = 0; i < inNumberFrames; i++)
{
    sampleValue = sinf(inc) * 32767.0f; // generate sine signal
    inc += .08;

    buffer[i] = sampleValue;
}

if(inc > 2e10) inc -= 2e10;

This plays a sine wave on the left channel... The pitch kind of changes every 10 seconds or so, another indicator that i'm doing it wrong :]

i've tried other ways of stepping through the array. this produced interesting sounds which were far from a sine signal. At one point i had glitchy/choppy output on both channels, which was kind of like a success.

If i inspect the AudioBuffer struct, it confirms there are 2 channels, and the bytesize per frame is 4. So per frame, there are two SInt16, right? One for left, and one for the right channel.. and they are supposed to be interleaved?

Note that i am using a stream format that is different from Apple's example because i don't know fixed point math.

The stream format is setup like so:

size_t bytesPerSample = sizeof (AudioUnitSampleType);

stereoStreamFormat.mFormatID          = kAudioFormatLinearPCM;
stereoStreamFormat.mFormatFlags       = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
stereoStreamFormat.mBytesPerPacket    = bytesPerSample;
stereoStreamFormat.mFramesPerPacket   = 1;
stereoStreamFormat.mBytesPerFrame     = bytesPerSample;
stereoStreamFormat.mChannelsPerFrame  = 2;                    
stereoStreamFormat.mBitsPerChannel    = 8 * bytesPerSample;
stereoStreamFormat.mSampleRate        = graphSampleRate;

so my question is, how do i fill a stereo buffer which is setup like above with data so that it just works?

thanks!


回答1:


Take a look at Classes/MixerHostAudio.m in the MixerHost example, and scroll down to where they define and assign outSamplesChannelLeft and outSamplesChannelRight. It looks like the API expects left and right samples in different buffers, not interleaved.

As for the changing pitch, try

if (inc > M_PI) inc -= 2.0*M_PI;

(or whatever Apple defines in place of M_PI) and do this within the loop, not after filling the whole frame. Floating point error accumulates surprisingly quickly. The correction above uses the fact that sin is periodic over 2*pi. Your correction arbitrarily wraps inc back in, and will cause a glitch at the wrap point if the wrapping isn't phase continuous.

And finally, it's not clear to me if your bytesPerSample is 2 or not, you might want to check this. If it is, then I'd guess your other assumption about bytesPerFrame is correct.




回答2:


You are setting mBytesPerFrame = bytesPerSample. This only allows one sample per frame. For interleaved stereo (i.e. mChannelsPerFrame = 2) you need two samples per frame. Try setting mBytesPerFrame = 2 * bytesPerSample.

In your render function:

UInt32 numOfSamples = 2 * inNumberFrames;
for (i = 0; i < numOfSamples; i+=2) {
 buffer[i] = //assign left channel value;
 buffer[i+1] = //assign right channel value;
}


来源:https://stackoverflow.com/questions/6091500/how-to-properly-fill-a-stereo-audiobuffer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!