NSSound-подобная структура, которая работает, но не требует иметь дело с крутой кривой обучения - PullRequest
1 голос
/ 24 августа 2010

Я почти закончил работу над функцией белого шума для одного из моих приложений, использующего NSSound для воспроизведения цикла из 10 секунд предварительно записанного белого шума в кодировке AAC.

[sound setLoops: YES]

должно быть все, что требуется, верно?

Это работает как брелок, но я заметил, что между завершением и перезапуском звукового файла слышна пауза ... что-то вроде "хлопающего" звука. Этого нет при зацикливании исходных звуковых файлов и после часа или около того попытки выяснить это, я пришел к выводу, что NSSound отстой и что слышимая пауза является артефактом синхронизации частного фонового потока Воспроизведение звука. Кажется, это как-то зависит от основного цикла выполнения, и это вызывает слышимый разрыв между концом и перезапуском звука.

Я очень мало знаю о звуковых вещах, и это очень незначительная функция, поэтому я не хочу вдаваться в глубины CoreAudio только для воспроизведения зацикленного звукового фрагмента 10-х годов ... так что я пошел в погоню за хорошей альтернативой, но, похоже, ничего не подходит:

  • Core Audio: полный перебор, но, по крайней мере, стандартная структура
  • AudioQueue: сложный, с примером кода C ++!?
  • MusicKit / SndKit: также огромная кривая обучения, основанная на большом количестве открытых ресурсов и т. Д.

Я видел, что AVFoundation на iOS 4 будет хорошим способом воспроизведения звуков, но это запланировано только для Mac OS X 10.7.

Существует ли какой-либо простой в использовании способ надежного зацикливания звука в Mac OS X 10.5+?

Существует ли какой-нибудь пример кода для AudioQueue или Core Audio, который избавляет от необходимости использовать их из приложения Objective-C?

Любая помощь будет очень признательна ..

С уважением,

Frank

Ответы [ 3 ]

2 голосов
/ 24 августа 2010

Используйте QTKit.Создайте QTMovie для звука, установите его на петлю и оставьте его воспроизводить.

2 голосов
/ 26 августа 2010

Только ради архивов.

QTKit также страдает от разрыва между концом одного воспроизведения и началом следующего.Кажется, это связано с повторной инициализацией данных (возможно, повторным чтением их с диска?).Это гораздо более заметно при использовании гораздо меньшего, но сильно сжатого формата m4a, чем при воспроизведении несжатых aiff-файлов, но оно все еще там.

Решение, которое я нашел, заключается в использовании Audio Queue Services:

http://developer.apple.com/mac/library/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/AQPlayback/PlayingAudio.html#//apple_ref/doc/uid/TP40005343-CH3-SW1

и

http://developer.apple.com/mac/library/samplecode/AudioQueueTools/Listings/aqplay_cpp.html#//apple_ref/doc/uid/DTS10004380-aqplay_cpp-DontLinkElementID_4

Аудио-очередь вызывает функцию обратного вызова, которая подготавливает и ставит в очередь следующий буфер, поэтому, когда вы достигнете концатекущий файл нужно начинать заново с самого начала.Это обеспечивает абсолютно безупречное воспроизведение.

В примере кода в документации есть два недочета.

Первый - это настоящая ошибка (я сообщу об этом в DTS, чтобы они могли ее исправить).Перед выделением и заполнением аудио-буферов пользовательская структура должна включить воспроизведение, иначе аудио-буфер никогда не будет заполнен, и ничего не будет воспроизведено:

    aqData.mIsRunning = 1;

Второй момент заключается в том, что код не запускается в Какао, нокак автономный инструмент, поэтому код соединяет аудио-очередь с новым циклом выполнения и фактически реализует сам цикл выполнения в качестве последнего шага программы.

Вместо передачи CFRunLoopGetCurrent (), просто передайте NULL, что вызываетAudioQueue для запуска в своем собственном цикле выполнения.

result = AudioQueueNewOutput (                                // 1
                     &aqData.mDataFormat,                             // 2
                     HandleOutputBuffer,                              // 3
                     &aqData,                                         // 4
                     NULL, //CFRunLoopGetCurrent (),                          // 5
                     kCFRunLoopCommonModes,                           // 6
                     0,                                               // 7
                     &aqData.mQueue                                   // 8
                     );

Я надеюсь, что это может спасти бедняков, пытающихся сделать то же самое в будущем немного времени: -)

0 голосов
/ 24 августа 2010

К сожалению, при разработке аудиоприложений на OS X возникает большая боль. Кривая обучения очень крутая, потому что документация довольно скудная.

Если вы не возражаете против Objective-C ++, я написал основу для такого рода вещей: SFBAudioEngine . Если вы хотите воспроизвести звук с моим кодом, вот как вы могли бы это сделать:

DSPAudioPlayer *player = new DSPAudioPlayer();
player->Enqueue((CFURLRef)audioURL);
player->Play();

Возможно также зацикливание.

...