【问题标题】:How to merge two mp3 files iOS?如何合并两个 mp3 文件 iOS?
【发布时间】:2012-07-22 00:42:50
【问题描述】:

我的应用程序中有一个用户录音和另一个 mp3 文件,我希望用户能够将这两个文件作为一个文件导出,这意味着这两个文件将以某种方式合并或相互叠加。

如果不理解,两个 mp3 文件将同时播放,就像用户可以通过乐器录制歌曲的任何应用程序一样。

录音和乐器是两个独立的 mp3 文件,需要作为一个文件导出。

我该怎么做呢?根据我的阅读,我找不到解决方案。我看到很多关于连接两个音频文件的内容,但我不希望它们一个接一个地播放,而是同时播放。

谢谢。

编辑:我知道这已经很晚了,但如果有人偶然发现并正在寻找示例代码,我的答案就在这里:How can I overlap audio files and combine for iPhone in Xcode?

【问题讨论】:

  • 嗨,@gg13 帮了大忙,谢谢。

标签: iphone objective-c ios ipad audio


【解决方案1】:

如果我没听错的话,您是在要求音频混音器功能。这不是一项微不足道的任务。 看看Core Audio。一本好书是this one。 一种解决方案是创建一个无 GUI 的音频单元(混音器单元),它可以播放、混合和渲染两种信号 (mp3)。

除了编程方面,这里还有音频工程方面:您应该注意信号的电平。想象一下,您有 2 个相同的 0dB 级别的 mp3。如果你把它们加起来,你的水平将是+3dB。这在数字世界中不存在(最大为 0dB)。因此,您必须在混音前降低输入电平。

编辑:对于迟到的输入感到抱歉,但也许这对将来的某人有帮助:Apple has an example 我刚刚偶然发现的混音器。

【讨论】:

【解决方案2】:

如果您在 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)
    }

})           }

【讨论】:

  • trackDuration 变量未在代码中使用。这是一个被忽视的错误还是只是多余的代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 2019-05-19
  • 1970-01-01
  • 2011-04-28
  • 2011-12-06
相关资源
最近更新 更多