2017-03-10 366 views
1

我从外部接收音频数据和大小,音频看起来像是线性PCM,带符号int16,但是当使用AssetWriter录制时,它会保存到音频文件中扭曲和更高的音调。从原始PCM 16000采样率流使用CMSampleTimingInfo,CMSampleBuffer和AudioBufferList

#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

不知道为什么你将len两个人,但你应该time进步的而不是恒定的,像

CMTime time = CMTimeMake(framesAlreadyWritten , kSamplingRate); 
+0

我添加此,还是同样的问题 UInt32的framesAlreadyWritten = 0; CMTime时间= CMTimeMake(framesAlreadyWritten,kSamplingRate); CMSampleTimingInfo定时= {CMTimeMake(1,kSamplingRate),时间,kCMTimeInvalid}; error = CMSampleBufferCreate framesAlreadyWritten + = len; – crossle

+0

为什么仍然应该是'len/2'?不应该是'len'? –

+0

这应该错误,时间是一个点,需要生成一个进度时间 – crossle