上一篇, 主要总结的是数据发送(音频播放)的实现
接下来,我们来说一下数据接收。音频的数据接收主要就是录音的操作,对输入数据进行解析,将波形数据转化为字节码
这个主要取决于算法,实现的方法有很多,大家可以自由发挥
好了,老规矩,还是上代码吧〜〜〜
//
// MFAudioRecorder.h
// audiotest
//
// Created by Chen Jiaqi(winton.chen@gmail.com) on 15/3/19.
// Copyright (c) 2015年 MoreFun-et. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef int (*MFAudioRecvFunc)(char *data, int datalen);
//#define MF_DEBUG_RECORDER
// use Audio Queue
#define kNumberBuffers 3
#define kDataBufferSize (2 * 1024 * 1024)
typedef struct AQCallbackStruct
{
AudioStreamBasicDescription mDataFormat;
AudioQueueRef queue;
AudioQueueBufferRef mBuffers[kNumberBuffers];
AudioFileID outputFile;
UInt32 frameSize;
long long recPtr;
int run;
} AQCallbackStruct;
@interface MFAudioRecorder: NSObject
{
AQCallbackStruct aqc;
AudioFileTypeID fileFormat;
long audioDataLength;
#ifdef MF_DEBUG_RECORDER
Byte audioByte[kDataBufferSize];
#endif
long audioDataIndex;
MFAudioRecvFunc recvFunc;
//NSTimer *recvTimer;
}
-(id) init;
-(void) start;
-(void) stop;
-(void) pause;
#ifdef MF_DEBUG_RECORDER
-(Byte *) getBytes;
#endif
-(void) setRecvFunc: (MFAudioRecvFunc)func;
-(void) dealloc;
@property (nonatomic, assign) AQCallbackStruct aqc;
@property (nonatomic, assign) long audioDataLength;
@end
//
// MFAudioRecorder.mm
// audiotest
//
// Created by Chen Jiaqi(winton.chen@gmail.com) on 15/3/19.
// Copyright (c) 2015年 MoreFun-et. All rights reserved.
//
#import "MFAudioRecorder.h"
#import "MFAudioConstant.h"
#include "MFAudioDecode.h"
static MFAudioDecode audioDecode;
@implementation MFAudioRecorder
@synthesize aqc;
@synthesize audioDataLength;
static void AQInputCallback (void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDescs)
{
MFAudioRecorder *engine = (__bridge MFAudioRecorder *) inUserData;
if (inNumPackets > 0) {
[engine processAudioBuffer:inBuffer withQueue: inAQ];
}
if (engine.aqc.run) {
AudioQueueEnqueueBuffer(engine.aqc.queue, inBuffer, 0, NULL);
}
}
-(id) init
{
self = [super init];
if (self) {
aqc.mDataFormat.mSampleRate = SAMPLE_RATE;
aqc.mDataFormat.mFormatID = kAudioFormatLinearPCM;
aqc.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |kLinearPCMFormatFlagIsPacked;
aqc.mDataFormat.mFramesPerPacket = 1;
aqc.mDataFormat.mChannelsPerFrame = NUM_CHANNELS;
aqc.mDataFormat.mBitsPerChannel = BITS_PER_CHANNEL;
aqc.mDataFormat.mBytesPerPacket = BYTES_PER_FRAME;
aqc.mDataFormat.mBytesPerFrame = BYTES_PER_FRAME;
aqc.frameSize = 0x400;
// create the queue
AudioQueueNewInput(&aqc.mDataFormat, AQInputCallback, (__bridge void *)(self), NULL, kCFRunLoopCommonModes,0, &aqc.queue);
for (int i=0;i<kNumberBuffers;i++) {
AudioQueueAllocateBuffer(aqc.queue, aqc.frameSize, &aqc.mBuffers[i]);
AudioQueueEnqueueBuffer(aqc.queue, aqc.mBuffers[i], 0, NULL);
}
aqc.recPtr = 0;
aqc.run = 0;
audioDataIndex = 0;
//recvTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(checkDecoder) userInfo:nil repeats:YES];
}
return self;
}
- (void) dealloc
{
printf("MFAudioRecorder dealloc.\n");
AudioQueueStop(aqc.queue, true);
aqc.run = 0;
AudioQueueDispose(aqc.queue, true);
}
- (void) start
{
printf("MFAudioRecorder start.\n");
audioDataIndex = 0;
aqc.run = 1;
AudioQueueStart(aqc.queue, NULL);
}
- (void) stop
{
printf("MFAudioRecorder stop.\n");
aqc.run = 0;
AudioQueueStop(aqc.queue, true);
}
- (void) pause
{
printf("MFAudioRecorder pause.\n");
aqc.run = 0;
AudioQueuePause(aqc.queue);
}
-(void) setRecvFunc: (MFAudioRecvFunc)func
{
recvFunc = func;
}
#ifdef MF_DEBUG_RECORDER
- (Byte *)getBytes
{
return audioByte;
}
#endif
-(void) checkDecoder
{
if (aqc.run) {
if (audioDecode.getDecodeStatus() == 1) {
// decode finish
//printf("decode finish\n");
audioDecode.resetDecodeStatus();
if (recvFunc) {
recvFunc(audioDecode.getDecodeBuffer(), audioDecode.getDecodeLength());
}
}
}
}
- (void) processAudioBuffer:(AudioQueueBufferRef) buffer withQueue:(AudioQueueRef) queue
{
//printf("processAudioData :%d\n", buffer->mAudioDataByteSize);
audioDecode.decode((const SAMPLE *)buffer->mAudioData, buffer->mAudioDataByteSize / 2);
[self checkDecoder];
#ifdef MF_DEBUG_RECORDER
if (kDataBufferSize - audioDataIndex > buffer->mAudioDataByteSize) {
memcpy(audioByte+audioDataIndex, buffer->mAudioData, buffer->mAudioDataByteSize);
audioDataIndex += buffer->mAudioDataByteSize;
audioDataLength = audioDataIndex;
} else {
printf("record full...\n");
audioDataIndex = audioDataLength = 0;
}
#endif
}
@end