iOS Swift - 合并 .wav 文件并将其转换为 .mp3

swiftIOS

1个回答

写回答

白炫宇

2025-06-26 14:05

+ 关注

移动
移动

合并和转换音频文件是移动应用开发中常见的需求之一。本文将介绍如何使用Swift语言将多个.wav文件合并,并将合并后的文件转换为.mp3格式。同时,我们还会在文章的中间段落中添加标题,并为标题添加标签,以增强可读性。

在开始之前,我们需要确保已经导入了AVFoundation和AudioToolbox框架,这两个框架提供了处理音频文件的功能。

首先,我们需要创建一个函数来合并.wav文件。以下是一个示例代码:

Swift

func mergeWavFiles(fileURLs: [URL]) -> URL? {

guard fileURLs.count > 1 else {

return nil

}

let composition = AVMutableComposition()

var nextStartTime = CMTime.zero

for fileURL in fileURLs {

let asset = AVURLAsset(url: fileURL)

let track = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)

do {

try track?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: asset.duration), of: asset.tracks(withMediaType: .audio)[0], at: nextStartTime)

} catch {

print("Error merging audio files: \(error.localizedDescription)")

return nil

}

nextStartTime = CMTimeAdd(nextStartTime, asset.duration)

}

let mergedFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("merged.wav")

guard let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) else {

return nil

}

exporter.outputFileType = .wav

exporter.outputURL = mergedFileURL

exporter.exportAsynchronously(completionHandler: {

if exporter.status == .completed {

print("Merge complete: \(mergedFileURL)")

} else if exporter.status == .fAIled {

print("Error merging audio files: \(exporter.error?.localizedDescription ?? "")")

}

})

return mergedFileURL

}

上述代码中,我们首先创建了一个AVMutableComposition对象,用于存储合并后的音频文件。然后,我们遍历传入的.wav文件URL数组,并将每个文件的音轨插入到composition中。最后,我们使用AVAssetExportSession将composition导出为.wav格式的文件。

要将.wav文件转换为.mp3格式,我们可以使用第三方库,例如LAME。以下是一个使用LAME库进行转换的示例代码:

Swift

import AVFoundation

import lame

func convertWavToMp3(wavFileURL: URL, mp3FileURL: URL) {

let pcmFilePath = wavFileURL.path

let mp3FilePath = mp3FileURL.path

let read = AVAudioFile(forReading: wavFileURL)

guard let pcmBuffer = AVAudioPCMBuffer(pcmFormat: read.processingFormat, frameCapacity: AVAudioFrameCount(read.length)) else {

return

}

do {

try read.read(into: pcmBuffer)

} catch {

print("Error converting audio file: \(error.localizedDescription)")

return

}

let mp3 = lame_init()

lame_set_in_samplerate(mp3, Int32(pcmBuffer.format.sampleRate))

lame_set_num_channels(mp3, Int32(pcmBuffer.format.channelCount))

lame_set_out_samplerate(mp3, Int32(pcmBuffer.format.sampleRate))

lame_set_brate(mp3, 128)

lame_set_mode(mp3, MONO)

lame_set_quality(mp3, 2)

lame_init_params(mp3)

let mp3File = fopen(mp3FilePath, "wb")

let pcmBufferList = UnsafeBufferPointer<AudioBuffer>(start: pcmBuffer.audioBufferList.pointee.mBuffers, count: Int(pcmBuffer.audioBufferList.pointee.mNumberBuffers))

for pcmBuffer in pcmBufferList {

let samples = pcmBuffer.mData?.assumingMemoryBound(to: Float.self)

let inputSamples = samples?.withMemoryRebound(to: Int16.self, capacity: Int(pcmBuffer.mDataByteSize) / MemoryLayout<Int16>.size) { $0 }

let outputBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 4096)

let outputBufferPointer = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?>.allocate(capacity: 1)

outputBufferPointer.initialize(to: outputBuffer)

let outputBufferSize = lame_encode_buffer(mp3, inputSamples, nil, Int32(pcmBuffer.frameLength), outputBufferPointer, 4096)

let outputData = Data(bytes: outputBuffer, count: Int(outputBufferSize))

fwrite(outputData.bytes, 1, outputData.count, mp3File)

outputBuffer.deallocate()

outputBufferPointer.deinitialize(count: 1)

outputBufferPointer.deallocate()

}

let outputBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 4096)

let outputBufferPointer = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?>.allocate(capacity: 1)

outputBufferPointer.initialize(to: outputBuffer)

let outputBufferSize = lame_encode_flush(mp3, outputBufferPointer, 4096)

let outputData = Data(bytes: outputBuffer, count: Int(outputBufferSize))

fwrite(outputData.bytes, 1, outputData.count, mp3File)

outputBuffer.deallocate()

outputBufferPointer.deinitialize(count: 1)

outputBufferPointer.deallocate()

lame_mp3_tags_fid(mp3, mp3File)

lame_close(mp3)

fclose(mp3File)

}

在上述代码中,我们首先使用AVAudioFile从.wav文件中读取PCM数据,并将其存储在AVAudioPCMBuffer中。然后,我们使用lame库将PCM数据编码为MP3格式,并将其写入到指定的.mp3文件中。

在中间段落中,我们添加了标题合并.wav文件转换为.mp3格式来提醒读者这两个部分的功能。这样,读者可以更加清晰地理解代码的作用。

本文介绍了如何使用Swift语言合并.wav文件并将其转换为.mp3格式。我们首先使用AVFoundation和AudioToolbox框架处理音频文件,然后使用AVMutableComposition和AVAssetExportSession合并.wav文件。接下来,我们使用第三方库LAME将.wav文件转换为.mp3格式。通过阅读本文,读者可以了解如何在移动应用开发中实现音频文件的合并和转换。

举报有用(4分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号