Slowing metronome
A few nights ago I was wired and restless and couldn't sleep, and I wondered if there was something I could listen to
that would help me chill out. I searched around the Android app store for sleep-related apps, but most of them just
played noises of crickets or rain or new age music and it wasn't helping. I wanted something simple and rhythmic I could
focus on. Perhaps a
metronome.
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.
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 (yt@hjfreyer.com)
#
# 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[1])
start = float(argv[2]) / 60
end = float(argv[3]) / 60
tick(duration, start, end)
if __name__ == '__main__':
import sys
main(sys.argv)