remoteIO how to play it? - objective-c

i manage to get the recordCallBck and deal with the buffer data.
now i want to play that data.
i have the play callback but i just cant find anywhere how to play this buffers.
callback:
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
for (int i = 0 ; i < ioData->mNumberBuffers; i++){
AudioBuffer buffer = ioData->mBuffers[i];
unsigned char *frameBuffer = buffer.mData;
now what?
how would i play that?

have a look at this example, helped me out a lot when trying to deal with the data. This is an example of a working app that plays anything you have spoken into the microphone. It uses 2 callbacks, one for recording the data and placing in a global audio buffer and a second for getting that data back into the playback callback.
http://www.stefanpopp.de/2011/capture-iphone-microphone/

Related

Using RemoteIO gives unreasonable buffers value and sizes

Using the callback function on the iphone , i am trying get microphone input signal.
After so much problems i have discover this :
When i input to the buffer a pure sin wave (to the mac simulator ) i can see the signal, but then, it becomes lower and lower till zero .
I was thinking that this is relate to apple's bug ,that the number of buffer's samples on the mac is 471 instead of 1024 . can i solve this bug somehow ???
This is my callback :
static OSStatus recordingCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
AudioBuffer buffer;
buffer.mNumberChannels = 1;
buffer.mDataByteSize = inNumberFrames * 2; //* sizeof(SInt16) ?
buffer.mData = NULL;
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0] = buffer;
OSStatus status;
status = AudioUnitRender(audioUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
&bufferList);
int16_t *q = (int16_t *)(&bufferList)->mBuffers[0].mData;
//here i print q,which is good for 4 seconds-when i can see the pure sin, than it goes down to zero-while sin wave is still in the air
EDIT:
this is not happening on the device, only on the mac !
i am pretty sure its related to the bug that the mac see 417 samples in the buffer !

Cliks and distortions in Lame encoded Mp3 file

I'm trying to encode the raw PCM data from microphone to MP3 using AudioToolbox framework and Lame. And although everything seems to run fine, there is this problem with "clicks" and "distortions" present in the encoded stream.
I'm not sure that I setup AudioQueue correctly and also that I process the encoded buffer in the right wat...
My code to setup audio recording:
AudioStreamBasicDescription streamFormat;
memset(&streamFormat, 0, sizeof(AudioStreamBasicDescription));
streamFormat.mSampleRate = 44100;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger|kLinearPCMFormatFlagIsPacked;
streamFormat.mBitsPerChannel = 16;
streamFormat.mChannelsPerFrame = 1;
streamFormat.mBytesPerPacket = 2;
streamFormat.mBytesPerFrame = 2;
streamFormat.mFramesPerPacket = 1;
streamFormat.mReserved = 0;
AudioQueueNewInput(&streamFormat, InputBufferCallback, (__bridge void*)(self), nil, nil, 0, &mQueue);
UInt32 bufferByteSize = 44100;
memset(&mEncodedBuffer, 0, sizeof(mEncodedBuffer)); //mEncoded buffer is
//unsigned char [72000]
AudioQueueBufferRef buffer;
for (int i=0; i<3; i++) {
AudioQueueAllocateBuffer(mQueue, bufferByteSize, &buffer);
AudioQueueEnqueueBuffer(mQueue, buffer, 0, NULL);
}
AudioQueueStart(mQueue, nil);
Then the AudioQueue callback function calls to lame_encode_buffer and then writes the encoded buffer to file:
void InputBufferCallback (void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription* inPacketDesc) {
memset(&mEncodedBuffer, 0, sizeof(mEncodedBuffer));
int encodedBytes = lame_encode_buffer(glf, (short*)inBuffer->mAudioData, NULL, inBuffer->mAudioDataByteSize, mEncodedBuffer, 72000);
//What I don't understand is that if I write the full 'encodedBytes' data, then there are A LOT of distortions and original sound is seriously broken
NSData* data = [NSData dataWithBytes:mEncodedBuffer length:encodedBytes/2];
[mOutputFile writeData:data];
}
And when I afterward try to play the file which contains Lame encoded data with AVAudioPlayer I clearly hear original sound but with some clicks and distortions around.
Can anybody advise what's wrong here?
Your code does not appear to be paying attention to inNumPackets, which is the amount of actual audio data given the callback.
Also, doing a long operation, such as running an encoder, inside an audio callback might not be fast enough and thus may violate response requirements. Any long function calls should be done outside the callback.

Removing Last Buffer Played From Memory

I have an Objective-C audio app based on audio unit and my problem is when I play a sound then stop it then play another sound I hear the last buffer from the first sound. I think I should just free the ioData or something but all my tries have failed.
static OSStatus playbackCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
RemoteIOPlayer *remoteIOplayer = (__bridge RemoteIOPlayer *)inRefCon;
for (int i = 0 ; i < ioData->mNumberBuffers; i++)
{
AudioBuffer buffer = ioData->mBuffers[i];
UInt32 *frameBuffer = buffer.mData;
for (int j = 0; j < inNumberFrames; j++)
{
frameBuffer[j]= [[remoteIOplayer inMemoryAudioFile] getNextPacket:inBusNumber];
}
}
return noErr;
}
Please help :) Thanks.
Ok its just about UNintializing the augraph and initializing it again after the user stops

core audio callback, inTimeStamp at the beginning or end of recording

In core audio, when the recordingCallback is called:
static OSStatus recordingCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
does inTimeStamp reference the time when the audio began to be received or the time when the audio was finished being received.
was it
X if X is equal to the time when recording began
or
X + the buffer length
thank you,
nonono
The timestamp is for the time when the buffer was captured, specifically the bus time of the system (see this thread on the CoreAudio mailing list for details). So it would refer to the time in the first sample of the buffer, not the last sample.

Manipulating audio data in C++ for DSP purposes

I hope this question is not too vague. I'm trying to take info from an audio buffer in this Xcode project and use it to do some DSP.
framebuffer points to an array of values that I would like to pass to a function, loop through and finally plug into the original buffer. The method would act like a sound filter or effect.
Maybe to keep my question as clear as possible, could we get an example of a sub-routine that would add 0.25 to each sample in the buffer?
Here's the code so far:
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
EAGLView *remoteIOplayer = (EAGLView *)inRefCon;
for (int i = 0 ; i < ioData->mNumberBuffers; i++){
//get the buffer to be filled
AudioBuffer buffer = ioData->mBuffers[i];
short *frameBuffer = (short*)buffer.mData;
for (int j = 0; j < inNumberFrames; j++){
// get NextPacket returns a 32 bit value, one frame.
frameBuffer[j] = [[remoteIOplayer inMemoryAudioFile] getNextPacket];
}
EAGLView* thisView = [[EAGLView alloc] init];
[thisView DoStuffWithTheRecordedAudio:ioData];
[thisView release];
}
return noErr;
}
Trying to do UI or Open GL stuff inside an audio callback is a bad idea on iOS devices. You need to decouple the callback and UI execution using queues or fifos, and the like.
Trying to do Objective C messaging inside the inner loop of real-time audio may also a very bad idea in term of device performance. Sticking to plain C/C++ works far better in performance critical inner loops.
Also, adding a constant to audio data will likely just result in an inaudible DC offset.