从原始PCM 16000采样率流中使用CMSampleTimingInfo,CMSampleBuffer和AudioBufferList

时间:2017-03-10 01:14:33

标签: ios core-audio

我从外面接收音频数据和大小,音频似乎是线性PCM,签名为int16,但是当使用AssetWriter录制时,它会保存到高度失真和高音调的音频文件。

#define kSamplingRate       16000
#define kNumberChannels     1

UInt32 framesAlreadyWritten = 0;

-(AudioStreamBasicDescription) getAudioFormat {
AudioStreamBasicDescription format;
format.mSampleRate = kSamplingRate;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
format.mChannelsPerFrame = 1;  // mono
format.mBitsPerChannel = 16;
format.mBytesPerFrame = sizeof(SInt16);
format.mFramesPerPacket = 1;
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
format.mReserved = 0;
return format;
}

 - (CMSampleBufferRef)createAudioSample:(const void *)audioData frames:    (UInt32)len {

AudioStreamBasicDescription asbd = [self getAudioFormat];

CMSampleBufferRef buff = NULL;
static CMFormatDescriptionRef format = NULL;
OSStatus error = 0;

if(format == NULL) {
    AudioChannelLayout acl;
    bzero(&acl, sizeof(acl));
    acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
    error = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &asbd, sizeof(acl), &acl, 0, NULL, NULL, &format);
}

CMTime duration = CMTimeMake(1, kSamplingRate);
CMTime pts = CMTimeMake(framesAlreadyWritten, kSamplingRate);
NSLog(@"-----------pts");
CMTimeShow(pts);
CMSampleTimingInfo timing = {duration , pts, kCMTimeInvalid };
error = CMSampleBufferCreate(kCFAllocatorDefault, NULL, false, NULL, NULL, format, len, 1, &timing, 0, NULL, &buff);
framesAlreadyWritten += len;

if (error) {
    NSLog(@"CMSampleBufferCreate returned error: %ld", (long)error);
    return NULL;
}

AudioBufferList audioBufferList;
audioBufferList.mNumberBuffers = 1;
audioBufferList.mBuffers[0].mNumberChannels = asbd.mChannelsPerFrame;
audioBufferList.mBuffers[0].mDataByteSize = (UInt32)(number_of_frames * audioFormat.mBytesPerFrame);
audioBufferList.mBuffers[0].mData = audioData;

error = CMSampleBufferSetDataBufferFromAudioBufferList(buff, kCFAllocatorDefault, kCFAllocatorDefault, 0, &audioBufferList);
if(error) {
    NSLog(@"CMSampleBufferSetDataBufferFromAudioBufferList returned error: %ld", (long)error);
    return NULL;
}
return buff;
}

1 个答案:

答案 0 :(得分:1)

不确定为什么要将len除以2,但time应该进展而不是保持不变,例如

CMTime time = CMTimeMake(framesAlreadyWritten , kSamplingRate);