我正在研究BLE项目,其中硬件记录音频数据&发送到iOS应用程序。我写了一个逻辑来转换数据中的mp3 / wav文件。
在这里,我从Data中编写了mp3文件转换逻辑,如下所示:
func storeMusicFile(data: Data) {
let fileName = "Record-1"
guard mediaDirectoryURL != nil else {
print("Error: Failed to fetch mediaDirectoryURL")
return
}
let filePath = mediaDirectoryURL!.appendingPathComponent("/\(fileName).mp3")
do {
try data.write(to: filePath, options: .atomic)
} catch {
print("Failed while storing files.")
}
}
但是在AVAudioPlayer中播放音频文件时,我收到“操作无法完成。(OSStatus错误1954115647。)”错误。
那么,混淆音频文件转换逻辑是错误还是硬件数据仍然需要解码?
答案 0 :(得分:1)
@ sagar-thummar的上一个答案为我节省了很多时间。不幸的是,我不允许对此进行投票或评论。 我需要做的一些更正是:
答案 1 :(得分:0)
要创建音频文件(.mp3 / .wav),必须动态计算头文件数据,并且需要在该头上附加来自硬件的实际传输音频数据。
在这里,我在下面添加了Swift 4代码片段作为参考
//MARK: Logic for Creating Audio file
class ARFileManager {
static let shared = ARFileManager()
let fileManager = FileManager.default
var documentDirectoryURL: URL? {
return fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
}
func createWavFile(using rawData: Data) throws -> URL {
//Prepare Wav file header
let waveHeaderFormate = createWaveHeader(data: rawData) as Data
//Prepare Final Wav File Data
let waveFileData = waveHeaderFormate + rawData
//Store Wav file in document directory.
return try storeMusicFile(data: waveFileData)
}
private func createWaveHeader(data: Data) -> NSData {
let sampleRate:Int32 = 2000
let chunkSize:Int32 = 36 + Int32(data.count)
let subChunkSize:Int32 = 16
let format:Int16 = 1
let channels:Int16 = 1
let bitsPerSample:Int16 = 8
let byteRate:Int32 = sampleRate * Int32(channels * bitsPerSample / 8)
let blockAlign: Int16 = channels * bitsPerSample / 8
let dataSize:Int32 = Int32(data.count)
let header = NSMutableData()
header.append([UInt8]("RIFF".utf8), length: 4)
header.append(intToByteArray(chunkSize), length: 4)
//WAVE
header.append([UInt8]("WAVE".utf8), length: 4)
//FMT
header.append([UInt8]("fmt ".utf8), length: 4)
header.append(intToByteArray(subChunkSize), length: 4)
header.append(shortToByteArray(format), length: 2)
header.append(shortToByteArray(channels), length: 2)
header.append(intToByteArray(sampleRate), length: 4)
header.append(intToByteArray(byteRate), length: 4)
header.append(shortToByteArray(blockAlign), length: 2)
header.append(shortToByteArray(bitsPerSample), length: 2)
header.append([UInt8]("data".utf8), length: 4)
header.append(intToByteArray(dataSize), length: 4)
return header
}
private func intToByteArray(_ i: Int32) -> [UInt8] {
return [
//little endian
UInt8(truncatingIfNeeded: (i ) & 0xff),
UInt8(truncatingIfNeeded: (i >> 8) & 0xff),
UInt8(truncatingIfNeeded: (i >> 16) & 0xff),
UInt8(truncatingIfNeeded: (i >> 24) & 0xff)
]
}
private func shortToByteArray(_ i: Int16) -> [UInt8] {
return [
//little endian
UInt8(truncatingIfNeeded: (i ) & 0xff),
UInt8(truncatingIfNeeded: (i >> 8) & 0xff)
]
}
func storeMusicFile(data: Data) throws -> URL {
let fileName = "Record \(Date().dateFileName)"
guard mediaDirectoryURL != nil else {
debugPrint("Error: Failed to fetch mediaDirectoryURL")
throw ARError(localizedDescription: AlertMessage.medioDirectoryPathNotAvaiable)
}
let filePath = mediaDirectoryURL!.appendingPathComponent("\(fileName).wav")
debugPrint("File Path: \(filePath.path)")
try data.write(to: filePath)
return filePath //Save file's path respected to document directory.
}
}