- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用原生 Apple 类实现了 FFT 算法。我直接从他们的网站上获取了代码:
尽管如此,当我运行代码时,它每次都会提供不同的结果。我创建了一个单元测试,它重复运行它并比较单元测试失败时结果是否相同。我唯一的猜测是这是一个内存问题。这是我能想象每次结果都会不同的唯一方法。
import Foundation
import Accelerate
class AppleFFT{
var windowSize = 512
var n = vDSP_Length(512)
var halfN = Int(512 / 2)
var fftSetUp : FFTSetup?
var log2n : vDSP_Length?
init(windowSize: Int){
self.windowSize = windowSize
n = vDSP_Length(windowSize)
halfN = Int(n / 2)
initialize()
}
private init(){
initialize()
}
func initialize(){
log2n = vDSP_Length(log2(Float(n)))
if log2n == nil { return }
fftSetUp = vDSP_create_fftsetup(log2n!, FFTRadix(kFFTRadix2))
}
func process(signal : [Float], n: vDSP_Length) ->DSPSplitComplex{
let window = vDSP.window(ofType: Float.self,
usingSequence: .hanningDenormalized,
count: Int(n),
isHalfWindow: false)
let signal2 = vDSP.multiply(signal, window)
let observed: [DSPComplex] = stride(from: 0, to: Int(n), by: 2).map {
return DSPComplex(real: signal[$0],
imag: signal[$0.advanced(by: 1)])
}
var forwardInputReal = [Float](repeating: 0, count: halfN)
var forwardInputImag = [Float](repeating: 0, count: halfN)
var forwardInput = DSPSplitComplex(realp: &forwardInputReal,
imagp: &forwardInputImag)
vDSP_ctoz(observed, 2,
&forwardInput, 1,
vDSP_Length(halfN))
//Create some empty arrays we can put data into
var forwardOutputReal = [Float](repeating: 0, count: halfN)
var forwardOutputImag = [Float](repeating: 0, count: halfN)
var forwardOutput = DSPSplitComplex(realp: &forwardOutputReal,
imagp: &forwardOutputImag)
//Perform actual fft, placing results in forwardOutput
vDSP_fft_zrop(fftSetUp!,
&forwardInput, 1,
&forwardOutput, 1,
log2n!,
FFTDirection(kFFTDirection_Forward))
//Do cheap analysis to figure out original frequencies
let componentFrequencies = forwardOutputImag.enumerated().filter {
$0.element < -1
}.map {
return $0.offset
}
return forwardOutput
}
}
import XCTest
import Accelerate
class testAppleFFT: XCTestCase {
func testFFTConsistency(){
let signal = genSignalWith(frequencies:[100, 500], numSamples: 512, sampleRate: 44100)
let fft = AppleFFT(windowSize: 512)
let complex1 = fft.process(signal: signal , n: 512)
for i in 0..<10{
print("i = \(i)")
let complex2 = fft.process(signal: signal, n: 512)
var complex1realp = complex1.realp
var complex1imagp = complex1.imagp
var complex2realp = complex2.realp
var complex2imagp = complex2.imagp
for j in 0..<512 {
let r1 = complex1realp.pointee
let i1 = complex1imagp.pointee
let r2 = complex2realp.pointee
let i2 = complex2imagp.pointee
XCTAssert(abs(r1 - r2) < 0.00001)
XCTAssert(abs(i1 - i2) < 0.00001)
if !(abs(r1 - r2) < 0.00001){
print(" error: i: \(i) j: \(j) r1: \(r1) r2: \(r2)")
}
if !(abs(i1 - i2) < 0.00001){
print(" error: index: \(i) i1: \(i1) i2: \(i2)")
}
complex1realp = complex1realp.advanced(by: 1)
complex1imagp = complex1imagp.advanced(by: 1)
complex2realp = complex2realp.advanced(by: 1)
complex2imagp = complex2imagp.advanced(by: 1)
}
}
}
func genSignalWith(frequencies: [Float], numSamples: Int, sampleRate: Float, amplitudes: [Float] = []) -> [Float]{
var sig : [Float] = []
for t in 0..<numSamples{
var sum : Float = 0.0
for i in 0..<frequencies.count{
let f = frequencies[i]
var a : Float = 1.0
if(amplitudes.count > i){
a = amplitudes[i]
}
let thisValue = sin(Float(t) / sampleRate * 2 * .pi * f)
sum += thisValue
}
sig.append(sum)
}
return sig
}
}
最佳答案
这个:
var forwardInput = DSPSplitComplex(realp: &forwardInputReal,
imagp: &forwardInputImag)
vDSP_ctoz(observed, 2, &forwardInput, 1, vDSP_Length(halfN))
没有做你想做的事。它的问题有点微妙,特别是如果您有 C 或 C++ 背景。 swift 中的数组与 C 或 C++ 中的数组不同;特别是,它们在内存中没有固定地址。它们是 Swift 可能选择移动的对象。当您在 Swift 中工作时,这很好,但有时当您需要与 C 函数交互时(尤其是想要在函数调用之间保留指针的 C 类型,正如您所注意到的那样),有时会带来痛苦。
当您调用DSPSplitComplex(realp: &forwardInputReal, ...)
时,&
隐式创建 UnsafeMutablePointer<Float>
纪念forwardInputReal
,但是该指针仅在调用 init
期间有效。当您经过 forwardInput
至vDSP_ctoz
,指针已经超出范围并且不再有效,因此您正在调用未定义的行为。特别是,编译器可以假设对 vDSP_ctoz
的调用不修改 forwardInputReal
的内容或forwardInputImag
,因为该函数没有收到指向其内容的有效指针。
解决这个问题的最佳方法是更加明确:
forwardInputReal.withUnsafeMutableBufferPointer { r in
forwardInputImag.withUnsafeMutableBufferPointer { i in
var splitComplex = DSPSplitComplex(realp: r.baseAddress!, imagp: i.baseAddress!)
vDSP_ctoz(observed, 2, &splitComplex, 1, vDSP_Length(halfN))
}
}
// forwardInput[Real,Imag] now contain the de-interleaved data.
// splitComplex is out-of-scope and cannot be used, so the invalid pointers
// are discarded.
有一些事情可以让这件事变得更容易。
首先,有一个 change coming to the Swift compiler这将为您诊断此错误。
其次,我们可以将我展示的小舞蹈包装成一些方便的函数:
/// De-interleave the real and imaginary parts of a complex buffer into two
/// new Float arrays.
func ctoz<T>(_ data: T) -> (real: [Float], imag: [Float])
where T: AccelerateBuffer, T.Element == DSPComplex {
var imag = [Float]()
let real = [Float](unsafeUninitializedCapacity: data.count) { r, n in
imag = [Float](unsafeUninitializedCapacity: data.count) { i, n in
ctoz(data, real: &r, imag: &i)
n = data.count
}
n = data.count
}
return (real, imag)
}
/// De-interleave the real and imaginary parts of a complex buffer into two
/// caller-provided Float buffers.
///
/// - Precondition: data, real, and imag must all have the same length.
func ctoz<T, U, V>(_ data: T, real: inout U, imag: inout V)
where T: AccelerateBuffer, T.Element == DSPComplex,
U: AccelerateMutableBuffer, U.Element == Float,
V: AccelerateMutableBuffer, V.Element == Float
{
precondition(data.count == real.count && data.count == imag.count)
real.withUnsafeMutableBufferPointer { r in
imag.withUnsafeMutableBufferPointer { i in
var split = DSPSplitComplex(realp: r.baseAddress!, imagp: i.baseAddress!)
data.withUnsafeBufferPointer { d in
vDSP_ctoz(d.baseAddress!, 2, &split, 1, vDSP_Length(data.count))
}
}
}
}
定义了这些便利函数后,您可以执行以下操作:
var forwardInputReal = [Float](repeating: 0, count: halfN)
var forwardInputImag = [Float](repeating: 0, count: halfN)
ctoz(observed, real: &forwardInputReal, imag: &forwardInputImag)
甚至:
let (forwardInputReal, forwardInputImag) = ctoz(data)
我将与 vDSP 团队联系,看看我们是否无法在未来版本的框架中添加类似的内容,这样您就不需要自己编写它。
关于ios - Apple FFT 给出不一致的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58332930/
一直以来中国版Apple Watch心不支持心电图功能,不过近日Apple Watch心电图终于在国行版上线了!那么Apple Watch心国内版心电图要如何使用呢?下面一起来看看吧! App
我正在尝试将“使用 Apple 登录”添加到我现有的 App ID。检查启用它的选项后,显示以下弹出窗口:带有此消息: If you're enabling an App ID for the fir
我有一个并发症,可能需要每 5 分钟更新一次。这很容易总结为每天 120 次更新。有没有办法只在用户唤醒 watch 时更新? 最佳答案 我认为您的问题的答案是否,目前没有办法只在用户唤醒 watch
我们正在测试新 Sign in with Apple我们的应用程序的功能,并且在初始请求时,我们会提供用户的全名和电子邮件地址(如果用户启用了这些选项)。 但是在随后的请求中,此数据不仅提供 iden
在我的苹果 watch 扩展中,我想使用长按手势功能。是否有任何 api 等效于 UILongPressGestureRecognizer。我的要求是,在 watch 扩展上,我有表格想要长按单元格,
有没有办法以编程方式显示苹果 map 中多个点之间的路线,如谷歌地图? 最佳答案 正如 MKMapItem 文档所述: If you specify the MKLaunchOptionsDirect
我一直在互联网上关注很多教程来学习如何设置并发症。按预期设置并发症我没有问题。 直到初始时间线条目过期。 12 小时后,我不知道如何更新它以保持并发症的存在。我将在下面分享我拥有的所有内容,希望有人可
我看到一本书的描述...... 书上说 /^Apple/ 会匹配字符串开头有一个 Apple 的字符串。所以它将匹配 Apple Apple1 AppleApple AppleABC ...... 书
众所周知,您可以禁止从允许接收 Apple 通知的应用程序接收通知。但是有谁知道禁用是在本地进行的(忽略 Apple 发送到应用程序的通知),还是 Apple 停止从它的服务器向您发送通知? 最佳答案
我有一个 Apple id,我正在构建一个使用 Apple 推送通知服务的应用程序,但我对此有点困惑。 Apple 执行此过程是否收费?它可以在安装了我的应用程序的特定数量的设备上运行是否有任何限制?
我正在制作一个音频播放器应用。 在苹果的音乐应用中,如果音乐专辑或播客没有插图,则显示音符图像或播客图标图像而不是插图。 我想做同样的事情。 我可以在我的应用程序中使用苹果音乐应用程序中的图像吗? 苹
我有一个自定义框架,我正在归档以在另一个项目中使用。更新到 Xcode11 后,我在使用该框架的项目中收到以下错误。 找不到目标“x86_64-apple-ios-simulator”的模块“MyCu
我有一个在 iOS 上运行良好的应用程序,但是当使用催化剂运行时,如果我在 macOS 上滑动到另一个虚拟桌面,然后再返回大约 10 次,它会间歇性地崩溃。它主要发生在 UICollectionVie
我正在使用 Xcode 开发 Apple Watch 应用程序。我想在屏幕的左上角放置一些文本,与列出时间的位置相邻。 当我将标签向上拖动到屏幕的一部分时,它会自动向下对齐。 我看到大多数 Apple
我似乎找不到在哪里设置我的 Apple Watch 应用程序的产品名称。我确实看到了产品名称选项,但更新它没有任何作用。也看不到文档中的任何内容 最佳答案 为了让您的应用程序名称在 iPhone 上的
问题:如何在我的服务器产品的安装程序中安全地包含推送通知所需的 SSL 证书? 背景:Apple 推送通知要求客户端 SSL 证书位于向 Apple 发出调用的服务器上。 我的产品采用传统的客户端/服
我已经在我的网站上实现了 Sign In with Apple。但问题是它只适用于我开发者的 Apple ID。 我尝试在同一环境中使用我的个人 Apple ID,并且登录过程也运行良好。 但是,当真
我的苹果触摸图标中的白色背景变黑了??我的白色背景不透明。该图标有一个白色三角形、红色圆圈和黑色文本。我唯一能辨认出来的是白色三角形和红色圆圈。知道是什么导致了这种情况以及如何使图标保持白色背景吗?
我正在考虑制作一个使用加速度计的 watchOS2 应用程序。如果应用程序在后台运行,它是否仍然能够接收来自加速度计或 CMMotionManager 的输入? 最佳答案 只有当 watchOS2 应
我想切换 Apple App Loader 使用的 Apple ID。 我找不到更改应用程序本身使用的帐户的方法。谷歌搜索没有带来任何有用的信息。当我启动加载程序应用程序时,它给我一个错误:“...您
我是一名优秀的程序员,十分优秀!