2012-07-22 69 views
3

我有一個用戶在我的應用程序中錄製和另一個mp3文件,我希望用戶能夠將這兩個文件導出爲一個文件,這意味着這兩個文件將以某種方式合併或放在彼此之上。如何合併兩個mp3文件的iOS?

如果沒有理解,兩個mp3文件將被同時播放,就像任何應用程序,用戶可以在樂器上錄製說,歌曲一樣。

錄音和樂器是兩個獨立的MP3文件,需要導出爲一個。

我該如何去做這件事?從我讀過的內容來看,我找不到解決方案。我在連接兩個音頻文件方面看到很多,但我不想讓他們一個接一個地播放,而是同時播放。

謝謝。

編輯:我知道這是遲到了,但萬一有人通過此絆倒,並一直在尋找示例代碼,它在我的答案在這裏:How can I overlap audio files and combine for iPhone in Xcode?

+0

嗨,這是一個偉大的幫助@ gg13,謝謝。 – Hima 2016-04-21 12:45:38

回答

3

如果我得到你的權利,你所要求的一個音頻混合器特徵。這不是一項簡單的任務。 看看Core Audio。一本好書首先是this one。 一個解決方案是創建一個無GUI的音頻單元(混音器單元),播放,混合和渲染兩個信號(mp3)。

除了編程方面,這裏還有一個音頻工程方面:您應該注意信號的電平。想象一下你有2個相同的MP3在0dB的水平。如果你總結他們,你的水平將是+ 3dB。這在數字世界中不存在(最大0dB)。因此,您必須在混合之前降低輸入電平。

編輯:對於遲來的輸入抱歉,但也許這有助於未來的某個人:Apple has an example對於我剛剛弄糟的音頻混音器。

+0

這看起來如何? http://stackoverflow.com/questions/7656512/combining-two-caf-files-on-iphone – gg13 2012-07-23 02:33:48

+0

看起來不錯。你有沒有嘗試過? – brainray 2012-07-23 05:59:44

+0

很抱歉這麼晚回到你身邊,但它的工作原理! – gg13 2012-08-09 00:40:39

3

如果您在2016年閱讀此內容,並且您正在尋找swift 2.x中的解決方案 - 我找到了您。我的解決方案實現了一個閉包,在寫入後返回輸出文件,以避免立即讀取零字節的文件,因爲該操作是異步操作。這特別適用於通過使用第一音軌的持續時間作爲總輸出持續時間來重疊兩個音軌。

func setUpAndAddAudioAtPath(assetURL: NSURL, toComposition composition: AVMutableComposition, duration: CMTime) { 
let songAsset: AVURLAsset = AVURLAsset(URL: assetURL, options: nil) 
let track: AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid) 
let sourceAudioTrack: AVAssetTrack = songAsset.tracksWithMediaType(AVMediaTypeAudio)[0] 
var error: NSError? = nil 
var ok: Bool = false 
let startTime: CMTime = CMTimeMakeWithSeconds(0, 1) 
let trackDuration: CMTime = songAsset.duration 
//CMTime longestTime = CMTimeMake(848896, 44100); //(19.24 seconds) 
let tRange: CMTimeRange = CMTimeRangeMake(startTime, duration) 
//Set Volume 
let trackMix: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: track) 
trackMix.setVolume(1.0, atTime: kCMTimeZero) 
audioMixParams.append(trackMix) 

//Insert audio into track 
try! track.insertTimeRange(tRange, ofTrack: sourceAudioTrack, atTime: CMTimeMake(0, 44100))} 


func saveRecording(audio1: NSURL, audio2: NSURL, callback: (url: NSURL?, error: NSError?)->()) { 
let composition: AVMutableComposition = AVMutableComposition() 

//Add Audio Tracks to Composition 
let avAsset1 = AVURLAsset(URL: audio1, options: nil) 
var track1 = avAsset1.tracksWithMediaType(AVMediaTypeAudio) 
let assetTrack1:AVAssetTrack = track1[0] 
let duration: CMTime = assetTrack1.timeRange.duration 
setUpAndAddAudioAtPath(audio1, toComposition: composition, duration: duration) 
setUpAndAddAudioAtPath(audio2, toComposition: composition, duration: duration) 

let audioMix: AVMutableAudioMix = AVMutableAudioMix() 
audioMix.inputParameters = audioMixParams 
//If you need to query what formats you can export to, here's a way to find out 
NSLog("compatible presets for songAsset: %@", AVAssetExportSession.exportPresetsCompatibleWithAsset(composition)) 

let format = NSDateFormatter() 
format.dateFormat="yyyy-MM-dd-HH-mm-ss" 
let currentFileName = "recording-\(format.stringFromDate(NSDate()))-merge.m4a" 

let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] 
let outputUrl = documentsDirectory.URLByAppendingPathComponent(currentFileName) 

let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) 
assetExport!.outputFileType = AVFileTypeAppleM4A 
assetExport!.outputURL = outputUrl 
assetExport!.exportAsynchronouslyWithCompletionHandler({ 
    audioMixParams.removeAll() 
    switch assetExport!.status{ 
    case AVAssetExportSessionStatus.Failed: 
     print("failed \(assetExport!.error)") 
     callback(url: nil, error: assetExport!.error) 
    case AVAssetExportSessionStatus.Cancelled: 
     print("cancelled \(assetExport!.error)") 
     callback(url: nil, error: assetExport!.error) 
    default: 
     print("complete") 
     callback(url: outputUrl, error: nil) 
    } 

})   } 
+0

代碼中未使用「trackDuration」變量。這是一個被忽視的錯誤還是隻是多餘的代碼? – 2016-09-13 12:02:22