Iphone 如何完全删除和释放OpenAL声音文件的内存?

Iphone 如何完全删除和释放OpenAL声音文件的内存?,iphone,audio,release,openal,Iphone,Audio,Release,Openal,我有一个基于小级别的iPhone应用程序。我需要加载和发布每个级别的声音文件。 除了释放声音,我的openAL SoundManager一切都很好 起初,当我删除一个声音时,它似乎做了它应该做的事情——它删除了声音,除非我重新加载它,否则我无法再次访问它。但是,当我用“工具”测试我的应用程序dealloc时,它没有显示任何释放。它似乎无法释放内存。因此,当您从一个级别移动到另一个级别时,内存很快就会耗尽,应用程序也会崩溃 我在控制台中遇到此错误: 程序接收到信号:“0”。 警告:检查安全呼叫:无

我有一个基于小级别的iPhone应用程序。我需要加载和发布每个级别的声音文件。 除了释放声音,我的openAL SoundManager一切都很好

起初,当我删除一个声音时,它似乎做了它应该做的事情——它删除了声音,除非我重新加载它,否则我无法再次访问它。但是,当我用“工具”测试我的应用程序dealloc时,它没有显示任何释放。它似乎无法释放内存。因此,当您从一个级别移动到另一个级别时,内存很快就会耗尽,应用程序也会崩溃

我在控制台中遇到此错误:

程序接收到信号:“0”。 警告:检查安全呼叫:无法还原当前帧 杀死 退出

这就是我加载声音的方式-

- (void)loadSoundWithKey:(NSString*)aSoundKey fileName:(NSString*)aFileName fileExt:(NSString*)aFileExt {
// Check to make sure that a sound with the same key does not already exist
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is found log it and finish
if(numVal != nil) {
    NSLog(@"WARNING - SoundManager: Sound key '%@' already exists.", aSoundKey);
    return;
}
    NSUInteger bufferID;
// Generate a buffer within OpenAL for this sound
alGenBuffers(1, &bufferID);
// Set up the variables which are going to be used to hold the format
// size and frequency of the sound file we are loading
ALenum  error = AL_NO_ERROR;
ALenum  format;
ALsizei size;
ALsizei freq;
ALvoid *data;
NSBundle *bundle = [NSBundle mainBundle];
// Get the audio data from the file which has been passed in
CFURLRef fileURL = (CFURLRef)[[NSURL fileURLWithPath:[bundle pathForResource:aFileName ofType:aFileExt]] retain];
if (fileURL)
{   
    data = MyGetOpenALAudioData(fileURL, &size, &format, &freq);
    CFRelease(fileURL);
    if((error = alGetError()) != AL_NO_ERROR) {
        NSLog(@"ERROR - SoundManager: Error loading sound: %x\n", error);
        exit(1);
    }
    // Use the static buffer data API
    alBufferDataStaticProc(bufferID, format, data, size, freq);
    if((error = alGetError()) != AL_NO_ERROR) {
        NSLog(@"ERROR - SoundManager: Error attaching audio to buffer: %x\n", error);
    }       
}
else
{
    NSLog(@"ERROR - SoundManager: Could not find file '%@.%@'", aFileName, aFileExt);
    data = NULL;
}

// Place the buffer ID into the sound library against |aSoundKey|
[soundLibrary setObject:[NSNumber numberWithUnsignedInt:bufferID] forKey:aSoundKey];
if(DEBUG) NSLog(@"INFO - SoundManager: Loaded sound with key '%@' into buffer '%d'", aSoundKey, bufferID);
}

这就是我试图删除/释放的方式。但它似乎仍然保留着声音文件的记忆-

- (void)removeSoundWithKey:(NSString*)aSoundKey {
// Find the buffer which has been linked to the sound key provided
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is not found log it and finish
if(numVal == nil) {
    NSLog(@"WARNING - SoundManager: No sound with key '%@' was found so cannot be removed", aSoundKey);
    return;
}    
// Get the buffer number form the sound library so that the sound buffer can be released
NSUInteger bufferID = [numVal unsignedIntValue];
alDeleteBuffers(1, &bufferID);
[soundLibrary removeObjectForKey:aSoundKey];
if(DEBUG) NSLog(@"INFO - SoundManager: Removed sound with key '%@'", aSoundKey);
}

有人能想出办法完全删除我的声音文件的所有痕迹(能够再次加载)


多谢各位

我不熟悉OpenAL for iPhone的特点,但我粗略猜测如下:

缓冲区是否仍然连接到OpenAL源代码,即在加载和发布之间是否调用了alSourcei(…,AL_buffer…)或alSourceQueueBuffers?如果是这种情况,您可能需要在删除缓冲区之前运行alSourcei(…,AL_BUFFER,NULL)或ALSOURCEUNQUEUEBURES


在调用AldeleteBuffer之后,尝试检查OpenAL错误(AlgeTerr)

如果有人感兴趣。。。通过将alBufferDataStaticProc更改为alBufferData,解决了我的问题。然后添加
if(数据)free(数据)见下文

谢谢你的帮助

alBufferData(bufferID, format, data, size, freq);
    if((error = alGetError()) != AL_NO_ERROR) {
        NSLog(@"ERROR - SoundManager: Error attaching audio to buffer: %x\n", error);
    }
    if (data) 
        free(data);
}else{
    NSLog(@"ERROR - SoundManager: Could not find file '%@.%@'", fileName, fileType);
    data = NULL;

这是我所做的总结,“完全删除我的声音文件的每个痕迹(能够再次加载)”,使用相同的和一些:


这里主要添加的是
if
,在我的例子中,我实际上添加到了
teardownOpenAL

嗨,有几个视图,但还没有答案?。。。如果你看了这段代码没有发现任何错误,请说出来。然后它可能会让我认为我的问题不是缓冲区没有释放内存。ThanksalBufferDataStatic是一把“锋利的刀”,有一大堆隐藏的警告。我建议看这段视频:事实上,这对我来说并不管用,但它在发现问题方面帮助很大。从使用同一个苹果示例开始,我所需要做的就是添加
if(device!=NULL)[self-teardownownopenal]
[self initOpenAL]之前
if (device != NULL)
    [self teardownOpenAL];
[self initOpenAL];
alSourcePlay(source);