0

Folks i have been searching and trying to resolve following problem since a whole day. No success yet

Ok, So i have been using apple sample code project name WiTap to communicate b/w two devices over wifi using NSInputStreams and NSOutputStreams I have been able to transfer data (audio data) b/w devices successfully.

However on the destination device i receive data and fill it in an audio buffer as follows:

bytesRead = [self.inputStream read:anAudioBuffer.mData maxLength:anAudioBuffer.mDataByteSize];

while anAudioBuffer itself is declared as follows

anAudioBuffer.mNumberChannels = 1;
anAudioBuffer.mDataByteSize = 512 * 2;
anAudioBuffer.mData = malloc( 512 * 2 );

Now i access this audio buffer as someObject.anAudioBuffer in the AudioUnit Callback from the Apple's sample code

which is as follows

static OSStatus playbackCallback(void *inRefCon, 
                                 AudioUnitRenderActionFlags *ioActionFlags, 
                                 const AudioTimeStamp *inTimeStamp, 
                                 UInt32 inBusNumber, 
                                 UInt32 inNumberFrames, 
                                 AudioBufferList *ioData) {    
    // Notes: ioData contains buffers (may be more than one!)
    // Fill them up as much as you can. Remember to set the size value in each buffer to match how
    // much data is in the buffer.

    for (int i=0; i < ioData->mNumberBuffers; i++) { // in practice we will only ever have 1 buffer, since audio format is mono
        AudioBuffer buffer = ioData->mBuffers[i];

        // copy temporary buffer data to output buffer
        UInt32 size = min(buffer.mDataByteSize, someObject.anAudioBuffer.mDataByteSize); // dont copy more data then we have, or then fits
        memcpy(buffer.mData, someObject.anAudioBuffer.mData, size);
        buffer.mDataByteSize = size; // indicate how much data we wrote in the buffer

        // uncomment to hear random noise
        /*
        UInt16 *frameBuffer = buffer.mData;
        for (int j = 0; j < inNumberFrames; j++) {
            frameBuffer[j] = arc4random();
        }
        */

    }

    return noErr;
}

Now i want to play the bytes that i copied from someObject.anAudioBuffer into a local var buffer

I do note that the this section of the code has to do with playing the audio

/*
 UInt16 *frameBuffer = buffer.mData;
 for (int j = 0; j < inNumberFrames; j++) {
    frameBuffer[j] = arc4random();
 }
*/

now the arc4random is used to play static noise. With best of my efforts and searching all over the internet i could not figure out how to play my own bytes and also this piece of code b/w /* */

e.g what is the purpose of this line?

UInt16 *frameBuffer = buffer.mData;

and how do i fill this frameBuffer with my own data to play.

Can anybody please guide me. Too much of my time is wasted on this seemingly trivial problem.

I can provide more detail, if required.

Waiting in anticipation...

Umair
  • 400
  • 5
  • 19

2 Answers2

0

You have to fill the memory (or array) pointed to by mBuffer.mData[0] with exactly inNumberFrames of audio sample frames (whether you have those samples available or not). You do this in your noise generator, but not in your memcopy code.

Also leave mDataByteSize unchanged, as it is an input to the callback, not an inout. An audio callback is a demand, not an optional request.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • my data from the source is filled in `someObject.anAudioBuffer` Can you guide how do i accomplish the filling task i.e filling the `frameBuffer[j]` – Umair Aug 22 '16 at 14:50
  • Same way you did in your for loop, except using data from someObject instead of rnd(). – hotpaw2 Aug 22 '16 at 15:10
  • sorry if i am sounding too novice, but what i gather that you are suggesting this in loop `frameBuffer[j] = someObject.anAudioBuffer.mData` if that is the case, i am still unsuccessful – Umair Aug 22 '16 at 15:17
  • Did you want to copy the samples in = ...mData[j] ? – hotpaw2 Aug 23 '16 at 03:49
  • as `frameBuffer = buffer.mData;` so as a result we need to write audio data in frameBuffer[j], No? i have my data as bytes in `someObject.anAudioBuffer.mData` – Umair Aug 23 '16 at 07:42
0

So i have found the Answer

It was simple but i had no knowledge of reading C pointer arrays. All i had to do was:

 UInt16 *frameBuffer = buffer.mData;
 for (int j = 0; j < inNumberFrames; j++) {
    frameBuffer[j] = *(frameBuffer + j);
 }

While this UInt16 *frameBuffer = buffer.mData; makes frameBuffer point to starting index of buffer.mData, the following

*(frameBuffer + j); is C's way of reading the next pointer.

After writing frameBuffer[j] = *(frameBuffer + j); my audio from stream plays like a charm.

Will be glad to know if this helped some other too.

Found C pointer arrays info from here

Umair
  • 400
  • 5
  • 19
  • 1
    It did help. at first was not making sense for me and still isnt compltly clear for whats happening and how i got it to work. For me it worked when i switched it to this. frameBuffer[j] = frameBuffer[+j]; Thanks! – Charlie Nov 28 '18 at 21:01