最近项目需求,使用蓝牙传输语音,并且集成到已有的直播SDK中。
汗本人对蓝牙一知半解,加油研究吧。先将手机连上蓝牙音箱,然后开启手机本地的录制视频,发现蓝牙的声音并不能被录到视频中,汗,看来苹果自带的摄像机并没有把蓝牙集成进来,好吧我们能做的只有,从苹果相机获取视频,从可识别蓝牙的麦克风中,获取蓝牙音频。
废话有点多直接上代码了。
AVAudioSession中很好的集成了蓝牙获取
使用AVAudioSession可以获取蓝牙音频。
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&error];
使用AudioQueue可以获取音频流。
这里做下解释,AVAudioSession 只是将音频的输入设备指向了蓝牙而已,AudioQueue 用于从麦克风获取声音。
typedef struct AQCallbackStruct
{
AudioStreamBasicDescription mDataFormat;
AudioQueueRef queue;
AudioQueueBufferRef mBuffers[kNumberBuffers];
AudioFileID outputFile;
unsigned long frameSize;
long long recPtr;
int run;
} AQCallbackStruct;
// Audio Settings
#define kNumberBuffers 3
#define kSamplingRate 44100
#define t_sample SInt16
#define kNumberChannels 1
#define kBitsPerChannels (sizeof(t_sample) * 8)
#define kBytesPerFrame (kNumberChannels * sizeof(t_sample))
//#define kFrameSize (kSamplingRate * sizeof(t_sample))
#define kFrameSize 4096
#define QUEUE_BUFFER_SIZE 2//队列缓冲个数
#define EVERY_READ_LENGTH 10240 //每次从文件读取的长度
#define MIN_SIZE_PER_FRAME 10240 //每侦最小数据长度
@property (nonatomic, assign) AQCallbackStruct aqc;
- (void) startGetAudio
{
aqc.mDataFormat.mSampleRate = kSamplingRate;
aqc.mDataFormat.mFormatID = kAudioFormatLinearPCM;
aqc.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |kLinearPCMFormatFlagIsPacked;
aqc.mDataFormat.mFramesPerPacket = 1;
aqc.mDataFormat.mChannelsPerFrame = kNumberChannels;
aqc.mDataFormat.mBitsPerChannel = kBitsPerChannels;
aqc.mDataFormat.mBytesPerPacket = kBytesPerFrame;
aqc.mDataFormat.mBytesPerFrame = kBytesPerFrame;
aqc.frameSize = kFrameSize;
AudioQueueNewInput(&aqc.mDataFormat, AQInputCallback, (__bridge void *)(self), NULL, kCFRunLoopCommonModes, 0, &aqc.queue);
// AudioQueueNewInput(&aqc.mDataFormat, AQInputCallback, (__bridge void *)(self), NULL, kCFRunLoopCommonModes,0, &aqc.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 );
AudioQueueEnqueueBuffer(aqc.queue, aqc.mBuffers, 0, NULL);
}
aqc.recPtr = 0;
aqc.run = 1;
audioDataIndex = 0;
AudioQueueStart(aqc.queue, NULL);
}
回调方法AQInputCallback中可以获取到音频数据 inBuffer
static void AQInputCallback (void * inUserData,
AudioQueueRef inAudioQueue,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp * inStartTime,
unsigned long inNumPackets,
const AudioStreamPacketDescription * inPacketDesc)
{
NSLog(@"AQInputCallback");
Record * engine = (__bridge Record *) inUserData;
if (inNumPackets > 0)
{
[engine processAudioBuffer:inBuffer withQueue:inAudioQueue];
}
if (engine.aqc.run)
{
AudioQueueEnqueueBuffer(engine.aqc.queue, inBuffer, 0, NULL);
}
}
参考了【iOS录音与播放】实现利用音频队列,通过缓存进行对声音的采集与播放
下载地址 http://download.csdn.net/detail/yp2049858/9550554