我正在尝试将mp3文件加载到ios的OpenAL缓冲区中,并且已经从示例中复制了一些代码。

因此,使用此代码:

    CFURLRef fileURL = nil;
    NSString* nsPath = [CDUtilities fullPathFromRelativePath:[NSString stringWithUTF8String:FilePath.c_str()]];

    if (nsPath) {
        fileURL = (CFURLRef)[[NSURL fileURLWithPath:nsPath] retain];
    }

#if 0
    status = AudioFileOpenURL (fileURL, kAudioFileReadPermission, kAudioFileMP3Type, &AudioFileHandle );
    ExtAudioFileWrapAudioFileID ( AudioFileHandle, false, &ExtAudioFileHandle );

    // Close the AudioFile handle. It's no longer needed
    AudioFileClose ( AudioFileHandle );
    AudioFileHandle = nullptr;

#else
    status = ExtAudioFileOpenURL ( fileURL, &ExtAudioFileHandle );
#endif

    // Get the audio data format
    UInt32 PropertySize = sizeof ( InputDataFormat );
    status = ExtAudioFileGetProperty ( ExtAudioFileHandle, kExtAudioFileProperty_FileDataFormat, &PropertySize, &InputDataFormat);
    if (status != noErr)
    {
        DecodeResult = false;
        goto function_exit;
    }

    if ( InputDataFormat.mChannelsPerFrame > 2 )
    {
        DecodeResult = false;
        goto function_exit;
    }

    // Set the client format to 16 bit signed integer (native-endian) data
    // Maintain the channel count and sample rate of the original source format
    OutputDataFormat.mSampleRate = InputDataFormat.mSampleRate;
    OutputDataFormat.mChannelsPerFrame = InputDataFormat.mChannelsPerFrame;

    OutputDataFormat.mFormatID = kAudioFormatLinearPCM;
    OutputDataFormat.mBytesPerPacket = 2 * InputDataFormat.mChannelsPerFrame;
    OutputDataFormat.mFramesPerPacket = 1;
    OutputDataFormat.mBytesPerFrame = 2 * InputDataFormat.mChannelsPerFrame;
    OutputDataFormat.mBitsPerChannel = 16;
    OutputDataFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;

    // Set the desired client (output) data format
    status = ExtAudioFileSetProperty ( ExtAudioFileHandle, kExtAudioFileProperty_ClientDataFormat, sizeof ( OutputDataFormat ), &OutputDataFormat );
    if (status != noErr)
    {
        DecodeResult = false;
        goto function_exit;
    }

    // Get the total frame count
    PropertySize = sizeof ( FrameCount );
    status = ExtAudioFileGetProperty ( ExtAudioFileHandle, kExtAudioFileProperty_FileLengthFrames, &PropertySize, &FrameCount );
    if (status != noErr)
    {
        DecodeResult = false;
        goto function_exit;
    }

在该#if中,如果我将其切换为1,它将以音频文件的形式打开mp3,然后将其转换为ExtAudioFile,否则,它将以ExtAudioFile的形式直接打开。

在第一种情况下,由于某种原因,以后使用kExtAudioFileProperty_FileLengthFrames调用ExtAudioFileGetProperty失败,并带有0xffffffda。到目前为止,一切正常。如果我从一开始就以ExtAudioFile的形式打开它,那么一切正常。

我需要将其作为AudioFile打开,因为我实际上是在使用AudioFileOpenWithCallbacks从缓冲区读取数据(我已经有了另一种将文件加载到缓冲区中的机制)。如果有人知道从缓冲区获取ExtAudioFile的其他方法,或者甚至将MP3缓冲区转换为PCM的方法,请共享:)

为什么当我以AudioFile打开并转换它时却失败,而当我直接以ExtAudioFile打开时却没有失败?

最佳答案

好的,所以我找到了答案。显然完全与我在某些示例中看到的相反,您无法在将原始句柄转换为ExtAudioFile后释放它。我将那个AudioFileClose代码移到了函数的末尾,突然一切正常。我只是想知道为什么其他所有东西都继续使用封闭的句柄,但不是那个特定的属性得到了,而是……苹果的奥秘:)

10-06 01:52