AudioKit:调用“AudioKit.stop()”后无法重新启动 AudioKit 频率采样
Posted
技术标签:
【中文标题】AudioKit:调用“AudioKit.stop()”后无法重新启动 AudioKit 频率采样【英文标题】:AudioKit: can't restart AudioKit sampling of frequency after calling 'AudioKit.stop()' 【发布时间】:2020-06-05 22:12:02 【问题描述】:我正在使用 AudioKit 4.10。 我使用这个简单的代码来采样麦克风的频率和幅度:
import AudioKit
protocol MicAnalyzerDelegate
/**
* The MicAnalyzer calls this delegate function.
*/
func micAnalyzerInfos(infos: (frequency : Double, amplitude : Double)?)
class MicAnalyzer: NSObject
// MARK: - Properties
private static var micAnalyzer: MicAnalyzer = MicAnalyzer()
var delegate: MicAnalyzerDelegate?
fileprivate var mic: AKMicrophone!
fileprivate var tracker: AKFrequencyTracker!
fileprivate var silence: AKBooster!
fileprivate var timer: Timer?
// MARK: - Initializations
private override init()
super.init()
AKSettings.audioInputEnabled = true
self.initMicTracker()
private func initMicTracker()
/* Add the built-in microphone. */
mic = AKMicrophone()
/* Add a traker */
tracker = AKFrequencyTracker(mic)
silence = AKBooster(tracker, gain: 0)
// MARK: - Accessors
class func shared() -> MicAnalyzer
return micAnalyzer
func startMonitoring()
/* Start the microphone and analyzer. */
AudioKit.output = silence
do
try AudioKit.start()
catch
AKLog("AudioKit did not start!")
/* Initialize and schedule a new run loop timer. */
timer = Timer.scheduledTimer(timeInterval: 0.1,
target: self,
selector: #selector(MicAnalyzer.tick),
userInfo: nil,
repeats: true)
// Stopped as described here: https://github.com/AudioKit/AudioKit/issues/1716
func stopMonitoring()
do
AudioKit.disconnectAllInputs()
try AudioKit.stop()
try AudioKit.shutdown()
catch
print("AudioKit did not stop")
AudioKit.output = nil
// Interrupts polling on tick infos
timer?.invalidate()
timer = nil
var infos: (frequency : Double, amplitude : Double)?
if(!tracker.isStopped)
let frequency = tracker.frequency
let amplitude = tracker.amplitude
return (frequency: frequency, amplitude: amplitude)
else
return nil
/* Call the delegate. */
@objc func tick()
self.delegate?.micAnalyzerInfos(infos: infos)
按以下代码调用我有这种情况:
MicAnalyzer.shared().startMonitoring() // --> Everything works good
MicAnalyzer.shared().stopMonitoring() // --> I think it is stopped correctly
MicAnalyzer.shared().startMonitoring() // --> From now on the delegate is called but I get always 0 as frequency and amplitude
为什么在调用AudioKit.start()
(在MicAnalyzer.shared().startMonitoring()
内)后,我不能再对频率和幅度进行采样了?我应该如何重新开始整个事情?
如果我每次都重新启动变量mic
、tracker
和silence
,内存会增长,因为它们并没有真正被释放。
这是相同代码理念的第二个版本:
import AudioKit
protocol MicAnalyzerDelegate : class
/**
* The tuner calls this delegate function
*/
func micAnalyzerInfos(infos: (frequency : Double, amplitude : Double)?)
// https://audiokit.io/examples/MicrophoneAnalysis/
class MicAnalyzer: NSObject
// MARK: - Properties
private weak var delegate: MicAnalyzerDelegate?
fileprivate var mic: AKMicrophone!
fileprivate var tracker: AKFrequencyTracker!
fileprivate var silence: AKBooster!
fileprivate var timer: Timer?
// MARK: - Initializations
init(delegate: MicAnalyzerDelegate)
print("Init called!!!")
self.delegate = delegate
super.init()
deinit
print("Deinit called!!!")
// MARK: - Accessors
func startMonitoring()
AKSettings.audioInputEnabled = true
/* Add the built-in microphone. */
mic = AKMicrophone()
/* Add a traker */
tracker = AKFrequencyTracker(mic)
silence = AKBooster(tracker, gain: 0)
/* Start the microphone and analyzer. */
AudioKit.output = silence
do
try AudioKit.start()
catch
AKLog("AudioKit did not start!")
/* Initialize and schedule a new run loop timer. */
timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(MicAnalyzer.tick),
userInfo: nil,
repeats: true)
func stopMonitoring()
do
AudioKit.disconnectAllInputs()
try AudioKit.stop()
try AudioKit.shutdown()
catch
print("AudioKit did not stop")
AudioKit.output = nil
// Interrupts polling on tick infos
timer?.invalidate()
timer = nil
silence.stop()
silence = nil
tracker.stop()
tracker = nil
mic.stop()
mic = nil
var infos: (frequency : Double, amplitude : Double)?
if(!tracker.isStopped)
let frequency = tracker.frequency
let amplitude = tracker.amplitude
return (frequency: frequency, amplitude: amplitude)
else
return nil
/* Call the delegate. */
@objc func tick()
print(infos?.frequency ?? "0.0")
//self.delegate.micAnalyzerInfos(infos: infos)
然后我可以这样调用“第二个代码测试”:
override func viewDidAppear()
super.viewDidAppear()
print("viewDidAppear!!!")
tuner = Tuner(delegate: self)
tuner?.startMonitoring()
override func viewDidDisappear()
super.viewDidDisappear()
print("viewDidDisappear!!!")
tuner?.stopMonitoring()
tuner = nil
【问题讨论】:
【参考方案1】:您需要确保 AKFrequencyTracker 是信号链的一部分,因为这是 AVAudioEngine 引擎的要求。
这意味着如果你这样做:
do
AudioKit.disconnectAllInputs()
try AudioKit.stop()
try AudioKit.shutdown()
catch
// error handler
AudioKit.output = nil
您必须调用initMicTracker
才能让AKFrequencyTracker
回到信号链中。所以,要重新启动你会这样做:
因为你的 stopMonitoring 做了:
AudioKit.disconnectAllInputs(),表示(stop)MicTracker
您知道您已经为AKMicrophone
、AKFrequencyTracker
和AKBooster
创建了实例,将其从内存中释放
func stopMonitoring()
...
self.mic = nil
self.tracker = nil
self.silence = nil
【讨论】:
是的,我已经看到将“initMicTracker”放在 startMonitoring 的开头会开始采样(我应该写那个),但我有两个大问题。 1)即使我没有“disconnectAllInputs”也会发生这种情况 2)我尝试使用 XCode“Allocations Profiler”运行这样的程序(如你所建议的那样),每次我调用“startMonitoring”然后“stopMonitoring”内存分配增加...似乎内存中有些东西没有正确释放...这就是为什么我认为即使使用这个解决方案仍然不是正确的方法 如果要创建新实例或使用内存中的内容,您必须重置必须重新初始化的引用。我会将此添加到我的答案中,但我的解决方案只是为了回答原始问题...... 是的,是的,你是对的,我必须写得更好......谢谢你的耐心。我什至尝试停止它们,然后将它们置于停止监视内,但显示的“分配探查器”分配没有增长......(我在上面发布了第二个代码)我已经用我的当前代码更新了我的答案我正在尝试使用。 好吧,这似乎是另外一回事;您必须将 AudioKit 更新到最新版本或至少 4.9.5,然后返回此线程并留下反馈。 我现在已经从audiokit.io/downloads 安装了“AudioKit-macOS-4.9.5”框架,没什么新的,同样的内存问题。以上是关于AudioKit:调用“AudioKit.stop()”后无法重新启动 AudioKit 频率采样的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在播放 AudioKit 音序器时修改 MusicSequnce