簡體   English   中英

簡單的節拍器

[英]Simple Metronome

我試圖通過每0.25秒播放一次系統聲音來編寫一個簡單的節拍器。 我使用GCD來播放單獨一個帖子上的點擊,但是播放是不均勻的,點擊有時是兩個快節拍,然后是慢節拍。 我記錄了循環中if語句執行的時間,以及0.25秒的權限。 我希望我不必使用音頻隊列服務。 有什么建議么?

- (IBAction)start:(id)sender 
{
    dispatch_queue_t clickQueue; // the queue to run the metronome clicker
    dispatch_queue_t mainQueue; // I access the main queue to demonstrate how to change UIKit items
    //clickQueue = dispatch_queue_create("clickQueue", NULL);
    clickQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    mainQueue = dispatch_get_main_queue();
    dispatch_async(clickQueue, ^{
        double timeWas = [NSDate timeIntervalSinceReferenceDate];
        //delay by a 1/10 of a second so the first few clicks don't bunch up.
        double timeIs = [NSDate timeIntervalSinceReferenceDate]  - 0.1; 
        // playing starts out as NO because it gets switched at the end of the loop
        // and the PlaySystemSound block isn't off the queue yet. There is probably a
        // better way to do this.
        while (playing) {
            timeIs = [NSDate timeIntervalSinceReferenceDate] ;
            if ((timeIs - timeWas) > (60.0/240)) {
                AudioServicesPlaySystemSound(sound);
                timeWas = timeIs;
                // I want to flast the 200 label between orange and black but I have to access
                // user interface objects from the queue that they are running in, usually the
                // main queue.
                dispatch_async(mainQueue, ^{
                    if (flash)
                        [bpm setTextColor:[UIColor orangeColor]];
                    else
                        [bpm setTextColor:[UIColor blackColor]];
                    flash = !flash;
                });
            }
        }
    });
    playing = !playing;
    if (playing) 
        [startButton setTitle:@"Stop" forState:UIControlStateNormal];
    else
        [startButton setTitle:@"Start" forState:UIControlStateNormal];
}

當時使用NSTimer,聲音使用AVFoundation。

放在一起http://www.metronomeonline.com/的人們在處理時序問題方面做得非常好,盡管他們沒有針對任何特定的硬件/操作系統進行開發。 我相信他們這樣做的方法是為每個節奏創建預先錄制的.wav / .mp3文件幾秒鍾,然后循環播放。 循環速率計算為速度准確。 通過使循環事件成為唯一依賴於客戶端定時的事件,它們可以減少定時錯誤。

更好的方法是使用具有所需間隔的重復NSTimer。 您的方法會攪動CPU。

我用我的節拍器應用程序一次自己走同一條路。 不幸的是,你永遠無法通過像PlaySystemSound這樣的高級API獲得你想要的精度 - 他們只是沒有足夠快的響應。

更有可能的是,如果你想要你的節奏真正的精確度和你作為“點擊”播放的聲音,你將需要使用音頻單元 - 你可能能夠擺脫音頻隊列服務 - 我沒有實驗很多事情,意識到我無論如何都需要在某個時候達到低水平,並選擇全力以赴。

我會嘗試使用:

void dispatch_after(
   dispatch_time_t when,
   dispatch_queue_t queue,
   dispatch_block_t block);

您還可以閱讀http://atastypixel.com/blog/experiments-with-precise-timing-in-ios/ ,這在您的上下文中非常有趣......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM