1

I have found 3-4 examples which show usage of Remote IO Audio Units. like here, here etc. They covert the analog audio data from iPhone microphone and digitize them and then play them back. Upto this point everything works fine and now I have a good understanding of Audio Units.

Now, rather then playing back the recorded audio stored in AudioBufferList on the same device, I want to stream it to another device.

Below is how I'm converting AudioBufferList to nsdata and send it to another device.

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject:@(bufferList->mNumberBuffers) forKey:@"buffersCount"];


NSMutableArray *buffers = [NSMutableArray array];
for ( int i=0; i< bufferList->mNumberBuffers; i++ ) {
    NSData *data = [NSData dataWithBytes:bufferList->mBuffers[i].mData length:bufferList->mBuffers[i].mDataByteSize];
    NSDictionary *obj = @{@"data":data, @"channels":@(bufferList->mBuffers[i].mNumberChannels)};
    [buffers addObject:obj];
}
[dict setValue:buffers forKey:@"buffers"];

NSData *packet = [NSKeyedArchiver archivedDataWithRootObject:dict];

Below is how I'm converting nsdata back to AudioBufferList on the receiving device and copying it to tempBuffer which is then played.

NSDictionary *dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:voiceData];

int numberOfBuffers = [dict[@"buffersCount"] intValue];

AudioBufferList *audio = malloc(sizeof(AudioBufferList) + (numberOfBuffers-1)*sizeof(AudioBuffer));
if ( !audio ) {
    return;
}

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

    NSLog(@"Buffer %d has %d channels and wants %d bytes of data.", i, (unsigned int)buffer.mNumberChannels, buffer.mDataByteSize);

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

But on the other device I'm not able to hear anything.

Please guide as to what might be wrong.

iAmd
  • 812
  • 1
  • 12
  • 22
  • Debug by inspecting and comparing the count and actual samples of audio sent with those received (NSLog or whatever). Then test your tempBuffer play routine by filling it with known sine waves. – hotpaw2 May 20 '14 at 07:07
  • I have debugged the code and found that there is a difference in the data which I'm sending from the source and the one I'm receiving at the destination. Can you explain how an NSData is converted back to AudioBufferList properly? – iAmd May 20 '14 at 10:34

2 Answers2

1

You didn't retrieve any data from the dictionary, just the number of buffers.

    NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    NSLog(@"%@", dict);

    int numberOfBuffers = [dict[@"buffersCount"] intValue];
    NSLog(@"%d", numberOfBuffers);

    AudioBufferList *audioBufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList));
    if (NULL == audioBufferList) {
        NSLog(@"*** malloc failure for allocating audioBufferList memory");
        return;
    }
    audioBufferList->mNumberBuffers = (int)dict[@"buffersCount"];

    for(NSDictionary *obj in dict[@"buffers"]){
        NSMutableData *data = [NSMutableData dataWithData:obj[@"data"]];
        audioBufferList->mBuffers[0].mNumberChannels = (int)obj[@"channels"];
        audioBufferList->mBuffers[0].mDataByteSize = (int)[data length];
        audioBufferList->mBuffers[0].mData = (AudioBuffer *)malloc([data length]);

        if (NULL == audioBufferList->mBuffers[0].mData) {
            NSLog(@"*** malloc failure for allocating mData memory");
            return;
        }
        memcpy(audioBufferList->mBuffers[0].mData, [data mutableBytes], [data length]);

        NSLog(@"Buffer has %d channels and wants %d bytes of data.", (unsigned int)audioBufferList->mBuffers[0].mNumberChannels, (unsigned int)audioBufferList->mBuffers[0].mDataByteSize);
    }
keji
  • 5,947
  • 3
  • 31
  • 47
0

There are a number of ways to open a network connection between two devices. You want to do this and simply package up the data in whatever format you desire to get it from device A to device B.

Start here: http://nshipster.com/multipeer-connectivity/

nsdebug
  • 364
  • 2
  • 8
  • I am able to open a network connection between two devices and also send data from one device to the other. What I'm not able to achieve is to play voice on the other device. I have edited my question. Please see if I can be assisted. – iAmd May 20 '14 at 05:48