在 Swift 中,我试图创建一个AUSamplerBankPresetData需要Unmanaged<CFURL>对象的对象。
如何快速将 URL 对象转换为Unmanaged<CFURL>Swift 对象?
我正在使用 AVAudioPlayerNode 在 Swift 中构建多轨音频播放器。当安排音频片段播放时,我希望在安排完成时以及文件播放完成时/如果完成时收到通知。从 Swift API 的编写方式看来,您只能注册其中之一。如果调用短函数:
func scheduleSegment(_ file: AVAudioFile,
startingFrame startFrame: AVAudioFramePosition,
frameCount numberFrames: AVAudioFrameCount,
at when: AVAudioTime?,
completionHandler: AVAudioNodeCompletionHandler? = nil)
Run Code Online (Sandbox Code Playgroud)
一旦文件被安排(不播放,只是安排播放),回调就会被调用,并且您不能传递任何特殊参数,只能传递一个基本的闭包。
当调用更高级的函数时,您可以指定您想要的回调类型,但是您必须选择一个且只能选择一个:
func scheduleSegment(_ file: AVAudioFile,
startingFrame startFrame: AVAudioFramePosition,
frameCount numberFrames: AVAudioFrameCount,
at when: AVAudioTime?,
completionCallbackType callbackType: AVAudioPlayerNodeCompletionCallbackType,
completionHandler: AVAudioPlayerNodeCompletionHandler? = nil)
Run Code Online (Sandbox Code Playgroud)
枚举 AVAudioPlayerNodeCompletionCallbackType 可以是以下之一:dataConsumed、dataRendered 或 dataPlayedBack
不幸的是我必须选择一个,但实际上我需要两个。当安排完成并且数据播放时我需要收到通知。
有没有办法做到这一点?
我使用本机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: …Run Code Online (Sandbox Code Playgroud) 我有一个 AVAudioPlayerNode 对象,它在播放完毕后发送回调。该回调会触发应用程序中的许多其他功能,其中之一会发出一条礼貌的 stop() 消息。由于某种原因,在 AVAudioPlayerNode 完成时调用 stop() 会导致崩溃。在此处的代码中,我对其进行了缩写,以便 AVAudioPlayerNode 仅立即调用 stop 来演示效果(而不是包括我的整个应用程序)。你可以清楚地看到它崩溃了。我不明白为什么。a) 节点仍在播放并且 stop() 停止它,或者 b) 节点播放完毕并且 stop 可以被忽略。
我的猜测是,这是某种边缘情况,它位于文件缓冲区的最末尾,并且处于不明确的状态,没有剩余的缓冲区,但技术上仍在播放。也许调用 stop() 尝试刷新剩余的缓冲区,但它们是空的?
func testAVAudioPlayerNode(){
let testBundle = Bundle(for: type(of: self))
let url = URL(fileURLWithPath: testBundle.path(forResource: "19_lyrics_1", ofType: "m4a")!)
let player = AVAudioPlayerNode()
let engine = AVAudioEngine()
let format = engine.mainMixerNode.outputFormat(forBus: 0)
engine.attach(player)
engine.connect(player, to: engine.mainMixerNode, format: format)
let delegate = FakePlayMonitorDelegate()
do {
let audioFile = try AVAudioFile(forReading: url)
let length = audioFile.length
player.scheduleFile(audioFile, at: nil, completionCallbackType: AVAudioPlayerNodeCompletionCallbackType.dataPlayedBack, completionHandler: …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现从苹果 WWDC 视频中获得的这段代码。但是视频是 2016 年的,我认为语法已经改变。我如何调用 sizeof(Float)?这会产生错误。
func render(buffer:AudioBuffer){
let nFrames = Int(buffer.mDataByteSize) / sizeof(Float)
var ptr = UnsafeMutableRawPointer(buffer.mData)
var j = self.counter
let cycleLength = self.sampleRate / self.frequency
let halfCycleLength = cycleLength / 2
let amp = self.amplitude, minusAmp = -amp
for _ in 0..<nFrames{
if j < halfCycleLength{
ptr.pointee = amp
} else {
ptr.pointee = minusAmp
}
ptr = ptr.successor()
j += 1.0
if j > cycleLength {
}
}
self.counter = j
}
Run Code Online (Sandbox Code Playgroud)