Vinay
Vinay

Reputation: 1

audio Streaming AVFoundation using Audio Queues/ buffer in iOS

I need to do audio streaming in an iOS app using Objective C. I have used AVFoundation framework and capture the raw data from microphone and send to sever. However raw data which I am receiving is corrupt, Below is my code.

Please suggest me where I am doing wrong.

session = [[AVCaptureSession alloc] init];

NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                [NSNumber numberWithFloat:16000.0], AVSampleRateKey,
                                [NSNumber numberWithInt: 1],AVNumberOfChannelsKey,
                                [NSNumber numberWithInt:32], AVLinearPCMBitDepthKey,
                                [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
                                [NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey,
                                [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                nil];


AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
[session addInput:audioInput];

AVCaptureAudioDataOutput *audioDataOutput = [[AVCaptureAudioDataOutput alloc] init];
dispatch_queue_t audioQueue = dispatch_queue_create("AudioQueue", NULL);
[audioDataOutput setSampleBufferDelegate:self queue:audioQueue];

AVAssetWriterInput *_assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:recordSettings];
_assetWriterVideoInput.performsMultiPassEncodingIfSupported = YES;

if([session canAddOutput:audioDataOutput] ){
    [session addOutput:audioDataOutput];
}
[session startRunning];

Capturing:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    AudioBufferList audioBufferList;
    NSMutableData *data= [NSMutableData data];
    CMBlockBufferRef blockBuffer;
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer);

    for( int y=0; y< audioBufferList.mNumberBuffers; y++ ){

        AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
        Float32 *frame = (Float32*)audioBuffer.mData;
        [data appendBytes:frame length:audioBuffer.mDataByteSize];

        NSString *base64Encoded = [data base64EncodedStringWithOptions:0];
        NSLog(@"Encoded: %@", base64Encoded);

    }

    CFRelease(blockBuffer);
}

Upvotes: 0

Views: 605

Answers (1)

James Bush
James Bush

Reputation: 1527

I posted a sample of the kind of code you need to make this work. Its approach is nearly the same as yours. You should be able to read it easily.

The app uses AudioUnit to record and playback microphone input and speaker output, NSNetServices to connect two iOS devices on your network, and NSStreams to send an audio stream between the devices.

You can download the source code at:

https://drive.google.com/open?id=1tKgVl0X92SYvgpvbljRzilXNQ6iBcjqM

It requires the latest Xcode 9 beta release to compile, and the latest iOS 11 beta release to run it.

NOTE | A log entry for each method call and event is displayed in a textfield that encompasses the entire screen; there is no interactive interface—no buttons, etc. After installing the app on two iOS devices, simply launch it on both devices to automatically connect to your network and start streaming audio.

enter image description here

Upvotes: 1

Related Questions