If I just take every other 16 bits like so for the second (right) channel, which I think you're suggesting:
I still get really chunky data, jumping noisily between -1, -.5, 0, .5 and 1. I have a debugging routine to graph the data and it looks much different than the sine wave I see from the Simulator.
(lldb) frame variable floatSamples
(float *) floatSamples = 0x03eaa000 [0,0,0,-1.00003,-1.00003,-1.00003,0.500015,0,-0.500015,0.500015,0.500015,-1.00003,0,0,0,-1.00003,-1.00003,0,-1.00003,0,0,0,0,0,0,-1.00003,-1.00003,-1.00003,0,-0.500015,-1.00003,-1.00003,0.500015,0.500015,-1.00003,0,0,0,-1.00003,-1.00003,0,0,0,0,0,0,0,-1.00003,0,-1.00003,-0.500015,-0.500015,-0.500015,-1.00003,0.500015,-0.500015,-0.500015,-0.500015,-1.00003,0,0,0,0,-1.00003]
This is my whole messy render callback in case it makes things clearer. I'd also love to hear if I'm doing something else wrong.
extern OSStatus tonallyAnalyzeCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 L, // was inNumberFrames
AudioBufferList *ioData) {
if (*ioActionFlags & kAudioUnitRenderAction_PostRender) {
// Cast to our tracking struct
TonallyAudioAnalyzerStruct *taas = (TonallyAudioAnalyzerStruct *) inRefCon;
float* floatSamples = taas->analyzeBuffer;
float* scratchBuffer = taas->scratchBuffer;
for (int i=0; i < ioData->mNumberBuffers; i++) {
short channels = ioData->mBuffers[i].mNumberChannels;
short bytesPerChannel = taas->asbd.mBytesPerFrame / taas->asbd.mChannelsPerFrame;
SInt16* samples = (SInt16*)(ioData->mBuffers[i].mData);
// Convert native SInt16 (short) to floats so we can use more vector math functions
if (channels == 1) {
// vDSP_vflt16(samples, 1, floatSamples, 1, L);
vDSP_vflt16(samples + bytesPerChannel // pointer arithmetic for the beginning of the second channel
, 2, floatSamples, 1, L);
}
// If it's stereo, convert to mono.
// Add in the second channel and divide by 2 so the amplitudes aren't doubled.
else {
vDSP_vflt16(samples, 2, floatSamples, 1, L);
vDSP_vflt16(samples + bytesPerChannel // pointer arithmetic for the beginning of the second channel
, 2, scratchBuffer, 1, L);
float monoScale = 0.5;
// Add vectors and multiply scalar in one fell swoop.
vDSP_vasm(floatSamples, 1, scratchBuffer, 1, &monoScale, floatSamples, 1, L);
}
// Scale from 0 to 1 by dividing by the max int value
float scaleMax = INT16_MAX;
vDSP_vsdiv(floatSamples, 1, &scaleMax, floatSamples, 1, L);
TPCircularBuffer* ringBuffer = &taas->buffer;
// NSLog(@"Jamming %ld frames OF FLOATS into the circular buffer.", L);
int numBytesFedToRingBuf = L * sizeof(float);
TPCircularBufferProduceBytes(ringBuffer, floatSamples, numBytesFedToRingBuf);
// Notify we can read out of the ring buffer.
// Is this okay? It seems to work.
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kTAAHasAudioNotification object: nil];
});
// Let the audio play in test mode
if (taas->inputType == kTAAInputTypeLive) {
// Silence the output of the audio unit
// memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
zeroBuffer(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize);
}
}
// Is this okay? It seems to work.
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kTACAudioUpdatedNotification object: nil];
});
}
return noErr;
}