Хотя мы просим AVAudioRecorder
записывать в формате MPEG4-AAC, он всегда создает файл .caf (Core Audio Format). Однако это всего лишь формат оболочки, и фактические аудиоданные, которые он содержит, находятся в формате AAC.
В конце концов, добавление файлов сводилось к управлению побайтовыми файлами .caf. Спецификация для файлов Core Audio Format: здесь . Сначала было немного утомительно переваривать этот документ и соответственно обрабатывать файлы, но оказалось, что спецификация очень ясная и полная, поэтому она не была слишком обременительной.
Как поясняется в спецификации, файлы .caf состоят из кусков с четырехбайтовыми именами в начале. Для файлов AAC всегда есть чанк desc
и чанк kuki
. Поскольку мы знаем, что наши два исходных файла находятся в одном и том же формате, мы можем скопировать эти куски без изменений в выходной файл.
Есть также блок pakt
и блок data
. Мы не можем гарантировать, в каком порядке они будут во входных файлах. Может существовать или не быть фрагмент free
- но он содержит только отступы 0x00, поэтому нам не нужно копировать его в выходной файл.
Чтобы объединить чанки pakt
, нам нужно проверить заголовки чанков и создать новый чанк pakt
, чьи поля mNumberPackets
и mNumberValidFrames
являются суммами полей во входных файлах. mPrimingFrames
и mRemainderFrames
всегда равны нулю - они актуальны только для потокового мультимедиа. Большая часть блоков pakt
(т.е. фактических данных таблицы пакетов) может быть просто объединена.
Аналогично для блоков data
: поля mChunkSize
необходимо суммировать, а затем можно объединить большую часть данных.
Будьте внимательны при чтении данных из всех двоичных числовых полей в этих файлах: файлы с прямым порядком байтов, но iPhone с прямым порядком байтов.
Для дополнительной оценки вы можете также рассмотреть возможность удаления сегментов звука из файла или вставки одного аудиофайла в середину другого. Это немного сложнее, так как вам нужно проанализировать содержимое блока pakt
. Опять же, это случай следования спецификации: есть хорошее описание того, как размеры пакетов хранятся в целых числах переменной длины, поэтому вам придется проанализировать их, чтобы найти, сколько байтов занимает каждый пакет в блоке data
, и рассчитать их позиции соответственно.
В целом, это намного сложнее, чем я надеялся. Может быть, есть библиотека с открытым исходным кодом, которая сделает все это за вас, но я не смог ее найти.
Тем не менее, обработка необработанных файлов, таких как эта, слепа по сравнению с использованием AVMutableComposition
и AVMutableCompositionTrack
, как в первоначальном вопросе - вставка записи продолжительностью в один час в другую такой же длины занимает около двух секунд.
Удачи!