对于OpenAL的可可加载.wav文件 [英] Load .wav file for OpenAL in Cocoa

查看:439
本文介绍了对于OpenAL的可可加载.wav文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要的声音文件加载到一个基于Cocoa的OpenAL的应用程序。

I need to load sound files to a Cocoa-based OpenAL app.

进展:


  • 的OpenAL的效用函数alutLoadWAVFile已经去precated;该ALUT头不再包含在Mac OS X的SDK。根据该技术说明,实际code是仍然存在的二进制兼容性。但是,如果我尝试添加该功能的声明中,code编译但链接程序将中止,抱怨对alutLoadWAVFile符号找不到。 (我链接到OpenAL.framework)。

  • The OpenAL utility function alutLoadWAVFile has been deprecated; the alut header is no longer included in Mac OS X SDKs. According to the TechNotes, the actual code is still there for binary compatibility. However, if I attempt to add a declaration for the function, the code will compile but the linker will abort, complaining that the symbol for alutLoadWAVFile could not be found. (I am linking to the OpenAL.framework).

然而,苹果公司的OpenAL样品code仍然使用这个符号。当我清洁样品code项目,它编译和链接就好了。然而,没有函数的声明中被发现。 (方的问题:它如何能够建立和链接,然后)

Yet, Apple OpenAL sample code still uses this symbol. When I Clean the sample code project, it compiles and links just fine. Yet there is no declaration of the function to be found. (Side question: how can it build and link, then?)

所以,我发现乔治华纳约code。在苹果,含更换功能alutCreateBufferFromFile和alutLoadMemoryFromFile。虽然能够直接从最创建的OpenAL缓冲区中的任何一种音频文件时,code似乎只支持8位单声道声音文件。 16位立体声或单声道44kHz的文件可能会导致一个讨厌的嘶嘶声和剪裁。 (这些文件都OK;的QuickTime播放这些就好了。)

So, I found some code by George Warner at Apple, containing replacement functions for alutCreateBufferFromFile and alutLoadMemoryFromFile. Although capable of creating an OpenAL buffer directly from most any kind of audio file, the code appears to support only 8bit mono sound files. 16bit stereo or mono 44khz files result in a nasty hissing sound and clipping. (The files are ok; Quicktime plays them just fine.)

因此​​,我的问题:可有人请点我的可可/碳一些.WAV装载code /帮助,适合与OpenAL的缓冲?三江源。

Thus, my question: can someone please point me to some .wav loading code/help for Cocoa/Carbon, suitable for use with an OpenAL Buffer? Thankyou.

推荐答案

我敢肯定你已经解决了这一点,但对于谁通过谷歌找到这个人,这里的一些勉强测试WAV装载code。它的工作原理,但你最好仔细检查内存泄漏和诸如此类的东西使用真实的东西了。

I'm sure you've solved this already, but for people who find this via Google, here's some barely tested WAV loading code. It works but you'd better double check for memory leaks and whatnot before using for something real.

static bool LoadWAVFile(const char* filename, ALenum* format, ALvoid** data, ALsizei* size, ALsizei* freq, Float64* estimatedDurationOut)
{
    CFStringRef filenameStr = CFStringCreateWithCString( NULL, filename, kCFStringEncodingUTF8 );
    CFURLRef url = CFURLCreateWithFileSystemPath( NULL, filenameStr, kCFURLPOSIXPathStyle, false );
    CFRelease( filenameStr );

    AudioFileID audioFile;
    OSStatus error = AudioFileOpenURL( url, kAudioFileReadPermission, kAudioFileWAVEType, &audioFile );
    CFRelease( url );

    if ( error != noErr )
    {
        fprintf( stderr, "Error opening audio file. %d\n", error );
        return false;
    }

    AudioStreamBasicDescription basicDescription;
    UInt32 propertySize = sizeof(basicDescription);
    error = AudioFileGetProperty( audioFile, kAudioFilePropertyDataFormat, &propertySize, &basicDescription );

    if ( error != noErr )
    {
        fprintf( stderr, "Error reading audio file basic description. %d\n", error );
        AudioFileClose( audioFile );
        return false;
    }

    if ( basicDescription.mFormatID != kAudioFormatLinearPCM )
    {
        // Need PCM for Open AL. WAVs are (I believe) by definition PCM, so this check isn't necessary. It's just here
        // in case I ever use this with another audio format.
        fprintf( stderr, "Audio file is not linear-PCM. %d\n", basicDescription.mFormatID );
        AudioFileClose( audioFile );
        return false;
    }

    UInt64 audioDataByteCount = 0;
    propertySize = sizeof(audioDataByteCount);
    error = AudioFileGetProperty( audioFile, kAudioFilePropertyAudioDataByteCount, &propertySize, &audioDataByteCount );
    if ( error != noErr )
    {
        fprintf( stderr, "Error reading audio file byte count. %d\n", error );
        AudioFileClose( audioFile );
        return false;
    }

    Float64 estimatedDuration = 0;
    propertySize = sizeof(estimatedDuration);
    error = AudioFileGetProperty( audioFile, kAudioFilePropertyEstimatedDuration, &propertySize, &estimatedDuration );
    if ( error != noErr )
    {
        fprintf( stderr, "Error reading estimated duration of audio file. %d\n", error );
        AudioFileClose( audioFile );
        return false;
    }

    ALenum alFormat = 0;

    if ( basicDescription.mChannelsPerFrame == 1 )
    {
        if ( basicDescription.mBitsPerChannel == 8 )
            alFormat = AL_FORMAT_MONO8;
        else if ( basicDescription.mBitsPerChannel == 16 )
            alFormat = AL_FORMAT_MONO16;
        else
        {
            fprintf( stderr, "Expected 8 or 16 bits for the mono channel but got %d\n", basicDescription.mBitsPerChannel );
            AudioFileClose( audioFile );
            return false;
        }

    }
    else if ( basicDescription.mChannelsPerFrame == 2 )
    {
        if ( basicDescription.mBitsPerChannel == 8 )
            alFormat = AL_FORMAT_STEREO8;
        else if ( basicDescription.mBitsPerChannel == 16 )
            alFormat = AL_FORMAT_STEREO16;
        else
        {
            fprintf( stderr, "Expected 8 or 16 bits per channel but got %d\n", basicDescription.mBitsPerChannel );
            AudioFileClose( audioFile );
            return false;
        }
    }
    else
    {
        fprintf( stderr, "Expected 1 or 2 channels in audio file but got %d\n", basicDescription.mChannelsPerFrame );
        AudioFileClose( audioFile );
        return false;
    }

    UInt32 numBytesToRead = audioDataByteCount;
    void* buffer = malloc( numBytesToRead );

    if ( buffer == NULL )
    {
        fprintf( stderr, "Error allocating buffer for audio data of size %u\n", numBytesToRead );
        return false;
    }

    error = AudioFileReadBytes( audioFile, false, 0, &numBytesToRead, buffer );
    AudioFileClose( audioFile );

    if ( error != noErr )
    {
        fprintf( stderr, "Error reading audio bytes. %d\n", error );
        free(buffer);
        return false;
    }

    if ( numBytesToRead != audioDataByteCount )
    {
        fprintf( stderr, "Tried to read %lld bytes from the audio file but only got %d bytes\n", audioDataByteCount, numBytesToRead );
        free(buffer);
        return false;
    }

    *freq = basicDescription.mSampleRate;
    *size = audioDataByteCount;
    *format = alFormat;
    *data = buffer;
    *estimatedDurationOut = estimatedDuration;

    return true;
}

这篇关于对于OpenAL的可可加载.wav文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆