Я использую модуль аудиовыхода для захвата данных микрофона. Я получаю уведомление, что есть данные для чтения через обратный вызов, который я установил, используя свойство kAudioOutputUnit_SetInputCallback, а в обратном вызове я прочитал данные, вызвав AudioUnitRender().Какие действия разрешены в обратном вызове входного аудиовыхода
В конечном счете, я буду обновлять пользовательский интерфейс своего приложения на основе некоторой информации, извлеченной путем анализа этих данных. Поэтому мне нужно на каком-то этапе сделать dispatch_async в основной очереди. Анализ умеренно трудоемкий и выполняется в кусках, которые больше, чем те, которые я получаю от AudioUnitRender(), поэтому нагрузка является взрывоопасной.
Мой вопрос: какие операции считаются приемлемыми при реализации самого обратного вызова ввода? Я нашел много источников, указав строгие ограничения на render callbacks (без распределения памяти, без ввода/вывода, без синхронизации с другими потоками и т. Д.), Но никакой информации о ввода обратных вызовов.
Если я выполняю те же правила, что и для обратных вызовов рендеринга, у меня есть проблема. сама dispatch_async() нежелательна, так как она выделяет память, а загрузка все равно (может быть, она может быть длиннее одного цикла рендеринга на некоторых витках и практически равна нулю на других). Поэтому представляется необходимым отправить мои данные в рабочий поток для обработки и для вызовов dispatch_async(), которые необходимо выполнить. Однако мне все же нужно управлять передачей данных этому рабочему потоку. Самый простой способ (в C++) - с циклическим буфером, плюс мьютекс и переменная условия, чтобы сигнализировать, когда доступны данные. Однако для этого потребуется обратный вызов ввода для блокировки мьютекса, который явно отвергает рекомендации по обратным вызовам рендеринга.
Избегая этого блокировки мьютекса, я отведу на блокирующие круговые буферы, семафоры (POSIX или GCD), шпиндельные замки и т. Д., И мне интересно, может ли это быть излишним, просто слушая микрофон. У нас ужасная нехватка документации для этого материала, и я понятия не имею, что действительно происходит за кулисами. Мне действительно нужно беспокоиться о ожидании на мьютексе (только кратко и редко заблокированном другим потоком) в моей реализации обратного вызова ввода?
Да, как я уже упоминал в конце, чтобы избежать блокировки мьютекса, похоже, что мне понадобится бесплатный кольцевой буфер и что-то другое, кроме std :: condition_variable, чтобы заставить рабочий поток проснуться, когда есть данные (семафор GCD выглядит наиболее перспективным для этого).Эта реализация циклического буфера полезна, и хорошо, что на самом деле у нее есть * документированная * технология потоковой передачи, в отличие от CARingBuffer, поэтому благодарим за это. Тем не менее, по-прежнему стоит вопрос о том, действительно ли необходимо избегать мьютекса во входном обратном вызове. – Tom
Обновленный ответ. – rocky