| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*
- * 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
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <memory.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <pnames.h>
- #include <globcon.h>
- #include <processno.h>
- #include <modeno.h>
- #include <arrays.h>
- #include <specpinfo.h>
- #include <cdpmain.h>
- #include <formants.h>
- #include <speccon.h>
- #include <sfsys.h>
- #include <osbind.h>
- #include <float.h>
- #include <specpinfo.h>
- static int do_specpinfo(dataptr dz);
- static int specpzeros(dataptr dz);
- static int prescale_transposition_data(dataptr dz);
- static int generate_noise_in_buffer(double noischan_amp,dataptr dz);
- static int generate_tone_in_buffer(double pre_totalamp,double thisfrq,dataptr dz);
- static int preset_chanfrqs_to_chancentres(dataptr dz);
- static int construct_screen_message(dataptr dz);
- /**************************** SPECPINFO *********************/
- int specpinfo(dataptr dz)
- {
- int exit_status, valid_pitch_data = FALSE;
- int n;
- if(dz->is_transpos) {
- if((dz->transpos = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for transposition array.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->wlength;n++)
- dz->transpos[n] = 1.0f; /* DEFAULT: no transposition */
- }
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] > FLTERR) {
- valid_pitch_data = 1;
- break;
- }
- }
- if(!valid_pitch_data) {
- sprintf(errstr,"No valid pitches found in input data.\n");
- return(DATA_ERROR);
- }
- switch(dz->process) {
- case(P_INFO):
- if((exit_status = do_specpinfo(dz))<0)
- return(exit_status);
- break;
- case(P_ZEROS):
- if((exit_status = specpzeros(dz))<0)
- return(exit_status);
- break;
- default:
- sprintf(errstr,"Unknown process in specpinfo()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /************************************* DO_SPECPINFO ******************************/
- int do_specpinfo(dataptr dz)
- {
- int exit_status;
- int n, minpos = -1, maxpos = -1;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- if(dz->pitches[n] > dz->param[PINF_MAX]) {
- dz->param[PINF_MAX] = dz->pitches[n];
- maxpos = n;
- }
- if(dz->pitches[n] < dz->param[PINF_MIN]) {
- dz->param[PINF_MIN] = dz->pitches[n];
- minpos = n;
- }
- dz->param[PINF_MEAN] += dz->pitches[n];
- }
- dz->param[PINF_MEAN] /= (double)dz->wlength;
- dz->param[PINF_MAXPOS] = (double)maxpos * dz->frametime;
- dz->param[PINF_MINPOS] = (double)minpos * dz->frametime;
- if(maxpos < 0) {
- sprintf(errstr,"No valid pitch information found.\n");
- return(GOAL_FAILED);
- }
- if(minpos < 0) {
- sprintf(errstr,"No valid pitch below the nyquist frq found.\n");
- return(GOAL_FAILED);
- }
- if((exit_status = construct_screen_message(dz))<0)
- return(exit_status);
- return(FINISHED);
- }
-
- /***************************** SPECPZEROS *****************/
- int specpzeros(dataptr dz)
- {
- int n;
- dz->zeroset = FALSE;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH) {
- dz->zeroset = TRUE;
- break;
- }
- }
- if(dz->zeroset)
- sprintf(errstr,"File contains unpitched windows.\n");
- else
- sprintf(errstr,"File does NOT contain unpitched windows.\n");
- return(FINISHED);
- }
-
- /*************************************** SPECPSEE *************************/
- int specpsee(dataptr dz)
- {
- int exit_status;
- int wc;
- double val;
- if(dz->is_transpos) {
- if((exit_status = prescale_transposition_data(dz))<0)
- return(exit_status);
- for(wc=0;wc<dz->wlength;wc++) {
- *(dz->sbufptr[0]++) = dz->transpos[wc];
- if(dz->sbufptr[0] >= dz->sampbuf[1]) {
- if((exit_status = write_exact_samps(dz->bigbuf,dz->buflen,dz))<0)
- return(exit_status);
- dz->sbufptr[0] = dz->bigbuf;
- }
- }
- } else {
- for(wc=0;wc<dz->wlength;wc++) {
- if((val = dz->pitches[wc] * dz->param[PSEE_SCF]) > F_MAXSAMP) {
- if(!dz->zeroset) {
- fprintf(stdout,"WARNING: output value(s) too big: truncated.\n");
- dz->zeroset = TRUE;
- }
- val = F_MAXSAMP;
- }
- if(val < F_MINSAMP) {
- if(!dz->zeroset) {
- fprintf(stdout,"WARNING: output value(s) too small: truncated.\n");
- dz->zeroset = TRUE;
- }
- val = F_MINSAMP;
- }
- *(dz->sbufptr[0]++) = (float)val;
- if(dz->sbufptr[0] >= dz->sampbuf[1]) {
- if((exit_status = write_exact_samps(dz->bigbuf,dz->buflen,dz))<0)
- return(exit_status);
- dz->sbufptr[0] = dz->bigbuf;
- }
- }
- }
- if(dz->sbufptr[0] != dz->bigbuf) {
- if((exit_status = write_samps(dz->bigbuf,dz->sbufptr[0] - dz->bigbuf,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /*************************** PRESCALE_TRANSPOSITION_DATA ********************/
- int prescale_transposition_data(dataptr dz)
- {
- int n;
- double scalefact;
- double mintransp = DBL_MAX;
- double maxtransp = -DBL_MAX;
- for(n=0;n<dz->wlength;n++) {
- if(dz->transpos[n] <= 0.0) {
- sprintf(errstr,"Anomaly in transposition data: prescale_transposition_data()\n");
- return(PROGRAM_ERROR);
- }
- dz->transpos[n] = (float)log10(dz->transpos[n]);
- if(dz->transpos[n] < mintransp)
- mintransp = dz->transpos[n];
- if(dz->transpos[n] > maxtransp)
- maxtransp = dz->transpos[n];
- }
- maxtransp = max(fabs(maxtransp),fabs(mintransp));
- scalefact = F_MAXSAMP/2.0/maxtransp;
- for(n=0;n<dz->wlength;n++)
- dz->transpos[n] = (float)(dz->transpos[n] * scalefact);
- return(FINISHED);
- }
- /************************* SPECPHEAR *************************/
- int specphear(dataptr dz)
- {
- #define WINDOW_AMP (0.50) /* AVOID OVERLOAD */
- int exit_status;
- double pre_totalamp, noischan_amp;
- double thisfrq;
- int n = 0;
- int vc;
- pre_totalamp = WINDOW_AMP * dz->param[PH_GAIN];
- noischan_amp = pre_totalamp/(double)dz->clength;
- memset((char *)dz->bigfbuf,0,(size_t)(dz->big_fsize * sizeof(float)));
- dz->flbufptr[0] = dz->bigfbuf;
- dz->infile->channels = dz->infile->origchans; /* setup channel count for outfile */
- dz->wanted = dz->infile->channels;
- while(n < dz->wlength) {
- thisfrq = (double)dz->pitches[n];
- if(thisfrq < 0.0) { /* NO PITCH FOUND : GENERATE NOISE */
- if((exit_status = generate_noise_in_buffer(noischan_amp,dz))<0)
- return(exit_status);
- } else { /* GENERATE TESTTONE AT FOUND PITCH */
- if((exit_status = preset_chanfrqs_to_chancentres(dz))<0)
- return(exit_status);
- if((exit_status = generate_tone_in_buffer(pre_totalamp,thisfrq,dz))<0)
- return(exit_status);
- }
- if(n==0) {
- for(vc = 0; vc < dz->wanted ; vc += 2)
- dz->flbufptr[0][AMPP] = 0.0f;
- }
- if((dz->flbufptr[0] += dz->wanted) >= dz->flbufptr[1]) {
- if((exit_status = write_exact_samps(dz->bigfbuf,dz->big_fsize,dz))<0)
- return(exit_status);
- memset((char *)dz->bigfbuf,0,(size_t)(dz->big_fsize * sizeof(float)));
- dz->flbufptr[0] = dz->bigfbuf;
- }
- n++;
- }
- if(dz->flbufptr[0] != dz->bigfbuf) {
- if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /*************************** GENERATE_NOISE_IN_BUFFER *********************/
- int generate_noise_in_buffer(double noischan_amp,dataptr dz)
- {
- int cc, vc;
- dz->flbufptr[0][0] = (float)noischan_amp;
- dz->flbufptr[0][1] = (float)(drand48() * dz->halfchwidth);
- for(cc = 1, vc = 2; cc < dz->clength-1; cc++, vc += 2) {
- dz->flbufptr[0][FREQ] = (float)((drand48() * dz->chwidth) + dz->windowbuf[CHBOT][cc]);
- dz->flbufptr[0][AMPP] = (float)noischan_amp;
- }
- dz->flbufptr[0][FREQ] = (float)((drand48() * dz->halfchwidth) + dz->windowbuf[CHBOT][cc]);
- dz->flbufptr[0][AMPP] = (float)noischan_amp;
- return(FINISHED);
- }
- /********************** GENERATE_TONE_IN_BUFFER ***************************/
- int generate_tone_in_buffer(double pre_totalamp,double thisfrq,dataptr dz)
- {
- int exit_status;
- int cc, vc, m, ampadjusted = 0;
- int lastvc = -1;
- double post_totalamp;
- for(m=0;m<PARTIALS_IN_TEST_TONE;m++) {
- cc = (int)((thisfrq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- vc = cc * 2;
- if(vc != lastvc) { /* AVOID OVERWRITING ALREADY GENERATED LOWER PARTIALS */
- dz->flbufptr[0][AMPP] = dz->windowbuf[TESTPAMP][m];
- dz->flbufptr[0][FREQ] = (float)thisfrq;
- }
- lastvc = vc;
- if((thisfrq = thisfrq * 2.0) > dz->nyquist) {
- post_totalamp = (double)dz->windowbuf[TOTPAMP][m];
- /* THIS NORMALISATION DOESN'T QUITE WORK */
- if((exit_status = normalise(pre_totalamp,post_totalamp,dz))<0)
- return(exit_status);
- ampadjusted = 1; /* IF PITCH IS LESS THAN CHAN SPACING */
- break; /* BUT THAT'S MINOR AESTHETIC QUIBBLE ONLY */
- }
- }
- if(!ampadjusted) {
- post_totalamp = (double)dz->windowbuf[TOTPAMP][PARTIALS_IN_TEST_TONE-1];
- if((exit_status = normalise(pre_totalamp,post_totalamp,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /**************************** PRESET_CHANFRQS_TO_CHANCENTRES **********************
- *
- * Preset all frqs to centre of channels.
- */
- int preset_chanfrqs_to_chancentres(dataptr dz)
- {
- int cc, vc;
- dz->flbufptr[0][1] = (float)(dz->halfchwidth/2.0);
- for(cc = 1, vc = 2; cc < dz->clength-1; cc++, vc += 2)
- dz->flbufptr[0][FREQ] = (float)(dz->windowbuf[CHBOT][cc] + dz->halfchwidth);
- dz->flbufptr[0][FREQ]=(float)(dz->windowbuf[CHBOT][dz->clength-1]+(dz->halfchwidth/2.0));
- return(FINISHED);
- }
- /****************************** SPECPWRITE *********************************/
- int specpwrite(dataptr dz)
- {
- int exit_status;
- int brkcnt;
- if((dz->parray[PW_BRK] = (double *)malloc(dz->wlength * 2 * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for pitch brkpnt array.\n");
- return(MEMORY_ERROR);
- }
- if(dz->is_transpos) {
- if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(&brkcnt,dz->transpos,dz->frametime,PW_BRK,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(&brkcnt,dz->pitches,dz->frametime,PW_BRK,dz))<0)
- return(exit_status);
- }
- return write_brkfile(dz->fp,brkcnt,PW_BRK,dz);
- }
-
- /****************************** CONSTRUCT_SCREEN_MESSAGE *********************************/
- int construct_screen_message(dataptr dz)
- {
- int exit_status;
- int oct = 0;
- double z1, z2, z3, z4, z5;
- if((exit_status = hztomidi(&z1,dz->param[PINF_MAX]))<0)
- return(exit_status);
- if((exit_status = hztomidi(&z2,dz->param[PINF_MIN]))<0)
- return(exit_status);
- if((exit_status = hztomidi(&z3,dz->param[PINF_MEAN]))<0)
- return(exit_status);
- if((exit_status = hztomidi(&z4,dz->param[PINF_MAX]))<0)
- return(exit_status);
- if((exit_status = hztomidi(&z5,dz->param[PINF_MIN]))<0)
- return(exit_status);
- z4 -= z5;
- if(z4 > 12.0) {
- oct = (int)(z4/12.0); /* TRUNCATE */
- z4 -= (double)(oct * 12);
- }
- if(oct > 0) {
- sprintf(errstr,"MAX PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"
- "MIN PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"
- "MEAN PITCH: %.2lfHZ\tMIDI : %.2lf\n\n"
- "TOTAL RANGE: %d OCTAVES and %.2lf SEMITONES\n",
- dz->param[PINF_MAX],z1,dz->param[PINF_MAXPOS],dz->param[PINF_MIN],z2,dz->param[PINF_MINPOS],
- dz->param[PINF_MEAN],z3, oct, z4);
- } else {
- sprintf(errstr,"MAX PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"
- "MIN PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"
- "MEAN PITCH: %.2lfHZ\tMIDI : %.2lf\n\n"
- "TOTAL RANGE: %.2lf SEMITONES\n",
- dz->param[PINF_MAX],z1,dz->param[PINF_MAXPOS],dz->param[PINF_MIN],z2,dz->param[PINF_MINPOS],
- dz->param[PINF_MEAN],z3,z4);
- }
- return(FINISHED);
- }
|