Esempio n. 1
0
int main (int argc, char**argv)
{
	PSF_PROPS outprops;
	unsigned long srate;
	double amp, freq, pwval, dur, peakdiff;
	unsigned long nbufs, outframes, remainder, nframes;
	psf_format outformat = PSF_FMT_UNKNOWN;
	int wavetype=-1;
	float wavevalue;
	int nchans;
	int ispwval=0; /* flagged if pwval is a value and not a breakpoint file */
	char* arg_pwmod; /* retains the name of the pwval breakpoint file */
	double minval, maxval; /* used for breakpoint amplitude values */	
	tickfunc tick; /* point to the specified wavetype function */
	char option; /* stores command line options */
	psf_stype samptype = PSF_SAMP_16; /* outfile is set to 16-bit by default */	
	double phase=0.0; /* fraction between 0 and 1 which sets the phase offset
	                 default values match the direction of the sine wave
	                 (i.e starting at zero, going positive)  */

	/* init resource values */
	int ofd=-1;
	int error=0;
	float* outbuf = NULL;  /* buffer for outfile */
	OSCIL* p_osc = NULL;  /* waveform oscillator */
	BRKSTREAM* ampstream = NULL; /* breakpoint stream of amplitude values */
	BRKSTREAM* freqstream = NULL; /* breakpoint stream of frequency values */
	BRKSTREAM* pwmodstream = NULL; /* breakpoint stream of pwmod values */
	FILE* fpamp = NULL; /* amplitude breakpoint file */
	FILE* fpfreq = NULL; /* frequency breakpoint file */	
	FILE* fppwmod = NULL; /* pulse width modulation breakpoint file */
	unsigned long brkampSize = 0; /* number of amplitude breakpoints */
	unsigned long brkfreqSize = 0; /* number of frequency breakpoints */
	unsigned long brkpwmodSize = 0; /* number of pulse wave mod breakpoints */
	
	printf("SIGGEN: generate a simple waveform\n");

	/* check for command-line options */
	if (argc>1)
	{
		while (argv[1][0] == '-')
		{
			option = argv[1][1];
			switch (option)
			{
				case('\0'):
					printf("ERROR:   you did not specify an option\n"
					       "options: -sN  select the format of the output sound file\n" 
					       "              N = 16 (16-bit), 24 (24-bit), or 32 (32-bit)\n"
					      );
					return 1;
				case('s'):
					if (argv[1][2]=='\0')
					{
						printf("ERROR: you did not specify a format\n"
						       "formats: 16 (16-bit), 24 (24-bit), or 32 (32-bit)\n",
						        &argv[1][2]);
						return 1;
					}
					samptype = atoi(&argv[1][2]);
					if (samptype == 16)
					{
						samptype = PSF_SAMP_16;
						break;
					}	
					if (samptype == 24)
					{
						samptype = PSF_SAMP_24;
						break;
					}
					if (samptype == 32)
					{
						samptype = PSF_SAMP_32;
						break;
					}
					printf("ERROR:   %s is not a valid format\n"
					       "formats: 16 (16-bit), 24 (24-bit), or 32 (32-bit)\n",
					        &argv[1][2]);
					return 1;
				case('o'):
					if (argv[1][2]=='\0')
					{
						printf("ERROR: you did not specify an offset\n"
						       "USAGE: -oN   (0 <= N <= 1)\n"
						      );
						return 1;
					}
					if (!(argv[1][2] >= 'a' && argv[1][2]<='z'))
					{
						phase = atof(&argv[1][2]);
						if (phase < 0.0)
							phase = 0.0;
						if (phase > 1.0)
							phase = 1.0;
						break;
					}
				default:
					printf("ERROR: %s is not a valid option\n"
					       "options: -sN  select the format of the output sound file\n" 
					       "              N = 16 (16-bit), 24 (24-bit), or 32 (32-bit)\n"
					       "         -oN  select the offset of the oscillator\n"
					       "              0 <= N <= 1\n",
					        argv[1]);
					return 1;
			}
			argc--;
			argv++;
		}
	}

	if (argc!=ARG_NARGS)
		if (argc==(ARG_NARGS+1))
		{
			/* check if pwval is specified */
			fppwmod = fopen(argv[ARG_PWMOD], "r");
			if (fppwmod==NULL)
			{
				if (argv[ARG_PWMOD][0] >='a' && argv[ARG_PWMOD][0] <= 'z') 
				{
					printf("Error: breakpoint file \"%s\" does not exist.\n",
					        argv[ARG_PWMOD]);
					return 1;
				}
				pwval = atof(argv[ARG_PWMOD]);
				if (pwval < 1 || pwval > 99)
				{
					printf("Error: pwval is out of range.\n"
					       "       1 <= pwval <= 99\n");
					return 1;
				}
				/* we have gathered a pwval value */
				ispwval=1;
			}
			else
		  {
				/* breakpoint file exists, gather breakpoint values */
				pwmodstream = bps_newstream(fppwmod,atof(argv[ARG_SRATE+1]),&brkpwmodSize);
				if (pwmodstream==NULL)
				{
					printf("ERROR: unable to obtain breakpoints from \"%s\"\n",
									argv[ARG_PWMOD]);
					error++;
					goto exit;
				}
			}
			/* make sure enum ARG values are aligned with command-line arguments */	
			int argnum = ARG_PWMOD;
			arg_pwmod = argv[ARG_PWMOD];
			while (argnum != (ARG_NARGS+1))
				argv[argnum] = argv[++argnum];
		}
		else
		{
			printf("ERROR: insufficient number of arguments.\n"
						 "USAGE: siggen [-sN] [-oN] outsndfile wavetype [pwval] duration srate nchans amp freq\n"
						 "       -sN:       select the format of the output sound file (16-bit by default)\n"
						 "                  N = 16 (16-bit), 24 (24-bit), or 32 (32-bit)\n"
			       "       -oN:       select the offset of the oscillator\n"
			       "                  0 <= N <= 1\n"
			       "                  if you set N < 0, then N is set to 0\n"
		         "                  if you set N > 1, then N is set to 1\n"
						 "       wavetype:  sine, triangle, square, pwmod, sawtooth_up, sawtooth_down\n" 
						 "       pwval:     pulse wave percentage value or breakpoint file\n"
			       "                  modulation range is from 1%% to 99%%\n"
			       "                  a normal square wave is 50%%\n" 
						 "                  pwval must be selected only when the\n"
						 "                  pwmod wavetype has been selected.\n"
						 "       duration:  duration of outfile (seconds)\n"
						 "       srate:     required sample rate of outfile\n"
						 "       amp:       amplitude value or breakpoint file\n"
						 "                  (0 < amp <= 1.0)\n"
						 "       freq:      frequency value or breakpoint file\n"
						 "                  (freq > 0 )\n"
						);
			return 1;
		}

	/** at this point we may have gathered resources 
	    we henceforth use goto upon hitting any errors **/

	/* define outfile format */	
	srate = atof(argv[ARG_SRATE]);		
	if (srate<=0)
	{
		printf("ERROR: sample rate must be positive.\n");
		error++;
		goto exit;
	}
	outprops.srate = srate;
	outprops.samptype = samptype;
	outprops.chformat = PSF_STDWAVE;
	/* get outfile extension */
	outformat = psf_getFormatExt(argv[ARG_OUTFILE]);
	if (outformat==PSF_FMT_UNKNOWN)
	{
		printf("Outfile name \"%s\" has unknown format.\n"
		       "Use any of .wav .aiff .aif .afc .aifc\n",
		        argv[ARG_OUTFILE]
		      );
		error++;
		goto exit;
	}
	outprops.format = outformat;
	/* get number of channels */
	nchans = atoi(argv[ARG_NCHANS]);
	if (nchans > MC_WAVE_EX)
	{
		printf("ERROR: portsf does not support %d channels\n",
		        nchans); 
		error++;
		goto exit;
	}
	outprops.chans = nchans;	

	/* get the wavetype */
	int count = 0;
	while (argv[ARG_TYPE][count]!='\0') count++;
	switch (count)
	{
		case(WAVE_SINE):
			if (!strcmp(argv[ARG_TYPE],"sine")) 
				wavetype = WAVE_SINE;
			break;
		case(WAVE_PWMOD):
			if (!strcmp(argv[ARG_TYPE],"pwmod"))
				wavetype = WAVE_PWMOD;
			break;
		case(WAVE_SQUARE):
			if (!strcmp(argv[ARG_TYPE],"square"))
				wavetype = WAVE_SQUARE;
			break;
		case(WAVE_TRIANGLE):
			if (!strcmp(argv[ARG_TYPE],"triangle"))
				wavetype = WAVE_TRIANGLE;
			break;
		case(WAVE_SAWUP):
			if (!strcmp(argv[ARG_TYPE],"sawtooth_up"))
				wavetype = WAVE_SAWUP;
			break;
		case(WAVE_SAWDOWN):
			if (!strcmp(argv[ARG_TYPE],"sawtooth_down"))
				wavetype = WAVE_SAWDOWN;
			break;	
		default:
			wavetype = -1;		
	}
	if (wavetype<0)
	{
		printf("ERROR: you have chosen an unknown wavetype.\n"
		       "wavetypes: sine, square, pwmod, triangle, sawtooth_up, sawtooth_down\n"
		      );
		error++;
		goto exit;
	}
	
	/* if user specifies pwval, make sure pwmod wavetype is selected */
	if (pwmodstream||ispwval)
		if (wavetype!=WAVE_PWMOD)
		{
			printf("ERROR: if you select a value or breakpoint file for pwval,\n"
			       "       you must select the pwmod wavetype.\n");
			error++;
			goto exit;
		}

	/* select waveform function */
	switch (wavetype)
	{
		case(WAVE_SINE):
			tick = sinetick;
			phase += 0.0;
			break;
		case(WAVE_TRIANGLE):
			tick = tritick;
			phase += 0.75;
			break;
		case(WAVE_SQUARE):
			tick = sqtick;
			phase += 0.0;
			break;
		case(WAVE_PWMOD):
			if (pwmodstream==NULL && !ispwval)
			{
				printf("ERROR: you didn't specify a pulse wave value "
				       "or breakpoint file.\n");
				error++;
				goto exit;
			}
			phase += 0.0;
			break;
		case(WAVE_SAWUP):
			tick = sawutick;
			phase += 0.5;
			break;
		case(WAVE_SAWDOWN):
			tick = sawdtick;
			phase += 0.5;
	}

	/* get the time duration of the soundfile */
	dur = atof(argv[ARG_DUR]);
	if (dur<=0.0)
	{
		printf("ERROR: time duration must be positive.\n");
		error++;
		goto exit;
	}

	/* open breakpoint file, or set constant amplitude */ 
	fpamp = fopen(argv[ARG_AMP],"r"); 
	if (fpamp==NULL)
	{
		if (argv[ARG_AMP][0] >= 'a' && argv[ARG_AMP][0] <= 'z')
		{
			printf("ERROR: breakpoint file \"%s\" does not exist.\n",
			        argv[ARG_AMP]);
			error++;
			goto exit;
		}
		amp = atof(argv[ARG_AMP]);
		if (amp<=0.0 || amp>1.0)
		{
			printf("ERROR: amplitude value out of range.\n"
			       "       0.0 < amp <= 1.0\n"
			      );
			error++;
			goto exit;
		}
	}
	else
	{
		ampstream = bps_newstream(fpamp,outprops.srate,&brkampSize);
		if (ampstream==NULL)
		{
			printf("ERROR: unable to obtain breakpoints from \"%s\"\n",
							argv[ARG_AMP]);
			error++;
			goto exit;
		}
		if (bps_getminmax(ampstream,&minval,&maxval))
		{
			printf("Error reading range of breakpoint file \"%s\"\n",
			        argv[ARG_AMP]);
			error++;
			goto exit;
		}
		if (minval < 0.0 || minval > 1.0 || maxval < 0.0 || maxval > 1.0)
		{
			printf("Error: amplitude values out of range in file \"%s\"\n"
			       "       0.0 < amp <= 1.0\n",
			        argv[ARG_AMP]);
			error++;
			goto exit;
		}
	}

	/* open breakpoint file, or set constant frequency */
	fpfreq = fopen(argv[ARG_FREQ],"r");
	if (fpfreq==NULL)
	{
		if (argv[ARG_FREQ][0] >= 'a' && argv[ARG_FREQ][0] <='z')
		{
			printf("ERROR: breakpoint file \"%s\" does not exist.\n",
			        argv[ARG_FREQ]); 
			error++;
			goto exit;
		}
		freq = atof(argv[ARG_FREQ]);
		if (freq<=0.0)
		{
			printf("ERROR: frequency must be positive.\n");
			error++;
			goto exit;
		}
	}
	else
	{
		freqstream = bps_newstream(fpfreq,outprops.srate,&brkfreqSize);
		if (freqstream==NULL)
		{
			printf("ERROR: unable to obtain breakpoint from \"%s\"\n",
			        argv[ARG_FREQ]);
			error++;
			goto exit;
		}
	}

	/* start portsf */
	psf_init();

	ofd = psf_sndCreate(argv[ARG_OUTFILE],&outprops,0,0,PSF_CREATE_RDWR); 
	if (ofd<0)
	{
		printf("ERROR: unable to create outfile: %s\n",argv[ARG_OUTFILE]);
		error++;
		goto exit;
	}

	/* initialize waveform oscillator */
	p_osc = new_oscilp(outprops.srate, phase);

	/* calculate the number of frames for the soundfile */
	outframes = (unsigned long) (dur * outprops.srate + 0.5);

	/* allocate a buffer for outfile */
	nframes = NFRAMES;
	outbuf = (float*)malloc(sizeof(float)*nframes*outprops.chans);

	/* calculate the number of buffers */
	nbufs = outframes/nframes;	
	remainder = outframes - nbufs*nframes;
	if (remainder > 0)
		nbufs++;	

	printf("Creating soundfile...\n");

	
	/* process soundfile */	
	long i,j,i_out;
	for (i=0; i < nbufs; i++)
	{ 
		if ((i == (nbufs-1)) && remainder)
			nframes = remainder;
		for (j=0; j < nframes; j++)
		{
			if (ampstream)
				amp = bps_tick(ampstream);	
			if (freqstream)
				freq = bps_tick(freqstream);
			if (pwmodstream)
				pwval = bps_tick(pwmodstream);
			if (pwmodstream || ispwval )
				wavevalue = (float)(amp * pwmtick(p_osc,freq,pwval));
			else
				wavevalue = (float)(amp * tick(p_osc,freq));
			for (i_out=0; i_out < outprops.chans; i_out++)
				outbuf[j*outprops.chans+i_out] = wavevalue; 
		}
		if (psf_sndWriteFloatFrames(ofd,outbuf,nframes)!=nframes)
		{
			printf("Error writing to outfile\n");
			error++;
			break;
		}
	}

	/* make sure peak amplitude roughly matches the
	   user requested amplitude */
	if (ampstream==NULL)
		peakdiff = amp-psf_sndPeakValue(ofd,&outprops);
	else
		peakdiff = maxval-psf_sndPeakValue(ofd,&outprops);
	if ((peakdiff>.001) || (peakdiff<-.001))
	{
		printf("ERROR: unable to generate the correct peak\n"
		       "       amplitude for %s\n", argv[ARG_OUTFILE]); 	
		error++;
	}

	printf("Done.\t%d error%s\n"
	       "Outfile created: %s\n",
	        error, (error==1)?"":"s", argv[ARG_OUTFILE]);

	/* display outfile properties */
	psf_sndInfileProperties(argv[ARG_OUTFILE],ofd,&outprops);	

	/* cleanup resources */ 
	exit:
	if (ofd>=0)	
		if (psf_sndClose(ofd))
			printf("Error: unable to close outfile: %s\n",argv[ARG_OUTFILE]);
		else if (error)
		{
			printf("There was an error while processing the outfile.\n"
			       "Deleting outfile: %s ...\n", argv[ARG_OUTFILE]);
			if (remove(argv[ARG_OUTFILE]))
				printf("Error: failed to delete %s\n", argv[ARG_OUTFILE]);
			else
				printf("%s successfully deleted.\n", argv[ARG_OUTFILE]);
		}
	if (outbuf)
	{
		free(outbuf);
		outbuf=NULL;
	}
	if (p_osc)
	{
		free(p_osc);
		p_osc=NULL;
	}
	if (ampstream)
		bps_freepoints(ampstream);
	if (freqstream)
		bps_freepoints(freqstream);
	if (pwmodstream)
		bps_freepoints(pwmodstream);
	if (fpamp)
		if (fclose(fpamp))
		{
			printf("Error closing breakpoint file \"%s\"\n",
			        argv[ARG_AMP]);
		}
	if (fpfreq)
		if (fclose(fpfreq))
		{
			printf("Error closing breakpoint file \"%s\"\n",
			        argv[ARG_FREQ]);
		}
	if (fppwmod)
		if (fclose(fppwmod))
		{
			printf("Error closing breakpoint file \"%s\"\n",
			        arg_pwmod);
		}
	psf_finish();

	return error;	
}
Esempio n. 2
0
int main (int argc, char**argv)
{
	/* declare variables */
	PSF_PROPS outprops; // properties of output soundfile
	psf_format outformat = PSF_FMT_UNKNOWN; 
	double dur, freq, amp, peakdiff;
	float val;
	double minval, maxval, maxamp;
	int srate, nharms;
	unsigned long i, j;
	int i_out;
	int wavetype = -1;
	int chans;
	unsigned long width = DEFAULT_WIDTH;
	unsigned long nbufs, outframes, remainder, nframes, framesread;
	oscilt_tickfunc tickfunc = tabitick; // default table lookup is interpolating

	/* init resources */
	int ofd = -1;
	int error = 0;
	FILE *fpamp = NULL; // amplitude breakpoint file
	FILE *fpfreq = NULL; // frequency breakpoint file
	float* buffer = NULL;
	BRKSTREAM* ampstream = NULL; // breakpoint amplitude values
	BRKSTREAM* freqstream = NULL; // breakpoint frequency values
	GTABLE* gtable = NULL; // wave table with guard point
	OSCILT* p_osc = NULL; // oscillator using table lookup	
	unsigned long brkampSize = 0, // number of breakpoints
	              brkfreqSize = 0;
	
	printf("TABGEN: a table lookup oscillator generator.\n");

	/* check for command line options */
	if (argc > 1)
	{
		while (argv[1][0]=='-')
		{
			switch(argv[1][1])
			{
				case('\0'):
					printf("Error:   you did not specify an option.\n"
					       "options: -wN  set width of lookup table "
					       "to N points (default: 1024 points)\n"
					       "         -t   use truncating lookup "
					       "(default: interpolating lookup)\n");
					return 1;
				case('t'):
					if (argv[1][2] == '\0')
						tickfunc = tabtick;	
					else
					{
						printf("Error:   %s is not a valid option.\n"
						       "options: -wN  set width of lookup table "
						       "to N points (default: 1024 points)\n"
						       "         -t   use truncating lookup "
						       "(default: interpolating lookup)\n",
						        argv[1]);
						return 1;	
					}
					break;
				case('w'):
					if (argv[1][2] == '\0')
					{
						printf("Error: you did not specify a table lookup width.\n");
						return 1;
					}
					if (argv[1][2] >= '0' && argv[1][2] <= '9')
					{
						width = atoi(&argv[1][2]);
						if (width < 1)
						{
							printf("Error: table width must be at least 1\n");
							return 1;
						}
						break;
					}
				default:
						printf("Error:   %s is not a valid option.\n"
						       "options: -wN  set width of lookup table "
						       "to N points (default: 1024 points)\n"
						       "         -t   use truncating lookup "
						       "(default: interpolating lookup)\n",
						        argv[1]);
						return 1;	
			}
			argc--;
			argv++;
		}
	}

	/* check for sufficient command line input */
	if (argc != ARG_NARGS)
	{
		printf("Error: insufficient number of arguments.\n"
		       "Usage: tabgen [-wN] [-t] outfile dur srate nchans amp freq type nharms\n"
		       "       -wN:      w option sets the width of the lookup table to N points\n"
		       "                 N >= 1\n"
		       "       -t:       t option selects truncating table lookup\n"
		       "                 default is interpolating table lookup\n"
		       "       outfile:  output soundfile\n"
		       "                 set to 16-bit format\n"
		       "                 use any of .wav .aiff .aif .afc .aifc formats\n"
		       "       dur:      duration of soundfile (seconds)\n"
		       "       srate:    sample rate\n"
		       "       nchans:   number of channels\n"
		       "       amp:      amplitude value or breakpoint file\n"
		       "                 0.0 < amp <= 1.0\n"
		       "       freq:     frequency value or breakpoint file\n"
		       "                 freq >= 0.0\n"
		       "       type:     oscillator wave type\n"
		       "                 sine, square, triangle, sawup, sawdown, pulse\n"
		       "       nharms:   number of wave harmonics that are\n"
		       "                 added together in oscillator bank\n" 
		       "                 nharms >= 1\n"
		      );
		return 1;
	} 

	/* check duration input */
	dur = atof(argv[ARG_DUR]);
	if (dur <= 0.0)
	{
		printf("Error: duration must be positive.\n");
		return 1;
	}

	/* check sample rate input */
	srate = atoi(argv[ARG_SR]);
	if (srate <= 0)
	{
		printf("Error: sample rate must be positive.\n");
		return 1;		
	}
	outprops.srate = srate;

	/* check number of channels input */
	chans = atoi(argv[ARG_CHANS]);
	if (chans <= STDWAVE || chans > MC_WAVE_EX)
	{ 
		printf("Error: portsf does not support %d channels.\n",
		        chans);
		return 1;
	}
	outprops.chans = chans;

	/* check the output soundfile extension */
	outformat = psf_getFormatExt(argv[ARG_OUTFILE]);
	if (outformat == PSF_FMT_UNKNOWN)
	{
		printf("Error: outfile extension unknown.\n"
		       "       use any of .wav .aiff .aif .afc .aifc formats\n");
		return 1; 
	}	
	outprops.format = outformat;

	/* check for number of harmonics */
	nharms = atoi(argv[ARG_NHARMS]);
	if (nharms <= 0)
	{
		printf("Error: you must enter a positive number for harmonics.\n");
		return 1;
	} 
	
	/* get the wavetype */
	int count = 0;
	while (argv[ARG_TYPE][count] != '\0') count++;

	switch (count)
	{
		case (WAVE_SINE):
			if (!strcmp(argv[ARG_TYPE],"sine"))
				wavetype = WAVE_SINE;
			break;
		case (WAVE_SAWUP): 
			if (!strcmp(argv[ARG_TYPE],"sawup"))
				wavetype = WAVE_SAWUP;
		/* case (WAVE_PULSE): */
			if (!strcmp(argv[ARG_TYPE],"pulse"))
				wavetype = WAVE_PULSE;
			break;
		case (WAVE_SQUARE):
			if (!strcmp(argv[ARG_TYPE],"square"))
				wavetype = WAVE_SQUARE;
			break;
		case (WAVE_SAWDOWN):
			if (!strcmp(argv[ARG_TYPE],"sawdown"))
				wavetype = WAVE_SAWDOWN;
			break;	
		case (WAVE_TRIANGLE):
			if (!strcmp(argv[ARG_TYPE],"triangle"))
				wavetype = WAVE_TRIANGLE;
			break;
		default:
			wavetype = -1;
	} 
	if (wavetype < 0) 
	{
		printf("Error:    %s is not a valid wave type.\n"
		       "wavetype: sine, square, triangle, sawup, sawdown, pulse\n",
		        argv[ARG_TYPE]); 
		return 1;
	}

	/* start portsf */
	psf_init();

	/* create output soundfile - set to 16-bit by default */
	outprops.samptype = PSF_SAMP_16;
	outprops.chformat = PSF_STDWAVE;
	ofd = psf_sndCreate(argv[ARG_OUTFILE],&outprops,0,0,PSF_CREATE_RDWR);
	if (ofd < 0)
	{
		printf("Error: unable to create soundfile \"%s\"\n",
		        argv[ARG_OUTFILE]);
		return 1;
	}

	/* resources have been gathered at this point
	   use goto upon hitting any errors */

	/* get amplitude value or breakpoint file */
	fpamp = fopen(argv[ARG_AMP],"r");		
	if (fpamp == NULL)
	{
		/* if the user specified a non-existant breakpoint file
		   or didn't specify a breakpoint value */
		if ( (argv[ARG_AMP][0] < '0' || argv[ARG_AMP][0] > '9') &&
		   (argv[ARG_AMP][0] != '.' && argv[ARG_AMP][0] != '-') ||
		   (argv[ARG_AMP][0] == '.' && (argv[ARG_AMP][1] < '0' || argv[ARG_AMP][1] > '9')) ||
		   (argv[ARG_AMP][0] == '-' && (argv[ARG_AMP][1] < '0' || argv[ARG_AMP][1] > '9') && argv[ARG_AMP][1] != '.') )
		{
			printf("Error: breakpoint file \"%s\" does not exist.\n",
			        argv[ARG_AMP]);
			error++;
			goto exit;
		}
		/* the user specified a breakpoint value */
		amp = atof(argv[ARG_AMP]);
		if (amp <= 0.0 || amp > 1.0)
		{
			printf("Error: amplitude value out of range.\n"
			       "       0.0 < amp <= 1.0\n");
			error++;
			goto exit;
		}
	}
	else
	{
		/* gather breakpoint values */
		ampstream = bps_newstream(fpamp,outprops.srate,&brkampSize);
		if (ampstream == NULL)
		{
			printf("Error reading breakpoint values from file \"%s\".\n",
			        argv[ARG_AMP]);
			error++;
			goto exit;			
		}
		if (bps_getminmax(ampstream,&minval,&maxval))
		{
			printf("Error: unable to read breakpoint range "
			       "from file \"%s\".\n", argv[ARG_AMP]);
			error++;
			goto exit;
		}
		if (minval <= 0.0 || minval > 1.0 || maxval <= 0.0 || maxval > 1.0)
		{
			printf("Error: breakpoint amplitude values out of range in file \"%s\"\n"
			       "       0.0 < amp <= 1.0\n", argv[ARG_AMP]);
			error++;
			goto exit; 
		}
		maxamp = maxval; // retain the maximum breakpoint amplitude value	
	}

	/* get frequency value or breakpoint file */
	fpfreq = fopen(argv[ARG_FREQ],"r");
	if (fpfreq == NULL)
	{
		if ( (argv[ARG_FREQ][0] < '0' || argv[ARG_FREQ][0] > '9') &&
		   (argv[ARG_FREQ][0] != '.' && argv[ARG_FREQ][0] != '-') ||
		   (argv[ARG_FREQ][0] == '.' && (argv[ARG_FREQ][1] < '0' || argv[ARG_FREQ][1] > '9')) ||
		   (argv[ARG_FREQ][0] == '-' && (argv[ARG_FREQ][1] < '0' || argv[ARG_FREQ][1] > '9') && argv[ARG_FREQ][1] != '.') )
		{
			printf("Error: breakpoint file \"%s\" does not exist.\n",
			        argv[ARG_FREQ]);
			error++;
			goto exit;
		}
		freq = atof(argv[ARG_FREQ]);
		if (freq <= 0.0)
		{
			printf("Error: frequency must be positive.\n");
			error++;
			goto exit;
		}
	}
	else
	{
		freqstream = bps_newstream(fpfreq,outprops.srate,&brkfreqSize);
		if (freqstream == NULL)
		{
			printf("Error reading breakpoing values from file \"%s\".\n",
			        argv[ARG_FREQ]);
			error++;
			goto exit;
		}	
		if (bps_getminmax(freqstream,&minval,&maxval))
		{
			printf("Error: unable to read breakpoint range "
			       "from file \"%s\".\n", argv[ARG_FREQ]);
			error++;
			goto exit;
		}
		if (minval < 0.0 || maxval < 0.0)
		{
			printf("Error: breakpoint frequency values out of range in file \"%s\"\n"
			       "       freq >= 0.0\n", argv[ARG_FREQ]);
			error++;
			goto exit;
		}
	}

	/* create an outfile buffer */	
	nframes = DEFAULT_NFRAMES;
	buffer = (float *) malloc (sizeof(float) * nframes * outprops.chans);
	if (buffer == NULL)
	{
		printf("No memory!\n");
		error++;
		goto exit;
	}

	/* calculate the total number of outfile frames */
	outframes = (unsigned long) (dur * outprops.srate + 0.5);	

	/* calculate the number of buffers used in outfile */
	nbufs = outframes / nframes;
	remainder = outframes - nframes * nbufs; 
	if (remainder > 0)
		nbufs++;

	/* allocate space for new wavetype table oscillator 
	   and initialize oscillator */
	switch (wavetype)
	{
		case (WAVE_SINE):
			gtable = new_sine(width); 
			if (gtable == NULL)
			{
				printf("Error: unable to create a sine wave table.\n");
				error++;
				goto exit;
			}
			p_osc = new_oscilt(outprops.srate,gtable,0); 
			break;
		case (WAVE_SQUARE):
			gtable = new_square(width,nharms);
			if (gtable == NULL)
			{
				printf("Error: unable to create a square wave table.\n");
				error++;
				goto exit;
			}
			p_osc = new_oscilt(outprops.srate,gtable,0); 
			break;
		case (WAVE_TRIANGLE):
			gtable = new_triangle(width,nharms);
			if (gtable == NULL)
			{
				printf("Error: unable to create a triangle wave table.\n");
				error++;
				goto exit;
			}
			p_osc = new_oscilt(outprops.srate,gtable,0.25); 
			break;
		case (WAVE_SAWUP):
		if (!strcmp(argv[ARG_TYPE],"pulse")) /* case (WAVE_PULSE): */
		{
			gtable = new_pulse(width,nharms);
			if (gtable == NULL)
			{
				printf("Error: unable to create a pulse wave table.\n");
				error++;
				goto exit;
			}
			p_osc = new_oscilt(outprops.srate,gtable,0);
			break;
		}
		case (WAVE_SAWDOWN):
			if (wavetype==WAVE_SAWUP)
				gtable = new_saw(width,nharms,SAW_UP);
			else 
				gtable = new_saw(width,nharms,SAW_DOWN);
			if (gtable == NULL)
			{
				printf("Error: unable to create a saw%s wave table.\n",
				        (wavetype==SAW_UP)?"up":"down");
				error++;
				goto exit;
			}	
			p_osc = new_oscilt(outprops.srate,gtable,0);
			break;
	}	

	printf("Creating soundfile...\n");

	/* process soundfile */
	framesread = 0;
	for (i=0; i < nbufs; i++)	
	{
		/* update outfile copy status after the buffer
		   is refreshed every 100 times */
		if(i%100)
		{
			printf("%lu frames copied... %d%%\r",
			        framesread, (int)(framesread*100/outframes));
		} 
		/* clear update status when done */
		if (i==(nbufs-1))
			printf("                                        \n");

		if ((i == (nbufs-1)) && remainder)	
			nframes = remainder;
		for (j=0; j < nframes; j++)
		{
			if (ampstream)
				amp = bps_tick(ampstream);
			if (freqstream)
				freq = bps_tick(freqstream);
			val = tickfunc(p_osc,freq) * amp;	
			for (i_out=0; i_out < outprops.chans; i_out++)
				buffer[j*outprops.chans + i_out] = val;
		}
		if (psf_sndWriteFloatFrames(ofd,buffer,nframes) != nframes)
		{
			printf("Error: unable to write frames to outfile.\n");
			error++;
			break;
		}
		framesread += nframes;
	}

	/* make sure peak amplitude roughly matches the
	   user requested amplitude */
	if (ampstream)
		peakdiff = maxamp-psf_sndPeakValue(ofd,&outprops);
	else	
		peakdiff = amp-psf_sndPeakValue(ofd,&outprops);
	if ((peakdiff>.001) || (peakdiff<-.001))
	{
		printf("ERROR: unable to generate the correct peak\n"
		       "       amplitude for %s\n", argv[ARG_OUTFILE]);
		error++;
	}

	printf("Done. %d error%s\n"
	       "soundfile created: %s\n"
	       "number of frames:  %lu\n",
	        error, (error==1)?"":"s",
	        argv[ARG_OUTFILE], framesread);

	/* display soundfile properties if successfully copied */
	if (!error)
		psf_sndInfileProperties(argv[ARG_OUTFILE],ofd,&outprops);

	/* clean resources */
	exit:
	if (ofd >= 0)
	{
		if (psf_sndClose(ofd))
		{
			printf("Error: unable to close soundfile: %s\n",
			        argv[ARG_OUTFILE]); 
		}
		else if (error)
		{
			printf("There was an error while processing the soundfile.\n"
			       "Deleting soundfile: %s\n", argv[ARG_OUTFILE]);
			if (remove(argv[ARG_OUTFILE]))
				printf("Error: unable to delete %s\n", argv[ARG_OUTFILE]);
			else
				printf("%s successfully deleted.\n", argv[ARG_OUTFILE]); 
		}
	}
	if (fpamp)
	{
		if (fclose(fpamp))
		{
			printf("Error: unable to close breakpoint file \"%s\"\n",
			        argv[ARG_AMP]);	
		}
	} 
	if (fpfreq)
	{
		if (fclose(fpfreq))
		{
			printf("Error: unable to close breakpoint file \"%s\"\n",
			        argv[ARG_FREQ]);
		}
	}
	if (buffer)
	{
		free(buffer);
		buffer = NULL;
	}
	if (ampstream)
	{
		bps_freepoints(ampstream);
		ampstream = NULL;
	}
	if (freqstream)
	{
		bps_freepoints(freqstream);
		freqstream = NULL;
	}
	if (gtable)
		gtable_free(&gtable);
	if (p_osc)
	{
		free(p_osc);
		p_osc = NULL;
	}
	psf_finish();

	return error;
}
Esempio n. 3
0
void sig_gen(int argc, char *argv[])
{
    //This function will generate simple waveforms --> Sine, Triangle, Square, Sawtooth up, Sawtooth down
	//Showcases Pseudo-Object Oriented Programming, Function Pointers (functoids)
    /***************USAGE***************
     siggen outfile wavetype dur srate amp freq
     **********************************/
    if(argc < SIG_GEN_NARGS)
    {
        fprintf(stderr, "insufficient arguments.\n"
               "usage: siggen outfile wavetype dur srate amp freq\n"
               "where wavetype =:\n"
               "                0 = sine\n"
               "                1 = triangle\n"
               "                2 = square\n"
               "                3 = sawtooth up\n"
               "                4 = sawtooth down\n"
               "dur   = duration of outfile (seconds)\n"
               "srate = required sample rate of outfile\n"
               "amp   = amplitude value or breakpoint file (0 < amp <= 1.0)\n"
               "freq  = frequency value (freq > 0) or breakpoint file.\n"
               );
        exit(1);
    }
    
   /********* initialize all dynamic resources to default states **********/
    PSF_PROPS outprops;
    int ofd = -1;
    PSF_CHPEAK* peaks = NULL;
    psf_format outformat = PSF_FMT_UNKNOWN; //all psf* defined in portsf sound library
    long nframes = NFRAMES;
    float* outframe = NULL;
    double amp,freq,dur;
    unsigned long outframes,nbufs,i;
    long remainder;
    int wavetype;
    OSCIL* osc = NULL; //OSCIL pseudo-object defined in wave_generator.h
    node_func_ptr node; //function pointer defined in wave_generator.h
    FILE* fpfreq = NULL;
    FILE* fpamp = NULL;
    BRKSTREAM* freqstream = NULL; //BRKSTREAM* defined in breakpoint.h
    BRKSTREAM* ampstream = NULL;
    unsigned long brkfreqSize = 0, brkampSize = 0;
    double minval, maxval;
    
    /********** error checking on wave type **********/
    wavetype = atoi(argv[SIG_GEN_TYPE]);
    if(wavetype < SINE_WAVE || wavetype >= NUM_WAVE_TYPES)
    {
        fprintf(stderr, "Error: wavetype not defined\n");
        goto exit;
    }
    
	/********** assigning function pointer accordingly **********/
    switch(wavetype)
    {
        case(SINE_WAVE):
            node = sine_wave_node; //node is a function pointer (type: node_func_ptr); sine_wave_node is function
            break;
		case(SQAURE_WAVE):
			node = square_wave_node;
			break;
		case(TRIANGLE_WAVE):
			node = triangle_wave_node;
			break;
		case(SAW_UP_WAVE):
			node = sawtooth_up_wave_node;
			break;
		case(SAW_DOWN_WAVE):
			node = sawtooth_down_wave_node;
			break;
    }
    
    /********** define outfile format (with embedded error checking) **********/
    outprops.srate = atoi(argv[SIG_GEN_SRATE]);
    if(outprops.srate <= 0)
    {
        fprintf(stderr, "Error: srate must by positive (>=0)\n");
        goto exit;
    }
    outprops.chans = 1; //as of this sig_gen implementation --> mono
    outprops.samptype = (psf_stype) PSF_SAMP_16; //16-bit samples
    outprops.chformat = STDWAVE; //STDWAVE defined in portsf library 
    
    dur = atof(argv[SIG_GEN_DUR]);
    if(dur <= 0.0)
    {
        fprintf(stderr, "Error: duration must be positive (>=0)\n");
        goto exit;
    }
    outframes = (unsigned long) (dur * outprops.srate + 0.5);
    nbufs = outframes / nframes;
    remainder = outframes - nbufs * nframes;
    if(remainder) nbufs++;
    
    /********** open breakpoint files, or set constants if no breakpoint file is defined **********/
    /***** amp (amplitude) breakpoints file *****/
    fpamp = fopen(argv[SIG_GEN_AMP], "r"); //try opening specified argument
    if(fpamp == NULL)
    {
        //meaning that either argument SIG_GEN_AMP is not a breakpoint file or error opening
        amp = atof(argv[SIG_GEN_AMP]);
        if(amp <= 0.0 || amp > 1)
        {
            fprintf(stderr, "Error: amplitude must be between 0 and 1 (0 <= amp <= 1)\n");
            goto exit;
        }
    }
    else
    {
        //meaning that argument SIG_GEN_AMP is indeed a breakpoint file
        ampstream = bps_newstream(fpamp,outprops.srate,&brkampSize);
        if(ampstream == NULL)
        {
            fprintf(stderr, "Error reading amplitude breakpoint file: %s\n", argv[SIG_GEN_AMP]);
            goto exit;
        }
        if(bps_getminmax(ampstream, &minval, &maxval))
        {
            //meaning we called upon said function that will put into minval and maxval appropriate values
            //if said function returns 1 --> we have error
            fprintf(stderr, "Error reading range breakpoint file: %s\n", argv[SIG_GEN_AMP]);
            goto exit;
        }
        if(minval < 0.0 || minval > 1.0 || maxval < 0.0 || maxval > 1.0)
        {
            fprintf(stderr, "Error: amplitude values out of range in breakpoint file\n");
            goto exit;
        }
    }
    
    /***** freq (frequency) breakpoints file *****/
    fpfreq = fopen(argv[SIG_GEN_FREQ], "r");
    if(fpfreq == NULL)
    {
        //meaning that either argument SIG_GEN_FREQ is not a breakpoint file or error opening
        freq = atof(argv[SIG_GEN_FREQ]);
        if(freq <= 0.0)
        {
            fprintf(stderr, "Error: frequency must be positive\n");
            goto exit;
        }
    }
    else
    {
        //meaning that argument SIG_GEN_FREQ is indeed a breakpoint file
        freqstream = bps_newstream(fpfreq, outprops.srate, &brkfreqSize);
        if(freqstream == NULL)
        {
            fprintf(stderr, "Error reading frequncy from breakpoint file: %s\n", argv[SIG_GEN_FREQ]);
            goto exit;
        }
        if(bps_getminmax(freqstream, &minval, &maxval))
        {
            fprintf(stderr, "Error reading range from breakpoint file: %s\n", argv[SIG_GEN_FREQ]);
            goto exit;
        }
        if(minval <= 0.0)
        {
            fprintf(stderr, "Error in breakpoing file; Frequency values must be positive\n");
            goto exit;
        }
            
    }
    
    
    /********** Initialize OSCIL pseudo-object **********/
    osc = new_oscil(outprops.srate);
    if(osc == NULL)
    {
        fprintf(stderr, "No memory for oscillator\n");
        goto exit;
    }
    
    /********** Initialize portsf **********/
    if(psf_init())
    {
        fprintf(stderr, "Error: Unable to initialize portsf\n");
        goto exit;
    }
    
    /********** Sample Frame Buffer Memory Aloocation **********/
    outframe = (float*)malloc(nframes * outprops.chans * sizeof(float));
    if(outframe == NULL)
    {
        fprintf(stderr, "Error: No memory for outframe buffer\n");
        goto exit;
    }
    
    /********** Check for correct output extension **********/
    outformat = psf_getFormatExt(argv[SIG_GEN_OUTFILE]);
    if(outformat == PSF_FMT_UNKNOWN)
    {
        fprintf(stderr, "Error: invalid extension\n"
                "Possible extensions:\t *.wav\t *.aiff\t *.aif\t *.afc\t *.aifc\n");
        goto exit;
    }
    //reach here meaning outformat is viable extension
    outprops.format = outformat;
    
    /********** Initialize Peak nfo **********/
    peaks = (PSF_CHPEAK*)malloc(outprops.chans * sizeof(PSF_CHPEAK));
    if(peaks == NULL)
    {
        fprintf(stderr, "Error: No memory for peaks\n");
        goto exit;
    }
    
    /********** Create and Handle outfile **********/
    ofd = psf_sndCreate(argv[SIG_GEN_OUTFILE],&outprops, 0, 0, PSF_CREATE_RDWR); //refer to sf2float for documentation
    if(ofd < 0)
    {
        fprintf(stderr, "Error: Unable to create outfile\n");
        goto exit;
    }
    
    /********** Audio Processing **********/
    for(i=0; i<nbufs; i++)
    {
        long j;
        if(i == nbufs-1) 
            nframes = remainder;
        
        for(j=0; j<nframes; j++)
        {
            if(freqstream)
                freq = bps_tick(freqstream);
            if(ampstream)
                amp = bps_tick(ampstream);
            outframe[j] = (float)(amp * node(osc,freq)); //call upon function via function pointer with OSCIL pseudo-object and freq;
        }
        if(psf_sndWriteFloatFrames(ofd, outframe, nframes) != nframes)
        {
            fprintf(stderr, "Error: unable to write to outfile\n");
            goto exit;
        }
    }   
    
    /********** Clean_up section **********/
    exit:
    fprintf(stderr, "Task Finished\n");
    /***** Report PEAK values to user *****/
    if(psf_sndReadPeaks(ofd,peaks,NULL) > 0){
		long i;
		double peaktime;
		printf("PEAK information:\n");	
        for(i=0;i < outprops.chans;i++){
            peaktime = (double) peaks[i].pos / (double) outprops.srate;
            printf("CH %d:\t%.4f at %.4f secs\n", (int)(i+1), peaks[i].val, peaktime);
        }
	}
    
    
    if(ofd >= 0)
		if(psf_sndClose(ofd))
			printf("Error closing outfile %s\n",argv[SIG_GEN_OUTFILE]);
	if(outframe)
		free(outframe);
	if(peaks)
		free(peaks);
	/*TODO: cleanup any other resources */
	if(osc)
		free(osc);
	if(fpfreq)
		if(fclose(fpfreq))
			printf("Error closing breakpoint file %s\n",argv[SIG_GEN_FREQ]);
	if(fpamp)
		if(fclose(fpamp))
			printf("Error closing breakpoint file %s\n",argv[SIG_GEN_AMP]);
	if(freqstream){
		bps_freepoints(freqstream);
		free(freqstream);
	}
	if(ampstream){
		bps_freepoints(ampstream);
		free(ampstream);
	}
	psf_finish();
    exit(1);
}