#include #include #include #include static unsigned int FREQUENCY = 8192; static double (*waveForm)( double angle ); enum { BYTES_PER_SAMPLE = 2 }; enum { MAX_SAMPLE = (~(~0 << (8*BYTES_PER_SAMPLE-1))) }; static double squareWave( double angle ) { double waveNumber; double proportion; proportion = modf( angle / ( 2.0 * M_PI ), &waveNumber ); if ( proportion < 0.5 ) { return 1.0; } else { return -1.0; } } static double triangleWave( double angle ) { double waveNumber; double proportion; proportion = modf( angle / ( 2.0 * M_PI ), &waveNumber ); if ( proportion < 0.5 ) { return 1.0 - 4.0 * proportion; } else { return 4.0 * proportion - 3.0; } } static double sawtoothWave( double angle ) { double waveNumber; double proportion; proportion = modf( angle / ( 2.0 * M_PI ), &waveNumber ); return 2.0 * proportion - 1.0; } static double toothsawWave( double angle ) { double waveNumber; double proportion; proportion = modf( angle / ( 2.0 * M_PI ), &waveNumber ); return 1.0 - 2.0 * proportion; } static double (*waveForm)( double angle ); static double getSample( unsigned int sampleNumber, double hz ) { return (*waveForm)( sampleNumber * hz * 2.0 * M_PI / (double)FREQUENCY ); } static double getValue( FILE* fp ) { int input; int hi; int lo; hi = fgetc( stdin ); lo = fgetc( stdin ); if ( hi == EOF || lo == EOF ) { return 0.0; } input = ( hi << 8 ) | ( lo << 0 ); if ( ( input & ( 1 << ( BYTES_PER_SAMPLE * 8 - 1 ) ) ) != 0 ) { input |= ~( 0xFFFF ); } return (double)input / (double)MAX_SAMPLE; } static int getOutputValue( double val, double gamma ) { if ( val < 0.0 ) { return 0; } else if ( val >= 255.0 ) { return 255; } else { return (int)( 255.0 * pow( val / 255.0, gamma ) ); } } int main( int argc, const char* argv[] ) { unsigned int help = 0; double linesPerSecond = 64.0; unsigned int width = 32; double minHz = 128.0; double maxHz = 4096.0; unsigned int stereo = 0; double logMinHz; double logMaxHz; double* hzTable; double gamma = 0.44; unsigned int ii; unsigned int yy = 0; double* outBuf; for ( ii=1; ii < argc; ++ii ) { if ( !strcmp( argv[ ii ], "-lps" ) ) { linesPerSecond = strtod( argv[ ++ii ], 0 ); } else if ( !strcmp( argv[ ii ], "-width" ) ) { width = strtol( argv[ ++ii ], 0, 0 ); } else if ( !strcmp( argv[ ii ], "-gamma" ) ) { gamma = strtod( argv[ ++ii ], 0 ); } else if ( !strcmp( argv[ ii ], "-minHz" ) ) { minHz = strtod( argv[ ++ii ], 0 ); } else if ( !strcmp( argv[ ii ], "-maxHz" ) ) { maxHz = strtod( argv[ ++ii ], 0 ); } else if ( !strcmp( argv[ ii ], "-freq" ) ) { FREQUENCY = strtol( argv[ ++ii ], 0, 0 ); } else if ( !strcmp( argv[ ii ], "-stereo" ) ) { stereo = 1; } else if ( !strcmp( argv[ ii ], "-wave" ) ) { ++ii; if ( !strcmp( argv[ ii ], "sine" ) ) { waveForm = sin; } else if ( !strcmp( argv[ ii ], "square" ) ) { waveForm = squareWave; } else if ( !strcmp( argv[ ii ], "triangle" ) ) { waveForm = triangleWave; } else if ( !strcmp( argv[ ii ], "sawtooth" ) ) { waveForm = sawtoothWave; } else if ( !strcmp( argv[ ii ], "toothsaw" ) ) { waveForm = toothsawWave; } else { fprintf( stderr, "Unknown waveform: %s\n", argv[ii] ); help = 1; } } else { help = 1; } } if ( FREQUENCY == 0 || linesPerSecond < 0.0000001 || width == 0 ) { fprintf( stderr, "Bad parameters\n" ); help = 1; } if ( help ) { fprintf( stderr, "Usage: %s\n", argv[0] ); fprintf( stderr, "\t[-lps linesPerSecond]\n" ); fprintf( stderr, "\t[-width width]\n" ); fprintf( stderr, "\t[-gamma gamma]\n" ); fprintf( stderr, "\t[-minHz minimumFrequency]\n" ); fprintf( stderr, "\t[-maxHz maximumFrequency]\n" ); fprintf( stderr, "\t[-freq outputSamplesPerSecond]\n" ); fprintf( stderr, "\t[-stereo]\n" ); fprintf( stderr, "\t[-wave sine | triangle | square | sawtooth | toothsaw ]\n" ); fprintf( stderr, "\t[-help]\n" ); return __LINE__; } if ( minHz < 1.0 ) { minHz = 1.0; } if ( maxHz < 1.0 ) { maxHz = 1.0; } hzTable = (double*)malloc( width * sizeof( double ) ); if ( hzTable == 0 ) { fprintf( stderr, "Couldn't get hzTable memory\n" ); return __LINE__; } logMinHz = log( minHz ); logMaxHz = log( maxHz ); for ( ii=0; ii < width; ++ii ) { double horz = (double) ii / (double)width; double logHz = logMinHz + horz * ( logMaxHz - logMinHz ); hzTable[ ii ] = exp( logHz ); } if ( waveForm == 0 ) { waveForm = sin; } outBuf = (double*)malloc( width * sizeof( double ) ); if ( outBuf == 0 ) { fprintf( stderr, "Couldn't get outBuf memory\n" ); return __LINE__; } fprintf( stdout, "%d # %s\n", width, argv[0] ); while ( !feof( stdin ) ) { static unsigned int lastRow = 0; static unsigned int lastYY = 0; double vert = ( (double) yy * linesPerSecond ) / (double)FREQUENCY; double realRow; double proportion; double value; int row; proportion = modf( vert, &realRow ); row = (int)( realRow + 1.5 ); if ( row != lastRow ) { if ( yy > lastYY ) { double scale = 255.0 / (double)( yy - lastYY ); for ( ii=0; ii < width; ++ii ) { int output = getOutputValue( outBuf[ ii ] * scale, gamma ); if ( output < 0 ) { output = -output; output = 0; } if ( output > 255 ) { output = 255; } fputc( output, stdout ); } } for ( ii=0; ii < width; ++ii ) { outBuf[ ii ] = 0.0; } lastRow = row; lastYY = yy; } if ( stereo ) { value = getValue( stdin ) + getValue( stdin ); } else { value = getValue( stdin ); } for ( ii=0; ii < width; ++ii ) { outBuf[ ii ] += value * getSample( yy, hzTable[ ii ] ); } ++yy; } return 0; }