线性 PCM 16 位到 8 位

Posted

技术标签:

【中文标题】线性 PCM 16 位到 8 位【英文标题】:Linear PCM 16 bit to 8 bit 【发布时间】:2013-08-20 14:14:51 【问题描述】:

我正在尝试采用标题为“SpeakHere”的 Apple 示例的录音部分来实现我的目的。一切似乎都很好,但我需要添加一个实际上提供 8 位录制的选项。 这是根据任何音频设置都不允许的规范,所以我需要从 16 位进行某种转换。 我想我需要把它放在回调函数中。

// ____________________________________________________________________________________
// AudioQueue callback function, called when an input buffers has been filled.
void AQRecorder::MyInputBufferHandler(  void *                              inUserData,
                                        AudioQueueRef                       inAQ,
                                        AudioQueueBufferRef                 inBuffer,
                                        const AudioTimeStamp *              inStartTime,
                                        UInt32                              inNumPackets,
                                        const AudiostreamPacketDescription* inPacketDesc)

    AQRecorder *aqr = (AQRecorder *)inUserData;
    try 
        if (inNumPackets > 0) 
            // write packets to file
            XThrowIfError(AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize,
                                             inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData),
                       "AudioFileWritePackets failed");
            aqr->mRecordPacket += inNumPackets;
        

        // if we're not stopping, re-enqueue the buffe so that it gets filled again
        if (aqr->IsRunning())
            XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed");
     catch (CAXException e) 
        char buf[256];
        fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
    

但说实话不知道怎么做。任何想法将不胜感激。

【问题讨论】:

我认为您只需将每个样本除以 256。我不熟悉样本中使用的抽象和数据结构,但如果您可以获得原始 PCM 数据,您只需处理每两个字节作为signed short int 并将每个字节除以256 并写入signed chars 的缓冲区。当然,您仍然必须创建正确的元数据以表明您的数据是每个样本 PCM 音频 8 位。 【参考方案1】:

你为什么不尝试用类似的东西来初始化你的音频队列?

    aqData.mDataFormat.mFormatID = kAudioFormatLinearPCM;        // 2
    aqData.mDataFormat.mSampleRate = 44100.0;                    // 3
    aqData.mDataFormat.mChannelsPerFrame = 1;                    // 4
    aqData.mDataFormat.mBitsPerChannel = 8;                     // 5
    aqData.mDataFormat.mBytesPerPacket =                         // 6
    aqData.mDataFormat.mBytesPerFrame =
    aqData.mDataFormat.mChannelsPerFrame * sizeof (SInt8);
    aqData.mDataFormat.mFramesPerPacket = 1;                     // 7

    AudioFileTypeID fileType = kAudioFileAIFFType;               // 8
    aqData.mDataFormat.mFormatFlags =                            // 9
    kLinearPCMFormatFlagIsBigEndian
    | kLinearPCMFormatFlagIsSignedInteger
    | kLinearPCMFormatFlagIsPacked; 

【讨论】:

所有 CAF 解析器都应支持线性 PCM 音频的以下变体: 任何采样率 16、24 和 32 位有符号整数的样本,包括大端和小端的样本32 位和 64 位浮点,包括大端和小端【参考方案2】:

经过一番调查和尝试,我发现我不需要转换,只需要设置不同的格式标志。

mRecordFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian; mRecordFormat.mBitsPerChannel = 8;

【讨论】:

以上是关于线性 PCM 16 位到 8 位的主要内容,如果未能解决你的问题,请参考以下文章

从线性 PCM 中提取音频通道

交错立体声 PCM 线性 Int16 大端音频是啥样的?

在 iPhone 上从线性 PCM 中提取幅度数据

将 PCM 16 位音频转换为 PCM 8 位

NEON 加速 12 位到 8 位

PCM音频实时播放:音频字节数组(16/8位)转为PCM ArrayBuffer流