###背景
SwiftでiPhoneアプリを開発中です。
アプリ内で、m4a
からwav
への音声変換を行おうとしています。
以下の記事を参考にしています。
Swift3でCore Audioを使用した音声ファイル変換 - Voicy Tech Blog
audio - iOS Code to Convert m4a to WAV - Stack Overflow
avAudioPlayer OSStatus error 2003334207 | Apple Developer Forums
###実現したいこと
convertAudio
メソッドを上手く動作させて、音声変換を行いたいです。
###該当のソースコード
- 音声変換メソッド
swift
1import AVKit 2import AVFoundation 3import AudioToolbox 4import CoreAudioKit 5 6/* m4a -> wav の音声変換 */ 7 func convertAudio(_ inFileUrl: URL, _ outFileUrl: URL) { 8 9 // ステータス 10 var status: OSStatus = noErr 11 12 // 変換元のm4aファイルを開く 13 var inFile: ExtAudioFileRef? 14 status = ExtAudioFileOpenURL(inFileUrl as CFURL, &inFile) 15 print("---> 01") 16 print(status) 17 print("<--- 01") 18 19 // 変換先のwavファイルを開く 20 var outFile: ExtAudioFileRef? 21 status = ExtAudioFileOpenURL(outFileUrl as CFURL, &outFile) 22 print("---> 02") 23 print(status) 24 print("<--- 02") 25 26 // 出力するwavファイルの情報を取得 27 var inASBDSize = UInt32(MemoryLayout<AudioStreamBasicDescription>.size) 28 var inFormat = AudioStreamBasicDescription() 29 30 /* *** ERROR!! *** */ 31 status = ExtAudioFileGetProperty(inFile!, kExtAudioFileProperty_FileDataFormat, &inASBDSize, &inFormat) 32 print("---> 03") 33 print(status) 34 print("<--- 03") 35 36 37 // wavファイル情報 38 var outASBDSize = UInt32(MemoryLayout<AudioStreamBasicDescription>.size) 39 var wavFormat = AudioStreamBasicDescription() 40 wavFormat.mFormatID = kAudioFormatLinearPCM 41 wavFormat.mSampleRate = 44100.0 42 wavFormat.mChannelsPerFrame = 1 43 AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, nil, &outASBDSize, &wavFormat) 44 45 // wavファイルファイルを開く 46 status = ExtAudioFileCreateWithURL(outFileUrl as CFURL, 47 kAudioFormatLinearPCM, 48 &wavFormat, 49 nil, 50 AudioFileFlags.eraseFile.rawValue, 51 &outFile) 52 print("---> 04") 53 print(status) 54 print("<--- 04") 55 56 57 58 /// MARK: 変換ルールの指定 59 60 // 書き込みプロパティ設定 61 status = ExtAudioFileSetProperty(outFile!, 62 kExtAudioFileProperty_ClientDataFormat, 63 inASBDSize, 64 &inFormat) 65 print("---> 05") 66 print(status) 67 print("<--- 05") 68 69 70 /// MARK: 変換処理 71 72 // バッファ作成 73 var readFrameSize: UInt32 = 1024 // 一度に読み込むフレーム数 74 var bufferSize = readFrameSize * inFormat.mBytesPerPacket 75 var buffer: UnsafeMutableRawPointer = malloc(Int(bufferSize)) 76 defer { free(buffer) } 77 78 var audioBuffer = AudioBufferList() 79 audioBuffer.mNumberBuffers = 1 80 audioBuffer.mBuffers.mNumberChannels = inFormat.mChannelsPerFrame 81 audioBuffer.mBuffers.mDataByteSize = bufferSize 82 audioBuffer.mBuffers.mData = buffer 83 84 // ファイルを読み込んで出力 85 while (true) { 86 // WAVファイル読み込み 87 ExtAudioFileRead(inFile!, &readFrameSize, &audioBuffer) 88 // 読み込むデータがなくなれば終了 89 if readFrameSize <= 0 { break } 90 // AACファイル書き込み 91 ExtAudioFileWrite(outFile!, readFrameSize, &audioBuffer) 92 } 93 94 95 /// MARK: ファイルを閉じる 96 97 ExtAudioFileDispose(inFile!) 98 ExtAudioFileDispose(outFile!) 99 }
- 呼び出し元
swift
1//audioM4aURL: URL? // result: file:///Users/Polaris/Library/Developer/CoreSimulator/Devices/7A5A0C5B-AB28-4582-86D8-652072416B1F/data/Containers/Data/Application/62BAB05E-D169-4886-9327-7F8B041E397A/Documents/2017-11-10-13-45-28.m4a 2 3// audioWavURL: URL? // result: "file:///Users/Polaris/Library/Developer/CoreSimulator/Devices/7A5A0C5B-AB28-4582-86D8-652072416B1F/data/Containers/Data/Application/63026CA3-FABA-474B-8FF6-10C819A00CBC/Documents/2017-11-10-15-45-45.wav" 4 5convertAudio(audioM4aURL!, audioWavURL!) 6
###発生している問題・エラーメッセージ
convertAudio
メソッドのExtAudioFileGetProperty(inFile!, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &srcFormat)
にて、
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
というエラーが表示され、アプリが落ちます。
inFile
にnil
が入っていることが原因のエラーだということはわかっています。
- コンソール
2017-11-11 01:17:00.088640+0900 enPiT2SUProduct[34488:655917] 231: EXCEPTION (2003334207): "open audio file" ---> 01 2003334207 <--- 01 2017-11-11 01:17:00.089532+0900 enPiT2SUProduct[34488:655917] 231: EXCEPTION (2003334207): "open audio file" ---> 02 2003334207 <--- 02 // ここでアプリが落ちる
###考えたこと
音声変換の途中で、 ExtAudioFileOpenURL(url as CFURL, &inFile)
という処理を行ったときに、url
が指す音声ファイルをinFile
にセットすれば、とりあえず、次の処理に進めるのではないかと考えました。
