|
@@ -0,0 +1,1504 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * 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 <structures.h>
|
|
|
|
|
+#include <tkglobals.h>
|
|
|
|
|
+#include <pnames.h>
|
|
|
|
|
+#include <globcon.h>
|
|
|
|
|
+#include <modeno.h>
|
|
|
|
|
+#include <arrays.h>
|
|
|
|
|
+#include <flags.h>
|
|
|
|
|
+#include <strange.h>
|
|
|
|
|
+#include <cdpmain.h>
|
|
|
|
|
+#include <formants.h>
|
|
|
|
|
+#include <speccon.h>
|
|
|
|
|
+#include <sfsys.h>
|
|
|
|
|
+#include <osbind.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+#include <strange.h>
|
|
|
|
|
+
|
|
|
|
|
+#ifdef unix
|
|
|
|
|
+#define round(x) lround((x))
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#define RATIO_LIMIT (20.0) /* Max ratio actual chanamp allowed to exceed
|
|
|
|
|
+ formant derived amp for frq */
|
|
|
|
|
+#define SMOOTHER (0.5)
|
|
|
|
|
+#define VERY_SMALL (0.0000000000000001)
|
|
|
|
|
+
|
|
|
|
|
+static int zero_sampbuf(dataptr dz);
|
|
|
|
|
+static int establish_frq_params(double *scalefact,dataptr dz);
|
|
|
|
|
+static int write_partials_moving_down(double scalefact,dataptr dz);
|
|
|
|
|
+static int write_partials_moving_up(double scalefact,dataptr dz);
|
|
|
|
|
+static int cut_or_rolloff_high_frq(dataptr dz);
|
|
|
|
|
+static int selfglis_down_within_spectral_envelope(int vc,double transpos,dataptr dz);
|
|
|
|
|
+static int glis_down_within_spectral_envelope(double fundamental,double *thisfrq,double scalefact,int *n,dataptr dz);
|
|
|
|
|
+static int selfglis_up_within_spectral_envelope(int vc,double transpos,dataptr dz);
|
|
|
|
|
+static int glis_up_within_spectral_envelope(double fundamental,double *thisfrq,double scalefact,int *n,dataptr dz);
|
|
|
|
|
+static int do_waver(int *wc,int *w_to_buf,int *samps_read,int wcnt,int upwcnt,int dnwcnt,dataptr dz);
|
|
|
|
|
+static int spectrally_stretch_window(double thisstr,dataptr dz);
|
|
|
|
|
+static int advance_along_windows(int *wc,int *w_to_buf,int *samps_read,dataptr dz);
|
|
|
|
|
+static int warp_pitch(int *avcnt,dataptr dz);
|
|
|
|
|
+static int warp_time(int avcnt,dataptr dz);
|
|
|
|
|
+static int get_pitch_averages(int *avcnt,dataptr dz);
|
|
|
|
|
+static int setup_and_do_pitchwarp(int start,int avg_no,int *lastpos,double *lastmidi,dataptr dz);
|
|
|
|
|
+static int do_pitch_wiggle(double *thismidi,double ttime, dataptr dz);
|
|
|
|
|
+static int warp_pitches(int thispos,int diff,int *lastpos,double thismidi,double *lastmidi,dataptr dz);
|
|
|
|
|
+static int setup_and_do_timewarp(float **thisbuf,float **nextbuf,int n,int *lastoutpos,
|
|
|
|
|
+ int *lastinpos,int *last_total_wndws,dataptr dz);
|
|
|
|
|
+static int adjust_input_buffers(float **thisbuf,float **nextbuf,int thisindex,
|
|
|
|
|
+ int *last_total_wndws,int do_next,dataptr dz);
|
|
|
|
|
+static int transpos_initial_windows(float **thisbuf,float **nextbuf,int cnt,int *last_total_wndws,dataptr dz);
|
|
|
|
|
+static int do_time_wiggle(double *ttime,dataptr dz);
|
|
|
|
|
+static int do_timewarp(float **thisbuf,float **nextbuf,int thisinpos,int outdiff,
|
|
|
|
|
+ int *lastinpos,int *last_total_wndws,dataptr dz);
|
|
|
|
|
+static int find_currentbuf_index(int *currentbuf_index,int *last_total_wndws,float **thisbuf,dataptr dz);
|
|
|
|
|
+static int find_currentbuf_nextindex(int *currentbuf_nextindex,int last_total_wndws,dataptr dz);
|
|
|
|
|
+static int setup_thisbuf_and_nextbuf(int last_total_wndws,float **thisbuf,float **nextbuf,dataptr dz);
|
|
|
|
|
+static int interp_between_vals_in_two_bufs(float *thisbuf,float *nextbuf,double interpval,dataptr dz);
|
|
|
|
|
+static int interp_between_pitch_vals(double *thismidi,float *pitch,int thisindex,double interpval,dataptr dz);
|
|
|
|
|
+static int interp_between_pitch_vals2(double *thismidi,double *pitch,int thisindex,double interpval,dataptr dz);
|
|
|
|
|
+static int transpose_outbuf(double transp,dataptr dz);
|
|
|
|
|
+static int put_transposed_data_in_appropriate_chans(double transp,dataptr dz);
|
|
|
|
|
+static int put_thisdata_in_appropriate_chan(int cc,int vc, dataptr dz);
|
|
|
|
|
+static int do_specshift(int windows_in_buf,dataptr dz);
|
|
|
|
|
+static int do_the_specshift(dataptr dz);
|
|
|
|
|
+static int logread_shift(double timenow,int btktable_no,dataptr dz);
|
|
|
|
|
+static int read_value_from_brktable_using_log_interpolation(double thistime,int paramno,dataptr dz);
|
|
|
|
|
+static int reassign_frqs_to_appropriate_chans(dataptr dz);
|
|
|
|
|
+static int do_chan_shifting(int cc,int vc,dataptr dz);
|
|
|
|
|
+static int assign_new_frqs_to_appropriate_channels(dataptr dz);
|
|
|
|
|
+
|
|
|
|
|
+/**************************** SPECSHIFT ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int specshift(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int samps_read, windows_in_buf;
|
|
|
|
|
+ dz->time = 0.0f;
|
|
|
|
|
+ if(dz->bptrcnt <= 0) {
|
|
|
|
|
+ sprintf(errstr,"flbufptr[0] not established by outer_shift_loop()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ while((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) > 0) {
|
|
|
|
|
+ dz->flbufptr[0] = dz->bigfbuf;
|
|
|
|
|
+ windows_in_buf = samps_read/dz->wanted;
|
|
|
|
|
+ if((exit_status = do_specshift(windows_in_buf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = write_exact_samps(dz->bigfbuf,samps_read,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** DO_SPECSHIFT ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_specshift(int windows_in_buf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int wc;
|
|
|
|
|
+ for(wc=0; wc<windows_in_buf; wc++) {
|
|
|
|
|
+ if(dz->vflag[SHIFT_LOG]) {
|
|
|
|
|
+ if(dz->brksize[SHIFT_SHIF]) {
|
|
|
|
|
+ if((exit_status = logread_shift(dz->time,SHIFT_SHIF,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[SHIFT_FRQ1]) {
|
|
|
|
|
+ if((exit_status =
|
|
|
|
|
+ read_value_from_brktable_using_log_interpolation((double)dz->time,SHIFT_FRQ1,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[SHIFT_FRQ2]) {
|
|
|
|
|
+ if((exit_status =
|
|
|
|
|
+ read_value_from_brktable_using_log_interpolation((double)dz->time,SHIFT_FRQ2,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = do_the_specshift(dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->flbufptr[0] += dz->wanted;
|
|
|
|
|
+ dz->time = (float)(dz->time + dz->frametime);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** DO_THE_SPECSHIFT ***************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * linear frequency shift of spectrum.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int do_the_specshift(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(SHIFT_ALL):
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2)
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ] + dz->param[SHIFT_SHIF]);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(SHIFT_ABOVE):
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] > dz->param[SHIFT_FRQ1])
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ] + dz->param[SHIFT_SHIF]);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(SHIFT_BELOW):
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] < dz->param[SHIFT_FRQ1])
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ] + dz->param[SHIFT_SHIF]);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(SHIFT_BETWEEN):
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] > dz->param[SHIFT_FRQ1] && dz->flbufptr[0][FREQ] < dz->param[SHIFT_FRQ2])
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ] + dz->param[SHIFT_SHIF]);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(SHIFT_OUTSIDE):
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] < dz->param[SHIFT_FRQ1] || dz->flbufptr[0][FREQ] > dz->param[SHIFT_FRQ2])
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ] + dz->param[SHIFT_SHIF]);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unkonwn mode in do_specshift()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return reassign_frqs_to_appropriate_chans(dz);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+/*************************** REASSIGN_FRQS_TO_APPROPRIATE_CHANS ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int reassign_frqs_to_appropriate_chans(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ dz->iparray[SHIFT_OVER][cc] = 0;
|
|
|
|
|
+ dz->iparray[SHIFT_DONE][cc] = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->param[SHIFT_SHIF] > 0.0) {
|
|
|
|
|
+ for(cc=0,vc=0;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] > (float)dz->parray[SHIFT_CHTOP][cc])
|
|
|
|
|
+ dz->iparray[SHIFT_OVER][cc] = 1;
|
|
|
|
|
+ } /* Work down from top, shifting up */
|
|
|
|
|
+ for(cc=dz->clength-1,vc=(dz->clength-1)*2;cc>=0; cc--, vc-=2) {
|
|
|
|
|
+ if(dz->iparray[SHIFT_OVER][cc]) {
|
|
|
|
|
+ if((exit_status = do_chan_shifting(cc,vc,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } /* Work up from bottom shifting down */
|
|
|
|
|
+ if(dz->param[SHIFT_SHIF] < 0.0) {
|
|
|
|
|
+ for(cc=1,vc=2;cc< dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] <= (float)dz->parray[SHIFT_CHTOP][cc-1]) {
|
|
|
|
|
+ if((exit_status = do_chan_shifting(cc,vc,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*************************** DO_CHAN_SHIFTING ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_chan_shifting(int cc,int vc,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int k = (int)((dz->flbufptr[0][FREQ] + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
|
|
|
|
|
+ int newvc = k * 2;
|
|
|
|
|
+ if(k >=0 && k < dz->clength) {
|
|
|
|
|
+ if(!dz->iparray[SHIFT_DONE][k]
|
|
|
|
|
+ || (dz->iparray[SHIFT_DONE][k] && (dz->flbufptr[0][AMPP] > dz->flbufptr[0][newvc]))) {
|
|
|
|
|
+ dz->flbufptr[0][newvc++] = dz->flbufptr[0][AMPP];
|
|
|
|
|
+ dz->flbufptr[0][newvc] = dz->flbufptr[0][FREQ];
|
|
|
|
|
+ dz->iparray[SHIFT_DONE][k] = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)dz->parray[SHIFT_CHMID][cc];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*********************** SPECGLIS ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int specglis(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double pre_totalamp, post_totalamp;
|
|
|
|
|
+ double scalefact;
|
|
|
|
|
+ if(dz->brksize[GLIS_RATE])
|
|
|
|
|
+ dz->param[GLIS_RATE] *= dz->param[GLIS_CONVERTOR];
|
|
|
|
|
+ rectify_window(dz->flbufptr[0],dz);
|
|
|
|
|
+ if((exit_status = extract_specenv(0,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->mode != SELFGLIS) {
|
|
|
|
|
+ if((exit_status = zero_sampbuf(dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = establish_frq_params(&scalefact,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->param[GLIS_RATE] <= 0.0) {
|
|
|
|
|
+ if((exit_status = write_partials_moving_down(scalefact,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = write_partials_moving_up(scalefact,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->vflag[GLIS_FTOP]) {
|
|
|
|
|
+ if((exit_status = cut_or_rolloff_high_frq(dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return normalise(pre_totalamp,post_totalamp,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/*********************** ZERO_SAMPBUF **********************/
|
|
|
|
|
+
|
|
|
|
|
+int zero_sampbuf(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int vc;
|
|
|
|
|
+ for(vc = 0; vc < dz->wanted; vc += 2)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*********************** ESTABLISH_FRQ_PARAMS **********************/
|
|
|
|
|
+
|
|
|
|
|
+int establish_frq_params(double *scalefact,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double thispitch;
|
|
|
|
|
+ dz->param[GLIS_BASEFRQ] *= pow(2.0,dz->param[GLIS_RATE]);
|
|
|
|
|
+ if(dz->param[GLIS_RATE] >= 0.0) { /* GOING UP */
|
|
|
|
|
+ while(dz->param[GLIS_BASEFRQ] > GLIS_REFERENCE_FRQ * 2.0)
|
|
|
|
|
+ dz->param[GLIS_BASEFRQ] /= 2.0;
|
|
|
|
|
+ thispitch = log(dz->param[GLIS_BASEFRQ]);
|
|
|
|
|
+ *scalefact = thispitch - dz->param[GLIS_REFPITCH];
|
|
|
|
|
+ } else { /* GOING DOWN */
|
|
|
|
|
+ while(dz->param[GLIS_BASEFRQ] < GLIS_REFERENCE_FRQ/2.0)
|
|
|
|
|
+ dz->param[GLIS_BASEFRQ] *= 2.0;
|
|
|
|
|
+ thispitch = log(dz->param[GLIS_BASEFRQ]);
|
|
|
|
|
+ *scalefact = thispitch - dz->param[GLIS_HALF_REFPITCH];
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/********************* WRITE_PARTIALS_MOVING_DOWN *********************
|
|
|
|
|
+ *
|
|
|
|
|
+ * (0) Assume we start at fundamental.
|
|
|
|
|
+ * (1) Calculate partials from where we are.
|
|
|
|
|
+ * (2) Fade out odd partials.
|
|
|
|
|
+ * (3) Move up by equal frq steps, or by multiples of current fundamental.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int write_partials_moving_down(double scalefact,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, cc, vc; /* 0 */
|
|
|
|
|
+ double fundamental, thisfrq, transpos;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(SELFGLIS):
|
|
|
|
|
+ rectify_window(dz->flbufptr[0],dz);
|
|
|
|
|
+ transpos = dz->param[GLIS_BASEFRQ]/GLIS_REFERENCE_FRQ;
|
|
|
|
|
+ for(cc=0,vc=0;cc < dz->clength;cc++,vc+=2) {
|
|
|
|
|
+ dz->amp[cc] = 0.0f;
|
|
|
|
|
+ dz->freq[cc] = dz->flbufptr[0][FREQ];
|
|
|
|
|
+ }
|
|
|
|
|
+ for(vc=0;vc < dz->wanted; vc+=2) {
|
|
|
|
|
+ if((exit_status = selfglis_down_within_spectral_envelope(vc,transpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = put_amp_and_frq(dz->flbufptr[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(INHARMONIC):
|
|
|
|
|
+ case(SHEPARD):
|
|
|
|
|
+ fundamental = dz->param[GLIS_BASEFRQ]; /* 1 */
|
|
|
|
|
+ thisfrq = dz->param[GLIS_BASEFRQ];
|
|
|
|
|
+ n = 1;
|
|
|
|
|
+ while(thisfrq < dz->nyquist) {
|
|
|
|
|
+ if((exit_status = glis_down_within_spectral_envelope(fundamental,&thisfrq,scalefact,&n,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown mode in write_partials_moving_down()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************ WRITE_PARTIALS_MOVING_UP ***********************
|
|
|
|
|
+ *
|
|
|
|
|
+ * (0) Assume we start at 2nd harmonic.
|
|
|
|
|
+ * (1) Calculate partials from a fundamental an 8va below ref pitch.
|
|
|
|
|
+ * (2) Fade in lowest component, and odd partials.
|
|
|
|
|
+ * (3) Move up by equal frq steps, or by multiples of current fundamental.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int write_partials_moving_up(double scalefact,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n = 2, cc, vc; /* 0 */
|
|
|
|
|
+ double fundamental = dz->param[GLIS_BASEFRQ]/2.0; /* 1 */
|
|
|
|
|
+ double thisfrq = dz->param[GLIS_BASEFRQ];
|
|
|
|
|
+ double transpos;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(SELFGLIS) :
|
|
|
|
|
+ transpos = dz->param[GLIS_BASEFRQ]/ GLIS_REFERENCE_FRQ;
|
|
|
|
|
+ for(cc=0,vc=0;cc < dz->clength;cc++,vc+=2) {
|
|
|
|
|
+ dz->amp[cc] = 0.0f;
|
|
|
|
|
+ dz->freq[cc] = dz->flbufptr[0][FREQ];
|
|
|
|
|
+ }
|
|
|
|
|
+ for(vc=0;vc < dz->wanted;vc+=2) {
|
|
|
|
|
+ if((exit_status = selfglis_up_within_spectral_envelope(vc,transpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = put_amp_and_frq(dz->flbufptr[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(SHEPARD):
|
|
|
|
|
+ case(INHARMONIC):
|
|
|
|
|
+ while(thisfrq < dz->nyquist) {
|
|
|
|
|
+ if((exit_status = glis_up_within_spectral_envelope(fundamental,&thisfrq,scalefact,&n,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown mode in write_partials_moving_up()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** CUT_OR_ROLLOFF_HIGH_FRQ *****************************/
|
|
|
|
|
+
|
|
|
|
|
+int cut_or_rolloff_high_frq(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int vc;
|
|
|
|
|
+ for(vc = 0; vc < dz->wanted;vc += 2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] > dz->param[GLIS_HIFRQ]) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] >= dz->param[GLIS_FRQTOP_TOP])
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ else
|
|
|
|
|
+ dz->flbufptr[0][AMPP] =
|
|
|
|
|
+ (float)(dz->flbufptr[0][AMPP] * (dz->param[GLIS_FRQTOP_TOP] - dz->flbufptr[0][FREQ])/dz->param[GLIS_ROLL_OFF]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************* SELFGLIS_DOWN_WITHIN_SPECTRAL_ENVELOPE ********************/
|
|
|
|
|
+
|
|
|
|
|
+int selfglis_down_within_spectral_envelope(int vc,double transpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double ampratio, amphere, thisfrq, thisamp, frqhi, amphi;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ if((exit_status = getspecenvamp(&here,dz->flbufptr[0][FREQ],0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(amphere <= VERY_SMALL)
|
|
|
|
|
+ ampratio = 0.0;
|
|
|
|
|
+ else {
|
|
|
|
|
+ if((ampratio = fabs(dz->flbufptr[0][AMPP]/amphere)) > RATIO_LIMIT)
|
|
|
|
|
+ ampratio = RATIO_LIMIT;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((thisfrq = fabs(dz->flbufptr[0][FREQ]) * transpos) < dz->nyquist) {
|
|
|
|
|
+ if((exit_status = getspecenvamp(&thisamp,thisfrq,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ thisamp *= ampratio;
|
|
|
|
|
+ thisamp *= pow(max(0.0,(transpos * 2.0) - 1.0),SMOOTHER);
|
|
|
|
|
+ if((exit_status = get_channel_corresponding_to_frq(&n,thisfrq,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(n >=0 && n < dz->clength && thisamp > dz->amp[n]) {
|
|
|
|
|
+ dz->amp[n++] = (float)thisamp;
|
|
|
|
|
+ dz->freq[n] = (float)thisfrq;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((frqhi = thisfrq * 2.0) < dz->nyquist) {
|
|
|
|
|
+ if((exit_status = getspecenvamp(&hi,frqhi,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ amphi *= ampratio;
|
|
|
|
|
+ amphi *= pow(max(0.0,2.0 - (transpos * 2.0)),SMOOTHER);
|
|
|
|
|
+ if((exit_status = get_channel_corresponding_to_frq(&n,thisfrq,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(n >=0 && n < dz->clength && amphi > dz->amp[n]) {
|
|
|
|
|
+ dz->amp[n++] = (float)amphi;
|
|
|
|
|
+ dz->freq[n] = (float)frqhi;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************* GLIS_DOWN_WITHIN_SPECTRAL_ENVELOPE ********************/
|
|
|
|
|
+
|
|
|
|
|
+int glis_down_within_spectral_envelope(double fundamental,double *thisfrq,double scalefact,int *n,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ double thisamp;
|
|
|
|
|
+ if((exit_status = get_channel_corresponding_to_frq(&cc,*thisfrq,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ vc = cc * 2;
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(*thisfrq);
|
|
|
|
|
+ if((exit_status = getspecenvamp(&thisamp,*thisfrq,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = (float)thisamp;
|
|
|
|
|
+ if(ODD(*n))
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * scalefact); /* 2 */
|
|
|
|
|
+ (*n)++;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(INHARMONIC): *thisfrq += dz->param[GLIS_SHIFT]; break;
|
|
|
|
|
+ case(SHEPARD): *thisfrq = fundamental * (double)(*n); break;
|
|
|
|
|
+ } /* 3 */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************* SELFGLIS_UP_WITHIN_SPECTRAL_ENVELOPE ********************/
|
|
|
|
|
+
|
|
|
|
|
+int selfglis_up_within_spectral_envelope(int vc,double transpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double amphere, ampratio;
|
|
|
|
|
+ double thisfrq, thisamp, frqlo, amplo;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ if((exit_status = getspecenvamp(&here,dz->flbufptr[0][FREQ],0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(amphere <= VERY_SMALL)
|
|
|
|
|
+ ampratio = 0.0;
|
|
|
|
|
+ else {
|
|
|
|
|
+ if((ampratio = fabs(dz->flbufptr[0][AMPP]/amphere)) > RATIO_LIMIT)
|
|
|
|
|
+ ampratio = RATIO_LIMIT;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((thisfrq = fabs(dz->flbufptr[0][FREQ]) * transpos) < dz->nyquist) {
|
|
|
|
|
+ if((exit_status = getspecenvamp(&thisamp,thisfrq,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ thisamp *= ampratio;
|
|
|
|
|
+ thisamp *= pow(2.0 - transpos,SMOOTHER);
|
|
|
|
|
+ if((exit_status = get_channel_corresponding_to_frq(&n,thisfrq,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(n >=0 && n < dz->clength && thisamp > dz->amp[n]) {
|
|
|
|
|
+ dz->amp[n] = (float)thisamp;
|
|
|
|
|
+ dz->freq[n] = (float)thisfrq;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((frqlo = thisfrq/2.0) < dz->nyquist) {
|
|
|
|
|
+ if((exit_status = getspecenvamp(&lo,frqlo,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ amplo *= ampratio;
|
|
|
|
|
+ amplo *= pow(transpos - 1.0,SMOOTHER);
|
|
|
|
|
+ exit_status = get_channel_corresponding_to_frq(&n,thisfrq,dz);
|
|
|
|
|
+ if(n < dz->clength && amplo > dz->amp[n]) {
|
|
|
|
|
+ dz->amp[n] = (float)amplo;
|
|
|
|
|
+ dz->freq[n] = (float)frqlo;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************* GLIS_UP_WITHIN_SPECTRAL_ENVELOPE ********************/
|
|
|
|
|
+
|
|
|
|
|
+int glis_up_within_spectral_envelope(double fundamental,double *thisfrq,double scalefact,int *n,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ double thisamp;
|
|
|
|
|
+ if((exit_status = get_channel_corresponding_to_frq(&cc,*thisfrq,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ vc = cc * 2;
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(*thisfrq);
|
|
|
|
|
+ if((exit_status = getspecenvamp(&thisamp,*thisfrq,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = (float)thisamp;
|
|
|
|
|
+ if(ODD(*n) || *n==2)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * scalefact); /* 2 */
|
|
|
|
|
+ (*n)++;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(INHARMONIC):*thisfrq += dz->param[GLIS_HALF_SHIFT]; break;
|
|
|
|
|
+ case(SHEPARD): *thisfrq = fundamental * (double)(*n); break;
|
|
|
|
|
+ } /* 3 */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*************************** SPECINVERT *********************/
|
|
|
|
|
+
|
|
|
|
|
+int specinvert(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double zort, pre_totalamp;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(INV_NORMAL):
|
|
|
|
|
+ for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = dz->amp[cc] - dz->flbufptr[0][AMPP];
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(INV_KEEPAMP):
|
|
|
|
|
+ if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(pre_totalamp > MINAMP) {
|
|
|
|
|
+ for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) {
|
|
|
|
|
+ zort = dz->parray[INV_AMPRATIO][cc] - (dz->flbufptr[0][vc]/pre_totalamp);
|
|
|
|
|
+ dz->flbufptr[0][vc] = (float)(zort * pre_totalamp);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************************* SPECWAVER ********************************/
|
|
|
|
|
+
|
|
|
|
|
+int specwaver(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status = FINISHED;
|
|
|
|
|
+ double duration = dz->wlength * dz->frametime;
|
|
|
|
|
+ int wcnt, upwcnt, dnwcnt, wc, samps_read, w_to_buf;
|
|
|
|
|
+ if(duration <= 0.0) {
|
|
|
|
|
+ sprintf(errstr,"Zero length analysis file: cannot proceed.\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) > 0) {
|
|
|
|
|
+ dz->flbufptr[0] = dz->bigfbuf;
|
|
|
|
|
+ w_to_buf = samps_read/dz->wanted;
|
|
|
|
|
+ wc = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ if(samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ sprintf(errstr,"No windows found. specwaver()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ while(dz->time < duration) {
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ wcnt = round(1.0/(dz->param[WAVER_VIB] * dz->frametime));
|
|
|
|
|
+ dnwcnt = upwcnt = wcnt/2;
|
|
|
|
|
+ if(ODD(wcnt))
|
|
|
|
|
+ upwcnt++;
|
|
|
|
|
+ if((exit_status = do_waver(&wc,&w_to_buf,&samps_read,wcnt,upwcnt,dnwcnt,dz))!=CONTINUE)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************************** DO_WAVER *******************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_waver(int *wc,int *w_to_buf,int *samps_read,int wcnt,int upwcnt,int dnwcnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ double strstep = dz->param[WAVER_STR]/(double)upwcnt;
|
|
|
|
|
+ double thisstr = dz->param[WAVER_STR];
|
|
|
|
|
+ for(n=0;n<upwcnt;n++) {
|
|
|
|
|
+ if((exit_status = spectrally_stretch_window(thisstr,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = advance_along_windows(wc,w_to_buf,samps_read,dz))!=CONTINUE)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ thisstr += strstep;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(ODD(wcnt))
|
|
|
|
|
+ thisstr -= strstep;
|
|
|
|
|
+ for(n=0;n<dnwcnt;n++) {
|
|
|
|
|
+ if((exit_status = spectrally_stretch_window(thisstr,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = advance_along_windows(wc,w_to_buf,samps_read,dz))!=CONTINUE)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ thisstr -= strstep;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*********************** SPECTRALLY_STRETCH_WINDOW *****************************/
|
|
|
|
|
+
|
|
|
|
|
+int spectrally_stretch_window(double thisstr,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int dd;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ double herestr, thislocation, strdiff = thisstr - 1.0;
|
|
|
|
|
+ for(dd=0,cc=dz->iparam[WAVER_BOTCHAN],vc=dz->iparam[WAVER_BOTCHAN]*2; cc < dz->clength; dd++,cc++,vc+=2) {
|
|
|
|
|
+ thislocation = (double)dd/(double)dz->iparam[WAVER_STRCHANS];
|
|
|
|
|
+ if(dz->mode==WAVER_SPECIFIED)
|
|
|
|
|
+ thislocation = pow(thislocation,dz->param[WAVER_EXP]);
|
|
|
|
|
+ herestr = (thislocation * strdiff) + 1.0;
|
|
|
|
|
+ dz->amp[cc] = dz->flbufptr[0][AMPP];
|
|
|
|
|
+ dz->freq[cc] = (float)fabs(dz->flbufptr[0][FREQ] * herestr);
|
|
|
|
|
+ }
|
|
|
|
|
+ return assign_new_frqs_to_appropriate_channels(dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************************** ADVANCE_ALONG_WINDOWS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int advance_along_windows(int *wc,int *w_to_buf,int *samps_read,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ dz->flbufptr[0] += dz->wanted;
|
|
|
|
|
+ if(++(*wc) >= *w_to_buf) {
|
|
|
|
|
+ if(*samps_read > 0) {
|
|
|
|
|
+ if((exit_status = write_exact_samps(dz->bigfbuf,*samps_read,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((*samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) > 0) {
|
|
|
|
|
+ dz->flbufptr[0] = dz->bigfbuf;
|
|
|
|
|
+ *w_to_buf = *samps_read/dz->wanted;
|
|
|
|
|
+ *wc = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+//TW CORRECTED indirection error : Dec 2002
|
|
|
|
|
+ if(*samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->time = (float)(dz->time + dz->frametime);
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** SPECWARP ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int specwarp(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int avcnt;
|
|
|
|
|
+ if(sloom) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Warping pitch.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = warp_pitch(&avcnt,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(sloom) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Warping time.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ return warp_time(avcnt,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** WARP_PITCH ************************/
|
|
|
|
|
+
|
|
|
|
|
+int warp_pitch(int *avcnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n = 0, lastpos = 0, thispos, diff, q, start;
|
|
|
|
|
+ double lastmidi;
|
|
|
|
|
+ double ttime, thismidi;
|
|
|
|
|
+ initrand48();
|
|
|
|
|
+ if((exit_status = get_pitch_averages(avcnt,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = get_statechanges(*avcnt,WARP_SRNG,WARP_AVP,WARP_CHANGE,WARP_MININT,-WARP_MININT,IS_PITCH,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ while(dz->parray[WARP_AVP][n] < MIDIMIN) {
|
|
|
|
|
+ if(++n >= *avcnt) {
|
|
|
|
|
+ sprintf(errstr,"No valid pitch-average data found: warp_pitch()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->iparray[WARP_CHANGE][n] = 1;
|
|
|
|
|
+ start = n;
|
|
|
|
|
+ for(;n < *avcnt;n++) {
|
|
|
|
|
+ if(dz->iparray[WARP_CHANGE][n]) {
|
|
|
|
|
+ if((exit_status = setup_and_do_pitchwarp(start,n,&lastpos,&lastmidi,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ thispos = (dz->wlength - 1);
|
|
|
|
|
+ if((diff = thispos - lastpos) > 0) {
|
|
|
|
|
+ q = (*avcnt) - 1;
|
|
|
|
|
+ while(dz->parray[WARP_AVP][q]<MIDIMIN) {
|
|
|
|
|
+ if(--q<=lastpos)
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ thismidi = dz->parray[WARP_AVP][q];
|
|
|
|
|
+ ttime = (q * BLOKCNT) * dz->frametime;
|
|
|
|
|
+ if((exit_status = do_pitch_wiggle(&thismidi,ttime,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = warp_pitches(thispos,diff,&lastpos,thismidi,&lastmidi,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** WARP_TIME ************************/
|
|
|
|
|
+
|
|
|
|
|
+int warp_time(int avcnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status = CONTINUE;
|
|
|
|
|
+ int lastoutpos = 0, lastinpos = 0, indiff, remain;
|
|
|
|
|
+ int n, ip, samps_read;
|
|
|
|
|
+ int last_total_wndws = 0;
|
|
|
|
|
+ float *nextbuf = dz->flbufptr[0] + dz->wanted, *thisbuf = dz->flbufptr[0];
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ dz->total_samps_read = 0;
|
|
|
|
|
+ if((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) <= 0) {
|
|
|
|
|
+ if(samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ sprintf(errstr,"Cannot read data from input analysis file.\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ dz->total_samps_read += samps_read;
|
|
|
|
|
+ dz->iparam[WARP_WREAD] = samps_read/dz->wanted;
|
|
|
|
|
+ if((dz->flbufptr[6] = dz->bigfbuf + samps_read)!=dz->flbufptr[2]) {
|
|
|
|
|
+ dz->iparam[WARP_PART_INBUF] = 1;
|
|
|
|
|
+ dz->iparam[WARP_ATEND] = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<avcnt;n++) {
|
|
|
|
|
+ if(dz->iparray[WARP_CHANGE][n]) {
|
|
|
|
|
+ if((exit_status = setup_and_do_timewarp(&thisbuf,&nextbuf,n,&lastoutpos,&lastinpos,&last_total_wndws,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(exit_status!=CONTINUE)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((indiff = (dz->wlength - 1) - lastinpos) > 0) {
|
|
|
|
|
+ ip = lastinpos + 1;
|
|
|
|
|
+ while(lastinpos < dz->wlength) {
|
|
|
|
|
+ if((exit_status = adjust_input_buffers(&thisbuf,&nextbuf,ip,&last_total_wndws,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->flbufptr[1]!=thisbuf)
|
|
|
|
|
+ memmove((char *)dz->flbufptr[1],(char *)thisbuf,(size_t)(dz->wanted * sizeof(float)));
|
|
|
|
|
+ if((dz->flbufptr[1] += dz->wanted) >= dz->flbufptr[3]) {
|
|
|
|
|
+ if((exit_status = write_exact_samps(dz->flbufptr[2],dz->big_fsize,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->flbufptr[1] = dz->flbufptr[2];
|
|
|
|
|
+ }
|
|
|
|
|
+ lastinpos++; /* MAY 1997 ??? */
|
|
|
|
|
+ ip = lastinpos; /* MAY 1997 ??? */
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((remain = (dz->flbufptr[1] - dz->flbufptr[2]))>0) {
|
|
|
|
|
+ if((exit_status = write_samps(dz->flbufptr[2],remain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** GET_PITCH_AVERAGES ************************/
|
|
|
|
|
+
|
|
|
|
|
+int get_pitch_averages(int *avcnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int k = 0, OK = 1, n = 0, m, cnt;
|
|
|
|
|
+ while(OK) {
|
|
|
|
|
+ dz->parray[WARP_AVP][k] = 0.0;
|
|
|
|
|
+ m = 0;
|
|
|
|
|
+ cnt = 0;
|
|
|
|
|
+ while(m < BLOKCNT) {
|
|
|
|
|
+ if(dz->pitches[n]<MIDIMIN) {
|
|
|
|
|
+ m++;
|
|
|
|
|
+ if(++n >= dz->wlength) {
|
|
|
|
|
+ OK = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->parray[WARP_AVP][k] += dz->pitches[n];
|
|
|
|
|
+ cnt++;
|
|
|
|
|
+ m++;
|
|
|
|
|
+ if(++n >= dz->wlength) {
|
|
|
|
|
+ OK = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(cnt==0)
|
|
|
|
|
+ dz->parray[WARP_AVP][k] = -1.0;
|
|
|
|
|
+ else
|
|
|
|
|
+ dz->parray[WARP_AVP][k] /= (double)cnt;
|
|
|
|
|
+ k++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[WARP_AVP] = (double *)realloc((char *)dz->parray[WARP_AVP],k * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for warp averages array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *avcnt = k;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** SETUP_AND_DO_PITCHWARP ************************/
|
|
|
|
|
+
|
|
|
|
|
+int setup_and_do_pitchwarp(int start,int avg_no,int *lastpos,double *lastmidi,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int here, q, z, diff;
|
|
|
|
|
+ double thismidi, ttime;
|
|
|
|
|
+ here = min((dz->wlength - 1),avg_no * BLOKCNT); /* just being ultra careful !! */
|
|
|
|
|
+ for(q = here; q < here+BLOKCNT; q++) {
|
|
|
|
|
+ if(q>=dz->wlength)
|
|
|
|
|
+ break;
|
|
|
|
|
+ if(dz->pitches[q] >= MIDIMIN)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(q >= here+BLOKCNT || q>=dz->wlength) { /* No valid pitchdata here !! */
|
|
|
|
|
+ for(z=here; z<q; z++)
|
|
|
|
|
+ dz->parray[WARP_P2][z] = -1.0;
|
|
|
|
|
+ dz->iparray[WARP_CHANGE][avg_no] = 0;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ } else /* [WARP_CHANGE] remembers position of approp wndw to work on */
|
|
|
|
|
+ dz->iparray[WARP_CHANGE][avg_no] = q;
|
|
|
|
|
+ here = q;
|
|
|
|
|
+ ttime = dz->frametime * (double)here;
|
|
|
|
|
+ thismidi = dz->pitches[here];
|
|
|
|
|
+ if((exit_status = do_pitch_wiggle(&thismidi,ttime,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(avg_no==start) {
|
|
|
|
|
+ dz->parray[WARP_P2][q] = thismidi;
|
|
|
|
|
+ *lastpos = q;
|
|
|
|
|
+ *lastmidi = thismidi;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ diff = q - *lastpos;
|
|
|
|
|
+ return warp_pitches(q,diff,lastpos,thismidi,lastmidi,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** DO_PITCH_WIGGLE *******************/
|
|
|
|
|
+
|
|
|
|
|
+int do_pitch_wiggle(double *thismidi,double ttime, dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double wiggle, this_prange;
|
|
|
|
|
+ if(dz->brksize[WARP_PRNG]) {
|
|
|
|
|
+ if((exit_status = read_value_from_brktable(ttime,WARP_PRNG,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ wiggle = (drand48() * 2.0) -1.0; /* random +- */
|
|
|
|
|
+ this_prange = wiggle * dz->param[WARP_PRNG];
|
|
|
|
|
+ *thismidi += this_prange;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** WARP_PITCHES *******************/
|
|
|
|
|
+
|
|
|
|
|
+int warp_pitches(int thispos,int diff,int *lastpos,double thismidi,double *lastmidi,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, m;
|
|
|
|
|
+ double mididiff = thismidi - *lastmidi;
|
|
|
|
|
+ double midistep = mididiff/(double)diff;
|
|
|
|
|
+ for(m=1, n=(*lastpos)+1; m <= diff; m++, n++) {
|
|
|
|
|
+ if(n < dz->wlength && dz->pitches[n]<MIDIMIN) {
|
|
|
|
|
+ dz->parray[WARP_P2][n] = -1.0;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ thismidi = *lastmidi + (midistep * (double)m);
|
|
|
|
|
+ dz->parray[WARP_P2][n] = thismidi;
|
|
|
|
|
+ }
|
|
|
|
|
+ *lastmidi = thismidi;
|
|
|
|
|
+ *lastpos = thispos;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** SETUP_AND_DO_TIMEWARP ************************/
|
|
|
|
|
+
|
|
|
|
|
+int setup_and_do_timewarp
|
|
|
|
|
+(float **thisbuf,float **nextbuf,int n,int *lastoutpos,int *lastinpos,int *last_total_wndws,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int thisoutpos, outdiff;
|
|
|
|
|
+ int thisinpos = dz->iparray[WARP_CHANGE][n];
|
|
|
|
|
+ double ttime = dz->frametime * (double)thisinpos;
|
|
|
|
|
+ if(n==0) {
|
|
|
|
|
+ if((exit_status = transpos_initial_windows(thisbuf,nextbuf,thisinpos,last_total_wndws,dz))!=CONTINUE)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *lastinpos = thisinpos;
|
|
|
|
|
+ *lastoutpos = thisinpos;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = do_time_wiggle(&ttime,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ thisoutpos = round(ttime/dz->frametime);
|
|
|
|
|
+ thisoutpos = max(0L,thisoutpos);
|
|
|
|
|
+ if((outdiff = thisoutpos - *lastoutpos)>0) {/* number of windows to scan in output data */
|
|
|
|
|
+ if((exit_status = do_timewarp(thisbuf,nextbuf,thisinpos,outdiff,lastinpos,last_total_wndws,dz))!=CONTINUE)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ *lastinpos = thisinpos; /* ??? */
|
|
|
|
|
+ *lastoutpos = thisoutpos; /* ??? */
|
|
|
|
|
+ }
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** ADJUST_INPUT_BUFFERS *******************/
|
|
|
|
|
+
|
|
|
|
|
+int adjust_input_buffers(float **thisbuf,float **nextbuf,int thisindex,int *last_total_wndws,int do_next,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int currentbuf_index, currentbuf_nextindex;
|
|
|
|
|
+ currentbuf_index = thisindex - *last_total_wndws;
|
|
|
|
|
+
|
|
|
|
|
+ if(currentbuf_index >= dz->iparam[WARP_WREAD]) {
|
|
|
|
|
+ if((exit_status = find_currentbuf_index(¤tbuf_index,last_total_wndws,thisbuf,dz))!=CONTINUE)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(do_next) {
|
|
|
|
|
+ currentbuf_nextindex = currentbuf_index + 1;
|
|
|
|
|
+ if(currentbuf_nextindex >= dz->iparam[WARP_WREAD]) {
|
|
|
|
|
+ if(dz->flbufptr[3]!=*thisbuf)
|
|
|
|
|
+ memmove((char *)dz->flbufptr[3],(char *)(*thisbuf),(size_t)(dz->wanted * sizeof(float)));
|
|
|
|
|
+ *thisbuf = dz->flbufptr[3];
|
|
|
|
|
+ if((exit_status = find_currentbuf_nextindex(¤tbuf_nextindex,*last_total_wndws,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *nextbuf = dz->bigfbuf + (currentbuf_nextindex * dz->wanted);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** TRANSPOS_INITIAL_WINDOWS ******************/
|
|
|
|
|
+
|
|
|
|
|
+int transpos_initial_windows(float **thisbuf,float **nextbuf,int cnt,int *last_total_wndws,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ int n = 0, samps_to_write, samps_read;
|
|
|
|
|
+ double transp;
|
|
|
|
|
+ while(n <= cnt) {
|
|
|
|
|
+ rectify_window(dz->flbufptr[0],dz);
|
|
|
|
|
+ if(dz->pitches[n] > MIDIMIN) {
|
|
|
|
|
+ transp = SEMITONES_AS_RATIO(dz->parray[WARP_P2][n] - dz->pitches[n]);
|
|
|
|
|
+ for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
|
|
|
|
|
+ dz->flbufptr[1][AMPP] = dz->flbufptr[0][AMPP];
|
|
|
|
|
+ dz->flbufptr[1][FREQ] = (float)(dz->flbufptr[0][FREQ] * transp);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = put_transposed_data_in_appropriate_chans(transp,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(vc=0;vc<dz->wanted;vc+=2)
|
|
|
|
|
+ dz->flbufptr[1][vc] = dz->flbufptr[0][vc]; /* Copy unpitched windows */
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->flbufptr[1] += dz->wanted;
|
|
|
|
|
+ if((dz->flbufptr[0] += dz->wanted) >= dz->flbufptr[6]) {
|
|
|
|
|
+ if(dz->iparam[WARP_PART_INBUF]) {
|
|
|
|
|
+ if((samps_to_write = dz->flbufptr[1] - dz->flbufptr[2])>0)
|
|
|
|
|
+ return write_samps(dz->flbufptr[2],samps_to_write,dz);
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = write_exact_samps(dz->flbufptr[2],dz->big_fsize,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) <= 0) {
|
|
|
|
|
+ if(samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ dz->total_samps_read += samps_read;
|
|
|
|
|
+ *last_total_wndws += dz->iparam[WARP_WREAD];
|
|
|
|
|
+ dz->iparam[WARP_WREAD] = samps_read/dz->wanted;
|
|
|
|
|
+ if(samps_read < dz->big_fsize) {
|
|
|
|
|
+ dz->iparam[WARP_PART_INBUF] = 1;
|
|
|
|
|
+ dz->flbufptr[6] = dz->bigfbuf + samps_read;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->flbufptr[1] = dz->flbufptr[2];
|
|
|
|
|
+ dz->flbufptr[0] = dz->bigfbuf;
|
|
|
|
|
+ }
|
|
|
|
|
+ n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = setup_thisbuf_and_nextbuf(*last_total_wndws,thisbuf,nextbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_TIME_WIGGLE ************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_time_wiggle(double *ttime,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double this_trange;
|
|
|
|
|
+ double wiggle = (drand48() * 2.0) -1.0;
|
|
|
|
|
+ if(dz->brksize[WARP_TRNG]) { /* RWD need curly */
|
|
|
|
|
+ if((exit_status = read_value_from_brktable(*ttime,WARP_TRNG,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ this_trange = dz->param[WARP_TRNG] * wiggle;
|
|
|
|
|
+ *ttime += this_trange;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_TIMEWARP ************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_timewarp
|
|
|
|
|
+(float **thisbuf,float **nextbuf,int thisinpos,int outdiff,int *lastinpos,int *last_total_wndws,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int indiff = thisinpos - *lastinpos; /* number of windows to scan in input data */
|
|
|
|
|
+ double step = (double)indiff/(double)outdiff; /* fractional step in input data */
|
|
|
|
|
+ int move;
|
|
|
|
|
+ int n, ip, lastip = *lastinpos;
|
|
|
|
|
+ double thisfrac, thisindex = (double)(*lastinpos) + step; /* fractional position in input data */
|
|
|
|
|
+ double oldmidi, newmidi, transp;
|
|
|
|
|
+
|
|
|
|
|
+ for(n=1; n <= outdiff; n++, thisindex+=step) {
|
|
|
|
|
+ ip = (int)thisindex; /* TRUNCATE */
|
|
|
|
|
+ thisfrac = thisindex - (double)ip;
|
|
|
|
|
+ move = ip - lastip;
|
|
|
|
|
+ lastip = ip;
|
|
|
|
|
+ if(move) {
|
|
|
|
|
+ if((exit_status = adjust_input_buffers(thisbuf,nextbuf,ip,last_total_wndws,1,dz))!=CONTINUE)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = interp_between_vals_in_two_bufs(*thisbuf,*nextbuf,thisfrac,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = interp_between_pitch_vals(&oldmidi,dz->pitches,ip,thisfrac,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = interp_between_pitch_vals2(&newmidi,dz->parray[WARP_P2],ip,thisfrac,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ transp = SEMITONES_AS_RATIO(newmidi - oldmidi);
|
|
|
|
|
+ if((exit_status = transpose_outbuf(transp,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((dz->flbufptr[1] += dz->wanted) >= dz->flbufptr[3]) {
|
|
|
|
|
+ if((exit_status = write_exact_samps(dz->flbufptr[2],dz->big_fsize,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->flbufptr[1] = dz->flbufptr[2];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** FIND_CURRENTBUF_INDEX *******************/
|
|
|
|
|
+
|
|
|
|
|
+int find_currentbuf_index(int *currentbuf_index,int *last_total_wndws,float **thisbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int samps_read = 0;
|
|
|
|
|
+ int finalbuf_index;
|
|
|
|
|
+ if(dz->iparam[WARP_ATEND]) {
|
|
|
|
|
+ *currentbuf_index = max((dz->wlength - 2) - (*last_total_wndws),0);
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+ }
|
|
|
|
|
+ while(*currentbuf_index >= dz->iparam[WARP_WREAD]) {
|
|
|
|
|
+ if((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) <= 0) {
|
|
|
|
|
+ if(samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ dz->total_samps_read += samps_read;
|
|
|
|
|
+ if(samps_read <= dz->big_fsize)
|
|
|
|
|
+ dz->iparam[WARP_ATEND] = 1;
|
|
|
|
|
+ *currentbuf_index -= dz->iparam[WARP_WREAD];
|
|
|
|
|
+ *last_total_wndws += dz->iparam[WARP_WREAD];
|
|
|
|
|
+ if(dz->iparam[WARP_ATEND]) {
|
|
|
|
|
+ finalbuf_index = max((dz->wlength - 2) - (*last_total_wndws),0);
|
|
|
|
|
+ *currentbuf_index = min(*currentbuf_index,finalbuf_index);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->iparam[WARP_WREAD] = samps_read/dz->wanted;
|
|
|
|
|
+ if(dz->iparam[WARP_ATEND])
|
|
|
|
|
+ dz->flbufptr[6] = dz->bigfbuf + samps_read;
|
|
|
|
|
+
|
|
|
|
|
+ *thisbuf = dz->bigfbuf + (*currentbuf_index * dz->wanted);
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** FIND_CURRENTBUF_NEXTINDEX *******************/
|
|
|
|
|
+
|
|
|
|
|
+int find_currentbuf_nextindex(int *currentbuf_nextindex,int last_total_wndws,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int samps_read;
|
|
|
|
|
+ int lastindex = (dz->wlength - 1) - last_total_wndws;
|
|
|
|
|
+ *currentbuf_nextindex = lastindex;
|
|
|
|
|
+ if(dz->iparam[WARP_ATEND])
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ if((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) <= 0) {
|
|
|
|
|
+ if(samps_read<0) {
|
|
|
|
|
+ sprintf(errstr,"Sound read error.\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->iparam[WARP_ATEND] = 1;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ dz->total_samps_read += samps_read;
|
|
|
|
|
+ dz->iparam[WARP_WREAD] = samps_read/dz->wanted;
|
|
|
|
|
+ if(samps_read < dz->big_fsize) {
|
|
|
|
|
+ dz->iparam[WARP_ATEND] = 1;
|
|
|
|
|
+ dz->flbufptr[6] = dz->bigfbuf + samps_read;
|
|
|
|
|
+ }
|
|
|
|
|
+ *currentbuf_nextindex = 0L;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** SETUP_THISBUF_AND_NEXTBUF *******************/
|
|
|
|
|
+
|
|
|
|
|
+int setup_thisbuf_and_nextbuf(int last_total_wndws,float **thisbuf,float **nextbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int currentbuf_nextindex;
|
|
|
|
|
+ if(dz->flbufptr[0] + dz->wanted >= dz->flbufptr[2]) {
|
|
|
|
|
+ memmove((char *)dz->flbufptr[3],(char *)dz->flbufptr[0],(size_t)dz->wanted * sizeof(float));
|
|
|
|
|
+ *thisbuf = dz->flbufptr[3];
|
|
|
|
|
+ if((exit_status = find_currentbuf_nextindex(¤tbuf_nextindex,last_total_wndws,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *nextbuf = dz->bigfbuf + (currentbuf_nextindex * dz->wanted);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** INTERP_BETWEEN_VALS_IN_TWO_BUFS *******************/
|
|
|
|
|
+
|
|
|
|
|
+int interp_between_vals_in_two_bufs(float *thisbuf,float *nextbuf,double interpval,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int vc;
|
|
|
|
|
+ double thismidi, nextmidi, mididiff, ampdiff;
|
|
|
|
|
+ rectify_window(thisbuf,dz);
|
|
|
|
|
+ if(interpval<FLTERR) {
|
|
|
|
|
+ rectify_window(thisbuf,dz);
|
|
|
|
|
+ if(dz->flbufptr[1]!=thisbuf)
|
|
|
|
|
+ memmove((char *)dz->flbufptr[1],(char *)thisbuf,(size_t)(dz->wanted * sizeof(float)));
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(interpval > (1.0 - FLTERR)) {
|
|
|
|
|
+ rectify_window(nextbuf,dz);
|
|
|
|
|
+ if(dz->flbufptr[1]!=nextbuf)
|
|
|
|
|
+ memmove((char *)dz->flbufptr[1],(char *)nextbuf,(size_t)(dz->wanted * sizeof(float)));
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ rectify_window(thisbuf,dz);
|
|
|
|
|
+ rectify_window(nextbuf,dz);
|
|
|
|
|
+ for(vc = 0; vc<dz->wanted; vc+=2) {
|
|
|
|
|
+ thismidi = log(max(SPEC_MINFRQ,(double)thisbuf[FREQ])); /* quick calc using logs, without hztimidi() */
|
|
|
|
|
+ nextmidi = log(max(SPEC_MINFRQ,(double)nextbuf[FREQ])); /* works because logs to different bases are simply */
|
|
|
|
|
+ mididiff = nextmidi - thismidi; /* scaled versions of one another. See Feynmann book. */
|
|
|
|
|
+ ampdiff = nextbuf[AMPP] - thisbuf[AMPP];
|
|
|
|
|
+ dz->flbufptr[1][FREQ] = (float)exp(thismidi + (mididiff * interpval)); /* exp() = antilog of log() */
|
|
|
|
|
+ dz->flbufptr[1][AMPP] = (float)(thisbuf[AMPP] + (ampdiff * interpval));
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** INTERP_BETWEEN_PITCH_VALS *******************/
|
|
|
|
|
+
|
|
|
|
|
+int interp_between_pitch_vals(double *thismidi,float *pitch,int thisindex,double interpval,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double mididiff;
|
|
|
|
|
+ if(thisindex<0) {
|
|
|
|
|
+ sprintf(errstr,"Pitch_interpolation val < 0 in interp_between_pitch_vals()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thisindex >= (dz->wlength - 2)) {
|
|
|
|
|
+ *thismidi = (double)pitch[(dz->wlength - 1)];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(interpval < FLTERR) {
|
|
|
|
|
+ *thismidi = (double)pitch[thisindex];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(interpval > (1.0 - FLTERR)) {
|
|
|
|
|
+ *thismidi = (double)pitch[thisindex+1];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ mididiff = pitch[thisindex+1] - pitch[thisindex];
|
|
|
|
|
+ *thismidi = pitch[thisindex] + (mididiff * interpval);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** INTERP_BETWEEN_PITCH_VALS2 *******************/
|
|
|
|
|
+
|
|
|
|
|
+int interp_between_pitch_vals2(double *thismidi,double *pitch,int thisindex,double interpval,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double mididiff;
|
|
|
|
|
+ if(thisindex<0) {
|
|
|
|
|
+ sprintf(errstr,"Interpolation val < 0 in interp_between_pitch_vals2()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thisindex >= (dz->wlength - 2)) {
|
|
|
|
|
+ *thismidi = pitch[(dz->wlength - 1)];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(interpval < FLTERR) {
|
|
|
|
|
+ *thismidi = pitch[thisindex];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(interpval > (1.0 - FLTERR)) {
|
|
|
|
|
+ *thismidi = pitch[thisindex+1];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ mididiff = pitch[thisindex+1] - pitch[thisindex];
|
|
|
|
|
+ *thismidi = pitch[thisindex] + (mididiff * interpval);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** TRANSPOSE_OUTBUF *******************/
|
|
|
|
|
+
|
|
|
|
|
+int transpose_outbuf(double transp,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int vc;
|
|
|
|
|
+ for(vc=0;vc<dz->wanted;vc+=2)
|
|
|
|
|
+ dz->flbufptr[1][FREQ] = (float)(dz->flbufptr[1][FREQ] * transp);
|
|
|
|
|
+ return put_transposed_data_in_appropriate_chans(transp,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** PUT_TRANSPOSED_DATA_IN_APPROPRIATE_CHANS *******************/
|
|
|
|
|
+
|
|
|
|
|
+int put_transposed_data_in_appropriate_chans(double transp,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int cc,vc;
|
|
|
|
|
+ if((exit_status = rectify_frqs(dz->flbufptr[1],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(transp < 1.0) { /* If transposition is downwards, go up the channels */
|
|
|
|
|
+ for(cc=0,vc=0; cc < dz->clength; cc++,vc+=2) {
|
|
|
|
|
+ if((exit_status = put_thisdata_in_appropriate_chan(cc,vc,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else { /* If transposition is upwards, go down the channels */
|
|
|
|
|
+ for(cc=dz->clength-1,vc = dz->wanted-2; cc >=0 ;cc--,vc-=2) {
|
|
|
|
|
+ if((exit_status = put_thisdata_in_appropriate_chan(cc,vc,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************** PUT_THISDATA_IN_APPROPRIATE_CHAN *******************/
|
|
|
|
|
+
|
|
|
|
|
+int put_thisdata_in_appropriate_chan(int cc,int vc, dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int truecc, truevc, trutop;
|
|
|
|
|
+ if(dz->flbufptr[1][FREQ] > dz->nyquist) { /* zero out frqs above nyquist */
|
|
|
|
|
+ dz->flbufptr[1][AMPP] = 0.0f;
|
|
|
|
|
+ dz->flbufptr[1][FREQ] = (float)dz->nyquist;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ } /* if new frq outside acceptable frq limits for channel */
|
|
|
|
|
+ if(dz->flbufptr[1][FREQ] < dz->flbufptr[WCHBOT][cc] || dz->flbufptr[1][FREQ] > dz->flbufptr[WCHTOP][cc]) {
|
|
|
|
|
+ if((exit_status = get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[1][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ trutop = min(dz->clength-1,truecc + CHANSPAN);
|
|
|
|
|
+ truecc = max(truecc - CHANSPAN,0); /* find bottom and top chans that could receive this frq */
|
|
|
|
|
+ truevc = truecc * 2;
|
|
|
|
|
+ while(dz->flbufptr[1][FREQ] > dz->flbufptr[1][truevc+1]) {
|
|
|
|
|
+ truevc += 2; /* find position of new freq amongst freq ordering of existing data */
|
|
|
|
|
+ if(truevc >= trutop)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ truevc -= 2;
|
|
|
|
|
+ do {
|
|
|
|
|
+ if(dz->flbufptr[1][AMPP] > dz->flbufptr[1][truevc]) { /* If transpd data stronger than existing data */
|
|
|
|
|
+ dz->flbufptr[1][truevc] = dz->flbufptr[1][AMPP];/* replace existing data by transposed data */
|
|
|
|
|
+ dz->flbufptr[1][truevc+1] = dz->flbufptr[1][FREQ];
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ truevc += 2;
|
|
|
|
|
+ } while(truevc < trutop);
|
|
|
|
|
+ dz->flbufptr[1][AMPP] = 0.0f; /* Zero out channel from which data has been moved */
|
|
|
|
|
+ if(cc>0 && cc < dz->clength-1) /* Interp frq of that chan, betwn preexisting chans */
|
|
|
|
|
+ dz->flbufptr[1][FREQ] = (float)((dz->flbufptr[1][FREQ+2] + dz->flbufptr[1][FREQ-2])/2.0);
|
|
|
|
|
+ else {
|
|
|
|
|
+ if(cc==0) dz->flbufptr[1][FREQ] = 0.0f;
|
|
|
|
|
+ else dz->flbufptr[1][FREQ] = (float)dz->nyquist;
|
|
|
|
|
+ } /* This chan may later be filld by other moved data */
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** LOGREAD_SHIFT *****************************/
|
|
|
|
|
+
|
|
|
|
|
+int logread_shift(double timenow,int btktable_no,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double *endpair, *p;
|
|
|
|
|
+ double hival, loval, hiind, loind, lopshift, interval, newpshift;
|
|
|
|
|
+ if(!dz->brkinit[btktable_no]) {
|
|
|
|
|
+ dz->firstval[btktable_no] = *(dz->brk[btktable_no]+1);
|
|
|
|
|
+ endpair = dz->brk[btktable_no]
|
|
|
|
|
+ + ((dz->brksize[btktable_no]-1)*2);
|
|
|
|
|
+ dz->lastind[btktable_no] = *endpair;
|
|
|
|
|
+ dz->lastval[btktable_no] = *(endpair+1);
|
|
|
|
|
+ dz->brkinit[btktable_no] = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ p = dz->brkptr[btktable_no];
|
|
|
|
|
+ if(timenow <= *(dz->brk[btktable_no])) {
|
|
|
|
|
+ dz->param[btktable_no] = dz->firstval[btktable_no];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ } else if(timenow >= dz->lastind[btktable_no]) {
|
|
|
|
|
+ dz->param[btktable_no] = dz->lastval[btktable_no];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(timenow > *(p)) {
|
|
|
|
|
+ while(*(p)<timenow)
|
|
|
|
|
+ p += 2;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ while(*(p)>=timenow)
|
|
|
|
|
+ p -= 2;
|
|
|
|
|
+ p += 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ hival = *(p+1);
|
|
|
|
|
+ hiind = *p;
|
|
|
|
|
+ loval = *(p-1);
|
|
|
|
|
+ loind = *(p-2);
|
|
|
|
|
+ if(flteq(loval,hival))
|
|
|
|
|
+ dz->param[btktable_no] = loval;
|
|
|
|
|
+ else if(loval < 0.0 && hival < 0.0) {
|
|
|
|
|
+ lopshift = log(-loval);
|
|
|
|
|
+ interval = log(-hival/-loval);
|
|
|
|
|
+ interval *= (timenow - loind)/(hiind - loind);
|
|
|
|
|
+ newpshift = lopshift + interval;
|
|
|
|
|
+ dz->param[btktable_no] = -exp(newpshift);
|
|
|
|
|
+ } else if (loval > 0.0 && hival > 0.0){
|
|
|
|
|
+ lopshift = log(loval);
|
|
|
|
|
+ interval = log(hival/loval);
|
|
|
|
|
+ interval *= (timenow - loind)/(hiind - loind);
|
|
|
|
|
+ newpshift = lopshift + interval;
|
|
|
|
|
+ dz->param[btktable_no] = exp(newpshift);
|
|
|
|
|
+ } else {
|
|
|
|
|
+/* if shift changes from +ve (or 0) to -ve (or 0) or v.v., do linear shift */
|
|
|
|
|
+ interval = hival - loval;
|
|
|
|
|
+ interval *= (timenow - loind)/(hiind - loind);
|
|
|
|
|
+ dz->param[btktable_no] = loval + interval;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->brkptr[btktable_no] = p;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** READ_VALUE_FROM_BRKTABLE_USING_LOG_INTERPOLATION *****************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * Slightly weird function that fudges problem of log(0) and log(-ve).
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int read_value_from_brktable_using_log_interpolation(double thistime,int paramno,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double *endpair, *p;
|
|
|
|
|
+ double hival, loval, hiind, loind, lopitch, interval, newpitch;
|
|
|
|
|
+
|
|
|
|
|
+ if(!dz->brkinit[paramno]) {
|
|
|
|
|
+ dz->brkptr[paramno] = dz->brk[paramno];
|
|
|
|
|
+ dz->firstval[paramno] = *(dz->brk[paramno]+1);
|
|
|
|
|
+ endpair = dz->brk[paramno] + ((dz->brksize[paramno]-1)*2);
|
|
|
|
|
+ dz->lastind[paramno] = *endpair;
|
|
|
|
|
+ dz->lastval[paramno] = *(endpair+1);
|
|
|
|
|
+ dz->brkinit[paramno] = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ p = dz->brkptr[paramno];
|
|
|
|
|
+ if(thistime <= *(dz->brk[paramno])) {
|
|
|
|
|
+ dz->param[paramno] = dz->firstval[paramno];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ } else if(thistime >= dz->lastind[paramno]) {
|
|
|
|
|
+ dz->param[paramno] = dz->lastval[paramno];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thistime > *(p)) {
|
|
|
|
|
+ while(*(p)<thistime)
|
|
|
|
|
+ p += 2;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ while(*(p)>=thistime)
|
|
|
|
|
+ p -= 2;
|
|
|
|
|
+ p += 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ hival = *(p+1);
|
|
|
|
|
+ hiind = *p;
|
|
|
|
|
+ loval = *(p-1);
|
|
|
|
|
+ loind = *(p-2);
|
|
|
|
|
+ if(flteq(loval,hival))
|
|
|
|
|
+ dz->param[paramno] = loval;
|
|
|
|
|
+ else if(loval < 0.0 && hival < 0.0) {
|
|
|
|
|
+ lopitch = log(-loval);
|
|
|
|
|
+ interval = log(-hival/-loval);
|
|
|
|
|
+ interval *= (thistime - loind)/(hiind - loind);
|
|
|
|
|
+ newpitch = lopitch + interval;
|
|
|
|
|
+ dz->param[paramno] = -exp(newpitch);
|
|
|
|
|
+ } else if (loval > 0.0 && hival > 0.0){
|
|
|
|
|
+ lopitch = log(loval);
|
|
|
|
|
+ interval = log(hival/loval);
|
|
|
|
|
+ interval *= (thistime - loind)/(hiind - loind);
|
|
|
|
|
+ newpitch = lopitch + interval;
|
|
|
|
|
+ dz->param[paramno] = exp(newpitch);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ /* if val changes from +ve (or 0) to -ve (or 0) or v.v., do linear shift */
|
|
|
|
|
+ interval = hival - loval;
|
|
|
|
|
+ interval *= (thistime - loind)/(hiind - loind);
|
|
|
|
|
+ dz->param[paramno] = loval + interval;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->brkptr[paramno] = p;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** ASSIGN_NEW_FRQS_TO_APPROPRIATE_CHANNELS ****************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * (0) Find the lowest channel for which we have generated a new freq value.
|
|
|
|
|
+ * (0a) If no frqs lie below nyquist, zero all chan amps above botchan!!
|
|
|
|
|
+ * (1) Set initial amplitude for each transformed channel to zero.
|
|
|
|
|
+ * (2) Look through the set of stretched channels for any frequency
|
|
|
|
|
+ * values which lie below the top frq boundary of the current channel,
|
|
|
|
|
+ * (3) IF they are also above the bottom freq boundary of this channel,
|
|
|
|
|
+ * (i.e. they should be in THIS channel), if their amplitude
|
|
|
|
|
+ * is greater than any amp already assigned to this channel,
|
|
|
|
|
+ * substitute this frq/amp pair as the true value for this channel.
|
|
|
|
|
+ * (4) If we run out of values among the transformed freq values,
|
|
|
|
|
+ * break, and set OK=0 to break from outer loop too.
|
|
|
|
|
+ * (5) If we've broken from inner loop, break from outer loop too.
|
|
|
|
|
+ * (6) If we've broken from inner loop, zero amplitude of any channels
|
|
|
|
|
+ * which have not been assigned a new frequency.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int assign_new_frqs_to_appropriate_channels(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int dd = dz->iparam[WAVER_BOTCHAN]; /* 0 */
|
|
|
|
|
+ int OK = 1, cc = 0, vc;
|
|
|
|
|
+ while(dz->freq[dd] >= (float)(dz->parray[WAVER_CHFBOT][cc+1])) {
|
|
|
|
|
+ if(++cc >= dz->clength) { /* 0a */
|
|
|
|
|
+ for(vc = dz->iparam[WAVER_BOTCHAN] * 2; vc < dz->wanted; vc += 2)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0F;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(vc=cc*2; cc<dz->clength; cc++,vc+=2) {
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0F; /* 1 */
|
|
|
|
|
+ while(dz->freq[dd] < (float)(dz->parray[WAVER_CHFBOT][cc+1])) { /* 2 */
|
|
|
|
|
+ if((dz->freq[dd] >= dz->parray[WAVER_CHFBOT][cc]) && (dz->amp[dd] > dz->flbufptr[0][AMPP])) {
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = dz->amp[dd]; /* 3 */
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = dz->freq[dd];
|
|
|
|
|
+ }
|
|
|
|
|
+ if(++dd>=dz->clength) { /* 4 */
|
|
|
|
|
+ OK = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!OK) /* 5 */
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!OK) {
|
|
|
|
|
+ while(vc<dz->wanted) { /* 6 */
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0F;
|
|
|
|
|
+ vc += 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|