Технические вопросы и ответы QA1527

AUSampler - Добавление информации об инструменте и цикла указывает на файлы Core Audio

Q: Как я могу добавить информацию о Музыкальном инструменте и Демонстрационные Точки Цикла к Core Audio (.caf) файлы, таким образом, я могу использовать их с Аудиоустройством AUSampler?

A: Спецификация Формата файла Core Audio обеспечивает два типа блока для указания инструментальных данных включая информацию о цикличном выполнении к .caf файлу. Инструментальный тип блока и блоки Области сотрудничают, позволяя Вам создать список описаний Области, содержащих маркеры, аннотируя позицию (и) в аудиофайле, которые тогда именуются Инструментальным блоком для определения инструмента.

Для получения дополнительной информации посмотрите Спецификацию Формата аудио Огрызка и AudioFile.h который является частью AudioToolbox.framework.

Перечисление 1 демонстрирует, как добавить, что Инструментальный блок с синглом выдерживает область цикла, а также указание баса, низкий и высокий диапазон подачи, когда предоставленный открыть Core Audio File (.caf) файл.

Перечисление 1  

OSStatus SetupInstrument(AudioFileID inFileID,
                         UInt64 inFileLength,   // length in frames (samples)
                         UInt8 inBaseNote,      // MIDI note (0-127)
                         UInt8 inLowNote,       // MIDI note (0-127, <= inBaseNote)
                         UInt8 inHighNote) // MIDI note (0-127, >= inBaseNote)
{
 
    const UInt32 numRegionChunks = 1; // For our sustain loop, one region
    const UInt32 numMarkers = 2; // Two markers - One for loop start, one for loop end
    UInt32 totalChunkSize = 0;
 
    /**** Region Chunk ****/
 
    // Add up the total memory size we need to allocate for the variable-size AudioFileRegionList
 
    totalChunkSize += offsetof(AudioFileRegionList, mRegions);
    totalChunkSize += numRegionChunks * offsetof(AudioFileRegion, mMarkers);
    totalChunkSize += numRegionChunks * numMarkers * sizeof(AudioFileMarker);
 
    // Allocate the region chunk
 
    AudioFileRegionList *pRegionList = (AudioFileRegionList *) malloc(totalChunkSize);
    pRegionList->mNumberRegions = numRegionChunks;
    pRegionList->mSMPTE_TimeType = kCAF_SMPTE_TimeTypeNone; // Not used
 
    // Access the region
 
    AudioFileRegion *pRegion = &pRegionList->mRegions[0];
    pRegion->mRegionID = 6789; // Arbitrary, but must match the values used
                               // in the Instrument Chunk below
    pRegion->mName = NULL;
    pRegion->mNumberMarkers = numMarkers; // From above
    pRegion->mFlags = kAudioFileRegionFlag_LoopEnable |
                      kAudioFileRegionFlag_PlayForward; // enable forward looping for this region
 
    // Access the marker array
 
    AudioFileMarker *pMarkers = &pRegion->mMarkers[0];
 
    // Set up loop start
    pMarkers[0].mType = kCAFMarkerType_SustainLoopStart;
    memset(&pMarkers[0].mSMPTETime, 0, sizeof(pMarkers[0].mSMPTETime)); // zero out; not used
    pMarkers[0].mFramePosition = 0; // Loop from first sample
    pMarkers[0].mMarkerID = 1;
    pMarkers[0].mName = NULL; // Unused
    pMarkers[0].mChannel = 0; // Unused
 
    // Set up loop end
    pMarkers[1].mType = kCAFMarkerType_SustainLoopEnd;
    memset(&pMarkers[1].mSMPTETime, 0, sizeof(pMarkers[0].mSMPTETime)); // zero out; not used
    pMarkers[1].mFramePosition = inFileLength - 1; // Loop to the last sample
    pMarkers[1].mMarkerID = 2;
    pMarkers[1].mName = NULL; // Unused
    pMarkers[1].mChannel = 0; // Unused
 
    // Write out entire AudioFileRegionList into the file
    // Note that we use the full allocated size
 
    OSStatus err = AudioFileSetProperty(inFileID, kAudioFilePropertyRegionList, totalChunkSize, pRegionList);
     if (err) { free(pRegionList); return err; }
 
    // Set up Instrument Chunk, referencing the ID for the region chunk that we just wrote to the file
 
    CAFInstrumentChunk instChunk;
    instChunk.mBaseNote = (Float32) inBaseNote;
    instChunk.mMIDILowNote = inLowNote;
    instChunk.mMIDIHighNote = inHighNote;
    instChunk.mMIDILowVelocity = 0; // For this example, just setting full velocity range
    instChunk.mMIDIHighVelocity = 127;
    instChunk.mdBGain = 0.0f; // 0.0 dB means unity gain
    instChunk.mStartRegionID = 0; // Unused
    instChunk.mSustainRegionID = pRegion->mRegionID; // Set up above
    instChunk.mReleaseRegionID = 0; // Unused
    instChunk.mInstrumentID = 0;
 
    // CAF Specification requires all chunks to be BigEndian
 
    MakeCAFInstrumentBigEndian(&instChunk);
 
    // Write out CAFInstrumentChunk into the file
 
    err = AudioFileSetUserData(inFileID, kCAF_InstrumentChunkID, 0, sizeof(instChunk), &instChunk);
    free(pRegionList);
 
    return err;
}
#include <stddef.h>
#include "CAByteOrder.h" // from Core Audio public utilities
 
// CAF Files are big-endian, so the chunks contents need to be swapped
 
static void MakeCAFInstrumentBigEndian(CAFInstrumentChunk *chunk)
{
    chunk->mBaseNote = CASwapFloat32HostToBig(chunk->mBaseNote);
    chunk->mdBGain = CASwapFloat32HostToBig(chunk->mdBGain);
    chunk->mStartRegionID = CFSwapInt32HostToBig(chunk->mStartRegionID);
    chunk->mSustainRegionID = CFSwapInt32HostToBig(chunk->mSustainRegionID);
    chunk->mReleaseRegionID = CFSwapInt32HostToBig(chunk->mReleaseRegionID);
    chunk->mInstrumentID = CFSwapInt32HostToBig(chunk->mInstrumentID);
}


История версии документа


ДатаПримечания
29.05.2013

Новый документ, обсуждающий, как добавить информацию о Музыкальном инструменте и Демонстрационные Точки Цикла к Core Audio (.caf) файлы, таким образом, они могут использоваться с AUSampler.