试图将某些代码从Obj-C移植到Swift时,我遇到了一些问题。
我在“ myData:Data”中加载了一个16位单声道WAF文件,并且由于音频文件是由我的应用程序创建的,我知道WAF标头是规范的44字节块,实际音频数据从此偏移量开始。
此音频流只是一系列字节对,每个对代表一个16位样本(Int16)。
因此,在这种Swift数据结构中,最有效的方法是在这样的字节对上进行访问并做一些工作,例如改变音量或将每个样本乘以-1以便反转音频流的相位?
我真的必须将字节对复制到本地Int16缓冲区中以更改它们,还是可以动态地指向UInt8字节的'myData'序列,所以指针当然知道每个对必须解释为带符号的Int16?
[我在Obj-C中所做的工作是使用NSData的getBytes:方法将2个字节的范围复制到临时Int16缓冲区中,然后将处理后的结果写回到我的音频文件的相同NSData实例中,只是循环WAV文件的整个数据块。
在Swift中,完全相同的方法行不通:
myData = Data(contentsOf: soundFileUrl!) // the 16bit mono WAW file
var audioSample: Int16 = 0
var dataChunkOffset = 44 // where the audio data begins after the file header
var localRange: ClosedRange = 0...0
var dataLength = myData.count - dataChunkOffset // length of the audio data chunk in the WAV file
while dataChunkOffset < dataLength {
localRange = dataChunkOffset...dataChunkOffset+1 // first 2 bytes at the beginning of the audio stream
audioSample = Int16(myData[localRange]) // ERROR: initializer ‘init(_:)’ requires that ‘Data’ conform to ‘BinaryInteger’
// do some sound manipulation with the audio sample like e.g phase invert
audioSample *= (-1)
dataChunkOffset += 2 // advance to the next pair of bytes
}
———
第10行中的此ERROR:是什么意思,我该如何摆脱它?
尽管渲染将脱机而不是实时进行,但我绝对在寻找一种更有效的方法(除了上面的代码之外)直接访问音频数据,而无需在while循环中进行整个复制工作!
有人有想法吗?
您想做的是这样的:
var data = // ...
// omitting the question of whether data has even number of bytes!
for i in 0..<data.count where i.isMultiple(of:2) { // each pair
// convert pair to Int16
var val : Int16 = 0
withUnsafeMutableBytes(of: &val) {
data[i...i+1].copyBytes(to:$0)
}
// do calculation
val += 1 // this is a stand-in for your calculations
// convert Int16 back to pair, stick it back into the data
let d = withUnsafeBytes(of:val) {Data($0)}
data[i...i+1] = d
}
直接来自此答案: