6

好的,这是场景:我有一个使用 ExtAudioFileWriteAsync 针对 iOS 4.3 的实时录音应用程序。我第一次使用该应用程序录制时,它运行良好。如果我按停止,然后再次录制,则有一半的时间我会在录制开始时在 AudioRingBuffer::GetTimeBounds 中获得 EXC_BAD_ACCESS。

也就是说,ExtAudioFileWriteAsync 在开始第二次录制时在 GetTimeBounds 上失败。下面是录制开始时触发的一段代码,它创建了 ExtAudioFile 引用:

- (void) setActive:(NSString *) file 
{
if (mExtAFRef) {
    ExtAudioFileDispose(mExtAFRef);
    mExtAFRef = nil;
    NSLog(@"mExtAFRef Disposed.");
}

if (mOutputAudioFile)
{
    ExtAudioFileDispose(mOutputAudioFile);
    mOutputAudioFile = nil;
    NSLog(@"mOutputAudioFile Disposed.");
}

NSURL *outUrl = [NSURL fileURLWithPath:file];

OSStatus setupErr = ExtAudioFileCreateWithURL((CFURLRef)outUrl, kAudioFileWAVEType, &mOutputFormat, NULL, kAudioFileFlags_EraseFile, &mOutputAudioFile);  
NSAssert(setupErr == noErr, @"Couldn't create file for writing");

setupErr = ExtAudioFileSetProperty(mOutputAudioFile,       kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &audioFormat);
NSAssert(setupErr == noErr, @"Couldn't create file for format");

setupErr =  ExtAudioFileWriteAsync(mOutputAudioFile, 0, NULL);
NSAssert(setupErr == noErr, @"Couldn't initialize write buffers for audio file");

isActive = TRUE;

}

有没有人对可能导致这种情况的原因有任何想法?我假设,鉴于 EXC_BAD_ACCESS,这是内存泄漏或某些东西的引用计数被敲到零,但我无法终生弄清楚它可能是什么,而谷歌正在画一个完全空白。我在 Apple 开发论坛上为 CoreAudio 发布了同样的内容,但没有人同情我,甚至发表了一句精辟的评论。停!

编辑:发现问题。当 ExtAudioFileWriteAsync 在旧文件“优化”之前尝试写入新文件时发生错误。一点互斥爱解决了这个问题。

4

2 回答 2

5

我在录音应用程序上遇到了几乎相同的问题,谁能解释一下如何用“A little mutex love”来解决它? 编辑

Tnx to Chris Randall 我确实设法解决了我的问题。这就是我实现互斥锁的方式:

#include <pthread.h>
static pthread_mutex_t outputAudioFileLock;

然后在我的初始化中:

pthread_mutex_init(&outputAudioFileLock,NULL);

并在回调中:

if (THIS.mIsRecording) {
        if (0 == pthread_mutex_trylock(&outputAudioFileLock)) {
        OSStatus err = ExtAudioFileWriteAsync(THIS.mRecordFile, inNumberFrames, THIS.recordingBufferList);
        if (noErr != err) {
            NSLog(@"ExtAudioFileWriteAsync Failed: %ld!!!", err);
        } else {
        }
        pthread_mutex_unlock(&outputAudioFileLock);
    }
    }

最后在 stopRecord 方法中:

if (mRecordFile) {

    pthread_mutex_lock(&outputAudioFileLock);
    OSStatus setupErr;
    setupErr = ExtAudioFileDispose(mRecordFile);
    mRecordFile = NULL;
    pthread_mutex_unlock(&outputAudioFileLock);
    NSAssert(setupErr == noErr, @"Couldn't dispose audio file");
    NSLog(@"Stopping Record");  
    mIsRecording = NO;
}

再次Tnx寻求帮助,希望这可以节省某人的时间。

于 2012-05-13T18:11:24.280 回答
2

包括 pthread.h,并在构造函数中定义 pthread_mutex_t outputAudioFileLock。然后,在您的音频回调中,当您想编写时,请执行以下操作(根据您使用的内容调整变量):

if (0 == pthread_mutex_trylock(&outputAudioFileLock)) {
            OSStatus err = ExtAudioFileWriteAsync(mOutputAudioFile, frames, bufferList);
            if (noErr != err) {
                NSLog(@"ExtAudioFileWriteAsync Failed: %ld!!!", err);
            } else {
            }
            pthread_mutex_unlock(&outputAudioFileLock);
        }

pthread_mutex_trylock 检查线程是否被锁定(从而“优化”)。如果不是,则允许写入。然后我像这样包装音频文件设置(如上所示)和音频文件清理,以便在文件系统执行任何会导致 AudioRingBuffer BAD_ACCESS 错误的操作时锁定线程:

pthread_mutex_lock(&outputAudioFileLock);
OSStatus setupErr;
setupErr = ExtAudioFileDispose(mOutputAudioFile);
mOutputAudioFile = NULL;
pthread_mutex_unlock(&outputAudioFileLock);
NSAssert(setupErr == noErr, @"Couldn't dispose audio file");

这会锁定设置和清理线程,因此您无法写入正在“优化”的文件,这是错误的根源。希望这可以帮助!

编辑:我在音频控制器的 Obj-C 部分进行音频回调;如果您在 C++ 部分中进行操作,则其结构会有所不同;也许其他人可以回答这个问题?

于 2012-05-15T13:39:29.453 回答