123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- //
- // PQCreateEmptyWAV.swift
- // PQSpeed
- //
- // Created by ak on 2020/9/16.
- // Copyright © 2020 BytesFlow. All rights reserved.
- // 功能: 生成指定长度的空 WAV 文件
- /*
- e.g.
- let tool = LYEmptyWAV(sampleRate: 44100,
- channel: 1,
- duration: 20,
- bit: 16);
- var documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
- documentPath.append("/test.wav")
- tool.createEmptyWAVFile(url: URL(fileURLWithPath: documentPath))
- 600 s 622028807.468433 622028844.650877
- */
- import UIKit
- import AudioToolbox
- import Foundation
- public class PQCreateEmptyWAV {
- // 采样率
- private var mSampleRate: Double = 44100
- // 声道
- private var mChannel: Double = 1
- // 时长
- private var mduration: Double = 5.0
- // 采样位数
- private var mbit: Double = 16
- public init(sampleRate: Double = 44100, channel: Double = 1, duration: Double, bit: Double = 16) {
- mSampleRate = sampleRate
- mChannel = channel
- mduration = duration
- mbit = bit
- if mduration == 0 {
- BFLog(message: "时长为0??")
- }
- BFLog(message: "mSampleRate is\(mSampleRate) mChannel is \(mChannel) mduration is:\(mduration) mbit is \(mbit)")
- }
- public func createEmptyWAVFile(url: URL, completeHander: @escaping (_ fileURL: URL?) -> Void) {
- DispatchQueue.global().async {
- // 数字音频文件大小(Byte) = 采样频率(Hz)× 采样时长(S)×(采样位数 / 8)× 声道数(单声道为1,立体声为2)
- // BFLog(message: "createEmptyWAVFile 1")
- let size = Int64(self.mSampleRate * self.mduration * (self.mbit / 8) * self.mChannel)
- let bufer = Array(repeating: 0, count: Int(size))
- // BFLog(message: "createEmptyWAVFile 2 \(size)")
- let data = Data(bytes: bufer, count: Int(size))
- let totalAudioLen = size
- let totalDataLen = totalAudioLen + 44
- // BFLog(message: "createEmptyWAVFile 3")
- self.writewaveFileHeader(output: url,
- totalAudioLen: totalAudioLen,
- totalDataLen: totalDataLen,
- longSampleRate: Int64(self.mSampleRate),
- channels: Int(self.mChannel),
- byteRate: size,
- audioData: data)
- DispatchQueue.main.async {
- completeHander(url)
- }
- }
- }
- public func createEmptyWAVFile(url: URL) {
- // 数字音频文件大小(Byte) = 采样频率(Hz)× 采样时长(S)×(采样位数 / 8)× 声道数(单声道为1,立体声为2)
- // BFLog(message: "createEmptyWAVFile 1")
- let size = Int64(mSampleRate * mduration * (mbit / 8) * mChannel)
- let bufer = Array(repeating: 0, count: Int(size))
- // BFLog(message: "createEmptyWAVFile 2 \(size)")
- let data = Data(bytes: bufer, count: Int(size))
- let totalAudioLen = size
- let totalDataLen = totalAudioLen + 44
- // BFLog(message: "createEmptyWAVFile 3")
- writewaveFileHeader(output: url,
- totalAudioLen: totalAudioLen,
- totalDataLen: totalDataLen,
- longSampleRate: Int64(mSampleRate),
- channels: Int(mChannel),
- byteRate: size,
- audioData: data)
- }
- public func writewaveFileHeader(output: URL, totalAudioLen: Int64,
- totalDataLen: Int64,
- longSampleRate: Int64,
- channels: Int,
- byteRate: Int64,
- audioData: Data)
- {
- BFLog(message: "createEmptyWAVFile 4")
- var header: [UInt8] = Array(repeating: 0, count: 44)
- // RIFF/WAVE header
- header[0] = UInt8(ascii: "R")
- header[1] = UInt8(ascii: "I")
- header[2] = UInt8(ascii: "F")
- header[3] = UInt8(ascii: "F")
- header[4] = (UInt8)(totalDataLen & 0xFF)
- header[5] = (UInt8)((totalDataLen >> 8) & 0xFF)
- header[6] = (UInt8)((totalDataLen >> 16) & 0xFF)
- header[7] = (UInt8)((totalDataLen >> 24) & 0xFF)
- // WAVE
- header[8] = UInt8(ascii: "W")
- header[9] = UInt8(ascii: "A")
- header[10] = UInt8(ascii: "V")
- header[11] = UInt8(ascii: "E")
- // 'fmt' chunk
- header[12] = UInt8(ascii: "f")
- header[13] = UInt8(ascii: "m")
- header[14] = UInt8(ascii: "t")
- header[15] = UInt8(ascii: " ")
- // 4 bytes: size of 'fmt ' chunk
- header[16] = 16
- header[17] = 0
- header[18] = 0
- header[19] = 0
- // format = 1
- header[20] = 1
- header[21] = 0
- header[22] = UInt8(channels)
- header[23] = 0
- header[24] = (UInt8)(longSampleRate & 0xFF)
- header[25] = (UInt8)((longSampleRate >> 8) & 0xFF)
- header[26] = (UInt8)((longSampleRate >> 16) & 0xFF)
- header[27] = (UInt8)((longSampleRate >> 24) & 0xFF)
- header[28] = (UInt8)(byteRate & 0xFF)
- header[29] = (UInt8)((byteRate >> 8) & 0xFF)
- header[30] = (UInt8)((byteRate >> 16) & 0xFF)
- header[31] = (UInt8)((byteRate >> 24) & 0xFF)
- // block align
- header[32] = UInt8(2 * 16 / 8)
- header[33] = 0
- // bits per sample
- header[34] = 16
- header[35] = 0
- // data
- header[36] = UInt8(ascii: "d")
- header[37] = UInt8(ascii: "a")
- header[38] = UInt8(ascii: "t")
- header[39] = UInt8(ascii: "a")
- header[40] = UInt8(totalAudioLen & 0xFF)
- header[41] = UInt8((totalAudioLen >> 8) & 0xFF)
- header[42] = UInt8((totalAudioLen >> 16) & 0xFF)
- header[43] = UInt8((totalAudioLen >> 24) & 0xFF)
- // guard let writeHandler = try? FileHandle(forWritingTo: output) else { return }
- var data = Data(header)
- data.append(audioData)
- BFLog(message: "createEmptyWAVFile 5")
- do {
- try data.write(to: output, options: .atomicWrite)
- BFLog(message: "createEmptyWAVFile 6 \(data.count)")
- } catch {
- BFLog(message: " write file error \(error)")
- }
- }
- }
|