iPodライブラリからのファイル書き出し その2

※この記事の内容は、iOS4.2以降では正常に動作しない可能性があります。

iPodライブラリからの書き出し、第二回です。

前回、MP3からAACへの書き出しができないと書きましたが、おそらくAVAssetExportSessionがサポートしているファイルタイプにMP3がないからと思われます。supportedFileTypesメソッドで取得できるAVAssetExportSessionがサポートしているとおぼしきファイルタイプは以下のようなものです。

"com.apple.quicktime-movie",
"com.apple.m4a-audio",
"public.mpeg-4",
"com.apple.m4v-video",
"public.3gpp",
"org.3gpp.adaptive-multi-rate-audio",
"com.microsoft.waveform-audio",
"public.aiff-audio",
"public.aifc-audio"

オーディオで対応しているのは、「m4a」「3gpp」「wave」「aiff」「aifc」といったところのようです。

MP3の書き出しの他にも、WAVやAIFFの非圧縮ファイルをそのまま使いたい場合にも、ちょっとめんどくさい方法を使わないといけないようです。僕があれこれ試して成功した方法をとりあえず記録しておきます。もし他にスマートな方法がありましたらご指摘いただけるとうれしいです。

とりあえずコードです。前回のmediaPicker:didPickMediaItems:メソッドを以下のようにマルッと差し替えてください。あと、CoreMedia.Frameworkもインポートしてください。

- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
    MPMediaItem *item = [mediaItemCollection.items lastObject];
    NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:nil];
    
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
                                           initWithAsset:urlAsset
                                           presetName:AVAssetExportPresetPassthrough];
    
    
    NSArray *tracks = [urlAsset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *track = [tracks objectAtIndex:0];
    id desc = [track.formatDescriptions objectAtIndex:0];
    const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
    FourCharCode formatID = audioDesc->mFormatID;
    
    NSString *fileType = nil;
    NSString *ex = nil;
    
    switch (formatID) {
            
        case kAudioFormatLinearPCM:
        {
            UInt32 flags = audioDesc->mFormatFlags;
            if (flags & kAudioFormatFlagIsBigEndian) {
                fileType = @"public.aiff-audio";
                ex = @"aif";
            } else {
                fileType = @"com.microsoft.waveform-audio";
                ex = @"wav";
            }
        }
            break;
            
        case kAudioFormatMPEGLayer3:
            fileType = @"com.apple.quicktime-movie";
            ex = @"mp3";
            break;
            
        case kAudioFormatMPEG4AAC:
            fileType = @"com.apple.m4a-audio";
            ex = @"m4a";
            break;
            
        case kAudioFormatAppleLossless:
            fileType = @"com.apple.m4a-audio";
            ex = @"m4a";
            break;
            
        default:
            break;
    }
    
    exportSession.outputFileType = fileType;
    
    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *filePath = [[docDir stringByAppendingPathComponent:[item valueForProperty:MPMediaItemPropertyTitle]] stringByAppendingPathExtension:ex];
    exportSession.outputURL = [NSURL fileURLWithPath:filePath];
    
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        
        if (exportSession.status == AVAssetExportSessionStatusCompleted) {
            NSLog(@"export session completed");
        } else {
            NSLog(@"export session error");
        }
        
        [exportSession release];
    }];
}

では、ちょっと解説していきます。

AVAssetExportSessionのpresetNameは前回のM4AではなくAVAssetExportPresetPassthroughにしています。これはiPodライブラリから変換をせずにコピーをするpresetのようです。ただし、この場合、outputFileTypeに指定すべきファイルタイプをM4Aの時のように絞ってくれませんので、自分で調べる必要があります。

まず、AVURLAssetが持っているオーディオのAVAssetTrackを取得。さらにAVAssetTrackがもっているformatDescriptionsを取得。formatDescriptionsはNSArrayなのですが、その中に入ってるのはObjective-Cのオブジェクトではなくて、CMAudioFormatDescriptionRefというCarbon?なオブジェクトが入っています。このCMAudioFormatDescriptionRefからCMAudioFormatDescriptionGetStreamBasicDescription()という関数を使って、みなさんおなじみのAudioStreamBasicDescriptionが取得できますので、これを見て判断しています。

wavやaiffのLinearPCMなファイルはどちらもFileIDがkAudioFormatLinearPCMですので、エンディアンで違いを判別しています。

MP3はあれこれ試した結果、FileTypeを@”com.apple.quicktime-movie”にして、ファイル名に拡張子「.mp3」をつけておくと、ExtAudioFileで開くことができました。この挙動は試してみたらできちゃった的な感じなので、なにか正当な方法があるといいなと思っているのですが…。ちなみに、もしかしたらMP3以外もQuickTimeで共通でいけるんじゃないかと思ったのですが、MP3以外でもデータはコピーされるものの、ExtAudioFileでそのままOpenというわけにはいかないようです。

あと、何かが取得できなかった時とかのエラー処理とかはいっさいやってませんのであしからずご了承ください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です