3

CoreAudioのリアルタイムスレッドとUIスレッドの間でデータを渡す必要があります(一方向、RT-> UI)。performSelectorOnMainThreadまたはのようなCocoa/Objective Cメソッドを使用できないことはわかっていNSNotificationます。また、RTスレッドをブロックする可能性があるため、メモリを割り当てるものは使用できません。

スレッド間で通信するための正しい方法は何ですか?GCDメッセージキューを使用できますか、それとも使用するより基本的なシステムがありますか?

編集:

これについてもう少し考えてみると、RTスレッドがメッセージを入れ、UIスレッドがメッセージを引き出すかどうかをチェックするロックフリーのリングバッファーを使用できると思います。これが最善の方法ですか?もしそうなら、CoreAudioでこれを行うシステムがすでにあるか、他の場所で利用できますか、それとも自分でコーディングする必要がありますか?

4

2 に答える 2

2

これは私が思っていたよりもずっと簡単だったことがわかりました。私が思いついた解決策は、Portaudioのリングバッファを使用することだけでした。プロジェクトにpa_ringbuffer。[ch]とpa_memorybarrier.hを追加してから、リングバッファに格納するMessageData構造を定義する必要がありました。

typedef struct MessageData {
    MessageType type;
    union {
        struct {
            NSUInteger position;
        } position;
    } data;
} MessageData;

次に、32個のメッセージを格納するためのスペースを割り当て、リングバッファーを作成しました。

_playbackData->RTToMainBuffer = malloc(sizeof(MessageData) * 32);
PaUtil_InitializeRingBuffer(&_playbackData->RTToMainRB, sizeof(MessageData),
                            32, _playbackData->RTToMainBuffer);

最後に、リングバッファからデータをプルするために20msごとにNSTimerを開始しました

while (PaUtil_GetRingBufferReadAvailable(&_playbackData->RTToMainRB)) {
    MessageData *dataPtr1, *dataPtr2;
    ring_buffer_size_t sizePtr1, sizePtr2;

    // Should we read more than one at a time?
    if (PaUtil_GetRingBufferReadRegions(&_playbackData->RTToMainRB, 1,
                                        (void *)&dataPtr1, &sizePtr1,
                                        (void *)&dataPtr2, &sizePtr2) != 1) {
        continue;
    }

    // Parse message
    switch (dataPtr1->type) {
        case MessageTypeEOS:
            break;

        case MessageTypePosition:
            break;

        default:
            break;
    }
    PaUtil_AdvanceRingBufferReadIndex(&_playbackData->RTToMainRB, 1);
}

次に、リアルタイムスレッドでは、メッセージをリングバッファにプッシュするだけでした。

MessageData *dataPtr1, *dataPtr2;
ring_buffer_size_t sizePtr1, sizePtr2;

if (PaUtil_GetRingBufferWriteRegions(&data->RTToMainRB, 1,
                                     (void *)&dataPtr1, &sizePtr1,
                                     (void *)&dataPtr2, &sizePtr2)) {
    dataPtr1->type = MessageTypePosition;
    dataPtr1->data.position.position = currentPosition;

    PaUtil_AdvanceRingBufferWriteIndex(&data->RTToMainRB, 1);
} 
于 2013-03-23T12:53:49.087 に答える
2

リングバッファは良い解決策です。両方の方法で通信する必要がある場合は2つ。受信トレイ/送信トレイのメッセージパッシング。

これは、Portaudioを使用したくない場合のiOS/Macの優れた実装です。

https://github.com/michaeltyson/TPCircularBuffer

于 2015-02-15T12:07:13.177 に答える