如何在iPhone上使用OpenAL播放循环声音 [英] How to play looping sound with OpenAL on iPhone

查看:108
本文介绍了如何在iPhone上使用OpenAL播放循环声音的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注有关使用OpenAL播放声音的教程.现在一切正常,除了我无法使声音循环播放.我相信我已经使用AL_LOOPING作为来源.现在,它只能播放一次,播放完毕后,该应用将被阻止(对我在播放按钮上的点击无响应).关于代码有什么问题的任何想法吗?

I'm following a tutorial about playing sound with OpenAL. Now everything works fine except I can't make the sound looping. I believe that I've used AL_LOOPING for the source. Now it can only play once and when it finishes playing, the app will block(doesn't response to my tap on the play button). Any ideas about what's wrong with the code?

// start up openAL
// init device and context
-(void)initOpenAL
{
    // Initialization
    mDevice = alcOpenDevice(NULL); // select the "preferred device"
    if (mDevice) {
        // use the device to make a context
        mContext = alcCreateContext(mDevice, NULL);
        // set my context to the currently active one
        alcMakeContextCurrent(mContext);
    }
}


// open the audio file
// returns a big audio ID struct
-(AudioFileID)openAudioFile:(NSString*)filePath
{
    AudioFileID outAFID;
    // use the NSURl instead of a cfurlref cuz it is easier
    NSURL * afUrl = [NSURL fileURLWithPath:filePath];

    // do some platform specific stuff..
#if TARGET_OS_IPHONE
    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, kAudioFileReadPermission, 0, &outAFID);
#else
    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, fsRdPerm, 0, &outAFID);
#endif
    if (result != 0) NSLog(@"cannot openf file: %@",filePath);
    return outAFID;
}


// find the audio portion of the file
// return the size in bytes
-(UInt32)audioFileSize:(AudioFileID)fileDescriptor
{
    UInt64 outDataSize = 0;
    UInt32 thePropSize = sizeof(UInt64);
    OSStatus result = AudioFileGetProperty(fileDescriptor, kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize);
    if(result != 0) NSLog(@"cannot find file size");
    return (UInt32)outDataSize;
}

- (void)stopSound
{
    alSourceStop(sourceID);
}

-(void)cleanUpOpenAL:(id)sender
{
    // delete the sources
    alDeleteSources(1, &sourceID);

    // delete the buffers
    alDeleteBuffers(1, &bufferID);

    // destroy the context
    alcDestroyContext(mContext);

    // close the device
    alcCloseDevice(mDevice);
}

-(IBAction)play:(id)sender
{
    alSourcePlay(sourceID);
}


#pragma mark -
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    [self initOpenAL];
    // get the full path of the file
    NSString* fileName = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"caf"];
    // first, open the file
    AudioFileID fileID = [self openAudioFile:fileName];

    // find out how big the actual audio data is
    UInt32 fileSize = [self audioFileSize:fileID];

    // this is where the audio data will live for the moment
    unsigned char * outData = malloc(fileSize);

    // this where we actually get the bytes from the file and put them
    // into the data buffer
    OSStatus result = noErr;
    result = AudioFileReadBytes(fileID, false, 0, &fileSize, outData);
    AudioFileClose(fileID); //close the file

    if (result != 0) NSLog(@"cannot load effect: %@", fileName);

    //NSUInteger bufferID;              // buffer is defined in head file
    // grab a buffer ID from openAL
    alGenBuffers(1, &bufferID);

    // jam the audio data into the new buffer
    alBufferData(bufferID, AL_FORMAT_STEREO16, outData, fileSize, 8000); 


    //NSUInteger sourceID;              // source is defined in head file

    // grab a source ID from openAL
    alGenSources(1, &sourceID); 

    // attach the buffer to the source
    alSourcei(sourceID, AL_BUFFER, bufferID);
    // set some basic source prefs
    alSourcef(sourceID, AL_PITCH, 1.0f);
    alSourcef(sourceID, AL_GAIN, 1.0f);
    alSourcei(sourceID, AL_LOOPING, AL_TRUE);

    // clean up the buffer
    if (outData)
    {
        free(outData);
        outData = NULL;
    }
}

推荐答案

您应该能够在调用alBufferData()之后立即释放outData.它将其排除为罪魁祸首,您可以尝试使用静态扩展并自己管理内存.就像这样:

You should be able to release outData right after your alBufferData() call. It exclude it as the culprit, you can try the static extension and manage the memory yourself. It's something like:

alBufferDataStaticProcPtr alBufferDataStaticProc = (alBufferDataStaticProcPtr)alcGetProcAddress(0, (const ALCchar *)"alBufferDataStatic");
alBufferDataStaticProc(bufferID, bitChanFormat, audioData, audioDataSize, dataFormat.mSampleRate);

这篇关于如何在iPhone上使用OpenAL播放循环声音的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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