Record audio to NSData

2019-01-23 21:01发布

问题:

I have set up a TCP connection between two iPhones and I am able to send NSData packages between the two. I would like to talk into the microphone and get the recording as an NSData object and send this to the other iPhone. I have successfulyl used Audio Queue Services to record audio and play it but I have not managed to get the recording as NSData. I posted a question about converting the recording to NSData when using Audio Queue Services but it has not got me any further.

Therefore I would like to hear if there is any other approach I can take to speak into the microphone of an iPhone and have the input as raw data?

Update:

I need to send the packages continuous while recording. E.g. every second while recording I will send the data recorded during that second.

回答1:

Both Audio Queues and the RemoteIO Audio Unit will give you buffers of raw audio in real-time with fairly low latency. You can take the buffer pointer and the byte length given in each audio callback to create a new block of NSData. RemoteIO will provide the lowest latency, but may require the network messaging to be done outside the callback thread.



回答2:

Using AVAudioRecorder like this:

NSURL *filePath = //Your desired path for the file
NSDictionary *settings; //The settings for the recorded file
NSError *error = nil;
AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:filePath settings:recordSetting error:&error];
....
[recorder record];
....
[recorder stop];
....

And the retrieve the NSData from the file:

NSData *audioData = [[NSData alloc] initWithContentsOfFile:filePath];

AVAudioRecorder reference, here.

Edit:

In order to retrieve chunks of the recorded audio you could use the subdataWithRange: method in the NSData class. Keep an offset from which you wish to retrieve the bytes. You can have a NSTimer getting fired every second so you can collect the bytes and send them. You will need to find out how many bytes are getting recorded every second.



回答3:

This is what I did on the recording iphone:

void AudioInputCallback(void * inUserData,
                    AudioQueueRef inAQ,
                    AudioQueueBufferRef inBuffer,
                    const AudioTimeStamp * inStartTime,
                    UInt32 inNumberPacketDescriptions,
                    const AudioStreamPacketDescription * inPacketDescs)
{
RecordState * recordState = (RecordState*)inUserData;
if (!recordState->recording)
{
    printf("Not recording, returning\n");
}

// if (inNumberPacketDescriptions == 0 && recordState->dataFormat.mBytesPerPacket != 0)
// {
//     inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / recordState->dataFormat.mBytesPerPacket;
// }

printf("Writing buffer %lld\n", recordState->currentPacket);

OSStatus status = AudioFileWritePackets(recordState->audioFile,
                                        false,
                                        inBuffer->mAudioDataByteSize,
                                        inPacketDescs,
                                        recordState->currentPacket,
                                        &inNumberPacketDescriptions,
                                        inBuffer->mAudioData);
NSLog(@"DATA = %@",[NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataByteSize]);

[[NSNotificationCenter defaultCenter] postNotificationName:@"Recording" object:[NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataByteSize]];

if (status == 0)
{
    recordState->currentPacket += inNumberPacketDescriptions;
}

AudioQueueEnqueueBuffer(recordState->queue, inBuffer, 0, NULL);
}

I have called upon a notification which help to send data packets to the other iPhone in the network.

But I do not know how to read the data on the other side. I am still trying to figure out how that works. I will surely update once I do that.