使用AVAssetWriter Wave到Caf格式

时间:2013-07-12 14:30:16

标签: ios ipad avassetwriter wave caf

使用AVAssetWriter Wave to Caf格式。 我有一个wave文件。 我想将其转换为Core Audio格式。

这是我一直在尝试的代码,无处可去。 尝试搜索所有论坛,但没有任何人找到的工作代码。

NSError *error = nil ;

NSDictionary *audioSetting = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithFloat:16000.0], AVSampleRateKey,
[ NSNumber numberWithInt:1], AVNumberOfChannelsKey,
[ NSNumber numberWithInt:kAudioFormatAppleIMA4], AVFormatIDKey, nil ];

NSString *audioFilePath = filePath;
AVURLAsset * URLAsset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:audioFilePath] options:nil];

if (!URLAsset) return NO ;

AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:URLAsset error:&error];
if (error) return NO;

/*NSArray *tracks = [URLAsset tracksWithMediaType:AVMediaTypeAudio];
if (![tracks count]) return NO;

AVAssetReaderAudioMixOutput *audioMixOutput = [AVAssetReaderAudioMixOutput
assetReaderAudioMixOutputWithAudioTracks:tracks
audioSettings :audioSetting];

AVAssetReaderOutput *audioOutput = [AVAssetReaderOutput ]
if (![assetReader canAddOutput:audioMixOutput]) return NO ;

[assetReader addOutput :audioMixOutput];
*/

if (![assetReader startReading]) return NO;

NSString *outPath = [filePath stringByDeletingPathExtension];
outPath = [outPath stringByAppendingPathExtension:@"caf"];

[[NSFileManager defaultManager] removeItemAtPath:outPath error:nil];
NSURL *outURL = [NSURL fileURLWithPath:outPath];
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:outURL
fileType:AVFileTypeCoreAudioFormat
error:&error];
if (error) return NO;

AVAssetWriterInput *assetWriterInput = [ AVAssetWriterInput assetWriterInputWithMediaType :AVMediaTypeAudio
outputSettings:audioSetting];
assetWriterInput. expectsMediaDataInRealTime = NO;

if (![assetWriter canAddInput:assetWriterInput]) return NO ;

[assetWriter addInput :assetWriterInput];

if (![assetWriter startWriting]) return NO;

[assetWriter startSessionAtSourceTime:kCMTimeZero ];

dispatch_queue_t queue = dispatch_queue_create( "assetWriterQueue", NULL );

[assetWriterInput requestMediaDataWhenReadyOnQueue:queue usingBlock:^{

NSLog(@"start");

while (1)
{
if ([assetWriterInput isReadyForMoreMediaData]) {

CMSampleBufferRef sampleBuffer = [audioMixOutput copyNextSampleBuffer];

if (sampleBuffer) {
[assetWriterInput appendSampleBuffer :sampleBuffer];
CFRelease(sampleBuffer);
} else {
[assetWriterInput markAsFinished];
break;
}
}
}

[assetWriter finishWritingWithCompletionHandler:^(void)
{
NSLog(@"CAF Completed");
}];

NSLog(@"finish");
}];
return YES;

如果有人能指出正确的方向,那将会非常有帮助。

2 个答案:

答案 0 :(得分:1)

试试这个,

NSString *wavFilePath = [[NSBundle mainBundle] pathForResource:@"sampleaudio" ofType:@"wav"];

NSURL *assetURL = [NSURL fileURLWithPath:wavFilePath];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];

NSError *assetError = nil;
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset
                                                           error:&assetError]
;
if (assetError) {
    NSLog (@"error: %@", assetError);
    return;
}

AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput
                                          assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
                                          audioSettings: nil];
if (! [assetReader canAddOutput: assetReaderOutput]) {
    NSLog (@"can't add reader output... die!");
    return;
}
[assetReader addOutput: assetReaderOutput];

NSString *strcafFileName = [NSString stringWithFormat:@"%@.caf",[wavFilePath stringByDeletingPathExtension]];
NSString *cafFilePath = [delegate.strCassettePathSide stringByAppendingPathComponent:strcafFileName];

NSURL *exportURL = [NSURL fileURLWithPath:cafFilePath];
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportURL
                                                      fileType:AVFileTypeCoreAudioFormat
                                                         error:&assetError];
if (assetError)
{
    NSLog (@"error: %@", assetError);
    return;
}

AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                [NSNumber numberWithFloat:11025], AVSampleRateKey,
                                [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
                                [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
                                [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
                                nil];
AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
                                                                          outputSettings:outputSettings];
if ([assetWriter canAddInput:assetWriterInput])
{
    [assetWriter addInput:assetWriterInput];
}
else
{
    NSLog(@"can't add asset writer input... die!");
    return;
}

assetWriterInput.expectsMediaDataInRealTime = NO;

[assetWriter startWriting];
[assetReader startReading];

AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
[assetWriter startSessionAtSourceTime: startTime];

__block UInt64 convertedByteCount = 0;
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);

[assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue
                                        usingBlock: ^
 {
     while (assetWriterInput.readyForMoreMediaData)
     {
         CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
         if (nextBuffer)
         {
             // append buffer
             [assetWriterInput appendSampleBuffer: nextBuffer];
             convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);

             CMSampleBufferInvalidate(nextBuffer);
             CFRelease(nextBuffer);
             nextBuffer = NULL;
         }
         else
         {
             [assetWriterInput markAsFinished];
             //              [assetWriter finishWriting];
             [assetReader cancelReading];

             break;
         }
     }
 }];

答案 1 :(得分:0)

我使用以下方法解决了问题:

  1. 在我的解决方案中导入此文件ExtAudioFileConvert.cpp。 (https://developer.apple.com/library/ios/samplecode/iPhoneExtAudioFileConvertTest/Listings/ExtAudioFileConvert_cpp.html) 此外,还导入了所有其他所需文件,即PublicUtility Folder

  2. 调用此函数DoConvertFile

  3. 示例代码

    CFURLRef sourceURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)sourcefilePath, kCFURLPOSIXPathStyle, false);
    
    CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)destinationFilePath, kCFURLPOSIXPathStyle, false);
    
    OSStatus error = DoConvertFile((sourceURL, destinationURL, kAudioFormatAppleIMA4, 16000.0 );