| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260 |
- /*
- * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
- * http://www.trevorwishart.co.uk
- * http://www.composersdesktop.com
- *
- This file is part of the CDP System.
- The CDP System is free software; you can redistribute it
- and/or modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The CDP System is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the CDP System; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
- *
- */
- /* RWD/TW 24/02/18: removed usage ref to "Outputs..." names */
- #include <stdio.h>
- #include <stdlib.h>
- #include <structures.h>
- #include <cdpmain.h>
- #include <tkglobals.h>
- #include <pnames.h>
- #include <synth.h>
- #include <processno.h>
- #include <modeno.h>
- #include <globcon.h>
- #include <logic.h>
- #include <filetype.h>
- #include <mixxcon.h>
- #include <speccon.h>
- #include <flags.h>
- #include <arrays.h>
- #include <formants.h>
- #include <sfsys.h>
- #include <osbind.h>
- #include <string.h>
- #include <math.h>
- #include <srates.h>
- //TW UPDATES
- #include <ctype.h>
- #include <special.h>
- #ifndef HUGE
- #define HUGE 3.40282347e+38F
- #endif
- /********************************************************************************************/
- /********************************** FORMERLY IN pconsistency.c ******************************/
- /********************************************************************************************/
- static int synth_consistency(dataptr dz);
- static void init_specsynth(dataptr dz);
- static int specsynth_consistency(dataptr dz);
- //TW UPDATE: new functions
- static int read_clicktrack_data(char *,dataptr dz);
- static int gettempo(char *str,double *tempo,double *pulse_unit,double *accel,int linecnt,int *GP,int *is_abstime);
- static int getmeter(char *str,int *metre_num,int *metre_denom,int linecnt,int GP,int is_abstime,double *abstime,int *accent);
- static int getstyle(char *str,char *style,int metre_num,int linecnt,int GP,int is_abstime);
- static int getcount(char *str,int *barcnt,int linecnt,int GP,int is_abstime,double *timeincr);
- static int generate_clickdata(int init,int *arraysize,double tempo,double pulse_unit,int metre_num,int metre_denom,
- char *style,int barcnt,double accel,double *time,double *lasttime,
- int GP,int is_abstime,double abstime,int accent,double timeincr,int *tcnt,int *tarray,
- double *mintimestep,dataptr dz);
- static int default_style(char *style,int metre_num);
- static int generate_clicktable(dataptr dz);
- static int click_consistency(dataptr dz);
- static int getlineno(char *str,int tcnt,int linecnt);
- static int read_chord_data(char *str,dataptr dz);
- /***************************************************************************************/
- /****************************** FORMERLY IN aplinit.c **********************************/
- /***************************************************************************************/
- /***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
- int establish_bufptrs_and_extra_buffers(dataptr dz)
- {
- int exit_status;
- int is_spec = FALSE;
- dz->extra_bufcnt = -1; /* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
- dz->bptrcnt = 0;
- dz->bufcnt = 0;
- switch(dz->process) {
- case(SYNTH_SPEC):
- is_spec = TRUE;
- dz->extra_bufcnt = 0; dz->bptrcnt = 5;
- break;
- case(SYNTH_WAVE):
- case(MULTI_SYN):
- case(SYNTH_NOISE):
- case(SYNTH_SIL):
- //TW UPDATE
- case(CLICK):
- dz->extra_bufcnt = 0; dz->bufcnt = 1;
- break;
- default:
- sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
- return(PROGRAM_ERROR);
- }
- if(dz->extra_bufcnt < 0) {
- sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
- return(PROGRAM_ERROR);
- }
- if(is_spec)
- return establish_spec_bufptrs_and_extra_buffers(dz);
- else if((dz->process==HOUSE_SPEC && dz->mode==HOUSE_CONVERT) || dz->process==INFO_DIFF) {
- if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0)
- return(exit_status);
- }
- return establish_groucho_bufptrs_and_extra_buffers(dz);
- }
- /***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
- int setup_internal_arrays_and_array_pointers(dataptr dz)
- {
- int n;
- dz->ptr_cnt = -1; /* base constructor...process */
- dz->array_cnt = -1;
- dz->iarray_cnt = -1;
- dz->larray_cnt = -1;
- switch(dz->process) {
- //TW UPDATE
- case(CLICK): dz->array_cnt=3; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
- case(SYNTH_WAVE):
- case(SYNTH_NOISE): dz->array_cnt=1; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
- case(MULTI_SYN): dz->array_cnt=4; dz->iarray_cnt=0; dz->larray_cnt=1; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
- case(SYNTH_SPEC):
- case(SYNTH_SIL): dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
- }
- /*** WARNING ***
- ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
- **** WARNING ***/
- if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
- sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");
- return(PROGRAM_ERROR);
- }
- if(dz->array_cnt > 0) {
- if((dz->parray = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->array_cnt;n++)
- dz->parray[n] = NULL;
- }
- if(dz->iarray_cnt > 0) {
- if((dz->iparray = (int **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->iarray_cnt;n++)
- dz->iparray[n] = NULL;
- }
- if(dz->larray_cnt > 0) {
- if((dz->lparray = (int **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->larray_cnt;n++)
- dz->lparray[n] = NULL;
- }
- if(dz->ptr_cnt > 0) {
- if((dz->ptr = (double **)malloc(dz->ptr_cnt * sizeof(double *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->ptr_cnt;n++)
- dz->ptr[n] = NULL;
- }
- if(dz->fptr_cnt > 0) {
- if((dz->fptr = (float **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->fptr_cnt;n++)
- dz->fptr[n] = NULL;
- }
- return(FINISHED);
- }
- /****************************** ASSIGN_PROCESS_LOGIC *********************************/
- int assign_process_logic(dataptr dz)
- {
- switch(dz->process) {
- //TW UPDATE
- case(CLICK): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
- case(MULTI_SYN):
- case(SYNTH_WAVE): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
- case(SYNTH_NOISE): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
- case(SYNTH_SIL): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
- case(SYNTH_SPEC): setup_process_logic(NO_FILE_AT_ALL, BIG_ANALFILE, NO_OUTPUTFILE, dz); break;
- default:
- sprintf(errstr,"Unknown process: assign_process_logic()\n");
- return(PROGRAM_ERROR);
- break;
- }
- if(dz->has_otherfile) {
- switch(dz->input_data_type) {
- case(ALL_FILES):
- case(TWO_SNDFILES):
- case(SNDFILE_AND_ENVFILE):
- case(SNDFILE_AND_BRKFILE):
- case(SNDFILE_AND_UNRANGED_BRKFILE):
- case(SNDFILE_AND_DB_BRKFILE):
- break;
- case(MANY_SNDFILES):
- if(dz->process==INFO_TIMELIST)
- break;
- /* fall thro */
- default:
- sprintf(errstr,"Most processes accepting files with different properties\n"
- "can only take 2 sound infiles.\n");
- return(PROGRAM_ERROR);
- }
- }
- return(FINISHED);
- }
- /***************************** SET_LEGAL_INFILE_STRUCTURE **************************
- *
- * Allows 2nd infile to have different props to first infile.
- */
- void set_legal_infile_structure(dataptr dz)
- {
- switch(dz->process) {
- default:
- dz->has_otherfile = FALSE;
- break;
- }
- }
- /****************************** FORMERLY IN internal.c *********************************/
- /***************************************************************************************/
- /****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
- int set_legal_internalparam_structure(int process,int mode,aplptr ap)
- {
- int exit_status = FINISHED;
- switch(process) {
- //TW UPDATE
- case(CLICK): exit_status = set_internalparam_data("i",ap); break;
- case(SYNTH_SPEC):
- case(MULTI_SYN):
- case(SYNTH_WAVE): exit_status = set_internalparam_data("",ap); break;
- case(SYNTH_NOISE): exit_status = set_internalparam_data("0",ap); break;
- case(SYNTH_SIL): exit_status = set_internalparam_data("00",ap); break;
- default:
- sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
- return(PROGRAM_ERROR);
- }
- return(exit_status);
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN specialin.c *********************************/
- /********************************************************************************************/
- /********************** READ_SPECIAL_DATA ************************/
- int read_special_data(char *str,dataptr dz)
- {
- aplptr ap = dz->application;
- switch(ap->special_data) {
- //TW UPDATE
- case(CLICKTRACK):
- dz->infile->srate = CLICK_SRATE;
- return read_clicktrack_data(str,dz);
- case(CHORD_SYN):
- dz->infile->srate = CLICK_SRATE;
- return read_chord_data(str,dz);
- default:
- sprintf(errstr,"Unknown special_data type: read_special_data()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED); /* NOTREACHED */
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN preprocess.c ********************************/
- /********************************************************************************************/
- /****************************** PARAM_PREPROCESS *********************************/
- int param_preprocess(dataptr dz)
- {
- int exit_status = FINISHED, n;
- //TW UPDATE
- double x, convertor;
- switch(dz->process) {
- //TW UPDATE
- case(CLICK):
- if((exit_status = generate_clicktable(dz))<0)
- return(exit_status);
- break;
- case(SYNTH_WAVE):
- case(SYNTH_NOISE):
- case(SYNTH_SIL):
- break;
- case(MULTI_SYN):
- convertor = (double)dz->iparam[SYN_TABSIZE] / (double)dz->iparam[SYN_SRATE];
- for(n = 0;n<dz->itemcnt;n++)
- dz->parray[1][n] *= convertor;
- break;
- case(SYNTH_SPEC):
- x = (dz->param[SS_FOCUS] * 4.0) - 2.0;
- dz->param[SS_FOCUS] = pow(10,x);
- x = (dz->param[SS_FOCUS2] * 4.0) - 2.0;
- dz->param[SS_FOCUS2] = pow(10,x);
- break;
- default:
- sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN procgrou.c **********************************/
- /********************************************************************************************/
- /**************************** GROUCHO_PROCESS_FILE ****************************/
- int groucho_process_file(dataptr dz) /* FUNCTIONS FOUND IN PROCESS.C */
- {
- switch(dz->process) {
- //TW UPDATE
- case(CLICK):
- case(SYNTH_WAVE):
- case(MULTI_SYN):
- case(SYNTH_NOISE):
- case(SYNTH_SIL):
- return do_synth(dz);
- case(SYNTH_SPEC):
- return do_stereo_specsynth(dz);
- default:
- sprintf(errstr,"Unknown case in process_file()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED); /* NOTREACHED */
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN pconsistency.c ******************************/
- /********************************************************************************************/
- /****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
- int check_param_validity_and_consistency(dataptr dz)
- {
- int exit_status;
- handle_pitch_zeros(dz);
- switch(dz->process) {
- case(SYNTH_WAVE):
- case(MULTI_SYN):
- case(SYNTH_NOISE):
- case(SYNTH_SIL):
- if((exit_status = synth_consistency(dz))<0)
- return exit_status;
- dz->infile->channels = dz->iparam[SYN_CHANS];
- dz->infile->srate = dz->iparam[SYN_SRATE];
- dz->infile->stype = SAMP_SHORT;
- return create_sized_outfile(dz->wordstor[0],dz);
- case(SYNTH_SPEC):
- init_specsynth(dz);
- //TW UPDATE
- return specsynth_consistency(dz);
- case(CLICK):
- //TW UPDATE
- if((exit_status = click_consistency(dz))<0)
- return exit_status;
- dz->infile->channels = 1;
- dz->infile->srate = 44100;
- dz->infile->stype = SAMP_SHORT;
- return create_sized_outfile(dz->wordstor[0],dz);
- }
- return(FINISHED);
- }
- /****************************** SYNTH_CONSISTENCY *********************************/
- int synth_consistency(dataptr dz)
- {
- if(BAD_SR(dz->iparam[SYN_SRATE])) {
- sprintf(errstr,"Invalid sample rate.\n");
- return(DATA_ERROR);
- }
- dz->iparam[SYN_TABSIZE] /= 4;
- dz->iparam[SYN_TABSIZE] *= 4;
-
- return(FINISHED);
- }
- /****************************** SPECSYNTH_CONSISTENCY *********************************/
- int specsynth_consistency(dataptr dz)
- {
- if(dz->vflag[SS_PICHSPRD]) {
- if(dz->param[SS_SPREAD] > dz->nyquist/SPEC_MINFRQ) {
- sprintf(errstr,"SPREAD value is too large for pitch transposition (rather than frq) data.\n");
- return(DATA_ERROR);
- }
- }
- return(FINISHED);
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN buffers.c ***********************************/
- /********************************************************************************************/
- /**************************** ALLOCATE_LARGE_BUFFERS ******************************/
- int allocate_large_buffers(dataptr dz)
- {
- int exit_status, tempchans;
- switch(dz->process) {
- //TW UPDATE
- case(SYNTH_WAVE): case(SYNTH_NOISE): case(SYNTH_SIL): case(CLICK): case(MULTI_SYN):
- tempchans = dz->infile->channels;
- if(dz->process == CLICK)
- dz->infile->channels = 1;
- else
- dz->infile->channels = dz->iparam[SYN_CHANS];
- if((exit_status = create_sndbufs(dz))<0)
- return exit_status;
- dz->infile->channels = tempchans;
- return FINISHED;
- case(SYNTH_SPEC):
- return allocate_triple_buffer(dz);
- default:
- sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED); /* NOTREACHED */
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN cmdline.c ***********************************/
- /********************************************************************************************/
- int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
- {
- if (!strcmp(prog_identifier_from_cmdline,"wave")) dz->process = SYNTH_WAVE;
- else if(!strcmp(prog_identifier_from_cmdline,"noise")) dz->process = SYNTH_NOISE;
- else if(!strcmp(prog_identifier_from_cmdline,"silence")) dz->process = SYNTH_SIL;
- else if(!strcmp(prog_identifier_from_cmdline,"spectra")) dz->process = SYNTH_SPEC;
- else if(!strcmp(prog_identifier_from_cmdline,"clicks")) dz->process = CLICK;
- else if(!strcmp(prog_identifier_from_cmdline,"chord")) dz->process = MULTI_SYN;
- else {
- sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
- return(USAGE_ONLY);
- }
- //TW UPDATE
- return(FINISHED);
- }
- /********************************************************************************************/
- /********************************** FORMERLY IN usage.c *************************************/
- /********************************************************************************************/
- /******************************** USAGE1 ********************************/
- int usage1(void)
- {
- sprintf(errstr,
- "USAGE: synth NAME (mode) outfile parameters\n"
- "\n"
- "where NAME can be any one of\n"
- "\n"
- //TW UPDATE
- "wave noise silence spectra clicks chord\n"
- "\n"
- "Type 'synth wave' for more info on synth wave option... ETC.\n");
- return(USAGE_ONLY);
- }
- /******************************** USAGE2 ********************************/
- int usage2(char *str)
- {
- if(!strcmp(str,"wave")) {
- sprintf(errstr,
- "GENERATE SIMPLE WAVEFORMS\n\n"
- "USAGE: synth wave mode outfile sr chans dur freq [-aamp] [-ttabsize]\n\n"
- "MODES ARE\n"
- "1) sine wave\n"
- "2) square wave\n"
- "3) sawtooth wave\n"
- "4) ramp wave\n\n"
- "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
- "CHANS can be 1, 2 or 4\n"
- "DUR is duration of output snd, in seconds.\n"
- "FREQ is frq of output sond, in Hz\n"
- "AMP is amplitude of output sound: 0.0 < Range <= 1.0 (max & default).\n"
- "TABSIZE is size of table storing waveform.\n"
- " defaults to 256: input value always rounded to multiple of 4.\n\n"
- "Frq and Amp may vary through time.\n");
- } else if(!strcmp(str,"chord")) {
- sprintf(errstr,
- "GENERATE CHORD ON SIMPLE WAVEFORM\n\n"
- "USAGE: synth chord mode outfile datafile sr chans dur [-aamp] [-ttabsize]\n\n"
- "MODES ARE\n"
- "1) DATAFILE has list of midi data\n"
- "2) DATAFILE has list of frequency data\n"
- "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
- "CHANS can be 1, 2 or 4\n"
- "DUR is duration of output snd, in seconds.\n"
- "AMP is amplitude of output sound: 0.0 < Range <= 1.0 (max & default).\n"
- "TABSIZE is size of table storing waveform.\n"
- " defaults to 4096: input value always rounded to multiple of 4.\n\n");
- } else if(!strcmp(str,"noise")) {
- sprintf(errstr,
- "GENERATE NOISE\n\n"
- "USAGE: synth noise outfile sr chans dur [-aamp]\n\n"
- "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
- "CHANS can be 1, 2 or 4\n"
- "DUR is duration of output snd, in seconds.\n"
- "AMP is amplitude of output sound: 0.0 < Range <= 1.0 (max & default).\n\n"
- "Amp may vary through time.\n");
- } else if(!strcmp(str,"silence")) {
- sprintf(errstr,
- "MAKE SILENT SOUNDFILE\n\n"
- "USAGE: synth silence outfile sr chans dur\n\n"
- "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
- "CHANS can be 1, 2 or 4\n"
- "DUR is duration of output snd, in seconds.\n");
- //TW UPDATE : new options
- } else if(!strcmp(str,"spectra")) {
- sprintf(errstr,
- "GENERATE BOTH CHANNELS OF A STEREO SPECTRAL BAND\n\n"
- "USAGE: synth spectra outfilename dur frq spread max-foc min-foc\n"
- " timevar srate [-p]\n\n"
- "DUR duration of output snd, in seconds.\n"
- "FRQ centre frequency of the band.\n"
- "SPREAD width of band, in Hz (default) or as transposition ratio.\n"
- "'Foc' = focus, degree to which band energy is concentrated at centre frequency.\n"
- "MAX-FOC range 0 1\n"
- "MIN-FOC range 0 1\n"
- "TIMEVAR Degree to which the band varies over time. Range 0-1.\n"
- "SRATE Sample rate of output audio file.\n\n"
- "-p If flag set, 'SPREAD' is a transposition ratio.\n\n");
- } else if(!strcmp(str,"clicks")) {
- sprintf(errstr,
- "CLICKTRACK USAGE: synth clicks mode outname clickfile [-sstart -eend -zzero]\n\n"
- " make clicktrack from 'start' to 'end'; music starting at dataline 'zero'.\n"
- " MODE 1: start and end are TIMES: MODE 2: start & end are data linenos.\n"
- " CLICKFILE contains sequence of datalines. Each dataline has a line number \n"
- " followed by 2, 3 or 4 data items, separated by spaces, which can be....\n"
- "TIME 141.52 (Set time to 141.52 secs: must be later than previous event)\n"
- "GP 1 23.7 (Pause of 23.7sec, with accent [1] at start: '0' for no accent)\n"
- " OR the following set of items:-\n"
- "1) TEMPO : in one of the forms (with no spaces around '='):-\n"
- " 1=144 (crotchet = 144) 1.5=100 (dotted crotchet = 100)\n"
- " 0.5=144to85.3 (tempo change from quaver = 144 to 85.3)\n"
- "2) BARRING : in the form 4:4 or 6:8 or 7:16 etc. (no spaces around the ':')\n"
- "3) COUNT : i.e. the (integer) number of bars in this format.\n"
- "------- and, optionally ---------\n"
- "4) ACCENT PATTERN 1..... strong beat followed by 5 weak beats\n"
- " 1..1.. strong beat (start), secondary (at 4), weak between\n"
- " 100100 strong & secondary beats, but NO intermediate beats\n"
- "IF THE ACCENT PATTERN IS OMITTED, default patterns are used. These are:-\n"
- "An accent on the start of each bar PLUS\n"
- "a) in 6:8, 9:8, 12:8, 15:8 etc, or 6:4, 6:16, 6:32, 9:4, 9:16 etc.\n"
- " sound on every unit (4,8,16,32 etc.), secondary accents every 3rd beat\n"
- "b) in All other meters: NO secondary accents\n");
- } else
- sprintf(errstr,"Unknown option '%s'\n",str);
- return(USAGE_ONLY);
- }
- /******************************** USAGE3 ********************************/
- int usage3(char *str1,char *str2)
- {
- sprintf(errstr,"Insufficient parameters on command line.\n");
- return(USAGE_ONLY);
- }
- /******************************** INNER_LOOP (redundant) ********************************/
- int inner_loop
- (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
- {
- return(FINISHED);
- }
- /******************************** INIT_SPECSYNTH (redundant) ********************************/
- void init_specsynth(dataptr dz)
- {
- //TW Extensive rewrite
- dz->outfile->origrate = dz->infile->origrate = (int)round(dz->param[SS_SRATE]);
- if(dz->floatsam_output) {
- dz->outfile->stype = SAMP_FLOAT;
- dz->infile->stype = SAMP_FLOAT;
- dz->outfile->origstype = SAMP_FLOAT;
- dz->infile->origstype = SAMP_FLOAT;
- } else {
- dz->outfile->origstype = SAMP_SHORT;
- dz->infile->origstype = SAMP_SHORT;
- dz->outfile->stype = SAMP_SHORT;
- dz->infile->stype = SAMP_SHORT;
- }
- dz->wanted = SPECSYN_MLEN;
- dz->outfile->channels = SPECSYN_MLEN;
- dz->infile->channels = SPECSYN_MLEN;
- dz->outfile->Mlen = dz->infile->Mlen = (dz->outfile->channels-2);
- dz->wanted = dz->infile->channels;
- dz->clength = dz->wanted/2;
- dz->nyquist = dz->outfile->origrate / 2;
- dz->outfile->Dfac = dz->infile->Dfac = (dz->outfile->channels-2) / 8;
- dz->outfile->arate = dz->infile->arate = (float) dz->outfile->origrate / (float)dz->outfile->Dfac;
- dz->outfile->srate = dz->infile->srate = (int) dz->outfile->arate;
- dz->frametime = (float)(1.0/dz->outfile->arate);
- dz->wlength = (int)round(dz->param[SS_DUR] * dz->outfile->arate);
- dz->chwidth = dz->nyquist/(double)dz->clength;
-
- }
- //TW UPDATE : NEW FUNCTIONS below
- /******************************** READ_CLICKTRACK_DATA ********************************/
- #define CLICKLINE (0)
- #define CLICKTEMPO (1)
- #define CLICKMETER (2)
- #define CLICKCOUNT (3)
- #define CLICKSTYLE (4)
- int read_clicktrack_data(char *str,dataptr dz)
- {
- int exit_status, init = 1;
- int cnt, linecnt = 0, GP, is_abstime, accent;
- char temp[200], *q, *p;
- int arraysize = BIGARRAY * 10, tarray = BIGARRAY * 10, tcnt = 0;/* ARRAYS V. BIG AS free() fails inside realloc() or on its own */
- double tempo = -1.0, accel = -1.0, time = 0.0, pulse_unit = 0.0, timeincr, lasttime = -HUGE, abstime = 0.0;
- int metre_num = -1, metre_denom = 1, barcnt = 0;
- char style[200];
- double mintimestep = 0.0;
- FILE *fp;
- if((fp = fopen(str,"r"))==NULL) {
- sprintf(errstr,"Cannot open clicktrack data file %s\n",str);
- return(DATA_ERROR);
- }
- while(fgets(temp,200,fp)!=NULL) { /* READ AND TEST BRKPNT VALS */
- q = temp;
- cnt = 0;
- while(isspace(*q))
- q++;
- GP = 0;
- is_abstime = 0;
- accent = 0;
- timeincr = 0.0;
- if(*q == ENDOFSTR || *q == ';') /* ignore blank lines and comments */
- continue;
- while(get_word_from_string(&q,&p)) {
- switch(cnt) {
- case(CLICKLINE):
- if((exit_status = getlineno(p,tcnt+1,linecnt+1)) < 0)
- return(exit_status);
- break;
- case(CLICKTEMPO):
- if((exit_status = gettempo(p,&tempo,&pulse_unit,&accel,linecnt,&GP,&is_abstime)) < 0)
- return(exit_status);
- break;
- case(CLICKMETER):
- if((exit_status = getmeter(p,&metre_num,&metre_denom,linecnt,GP,is_abstime,&abstime,&accent)) < 0)
- return(exit_status);
- break;
- case(CLICKCOUNT):
- if((exit_status = getcount(p,&barcnt,linecnt,GP,is_abstime,&timeincr)) < 0)
- return(exit_status);
- break;
- case(CLICKSTYLE):
- if((exit_status = getstyle(p,style,metre_num,linecnt,GP,is_abstime)) < 0)
- return(exit_status);
- break;
- default:
- sprintf(errstr,"Too many data items on line %d\n",linecnt+1);
- return(DATA_ERROR);
- }
- cnt++;
- }
- if(cnt < 5) {
- switch(cnt) {
- case(3):
- if(!is_abstime) {
- sprintf(errstr,"Too few data items on line %d\n",linecnt+1);
- return(DATA_ERROR);
- }
- break;
- case(4):
- if(!GP && ((exit_status = default_style(style,metre_num)) < 0))
- return(exit_status);
- break;
- default:
- sprintf(errstr,"Too few data items on line %d\n",linecnt+1);
- return(DATA_ERROR);
- }
- }
- if ((exit_status = generate_clickdata(init,&arraysize,tempo,pulse_unit,metre_num,metre_denom,style,barcnt,
- accel,&time,&lasttime,GP,is_abstime,abstime,accent,timeincr,&tcnt,&tarray,&mintimestep,dz)) < 0)
- return(exit_status);
- init = 0;
- linecnt++;
- }
- dz->parray[2][tcnt] = lasttime;
- dz->iparam[CLICKTIME] = linecnt;
- dz->duration = (double)linecnt; /* tells cdparams about range of param 3 */
- return(FINISHED);
- }
- /******************************** READ_CHORD_DATA ********************************/
- int read_chord_data(char *str,dataptr dz)
- {
- int cnt = 0, exit_status;
- char temp[200], *q;
- double maxmidi = 127.0, minmidi;
- double maxfrq = miditohz(127);
- double minfrq = 1.0/MAX_SYN_DUR;
- double d;
- FILE *fp;
- if((exit_status = hztomidi(&minmidi,minfrq)) < 0)
- return exit_status;
- if((fp = fopen(str,"r"))==NULL) {
- sprintf(errstr,"Cannot open chord data file %s\n",str);
- return(DATA_ERROR);
- }
- dz->ringsize = 1;
- while(fgets(temp,200,fp)!=NULL) { /* READ AND TEST BRKPNT VALS */
- q = temp;
- while(get_float_from_within_string(&q,&d)) {
- switch(dz->mode) {
- case(0): /* MIDI */
- if(d < minmidi || d > maxmidi) {
- sprintf(errstr,"Value %d (%lf) is out of range.\n",cnt+1,d);
- return(DATA_ERROR);
- }
- break;
- case(1): /* FRQ */
- if(d < minfrq || d > maxfrq) {
- sprintf(errstr,"Value %d (%lf) is out of range.\n",cnt+1,d);
- return(DATA_ERROR);
- }
- break;
- case(2): /* MIDI, CHORD SEQUENCE */
- if(d < -99.0)
- dz->ringsize++;
- else if(d < minmidi || d > maxmidi) {
- sprintf(errstr,"Value %d (%lf) is out of range.\n",cnt+1,d);
- return(DATA_ERROR);
- }
- break;
- }
- cnt++;
- }
- }
- if(cnt == 0) {
- sprintf(errstr,"No data found in file.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[1] = (double *)malloc(cnt * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory to store MIDI values.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[2] = (double *)malloc(cnt * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory to store table step values.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[3] = (double *)malloc(cnt * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory to store sample interpolators.\n");
- return(MEMORY_ERROR);
- }
- if((dz->lparray[0] = (int *)malloc(cnt * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory to store samplecounters.\n");
- return(MEMORY_ERROR);
- }
- fseek(fp,0,0);
- cnt = 0;
- while(fgets(temp,200,fp)!=NULL) { /* READ AND TEST BRKPNT VALS */
- q = temp;
- while(get_float_from_within_string(&q,&d)) {
- switch(dz->mode) {
- case(0):
- d = miditohz(d);
- break;
- case(2):
- if(d < -99.0)
- d = 0.0;
- else
- d = miditohz(d);
- break;
- }
- dz->parray[1][cnt] = d;
- cnt++;
- }
- }
- dz->itemcnt = cnt;
- for(cnt=0;cnt<dz->itemcnt;cnt++) {
- dz->parray[2][cnt] = 0.0; /* initialise all table increments and positions */
- dz->parray[3][cnt] = 0.0;
- dz->lparray[0][cnt] = 0;
- }
- return(FINISHED);
- }
- /*********************************** GETTEMPO ***********************************
- *
- * Expected format 1=144 OR 1.5=134.567 [or "G" (or "g") as part of "G P"]
- */
- int gettempo(char *str,double *tempo,double *pulse_unit,double *accel,int linecnt,int *GP,int *is_abstime)
- {
- char *p;
- p = str;
- if(!strcmp(str,"GP")) {
- *GP = 1;
- return(FINISHED);
- } else if(!strcmp(str,"TIME")) {
- if(linecnt == 0) {
- sprintf(errstr,"'TIME' dataline too soon: You cannot reset the Absolute time before you start the clickdata.\n");
- return(DATA_ERROR);
- }
- *is_abstime = 1;
- return(FINISHED);
- } else if(!strcmp(str,".")) {
- if(*accel >= 0.0) {
- sprintf(errstr,"Bad tempo data at line %d : Cannot use a DOT (for same tempo) when previous tempo was changing\n",linecnt+1);
- return(DATA_ERROR);
- } else if(*tempo < 0.0) {
- sprintf(errstr,"Bad tempo data at line %d : Cannot use a DOT (for same tempo) when no previous tempo established\n",linecnt+1);
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
- if(!strgetfloat_within_string(&p,pulse_unit)) {
- sprintf(errstr,"Bad tempo data at line %d : Cannot get length of pulse unit (e.g. 1 = crotchet)\n",linecnt+1);
- return(DATA_ERROR);
- }
- if(!flteq(*pulse_unit,1.0) && !flteq(*pulse_unit,2.0) && !flteq(*pulse_unit,3.0) && !flteq(*pulse_unit,4.0)
- && !flteq(*pulse_unit,1.5) && !flteq(*pulse_unit,0.75) && !flteq(*pulse_unit,0.375) && !flteq(*pulse_unit,0.1875)
- && !flteq(*pulse_unit,0.5) && !flteq(*pulse_unit,0.25) && !flteq(*pulse_unit,0.125)) {
- sprintf(errstr,"Bad tempo data at line %d : Invalid pulse unit (%.3lf)\n",linecnt+1,*pulse_unit);
- return(DATA_ERROR);
- }
- if(*p++ != '=') {
- sprintf(errstr,"Bad tempo data at line %d : '=' missing, or spaces before '='\n",linecnt+1);
- return(DATA_ERROR);
- }
- if(!strgetfloat_within_string(&p,tempo)) {
- sprintf(errstr,"Bad tempo data at line %d : Failed to find metronome mark value\n",linecnt+1);
- return(DATA_ERROR);
- }
- *accel = -1.0;
- if(strlen(p) > 0) {
- if(!strncmp(p,"to",2)) {
- p += 2;
- if(!strgetfloat_within_string(&p,accel)) {
- sprintf(errstr,"Bad tempo data at line %d : Failed to find tempo at end of tempo-change\n",linecnt+1);
- return(DATA_ERROR);
- }
- } else {
- sprintf(errstr,"Bad tempo data at line %d : Spurious characters at end (can be 'to' followed by 2nd tempo only)\n",linecnt+1);
- return(DATA_ERROR);
- }
- }
- return(FINISHED);
- }
- /*********************************** GETMETER ***********************************
- *
- * Expected format 3:8, [OR P (or p) as part of "G P"]
- */
- int getmeter(char *str,int *metre_num,int *metre_denom,int linecnt,int GP,int is_abstime,double *abstime,int *accent)
- {
- char *q,*p = str;
- int k, j;
- if(GP) {
- if(!strcmp(str,"1")) {
- *accent = 1;
- return(FINISHED);
- } else if(!strcmp(str,"0"))
- return(FINISHED);
- else {
- sprintf(errstr,"Bad GP data at line %d : no accent indicator (0 or 1)\n",linecnt+1);
- return(DATA_ERROR);
- }
- } else if(is_abstime) {
- if(sscanf(str,"%lf",abstime)!=1) {
- sprintf(errstr,"Bad TIME data at line %d (found '%s')\n",linecnt+1,str);
- return(DATA_ERROR);
- }
- return(FINISHED);
- } else if(!strcmp(str,".")) {
- if(*metre_num < 0) {
- sprintf(errstr,"Bad meter data at line %d : Cannot use a DOT (for same meter) when no previous meter exists\n",linecnt+1);
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
- while(*p != ':') {
- if(!isdigit(*p)) {
- sprintf(errstr,"Bad meter data at line %d : no numerator, or non-numeric character or space in numerator before ':' or missing ':'\n",linecnt+1);
- return(DATA_ERROR);
- }
- p++;
- }
- *p = ENDOFSTR;
- if(sscanf(str,"%d",metre_num)!=1) {
- sprintf(errstr,"Bad meter data at line %d : Failed to find numerator of meter\n",linecnt+1);
- return(DATA_ERROR);
- }
- p++;
- q = p;
- while(*p != ENDOFSTR) {
- if(!isdigit(*p)) {
- sprintf(errstr,"Bad meter data at line %d : non-numeric (or no) characters after ':'\n",linecnt+1);
- return(DATA_ERROR);
- }
- p++;
- }
- if(sscanf(q,"%d",metre_denom)!=1) {
- sprintf(errstr,"Bad meter data at line %d : Failed to find denominator of meter (no spaces permitted after ':')\n",linecnt+1);
- return(DATA_ERROR);
- }
- if((k = *metre_denom) < 2) {
- sprintf(errstr,"Bad meter data at line %d : denominator of meter is not a multiple of 2\n",linecnt+1);
- return(DATA_ERROR);
- }
- while(k > 2) {
- j = k/2;
- if(k != j * 2) {
- sprintf(errstr,"Bad meter data at line %d : denominator of meter is not a multiple of 2\n",linecnt+1);
- return(DATA_ERROR);
- }
- k = j;
- }
- return(FINISHED);
- }
- /*********************************** GETSTYLE ***********************************************
- *
- * Expected format 1..... or 1..1.. or 100100 where number of chars = denominator of meter
- */
- int getstyle(char *str,char *style,int metre_num,int linecnt,int GP,int is_abstime)
- {
- char *p = str;
- if(GP || is_abstime)
- return(FINISHED);
- while(*p != ENDOFSTR) {
- if(*p != '1' && *p != '.' && *p != '0') {
- sprintf(errstr,"Bad style data at line %d : Invalid character (%c) in style string (must be '1','0' or '.'\n",linecnt+1,*p);
- return(DATA_ERROR);
- }
- p++;
- }
-
- if((p - str) != metre_num) {
- sprintf(errstr,"Bad style data at line %d : Wrong number of characters in style-string (must be %d in this meter)\n",linecnt+1,metre_num);
- return(DATA_ERROR);
- }
- strcpy(style,str);
- return(FINISHED);
- }
- /*********************************** GETLINENO ***********************************************
- *
- * Expected format = digit (increasing from 1)
- */
- int getlineno(char *str,int tcnt,int linecnt)
- {
- int lineno;
- if(sscanf(str,"%d",&lineno)!=1) {
- sprintf(errstr,"Failed to read line number, at line %d (found '%s')\n",linecnt,str);
- return(DATA_ERROR);
- }
- if(lineno != linecnt) {
- if(lineno == 0) {
- sprintf(errstr,"Lines should be numbered from 1 upwards\n");
- return(DATA_ERROR);
- } else {
- sprintf(errstr,"Line numbers are not in sequence, at line %d\n",linecnt);
- return(DATA_ERROR);
- }
- }
- if(lineno != tcnt) {
- sprintf(errstr,"Anomaly in counting lines, at line %d\n",linecnt);
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /*********************************** GETCOUNT ***********************************************
- *
- * Expected format is an INTEGER
- */
- int getcount(char *str,int *barcnt,int linecnt,int GP,int is_abstime,double *timeincr)
- {
- char *p = str;
- if(is_abstime)
- return(FINISHED);
- else if(GP) {
- if(sscanf(str,"%lf",timeincr)!=1) {
- sprintf(errstr,"Failed to read duration of General Pause at line %d\n",linecnt+1);
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
- while(*p != ENDOFSTR) {
- if(!isdigit(*p)) {
- sprintf(errstr,"Bad bar-count data at line %d : Non-numeric character encountered (must be whole number of bars)\n",linecnt+1);
- return(DATA_ERROR);
- }
- p++;
- }
- if(sscanf(str,"%d",barcnt)!=1) {
- sprintf(errstr,"Bad bar-count data at line %d : Failed to read bar-count\n",linecnt+1);
- return(DATA_ERROR);
- }
- if(*barcnt < 1) {
- sprintf(errstr,"Bad bar-count (%d) data at line %d\n",*barcnt,linecnt+1);
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
- /*********************************** GENERATE_CLICKDATA ***********************************************/
- #define ACCELPOW (0.6)
- #define RITPOW (1.0/ACCELPOW)
- int generate_clickdata
- (int init,int *arraysize,double tempo,double pulse_unit,int metre_num,int metre_denom,char *style,int barcnt,double accel,
- double *time,double *lasttime,int GP,int is_abstime,double abstime,int accent,double timeincr,int *tcnt,int *tarray,
- double *mintimestep,dataptr dz)
- {
- int n, eventcnt;
- double timestep, unit_tempo, *cliks, pulse_mutiplier;
- double orig_timestep = 0.0, final_timestep, total_beats = 1.0, tstepinc = 0.0, thisincr;
- char *p = style;
- int do_accel, steptype = 1;
- if(init) {
- if((dz->parray[0] = (double *)malloc(*arraysize * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to make clicktrack data array.\n");
- return(MEMORY_ERROR);
- }
- dz->itemcnt = 0;
- *mintimestep = (double)((CLICKLEN + 1) + 4 /* safety */)/(double)dz->infile->srate;
- if((dz->parray[2] = (double *)malloc(*tarray * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to store clicktrack data line times.\n");
- return(MEMORY_ERROR);
- }
- }
- cliks = dz->parray[0];
- dz->parray[2][(*tcnt)++] = *time;
- if(*tcnt > *tarray) {
- *tarray += BIGARRAY;
- if((dz->parray[2] = (double *)realloc((char *)dz->parray[2],(*tarray) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to store clicktrack data line times.\n");
- return(MEMORY_ERROR);
- }
- }
- if(GP) {
- if(accent) {
- if(dz->itemcnt + 2 >= *arraysize) {
- *arraysize += BIGARRAY;
- if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],*arraysize * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to make expand clicktrack data array.\n");
- return(MEMORY_ERROR);
- }
- cliks = dz->parray[0];
- }
- cliks[dz->itemcnt++] = *time;
- cliks[dz->itemcnt++] = CLICKAMP1;
- }
- *lasttime = *time;
- *time += timeincr;
- return(FINISHED);
- }
- if(is_abstime) {
- if(abstime < *lasttime) {
- sprintf(errstr,"ABSOLUTE TIME %lf is OUT OF SEQUENCE.\n",abstime); /*RWD 12:2003 added abstime arg */
- return(DATA_ERROR);
- }
- *time = abstime;
- return(FINISHED);
- }
- pulse_mutiplier = (double)metre_denom/4.0; /* could be .5 if beats are minims */
- unit_tempo = tempo * pulse_unit; /* crotchets per minute */
- unit_tempo *= pulse_mutiplier; /* basic pulse-divisions per minute */
- unit_tempo /= 60.0; /* basic pulse-divisions per second */
- if((timestep = (1.0/unit_tempo)) < *mintimestep) {
- sprintf(errstr,"Tempo too fast to separate clicks in output, at time %lf secs.\n",*time);
- return(DATA_ERROR);
- }
- eventcnt = 0;
- if(accel > 0.0) { /* in accel or rit case, change tempo logwise */
- if((final_timestep = timestep * (tempo/accel)) < *mintimestep) {
- sprintf(errstr,"Tempo too fast to separate clicks in output, at time %lf secs.\n",*time);
- return(DATA_ERROR);
- }
- total_beats = barcnt * metre_num;
- if((tstepinc = final_timestep - timestep) < 0) {
- steptype = -1;
- tstepinc = -tstepinc;
- }
- orig_timestep = timestep;
- do_accel = 1;
- } else
- do_accel = 0;
- for(n = 0; n < barcnt; n++) { /* for each bar */
- if(dz->itemcnt + (metre_num * 2) >= *arraysize) {
- *arraysize += BIGARRAY;
- if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],*arraysize * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to make expand clicktrack data array.\n");
- return(MEMORY_ERROR);
- }
- cliks = dz->parray[0];
- }
- while(*p != ENDOFSTR) { /* for each beat in specified pattern */
- switch(*p) {
- case('1'):
- cliks[dz->itemcnt++] = *time;
- if(p == style) /* stress first beat */
- cliks[dz->itemcnt++] = CLICKAMP1;
- else /* half-stress subsidiary accents */
- cliks[dz->itemcnt++] = CLICKAMP2;
- break;
- case('.'): /* sound other beats with no stress */
- cliks[dz->itemcnt++] = *time;
- cliks[dz->itemcnt++] = CLICKAMP3;
- break;
- /* case('0'): ignore unsounded beats */
- }
- if(do_accel) { /* if tempo changing, increment timestep logwise */
- if(steptype < 0)
- thisincr = pow(((double)eventcnt/(double)total_beats),ACCELPOW) * tstepinc * steptype;
- else
- thisincr = pow(((double)eventcnt/(double)total_beats),RITPOW) * tstepinc * steptype;
- timestep = orig_timestep + thisincr;
- eventcnt++;
- }
- *lasttime = *time;
- *time += timestep; /* advance absolute time to next beat */
- p++; /* advance along accent pattern */
- }
- p = style; /* at end of pattern, return to start of pattern */
- }
- return(FINISHED);
- }
- /*********************************** DEFAULT_STYLE ***********************************************/
- int default_style(char *style,int metre_num)
- {
- char *p = style;
- int triple = 0, n;
- if((((metre_num/3) * 3) == metre_num) && (metre_num > 3))
- triple = 1;
- *p++ = '1';
- for(n = 1; n < metre_num;n++) {
- if(triple & (n%3 == 0))
- *p = '1';
- else
- *p = '.';
- p++;
- }
- *p = ENDOFSTR;
- return(FINISHED);
- }
- /*********************************** GENERATE_CLICKTABLE ***********************************************/
- int generate_clicktable(dataptr dz)
- {
- int n;
- double rand1, rand2, maxval;
- if((dz->parray[1] = (double *)malloc((CLICKLEN +1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to store click table.\n");
- return(MEMORY_ERROR);
- }
- initrand48();
- maxval = 0.0;
- for(n=0;n < CLICKLEN;n++) {
- rand1 = (drand48() * 2.0) - 1.0; /* in case I decide to modify it every time !! */
- rand2 = (drand48() * .02) - .01;
- dz->parray[1][n] = sqrt(sin(PI/(double)n)) * ((double)n * 2.0 * PI/(6.0+ rand1)) * rand2 * (MAXSHORT * .98);
- /* 1/2 sin envel, steepened * sin oscil every 6 or so samps * noise * maxsamp adjusted for noise wander */
- maxval= max(maxval,fabs(dz->parray[1][n]));
- }
- maxval = MAXSHORT/maxval;
- for(n=0;n < CLICKLEN;n++)
- dz->parray[1][n] *= maxval;
- dz->parray[1][n] = 0.0;
- return(FINISHED);
- }
- /*********************************** CLICK_CONSISTENCY ***********************************************/
- int click_consistency(dataptr dz)
- {
- double lasttime;
- switch(dz->mode) {
- case(CLICK_BY_TIME):
- if(dz->param[CLIKSTART] >= dz->param[CLIKEND]) {
- sprintf(errstr,"Start time for Click Generation is beyond End time.\n");
- return(DATA_ERROR);
- }
- lasttime = dz->parray[0][dz->itemcnt - 2];
- if(dz->param[CLIKSTART] > lasttime - FLTERR) {
- sprintf(errstr,"Start time for Click Generation is beyond end of your data.\n");
- return(DATA_ERROR);
- }
- dz->param[CLIKEND] = min(dz->param[CLIKEND],lasttime);
- break;
- case(CLICK_BY_LINE):
- if(dz->iparam[CLIKSTART] > dz->iparam[CLIKEND]) {
- sprintf(errstr,"Start line for Click Generation is at or beyond End line.\n");
- return(DATA_ERROR);
- }
- if(dz->iparam[CLIKSTART] > dz->iparam[CLICKTIME]) {
- sprintf(errstr,"Start line for Click Generation is beyond end of your data.\n");
- return(DATA_ERROR);
- }
- dz->iparam[CLIKSTART]--;
- dz->iparam[CLIKEND]--;
- dz->iparam[CLIKEND] = min(dz->iparam[CLIKEND],(dz->iparam[CLICKTIME] - 1));
- break;
- }
- dz->iparam[CLIKOFSET]--; /* convert from "1-N" to "0 to N-1" */
- return(FINISHED);
- }
|