IOS语音采集(采集数据大小对齐算法)

语音采集碰到一个问题,设定每次采集大小320个字节,采集到的数据偶尔会小于320个字节,导致把数据放入压缩库压缩时候会出现杂音问题。
pc android采集没发现这个情况,所以ios需要对语音数据对齐分切,经过测试能正常压缩语音数据,能清晰播放出来。

ios头文件
Recorder.h
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>


#define RECORDER_NOTIFICATION_CALLBACK_NAME @"recorderNotificationCallBackName"
#define kNumberAudioQueueBuffers 3 //缓冲区设定3个
#define kDefaultSampleRate 8000    //采样率

@interface Recorder : NSObject
{
    AudioQueueRef _audioQueue;
    AudioStreamBasicDescription audioFormat;
    AudioQueueBufferRef _audioBuffers[kNumberAudioQueueBuffers];
    char data[1024];
    int offset;

}

@property (nonatomic, assign) BOOL isRecording;
@property (atomic, assign) NSUInteger sampleRate;
-(void)start;

-(void)stop;


@end

Recorder.m

#import "Recorder.h"

@implementation Recorder
- (id)init
{
    self = [super init];
    if (self) {

        self.sampleRate = kDefaultSampleRate;

        //设置录音 初始化录音参数
        [self setupAudioFormat:kAudioFormatLinearPCM SampleRate:(int)self.sampleRate];

    }
    return self;
}
//设置录音 初始化录音参数
- (void)setupAudioFormat:(UInt32)inFormatID SampleRate:(int)sampeleRate
{

    memset(&audioFormat, 0, sizeof(audioFormat));


    audioFormat.mSampleRate = sampeleRate;//采样率

    audioFormat.mChannelsPerFrame = 1;//单声道

    audioFormat.mFormatID = inFormatID;//采集pcm 格式
    audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
    audioFormat.mBitsPerChannel = 16;//每个通道采集2个byte
    audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame = (audioFormat.mBitsPerChannel / 8) * audioFormat.mChannelsPerFrame;
    audioFormat.mFramesPerPacket = 1;

}

//回调函数 不断采集声音。
void inputHandler(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime,UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc)
{

    Recorder *recorder = (__bridge Recorder*)inUserData;

    int k = 0;
    if (inBuffer->mAudioDataByteSize > 0) { 
        memcpy(recorder->data+recorder->offset,inBuffer->mAudioData,inBuffer->mAudioDataByteSize);//通过recorder->offset 偏移把语音数据存入recorder->data

        recorder->offset+=inBuffer->mAudioDataByteSize;//记录语音数据的大小

        k = recorder->offset/320;//计算语音数据有多个320个字节语音

        for(int i = 0; i <k; i++)
        {

            NSData *SpeechData = [[NSData alloc]initWithBytes:recorder->data+i*320 length:320];//把recorder->data 数据以320个字节分切放入 传出的数组中。
            [[NSNotificationCenter defaultCenter] postNotificationName:RECORDER_NOTIFICATION_CALLBACK_NAME object:SpeechData];
        }

        memcpy(recorder->data,recorder->data+k*320,recorder->offset-(k*320));//把剩下的语音数据放入原来的数组中

        recorder->offset-=(k*320);//计算剩下的语音数据大小


    }

    if (recorder.isRecording) {

        AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);

    }

}
//开始录音
-(void)start
{
    NSError *error = nil;

    //录音的设置和初始化
    BOOL ret = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
    if (!ret) {
        return;
    }

    //启用audio session
    ret = [[AVAudioSession sharedInstance] setActive:YES error:&error];
    if (!ret)
    {
        return;
    }


    //初始化缓冲语音数据数组
    memset(data,0,1024); 
    offset = 0;
    audioFormat.mSampleRate = self.sampleRate;
    //初始化音频输入队列
    AudioQueueNewInput(&audioFormat, inputHandler, (__bridge void *)(self), NULL, NULL, 0, &_audioQueue);

    int bufferByteSize = 320; //设定采集一帧320个字节

    //创建缓冲器
    for (int i = 0; i < kNumberAudioQueueBuffers; ++i){
        AudioQueueAllocateBuffer(_audioQueue, bufferByteSize, &_audioBuffers[i]);
        AudioQueueEnqueueBuffer(_audioQueue, _audioBuffers[i], 0, NULL);
    }

    //开始录音
    AudioQueueStart(_audioQueue, NULL);
    self.isRecording = YES;
}

//结束录音
-(void)stop
{
    if (self.isRecording) {
        self.isRecording = NO;
        AudioQueueStop(_audioQueue, true);
        AudioQueueDispose(_audioQueue, true);
         [[AVAudioSession sharedInstance] setActive:NO error:nil];
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    }
}


@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值