Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Thursday, June 16, 2016

Simple Metronome

Simple Metronome


I'm trying to write a simple metronome, by playing a system sound every 0.25 seconds. I use GCD to play the clicks on a separate thread but the playing is uneven with the clicks coming sometimes as two quick beats followed by a slower beat. I Logged the time when the if statement in the loop is executed and its right on 0.25 seconds. I'm hoping I don't have to use Audio Queue Services. Any suggestions?

- (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];  }  

Answer by Jonathan M for Simple Metronome


The folks who put together http://www.metronomeonline.com/ did a pretty good job of dealing with the timing issues, though they weren't developing for any specific hardware/OS. I believe the way they did it was by creating pre-recorded .wav/.mp3 files for a few seconds for each tempo, then looped them. The loop rate is calculated to be tempo-accurate. By making the loop event the only thing that depends on client timing, they reduce timing errors.

Answer by Fernando Cervantes for Simple Metronome


Use an NSTimer for the time, and AVFoundation for the sounds.

Answer by Danra for Simple Metronome


A better approach would be to use a repeating NSTimer with the required interval. Your method churns the CPU.

Answer by jn_pdx for Simple Metronome


I went down the same route myself at one point with my metronome app. Unfortunately, you'll never get the precision you want with the high-level APIs like PlaySystemSound -- they just don't respond quickly enough.

More than likely, if you want true precision with your tempos and the sounds you play as your "clicks" you'll want to use Audio Units -- you might be able to get away with Audio Queue Services -- I didn't experiment much with it, realizing that I was going to need to get low-level at some point anyway, and opting to go all out.

Answer by Jean-Denis Muys for Simple Metronome


I would try to use :

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

You can also read http://atastypixel.com/blog/experiments-with-precise-timing-in-ios/ which is very interesting in your context...


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.