我想建立一个可靠的固态系统中使用SWIFT在我的应用程序建立一个节拍器。斯威夫特固体节拍器系统
我已经建立了使用NSTimer到目前为止似乎是一个坚实的系统..我现在唯一的问题是当计时器开始第2次点击是关闭时间,但随后它捕捉到一个坚实的时间表。
现在我所有的研究后,我看到有人提到你应该使用其他音频工具,不是靠的NSTimer ..或者,如果你选择使用的NSTimer那么就应该是在自己的线程。现在我看到很多人对此感到困惑,包括我自己,我很想深入这个节拍器业务的底部,并解决这个问题并与所有正在挣扎的人分享。
UPDATE
所以我已经实现,并在反馈我最后一次收到后,这一点清理。这里是我的代码的结构。它的播放。但我仍然得到一开始2次快速点击,然后它在定居。
我对我的无知这一个道歉。我希望我走在正确的道路上。
我目前原型的另一种方法为好。在哪里我有一个非常小的音频文件,只需点击一下,死循环结束,并持续正确的持续时间,直到获得特定节奏的循环点。我正在循环使用,效果很好。但唯一的事情是我没有得到检测回路点视觉更新,所以我有我的基本的NSTimer只是检测正在处理的音频下的定时间隔,它似乎对决非常好整个无延迟。但我仍然宁愿用这个NSTimer来得到它。如果您可以轻易发现我的错误,那么我们可以在正确的方向上再踢一次,我相信它很快就会有效!非常感谢。
//VARIABLES
//AUDIO
var clickPlayer:AVAudioPlayer = AVAudioPlayer()
let soundFileClick = NSBundle.mainBundle().pathForResource("metronomeClick", ofType: ".mp3")
//TIMERS
var metroTimer = NSTimer()
var nextTimer = NSTimer()
var previousClick = CFAbsoluteTimeGetCurrent() //When Metro Starts Last Click
//Metro Features
var isOn = false
var bpm = 60.0 //Tempo Used for beeps, calculated into time value
var barNoteValue = 4 //How Many Notes Per Bar (Set To Amount Of Hits Per Pattern)
var noteInBar = 0 //What Note You Are On In Bar
//********* FUNCTIONS ***********
func startMetro()
{
MetronomeCount()
barNoteValue = 4 // How Many Notes Per Bar (Set To Amount Of Hits Per Pattern)
noteInBar = 0 // What Note You Are On In Bar
isOn = true //
}
//Main Metro Pulse Timer
func MetronomeCount()
{
previousClick = CFAbsoluteTimeGetCurrent()
metroTimer = NSTimer.scheduledTimerWithTimeInterval(60.0/bpm, target: self, selector: Selector ("MetroClick"), userInfo: nil, repeats: true)
nextTimer = NSTimer(timeInterval: (60.0/Double(bpm)) * 0.01, target: self, selector: "tick:", userInfo: ["bpm":bpm], repeats: true)
}
func MetroClick()
{
tick(nextTimer)
}
func tick(timer:NSTimer)
{
let elapsedTime:CFAbsoluteTime = CFAbsoluteTimeGetCurrent() - previousClick
let targetTime:Double = 60/timer.userInfo!.objectForKey("bpm")!.doubleValue!
if (elapsedTime > targetTime) || (abs(elapsedTime - targetTime) < 0.003)
{
previousClick = CFAbsoluteTimeGetCurrent()
//Play the click here
if noteInBar == barNoteValue
{
clickPlayer.play() //Play Sound
noteInBar = 1
}
else//If We Are Still On Same Bar
{
clickPlayer.play() //Play Sound
noteInBar++ //Increase Note Value
}
countLabel.text = String(noteInBar) //Update UI Display To Show Note We Are At
}
}
感谢您的创意。我很欣赏详细的反馈。我会研究这一点,看看我能从这个建议中得出什么。会及时向大家发布。 – CakeGamesStudios
嗯...所以我看着这似乎我被卡住....我已经设置它,并存储我现在的时间点击使用CFAbsoluteTime它将存储时间就好了,但每次我存储一个新的值来比较它也是通过当前时间进行的,所以总是有一个偏移量被加到存储的时间上,用来比较前一次和当前时间以获得我的容忍度。我花了相当长的时间试图让这个工作。我也仔细看过了这个例子,但仍然不清楚该怎么做。任何进一步的解释将不胜感激。谢谢! – CakeGamesStudios
你能用CFAbsoluteTime发布你的更新代码吗? – vigneshv