views:

191

answers:

2

i want to create a button that allows the user to tap on it and thereby set a beats per minute. i will also have touches moved up and down on it to adjust faster and slower. (i have already worked out this bit).

what are some appropriate ways to get the times that the user has clicked on the button to get an average time between presses and thereby work out a tempo.

A: 

Each time the button is pressed, store the current date/time (with [NSDate date]). Then, the next time it's pressed, you can calculate the difference with -[previousDate timeIntervalSinceNow] (negative because it's subtracting the current date from the previous), which will give you the number of seconds.

jtbandes
+1  A: 

Overall

  1. You best use time() from time.h instead of an NSDate. At the rate of beats the overhead of creating an NSDate could result in an important loss of precision.

    I believe time_t is guaranteed to be of double precision, therefore you're safe to use time() in combination with difftime().

  2. Use the whole screen for this, don't just give the user 1 small button.

Two idea

Post-process

  1. Store all times in an array.

  2. Trim the result. Remove elements from the start and end that are more than a threshold from the average.

  3. Get the average from the remaining values. That's your speed.

  4. If it's close to a common value, use that.

Adaptive

  1. Use 2 variables. One is called speed and the other error.

  2. After the first 2 beats calculate the estimated speed, set error to speed.

  3. After each beat

    queue = Fifo(5)                        # First-in, first-out queue. Try out
                                           # different values for the length
    currentBeat = now - timeOflastBeat
    currentError = |speed - currentBeat|
    
    
    # adapt
    error = (error + currentError) / 2     # you have to experiment how much
                                           # weight currentError should have
    
    
    queue.push(currentBeat)                # push newest speed on queue
                                           # automatically removes the oldest
    speed = average(queue)
    
  4. As soon as error gets smaller than a certain threshold you can stop and tell the user you've determined the speed.

  5. Go crazy with the interface. Make the screen flash whenever the user taps. Extra sparks for a tap that is nearly identical to the expected time.

    Make the background color correspond to the error. Make it brighter the smaller the error gets.

Georg
i used the NSTimeInterval touchTime = [touch timestamp]; to get the time of the touch and then used your post process idea, thanks.
Aran Mulholland
Glad I could help. I think the adaptive version would be awesome. Try it when you've got time. :)
Georg