Аудио-очередь - цикличное выполнение сжатое аудио
Q: Как я беспрепятственно циклично выполняюсь, AAC сжал аудио с помощью Аудио-очереди?
Беспрепятственно цикличное выполнение, сжатый аудиофайл требует трех данных, связанных с тем, как были сжаты аудио носители:
Число тихих демонстрационных кадров (известный как кадры воспламенения) добавило к передней стороне закодированных аудиоданных.
Число дополнения демонстрационных кадров (известный как кадры остатка) добавило до конца закодированных аудиоданных.
Количество пакетов аудиоданных, указывающее общее количество пакетов аудиоданных, содержится в файле.
Использовать AudioQueueEnqueueBufferWithParameters для постановки в очередь всех пакетов, Вы имеете к аудио-очереди, урезаете демонстрационные кадры воспламенения от запуска, урезаете демонстрационные кадры остатка от последнего пакета и сбрасываете текущее количество пакетов, чтобы начать считывать данные с начала файла, создающего цикл.
Фон
Для анализа, на что эта информация похожа в сжатом аудиофайле, создают закодированный Формат аудио Огрызка AAC (.caf) файл с afconvert, тогда используйте afinfo распечатать некоторые подробные данные о файле.
% afconvert -d aac -f caff /System/Library/Sounds/Submarine.aiff /tmp/output.caf |
% afinfo /tmp/output.caf |
File: /tmp/output.caf |
File type ID: caff |
Data format: 2 ch, 44100 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame |
no channel layout. |
estimated duration: 0.975 sec |
audio bytes: 10541 |
audio packets: 45 |
audio 42998 valid frames + 2112 priming + 970 remainder = 46080 |
Что означают числа?
Закодировать
Submarine.aiffфайл с помощью AAC требует 45 Аудио Пакетов. Это - Количество пакетов Аудиоданных.Эти 45 Аудио Пакетов содержат 1 024 кадра на пакет, который является 46 080 демонстрационными кадрами долго (45 * 1024 = 46080).
Первые 2 112 демонстрационных кадров являются тишиной. Эти тихие демонстрационные кадры являются кадрами воспламенения кодера; Чрезвычайно пустые пакеты AAC и пакеты, содержащие информацию, используемую для корректного декодирования первые выборки.
Последний Аудио Пакет имеет 970 демонстрационных кадров остатка тишины, добавленной к нему, окружая Аудио Размер пакета к 1 024. Другими словами, 1 024 демонстрационных кадров, представленных в последнем пакете, только 54 демонстрационных кадра являются фактически допустимыми выборками, которые мы хотим декодировать (1024 - 970 = 54).
Теперь, когда мы знаем задержки кодера и дополнение, мы можем полностью понять (и представлять в файле), эти клавиатуры, и поэтому получите фактическое число выборок в потоке битов.
Если Вы берете общее количество выборок (46080), вычитаете воспламенение и дополняющий демонстрационные кадры (2112, и 970 соответственно) Вас оставляют с 42 998 допустимыми выборками (46080 - 2112 - 970 = 42998). Можно подтвердить, что 42998 исходная длина Submarine.aiff при помощи afinfo снова.
% afinfo /System/Library/Sounds/Submarine.aiff |
File: /System/Library/Sounds/Submarine.aiff |
File type ID: AIFF |
Data format: 2 ch, 44100 Hz, 'lpcm' (0x0000000E) 16-bit big-endian signed integer |
no channel layout. |
estimated duration: 0.975 sec |
audio bytes: 171992 |
audio packets: 42998 |
Как только Вы имеете точное число воспламенения и кадров остатка вместе с количеством пакетов для закодированного потока битов, и помните эту информацию при постановке в очередь буферов, сплошное цикличное выполнение с Аудио-очередью становится довольно прямым усилием.
Чтобы декодировать вышеупомянутое, AAC сжал поток битов и вывести то же число выборок; Ставьте в очередь все пакеты, которые Вы имеете к аудио-очереди, урезаете 2 112 демонстрационных кадров от запуска, урезаете 970 демонстрационных кадров от последнего пакета, и Вы будете полностью декодировать сжатый поток битов точно к последней выборке. Как только Вы ставили в очередь все пакеты, сбрасывали Ваше текущее количество пакетов и запускаете снова, таким образом, цикличное выполнение аудио.
Подробные данные
Со всеми числами из пути и так как мы теперь знаем о кадрах воспламенения, кадрах остатка и количестве пакетов - где мы получаем эти значения от?
Структура AudioFilePacketTableInfo
Получите Кадры Воспламенения и значения Кадров Остатка путем вызова AudioFileGetProperty выяснение kAudioFilePropertyPacketTableInfo свойство как показано в Перечислении 1. Храните их для использования в выходном обратном вызове.
<AudioToolbox/AudioFile.h> |
/*! |
@struct AudioFilePacketTableInfo |
@abstract This contains information about the number of valid frames in a file and where they begin and |
end. |
@discussion Some data formats may have packets whose contents are not completely valid, but represent |
priming or remainder frames that are not meant to be played. For example a file with 100 |
packets of AAC is nominally 1024 * 100 = 102400 frames of data. However the first 2112 frames |
of that may be priming frames and there may be some number of remainder frames added to pad |
out to a full packet of 1024 frames. The priming and remainder frames should be discarded. The |
total number of packets in the file times the frames per packet (or counting each packet's |
frames individually for a variable frames per packet format) minus mPrimingFrames, minus |
mRemainderFrames, should equal mNumberValidFrames. |
@field mNumberValidFrames the number of valid frames in the file. |
@field mPrimingFrames the number of invalid frames at the beginning of the file. |
@field mRemainderFrames the number of invalid frames at the end of the file. |
*/ |
struct AudioFilePacketTableInfo |
{ |
SInt64 mNumberValidFrames; |
SInt32 mPrimingFrames; |
SInt32 mRemainderFrames; |
}; |
typedef struct AudioFilePacketTableInfo AudioFilePacketTableInfo; |
Перечисление 1
AudioFilePacketTableInfo thePacketTableInfo; |
UInt32 size = sizeof(thePacketTableInfo); |
AudioFileGetProperty(myAudioFileID, kAudioFilePropertyPacketTableInfo, &size, &thePacketTableInfo); |
myAudioLooper->mPrimingFrames = thePacketTableInfo.mPrimingFrames; |
myAudioLooper->mRemainderFrames = thePacketTableInfo.mRemainderFrames; |
Количество пакетов
Как упомянуто, знание, когда циклично выполнить файл, требует получения, сколько общих пакетов находится в файле. Получите это значение от аудиофайла путем вызова AudioFileGetProperty выяснение kAudioFileStreamProperty_AudioDataPacketCount свойство как показано в Перечислении 2.
Количество пакетов Аудиоданных является a UInt64 значение, указывающее число пакетов аудиоданных в файле. Храните это для использования в выходном обратном вызове.
Перечисление 2
UInt32 size = sizeof(myAudioLooper->mAudioFilePacketCount); |
AudioFileGetProperty(myAudioFileID, kAudioFileStreamProperty_AudioDataPacketCount, |
&size, &myAudioLooper->mAudioFilePacketCount); |
Постановка в очередь аудио пакетов
Постановка в очередь сделана с помощью AudioQueueEnqueueBufferWithParameters API, удобно обеспечивающий возможность обрезки. Используйте значение кадров воспламенения для inTrimFramesAtStart параметр как требуется и использование остаток структурируют значение для inTrimFramesAtEnd параметр как требуется.
AudioQueueEnqueueBufferWithParameters(AudioQueueRef inAQ, |
AudioQueueBufferRef inBuffer, |
UInt32 inNumPacketDescs, |
const AudioStreamPacketDescription * inPacketDescs, |
UInt32 inTrimFramesAtStart, |
UInt32 inTrimFramesAtEnd, |
UInt32 inNumParamValues, |
const AudioQueueParameterEvent * inParamValues, |
const AudioTimeStamp * inStartTime, |
AudioTimeStamp * outActualStartTime) |
Assigns a buffer to an audio queue for playback, providing parameters and start time information. |
You can exert some control of the buffer queue by using this function. You can assign audio queue settings that are in effect carried by an audio queue buffer as you enqueue it. Hence, these changes only take effect when an audio queue buffer begins playing. |
This function queues a buffer for playback only, not for recording. Audio queues for recording have no parameters, do not support variable-bit-rate (VBR) formats (which might require trimming), and have a different way to handle timing. When queued for playback, the buffer must contain the audio data to be played back. See AudioQueueEnqueueBuffer for details on queuing a buffer for recording. |
Parameters: |
inAQ - The audio queue associated with the buffer. |
inBuffer - The buffer to be played from. |
inNumPacketDescs - The number of packet descriptions pointed to by the inPacketDescs parameter. Required only |
for variable-bit-rate (VBR) audio formats. Pass 0 if no packet descriptions are required. |
inPacketDescs - A pointer to an array of audio stream packet descriptions. Required only for VBR audio |
formats. Pass NULL if no packet descriptions are required. |
inTrimFramesAtStart - The number of priming frames to skip at the start of the buffer. |
inTrimFramesAtEnd - The number of frames to skip at the end of the buffer. |
inNumParamValues - The number of parameter values pointed to by the inParamValues parameter. |
inParamValues - An array of parameter values(In Mac OS X v10.5, there is only one parameter, |
kAudioQueueParam_Volume.) These values are set before buffer playback and cannot be |
changed while the buffer is playing. How accurately changes in parameters can be |
scheduled depends on the size of the buffer. If there are no parameters to set |
(inNumParamValues = 0), pass NULL. |
inStartTime - A pointer to a structure containing the desired start time for playing the buffer. If |
you specify the time using the mSampleTime field of the AudioTimeStamp structure, the |
sample time is relative to the time the queue started. If you pass NULL for the start |
time, the buffer starts immediately after the previously queued buffer, or as soon as |
possible if no buffers are queued ahead of it. Buffers are played in the order they are |
queued. If multiple buffers are queued, their times must be in ascending order or NULL; |
otherwise, an error occurs. The start time indicates when the actual audio data in the |
buffer is to be played (that is, the trim frames are not counted). |
outActualStartTime - On return, points to an AudioTimeStamp structure indicating when the buffer will |
actually play. |
Реализация выходного обратного вызова аудио-очереди
Соедините все это в Выходном Обратном вызове Аудио-очереди. Также названный обратным вызовом буфера воспроизведения, эта функция вызывается, когда аудио-очередь закончила с данными играться, и буфер доступен приложению для повторного использования. Приложения обычно сразу пополняют и ставят в очередь завершенный буфер в это время.
Уважайте информацию об обрезке и сбросьте количество пакетов для цикличного выполнения аудио.
Пример перечисления 3 выходного обратного вызова цикличного выполнения
void AQLooper::AQBufferCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) |
{ |
AQLooper *THIS = (AQLooper *)inUserData; |
if (THIS->mIsDone) return; |
UInt32 numBytes; |
UInt32 nPackets = THIS->GetNumPacketsToRead(); // generally enough for a half second of audio based on the |
// format -- see CalculateBytesForTime() from aqplay.cpp |
OSStatus result = AudioFileReadPackets(THIS->GetAudioFileID(), |
false, |
&numBytes, |
inCompleteAQBuffer->mPacketDescriptions, |
THIS->GetCurrentPacket(), |
&nPackets, |
inCompleteAQBuffer->mAudioData); |
if (result) printf("AudioFileReadPackets failed: %d", result); |
if (nPackets > 0) { |
UInt32 trimFramesAtStart = 0; |
UInt32 trimFramesAtEnd = 0; |
inCompleteAQBuffer->mAudioDataByteSize = numBytes; |
inCompleteAQBuffer->mPacketDescriptionCount = nPackets; |
if (THIS->mCurrentPacket == 0) { |
// at the beginning -- need to trim priming frames |
trimFramesAtStart = THIS->mPrimingFrames; |
} |
THIS->mCurrentPacket = (THIS->GetCurrentPacket() + nPackets); |
if (THIS->mCurrentPacket == THIS->mAudioFilePacketCount) { |
// at the end -- need to trim remainder frames |
inTrimFramesAtEnd = THIS->mRemainderFrames; |
// reset read from the beginning again |
THIS->mCurrentPacket = 0; |
} |
result = AudioQueueEnqueueBufferWithParameters(inAQ, |
inCompleteAQBuffer, |
0, |
NULL, |
trimFramesAtStart, |
trimFramesAtEnd, |
0, NULL, NULL, NULL); |
if (result) printf("AudioQueueEnqueueBufferWithParameters failed: %d", result); |
} |
} |
Ссылки:
Создание формата Core Audio (.caf) файлы
История версии документа
| Дата | Примечания |
|---|---|
| 09.08.2013 | Передовая статья |
| 20.02.2009 | Новый документ, обсуждающий данные о формате, требуемые к беспрепятственно циклу, сжал аудио с помощью Аудио-очереди. |