美文网首页音视频技术
从CMSampleBufferRef中提取PCM数据

从CMSampleBufferRef中提取PCM数据

作者: starmier | 来源:发表于2019-06-02 16:44 被阅读0次

从CMSampleBufferRef中提取PCM数据

脉冲编码调制,其实是将不规则的模拟信号转换成数字信号,这样就可以通过物理介质存储起来。
而声音也是一种特定频率(20-20000HZ)的模拟信号,也可以通过这种技术转换成数字信号,从而保存下来。
PCM格式,就是录制声音时,保存的最原始的声音数据格式。比如 wav格式的音频,它其实就是给PCM数据流加上一段header数据,就成为了wav格式。而wav格式有时候之所以被称为无损格式,就是因为他保存的是原始pcm数据(也跟采样率和比特率有关)。像我们耳熟能详的那些音频格式,mp3,aac等等,都是有损压缩,为了节约占用空间,在很少损失音效的基础上,进行最大程度的压缩。
所有的音频编码器,都支持pcm编码,而且录制的声音,默认也是PCM格式,所以我们下一步就是要获取录制的PCM数据。

-(NSData *) convertAudioSmapleBufferToPcmData:(CMSampleBufferRef) audioSample{

AudioStreamBasicDescription inAudioStreamBasicDescription = *CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)CMSampleBufferGetFormatDescription(pcmData));
    
//获取CMBlockBufferRef
    CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(pcmData);
//获取pcm数据大小
    size_t length = CMBlockBufferGetDataLength(blockBufferRef);
    
//分配空间
    char buffer[length];
//直接将数据copy至我们自己分配的内存中
    CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, buffer);
    
    if ((inAudioStreamBasicDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagIsBigEndian)
    {
        for (int i = 0; i < length; i += 2)
        {
            char tmp = buffer[i];
            buffer[i] = buffer[i+1];
            buffer[i+1] = tmp;
        }
    }
    
    uint32_t ch = inAudioStreamBasicDescription.mChannelsPerFrame;
    uint32_t fs = inAudioStreamBasicDescription.mSampleRate;

    //返回数据
    return [NSData dataWithBytesNoCopy:buffer length:audioDataSize];
}

PCM填充CMSampleBufferRef

根据采样精度我们可以知道一个采样点的数据量,比如16位精度,即一个采样点需要2子节,则有200ms需要的数据量为:

//200ms 采样点数量
NSUInteger samples = self->mSampleRate * 200 * self->mChannelsPerFrame/1000;
//200ms pcm数量量
int len = samples*2;

PCM填充CMSampleBufferRef 代码示例:

- (CMSampleBufferRef)createAudioSampleBuffer:(char*) buf withLen:(int) len withASBD:(AudioStreamBasicDescription) asbd{
    
    AudioBufferList audioData;
    audioData.mNumberBuffers = 1;
    char* tmp = malloc(len);
    memcpy(tmp, buf, len);
    
    audioData.mBuffers[0].mData = tmp;
    audioData.mBuffers[0].mNumberChannels = asbd.mChannelsPerFrame;
    audioData.mBuffers[0].mDataByteSize = len;
    
    
    CMSampleBufferRef buff = NULL;
    CMFormatDescriptionRef format =NULL;
    OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &asbd,0, NULL, 0, NULL, NULL, &format);
    
    if (status) {
        return nil;
    }
    CMSampleTimingInfo timing = {CMTimeMake(asbd.mFramesPerPacket,asbd.mSampleRate), kCMTimeZero, kCMTimeInvalid };
    
    
    status = CMSampleBufferCreate(kCFAllocatorDefault,NULL, false,NULL, NULL, format, (CMItemCount)asbd.mFramesPerPacket,1, &timing, 0,NULL, &buff);
    
    if (status) { //失败
        return nil;
    }
    
    status = CMSampleBufferSetDataBufferFromAudioBufferList(buff,kCFAllocatorDefault,kCFAllocatorDefault,0, &audioData);
    
    if (tmp) {
        free(tmp);
    }
    CFRelease(format);
    
    return buff;
}

相关文章

  • 从CMSampleBufferRef中提取PCM数据

    从CMSampleBufferRef中提取PCM数据 脉冲编码调制,其实是将不规则的模拟信号转换成数字信号,这样就...

  • PCM音频数据

    目录 什么是PCM? PCM数据格式 FFmpeg支持的PCM数据格式 FFmpeg中Packed和Planar的...

  • FFmpeg处理原始数据

    这里的原始数据指的是FFmpeg解码后的数据,对于音频就是PCM数据,对于视频就是YUV数据。 FFmpeg提取Y...

  • libyuv NV12镜像

    从CMSampleBufferRef中取出NV12数据,转换为i420,对i420数据做镜像,然后把镜像的i420...

  • AudioToolBox 解码AAC

    上一篇文章中,我们针对PCM 数据,通过AudioToolBox将PCM 数据编码成AAC 数据,并把AAC 数据...

  • Android音视频开发-入门(二)

    目标任务 使用AudioRecord 采集PCM数据 使用AudioTrack API播放PCM音频 将Pcm数据...

  • 数据提取之JSON

    数据提取 什么是数据提取? 简单的来说,数据提取就是从响应中获取我们想要的数据的过程 数据分类 非结构化的数据:h...

  • FFmpeg分离出PCM数据

    本文将使用FFmpeg从mp4/aac/mp3等包含音频流的多媒体文件中提取PCM数据保存到本地。 一、使用命令行...

  • CMSampleBufferRef

    CMSampleBufferRef转换为data数据 - (NSData *)bufferToData:(CMSa...

  • SQL 命令

    SELECT - 从数据库中提取数据 UPDATE - 更新数据库中的数据 DELETE - 从数据库中删除数据 ...

网友评论

    本文标题:从CMSampleBufferRef中提取PCM数据

    本文链接:https://www.haomeiwen.com/subject/ldwxxctx.html