/* sound.c -- generally handy routines for sound. */ #include #include #include #include "sound.h" double rnd( void ) { return( (double) random() / RAND_MAX ); } int random_lt( int n ) { int bits, val; // Taken from Sun's published source for java.util.Random::nextInt(). if (n<=0) { fprintf( stderr, "random_lt: n == %d <= 0\n", n ); } if ((n & -n) == n) { // i.e., n is a power of 2 return( (int)((n * (long) random() ) >> 31) ); } do { bits = random(); val = bits % n; } while(bits - val + (n-1) < 0); return val; } /* Freq. of a chromatic note where A440 = 0. */ double chrom_freq( double chrom ) { return( ( 440 * CYCLE / SECOND ) * exp2( chrom / 12 ) ); } // Freq. of a standard midi note; double midi_note_freq( double midi_note ) { // Allows fractional midi notes. return( chrom_freq( midi_note - MIDI_A440 ) ); } /* This format is 12 characters wide: ###:##.##### */ void fprint_time( FILE *stream, long t ) { /* positive times only */ int minutes = t / MINUTE; double seconds = ( (double) t - ( minutes * MINUTE ) ) / SECOND; fprintf( stream, "%3d:%08.5f", minutes, seconds ); } /* This format is 13 characters wide: ###:##.##+### */ void fprint_time_step( FILE *stream, long t ) { /* positive times only */ int minutes = t / MINUTE; t = t % MINUTE; fprintf( stream, "%3d:%05.2f+%03d", minutes, (t / 441) * .01, t % 441 ); } // Format is [+-][mmm:][SS][.[hh][{+-}sss]] long parse_time( char *str, int *p_is_relative, char **endptr ) { char *puncs [4] = { "+-", ":", ".", "+-" }; double nums[4]; long t; int i; char *p, *ps[ 4 ]; for( i = 0; i < 4; i++ ) { nums[i] = 0; ps[i] = NULL; for( p = puncs[i]; *p != '\0'; p++ ) { if( *str == *p ) { ps[i] = p; str++; break; // Only one of each. } } if( isspace( *str ) || ispunct( *str ) ) { continue; // Don't let strtol accept space or +/-. } nums[i] = strtol( str, &p, 10 ); // Special for fractions of seconds: if( i == 2 ) { while( str < p ) { str++; nums[2] = nums[2] / 10; } } str = p; } // If no ':', first number is seconds, not minutes: if( ps[1] == NULL ) { nums[1] = nums[0]; nums[0] = 0; } // Final '-' makes negative sample offset: if( ps[3] != NULL && *ps[3] == '-' ) { nums[3] = -nums[3]; } t = nums[0] * MINUTE + nums[1] * SECOND + nums[2] * SECOND + nums[3]; if( *p_is_relative = ( ps[0] != NULL ) ) { if( *ps[0] == '-' ) { t = -t; } } if( endptr != NULL ) *endptr = str; return( t ); }