代码之家  ›  专栏  ›  技术社区  ›  mahboudz

extaudiofileconvert问题

  •  1
  • mahboudz  · 技术社区  · 15 年前

    我在获取压缩(MP3)声音并将其保存为PCM方面取得了一些进展。另外,我想在同一个过程中将原始文件分割成2秒长的块。我看起来很成功,但我有点困惑为什么。

    当我读取音频块并写出文件时,我会检查是否要写一个块,使我的文件超过2秒的限制。如果是这样的话,我写的足够多,可以达到2秒,关闭文件,然后打开一个新文件,将剩余部分写入新文件,然后读取更多数据。像这样:

    framesInTimedSegment += numFrames;
    if ((framesInTimedSegment  > (2.0 * sampleRate)) && (j < 5)) {
        UInt32 newNumFrames = numFrames;
        numFrames = framesInTimedSegment - (2.0 * sampleRate);
        newNumFrames -= numFrames;
    // Question A
        UInt32 segmentOffset = newNumFrames * numChannels * 2;
        error = ExtAudioFileWrite(segmentFile, newNumFrames, &fillBufList);
    // Question B
           // handle this error!  We might have an interruption
        if (segmentFile) ExtAudioFileDispose(segmentFile);
        XThrowIfError(ExtAudioFileCreateWithURL(urlArray[++j], kAudioFileCAFType, &dstFormat, NULL, kAudioFileFlags_EraseFile, &breakoutFile), "ExtAudioFileCreateWithURL failed! - segmentFile");
        size = sizeof(clientFormat);
        XThrowIfError(ExtAudioFileSetProperty(segmentFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat), "couldn't set destination client format"); 
        fillBufList.mBuffers[0].mData = srcBuffer + segmentOffset;
        fillBufList.mBuffers[0].mDataByteSize = numFrames * fillBufList.mBuffers[0].mNumberChannels * 2;
        framesInTimedSegment = numFrames;
    }
    error = ExtAudioFileWrite(segmentFile, numFrames, &fillBufList);
    

    以下是我的问题(我已尝试在相关行上加上标签):

    A:有没有更好的方法可以找到缓冲区中的偏移量,这样我就不会在缓冲区中错误地硬编码某个值?例如,是否有一种幸运的方法可以从帧号获得数据偏移量?

    B:如果extaudiofilewrite正在进行从压缩到解压缩的转换,那么我正在写的数据还没有被解压缩(对吗?)在处理压缩数据时,我不应该担心使用帧编号和偏移量吗?我应该先将文件转换为PCM文件还是内存,然后再拆分该PCM?

    谢谢!

    -马布德

    PS。

    客户端格式定义如下:

            clientFormat = dstFormat;
    

    和DSTFrase:

            dstFormat.mFormatID = outputFormat;
            dstFormat.mChannelsPerFrame = srcFormat.NumberChannels();
            dstFormat.mBitsPerChannel = 16;
            dstFormat.mBytesPerPacket = dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame;
            dstFormat.mFramesPerPacket = 1;
            dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; // little-endian
    
    1 回复  |  直到 15 年前
        1
  •  2
  •   sbooth    15 年前

    如果看不到更多的代码,很难正确回答。但是,假设clientformat是交错的pcm格式:

    b)extaudiofilewrite不执行从压缩到解压缩的转换,extaudiofileread执行转换,这取决于您设置的客户机格式。假设一个MP3源文件和一个“标准”的16位44.1 kHz的PCM客户机格式,对extaudiofileread的调用将从MP3字节转换为PCM数据。这是通过使用audiofile和audioConverter API在引擎盖下完成的。

    a)如果看不到srcbuffer是如何定义的,这就有点难回答(我假设一个int16_t数组)。如果您使用的是PCM数据,您所做的操作看起来正常。您也可以使用newNumFrames*clientFormat.mbytesperframe*clientFormat.mchannelsPerframe,但假设为16位PCM数据,mbytesperframe==mbytesperpacket==2。如果您使用的是非CBR数据,那么您需要关注数据包描述,但情况似乎并非如此。