view tools/tone.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
line wrap: on
line source
/*
  tone.c    generate a pure tone.
  ------
    Generate samples of a sine wave at a given sample rate.
    Specify wave amplitude, and frequency (in Hz or kHz), or alternatively
    period (in s, ms, or p (sample points) ). If both period and frequency
    are specified, then the given period takes precedence.
    If S is the samplerate, and Ts=1/S is the sample interval,
    then each sample of a sine wave of period T samples is given by:
	sin(n*(Ts/T)*TWOPI)  for  n=0,1,2,...
    Output samples in the given datatype for the given waveform duration.


Examples:

1. Sine wave with period 10ms sampled at 10kHz, (100 sample points per period)

tone period=10ms samplerate=10kHz | x11plot

2. Sine wave with frequency 100Hz sampled at 20kHz

tone frequency=100Hz | x11plot

3. Sine wave with period 100 sample points, with dc-offset set equal to
   amplitude of 500 so that waveform is just non-negative.

tone period=100p amplitude=500 offset=500 | x11plot

4. Quarter cycle of a sine wave with 8ms period.

tone period=8ms duration=2ms | x11plot

*/

#include <stdio.h>
#include <math.h>
#include "options.h"
#include "units.h"
#include "strmatch.h"

#define TWOPI   6.28318530717

char applic[]  = "generate a pure tone. " ;
char usage[]   = "tone [options]" ;

static char *helpstr, *debugstr, *sampstr, *perstr, *freqstr, *astr, *ostr, *dstr, *typestr ;
static char *phasestr ;

static Options option[] = {
    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                              , DEBUG   },
    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                  , DEBUG   },
    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                       , VAL     },
    {   "period"    ,   "8ms"       ,  &perstr      ,   "period of waveform"                , VAL     },
    {   "frequency" ,   "125Hz"     ,  &freqstr     ,   "frequency of waveform"             , VAL     },
    {   "phase"     ,   "0"         ,  &phasestr    ,   "phase offset"                      , VAL     },
    {   "amplitude" ,   "512"       ,  &astr        ,   "amplitude of waveform"             , VAL     },
    {   "mean"      ,   "0"         ,  &ostr        ,   "mean value of waveform"            , VAL     },
    {   "duration"  ,   "500ms"     ,  &dstr        ,   "duration of waveform"              , VAL     },
    {   "type"      ,   "short"     ,  &typestr     ,   "output datatype"                   , VAL     },
   ( char * ) 0 } ;


int     samplerate ;
float   amplitude  ;
float   offset     ;
int     type       ;    /* datatype index */

main(argc, argv)
int   argc ;
char *argv[] ;
{
    float  T=0, Tr, r, y ;
    int    i, n ;

    getopts( option,argc,argv ) ;
    if ( !isoff( helpstr ) )
	helpopts3( helpstr, argv[0], applic, usage, option ) ;

    samplerate = to_Hz( sampstr, 0 ) ;
    amplitude  = atof( astr ) ;
    offset     = atof( ostr ) ;

    if ( ( type = typeindex( typestr ) ) < 0 ) {
	fprintf( stderr, "tone: bad type [%s]\n", typestr ) ;
	exit( 1 ) ;
    }

    n  = to_p( dstr, samplerate ) ;

    if ( isstr( perstr, optdflt( option, "period" ) ) )
	T = 1.0 / to_Hz( freqstr, samplerate ) ;
    else
	T = to_s( perstr, samplerate ) ;

    Tr = TWOPI / ( samplerate * T ) ;   /* period of max resolution */

    if ( iststr( phasestr, "sine" ) )   /* start */
	r = 0 ;
    else if ( iststr( phasestr, "cosine" ) )
	r = TWOPI / 4 ;
    else if ( iststr( phasestr, "antisine" ) )
	r = TWOPI / 2 ;
    else if ( iststr( phasestr, "anticosine" ) )
	r = 3 * TWOPI / 4 ;
    else if ( isstr( phasestr + strlen( phasestr ) - 3, "deg" ) )
	r = TWOPI * ( atof( phasestr ) / 360. ) ;
    else
	r = TWOPI * ( to_s( phasestr, samplerate ) / T ) ;

    for ( i = 0  ; i < n ; i++, r += Tr ) {
	y = amplitude * sin(r) + offset ;
	writeitem( &y, type, 1, stdout ) ;
    }
}