How to play looping sound with OpenAL on iPhone

大城市里の小女人 提交于 2020-01-03 16:48:39

问题


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;
    }
}

回答1:


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);


来源:https://stackoverflow.com/questions/1873817/how-to-play-looping-sound-with-openal-on-iphone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!