我能够将多个带有编码PCM音频的CAF文件加入其中。首先,我从一个CAF文件中读取数据格式。
UInt32 size = sizeof(srcFormatDescription);
status = AudioFileGetProperty(srcAudioFile, kAudioFilePropertyDataFormat, &size, &srcFormatDescription);
PCM数据格式的如下所示
[Line 7697] mSampleRate: 44100.000000
[Line 7698] mFormatID: 1819304813d
[Line 7699] mFormatFlags: 12d
[Line 7700] mBytesPerPacket: 2d
[Line 7701] mFramesPerPacket: 1d
[Line 7702] mBytesPerFrame: 2d
[Line 7703] mChannelsPerFrame: 1d
[Line 7704] mBitsPerChannel: 16d
[Line 7705] mReserved: 0d
然后我为目标文件设置数据格式,其中包含所有CAF。
destFormatDescription = srcFormatDescription;
status = AudioFileCreateWithURL(dest, kAudioFileCAFType, &destFormatDescription, kAudioFileFlags_EraseFile, &destAudioFile);
下一步我从CAF读取数据
status = AudioFileReadBytes(srcAudioFile,
FALSE,
currentStartForReading,
&bytesNumberToRead,
buffer);
并将其写入destAudioFile
status = AudioFileWriteBytes(destAudioFile,
FALSE,
writePosition,
&bytesNumberToWrite,
buffer);
这个步骤是在一个循环中完成的。它很棒。 但是我有很大的问题,现在我尝试对CAF文件执行相同的步骤,其中包含ALAC格式的数据。它不起作用。 AudioFileWriteBytes不支持返回错误操作。
ALAC数据格式的如下所示
[Line 7697] mSampleRate: 44100.000000
[Line 7698] mFormatID: 1634492771d
[Line 7699] mFormatFlags: 1d
[Line 7700] mBytesPerPacket: 0d
[Line 7701] mFramesPerPacket: 4096d
[Line 7702] mBytesPerFrame: 0d
[Line 7703] mChannelsPerFrame: 1d
[Line 7704] mBitsPerChannel: 0d
[Line 7705] mReserved: 0d
有人知道如何在Apple Lossless数据中加入多个CAF文件吗?
答案 0 :(得分:1)
我能够将多个带有编码PCM音频的CAF文件加入其中。首先,我从一个CAF文件中读取数据格式。
如果ASBD匹配,那么您的音频文件将是正确的。但是,如果输入文件的样本格式不匹配,那么您的数据将会损坏。这是因为每个CAF文件只定义一个样本数据块和一个音频描述块。
因此,尝试将多种格式的样本数据附加到一个音频数据块中将是错误的。 (未指定是否是您正在尝试的内容)
此外,压缩格式还有一个必须设置的附加字段 - 即魔术cookie。所有的cookie必须是相同的(这是一个不透明的数据表示,顺便说一下。)
最后,编写压缩数据的正确方法是使用Packet Table Chunks。 VBR / VFR格式必须只指定一个数据包表块。
有人知道如何在Apple Lossless数据中加入多个CAF文件吗?
这一切意味着什么:使用您在ALAC的情况下选择的方法将会出现高故障率。同样,还有很多东西可以保持这些文件及其块与所涉及的所有Packet详细信息正确同步。
所以,让我们从另一个角度来看待这个问题:
ExtAudioFileCreateWithURL
创建新的ALAC文件ExtAudioFileOpenURL
打开输入文件ExtAudioFileSetProperty
+ kExtAudioFileProperty_ClientDataFormat
指定常用PCM格式应该是它(但如果你正在处理原始的AudioFile API,它可能需要几百行代码。)
答案 1 :(得分:0)
我想知道你为什么没有尝试使用AVAssetExportSession
,AVMutableComposition
,AVAsset
,AVMutableCompositionTrack
。我建议您按照以下步骤合并/合并不同的音频文件。
AVAsset
。使用以下代码初始化AVMutableComposition
对象。
AVMutableComposition* mixComposition = [[AVMutableComposition alloc] init];
将可变音轨添加到可变组合中,如下所示。
AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
将资产时间范围添加到AudioTrack
,如下所示。
[AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeAdd(firstAsset.duration, secondAsset.duration)) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
创建AVAssetExportSession
并合并代码下的所有音频文件。
// Prepare final exporter for merging
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition AVAssetExportPresetAppleM4A];
exporter.outputURL = outputURL;
exporter.outputFileType = AVFileTypeAppleM4A;
exporter.videoComposition = mainCompositionInst;
exporter.shouldOptimizeForNetworkUse = YES;
// Notify caller that merging process is about tro start
[self.delegate handler:self didStartMergingAtPath:[outputURL path]];
[exporter exportAsynchronouslyWithCompletionHandler:^ {
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinishMerging:exporter];
});
}];
还实现检查导出过程状态的方法。
- (void)exportDidFinishMerging:(AVAssetExportSession*)session {
if(session.status == AVAssetExportSessionStatusCompleted){
// notify the calling class that merging is finished
[self.delegate handler:self didFinishMergingAtPath:[session.outputURL path]];
}
}
注意:请注意,这不是您可以直接用于代码的示例代码,但这仅用于理解目的。希望这可以帮到你。