But what tempo? Too fast and it'd keep me wired. Too slow and I'd be impatient and annoyed. So I had an idea: how about a metronome that slows down gradually over a long time period?
I eventually got to sleep, but I kept playing with the idea. Yesterday I decided to write it up. I grabbed my notebook and used the power of calculus to find a formula for the frequency of the metronome over time. The key condition was that I wanted the period between ticks to get longer by a fixed N% with each tick, so the change would be as uniform as possible.
Here's the formula for the frequency at time t, given that the metronome starts with frequency S and ends with frequency E after D seconds:
So I whipped up a little script using pygame and when going to sleep last night I set it to tick for 15 minutes, starting at 90 beats per minute, ending at 12 bpm. I don't remember when it stopped, so that's a good sign! Try it out and let me know if it works!
Download the code.
#!/usr/bin/env python # # Copyright 2011 Hunter Freyer (firstname.lastname@example.org) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A metronome with a gradually changing tempo. Usage: python metronome.py <duration> <bpm_at_start> <bpm_at_end>. For example, a metronome invoked with the following: python metronome.py 900 120 12 Would tick for 15 minutes, slowing from a starting beat of 2 beats per second to an ending rate of one beat every 5 seconds. Requires pygame. """ import pygame import math def tick(duration, start_rate, end_rate): pygame.mixer.pre_init(44100, -16, 2, 512) pygame.init() def rate(t): return (start_rate*end_rate*duration)/( t*(start_rate-end_rate) + end_rate*duration) clock = pygame.time.Clock() time = 0 tick_sound = pygame.mixer.Sound('SoMe TeXt To PlAy') print "Control-C to exit." while True: if time > duration: return tick_sound.play() time += clock.tick(rate(time)) / 1000.0 def main(argv): if len(argv) != 4: print __doc__ return -1 duration = float(argv) start = float(argv) / 60 end = float(argv) / 60 tick(duration, start, end) if __name__ == '__main__': import sys main(sys.argv)