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. |