Cooper Baker · Ringtones

Ringtones is an interactive installation piece that generates algorithmic music based on any ten digit number dialed by a participant. Ten digits equates to ten billion unique phone numbers which means the phone is capable of creating ten billion unique pieces of music. In order to achieve this the phone's original circuitry was removed and a microcontroller was grafted into useful parts such as the keypad, hook, indicator light, and speaker. Basically, the microcontroller's program senses the state of the hook, waits for a phone number, then configures and plays the synthesis algorithm.

Ringtones has been exhibited at the 2008 Los Angeles Bent Festival, the 2008 Sound in Space Festival, and the 2009 UCSD Spring Music Festival.

Gallery

phone film crew

phone hacking

phone patron

ringtones close

ringtones far

ringtones phone

uc installed

ucsd cpmc

wall phone
ringtones.cpp
    1 /*============================================================================
    2  *  Ringtones
    3  *  (c) Cooper Baker 2008
    4  *  [tab] is 4 spaces for this file
    5 /*==========================================================================*/
    6 
    7 // include this header for arduino environment
    8 #include <WProgram.h>
    9 
   10 //= PROTOTYPES ===============================================================
   11 void setup( void );
   12 void loop( void );
   13 
   14 void composer( void );
   15 void song( void );
   16 void poll_keys( void );
   17 void dial_tone( void );
   18 void key_tone( float hertz, byte key_num );
   19 
   20 void tone( float hertz, float msec );
   21 void rest( float msec );
   22 
   23 void notewrap( int *note );
   24 void freqwrap( float *freq );
   25 
   26 void polytonic_scale( int note, int semitones, int iterations, float tone_msec, float pause_msec );
   27 void freq_scale( float freq, float freq_inc, int iterations, float tone_msec );
   28 void rand_freqs( float bot_freq, float top_freq, int iterations, float min_msec, float max_msec );
   29 void bounce_up( float freq, float initial_msec_length, float decrement_coeff );
   30 void bounce_down( float freq, float initial_msec_length, float decrement_coeff );
   31 void dyad_scale( int note, int interval, int scale_interval, int iterations, float msec_length );
   32 void freq_mirror( float freq, float initial_msec_length, float decrement_coeff );
   33 void num_melody( float tone_msec, float rest_msec, int octaves );
   34 
   35 //= VARIABLES ================================================================
   36 // These variables configure the i/o pins
   37 byte            key_pin[]       = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
   38 byte            HOOK            = 11;
   39 byte            SPEAKER         = 12;
   40 byte            LED             = 13;
   41 
   42 // This array holds the state of each key
   43 byte            key_state[]     = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   44 
   45 // More state variables below
   46 byte            on_hook         = 0;
   47 byte            speaker_state   = 0;
   48 byte            led_state       = 0;
   49 
   50 // Phone number variables
   51 byte            num[]           = { 6,6,1, 4,7,8, 4,0,6,8 };
   52 byte            num_index       = 0;
   53 
   54 // These variables are for the oscillator
   55 double          half_cyc_uc     = 0;
   56 unsigned int    cycles_2x       = 0;
   57 
   58 // These are the keypad key frequencies
   59 float           dtmf[]          = { 569.25, 476.5, 508.25, 536.75, 494.75, 526.5, 561.75, 515.25, 547, 582.25 };
   60 
   61 // This array defines a hertz value for each midi note 
   62 float           midi_note[]     = { 8.175799, 8.661957, 9.177024, 9.722718, 10.3, 10.913383, 11.562325, 12.25, 12.978271, 13.75, 14.567617, 15.433853, 16.351599, 17.323914, 18.354048, 19.445436, 20.601723, 21.826765, 23.124651, 24.5, 25.956543, 27.5, 29.135235, 30.867706, 32.703197, 34.647827, 36.708096, 38.890873, 41.203445, 43.65353, 46.249302, 49., 51.913086, 55., 58.27047, 61.735413, 65.406395, 69.295654, 73.416191, 77.781746, 82.406891, 87.30706, 92.498604, 97.998856, 103.826172, 110., 116.540939, 123.470825, 130.81279, 138.591309, 146.832382, 155.563492, 164.813782, 174.61412, 184.997208, 195.997711, 207.652344, 220., 233.081879, 246.94165, 261.62558, 277.182617, 293.664764, 311.126984, 329.627563, 349.228241, 369.994415, 391.995422, 415.304688, 440., 466.163757, 493.883301, 523.25116, 554.365234, 587.329529, 622.253967, 659.255127, 698.456482, 739.988831, 783.990845, 830.609375, 880., 932.327515, 987.766602, 1046.502319, 1108.730469, 1174.659058, 1244.507935, 1318.510254, 1396.912964, 1479.977661, 1567.981689, 1661.21875, 1760., 1864.655029, 1975.533203, 2093.004639, 2217.460938, 2349.318115, 2489.015869, 2637.020508, 2793.825928, 2959.955322, 3135.963379, 3322.4375, 3520., 3729.31, 3951.066406, 4186.009277, 4434.921875, 4698.63623, 4978.031738, 5274.041016, 5587.651855, 5919.910645, 6271.926758, 6644.875, 7040., 7458.620117, 7902.132812, 8372.018555, 8869.84375, 9397.272461, 9956.063477, 10548.082031, 11175.303711, 11839.821289, 12543.853516 };
   63 
   64 // This array keeps track of elapsed milliseconds
   65 unsigned long   msec[]          = { 0, 0 };
   66 
   67 int             elapsed         = 0;
   68 
   69 //= SETUP ====================================================================
   70 void setup( void )
   71 {
   72     int i;
   73     
   74     // sets up key pins as inputs and turns on pull-up resistors
   75     for( i = 0 ; i < 10 ; i++ )
   76     {
   77         pinMode( key_pin[ i ], INPUT );
   78         digitalWrite( key_pin[ i ], HIGH );
   79     }
   80         
   81     // set hook pin to input and turn on pull-up resistor
   82     pinMode( HOOK, INPUT );
   83     digitalWrite( HOOK, HIGH );
   84     
   85     // set up and init output pins
   86     pinMode( SPEAKER, OUTPUT );
   87     pinMode( LED, OUTPUT );
   88     digitalWrite( SPEAKER, LOW );
   89     digitalWrite( LED, LOW );   
   90     
   91     //play a 'ready' tone
   92     for( i = 5000 ; i > 2000 ; i -= 333 )
   93         tone( i, 7 );
   94     for( i = 2000 ; i < 5000 ; i += 333 )
   95         tone( i, 7 );
   96 }
   97 
   98 //= LOOP =====================================================================
   99 void loop( void )
  100 {   
  101     // this keeps track of millisecond values
  102     msec[ 1 ] = msec[ 0 ];
  103     msec[ 0 ] = millis();
  104     
  105     // this block blinks the led every five seconds
  106     if( msec[ 0 ] != msec[ 1 ] )
  107     {
  108         elapsed++;
  109         if( elapsed > 3933 )
  110         {
  111             elapsed = 0;
  112             digitalWrite( LED, 1 );
  113             delay( 66 );
  114             digitalWrite( LED, 0 );
  115         }   
  116     }
  117     
  118     // poll the hook pin
  119     on_hook = digitalRead( HOOK ); 
  120 
  121     while( !on_hook )
  122     {
  123         // reset phone number memory
  124         num_index = 0;
  125         
  126         // acquire a ten digit phone number
  127         while( num_index < 10 && !on_hook )
  128         {
  129             poll_keys();
  130             on_hook = digitalRead( HOOK );
  131             if( num_index < 1 )
  132                 dial_tone();
  133         }
  134         
  135         // look for specific numbers
  136         if(   num[0]== 0 &&num[1]== 0 &&num[2]== 0
  137             &&num[3]== 0 &&num[4]== 0 &&num[5]== 0
  138             &&num[6]== 0 &&num[7]== 0 &&num[8]== 0 &&num[9]== 0 )
  139         {
  140             song();
  141         }
  142         else
  143         {
  144             rest( 500 );
  145             composer();
  146             rest( 1500 );
  147         }
  148 
  149         // poll the hook pin
  150         on_hook = digitalRead( HOOK );
  151     }
  152 }
  153 
  154 //= FUNCTIONS ================================================================
  155 
  156 // song() used to test settings of sound algorithms
  157 void song( void )
  158 {
  159     bounce_up( 100, 100, 0.99);
  160 }
  161 
  162 // composer() sets algorithms' attributes and plays them
  163 void composer( void )
  164 {
  165     // increment and index variables
  166     byte i, j;
  167     byte a, b, c, d, e;
  168 
  169     // this for loop acts as an index that increments through the phone number
  170     for( i = 0 ; i < 10 ; i++ )
  171     {
  172         // this block makes alternate indicies to get different parts of the phone number
  173         a = i + 1; if( a > 9 ) a -= 9;
  174         b = i + 2; if( b > 9 ) b -= 9;
  175         c = i + 3; if( c > 9 ) c -= 9;
  176         d = i + 4; if( d > 9 ) d -= 9;
  177         e = i + 5; if( e > 9 ) e -= 9;
  178         
  179         // this for loop plays groups of different sounds based on the phone number
  180         for( j = 0 ; j <= num[ a ] ; j += 3 )
  181         {
  182             // this switch chooses a series of sounds to play based on the current number
  183             switch( num[ i ] )
  184             {
  185                 default:
  186 
  187                 case 0 :    num_melody( ( num[ a ] + 4 ), ( num[ b ] + 1 ) * 2, num[ c ] * 0.5 );
  188                             break;
  189                             
  190                 case 1 :    bounce_up( ( num[ a ] + 1 ) * 100, ( num[ b ] + 1 ) * 12, (float)( num[ c ] + 40 ) / 50 );
  191                             bounce_down( ( num[ a ] + 1 ) * 1000, ( num[ b ] + 1 ) * 8, (float)( num[ c ] + 20 ) / 30 );
  192                             break;
  193                             
  194                 case 2 :    bounce_down( ( num[ b ] + 1 ) * 1000, ( num[ c ] + 1 ) * 8, (float)( num[ d ] + 1 ) / 20 );
  195                             polytonic_scale( num[ a ] + 48, num[ b ] - 4, num[ c ] + 10, ( num[ d ] + 1 ) * 3, ( num[ e ] + 1 ) * 20 );
  196                             freq_mirror( ( num[ a ] + 1 ) * 150, ( num[ b ] + 1 ) * 7, (float)( num[ c ] + 20 ) / 30 );
  197                             break;
  198                             
  199                 case 3 :    polytonic_scale( num[ a ] + 48, num[ b ] - 4, num[ c ] + 10, ( num[ d ] + 1 ) * 4, ( num[ e ] + 1 ) * 25 );
  200                             freq_mirror( ( num[ b ] + 1 ) * 150, ( num[ c ] + 1 ) * 5, (float)( num[ d ] + 20 ) / 30 );
  201                             break;
  202                             
  203                 case 4 :    freq_mirror( ( num[ b ] + 1 ) * 150, ( num[ c ] + 1 ) * 5, (float)( num[ d ] + 20 ) / 30 );
  204                             dyad_scale( ( num[ b ] + 1 ) * 2 + 48, num[ c ] * 2 - 9, num[ d ] * 2 - 7, num[ e ] + 4, ( num[ a ] + 1 ) * 5 );
  205                             polytonic_scale( num[ a ] + 48, num[ b ] - 4, num[ c ] + 10, ( num[ d ] + 1 ) * 3, ( num[ e ] + 1 ) * 20 );
  206                             break;
  207                             
  208                 case 5 :    freq_scale( ( num[ a ] + 1 ) * 50, ( num[ b ] + 1 ) * 3, ( num[ c ] + 1 ) * 10, ( num[ d ] + 1 ) * 3 );
  209                             dyad_scale( ( num[ b ] + 1 ) * 2 + 48, num[ c ] * 2 - 9, num[ d ] * 2 - 7, num[ e ] + 4, ( num[ a ] + 1 ) * 5 );
  210                             rand_freqs( ( num[ a ] + 1 ) * 50, ( num[ b ] + 1 ) * 400, ( num[ c ] + 1 ) * 2, ( num[ c ] + 5 ) * 3, ( num[ d ] + 5 ) * 6 );
  211                             break;
  212 
  213                 case 6 :    freq_mirror( ( num[ b ] + 1 ) * 150, ( num[ c ] + 1 ) * 5, (float)( num[ d ] + 20 ) / 30 );
  214                             polytonic_scale( num[ b ] + 32, num[ c ] - 4, num[ d ] + 11, ( num[ e ] + 1 ) * 3, ( num[ a ] + 1 ) * 20 );
  215                             dyad_scale( ( num[ a ] + 1 ) * 2 + 24, num[ b ] * 2 - 9, num[ c ] * 2 - 7, num[ d ] + 4, ( num[ e ] + 1 ) * 5 );
  216                             break;
  217 
  218                 case 7 :    rand_freqs( ( num[ a ] + 1 ) * 50, ( num[ b ] + 1 ) * 100, ( num[ c ] + 1 ) * 2, ( num[ c ] + 10 ) * 2, ( num[ d ] + 3 ) * 6 );
  219                             rand_freqs( ( num[ b ] + 1 ) * 50, ( num[ c ] + 1 ) * 250, ( num[ d ] + 1 ) * 2, ( num[ e ] + 10 ) * 2, ( num[ a ] + 3 ) * 6 );
  220                             break;
  221 
  222                 case 8 :    bounce_up( ( num[ a ] + 1 ) * 100, ( num[ b ] + 1 ) * 3, (float)( num[ c ] + 20 ) / 30 );
  223                             freq_mirror( ( num[ a ] + 1 ) * 150, ( num[ b ] + 1 ) * 5, (float)( num[ c ] + 40 ) / 50 );
  224                             bounce_down( (num[ a ] + 1 ) * 1000, ( num[ b ] + 1 ) * 3, (float)( num[ c ] + 20 ) / 30 );
  225                             break;
  226 
  227                 case 9 :    bounce_up( ( num[ a ] + 1 ) * 100, ( num[ b ] + 1 ) * 7, (float)( num[ c ] + 15 ) / 30 );
  228                             rand_freqs( ( num[ a ] + 1 ) * 50, ( num[ b ] + 1 ) * 300, ( num[ c ] + 1 ) * 2, ( num[ c ] + 10 ) * 2, ( num[ d ] + 3 ) * 6 );
  229                             break;
  230             }
  231         }
  232     }
  233 }
  234 
  235 // looks for a pressed key
  236 void poll_keys( void )
  237 {   
  238     byte i = 0;
  239     
  240     // this loop looks at each key
  241     for( i = 0 ; i < 10 ; i++ )
  242     {
  243         // if a key is pressed
  244         if( !digitalRead( key_pin[ i ] ) )
  245         { 
  246             // debounce the switch
  247             delay( 50 );
  248             
  249             // play a key tone
  250             key_tone( dtmf[ i ], i );
  251             
  252             // store the key number
  253             num[ num_index ] = i;
  254             num_index++;
  255             
  256             break;
  257         }
  258     }
  259 }
  260 
  261 // plays a tone while a key is depressed
  262 void key_tone( float hertz, byte key_num )
  263 {
  264     // calculate microseconds per half wave cycle
  265     half_cyc_uc = ( 1000000. / hertz ) * 0.5;
  266     
  267     // turn on the led
  268     digitalWrite( LED, 1 );
  269     
  270     // generate a tone while the key is depressed 
  271     while( !digitalRead( key_pin[ key_num ] ) )
  272     {
  273         digitalWrite( SPEAKER, speaker_state );
  274         speaker_state = !speaker_state;
  275         delayMicroseconds( (unsigned int)half_cyc_uc );
  276     }
  277     
  278     // turn off the led
  279     digitalWrite( LED, 0 );
  280 }
  281 
  282 // plays a tone of arbitrary length
  283 void tone( float hertz, float msec )
  284 {
  285     // calculate microseconds per half cycle of waveform
  286     half_cyc_uc = ( 1000000. / hertz ) * 0.5;
  287     
  288     // calculate number of half cycles to output
  289     cycles_2x = ( msec * 1000. ) / half_cyc_uc;
  290     
  291     // turn on the led
  292     digitalWrite( LED, 1 );
  293     
  294     // generate the waveform
  295     while( cycles_2x-- )
  296     {
  297         digitalWrite( SPEAKER, speaker_state );
  298         speaker_state = !speaker_state;
  299         delayMicroseconds( (unsigned int)half_cyc_uc );
  300         
  301         // poll the hook pin
  302         on_hook = digitalRead( HOOK );
  303     }
  304     
  305     // turn off the led
  306     digitalWrite( LED, 0 );
  307 }
  308 
  309 // plays the dial_tone
  310 void dial_tone( void )
  311 {   
  312     // sounds somewhat similar to the dtmf dialtone
  313     float frequency = 371.0;
  314     
  315     // calculate microseconds per half cycle of waveform
  316     half_cyc_uc = ( 1000000. / frequency ) * 0.5;
  317     
  318     // calculate number of half cycles to output 
  319     cycles_2x = ( 2 * 1000. ) / half_cyc_uc;
  320     
  321     // generate the waveform
  322     while( cycles_2x-- )
  323     {
  324         digitalWrite( SPEAKER, speaker_state );
  325         speaker_state = !speaker_state;
  326         delayMicroseconds( (unsigned int)half_cyc_uc );
  327         
  328         // poll the hook pin
  329         on_hook = digitalRead( HOOK );
  330     }
  331 }
  332 
  333 // plays a rest of arbitrary length
  334 void rest( float msec )
  335 {
  336     // calculate length of silence
  337     half_cyc_uc = ( 1000000. / 100 ) * 0.5;
  338     cycles_2x = ( msec * 1000. ) / half_cyc_uc;
  339 
  340     // rest for a bit
  341     while( cycles_2x-- )
  342     {
  343         if( on_hook )
  344             break;
  345         delayMicroseconds( (unsigned int)half_cyc_uc );
  346         on_hook = digitalRead( HOOK );
  347     }
  348 }
  349 
  350 // wraps midi notes into midi range
  351 void notewrap( int *note )
  352 {
  353     if( *note > 127 ) *note -= 127;
  354     if( *note < 0 ) *note += 127;
  355 }
  356 
  357 // wraps frequencies into human hearing range
  358 void freqwrap( float *freq )
  359 {
  360     if( *freq > 20000 ) *freq -= 19980;
  361     if( *freq < 20 ) *freq += 19980;
  362 }
  363 
  364 // a polytonic scale of intervals
  365 void polytonic_scale( int note, int semitones, int iterations, float tone_msec, float pause_msec )
  366 {
  367     int i = 0;
  368     for( i = 0 ; i < iterations ; i++ )
  369     {
  370         if( on_hook )
  371             return;
  372         tone( midi_note[ note ], tone_msec );
  373         note += semitones;
  374         notewrap( &note );
  375         delayMicroseconds( (unsigned int)(pause_msec * 1000.) );
  376     }
  377 }
  378 
  379 // makes a linear set of incrementing frequencies
  380 void freq_scale( float freq, float freq_inc, int iterations, float tone_msec )
  381 {
  382     int i = 0;
  383     for( i = 0 ; i < iterations ; i++ )
  384     {
  385         if( on_hook )
  386             return;
  387         tone( freq, tone_msec );
  388         freq += freq_inc;
  389         freqwrap( &freq );
  390     }
  391 }
  392 
  393 // makes random frequencies in a specified range
  394 void rand_freqs( float bot_freq, float top_freq, int iterations, float min_msec, float max_msec )
  395 {
  396     int i = 0;
  397     float freq_range = top_freq - bot_freq;
  398     float msec_range = max_msec - min_msec;
  399     float duration;
  400     long int factorial = 1;
  401     
  402     for( i = 0 ; i < 10 ; i++ )
  403     {
  404         factorial *= num[i];
  405     }
  406     
  407     randomSeed( factorial );
  408     
  409     for( i = 0 ; i < iterations ; i++ )
  410     {
  411         if( on_hook )
  412             return;
  413         duration = random( 999 ) * 0.001 * msec_range + min_msec;       
  414         tone( random( (int)freq_range ) + bot_freq , duration );            
  415         duration = random( 999 ) * 0.001 * msec_range + min_msec;
  416         rest( duration );
  417     }
  418 }
  419 
  420 // plays an ascending or descending scale of alternading dyads
  421 void dyad_scale( int note, int interval, int scale_interval, int iterations, float msec_length )
  422 {
  423     int i;
  424     int dyad;
  425     
  426     for( i = 0 ; i < iterations ; i++ )
  427     {
  428         if( on_hook )
  429             return;
  430         tone( midi_note[ note ], msec_length );
  431         rest( msec_length * 0.5 );
  432         dyad = note + interval;
  433         notewrap( &dyad );
  434         tone( midi_note[ dyad ], msec_length );
  435         rest( msec_length * 0.5 );
  436         note += scale_interval;
  437         notewrap( &note );
  438     }   
  439 }
  440 
  441 // increasingly shorter ascending tones tones with rests
  442 void bounce_up( float freq, float initial_msec_length, float decrement_coeff )
  443 {
  444     float i;
  445     
  446     for( i = initial_msec_length ; i > 1 ; i = i * decrement_coeff )
  447     {
  448         if( on_hook )
  449             return;
  450         tone( freq, i );
  451         rest( i );
  452         freq *= 1 + ( 1 - decrement_coeff );
  453         freqwrap( &freq );
  454     }
  455 }
  456 
  457 // increasingly shorter descending tones tones with rests
  458 void bounce_down( float freq, float initial_msec_length, float decrement_coeff )
  459 {
  460     float i;
  461     
  462     for( i = initial_msec_length ; i > 1 ; i = i * decrement_coeff )
  463     {
  464         if( on_hook )
  465             return;
  466         tone( freq, i );
  467         rest( i );
  468         freq *= decrement_coeff;
  469         freqwrap( &freq );
  470     }
  471 }
  472 
  473 // frequencies moving apart from the initial frequency
  474 void freq_mirror( float freq, float initial_msec_length, float decrement_coeff )
  475 {
  476     float i;
  477     float mirror_freq = freq;
  478     
  479     for( i = initial_msec_length ; i > 1 ; i = i * decrement_coeff )
  480     {
  481         if( on_hook )
  482             return;
  483         tone( freq, i );
  484         rest( i );      
  485         freq *= 1 + ( 1 - decrement_coeff );
  486         mirror_freq *= decrement_coeff;     
  487         freqwrap( &freq );
  488         freqwrap( &mirror_freq );
  489         tone( mirror_freq, i );
  490         rest( i );      
  491     }
  492 }
  493 
  494 void num_melody( float tone_msec, float rest_msec, int octaves )
  495 {
  496     byte i, j;
  497     byte duration[] = { 12, 8, 16, 6, 12, 4, 16, 6, 12, 8 };
  498     int note;
  499     
  500     for( i = 0 ; i < octaves ; i++ )
  501     {
  502         for( j = 0 ; j < 10 ; j++ )
  503         {
  504             if( on_hook )
  505                 return;
  506             note = num[ j ] + 40 + ( 12 * i );
  507             notewrap( &note );
  508             tone( midi_note[ note ], tone_msec * duration[ num[ j ] ] );
  509             rest( rest_msec * duration[ 9 - num[ j ] ] );
  510         }
  511     }
  512 }
  513 
  514 //= Main =======================================================================
  515 int main( void )
  516 {
  517     // init the arduino environment
  518     init();
  519     
  520     // program-specific setup
  521     setup();
  522     
  523     // infinite loop
  524     spin:
  525         loop();
  526     goto spin;
  527     
  528     return 0;
  529 }
  530 
(c)(p) 2012 Cooper Baker · All Rights Reserved · 77276