【问题标题】:when in audio callback function, how to update the UI/call the view controller?在音频回调函数中,如何更新 UI/调用视图控制器?
【发布时间】:2012-11-29 10:18:34
【问题描述】:

我目前正在学习在 iOS 中使用音频队列服务。为此,我关注了Audio Queue Services Programming Guide - Recording Audio。这行得通。

现在我想在callback function 接收到来自麦克风的输入数据时更新一个 UI 元素(功率计)。这就是我遇到问题的地方。

我不确定从回调函数调用视图/视图控制器以更新功率计的好方法是什么。我试过这个: 对于指南中描述的custom struct to manage state,我添加了一个指向我的视图控制器的指针:

struct AQRecorderState {
    AudioStreamBasicDescription  mDataFormat;                   // 2
    AudioQueueRef                mQueue;                        // 3
    AudioQueueBufferRef          mBuffers[kNumberBuffers];      // 4
    AudioFileID                  mAudioFile;                    // 5
    UInt32                       bufferByteSize;                // 6
    SInt64                       mCurrentPacket;                // 7
    bool                         mIsRunning;                    // 8
    void*                        mViewController; // <- I've added this line
};

我在开始录制时初始化此指针。这是在视图控制器的方法中完成的,当开始按钮接收到 TouchUp 事件时会调用该方法:

- (IBAction)startAudioRecording:(id)sender {

    struct AQRecorderState* aqData = createAQRecorderState();

    void* pViewControllerAsVoidPointer = (__bridge void*) self;
    aqData->mViewController = pViewControllerAsVoidPointer;

//...

分配结构体的方法createAQRecorderState()如下所示:

struct AQRecorderState* createAQRecorderState() {
    struct AQRecorderState* pAqData = (struct AQRecorderState*) malloc(sizeof(AQRecorderState));

    initializeAQRecorderState(*pAqData); // sets members of the struct; does not set pointer to view controller

    return pAqData;
}

AFAIK,我在开始录制时创建的结构的实例被传递给以后对回调函数的调用。为此,我在回调函数中添加了以下代码,以便随后调用视图控制器:

void HandleInputBuffer(
                       void                                 *aqData,
                       AudioQueueRef                        inAQ,
                       AudioQueueBufferRef                  inBuffer,
                       const AudioTimeStamp                 *inStartTime,
                       UInt32                               inNumPackets,
                       const AudioStreamPacketDescription   *inPacketDesc
                       ) {

//...

NSLog(@"interesting part start");

void* pViewControllerAsVoidPtr = pAqData->mViewController;
NSLog(@"localized pointer to void");

ViewController* pViewController = (__bridge ViewController*) pViewControllerAsVoidPtr;  //EXC_BAD_ACCESS
NSLog(@"localized pointer to ViewController");

//...
}

但是,当我进行桥接指针转换时,我在上面标记行的回调函数中得到了 EXC_BAD_ACCESS (code=1, address=0xffffffff)。然后我用调试器检查了这一点,实际上pViewControllerAsVoidPtr 保存了我在执行方法startAudioRecording: 期间存储在pAqData-&gt;mViewController 中的地址。

为什么指针会改变?或者:如何正确地从我的回调函数调用到视图控制器以更新 UI?

【问题讨论】:

  • 除非已更新,否则 SpeakHere 示例是 ARC 之前的示例。您是否已将其转换为 ARC?我假设这是您使用的示例项目,因为它使用音频队列来控制电平表。
  • 我确实在我的项目中使用了 ARC。代码与 ARC 的兼容性是我将遵循的一个好主意。我也不得不承认我并不完全理解桥接指针转换。但是,我没有使用示例项目。我使用了一个新创建的项目,并从我链接到的指南中复制了大部分代码。
  • @MaxMacLeod,顺便说一句,看看 SpeakHere 示例是个好主意。如果他们使用音频队列并有电平表,那么我应该能够在那里看到它是如何完成的。
  • 大好时光!这正是你所需要的。 Btw AudioQueue 可能不适合您,具体取决于您在做什么。 AudioUnit 可以更容易使用。此外,如果您使用 SpeakHere,它不是 ARC,因此只需为项目中的这些类设置编译器标志。检查我的答案。我介绍了很多与 SpeakHere 相关的 AudioQueue 和 AudioUnit 问题。

标签: objective-c ios uiviewcontroller callback audioqueueservices


【解决方案1】:

我发现了我的错误。这是我如何执行步骤Creating a Recording Audio Queue。我完全按照指南中的复制粘贴操作:

AudioQueueNewInput (                              // 1
    &aqData.mDataFormat,                          // 2
    HandleInputBuffer,                            // 3
    &aqData, //<------------------ HERE           // 4
    NULL,                                         // 5
    kCFRunLoopCommonModes,                        // 6
    0,                                            // 7
    &aqData.mQueue                                // 8
);

问题在于,在指南中,变量 aqData 是一个结构,因此需要引用(前导和符号)才能将其转换为指针,而我的变量 aqData 已经是指向结构的指针,因此需要引用(前导&符号)将其更改为“指向结构的指针”。因此我将指针的地址而不是结构的地址传递给了函数AudioQueueNewInput(...),这是错误的,当然这个其他位置的内存有不同的内容。

编译器不会抱怨这种错误类型,因为它需要一个 (void*),它可以是任何指针,包括 (struct**),一个指向结构体指针的指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-24
    • 2023-03-14
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 2013-09-14
    相关资源
    最近更新 更多