我正在编写一个使用CoreAudio的Audio Unit API的iOS应用,在某个时候我进行了AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, ...)调用。那时,我设置了一个断点以查看ASBD,然后发现mFormatFlags字段为41。问题是,我可以从该数字中解码出实际的标志名称(例如kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked | ...)吗?

非常感谢。

最佳答案

这是用于打印ASBD的ostream重载,主要来自Apple示例代码:

std::ostream& operator<<(std::ostream& out, const AudioStreamBasicDescription& format)
{
    unsigned char formatID [5];
    *(UInt32 *)formatID = OSSwapHostToBigInt32(format.mFormatID);
    formatID[4] = '\0';

    // General description
    out << format.mChannelsPerFrame << " ch, " << format.mSampleRate << " Hz, '" << formatID << "' (0x" << std::hex << std::setw(8) << std::setfill('0') << format.mFormatFlags << std::dec << ") ";

    if(kAudioFormatLinearPCM == format.mFormatID) {
        // Bit depth
        UInt32 fractionalBits = ((0x3f << 7)/*kLinearPCMFormatFlagsSampleFractionMask*/ & format.mFormatFlags) >> 7/*kLinearPCMFormatFlagsSampleFractionShift*/;
        if(0 < fractionalBits)
            out << (format.mBitsPerChannel - fractionalBits) << "." << fractionalBits;
        else
            out << format.mBitsPerChannel;

        out << "-bit";

        // Endianness
        bool isInterleaved = !(kAudioFormatFlagIsNonInterleaved & format.mFormatFlags);
        UInt32 interleavedChannelCount = (isInterleaved ? format.mChannelsPerFrame : 1);
        UInt32 sampleSize = (0 < format.mBytesPerFrame && 0 < interleavedChannelCount ? format.mBytesPerFrame / interleavedChannelCount : 0);
        if(1 < sampleSize)
            out << ((kLinearPCMFormatFlagIsBigEndian & format.mFormatFlags) ? " big-endian" : " little-endian");

        // Sign
        bool isInteger = !(kLinearPCMFormatFlagIsFloat & format.mFormatFlags);
        if(isInteger)
            out << ((kLinearPCMFormatFlagIsSignedInteger & format.mFormatFlags) ? " signed" : " unsigned");

        // Integer or floating
        out << (isInteger ? " integer" : " float");

        // Packedness
        if(0 < sampleSize && ((sampleSize << 3) != format.mBitsPerChannel))
            out << ((kLinearPCMFormatFlagIsPacked & format.mFormatFlags) ? ", packed in " : ", unpacked in ") << sampleSize << " bytes";

        // Alignment
        if((0 < sampleSize && ((sampleSize << 3) != format.mBitsPerChannel)) || (0 != (format.mBitsPerChannel & 7)))
            out << ((kLinearPCMFormatFlagIsAlignedHigh & format.mFormatFlags) ? " high-aligned" : " low-aligned");

        if(!isInterleaved)
            out << ", deinterleaved";
    }
    else if(kAudioFormatAppleLossless == format.mFormatID) {
        UInt32 sourceBitDepth = 0;
        switch(format.mFormatFlags) {
            case kAppleLosslessFormatFlag_16BitSourceData:      sourceBitDepth = 16;    break;
            case kAppleLosslessFormatFlag_20BitSourceData:      sourceBitDepth = 20;    break;
            case kAppleLosslessFormatFlag_24BitSourceData:      sourceBitDepth = 24;    break;
            case kAppleLosslessFormatFlag_32BitSourceData:      sourceBitDepth = 32;    break;
        }

        if(0 != sourceBitDepth)
            out << "from " << sourceBitDepth << "-bit source, ";
        else
            out << "from UNKNOWN source bit depth, ";

        out << format.mFramesPerPacket << " frames/packet";
    }
    else
        out << format.mBitsPerChannel << " bits/channel, " << format.mBytesPerPacket << " bytes/packet, " << format.mFramesPerPacket << " frames/packet, " << format.mBytesPerFrame << " bytes/frame";

    return out;
}

08-19 12:18