|
@@ -0,0 +1,3743 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * Copyright (c) 1983-2020 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 aint with the CDP System; if not, write to the Free Software
|
|
|
|
|
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
|
|
+ 02111-1307 USA
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+/* floatsam vesion */
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <stdlib.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+#include <memory.h>
|
|
|
|
|
+#include <structures.h>
|
|
|
|
|
+#include <tkglobals.h>
|
|
|
|
|
+#include <globcon.h>
|
|
|
|
|
+#include <processno.h>
|
|
|
|
|
+#include <modeno.h>
|
|
|
|
|
+#include <arrays.h>
|
|
|
|
|
+#include <grain.h>
|
|
|
|
|
+#include <cdpmain.h>
|
|
|
|
|
+
|
|
|
|
|
+#define maxtime scalefact
|
|
|
|
|
+
|
|
|
|
|
+#include <sfsys.h>
|
|
|
|
|
+#include <osbind.h>
|
|
|
|
|
+#include <grain.h>
|
|
|
|
|
+
|
|
|
|
|
+#ifdef unix
|
|
|
|
|
+#define round(x) lround((x))
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+static int copygrain_from_elsewhere(int len,int k,int *obufposition,dataptr dz);
|
|
|
|
|
+static int store_the_grain_time(int grainstart,int *graincnt,int crosbuf,double samptotime,int init,dataptr dz);
|
|
|
|
|
+static int retime_grain(int ibufpos,int thisgap,int grainstart,int origgap,int bufno,int *obufpos,
|
|
|
|
|
+ int chans,int crosbuf,int *grainadjusted,int store_end,int is_first_grain,dataptr dz);
|
|
|
|
|
+static int keep_non_omitted_grains(int ibufpos,int bufno,int grainstart,int *graincnt,
|
|
|
|
|
+ int *obufpos,int crosbuf,int chans,int is_first_grain,dataptr dz);
|
|
|
|
|
+static int do_the_reordered_grains(int ibufpos,int bufno,int grainstart,int *graincnt,
|
|
|
|
|
+ int *obufpos,int crosbuf,int chans,int is_first_grain,int is_last_grain,dataptr dz);
|
|
|
|
|
+static int synchronise_the_grain(int ibufpos,int *graincnt,int bufno,int gapcnt,int *obufpos,
|
|
|
|
|
+ int grainstart,int crosbuf,int chans,int *grainadjusted,int is_first_grain,dataptr dz);
|
|
|
|
|
+static int do_final_reorder_grains(int graincnt,int *obufpos,dataptr dz);
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+static int output_final_grain(int grainstart,int start_splice,int bufno,int splicestart_bufno,int is_first_grain,
|
|
|
|
|
+ int *obufpos,int grainlen,int crosbuf,dataptr dz);
|
|
|
|
|
+static int do_rerhythm_grain(int ibufpos,int *graincnt,int bufno,int gapcnt,int *obufpos,int grainstart,
|
|
|
|
|
+ int crosbuf,int chans,int *grainadjusted,int is_first_grain,dataptr dz);
|
|
|
|
|
+static void swap_array_adresses_and_lens_for_reordr(int n,int m,dataptr dz);
|
|
|
|
|
+static int copy_grain_to_buf(int ibufpos,int bufno,int grainstart,int crosbuf,int chans,int n,dataptr dz);
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+static int retime_pre_firstgrain_material
|
|
|
|
|
+ (int new_grainstart,int *obufposition,int chans,int crosbuf,dataptr dz);
|
|
|
|
|
+static int output_grain_link(int thisgap,int abs_halfsplice,int *obufposition,dataptr dz);
|
|
|
|
|
+static int copy_start_of_grain(int grainstart,int start_splice,int bufno,int splicestart_bufno,
|
|
|
|
|
+ int *obufpos,int crosbuf,dataptr dz);
|
|
|
|
|
+static int read_dn_halfsplice(int *obufposition,int len,dataptr dz);
|
|
|
|
|
+static int create_an_upsplice_from_pregrain_material(int obufpos,int chans,dataptr dz);
|
|
|
|
|
+static int duplicate_grain(int ibufpos,int bufno,int gapcnt,int *obufpos,int grainstart,
|
|
|
|
|
+ int crosbuf,int chans,int *grainadjusted,int is_first_grain,dataptr dz);
|
|
|
|
|
+static int prepare_final_grain(int ibufpos,int *start_splice,int bufno,int *splicestart_bufno,
|
|
|
|
|
+ int grainstart,int *grainlen,int crosbuf,int chans,dataptr dz);
|
|
|
|
|
+static int read_up_halfsplice(int *obufposition,int len,dataptr dz);
|
|
|
|
|
+static int store_up_halfsplice(int storeno,int start,int bufno,int chans,int splicelen,dataptr dz);
|
|
|
|
|
+static int store_dn_halfsplice(int start,int bufno,int chans,int splicelen,dataptr dz);
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+static int duplicate_last_grain(int ibufpos,int bufno,int *obufpos,int grainstart,
|
|
|
|
|
+ int crosbuf,int chans,int is_first_grain,dataptr dz);
|
|
|
|
|
+static int store_upsplice_of_next_grain(int ibufpos,int bufno,int abs_halfsplice,int chans,dataptr dz);
|
|
|
|
|
+static int copy_last_grain_to_buf(int ibufpos,int bufno,int grainstart,int crosbuf,int chans,int n,dataptr dz);
|
|
|
|
|
+static int copy_up_halfsplice_to_grainstore(int len,int storeno,int storelen,int *storepos,dataptr dz);
|
|
|
|
|
+static int copy_dn_halfsplice_to_grainstore(int len,int storeno,int storelen,int storepos,dataptr dz);
|
|
|
|
|
+static int copy_midgrain_to_store(int mid_grainlen,int bufno,int storelen,int grainstart,
|
|
|
|
|
+ int *storepos,int crosbuf,int storeno,dataptr dz);;
|
|
|
|
|
+static int put_grain_into_store(int is_last_grain,int ibufpos,int bufno,int grainstart,
|
|
|
|
|
+ int crosbuf,int chans,int graincnt,dataptr dz);
|
|
|
|
|
+static int save_abs_sampletime_of_grain(int grainstart,int *graincnt,int crosbuf,dataptr dz);
|
|
|
|
|
+static int do_seek_and_read(int *seekbufs, int *seeksamps,int grainno,dataptr dz);
|
|
|
|
|
+static int test_buffer_overflows(float *obuf,int *obufpos,int *ibufpos,int n,int maxlen,int *crosbuf,dataptr dz);
|
|
|
|
|
+static int do_the_reversing_process(int graincnt,int *obufposition,int chans,dataptr dz);
|
|
|
|
|
+static int output_up_halfsplice(int *ibufpos,int *obufpos,int chans,int splicelen,int *crosbuf,dataptr dz);
|
|
|
|
|
+static int output_dn_halfsplice(int *ibufpos,int *obufpos,int chans,int splicelen,int *crosbuf,dataptr dz);
|
|
|
|
|
+static int copy_midgrain_to_output(int mid_grainlen,int *ibufpos,int *obufpos,int *crosbuf,int chans,dataptr dz);
|
|
|
|
|
+static int insert_EOF_sampletime_in_samptime_list(int graincnt,dataptr dz);
|
|
|
|
|
+static void adjust_for_last_grain(int *graincnt,int *grainpos,dataptr dz);
|
|
|
|
|
+static int clear_outbuf(dataptr dz);
|
|
|
|
|
+static int output_whole_grain(int n,int *obufpos,int *seeksamps,int *seekbufs,
|
|
|
|
|
+ int halfsplice,int abs_splicelen,int chans,dataptr dz);
|
|
|
|
|
+static int adjust_firstgrain_upsplice(int *ibufpos,int *startsplice,int n,int chans);
|
|
|
|
|
+static int do_grain_repitching(int *actual_grainlen,int bufno,int grainstart,
|
|
|
|
|
+ int new_grainlen,int orig_grainlen,int chans,int crosbuf,double pichratio,dataptr dz);
|
|
|
|
|
+static int test_for_bufcros(int *thishere,float **b,int bufno,int crosbuf,dataptr dz);
|
|
|
|
|
+static int save_nextgrain_upsplice_elsewhere(int ibufpos,int bufno,int abs_halfsplice,int halfsplice,
|
|
|
|
|
+ int chans,dataptr dz);
|
|
|
|
|
+static int copygrain_from_grainbuf_to_outbuf(int *obufpos,int grainlen,dataptr dz);
|
|
|
|
|
+static int retrieve_upsplice_for_nextgrain(int abs_halfsplice,dataptr dz);
|
|
|
|
|
+static int save_origgrain_length_and_store_nextgrains_upsplice(int *orig_grainlen,int ibufpos,int bufno,
|
|
|
|
|
+ int grainstart,int abs_halfsplice,int halfsplice,int crosbuf,int chans,int is_last_grain,dataptr dz);
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+static int create_repitched_and_retimed_grain(int bufno,int grainstart,int orig_grainlen,
|
|
|
|
|
+ int *new_grainlen,double pichratio,double timeratio,int *obufpos,int *is_first_grain,
|
|
|
|
|
+ int *grainadjusted,int abs_halfsplice,int chans,int crosbuf,dataptr dz);
|
|
|
|
|
+static int repitch_main_body_of_grain(int bufno,int grainstart,int new_grainlen,int orig_grainlen,
|
|
|
|
|
+ double pichratio,int chans,int crosbuf,int halfsplice,int abs_halfsplice,dataptr dz);
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+static int retime_main_body_of_grain(int grainstart,int bufno,double pichratio,
|
|
|
|
|
+ double timeratio,int chans,int crosbuf,int *grainadjusted,
|
|
|
|
|
+ int orig_grainlen,int *new_grainlen,dataptr dz);
|
|
|
|
|
+static int repitching_process(int ibufpos,int bufno,int grainstart,int abs_halfsplice,int halfsplice,
|
|
|
|
|
+ int *graincnt,int *obufpos,int *orig_grainlen,int *new_grainlen,int *grainadjusted,
|
|
|
|
|
+ int *is_first_grain,int is_last_grain,int chans,int crosbuf,dataptr dz);
|
|
|
|
|
+static int repitching_and_retiming_process(int ibufpos,int bufno,int grainstart,int abs_halfsplice,
|
|
|
|
|
+ int halfsplice,int *graincnt,int *obufpos,int *orig_grainlen,int *new_grainlen,
|
|
|
|
|
+ int *grainadjusted,int *is_first_grain,int is_last_grain,int chans,int crosbuf,dataptr dz);
|
|
|
|
|
+static int do_in_situ_halfsplice_on_stored_grain(int bufpos,int chans,int splicelen,int grainstorelen,dataptr dz);
|
|
|
|
|
+static int locate_zero_crossings(int local_minima_cnt,dataptr dz);
|
|
|
|
|
+static int which_minimum_to_eliminate(int minsegstartpos,int *pos,int maxseg,int segcnt,int *eliminate_pos,dataptr dz);
|
|
|
|
|
+static int eliminate_excess_minima(int *local_minima_cnt,int *pos,dataptr dz);
|
|
|
|
|
+static int find_all_local_minima(int peakcnt,int *local_minima_cnt,dataptr dz);
|
|
|
|
|
+static int find_all_positive_peaks(int startsearch,int endsearch,int *peakcnt,dataptr dz);
|
|
|
|
|
+static int eliminate_spurious_minima(int *local_minima_cnt,int *minimum_element_len,dataptr dz);
|
|
|
|
|
+static void hhshuflup(int k,int setlen,int *perm);
|
|
|
|
|
+static void hhprefix(int m,int setlen,int *perm);
|
|
|
|
|
+static void hhinsert(int m,int t,int setlen,int *perm);
|
|
|
|
|
+static void do_repet_restricted_perm(int *arr, int *perm, int arrsiz, int allowed, int endval);
|
|
|
|
|
+static int rand_ints_with_restricted_repeats(int element_cnt,int max_elements_needed,int arrsiz,int fullperms,int **pattern,dataptr dz);
|
|
|
|
|
+static int extract_rrr_env_from_sndfile(int paramno,dataptr dz);
|
|
|
|
|
+static void get_rrrenv_of_buffer(int samps_to_process,int envwindow_sampsize,float **envptr,float *buffer);
|
|
|
|
|
+static float getmaxsampr(int startsamp, int sampcnt,float *buffer);
|
|
|
|
|
+
|
|
|
|
|
+static int do_envgrain_write(int startsearch,int endsearch,int *last_total_samps_read,int *obufpos,dataptr dz);
|
|
|
|
|
+static int do_envgrain_zerowrite(int startsearch,int endsearch,int *obufpos,dataptr dz);
|
|
|
|
|
+static int do_envgrain_addwrite(int startsearch,int endsearch,int *last_total_samps_read,int *obufpos,dataptr dz);
|
|
|
|
|
+static int do_envgrain_zerowrite_dblbuf(int startsearch,int endsearch,int *obufpos,dataptr dz);
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_THE_GRAIN **********************/
|
|
|
|
|
+
|
|
|
|
|
+int do_the_grain(int ibufpos,int *graincnt,int bufno,int gapcnt,int *obufpos,int grainstart,
|
|
|
|
|
+int crosbuf,int chans,int *grainadjusted,double samptotime,
|
|
|
|
|
+int *is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int is_last_grain = FALSE;
|
|
|
|
|
+ int newgapcnt, orig_grainlen, new_grainlen;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ int halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int store_end;
|
|
|
|
|
+ static int init = 1;
|
|
|
|
|
+
|
|
|
|
|
+ switch(dz->process) {
|
|
|
|
|
+ case(GRAIN_COUNT):
|
|
|
|
|
+ (*graincnt)++;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_GET):
|
|
|
|
|
+ case(GRAIN_ALIGN):
|
|
|
|
|
+ if((exit_status = store_the_grain_time(grainstart,graincnt,crosbuf,samptotime,init,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ init = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REPITCH):
|
|
|
|
|
+ if((exit_status = repitching_process(ibufpos,bufno,grainstart,abs_halfsplice,halfsplice,graincnt,
|
|
|
|
|
+ obufpos,&orig_grainlen,&new_grainlen,grainadjusted,is_first_grain,is_last_grain,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = retrieve_upsplice_for_nextgrain(abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REMOTIF):
|
|
|
|
|
+ if((exit_status = repitching_and_retiming_process(ibufpos,bufno,grainstart,abs_halfsplice,halfsplice,graincnt,
|
|
|
|
|
+ obufpos,&orig_grainlen,&new_grainlen,grainadjusted,is_first_grain,is_last_grain,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = retrieve_upsplice_for_nextgrain(abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_RERHYTHM):
|
|
|
|
|
+ if((exit_status = do_rerhythm_grain
|
|
|
|
|
+ (ibufpos,graincnt,bufno,gapcnt,obufpos,grainstart,crosbuf,chans,grainadjusted,*is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_OMIT):
|
|
|
|
|
+ if((exit_status = keep_non_omitted_grains
|
|
|
|
|
+ (ibufpos,bufno,grainstart,graincnt,obufpos,crosbuf,chans,*is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REORDER):
|
|
|
|
|
+ if((exit_status = do_the_reordered_grains
|
|
|
|
|
+ (ibufpos,bufno,grainstart,graincnt,obufpos,crosbuf,chans,*is_first_grain,is_last_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_DUPLICATE):
|
|
|
|
|
+ if((exit_status = duplicate_grain
|
|
|
|
|
+ (ibufpos,bufno,gapcnt,obufpos,grainstart,crosbuf,chans,grainadjusted,*is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_TIMEWARP):
|
|
|
|
|
+ newgapcnt = round((double)(gapcnt/chans) * dz->param[GR_TSTRETCH]) * chans;
|
|
|
|
|
+ store_end = TRUE;
|
|
|
|
|
+ if((exit_status = retime_grain
|
|
|
|
|
+ (ibufpos,newgapcnt,grainstart,gapcnt,bufno,obufpos,chans,crosbuf,grainadjusted,store_end,*is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REVERSE):
|
|
|
|
|
+ if(*is_first_grain) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Searching for grains\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = save_abs_sampletime_of_grain(grainstart,graincnt,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_POSITION):
|
|
|
|
|
+ if((exit_status = synchronise_the_grain
|
|
|
|
|
+ (ibufpos,graincnt,bufno,gapcnt,obufpos,grainstart,crosbuf,chans,grainadjusted,*is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(exit_status!=CONTINUE)
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown case in do_the_grain()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *is_first_grain = FALSE;
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** STORE_THE_GRAIN_TIME **********************/
|
|
|
|
|
+
|
|
|
|
|
+int store_the_grain_time(int grainstart,int *graincnt,int crosbuf,double samptotime,int init,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int previous_total_ssampsread = dz->total_samps_read - dz->ssampsread;
|
|
|
|
|
+ int sampcnt = grainstart + previous_total_ssampsread;
|
|
|
|
|
+ if(init) {
|
|
|
|
|
+ if(*graincnt == 0) {
|
|
|
|
|
+ sprintf(errstr,"No grains found.\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[GR_SYNCTIME] = (double *)malloc(*graincnt * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to store sync times.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->iparam[GR_SYNCCNT] = *graincnt;
|
|
|
|
|
+ *graincnt = 0;
|
|
|
|
|
+ } else if(dz->parray[GR_SYNCTIME] == NULL) {
|
|
|
|
|
+ sprintf(errstr,"No grains found.\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ sampcnt -= dz->buflen;
|
|
|
|
|
+ dz->parray[GR_SYNCTIME][(*graincnt)++] = (double)sampcnt * samptotime;
|
|
|
|
|
+ if(*graincnt > dz->iparam[GR_SYNCCNT]) {
|
|
|
|
|
+ sprintf(errstr,"Error in memory asignment for storing grain times.\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* KEEP_NON_OMITTED_GRAINS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int keep_non_omitted_grains
|
|
|
|
|
+(int ibufpos,int bufno,int grainstart,int *graincnt,int *obufpos,int crosbuf,int chans,int is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int start_splice;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ int halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int splicestart_bufno = bufno;
|
|
|
|
|
+
|
|
|
|
|
+ /* Write previously stored up_splice to THIS grain */
|
|
|
|
|
+ if(*graincnt<dz->iparam[GR_KEEP] &&!is_first_grain) {
|
|
|
|
|
+ if((exit_status = read_up_halfsplice(obufpos,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ start_splice = ibufpos - abs_halfsplice; /* ALWAYS KEEP up_splice to NEXT grain */
|
|
|
|
|
+ if(start_splice < 0) {
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ start_splice += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_up_halfsplice(1,start_splice,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ if(*graincnt<dz->iparam[GR_KEEP]) {
|
|
|
|
|
+ start_splice -= abs_halfsplice;
|
|
|
|
|
+ if(start_splice < 0) {
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ start_splice += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_dn_halfsplice(start_splice,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = copy_start_of_grain(grainstart,start_splice,bufno,splicestart_bufno,obufpos,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = read_dn_halfsplice(obufpos,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(++(*graincnt)>=dz->iparam[GR_OUT_OF])
|
|
|
|
|
+ *graincnt = 0;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* DO_THE_REORDERED_GRAINS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_the_reordered_grains(int ibufpos,int bufno,int grainstart,int *graincnt,
|
|
|
|
|
+int *obufpos,int crosbuf,int chans,int is_first_grain,int is_last_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, m, k;
|
|
|
|
|
+ int len;
|
|
|
|
|
+ int abs_halfsplice = dz->iparam[GR_ABS_SPLICELEN]/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+
|
|
|
|
|
+ if(*graincnt > dz->iparam[GR_REOLEN]) { /* WE'RE BEYOND PERMUTE-SET: LOOKING AT GRAINS NOT USED */
|
|
|
|
|
+ if(*graincnt == dz->iparam[GR_REOSTEP]-1) { /* IF looking at very last unused grain */
|
|
|
|
|
+ if((exit_status = store_upsplice_of_next_grain(ibufpos,bufno,abs_halfsplice,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);/* store startsplice of nextgrain, found at end of final skipped grain */
|
|
|
|
|
+ *graincnt = -1; /* and reset grain counter to indicate end of skipped-over grains */
|
|
|
|
|
+ } /* Otherwise, completely ignore skipped over grain */
|
|
|
|
|
+
|
|
|
|
|
+ } else if(*graincnt == dz->iparam[GR_REOLEN]) { /* WE'VE REACHED THE END OF THE PERMUTABLE SET */
|
|
|
|
|
+ for(n=0;n<dz->iparam[GR_REOCNT];n++) {
|
|
|
|
|
+ k = dz->iparray[GR_REOSET][n]; /* write permuted set to outbuf */
|
|
|
|
|
+ len = dz->lparray[GR_THIS_LEN][k];
|
|
|
|
|
+ if((exit_status = copygrain_from_elsewhere(len,k,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->iparam[GR_REOSTEP] < dz->iparam[GR_REOLEN]) { /* IF NEXT PERMUTE SET BEGINS BEFORE END OF THIS */
|
|
|
|
|
+ for(n=0,m=dz->iparam[GR_REOSTEP];m < dz->iparam[GR_REOLEN];n++,m++)
|
|
|
|
|
+ swap_array_adresses_and_lens_for_reordr(n,m,dz); /* recycle the buffer storage */
|
|
|
|
|
+ *graincnt = dz->iparam[GR_REOLEN] - dz->iparam[GR_REOSTEP]; /* & reduce graincnt to no. of reused grains */
|
|
|
|
|
+ if((exit_status = put_grain_into_store(is_last_grain,ibufpos,bufno,grainstart,crosbuf,chans,*graincnt,dz))<0)
|
|
|
|
|
+ return(exit_status); /* Store the current grain */
|
|
|
|
|
+ } else if(dz->iparam[GR_REOSTEP] == dz->iparam[GR_REOLEN]) { /* IF IT BEGINS AT END OF THIS ONE */
|
|
|
|
|
+ *graincnt = 0; /* reset grain counter to zero, for next set */
|
|
|
|
|
+ if((exit_status = put_grain_into_store(is_last_grain,ibufpos,bufno,grainstart,crosbuf,chans,*graincnt,dz))<0)
|
|
|
|
|
+ return(exit_status); /* Store the current grain */
|
|
|
|
|
+ } else if (dz->iparam[GR_REOSTEP] == dz->iparam[GR_REOLEN]+1) {/* IF IT BEGINS AT 1st GRAIN BEYOND THIS SET */
|
|
|
|
|
+ if((exit_status = store_upsplice_of_next_grain(ibufpos,bufno,abs_halfsplice,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);/* store startsplice of nextgrain, found at end of final skipped grain */
|
|
|
|
|
+ *graincnt = -1; /* and reset grain counter to indicate end of skipped-over grains */
|
|
|
|
|
+ } /* IF IT BEGINS BEYOND THAT : DO NOTHING */
|
|
|
|
|
+
|
|
|
|
|
+ } else { /* WE'RE AT START OF, OR WITHIN, PERMUTABLE SET */
|
|
|
|
|
+ if(is_first_grain) {
|
|
|
|
|
+ if((exit_status = create_an_upsplice_from_pregrain_material(*obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status); /* Generate upsplice to 1st grain, of correct size */
|
|
|
|
|
+ memset((char *)dz->sampbuf[2],0,(size_t)dz->buflen * sizeof(float));
|
|
|
|
|
+ *obufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = put_grain_into_store(is_last_grain,ibufpos,bufno,grainstart,crosbuf,chans,*graincnt,dz))<0)
|
|
|
|
|
+ return(exit_status); /* Store the current grain */
|
|
|
|
|
+ }
|
|
|
|
|
+ (*graincnt)++;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*********************** SYNCHRONISE_THE_GRAIN ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int synchronise_the_grain(int ibufpos,int *graincnt,int bufno,int gapcnt,int *obufpos,
|
|
|
|
|
+int grainstart,int crosbuf,int chans,int *grainadjusted,int is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int newgapcnt;
|
|
|
|
|
+ int store_end = TRUE;
|
|
|
|
|
+ if(*graincnt >= dz->iparam[GR_SYNCCNT])
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ newgapcnt = round(dz->parray[GR_SYNCTIME][*graincnt]);
|
|
|
|
|
+ if(*graincnt==0) {
|
|
|
|
|
+ if((exit_status = retime_pre_firstgrain_material(newgapcnt,obufpos,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ (*graincnt)++;
|
|
|
|
|
+ }
|
|
|
|
|
+ newgapcnt = round(dz->parray[GR_SYNCTIME][*graincnt]);
|
|
|
|
|
+ if((exit_status = retime_grain(ibufpos,newgapcnt,grainstart,gapcnt,
|
|
|
|
|
+ bufno,obufpos,chans,crosbuf,grainadjusted,store_end,is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ (*graincnt)++;
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/************************* DEAL_WITH_LAST_GRAINS *************************/
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+int deal_with_last_grains
|
|
|
|
|
+(int ibufpos,int bufno,int *graincnt,int grainstart,int *grainadjusted,
|
|
|
|
|
+int *obufpos,int crosbuf,int chans,double samptotime,int *is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int is_last_grain = TRUE;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ int halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int n, start_splice, grainlen, orig_grainlen, new_grainlen;
|
|
|
|
|
+ int splicestart_bufno;
|
|
|
|
|
+ switch(dz->process) {
|
|
|
|
|
+ case(GRAIN_COUNT):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN])
|
|
|
|
|
+ (*graincnt)++;
|
|
|
|
|
+ sprintf(errstr,"%d grains found at this gate level.\n",*graincnt);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_GET):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = store_the_grain_time(grainstart,graincnt,crosbuf,samptotime,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n < *graincnt;n++)
|
|
|
|
|
+ fprintf(dz->fp,"%lf\n",dz->parray[GR_SYNCTIME][n]);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REVERSE):
|
|
|
|
|
+ if((exit_status = save_abs_sampletime_of_grain(grainstart,graincnt,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(*graincnt <= 1) {
|
|
|
|
|
+ sprintf(errstr,"No grains found.\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ fprintf(stdout,"INFO: Reversing grain order\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if((exit_status = do_the_reversing_process(*graincnt,obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_ALIGN):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = store_the_grain_time(grainstart,graincnt,crosbuf,samptotime,0,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->iparam[GR_SYNCCNT] != *graincnt)
|
|
|
|
|
+ dz->iparam[GR_SYNCCNT] = *graincnt;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REORDER):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = do_the_reordered_grains
|
|
|
|
|
+ (ibufpos,bufno,grainstart,graincnt,obufpos,crosbuf,chans,*is_first_grain,is_last_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = do_final_reorder_grains(*graincnt,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_RERHYTHM):
|
|
|
|
|
+ case(GRAIN_TIMEWARP):
|
|
|
|
|
+ case(GRAIN_POSITION):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = prepare_final_grain
|
|
|
|
|
+ (ibufpos,&start_splice,bufno,&splicestart_bufno,grainstart,&grainlen,crosbuf,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(exit_status==FINISHED)
|
|
|
|
|
+ break;
|
|
|
|
|
+ if((exit_status = output_final_grain
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+ (grainstart,start_splice,bufno,splicestart_bufno,*is_first_grain,obufpos,grainlen,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_OMIT):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]
|
|
|
|
|
+ && *graincnt<dz->iparam[GR_KEEP]) {
|
|
|
|
|
+ if((exit_status = prepare_final_grain
|
|
|
|
|
+ (ibufpos,&start_splice,bufno,&splicestart_bufno,grainstart,&grainlen,crosbuf,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(exit_status==FINISHED)
|
|
|
|
|
+ break;
|
|
|
|
|
+ if((exit_status = output_final_grain
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+ (grainstart,start_splice,bufno,splicestart_bufno,*is_first_grain,obufpos,grainlen,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_DUPLICATE):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = duplicate_last_grain
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+ (ibufpos,bufno,obufpos,grainstart,crosbuf,chans,*is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REPITCH):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = repitching_process(ibufpos,bufno,grainstart,abs_halfsplice,halfsplice,graincnt,
|
|
|
|
|
+ obufpos,&orig_grainlen,&new_grainlen,grainadjusted,is_first_grain,is_last_grain,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GRAIN_REMOTIF):
|
|
|
|
|
+ if(!dz->vflag[LOSE_LAST_GRAIN]) {
|
|
|
|
|
+ if((exit_status = repitching_and_retiming_process(ibufpos,bufno,grainstart,abs_halfsplice,halfsplice,graincnt,
|
|
|
|
|
+ obufpos,&orig_grainlen,&new_grainlen,grainadjusted,is_first_grain,is_last_grain,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown case in deal_with_last_grains()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* DO_FINAL_REORDER_GRAINS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_final_reorder_grains(int graincnt,int *obufpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, k;
|
|
|
|
|
+ int len;
|
|
|
|
|
+ if(graincnt > 0 && graincnt <= dz->iparam[GR_REOCNT]) { /* There are grains still to permute */
|
|
|
|
|
+ for(n=0;n<dz->iparam[GR_REOCNT];n++) {
|
|
|
|
|
+ if((k = dz->iparray[GR_REOSET][n])>=graincnt) /* If required grain doesn't exist, finish */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ len = dz->lparray[GR_THIS_LEN][k];
|
|
|
|
|
+ if((exit_status = copygrain_from_elsewhere(len,k,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* DO_RERHYTHM_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_rerhythm_grain(int ibufpos,int *graincnt,int bufno,int gapcnt,
|
|
|
|
|
+int *obufpos,int grainstart,int crosbuf,int chans,int *grainadjusted,int is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int newgapcnt, n;
|
|
|
|
|
+ int store_end;
|
|
|
|
|
+ double *ratio = dz->parray[GR_RATIO];
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(GR_NO_REPEATS):
|
|
|
|
|
+ store_end = TRUE;
|
|
|
|
|
+ newgapcnt = round((double)(gapcnt/chans) * ratio[*graincnt]) * chans;
|
|
|
|
|
+ if((exit_status = retime_grain
|
|
|
|
|
+ (ibufpos,newgapcnt,grainstart,gapcnt,bufno,obufpos,chans,crosbuf,grainadjusted,store_end,is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(++(*graincnt)>=dz->iparam[GR_RATIOCNT])
|
|
|
|
|
+ *graincnt = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GR_REPEATS):
|
|
|
|
|
+ store_end = FALSE;
|
|
|
|
|
+ if(is_first_grain && dz->iparam[GR_RATIOCNT]>1) {
|
|
|
|
|
+ if((exit_status = create_an_upsplice_from_pregrain_material(*obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0; n<dz->iparam[GR_RATIOCNT]-1; n++) {
|
|
|
|
|
+ newgapcnt = round((double)(gapcnt/chans) * ratio[n]) * chans;
|
|
|
|
|
+ if((exit_status = retime_grain
|
|
|
|
|
+ (ibufpos,newgapcnt,grainstart,gapcnt,bufno,obufpos,chans,crosbuf,grainadjusted,store_end,is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ is_first_grain = FALSE;
|
|
|
|
|
+ }
|
|
|
|
|
+ store_end = TRUE;
|
|
|
|
|
+ newgapcnt = round((double)(gapcnt/chans) * ratio[n]) * chans;
|
|
|
|
|
+ if((exit_status = retime_grain
|
|
|
|
|
+ (ibufpos,newgapcnt,grainstart,gapcnt,bufno,obufpos,chans,crosbuf,grainadjusted,store_end,is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown case in do_rerhythm_grain()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* DUPLICATE_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+int duplicate_grain(int ibufpos,int bufno,int gapcnt,int *obufpos,int grainstart,
|
|
|
|
|
+int crosbuf,int chans,int *grainadjusted,int is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int newgapcnt = gapcnt, n;
|
|
|
|
|
+ int store_end = FALSE;
|
|
|
|
|
+ int dupl = (int)dz->iparam[GR_DUPLS];
|
|
|
|
|
+ if(is_first_grain && dupl>1) {
|
|
|
|
|
+ if((exit_status = create_an_upsplice_from_pregrain_material(*obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0; n<dupl-1; n++) {
|
|
|
|
|
+ if((exit_status = retime_grain
|
|
|
|
|
+ (ibufpos,newgapcnt,grainstart,gapcnt,bufno,obufpos,chans,crosbuf,grainadjusted,store_end,is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ is_first_grain = FALSE;
|
|
|
|
|
+ }
|
|
|
|
|
+ store_end = TRUE;
|
|
|
|
|
+ if((exit_status = retime_grain
|
|
|
|
|
+ (ibufpos,newgapcnt,grainstart,gapcnt,bufno,obufpos,chans,crosbuf,grainadjusted,store_end,is_first_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* DUPLICATE_LAST_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+int duplicate_last_grain(int ibufpos,int bufno,int *obufpos,int grainstart,
|
|
|
|
|
+int crosbuf,int chans,int is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int /*newgapcnt = gapcnt,*/ n;
|
|
|
|
|
+ /*int store_end = FALSE;*/
|
|
|
|
|
+ int start_splice, grainlen;
|
|
|
|
|
+ int splicestart_bufno;
|
|
|
|
|
+ int dupl = (int)dz->iparam[GR_DUPLS];
|
|
|
|
|
+ if(is_first_grain && dupl>1) {
|
|
|
|
|
+ if((exit_status = create_an_upsplice_from_pregrain_material(*obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = prepare_final_grain
|
|
|
|
|
+ (ibufpos,&start_splice,bufno,&splicestart_bufno,grainstart,&grainlen,crosbuf,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(exit_status==FINISHED)
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ for(n=0; n<dupl; n++) {
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+ if((exit_status = output_final_grain
|
|
|
|
|
+ (grainstart,start_splice,bufno,splicestart_bufno,is_first_grain,obufpos,grainlen,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ is_first_grain = FALSE;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** COPYGRAIN_FROM_ELSEWHERE ******************************/
|
|
|
|
|
+
|
|
|
|
|
+int copygrain_from_elsewhere(int len,int k,int *obufposition,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ register int n, obufpos = *obufposition;
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ float *buf = dz->extrabuf[k+SPLBUF_OFFSET];
|
|
|
|
|
+ for(n=0;n<len;n++) {
|
|
|
|
|
+ obuf[obufpos++] = buf[n];
|
|
|
|
|
+ if(obufpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ obufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufposition = obufpos;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* SWAP_ARRAY_ADRESSES_AND_LENS_FOR_REORDR *************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * The arrays still needed are now pointed to by the lower-indexed lparrays.
|
|
|
|
|
+ * The arrays NO intER required get swapped, to be pointed to by the higher-indexed lparrays,
|
|
|
|
|
+ * hence are overwritten as the process proceeds.
|
|
|
|
|
+ *
|
|
|
|
|
+ * This works (I hope) even where an index is swapped over more than once!!
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+void swap_array_adresses_and_lens_for_reordr(int n,int m,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n_bufno = n + SPLBUF_OFFSET;
|
|
|
|
|
+ int m_bufno = m + SPLBUF_OFFSET;
|
|
|
|
|
+ float *tempadr = dz->extrabuf[n_bufno];
|
|
|
|
|
+ int temp_arraylen = dz->lparray[GR_ARRAYLEN][n];
|
|
|
|
|
+ int templen = dz->lparray[GR_THIS_LEN][n];
|
|
|
|
|
+ dz->extrabuf[n_bufno] = dz->extrabuf[m_bufno];
|
|
|
|
|
+ dz->extrabuf[m_bufno] = tempadr;
|
|
|
|
|
+ dz->lparray[GR_ARRAYLEN][n] = dz->lparray[GR_ARRAYLEN][m];
|
|
|
|
|
+ dz->lparray[GR_ARRAYLEN][m] = temp_arraylen;
|
|
|
|
|
+ dz->lparray[GR_THIS_LEN][n] = dz->lparray[GR_THIS_LEN][m];
|
|
|
|
|
+ dz->lparray[GR_THIS_LEN][m] = templen;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* COPY_GRAIN_TO_BUF *************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_grain_to_buf(int ibufpos,int bufno,int grainstart,int crosbuf,int chans,int storeno,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int grainlen = ibufpos - grainstart;
|
|
|
|
|
+ int storepos = 0, mid_grainlen;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2;
|
|
|
|
|
+ int halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int splicestart;
|
|
|
|
|
+ int grainbufno = storeno + SPLBUF_OFFSET;
|
|
|
|
|
+ int splicestart_bufno = bufno;
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ grainlen += dz->buflen;
|
|
|
|
|
+ if(grainlen > dz->lparray[GR_ARRAYLEN][storeno]) {
|
|
|
|
|
+ if((dz->extrabuf[grainbufno] = (float *)realloc(dz->extrabuf[grainbufno],grainlen * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to enlarge grain store.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->lparray[GR_ARRAYLEN][storeno] = grainlen;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->lparray[GR_THIS_LEN][storeno] = grainlen;
|
|
|
|
|
+ if((exit_status = copy_up_halfsplice_to_grainstore(abs_halfsplice,grainbufno,grainlen,&storepos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ splicestart = ibufpos - abs_halfsplice;
|
|
|
|
|
+ if(splicestart < 0) {
|
|
|
|
|
+ splicestart += dz->buflen;
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_up_halfsplice(1,splicestart,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ splicestart -= abs_halfsplice;
|
|
|
|
|
+ if(splicestart < 0) {
|
|
|
|
|
+ splicestart += dz->buflen;
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_dn_halfsplice(splicestart,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ mid_grainlen = grainlen - dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ if((exit_status = copy_midgrain_to_store(mid_grainlen,bufno,grainlen,grainstart,&storepos,crosbuf,grainbufno,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = copy_dn_halfsplice_to_grainstore(abs_halfsplice,grainbufno,grainlen,storepos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* COPY_LAST_GRAIN_TO_BUF *************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_last_grain_to_buf(int ibufpos,int bufno,int grainstart,int crosbuf,int chans,int storeno,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int storepos = 0, mid_grainlen;
|
|
|
|
|
+ int splicelen, abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2;
|
|
|
|
|
+ int splicestart;
|
|
|
|
|
+ int splicestart_bufno = bufno;
|
|
|
|
|
+ int grainbufno = storeno + SPLBUF_OFFSET;
|
|
|
|
|
+ int storelen;
|
|
|
|
|
+ int grainlen = ibufpos - grainstart;
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ grainlen += dz->buflen;
|
|
|
|
|
+ if((storelen = grainlen + abs_halfsplice)<abs_splicelen)
|
|
|
|
|
+ storelen = abs_splicelen; /* grainstore must store up_hsplice & dn_hsplice even if grain to short */
|
|
|
|
|
+ if(storelen > dz->lparray[GR_ARRAYLEN][storeno]) {
|
|
|
|
|
+ if((dz->extrabuf[grainbufno] = (float *)realloc(dz->extrabuf[grainbufno],storelen * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to enlarge grain store.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->lparray[GR_ARRAYLEN][storeno] = storelen;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->lparray[GR_THIS_LEN][storeno] = storelen;
|
|
|
|
|
+ if((exit_status = copy_up_halfsplice_to_grainstore(abs_halfsplice,grainbufno,storelen,&storepos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ if((mid_grainlen = grainlen - abs_halfsplice) < 0)
|
|
|
|
|
+ mid_grainlen = 0; /* HENCE mid_grainlen >= 0 */
|
|
|
|
|
+
|
|
|
|
|
+ abs_splicelen = min(grainlen,abs_halfsplice);
|
|
|
|
|
+ splicelen = abs_splicelen/chans;
|
|
|
|
|
+ /* HENCE abs_splicelen <= grainlen */
|
|
|
|
|
+ splicestart = ibufpos - abs_splicelen; /* splicestart >= grainstart, BECAUSE abs_splicelen <= grainlen */
|
|
|
|
|
+ if(splicestart < 0) {
|
|
|
|
|
+ splicestart += dz->buflen;
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_dn_halfsplice(splicestart,splicestart_bufno,chans,splicelen,dz))<0)
|
|
|
|
|
+ return(exit_status); /* forces an abs_halfsplice length unit, regardless of input splicelen */
|
|
|
|
|
+ if(mid_grainlen > 0) {
|
|
|
|
|
+ if((exit_status =
|
|
|
|
|
+ copy_midgrain_to_store(mid_grainlen,bufno,storelen,grainstart,&storepos,crosbuf,grainbufno,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = copy_dn_halfsplice_to_grainstore(abs_halfsplice,grainbufno,storelen,storepos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************ RETIME_PRE_FIRSTGRAIN_MATERIAL ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int retime_pre_firstgrain_material
|
|
|
|
|
+(int new_grainstart,int *obufposition,int chans,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ /*float *b = dz->sampbuf[bufno];*/ /* RWD: not used */
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ int excess, n, k;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ int obufpos = *obufposition;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN]/2;
|
|
|
|
|
+ int splicelen = abs_splicelen/chans;
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ sprintf(errstr,"1st grain starts beyond end of sound buffer: Can't proceed.\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ excess = new_grainstart - obufpos;
|
|
|
|
|
+ if(excess > 0) {
|
|
|
|
|
+ memmove((char *)dz->extrabuf[2],(char *)obuf,(size_t)dz->buflen * sizeof(float));
|
|
|
|
|
+ if(excess >= dz->buflen) {
|
|
|
|
|
+ memset((char *)obuf,0,(size_t)dz->buflen * sizeof(float));
|
|
|
|
|
+ while(excess >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ excess -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<excess;n++)
|
|
|
|
|
+ obuf[n] = 0;
|
|
|
|
|
+ for(m=0;m < obufpos;m++) {
|
|
|
|
|
+ obuf[n++] = dz->extrabuf[2][m];
|
|
|
|
|
+ if(n >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ new_grainstart = n;
|
|
|
|
|
+ } else if(excess < 0) {
|
|
|
|
|
+ for(n=0, m = excess; n < new_grainstart; n++, m++)
|
|
|
|
|
+ obuf[n] = obuf[m]; /* Move data backwards */
|
|
|
|
|
+ while(n < obufpos)
|
|
|
|
|
+ obuf[n++] = 0; /* rezero samples beyond new_grainstart */
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ for(n=0;n<splicelen;n++) { /* Put splice on start of file */
|
|
|
|
|
+ for(m=0;m<chans;m++) {
|
|
|
|
|
+ obuf[k] = (float) /*round*/ ((double)obuf[k] * splicetab[n]);
|
|
|
|
|
+ k++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ sprintf(errstr,"Buffer accounting problem: retime_pre_firstgrain_material()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufposition = new_grainstart; /* reset obuf pointer to (new) END of pre-grain material */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* OUTPUT_GRAIN_LINK *************************/
|
|
|
|
|
+
|
|
|
|
|
+int output_grain_link(int thisgap,int abs_halfsplice,int *obufposition,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, m;
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ int obufpos = *obufposition;
|
|
|
|
|
+ for(n = 0, m = -(thisgap - abs_halfsplice); n < thisgap; n++,m++) {
|
|
|
|
|
+ if(n < abs_halfsplice)
|
|
|
|
|
+ obuf[obufpos] = dz->extrabuf[0][n];
|
|
|
|
|
+ else
|
|
|
|
|
+ obuf[obufpos] = 0;
|
|
|
|
|
+ if(++obufpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ obufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufposition = obufpos;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* COPY_START_OF_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_start_of_grain
|
|
|
|
|
+(int grainstart,int start_splice,int bufno,int splicestart_bufno,int *obufpos,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ if(splicestart_bufno != bufno) {
|
|
|
|
|
+ if((exit_status = copygrain(grainstart,start_splice,!bufno,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = crosbuf_grain_type3(grainstart,start_splice,bufno,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = copygrain(grainstart,start_splice,bufno,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** PREPARE_FINAL_GRAIN ******************************/
|
|
|
|
|
+
|
|
|
|
|
+int prepare_final_grain(int ibufpos,int *start_splice,int bufno,int *splicestart_bufno,
|
|
|
|
|
+int grainstart,int *grainlen,int crosbuf,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ int halfsplice = abs_halfsplice/chans;
|
|
|
|
|
+ *grainlen = ibufpos - grainstart;
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ *grainlen += dz->buflen;
|
|
|
|
|
+ if(*grainlen < abs_splicelen) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Final grain omitted: too short\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ *start_splice = ibufpos - abs_halfsplice;
|
|
|
|
|
+ *splicestart_bufno = bufno;
|
|
|
|
|
+ if(*start_splice < 0) {
|
|
|
|
|
+ *splicestart_bufno = !bufno;
|
|
|
|
|
+ *start_splice += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_dn_halfsplice(*start_splice,*splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** OUTPUT_FINAL_GRAIN ******************************/
|
|
|
|
|
+
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+int output_final_grain(int grainstart,int start_splice,int bufno,int splicestart_bufno,int is_first_grain,
|
|
|
|
|
+int *obufpos,int grainlen,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ if(!is_first_grain) {
|
|
|
|
|
+ if((exit_status = read_up_halfsplice(obufpos,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(grainlen > 0) {
|
|
|
|
|
+ if((exit_status = copy_start_of_grain(grainstart,start_splice,bufno,splicestart_bufno,obufpos,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_dn_halfsplice(obufpos,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** READ_DN_HALFSPLICE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int read_dn_halfsplice(int *obufposition,int len,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, j = 0;
|
|
|
|
|
+ float *b = dz->extrabuf[0];
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ int obufpos = *obufposition;
|
|
|
|
|
+ for(n=0;n < len;n++) {
|
|
|
|
|
+ obuf[obufpos++] = b[j++];
|
|
|
|
|
+ if(obufpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ obufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufposition = obufpos;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** READ_UP_HALFSPLICE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int read_up_halfsplice(int *obufposition,int len,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, j = 0;
|
|
|
|
|
+ float *b = dz->extrabuf[1];
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ int obufpos = *obufposition;
|
|
|
|
|
+ for(n=0;n < len;n++) {
|
|
|
|
|
+ obuf[obufpos++] = b[j++];
|
|
|
|
|
+ if(obufpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ obufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufposition = obufpos;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** COPY_UP_HALFSPLICE_TO_GRAINSTORE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_up_halfsplice_to_grainstore(int len,int storeno,int storelen,int *storepos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ char *goaladdress = (char *)dz->extrabuf[storeno];
|
|
|
|
|
+ if(len > storelen) {
|
|
|
|
|
+ sprintf(errstr,"Buffer anomaly: copy_up_halfsplice_to_grainstore()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ memmove(goaladdress,(char *)dz->extrabuf[1],len * sizeof(float));
|
|
|
|
|
+ *storepos = len;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** COPY_DN_HALFSPLICE_TO_GRAINSTORE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_dn_halfsplice_to_grainstore(int len,int storeno,int storelen,int storepos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ char *goaladdress = (char *)(dz->extrabuf[storeno] + storepos);
|
|
|
|
|
+ if(storepos + len > storelen) {
|
|
|
|
|
+ sprintf(errstr,"Buffer anomaly: copy_dn_halfsplice_to_grainstore()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ memmove(goaladdress,(char *)dz->extrabuf[0],len * sizeof(float));
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** CREATE_AN_UPSPLICE_FROM_PREGRAIN_MATERIAL ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int create_an_upsplice_from_pregrain_material(int obufpos,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, k;
|
|
|
|
|
+ int m, j = 0, empty_space;
|
|
|
|
|
+ double ratio;
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ float *splicebuf = dz->extrabuf[1];
|
|
|
|
|
+ int abs_halfsplice = dz->iparam[GR_ABS_SPLICELEN]/2;
|
|
|
|
|
+ int halfsplice = abs_halfsplice/chans;
|
|
|
|
|
+ int splicelen;
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ if(obufpos >= abs_halfsplice) {
|
|
|
|
|
+ k = obufpos - abs_halfsplice;
|
|
|
|
|
+ for(n=0;n<halfsplice;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ splicebuf[j++] = (float) /*round*/ ((double)obuf[k++] * splicetab[n]);
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ sprintf(errstr,"Error in buffer accounting: create_an_upsplice_from_pregrain_material()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ splicelen = obufpos/chans;
|
|
|
|
|
+ empty_space = abs_halfsplice - obufpos;
|
|
|
|
|
+ for(n=0;n<empty_space;n++)
|
|
|
|
|
+ splicebuf[j++] = 0;
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ for(n=0;n<splicelen;n++) {
|
|
|
|
|
+ ratio = (double)n/(double)splicelen;
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ splicebuf[j++] = (float) /*round*/ ((double)obuf[k++] * ratio);
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ sprintf(errstr,"Error in buffer accounting: create_an_upsplice_from_pregrain_material()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* RETIME_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+int retime_grain(int ibufpos,int thisgap,int grainstart,int origgap,int bufno,
|
|
|
|
|
+int *obufpos,int chans,int crosbuf,int *grainadjusted,int store_end,int is_first_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int grainend, start_splice, gapchange;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ int halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int splicestart_bufno = bufno;
|
|
|
|
|
+
|
|
|
|
|
+ start_splice = ibufpos - abs_halfsplice;
|
|
|
|
|
+ if(start_splice < 0) {
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ start_splice += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!is_first_grain) {
|
|
|
|
|
+ if((exit_status = read_up_halfsplice(obufpos,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(store_end) {
|
|
|
|
|
+ if((exit_status = store_up_halfsplice(1,start_splice,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((gapchange = thisgap - origgap)>=0) {
|
|
|
|
|
+ start_splice -= abs_halfsplice;
|
|
|
|
|
+ if(start_splice < 0) {
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ start_splice += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_dn_halfsplice(start_splice,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = copy_start_of_grain(grainstart,start_splice,bufno,splicestart_bufno,obufpos,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = output_grain_link(abs_halfsplice+gapchange,abs_halfsplice,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if(thisgap < dz->iparam[GR_ABS_SPLICEX2]) {
|
|
|
|
|
+ grainend = grainstart + dz->iparam[GR_ABS_SPLICEX2];
|
|
|
|
|
+ (*grainadjusted)++;
|
|
|
|
|
+ } else
|
|
|
|
|
+ grainend = grainstart + thisgap;
|
|
|
|
|
+ start_splice = grainend - abs_splicelen; /* NB Ensures 1 grain stops before other starts */
|
|
|
|
|
+ splicestart_bufno = bufno;
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ if(start_splice >= dz->buflen)
|
|
|
|
|
+ start_splice -= dz->buflen;
|
|
|
|
|
+ else
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = store_dn_halfsplice(start_splice,splicestart_bufno,chans,halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = copy_start_of_grain(grainstart,start_splice,bufno,splicestart_bufno,obufpos,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = output_grain_link(abs_halfsplice,abs_halfsplice,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** STORE_UP_HALFSPLICE ***************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * GIVE IT bufno where splice STARTS!!!
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int store_up_halfsplice(int storeno,int start,int bufno,int chans,int splicelen,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, remain;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ float *b = dz->sampbuf[bufno];
|
|
|
|
|
+ float *obuf = dz->extrabuf[storeno];
|
|
|
|
|
+ int k = start, j = 0;
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ int true_halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ if((remain = true_halfsplice - splicelen)<0) {
|
|
|
|
|
+ sprintf(errstr,"Invalid splicelen in store_up_halfsplice()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ } else if(remain==0) {
|
|
|
|
|
+ for(n=0;n<splicelen;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/ ((double)b[k++] * splicetab[n]);
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ b = dz->sampbuf[!bufno];
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(n=0;n<remain;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = 0.0;
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<splicelen;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/ ((double)(b[k++] * n)/(double)splicelen);
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ b = dz->sampbuf[!bufno];
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** STORE_DN_HALFSPLICE ***************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * GIVE IT bufno where splice STARTS!!!
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int store_dn_halfsplice(int start,int bufno,int chans,int splicelen,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, k = start, j = 0;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ float *b = dz->sampbuf[bufno];
|
|
|
|
|
+ float *obuf = dz->extrabuf[0];
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ int true_halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int remain = true_halfsplice - splicelen;
|
|
|
|
|
+ if(remain < 0) {
|
|
|
|
|
+ sprintf(errstr,"Invalid splicelen: store_dn_halfsplice()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ } else if(remain==0) {
|
|
|
|
|
+ for(n=splicelen-1;n>=0;n--) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/ ((double)b[k++] * splicetab[n]);
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ b = dz->sampbuf[!bufno];
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(n=splicelen-1;n>=0;n--) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/ ((double)(b[k++] * n)/(double)splicelen);
|
|
|
|
|
+ if(k >= dz->buflen) {
|
|
|
|
|
+ b = dz->sampbuf[!bufno];
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<remain;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = 0.0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** COPY_MIDGRAIN_TO_STORE ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_midgrain_to_store
|
|
|
|
|
+(int mid_grainlen,int bufno,int storelen,int grainstart,int *storepos,int crosbuf,int storeno,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ float *b, *b2;
|
|
|
|
|
+ int /* j = *storepos,*/ partbuf, partbuf_samps;
|
|
|
|
|
+ if(mid_grainlen + *storepos > storelen) {
|
|
|
|
|
+ sprintf(errstr,"Buffer anomaly: copy_midgrain_to_store()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ if(grainstart + mid_grainlen <= dz->buflen) {
|
|
|
|
|
+ b2 = dz->sampbuf[!bufno] + grainstart;
|
|
|
|
|
+ b = dz->extrabuf[storeno] + *storepos;
|
|
|
|
|
+ memmove((char *)b,(char *)b2,mid_grainlen * sizeof(float));
|
|
|
|
|
+ *storepos += mid_grainlen;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ partbuf = dz->buflen - grainstart;
|
|
|
|
|
+ partbuf_samps = partbuf;
|
|
|
|
|
+ b2 = dz->sampbuf[!bufno] + grainstart;
|
|
|
|
|
+ b = dz->extrabuf[storeno] + *storepos;
|
|
|
|
|
+ memmove((char *)b,(char *)b2,partbuf_samps * sizeof(float));
|
|
|
|
|
+ *storepos += partbuf;
|
|
|
|
|
+ partbuf = mid_grainlen - partbuf;
|
|
|
|
|
+ partbuf_samps = partbuf;
|
|
|
|
|
+ b2 = dz->sampbuf[bufno];
|
|
|
|
|
+ b = dz->extrabuf[storeno] + *storepos;
|
|
|
|
|
+ memmove((char *)b,(char *)b2, partbuf_samps * sizeof(float));
|
|
|
|
|
+ *storepos += partbuf;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ b2 = dz->sampbuf[bufno] + grainstart;
|
|
|
|
|
+ b = dz->extrabuf[storeno] + *storepos;
|
|
|
|
|
+ memmove((char *)b,(char *)b2,mid_grainlen * sizeof(float));
|
|
|
|
|
+ *storepos += mid_grainlen;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** STORE_UPSPLICE_OF_NEXT_GRAIN ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int store_upsplice_of_next_grain(int ibufpos,int bufno,int abs_halfsplice,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int splicestart_bufno = bufno;
|
|
|
|
|
+ int halfsplice = abs_halfsplice/chans;
|
|
|
|
|
+ int splicestart = ibufpos - abs_halfsplice;
|
|
|
|
|
+ if(splicestart < 0) {
|
|
|
|
|
+ splicestart += dz->buflen;
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ }
|
|
|
|
|
+ return store_up_halfsplice(1,splicestart,splicestart_bufno,chans,halfsplice,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/**************************** PUT_GRAIN_INTO_STORE ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int put_grain_into_store
|
|
|
|
|
+(int is_last_grain,int ibufpos,int bufno,int grainstart,int crosbuf,int chans,int graincnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ if(is_last_grain)
|
|
|
|
|
+ return copy_last_grain_to_buf(ibufpos,bufno,grainstart,crosbuf,chans,graincnt,dz);
|
|
|
|
|
+ return copy_grain_to_buf(ibufpos,bufno,grainstart,crosbuf,chans,graincnt,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** SAVE_ABS_SAMPLETIME_OF_GRAIN ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int save_abs_sampletime_of_grain(int grainstart,int *graincnt,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int samps_read_before_thisbuf = dz->total_samps_read - dz->ssampsread;
|
|
|
|
|
+ dz->lparray[GR_ABS_POS][*graincnt] = grainstart + samps_read_before_thisbuf;
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ dz->lparray[GR_ABS_POS][*graincnt] -= dz->buflen;
|
|
|
|
|
+ (*graincnt)++;
|
|
|
|
|
+ if(*graincnt >= dz->iparam[GR_ARRAYSIZE]) {
|
|
|
|
|
+ dz->iparam[GR_ARRAYSIZE] += BIGARRAY;
|
|
|
|
|
+ if((dz->lparray[GR_ABS_POS] =
|
|
|
|
|
+ (int *)realloc(dz->lparray[GR_ABS_POS],dz->iparam[GR_ARRAYSIZE] * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to enlarge positions store.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** DO_THE_REVERSING_PROCESS ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_the_reversing_process(int graincnt,int *obufposition,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int obufpos = 0, seeksamps = 0, n, seekbufs = 0;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2;
|
|
|
|
|
+ int halfsplice = abs_halfsplice/chans;
|
|
|
|
|
+ int *grainpos;
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = insert_EOF_sampletime_in_samptime_list(graincnt,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ grainpos = dz->lparray[GR_ABS_POS];
|
|
|
|
|
+ for(n=0;n<graincnt;n++) /* adjust all grain-times to include start of splice */
|
|
|
|
|
+ grainpos[n] -= abs_halfsplice;
|
|
|
|
|
+ adjust_for_last_grain(&graincnt,grainpos,dz);
|
|
|
|
|
+ if((exit_status = clear_outbuf(dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+//TW UPDATE
|
|
|
|
|
+/* AUGUST 2002 : go back to start of source and read first buffer (to reset dz->ssampsread) */
|
|
|
|
|
+ if(sndseekEx(dz->ifd[0],0,0) < 0) {
|
|
|
|
|
+ sprintf(errstr,"seek error at start of do_the_reversing_process()\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = do_seek_and_read(&seekbufs,&seeksamps,graincnt-1,dz))<0)
|
|
|
|
|
+ return(exit_status); /* seek to a buffer containing (WHOLE) final grain */
|
|
|
|
|
+ for(n=graincnt-1;n>=0;n--) {
|
|
|
|
|
+ if((exit_status = output_whole_grain
|
|
|
|
|
+ (n,&obufpos,&seeksamps,&seekbufs,halfsplice,abs_splicelen,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufposition = obufpos;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** DO_SEEK_AND_READ ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_seek_and_read(int *seekbufs,int *seeksamps,int grainno,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int new_seekbufs = dz->lparray[GR_ABS_POS][grainno]/dz->buflen;
|
|
|
|
|
+ if(new_seekbufs != *seekbufs) {
|
|
|
|
|
+ *seekbufs = new_seekbufs;
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],(*seekbufs) * dz->buflen,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error in do_seek_and_read()\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *seeksamps = *seekbufs * dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** OUTPUT_UP_HALFSPLICE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int output_up_halfsplice(int *ibufpos,int *obufpos,int chans,int splicelen,int *crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, remain;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ float *b = dz->sampbuf[0];
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ int i = *ibufpos;
|
|
|
|
|
+ int j = *obufpos;
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ int true_halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ if((remain = true_halfsplice - splicelen)<0) {
|
|
|
|
|
+ sprintf(errstr,"Invalid splicelen in output_up_halfsplice()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ } else if(remain==0) {
|
|
|
|
|
+ for(n=0;n<splicelen;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/((double)b[i++] * splicetab[n]);
|
|
|
|
|
+ if((exit_status = test_buffer_overflows(obuf,&j,&i,n,splicelen-1,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(n=0;n<remain;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = 0;
|
|
|
|
|
+ if(j >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<splicelen;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/ ((double)(b[i++] * n)/(double)splicelen);
|
|
|
|
|
+ if((exit_status = test_buffer_overflows(obuf,&j,&i,n,splicelen-1,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *ibufpos = i;
|
|
|
|
|
+ *obufpos = j;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** OUTPUT_DN_HALFSPLICE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int output_dn_halfsplice(int *ibufpos,int *obufpos,int chans,int splicelen,int *crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, k, remain;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ float *b = dz->sampbuf[0];
|
|
|
|
|
+ float *obuf = dz->sampbuf[2];
|
|
|
|
|
+ int i = *ibufpos;
|
|
|
|
|
+ int j = *obufpos;
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ int true_halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ if((remain = true_halfsplice - splicelen)<0) {
|
|
|
|
|
+ sprintf(errstr,"Invalid splicelen in output_dn_halfsplice()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ } else if(remain==0) {
|
|
|
|
|
+ for(n=splicelen-1,k=0;n>=0;n--,k++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round */((double)b[i++] * splicetab[n]);
|
|
|
|
|
+ if((exit_status = test_buffer_overflows(obuf,&j,&i,k,splicelen-1,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(n=splicelen-1,k=0;n>=0;n--,k++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = (float) /*round*/ ((double)(b[i++] * n)/(double)splicelen);
|
|
|
|
|
+ if((exit_status = test_buffer_overflows(obuf,&j,&i,k,splicelen-1,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<remain;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = 0;
|
|
|
|
|
+ if(j >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *ibufpos = i;
|
|
|
|
|
+ *obufpos = j;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** DO_IN_SITU_HALFSPLICE_ON_STORED_GRAIN ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int do_in_situ_halfsplice_on_stored_grain(int bufpos,int chans,int splicelen,int grainstorelen,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, k, remain;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ float *obuf = dz->extrabuf[2];
|
|
|
|
|
+ double *splicetab = dz->parray[GR_SPLICETAB];
|
|
|
|
|
+ int true_halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+ int abs_halfsplice = true_halfsplice * chans;
|
|
|
|
|
+ if(bufpos + abs_halfsplice > grainstorelen) {
|
|
|
|
|
+ sprintf(errstr,"Grainstore buffer overflow: do_in_situ_halfsplice_on_stored_grain()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((remain = true_halfsplice - splicelen)<0) {
|
|
|
|
|
+ sprintf(errstr,"Invalid splicelen in do_in_situ_halfsplice_on_stored_grain()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ } else if(remain==0) {
|
|
|
|
|
+ for(n=splicelen-1,k=0;n>=0;n--,k++) {
|
|
|
|
|
+ for(m=0;m<chans;m++) {
|
|
|
|
|
+ obuf[bufpos] = (float) /*round*/((double)obuf[bufpos] * splicetab[n]);
|
|
|
|
|
+ bufpos++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(n=splicelen-1,k=0;n>=0;n--,k++) {
|
|
|
|
|
+ for(m=0;m<chans;m++) {
|
|
|
|
|
+ obuf[bufpos] = (float) /*round*/ ((double)(obuf[bufpos] * n)/(double)splicelen);
|
|
|
|
|
+ bufpos++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=0;n<remain;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[bufpos++] = 0.0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** TEST_BUFFER_OVERFLOWS ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int test_buffer_overflows(float *obuf,int *obufpos,int *ibufpos,int n,int maxlen,int *crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ if(*obufpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *obufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(*ibufpos >= dz->ssampsread && n < maxlen) {
|
|
|
|
|
+ if(*crosbuf) {
|
|
|
|
|
+ sprintf(errstr,"double crosbuf: test_buffer_overflows()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *crosbuf = TRUE;
|
|
|
|
|
+ *ibufpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** COPY_MIDGRAIN_TO_OUTPUT ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int copy_midgrain_to_output(int mid_grainlen,int *ibufpos,int *obufpos,int *crosbuf,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ float *b = dz->sampbuf[0], *obuf = dz->sampbuf[2];
|
|
|
|
|
+ int i = *ibufpos;
|
|
|
|
|
+ int j = *obufpos;
|
|
|
|
|
+ mid_grainlen /= chans;
|
|
|
|
|
+ for(n=0; n<mid_grainlen;n++) {
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ obuf[j++] = b[i++];
|
|
|
|
|
+ if((exit_status = test_buffer_overflows(obuf,&j,&i,n,mid_grainlen-1,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufpos = j;
|
|
|
|
|
+ *ibufpos = i;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** INSERT_EOF_SAMPLETIME_IN_SAMPTIME_LIST ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int insert_EOF_sampletime_in_samptime_list(int graincnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ if(graincnt+1 > dz->iparam[GR_ARRAYSIZE]) {
|
|
|
|
|
+ if((dz->lparray[GR_ABS_POS] =
|
|
|
|
|
+ (int *)realloc(dz->lparray[GR_ABS_POS],(graincnt+1) * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to enlarge positions store.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->lparray[GR_ABS_POS][graincnt] = dz->insams[0];
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** ADJUST_FOR_LAST_GRAIN ***************************/
|
|
|
|
|
+
|
|
|
|
|
+void adjust_for_last_grain(int *graincnt,int *grainpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int lastgap;
|
|
|
|
|
+ if(dz->vflag[LOSE_LAST_GRAIN]) /* get rid of last grain if flagged */
|
|
|
|
|
+ (*graincnt)--;
|
|
|
|
|
+ else if((lastgap = grainpos[*graincnt] - grainpos[(*graincnt)-1]) < dz->iparam[GR_ABS_SPLICELEN]) {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Loosing last grain: too short.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ (*graincnt)--;
|
|
|
|
|
+ } else if(lastgap > dz->buflen) { /* truncate last grain if too int */
|
|
|
|
|
+ fprintf(stdout,"WARNING: Last grain truncated: too int.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ grainpos[*graincnt] = grainpos[(*graincnt)-1] + dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** CLEAR_OUTBUF ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int clear_outbuf(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ memset((char *)dz->sampbuf[2],0,dz->buflen * sizeof(float));
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** OUTPUT_WHOLE_GRAIN ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int output_whole_grain(int n,int *obufpos,int *seeksamps,int *seekbufs,
|
|
|
|
|
+int halfsplice,int abs_splicelen,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int crosbuf = FALSE;
|
|
|
|
|
+ int ibufpos;
|
|
|
|
|
+ int mid_grainlen;
|
|
|
|
|
+ int startsplice;
|
|
|
|
|
+ int endsplice;
|
|
|
|
|
+ startsplice = endsplice = halfsplice;
|
|
|
|
|
+ if((ibufpos = dz->lparray[GR_ABS_POS][n] - *seeksamps)<0) { /* IF current grain NOT in current buffer */
|
|
|
|
|
+ if(*seeksamps==0) { /* IF at start of file */
|
|
|
|
|
+ if((exit_status = adjust_firstgrain_upsplice(&ibufpos,&startsplice,n,chans))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else { /* ELSE: change current buffer */
|
|
|
|
|
+ if((exit_status = do_seek_and_read(seekbufs,seeksamps,n,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ ibufpos = dz->lparray[GR_ABS_POS][n] - *seeksamps;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = output_up_halfsplice(&ibufpos,obufpos,chans,startsplice,&crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ mid_grainlen = (dz->lparray[GR_ABS_POS][n+1] - dz->lparray[GR_ABS_POS][n]) - abs_splicelen;
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ (*seekbufs)++;
|
|
|
|
|
+ (*seeksamps) += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ crosbuf = FALSE;
|
|
|
|
|
+ if(mid_grainlen > 0) {
|
|
|
|
|
+ if((exit_status = copy_midgrain_to_output(mid_grainlen,&ibufpos,obufpos,&crosbuf,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ (*seekbufs)++;
|
|
|
|
|
+ (*seeksamps) += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ crosbuf = FALSE;
|
|
|
|
|
+ if((exit_status = output_dn_halfsplice(&ibufpos,obufpos,chans,endsplice,&crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(crosbuf) {
|
|
|
|
|
+ (*seekbufs)++;
|
|
|
|
|
+ (*seeksamps) += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** ADJUST_FIRSTGRAIN_UPSPLICE ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int adjust_firstgrain_upsplice(int *ibufpos,int *startsplice,int n,int chans)
|
|
|
|
|
+{
|
|
|
|
|
+ if(n!=0) { /* MUST be 1st grain */
|
|
|
|
|
+ sprintf(errstr,"Grain accounting error: adjust_firstgrain_upsplice()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *startsplice += *ibufpos/chans; /* shorten startsplice by deficit of [stereo] samples */
|
|
|
|
|
+ *ibufpos = 0; /* reset output read to start of file */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* DO_GRAIN_REPITCHING *************************/
|
|
|
|
|
+/* RWD 4:2002 : NB modified to allow n-channels */
|
|
|
|
|
+int do_grain_repitching(int *actual_grainlen,int bufno,int grainstart,int new_grainlen,int orig_grainlen,
|
|
|
|
|
+int chans,int crosbuf,double pichratio,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int m;
|
|
|
|
|
+ int k = 0, here, thishere;
|
|
|
|
|
+ double dpoint = 0.0, frac;
|
|
|
|
|
+//TW CHANGED
|
|
|
|
|
+// float /*thisval[2],*/ nextval[2], diff[2];
|
|
|
|
|
+ float /*thisval[2],*/ nextval, diff;
|
|
|
|
|
+ float *b, *b2, *grainbuf = dz->extrabuf[2];
|
|
|
|
|
+ float *thisval;
|
|
|
|
|
+
|
|
|
|
|
+ thisval = (float *) malloc(chans * sizeof(float));
|
|
|
|
|
+ if(thisval==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to enlarge positions store.\n");
|
|
|
|
|
+ return MEMORY_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ b = dz->sampbuf[!bufno];
|
|
|
|
|
+ else
|
|
|
|
|
+ b = dz->sampbuf[bufno];
|
|
|
|
|
+ orig_grainlen /= chans;
|
|
|
|
|
+ while(k < new_grainlen) {
|
|
|
|
|
+ here = (int)dpoint; /* truncate */
|
|
|
|
|
+ frac = dpoint - (double)here;
|
|
|
|
|
+ thishere = (here*chans);
|
|
|
|
|
+ thishere += grainstart;
|
|
|
|
|
+ if((exit_status = test_for_bufcros(&thishere,&b,bufno,crosbuf,dz))<0) {
|
|
|
|
|
+ free(thisval);
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(exit_status == TRUE) /* changed buffer */
|
|
|
|
|
+ grainstart -= dz->buflen;
|
|
|
|
|
+ for(m=0;m<chans;m++)
|
|
|
|
|
+ thisval[m] = b[thishere+m];
|
|
|
|
|
+ b2 = b;
|
|
|
|
|
+ here++;
|
|
|
|
|
+ thishere = (here*chans);
|
|
|
|
|
+ thishere += grainstart;
|
|
|
|
|
+ if((exit_status = test_for_bufcros(&thishere,&b2,bufno,crosbuf,dz))<0) {
|
|
|
|
|
+ free(thisval);
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(m=0;m<chans;m++) {
|
|
|
|
|
+//TW MODIFIED
|
|
|
|
|
+ nextval = b2[thishere+m];
|
|
|
|
|
+ diff = nextval - thisval[m];
|
|
|
|
|
+ grainbuf[k++] = (float) /*round*/(((double)diff * frac) + thisval[m]);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dpoint += pichratio) > orig_grainlen)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ *actual_grainlen = k;
|
|
|
|
|
+ free(thisval);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* TEST_FOR_BUFCROS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int test_for_bufcros(int *thishere,float **b,int bufno,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ if(*thishere >= dz->buflen) {
|
|
|
|
|
+ if(crosbuf==FALSE) {
|
|
|
|
|
+ sprintf(errstr,"Buffer accounting problem: test_for_bufcros()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *b = dz->sampbuf[bufno];
|
|
|
|
|
+ *thishere -= dz->buflen;
|
|
|
|
|
+ return(TRUE);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FALSE);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* SAVE_NEXTGRAIN_UPSPLICE_ELSEWHERE *************************/
|
|
|
|
|
+
|
|
|
|
|
+int save_nextgrain_upsplice_elsewhere
|
|
|
|
|
+(int ibufpos,int bufno,int abs_halfsplice,int halfsplice,int chans,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int splicestart_bufno = bufno;
|
|
|
|
|
+ int start_splice = ibufpos - abs_halfsplice;
|
|
|
|
|
+ if(start_splice < 0) {
|
|
|
|
|
+ splicestart_bufno = !bufno;
|
|
|
|
|
+ start_splice += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ return store_up_halfsplice(0,start_splice,splicestart_bufno,chans,halfsplice,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* COPYGRAIN_FROM_GRAINBUF_TO_OUTBUF *************************/
|
|
|
|
|
+
|
|
|
|
|
+int copygrain_from_grainbuf_to_outbuf(int *obufpos,int grainlen,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int remain = dz->buflen - *obufpos;
|
|
|
|
|
+ float *there = dz->sampbuf[2] + *obufpos;
|
|
|
|
|
+ float *here = dz->extrabuf[2];
|
|
|
|
|
+ while(grainlen >= remain) {
|
|
|
|
|
+ memmove((char *)there,(char *)here,remain * sizeof(float));
|
|
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ *obufpos = 0;
|
|
|
|
|
+ there = dz->sampbuf[2];
|
|
|
|
|
+ here += remain;
|
|
|
|
|
+ grainlen -= remain;
|
|
|
|
|
+ remain = dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(grainlen) {
|
|
|
|
|
+ memmove((char *)there,(char *)here,grainlen * sizeof(float));
|
|
|
|
|
+ *obufpos += grainlen;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* RETRIEVE_UPSPLICE_FOR_NEXTGRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+int retrieve_upsplice_for_nextgrain(int abs_halfsplice,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ memmove((char *)dz->extrabuf[1],(char *)dz->extrabuf[0],abs_halfsplice * sizeof(float));
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* RETIME_MAIN_BODY_OF_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+int retime_main_body_of_grain(int grainstart,int bufno,double pichratio,
|
|
|
|
|
+double timeratio,int chans,int crosbuf,int *grainadjusted,
|
|
|
|
|
+int orig_grainlen,int *new_grainlen,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int abs_splicelen = dz->iparam[GR_ABS_SPLICELEN];
|
|
|
|
|
+ int abs_halfsplice = abs_splicelen/2; /* guaranteed to fall on stereo boundary */
|
|
|
|
|
+ int halfsplice = dz->iparam[GR_SPLICELEN]/2;
|
|
|
|
|
+
|
|
|
|
|
+ *new_grainlen = round((double)(orig_grainlen/chans) * timeratio) * chans;
|
|
|
|
|
+ if(*new_grainlen < dz->iparam[GR_ABS_SPLICEX2]) {
|
|
|
|
|
+ *new_grainlen = dz->iparam[GR_ABS_SPLICEX2];
|
|
|
|
|
+ (*grainadjusted)++;
|
|
|
|
|
+ }
|
|
|
|
|
+ *new_grainlen -= abs_halfsplice;
|
|
|
|
|
+ orig_grainlen -= abs_halfsplice;
|
|
|
|
|
+ if((exit_status = repitch_main_body_of_grain(bufno,grainstart,*new_grainlen,orig_grainlen,
|
|
|
|
|
+ pichratio,chans,crosbuf,halfsplice,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* REPITCH_MAIN_BODY_OF_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+int repitch_main_body_of_grain(int bufno,int grainstart,int new_grainlen,int orig_grainlen,
|
|
|
|
|
+double pichratio,int chans,int crosbuf,int halfsplice,int abs_halfsplice,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int actual_grainlen;
|
|
|
|
|
+ int splicelen;
|
|
|
|
|
+ int splicestart;
|
|
|
|
|
+ float *grainbuf;
|
|
|
|
|
+ if(new_grainlen > dz->iparam[GR_STORESIZE]) {
|
|
|
|
|
+ if((dz->extrabuf[2] = (float *)realloc(dz->extrabuf[2],new_grainlen * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to enlarge grain store.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->iparam[GR_STORESIZE] = (int)new_grainlen;
|
|
|
|
|
+ }
|
|
|
|
|
+ grainbuf = dz->extrabuf[2];
|
|
|
|
|
+ memset((char *)grainbuf,0,new_grainlen * sizeof(float));
|
|
|
|
|
+ if((exit_status = do_grain_repitching
|
|
|
|
|
+ (&actual_grainlen,bufno,grainstart,new_grainlen,orig_grainlen,chans,crosbuf,pichratio,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ splicelen = halfsplice;
|
|
|
|
|
+ splicestart = actual_grainlen - abs_halfsplice;
|
|
|
|
|
+ if(splicestart < 0) {
|
|
|
|
|
+ splicelen += splicestart/chans;
|
|
|
|
|
+ splicestart = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return do_in_situ_halfsplice_on_stored_grain(splicestart,chans,splicelen,new_grainlen,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* CREATE_REPITCHED_AND_RETIMED_GRAIN *************************/
|
|
|
|
|
+
|
|
|
|
|
+//TW REVISED
|
|
|
|
|
+int create_repitched_and_retimed_grain
|
|
|
|
|
+(int bufno,int grainstart,int orig_grainlen,int *new_grainlen,
|
|
|
|
|
+double pichratio,double timeratio,int *obufpos,int *is_first_grain,
|
|
|
|
|
+int *grainadjusted,int abs_halfsplice,int chans,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ if((exit_status = retime_main_body_of_grain(grainstart,bufno,pichratio,timeratio,
|
|
|
|
|
+ chans,crosbuf,grainadjusted,orig_grainlen,new_grainlen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(!(*is_first_grain)) {
|
|
|
|
|
+ if((exit_status = read_up_halfsplice(obufpos,abs_halfsplice,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ *is_first_grain = FALSE;
|
|
|
|
|
+ return copygrain_from_grainbuf_to_outbuf(obufpos,*new_grainlen,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* SAVE_ORIGGRAIN_LENGTH_AND_STORE_NEXTGRAINS_UPSPLICE *************************/
|
|
|
|
|
+
|
|
|
|
|
+int save_origgrain_length_and_store_nextgrains_upsplice(int *orig_grainlen,int ibufpos,int bufno,
|
|
|
|
|
+int grainstart,int abs_halfsplice,int halfsplice,int crosbuf,int chans,int is_last_grain,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ *orig_grainlen = ibufpos - grainstart;
|
|
|
|
|
+ if(crosbuf)
|
|
|
|
|
+ *orig_grainlen += dz->buflen;
|
|
|
|
|
+ if((*orig_grainlen - abs_halfsplice)<0) {
|
|
|
|
|
+ if(!is_last_grain) {
|
|
|
|
|
+ sprintf(errstr,"Anomalous too short grain: save_origgrain_length_and_store_nextgrains_upsplice()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Last grain omitted: too short.\n");
|
|
|
|
|
+ return(CONTINUE);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return save_nextgrain_upsplice_elsewhere(ibufpos,bufno,abs_halfsplice,halfsplice,chans,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* REPITCHING_PROCESS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int repitching_process(int ibufpos,int bufno,int grainstart,int abs_halfsplice,int halfsplice,int *graincnt,
|
|
|
|
|
+int *obufpos,int *orig_grainlen,int *new_grainlen,int *grainadjusted,
|
|
|
|
|
+int *is_first_grain,int is_last_grain,int chans,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double timeratio = 1.0, pichratio;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ if(*is_first_grain && (exit_status = create_an_upsplice_from_pregrain_material(*obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = save_origgrain_length_and_store_nextgrains_upsplice
|
|
|
|
|
+ (orig_grainlen,ibufpos,bufno,grainstart,abs_halfsplice,halfsplice,crosbuf,chans,is_last_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(exit_status==CONTINUE) /* last grain too short */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(GR_REPEATS):
|
|
|
|
|
+ for(n=0;n<dz->iparam[GR_RATIOCNT];n++) {
|
|
|
|
|
+ pichratio = dz->parray[GR_RATIO][n];
|
|
|
|
|
+ if((exit_status = create_repitched_and_retimed_grain
|
|
|
|
|
+ (bufno,grainstart,*orig_grainlen,new_grainlen,pichratio,timeratio,obufpos,
|
|
|
|
|
+ is_first_grain,grainadjusted,abs_halfsplice,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GR_NO_REPEATS):
|
|
|
|
|
+ pichratio = dz->parray[GR_RATIO][*graincnt];
|
|
|
|
|
+ if((exit_status = create_repitched_and_retimed_grain
|
|
|
|
|
+ (bufno,grainstart,*orig_grainlen,new_grainlen,pichratio,timeratio,obufpos,
|
|
|
|
|
+ is_first_grain,grainadjusted,abs_halfsplice,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(++(*graincnt)>=dz->iparam[GR_RATIOCNT])
|
|
|
|
|
+ *graincnt = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown case: repitching_process()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* REPITCHING_AND_RETIMING_PROCESS *************************/
|
|
|
|
|
+
|
|
|
|
|
+int repitching_and_retiming_process(int ibufpos,int bufno,int grainstart,int abs_halfsplice,
|
|
|
|
|
+int halfsplice,int *graincnt,int *obufpos,int *orig_grainlen,int *new_grainlen,int *grainadjusted,
|
|
|
|
|
+int *is_first_grain,int is_last_grain,int chans,int crosbuf,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double timeratio, pichratio;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ if(*is_first_grain && (exit_status = create_an_upsplice_from_pregrain_material(*obufpos,chans,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = save_origgrain_length_and_store_nextgrains_upsplice
|
|
|
|
|
+ (orig_grainlen,ibufpos,bufno,grainstart,abs_halfsplice,halfsplice,crosbuf,chans,is_last_grain,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(exit_status==CONTINUE) /* last grain too short */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(GR_REPEATS):
|
|
|
|
|
+ for(n=0;n<dz->iparam[GR_RATIOCNT];n+=2) {
|
|
|
|
|
+ pichratio = dz->parray[GR_RATIO][n];
|
|
|
|
|
+ timeratio = dz->parray[GR_RATIO][n+1];
|
|
|
|
|
+ if((exit_status = create_repitched_and_retimed_grain
|
|
|
|
|
+ (bufno,grainstart,*orig_grainlen,new_grainlen,pichratio,timeratio,obufpos,
|
|
|
|
|
+ is_first_grain,grainadjusted,abs_halfsplice,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GR_NO_REPEATS):
|
|
|
|
|
+ pichratio = dz->parray[GR_RATIO][(*graincnt)++];
|
|
|
|
|
+ timeratio = dz->parray[GR_RATIO][(*graincnt)++];
|
|
|
|
|
+ if((exit_status = create_repitched_and_retimed_grain
|
|
|
|
|
+ (bufno,grainstart,*orig_grainlen,new_grainlen,pichratio,timeratio,obufpos,
|
|
|
|
|
+ is_first_grain,grainadjusted,abs_halfsplice,chans,crosbuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(*graincnt >= dz->iparam[GR_RATIOCNT])
|
|
|
|
|
+ *graincnt = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Unknown case: repitching_and_retiming_process()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** TIMESTRETCH_ITERATIVE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int timestretch_iterative(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status, do_slow, do_regu;
|
|
|
|
|
+ float *ibuf = dz->sampbuf[0];
|
|
|
|
|
+ float *obuf = dz->sampbuf[1];
|
|
|
|
|
+// double *peak = dz->parray[0];
|
|
|
|
|
+ int *pos = dz->lparray[0];
|
|
|
|
|
+ int peakcnt, startsearch, endsearch, local_minima_cnt, minimum_element_len;
|
|
|
|
|
+ int stretchable_len, required_segsection_len, total_segsection_length;
|
|
|
|
|
+ int element_cnt, max_elements_needed;
|
|
|
|
|
+ int arrsiz, fullperms, patternsize;
|
|
|
|
|
+ int *pattern;
|
|
|
|
|
+ int finished;
|
|
|
|
|
+ int n, k=0, outpos, startseg, startpos, endpos, seglen;
|
|
|
|
|
+ int abspos, new_abspos;
|
|
|
|
|
+ int ascatter = 0, pscatter = 0, jitter = 0;
|
|
|
|
|
+ double gain = 1.0, trans = 1.0, d, part, time, diff;
|
|
|
|
|
+ float val, nextval;
|
|
|
|
|
+ double z = (dz->param[RRR_END] - dz->param[RRR_START]) * dz->param[RRR_REPET];
|
|
|
|
|
+ double starttime_of_iter, davg_step;
|
|
|
|
|
+ int total_slolen, total_slo_incr, slo_incr, min_step, j, avg_step, gap, maxsamp;
|
|
|
|
|
+ int *seg_step = NULL, *seg_len = NULL;
|
|
|
|
|
+ int thiselementcnt, regusegscnt, okcnt, *seg_ok = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->vflag[0] == 0)
|
|
|
|
|
+ z += dz->param[RRR_START];
|
|
|
|
|
+ if(dz->vflag[1] == 0)
|
|
|
|
|
+ z += dz->duration - dz->param[RRR_END];
|
|
|
|
|
+//2010
|
|
|
|
|
+ dz->tempsize = (int)round(z * dz->infile->srate) * dz->infile->channels;
|
|
|
|
|
+ fprintf(stdout,"INFO: Generating output.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ display_virtual_time(0,dz);
|
|
|
|
|
+ if(dz->brksize[RRR_ASCAT] || !flteq(dz->param[RRR_ASCAT],0.0)) {
|
|
|
|
|
+ ascatter = 1;
|
|
|
|
|
+ jitter = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[RRR_PSCAT] || !flteq(dz->param[RRR_PSCAT],0.0)) {
|
|
|
|
|
+ pscatter = 1;
|
|
|
|
|
+ jitter = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->sampbuf[0][dz->insams[0]] = dz->sampbuf[0][dz->insams[0] - 1]; /* wrap around point for interpolation */
|
|
|
|
|
+ startsearch = (int)round(dz->param[RRR_START] * dz->infile->srate);
|
|
|
|
|
+ endsearch = (int)round(dz->param[RRR_END] * dz->infile->srate);
|
|
|
|
|
+
|
|
|
|
|
+ /* FIND ALL POSITIVE PEAKS : always look only at +ve vals, so all zero-crossings eventually found will be from +ve to -ve */
|
|
|
|
|
+
|
|
|
|
|
+ peakcnt = 0;
|
|
|
|
|
+ if((exit_status = find_all_positive_peaks(startsearch,endsearch,&peakcnt,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ /* FIND ALL POSITIVE-PEAK MINIMA : overwriting the arrays peak-vals & peak-position with minima-vals & minima-positions */
|
|
|
|
|
+
|
|
|
|
|
+ local_minima_cnt = 0;
|
|
|
|
|
+ if((exit_status = find_all_local_minima(peakcnt,&local_minima_cnt,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ /* ELIMINATE SPURIOUS MINIMA */
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = eliminate_spurious_minima(&local_minima_cnt,&minimum_element_len,dz)) < 0)
|
|
|
|
|
+ return (exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ fprintf(stdout,"INFO: Original number of segments found = %d\n",local_minima_cnt - 1);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+
|
|
|
|
|
+ /* CHECK MINIMA FOUND AGAINST INPUT ESTIMATE */
|
|
|
|
|
+
|
|
|
|
|
+ if((local_minima_cnt - 1) >= 2 * dz->iparam[RRR_GET]) {
|
|
|
|
|
+ if((exit_status = eliminate_excess_minima(&local_minima_cnt,pos,dz)) < 0)
|
|
|
|
|
+ return (exit_status);
|
|
|
|
|
+ fprintf(stdout,"INFO: Reduced to = %d\n",local_minima_cnt - 1);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ /* SEARCH FOR ZERO CROSSINGS AFTER MINIMA */
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = locate_zero_crossings(local_minima_cnt,dz)) < 0)
|
|
|
|
|
+ return (exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ /* CALCULATE HOW int STRETCHED SECTION SHOULD BE */
|
|
|
|
|
+
|
|
|
|
|
+ stretchable_len = pos[local_minima_cnt-1] - pos[0];
|
|
|
|
|
+ required_segsection_len = (int)round((double)stretchable_len * dz->param[RRR_STRETCH]);
|
|
|
|
|
+
|
|
|
|
|
+ /* CALCULATE HOW MANY ELEMENTS TO USE */
|
|
|
|
|
+
|
|
|
|
|
+ element_cnt = local_minima_cnt - 1;
|
|
|
|
|
+ max_elements_needed = (int)round(ceil((double)required_segsection_len/(double)minimum_element_len));
|
|
|
|
|
+ max_elements_needed *= 2; /* required no of elements is set to a value greater than possibly required */
|
|
|
|
|
+
|
|
|
|
|
+ /* CALCULATE HOW MANY PERMUTATIONS NEEDED */
|
|
|
|
|
+
|
|
|
|
|
+ arrsiz = element_cnt * dz->iparam[RRR_REPET]; /* if elements can be repeated N times, perm-array can contain N copies of values */
|
|
|
|
|
+ fullperms = max_elements_needed / arrsiz;
|
|
|
|
|
+ if(fullperms * arrsiz < max_elements_needed) /* total number of permutations to generate must include any part permutation */
|
|
|
|
|
+ fullperms++;
|
|
|
|
|
+ patternsize = fullperms * arrsiz;
|
|
|
|
|
+
|
|
|
|
|
+ if((pattern = (int *)malloc(patternsize * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory to generate segment permutation.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* GENERATE RANDOM PATTERN */
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = rand_ints_with_restricted_repeats(element_cnt,max_elements_needed,arrsiz,fullperms,&pattern,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->brksize[RRR_SLOW]) {
|
|
|
|
|
+ maxsamp = (int)round(dz->maxtime * (double)dz->infile->srate);
|
|
|
|
|
+ if((seg_step = (int *)malloc(element_cnt * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory to store steps between segment if slowed.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[RRR_REGU]) {
|
|
|
|
|
+ if((seg_len = (int *)malloc(element_cnt * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory to store orig segment lengths, if slowed.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((seg_ok = (int *)malloc(element_cnt * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory to store segment flags, if regularised.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* COPY SOUND START TO OUTBUF */
|
|
|
|
|
+
|
|
|
|
|
+ outpos = 0;
|
|
|
|
|
+ if(dz->vflag[0] == 0) {
|
|
|
|
|
+ memcpy((char *)obuf,(char *)ibuf,pos[0] * sizeof(float));
|
|
|
|
|
+ outpos = pos[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ /* GENERATE OUTPUT SEQUENCE OF ELEMENTS */
|
|
|
|
|
+ total_segsection_length = 0;
|
|
|
|
|
+ finished = 0;
|
|
|
|
|
+ time = 0.0;
|
|
|
|
|
+ abspos = dz->total_samps_written + outpos;
|
|
|
|
|
+ if(dz->brksize[RRR_SLOW])
|
|
|
|
|
+ maxsamp += abspos;
|
|
|
|
|
+ starttime_of_iter = (double)abspos/(double)dz->infile->srate;
|
|
|
|
|
+
|
|
|
|
|
+ do {
|
|
|
|
|
+ for(n=0; n < patternsize; n++) {
|
|
|
|
|
+ if(n % element_cnt == 0) {
|
|
|
|
|
+ do_slow = 0;
|
|
|
|
|
+ do_regu = 0;
|
|
|
|
|
+ if(dz->brksize[RRR_SLOW]) {
|
|
|
|
|
+ time = (double)abspos/(double)dz->infile->srate;
|
|
|
|
|
+ time -= starttime_of_iter;
|
|
|
|
|
+ if((exit_status = read_value_from_brktable(time,RRR_SLOW,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->brksize[RRR_REGU] > 0) {
|
|
|
|
|
+ if((exit_status = read_value_from_brktable(time,RRR_REGU,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->param[RRR_SLOW] > 1.0) { // If segments are to be slowed (by intervening silence)
|
|
|
|
|
+ do_slow = 1;
|
|
|
|
|
+ while(do_slow) {
|
|
|
|
|
+ thiselementcnt = min(element_cnt,patternsize-n); // SAFETY (should be whole number of element_cnts in patternsize)
|
|
|
|
|
+ total_slolen = (int)round(stretchable_len * dz->param[RRR_SLOW]); // Sample duration of all segs, once slowed by intervening gaps
|
|
|
|
|
+ total_slo_incr = total_slolen - stretchable_len; // Total added silence, in samples
|
|
|
|
|
+ slo_incr = (int)round((double)total_slo_incr/(double)thiselementcnt); // Silence to be inserted after to each element
|
|
|
|
|
+ if(slo_incr <= 0) {
|
|
|
|
|
+ do_slow = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ } // Regularisation of rhythm of output cannot be done until there is
|
|
|
|
|
+ if(dz->param[RRR_REGU] > 0.0) { // maniupulable silence between segments, which only occues after SLOW applied
|
|
|
|
|
+ do_regu = 1;
|
|
|
|
|
+ while(do_regu) {
|
|
|
|
|
+ total_slo_incr = slo_incr * thiselementcnt; // Total added silence, after accounting for rounding
|
|
|
|
|
+ min_step = dz->insams[0] + 1;
|
|
|
|
|
+ avg_step = 0;
|
|
|
|
|
+ for(j = 0,k=n; j < thiselementcnt;j++,k++){
|
|
|
|
|
+ startseg = pattern[k];
|
|
|
|
|
+ startpos = pos[startseg];
|
|
|
|
|
+ endpos = pos[startseg+1];
|
|
|
|
|
+ seglen = endpos - startpos;
|
|
|
|
|
+ seg_len[j] = seglen; // Find actual length of each segment
|
|
|
|
|
+ seg_step[j] = seg_len[j] + slo_incr; // Find step between start of one seg & next (when intervening silence added) BEFORE REGULARISING
|
|
|
|
|
+ seg_ok[j] = 1; // Mark as a valid segment to regularise
|
|
|
|
|
+ min_step = min(min_step,seg_step[j]); // Find the minimim step
|
|
|
|
|
+ avg_step += seg_step[j]; // Find the average step
|
|
|
|
|
+ }
|
|
|
|
|
+ regusegscnt = 0;
|
|
|
|
|
+ okcnt = thiselementcnt;
|
|
|
|
|
+ davg_step = (double)avg_step/(double)okcnt; // Once regularised, step between seg entries will be set to the average value
|
|
|
|
|
+ for(j=0; j < thiselementcnt; j++) { // If length of a segment is > average, this can't be done
|
|
|
|
|
+ if(seg_len[j] > davg_step) { // So mark any such segment as not valid for the averaging process
|
|
|
|
|
+ seg_ok[j] = 0;
|
|
|
|
|
+ avg_step -= seg_len[j]; // and remove it from the calculation of the average step
|
|
|
|
|
+ okcnt--;
|
|
|
|
|
+ davg_step = (double)avg_step/(double)okcnt;
|
|
|
|
|
+ } else
|
|
|
|
|
+ regusegscnt++; // Count all the averagable segments
|
|
|
|
|
+ }
|
|
|
|
|
+ if(regusegscnt < 2) // If less than 2 valid segs, no averaging can be done
|
|
|
|
|
+ do_regu = 0;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(do_regu) {
|
|
|
|
|
+ avg_step = (int)round((double)avg_step/(double)regusegscnt);
|
|
|
|
|
+ for(j=0; j < thiselementcnt; j++) { // For all valid segments
|
|
|
|
|
+ if(seg_ok[j]) // (partially) adjust step between it and next to the average step
|
|
|
|
|
+ seg_step[j] = ((int)round((avg_step - seg_step[j]) * dz->param[RRR_REGU])) + seg_step[j];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(do_slow) {
|
|
|
|
|
+ if(do_regu) {
|
|
|
|
|
+ for(j=0; j < thiselementcnt; j++) // Find the gap left after each segment
|
|
|
|
|
+ seg_step[j] -= seg_len[j];
|
|
|
|
|
+ } else { // If seg_entries NOT to be regularised
|
|
|
|
|
+ for(j=0; j < thiselementcnt; j++) // Set silent gap between segs all to same val
|
|
|
|
|
+ seg_step[j] = slo_incr;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ startseg = pattern[n];
|
|
|
|
|
+ startpos = pos[startseg];
|
|
|
|
|
+ endpos = pos[startseg+1];
|
|
|
|
|
+ seglen = endpos - startpos;
|
|
|
|
|
+ if(jitter) {
|
|
|
|
|
+ time = (double)abspos/(double)dz->infile->srate;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ k = startpos;
|
|
|
|
|
+ d = (double)startpos;
|
|
|
|
|
+ part = 0.0;
|
|
|
|
|
+ if(ascatter) { /* generate random value for seg gain, within given range */
|
|
|
|
|
+ gain = drand48() * dz->param[RRR_ASCAT];
|
|
|
|
|
+ gain = 1.0 - gain;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(pscatter) {
|
|
|
|
|
+ trans = (drand48() * 2.0) - 1.0;
|
|
|
|
|
+ if(trans >= 0.0) /* randomly chose up or down transposition */
|
|
|
|
|
+ trans = 1.0;
|
|
|
|
|
+ else
|
|
|
|
|
+ trans = -1.0; /* generate random semitone step within given range */
|
|
|
|
|
+ trans *= (drand48() * dz->param[RRR_PSCAT]);
|
|
|
|
|
+ trans /= 12; /* convert to transposition ratio = step in sample-reading */
|
|
|
|
|
+ trans = pow(2.0,trans);
|
|
|
|
|
+ }
|
|
|
|
|
+ while(k < endpos) {
|
|
|
|
|
+ val = ibuf[k];
|
|
|
|
|
+ nextval = ibuf[k+1];
|
|
|
|
|
+ diff = nextval - val;
|
|
|
|
|
+ z = val + (diff * part);
|
|
|
|
|
+ z *= gain;
|
|
|
|
|
+ d += trans;
|
|
|
|
|
+ k = (int)d; /* TRUNCATE */
|
|
|
|
|
+ part = d - (double)k;
|
|
|
|
|
+ obuf[outpos] = (float)z;
|
|
|
|
|
+ if(++outpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ outpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(k = startpos; k < endpos; k++) {
|
|
|
|
|
+ obuf[outpos] = ibuf[k];
|
|
|
|
|
+ if(++outpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ outpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ new_abspos = dz->total_samps_written + outpos;
|
|
|
|
|
+ if(do_slow) {
|
|
|
|
|
+ k = n % element_cnt;
|
|
|
|
|
+ gap = seg_step[k];
|
|
|
|
|
+ for(j=0;j<gap;j++) {
|
|
|
|
|
+ obuf[outpos] = 0;
|
|
|
|
|
+ if(++outpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ outpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ new_abspos = dz->total_samps_written + outpos;
|
|
|
|
|
+ }
|
|
|
|
|
+ abspos = new_abspos;
|
|
|
|
|
+
|
|
|
|
|
+ // If reach end of slowing curve, but still patterns left, exit pattern generation
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->brksize[RRR_SLOW] && abspos >= maxsamp)
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+
|
|
|
|
|
+ // If reach end of patterns
|
|
|
|
|
+
|
|
|
|
|
+ if((total_segsection_length += seglen) >= required_segsection_len || (n == patternsize - 1)) { // Should be equivalent!!
|
|
|
|
|
+
|
|
|
|
|
+ // If not at end of slowing pattern, generate more random perms, and restart loop (n = 0)
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->brksize[RRR_SLOW] && abspos < maxsamp) {
|
|
|
|
|
+ if((exit_status = rand_ints_with_restricted_repeats(element_cnt,max_elements_needed,arrsiz,fullperms,&pattern,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(finished)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ } while(!finished);
|
|
|
|
|
+ if(!finished) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient segments generated at output stage.\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ /* COPY SOUND END TO OUTBUF */
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->vflag[1] == 0) {
|
|
|
|
|
+ for(n = pos[local_minima_cnt - 1]; n < dz->insams[0];n++) {
|
|
|
|
|
+ obuf[outpos] = ibuf[n];
|
|
|
|
|
+ if(++outpos >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ /*memset((char *)obuf,0,dz->bigbufsize);*/
|
|
|
|
|
+ memset(obuf,0,sizeof(float)* dz->buflen); /*RWD ?? */
|
|
|
|
|
+ outpos = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(outpos > 0) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,outpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** RAND_INTS_WITH_RESTRICTED_REPEATS ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int rand_ints_with_restricted_repeats(int element_cnt,int max_elements_needed,int arrsiz,int fullperms,int **pattern,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, m, i, k=0, j;
|
|
|
|
|
+ int endcnt, endval, allowed, checkpart;
|
|
|
|
|
+ int patterncnt = 0;
|
|
|
|
|
+ int *arr, *arr2, *perm;
|
|
|
|
|
+
|
|
|
|
|
+ if((arr = (int *)malloc(arrsiz * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory for permutation array 1.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((perm = (int *)malloc(arrsiz * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory for permutation array 2.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((arr2 = (int *)malloc(dz->iparam[RRR_REPET] * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory for permutation array 3.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ for(j=0;j<dz->iparam[RRR_REPET];j++) { /* fill array with REPET copies of values. */
|
|
|
|
|
+ for(i=0;i<element_cnt;i++) /* this set can be permd AS A WHOLE, as repet adjacent copies of any val */
|
|
|
|
|
+ arr[n++] = i; /* which might arise in perming this set, are allowed */
|
|
|
|
|
+ }
|
|
|
|
|
+ endcnt = 0; /* number of items repeated at end of previous perm */
|
|
|
|
|
+ endval = -1; /* value (possibly repeated) at end of previous perm (for first perm set it to a val not in perm */
|
|
|
|
|
+ /* initially this is just the 'startval' fixed by the user */
|
|
|
|
|
+ allowed = dz->iparam[RRR_REPET]; /* number of permissible repetitions of this val at start of 1st perm */
|
|
|
|
|
+ checkpart = arrsiz - dz->iparam[RRR_REPET]; /* items at end of array to test for repetitions */
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ while(n < fullperms) {
|
|
|
|
|
+ do_repet_restricted_perm(arr,perm,arrsiz,allowed,endval);
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ for(m = 0;m <arrsiz;m++) {
|
|
|
|
|
+ (*pattern)[patterncnt] = arr[perm[m]];
|
|
|
|
|
+ patterncnt++;
|
|
|
|
|
+ if(m >= checkpart) /* save last checkable stretch of perm */
|
|
|
|
|
+ arr2[j++] = arr[perm[m]];
|
|
|
|
|
+ }
|
|
|
|
|
+ if(n < fullperms -1) {
|
|
|
|
|
+ j--;
|
|
|
|
|
+ endval = arr2[j--]; /* note the val at end of perm */
|
|
|
|
|
+ endcnt = 1; /* and count it */
|
|
|
|
|
+ for(k = j; k>= 0; k--) {
|
|
|
|
|
+ if(arr2[k] == endval) /* check adjacent vals, for repetition of value: count */
|
|
|
|
|
+ endcnt++;
|
|
|
|
|
+ else /* if no more repetitions, finish counting */
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ allowed = dz->iparam[RRR_REPET] - endcnt; /* get number of permissible repets at start of next perm */
|
|
|
|
|
+ }
|
|
|
|
|
+ n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** DO_REPET_RESTRICTED_PERM ****************************/
|
|
|
|
|
+
|
|
|
|
|
+void do_repet_restricted_perm(int *arr, int *perm, int arrsiz, int allowed, int endval)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, t;
|
|
|
|
|
+ int checklen = allowed + 1;
|
|
|
|
|
+ int done = 0;
|
|
|
|
|
+ while(!done) {
|
|
|
|
|
+ for(n=0;n<arrsiz;n++) {
|
|
|
|
|
+ t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
|
|
|
|
|
+ if(t==n)
|
|
|
|
|
+ hhprefix(n,arrsiz,perm);
|
|
|
|
|
+ else
|
|
|
|
|
+ hhinsert(n,t,arrsiz,perm);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(checklen <= 0)
|
|
|
|
|
+ break;
|
|
|
|
|
+ for(n=0;n<checklen;n++) {
|
|
|
|
|
+ if(arr[perm[n]] == endval) { /* if this is val (repeated) at end of last perm */
|
|
|
|
|
+ if(allowed == 0) /* if repetition not allowed, force a new perm val */
|
|
|
|
|
+ break;
|
|
|
|
|
+ else /* else, repetitions still allowed */
|
|
|
|
|
+ allowed--; /* decrement number of permissible further repets */
|
|
|
|
|
+ } else {
|
|
|
|
|
+ done = 1; /* if this is not val at end of last perm */
|
|
|
|
|
+ break; /* perm is OK */
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************************** HHINSERT **********************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * Insert the value m AFTER the T-th element in perm[].
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+void hhinsert(int m,int t,int setlen,int *perm)
|
|
|
|
|
+{
|
|
|
|
|
+ hhshuflup(t+1,setlen,perm);
|
|
|
|
|
+ perm[t+1] = m;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/***************************** HHPREFIX ************************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * Insert the value m at start of the permutation perm[].
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+void hhprefix(int m,int setlen,int *perm)
|
|
|
|
|
+{
|
|
|
|
|
+ hhshuflup(0,setlen,perm);
|
|
|
|
|
+ perm[0] = m;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** HHSHUFLUP ***********************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * move set members in perm[] upwards, starting from element k.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+void hhshuflup(int k,int setlen,int *perm)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, *i;
|
|
|
|
|
+ int z = setlen - 1;
|
|
|
|
|
+ i = (perm+z);
|
|
|
|
|
+ for(n = z;n > k;n--) {
|
|
|
|
|
+ *i = *(i-1);
|
|
|
|
|
+ i--;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** ELIMINATE_SPURIOUS_MINIMA ***********************************/
|
|
|
|
|
+
|
|
|
|
|
+int eliminate_spurious_minima(int *local_minima_cnt,int *minimum_element_len,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int *seg;
|
|
|
|
|
+ int *segpos, badseg;
|
|
|
|
|
+ int n, m, segcnt = (*local_minima_cnt) - 1, temp,eliminate_pos;
|
|
|
|
|
+ double *peak = dz->parray[0];
|
|
|
|
|
+ int *pos = dz->lparray[0];
|
|
|
|
|
+ int maxseg, minseg, minsegstartpos;
|
|
|
|
|
+ if((seg = (int *)malloc(segcnt * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory (A) to check for spurious local minima\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((segpos = (int *)malloc(segcnt * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory (B) to check for spurious local minima\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(;;) { /* RECURSIVELY ELIMINATE TOO-SHORT GAPS */
|
|
|
|
|
+ for(n = 0; n < segcnt; n++)
|
|
|
|
|
+ seg[n] = pos[n+1] - pos[n];
|
|
|
|
|
+ for(n = 0; n < segcnt; n++)
|
|
|
|
|
+ segpos[n] = n;
|
|
|
|
|
+ for(n=0;n < segcnt-1; n++) { /* BUBBLE SORT THE GAPS BETWEEN LOCAL MINIMA TO DESCENDING SIZE ORDER */
|
|
|
|
|
+ for(m=n+1;m < segcnt; m++) {
|
|
|
|
|
+ if(seg[n] < seg[m]) {
|
|
|
|
|
+ temp = seg[n];
|
|
|
|
|
+ seg[n] = seg[m];
|
|
|
|
|
+ seg[m] = temp;
|
|
|
|
|
+ temp = segpos[n]; /* AND KEEP TRACK OF WHERE THESE NEWLY ORDERED GAPS ARE */
|
|
|
|
|
+ segpos[n] = segpos[m];
|
|
|
|
|
+ segpos[m] = temp;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ maxseg = seg[0];
|
|
|
|
|
+ minseg = seg[segcnt-1];
|
|
|
|
|
+ badseg = 0; /* Compare minimum seg with maximum seg */
|
|
|
|
|
+ if((double)minseg < (double)maxseg * dz->param[RRR_RANGE]) {
|
|
|
|
|
+ badseg = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!badseg) { /* No more anomalous segs found, exit loop */
|
|
|
|
|
+ *minimum_element_len = minseg;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(segcnt-1 < 3) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient valid local minima found during elimination of spurious minima. Are the search times incorrect??\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ minsegstartpos = segpos[segcnt-1]; /* Find positions of minimum seg start */
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = which_minimum_to_eliminate(minsegstartpos,pos,maxseg,segcnt,&eliminate_pos,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ for(n=eliminate_pos ; n < (*local_minima_cnt)-1;n++) {
|
|
|
|
|
+ peak[n] = peak[n+1]; /* Eliminate unwanted val, by moving values in array above it down 1 position */
|
|
|
|
|
+ pos[n] = pos[n+1]; /* If BAD minimum is at current end of array, it just gets ignored as result of "local_minima_cnt--" */
|
|
|
|
|
+ }
|
|
|
|
|
+ (*local_minima_cnt)--; /* Reduce count of minima, and count of segs between minima */
|
|
|
|
|
+ segcnt--;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** FIND_ALL_POSITIVE_PEAKS ***********************************/
|
|
|
|
|
+
|
|
|
|
|
+int find_all_positive_peaks(int startsearch,int endsearch,int *peakcnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double *peak = dz->parray[0], thispeak;
|
|
|
|
|
+ int *pos = dz->lparray[0];
|
|
|
|
|
+ float *ibuf = dz->sampbuf[0];
|
|
|
|
|
+ int thissamp = startsearch, thispos;
|
|
|
|
|
+ while(ibuf[thissamp] <= 0) { /* skip values below zero */
|
|
|
|
|
+ if(++thissamp >= endsearch)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thissamp >= endsearch) {
|
|
|
|
|
+ sprintf(errstr,"Cannot locate any peaks in the signal. Are the search times incorrect??\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ thispeak = ibuf[thissamp];
|
|
|
|
|
+ thispos = thissamp;
|
|
|
|
|
+ thissamp++;
|
|
|
|
|
+ while(thissamp < endsearch) {
|
|
|
|
|
+ if(ibuf[thissamp] >= 0.0) {
|
|
|
|
|
+ if(ibuf[thissamp] > thispeak) { /* search for (positive) peak val */
|
|
|
|
|
+ thispeak = ibuf[thissamp];
|
|
|
|
|
+ thispos = thissamp;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ peak[*peakcnt] = thispeak; /* once signal becomes -ve3, store last found peak */
|
|
|
|
|
+ pos[*peakcnt] = thispos;
|
|
|
|
|
+ (*peakcnt)++;
|
|
|
|
|
+ while(ibuf[thissamp] < 0) { /* then skip over -ve part of signal */
|
|
|
|
|
+ if(++thissamp >= endsearch)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ thispeak = ibuf[thissamp]; /* once dignal is +ve again, set up an initial value for peak */
|
|
|
|
|
+ thispos = thissamp;
|
|
|
|
|
+ }
|
|
|
|
|
+ thissamp++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(*peakcnt > 0) { /* check for peak found near end, before signal goes -ve once more */
|
|
|
|
|
+ if((thispos != pos[(*peakcnt)-1]) && (thispeak > 0.0)) {
|
|
|
|
|
+ peak[*peakcnt] = thispeak;
|
|
|
|
|
+ pos[*peakcnt] = thispos;
|
|
|
|
|
+ (*peakcnt)++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(*peakcnt < 3) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient signal peaks found. Are the search times incorrect??\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** FIND_ALL_LOCAL_MINIMA ***********************************/
|
|
|
|
|
+
|
|
|
|
|
+int find_all_local_minima(int peakcnt,int *local_minima_cnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int thispeak;
|
|
|
|
|
+ double *peak = dz->parray[0];
|
|
|
|
|
+ int *pos = dz->lparray[0];
|
|
|
|
|
+/* double peakmin = peak[0];*/
|
|
|
|
|
+ int finished = 0;
|
|
|
|
|
+ *local_minima_cnt = 0;
|
|
|
|
|
+ thispeak = 1;
|
|
|
|
|
+ while(thispeak < peakcnt) {
|
|
|
|
|
+ while(peak[thispeak] <= peak[thispeak-1]) { /* while peaks are falling, look for local peak minimum */
|
|
|
|
|
+ if(++thispeak >= peakcnt) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(finished)
|
|
|
|
|
+ break;
|
|
|
|
|
+ peak[*local_minima_cnt] = peak[thispeak-1]; /* store value and position of local mimimum */
|
|
|
|
|
+ pos[*local_minima_cnt] = pos[thispeak-1];
|
|
|
|
|
+ (*local_minima_cnt)++;
|
|
|
|
|
+ while(peak[thispeak] >= peak[thispeak-1]) { /* skip over rising sequence of peaks */
|
|
|
|
|
+ if(++thispeak >= peakcnt) {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(*local_minima_cnt < 3) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient local minima found in inital search. Are the search times incorrect??\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** LOCATE_ZERO_CROSSINGS ***********************************/
|
|
|
|
|
+
|
|
|
|
|
+int locate_zero_crossings(int local_minima_cnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int finished = 0;
|
|
|
|
|
+ int n;
|
|
|
|
|
+ float *ibuf = dz->sampbuf[0];
|
|
|
|
|
+ double *peak = dz->parray[0];
|
|
|
|
|
+ int *pos = dz->lparray[0];
|
|
|
|
|
+ for(n=0;n<local_minima_cnt;n++) {
|
|
|
|
|
+ while (peak[n] >= 0.0) { /* advance position from minimum +ve peak until value crosses zero */
|
|
|
|
|
+ if(++pos[n] >= dz->insams[0]) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ if(peak[n] > 0.0) { /* if end of file does not go to zero, Warn */
|
|
|
|
|
+ fprintf(stdout,"WARNING: End_of_sound segment doesn't fall to zero level, & may cause clicks in output. (Dovetail end of sound?)\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ peak[n] = ibuf[pos[n]];
|
|
|
|
|
+ }
|
|
|
|
|
+ if(finished)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** WHICH_MINIMUM_TO_ELIMINATE ***********************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * Too short segment can be eliminated by deleting minimum at its start, or at its end.
|
|
|
|
|
+ * Eliminating the minimum will make the preceding (or following) segment larger.
|
|
|
|
|
+ * Deduce which of the two minima to delete.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int which_minimum_to_eliminate(int minsegstartpos,int *pos,int maxseg,int segcnt,int *eliminate_pos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int newpreseg, newpostseg, later_seg, prior_seg;
|
|
|
|
|
+ double ratio, ratio2, presegratio=0, postsegratio=0;
|
|
|
|
|
+
|
|
|
|
|
+ if(minsegstartpos == 0) { /* if minseg is at start of sequence */
|
|
|
|
|
+ if(pos[2] - pos[0] > maxseg) /* losing end min of seg makes next seg bigger: if bigger than maxseg, eliminate start min instead */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos; /* effectively erasing the first seg */
|
|
|
|
|
+ else /* else lose end min, making following seg larger */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos + 1;
|
|
|
|
|
+ } else if(minsegstartpos + 1 == segcnt) { /* if minseg is at end of sequence */
|
|
|
|
|
+ if(pos[minsegstartpos+1] - pos[minsegstartpos-1] > maxseg)
|
|
|
|
|
+ *eliminate_pos = minsegstartpos + 1; /* if losing start min of seg makes prior seg > maxseg, eliminate end min instead */
|
|
|
|
|
+ else /* else element start min, making previous seg larger */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos;
|
|
|
|
|
+ /* ELSE we're not dealing with segs at ends of sequence */
|
|
|
|
|
+ } else {
|
|
|
|
|
+ newpreseg = (pos[minsegstartpos+1] - pos[minsegstartpos-1]); /* Find length new seg created by eliminating start min of shortest seg */
|
|
|
|
|
+ newpostseg = (pos[minsegstartpos+2] - pos[minsegstartpos]); /* Find length new seg created by eliminating end min of shortest seg */
|
|
|
|
|
+ if(newpreseg > maxseg || newpostseg > maxseg) { /* if either new seg is > maxseg */
|
|
|
|
|
+ if(newpostseg <= maxseg) /* If ONLY preseg inter than maxseg, choose to make postseg, elim end min */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos + 1;
|
|
|
|
|
+ else if(newpreseg <= maxseg) /* If ONLY postseg > maxseg, choose to make postseg, elim start min */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos;
|
|
|
|
|
+ /* else if BOTH > maxseg, choose smaller */
|
|
|
|
|
+ else if(newpreseg > newpostseg) /* if new preseg is larger, keep postseg, eliminate end min */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos + 1;
|
|
|
|
|
+ else /* if new preseg is smaller, keep preseg, eliminate start min */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos;
|
|
|
|
|
+ } else { /* both preseg and postseg are less than maxseg, choose seg that tallies best with local seg environment */
|
|
|
|
|
+ if(segcnt <=3) { /* with only 3 segs, any deletion affects (increases sizeof) maxseg */
|
|
|
|
|
+ /* Thus newly created seg, wherever it is, will be > sizeof orig maxseg, and will have been dealt with above */
|
|
|
|
|
+ sprintf(errstr,"Programming error xxxx.\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ /* find the maximum size ratio between new newpreseg and its adjacent segs */
|
|
|
|
|
+ later_seg = pos[minsegstartpos+2] - pos[minsegstartpos+1];
|
|
|
|
|
+ ratio = (double)newpreseg/(double)later_seg;
|
|
|
|
|
+ if(ratio < 1.0)
|
|
|
|
|
+ ratio = 1.0/ratio;
|
|
|
|
|
+ if(minsegstartpos - 2 > 0) {
|
|
|
|
|
+ prior_seg = pos[minsegstartpos-1] - pos[minsegstartpos-2];
|
|
|
|
|
+ ratio2 = (double)newpreseg/(double)prior_seg;
|
|
|
|
|
+ if(ratio2 < 1.0)
|
|
|
|
|
+ ratio2 = 1.0/ratio2;
|
|
|
|
|
+ ratio = max(ratio,ratio2);
|
|
|
|
|
+ }
|
|
|
|
|
+ presegratio = ratio;
|
|
|
|
|
+ /* find the maximum size ratio between new newpostseg and its adjacent segs */
|
|
|
|
|
+ ratio = 0.0;
|
|
|
|
|
+ prior_seg = pos[minsegstartpos] - pos[minsegstartpos-1];
|
|
|
|
|
+ ratio = (double)newpostseg/(double)prior_seg;
|
|
|
|
|
+ if(ratio < 1.0)
|
|
|
|
|
+ ratio = 1.0/ratio;
|
|
|
|
|
+ if(minsegstartpos + 3 < segcnt) {
|
|
|
|
|
+ later_seg = pos[minsegstartpos+3] - pos[minsegstartpos+2];
|
|
|
|
|
+ ratio2 = (double)newpostseg/(double)later_seg;
|
|
|
|
|
+ if(ratio2 < 1.0)
|
|
|
|
|
+ ratio2 = 1.0/ratio2;
|
|
|
|
|
+ ratio = max(ratio,ratio2);
|
|
|
|
|
+ }
|
|
|
|
|
+ postsegratio = ratio;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(postsegratio < presegratio) /* if newpostseg makes better sense, eliminate end min */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos + 1;
|
|
|
|
|
+ else /* else newporeseg makes better sense, elminate start min */
|
|
|
|
|
+ *eliminate_pos = minsegstartpos;
|
|
|
|
|
+ }
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** ELIMINATE_EXCESS_MINIMA ***********************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * If no of segments found is >> anticipated segments, Group segments together in 'best' arrangement.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int eliminate_excess_minima(int *local_minima_cnt,int *pos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, m, j, bestgroup = 0; /* if found-segs is exact multiple of anticipated-segs, bestgrouping starts at position 0 */
|
|
|
|
|
+ int more_than_possible = dz->insams[0]; /* i.e. too large to be reached by calculation */
|
|
|
|
|
+ int segcnt = (*local_minima_cnt) - 1; /* Number of segs found e.g. 19 */
|
|
|
|
|
+ int grouping_cnt = segcnt/dz->iparam[RRR_GET]; /* How many segs to join-as-a-group, to make no of segs tally with anticipated value */
|
|
|
|
|
+ /* if get=4 19/4 --> 4 by integer truncation */
|
|
|
|
|
+ int remnant = (int)(segcnt - (grouping_cnt * dz->iparam[RRR_GET])); /* How many segments are then spare at start or end of sequence of segs */
|
|
|
|
|
+ /* e.g. 19 - 16 = 3 */
|
|
|
|
|
+ int diff, mindiff = more_than_possible;
|
|
|
|
|
+ int grouped_len, max_grouped_len, min_grouped_len;
|
|
|
|
|
+ for(n=0;n<remnant;n++) { /* for all possible sets of consecutive segments i.e. in example 0-15, 1-16, 2-17, 3-18 */
|
|
|
|
|
+ grouped_len = 0; /* starting at 0,1,2,3 respectively */
|
|
|
|
|
+ max_grouped_len = 0;
|
|
|
|
|
+ min_grouped_len = more_than_possible;
|
|
|
|
|
+ for(m=n;m < segcnt;m+=grouping_cnt) {
|
|
|
|
|
+ for(j=0;j<grouping_cnt;j++) /* combine consecutive segs in groups of 'grouping_cnt', summing lengths */
|
|
|
|
|
+ grouped_len += pos[m+j]; /* find max and min lengths of new grouped-segments */
|
|
|
|
|
+ max_grouped_len = max(max_grouped_len,grouped_len);
|
|
|
|
|
+ min_grouped_len = min(min_grouped_len,grouped_len);
|
|
|
|
|
+ } /* Find range of the new lengths */
|
|
|
|
|
+ diff = max_grouped_len - min_grouped_len;
|
|
|
|
|
+ if(diff < mindiff)
|
|
|
|
|
+ bestgroup = n; /* look for set of grouped-segments with lowest range */
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n= 0,m=bestgroup;m < *local_minima_cnt;n++,m+=grouping_cnt)
|
|
|
|
|
+ pos[n] = pos[m]; /* group orig segs by overwriting intermediate min-positions */
|
|
|
|
|
+ *local_minima_cnt = n;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* TIMESTRETCH_ITERATIVE2 *******************************/
|
|
|
|
|
+
|
|
|
|
|
+int timestretch_iterative2(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+/* double maxenv = 10000.0;*/
|
|
|
|
|
+ int n, m, k, rrr_cnt, rrr_start=0, peakwidth;
|
|
|
|
|
+ int *trofpnt;
|
|
|
|
|
+ int trofpntcnt = 0, lasttrofpntcnt = 0;
|
|
|
|
|
+ float lastenval;
|
|
|
|
|
+ int could_be_rrr_flap, gotrrr = 0;
|
|
|
|
|
+ int envcnt;
|
|
|
|
|
+ fprintf(stdout,"INFO: Searching file envelope.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ rrr_cnt = -dz->iparam[RRR_SKIP]; /* Number of iterate units to skip before utilising any of them */
|
|
|
|
|
+ if(((envcnt = dz->insams[0]/dz->iparam[RRR_SAMP_WSIZENU]) * dz->iparam[RRR_SAMP_WSIZENU])!=dz->insams[0])
|
|
|
|
|
+ envcnt++;
|
|
|
|
|
+ if((dz->env=(float *)malloc((envcnt+20) * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for envelope array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = extract_rrr_env_from_sndfile(RRR_SAMP_WSIZENU,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((trofpnt = (int *)malloc(envcnt * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY TO ANALYSE ENVELOPE.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ trofpnt[0] = 0;
|
|
|
|
|
+ lastenval = dz->env[0];
|
|
|
|
|
+ n = 1;
|
|
|
|
|
+ while(n < envcnt) { /* GET FIRST ENVELOPE TROUGH */
|
|
|
|
|
+ if(dz->env[n] > lastenval) {
|
|
|
|
|
+ trofpnt[0] = 0;
|
|
|
|
|
+ lastenval = dz->env[n];
|
|
|
|
|
+ n++;
|
|
|
|
|
+ break;
|
|
|
|
|
+ } else if (dz->env[n] < lastenval) {
|
|
|
|
|
+ trofpnt[0] = n;
|
|
|
|
|
+ lastenval = dz->env[n];
|
|
|
|
|
+ n++;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ lastenval = dz->env[n];
|
|
|
|
|
+ n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(n >= envcnt) {
|
|
|
|
|
+ sprintf(errstr,"NO PEAKS FOUND IN ENVELOPE\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ while(n < envcnt) { /* GET ENVELOPE TROUGHS */
|
|
|
|
|
+ if(dz->env[n] > lastenval) {
|
|
|
|
|
+ trofpntcnt = lasttrofpntcnt + 1;
|
|
|
|
|
+ } else if (dz->env[n] < lastenval) {
|
|
|
|
|
+ trofpnt[trofpntcnt] = n;
|
|
|
|
|
+ lasttrofpntcnt = trofpntcnt;
|
|
|
|
|
+ }
|
|
|
|
|
+ lastenval = dz->env[n];
|
|
|
|
|
+ n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(trofpntcnt < 2) {
|
|
|
|
|
+ sprintf(errstr,"NO SIGNIFICANT PEAKS FOUND IN ENVELOPE\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(m = 0, n=1;n<trofpntcnt;m++,n++) {
|
|
|
|
|
+ peakwidth = trofpnt[n] - trofpnt[m];
|
|
|
|
|
+ if(peakwidth > 2 && peakwidth < 6) { /* IF PEAK WIDTH IS WITHIN LIMITS FOR AN ITERATE-UNIT */
|
|
|
|
|
+ could_be_rrr_flap = 0;
|
|
|
|
|
+ for(k = trofpnt[m]; k < trofpnt[n]; k++) { /* AND PEAK IS ABOVE GATE */
|
|
|
|
|
+ if(dz->env[k] > dz->param[RRR_GATE]) {
|
|
|
|
|
+ could_be_rrr_flap = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(could_be_rrr_flap) {
|
|
|
|
|
+ if(rrr_cnt == 0) /* IF (skipped unwanted flaps &) NO FLAPS HERE YET */
|
|
|
|
|
+ rrr_start = m; /* MARK START OF A POSSIBLE FLAP */
|
|
|
|
|
+ rrr_cnt++; /* COUNT FLAPS */
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ could_be_rrr_flap = 0; /* MARK NON-FLAP */
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!could_be_rrr_flap) {
|
|
|
|
|
+ if(rrr_cnt >= dz->iparam[RRR_GET]) { /* IF END OF FLAPS, AND WE HAVE ENOUGH ADJACENT FLAPS */
|
|
|
|
|
+ /* SET PARAMS FOR ZER-CROSSING SEARCH */
|
|
|
|
|
+ dz->iparam[RRR_START] = trofpnt[rrr_start] * dz->iparam[RRR_SAMP_WSIZENU];
|
|
|
|
|
+ dz->iparam[RRR_START] -= dz->iparam[RRR_SAMP_WSIZENU]/ 2; /* Start search before first flap segment */
|
|
|
|
|
+ dz->iparam[RRR_START] = max(0,dz->iparam[RRR_START]);
|
|
|
|
|
+ dz->iparam[RRR_END] = trofpnt[m] * dz->iparam[RRR_SAMP_WSIZENU];;
|
|
|
|
|
+ dz->iparam[RRR_END] += dz->iparam[RRR_SAMP_WSIZENU]/ 2; /* End search after last flap segment */
|
|
|
|
|
+ dz->iparam[RRR_END] = min(dz->insams[0],dz->iparam[RRR_END]);
|
|
|
|
|
+ dz->param[RRR_START] = (double)dz->iparam[RRR_START]/dz->infile->srate;
|
|
|
|
|
+ dz->param[RRR_END] = (double)dz->iparam[RRR_END]/dz->infile->srate;
|
|
|
|
|
+// dz->iparam[RRR_GET] = rrr_cnt;
|
|
|
|
|
+// EXPERIMENTAL!! FORCES zero-cross algo to get better result
|
|
|
|
|
+// if algo finds 8 zcs and there are really rrr_cnt=4, as 8 >= 2 * 4 , it groups the zcs in pairs to give 4 zcs
|
|
|
|
|
+// However, if algo finds 7 zcs and there are really rrr_cnt=4
|
|
|
|
|
+// 7 < (2*4), so it doesn't group the zcs in twos, so 7 zcs are kept, probalby too many...
|
|
|
|
|
+// With this mod 7 > 2*(rrr_cnt-1 = 3) so it groups the number of zcs in 2s (and throws 1 away) to give 3 zcs: better result
|
|
|
|
|
+ dz->iparam[RRR_GET] = rrr_cnt - 1;
|
|
|
|
|
+ gotrrr = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ rrr_cnt = -dz->iparam[RRR_SKIP];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(gotrrr == 0) {
|
|
|
|
|
+ sprintf(errstr,"NO ITERATIVE LOCATION FOUND\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fprintf(stdout,"INFO: searching between %.04lf and %.04lf secs: where %d peaks found\n",dz->param[RRR_START],dz->param[RRR_END],rrr_cnt);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ return timestretch_iterative(dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* EXTRACT_RRR_ENV_FROM_SNDFILE *******************************/
|
|
|
|
|
+
|
|
|
|
|
+int extract_rrr_env_from_sndfile(int paramno,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n;
|
|
|
|
|
+ float *envptr;
|
|
|
|
|
+ int bufcnt;
|
|
|
|
|
+ if(((bufcnt = dz->insams[0]/dz->buflen)*dz->buflen)!=dz->insams[0])
|
|
|
|
|
+ bufcnt++;
|
|
|
|
|
+ envptr = dz->env;
|
|
|
|
|
+ for(n = 0; n < bufcnt; n++) {
|
|
|
|
|
+ if((dz->ssampsread = fgetfbufEx(dz->sampbuf[0], dz->buflen,dz->ifd[0],0)) < 0) {
|
|
|
|
|
+ sprintf(errstr,"Can't read samples from soundfile: extract_rrr_env_from_sndfile()\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ display_virtual_time(dz->total_samps_read,dz);
|
|
|
|
|
+ get_rrrenv_of_buffer(dz->ssampsread,dz->iparam[paramno],&envptr,dz->sampbuf[0]);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->envend = envptr;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* GET_RRRENV_OF_BUFFER *******************************/
|
|
|
|
|
+
|
|
|
|
|
+void get_rrrenv_of_buffer(int samps_to_process,int envwindow_sampsize,float **envptr,float *buffer)
|
|
|
|
|
+{
|
|
|
|
|
+ int start_samp = 0;
|
|
|
|
|
+ float *env = *envptr;
|
|
|
|
|
+ while(samps_to_process >= envwindow_sampsize) {
|
|
|
|
|
+ *env++ = getmaxsampr(start_samp,envwindow_sampsize,buffer);
|
|
|
|
|
+ start_samp += envwindow_sampsize;
|
|
|
|
|
+ samps_to_process -= envwindow_sampsize;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(samps_to_process) /* Handle any final short buffer */
|
|
|
|
|
+ *env++ = getmaxsampr(start_samp,samps_to_process,buffer);
|
|
|
|
|
+ *envptr = env;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*************************** GETMAXSAMPR ******************************/
|
|
|
|
|
+
|
|
|
|
|
+float getmaxsampr(int startsamp, int sampcnt,float *buffer)
|
|
|
|
|
+{
|
|
|
|
|
+ int i, endsamp = startsamp + sampcnt;
|
|
|
|
|
+ float thisval, thismaxsamp = 0.0f;
|
|
|
|
|
+ for(i = startsamp; i<endsamp; i++) {
|
|
|
|
|
+ if((thisval = (float)fabs(buffer[i]))>thismaxsamp)
|
|
|
|
|
+ thismaxsamp = thisval;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(thismaxsamp);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/********************************** GRAB_NOISE_AND_EXPAND **********************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * Locate noise, then expand it by random-reads from zero-cross to zero-cross
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int grab_noise_and_expand(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
|
|
|
|
|
+ int phase, initialphase, isnoise = -1, finished = 0;
|
|
|
|
|
+ int j, k, n, m, waveset_cnt;
|
|
|
|
|
+ int lastzcross = 0, sampstart, sampend, len, temp, orig_buflen;
|
|
|
|
|
+ int brkpntcnt = 0, got_noise = 0;
|
|
|
|
|
+ double maxsamp, gate = dz->param[SSS_GATE];
|
|
|
|
|
+ int abovegate = 0;
|
|
|
|
|
+ if((dz->lparray[0] = (int *)malloc(dz->insams[0] * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY.\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ fprintf(stdout,"INFO: Searching for noise.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ orig_buflen = dz->buflen;
|
|
|
|
|
+ dz->buflen = dz->insams[0];
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ else if(dz->ssampsread <= 0) {
|
|
|
|
|
+ sprintf(errstr,"Failed to read sound from input file\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->buflen = orig_buflen;
|
|
|
|
|
+
|
|
|
|
|
+ /* ESTABLISH INITIAL PHASE OF SIGNAL */
|
|
|
|
|
+
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ while(ibuf[n]==0) {
|
|
|
|
|
+ if(++n >= dz->ssampsread) {
|
|
|
|
|
+ sprintf(errstr,"FAILED TO FIND ANY WAVECYCLES IN FILE.\n");
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(ibuf[n] > 0)
|
|
|
|
|
+ initialphase = 1;
|
|
|
|
|
+ else
|
|
|
|
|
+ initialphase = -1;
|
|
|
|
|
+
|
|
|
|
|
+ for(;;) {
|
|
|
|
|
+
|
|
|
|
|
+ /* FIND A WAVECYCLE */
|
|
|
|
|
+ maxsamp = 0.0;
|
|
|
|
|
+ if(initialphase == 1) {
|
|
|
|
|
+ while(ibuf[n] > 0) {
|
|
|
|
|
+ maxsamp = max(maxsamp,ibuf[n]);
|
|
|
|
|
+ if(++n >= dz->ssampsread) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ while(ibuf[n] <= 0) {
|
|
|
|
|
+ maxsamp = max(maxsamp,-ibuf[n]);
|
|
|
|
|
+ if(++n >= dz->ssampsread) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ while(ibuf[n] < 0) {
|
|
|
|
|
+ maxsamp = max(maxsamp,-ibuf[n]);
|
|
|
|
|
+ if(++n >= dz->ssampsread) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ while(ibuf[n] >= 0) {
|
|
|
|
|
+ maxsamp = max(maxsamp,ibuf[n]);
|
|
|
|
|
+ if(++n >= dz->ssampsread) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(finished)
|
|
|
|
|
+ break;
|
|
|
|
|
+ if(maxsamp < gate)
|
|
|
|
|
+ isnoise = 0;
|
|
|
|
|
+ else {
|
|
|
|
|
+ abovegate = 1;
|
|
|
|
|
+ dz->lparray[0][brkpntcnt] = n;
|
|
|
|
|
+ /* MEASURE WAVE-CYCLE LENGTH, AND TEST FOR NOISE */
|
|
|
|
|
+ /* IF SIGNAL SWITCHES FROM NOISE to NOT-NOISE or vice versa, STORE THAT POSITION */
|
|
|
|
|
+ if(dz->lparray[0][brkpntcnt] - lastzcross < dz->iparam[NOISE_MINFRQ]) {
|
|
|
|
|
+ if(brkpntcnt == 0) /* if noise-start pos, move to search for noise-end position */
|
|
|
|
|
+ brkpntcnt = 1;
|
|
|
|
|
+ else if(dz->lparray[0][1] - dz->lparray[0][0] >= dz->iparam[MAX_NOISLEN]) {
|
|
|
|
|
+ got_noise = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ isnoise = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if(isnoise == 1) { /* if at end of noise ... */
|
|
|
|
|
+ /* if enough noise present ... break */
|
|
|
|
|
+ if(dz->lparray[0][1] - dz->lparray[0][0] > dz->iparam[MIN_NOISLEN]) {
|
|
|
|
|
+ got_noise = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ } else { /* if NOT ENOUGH noise present, delete noise pos data, start again */
|
|
|
|
|
+ dz->lparray[0][0] = dz->lparray[0][1];
|
|
|
|
|
+ brkpntcnt = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ isnoise = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ lastzcross = n; /* store position of last waveset end... */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* CHECK THAT ANY NOISE : non-NOISE SWITCHES FOUND */
|
|
|
|
|
+
|
|
|
|
|
+ if(!abovegate) {
|
|
|
|
|
+ sprintf(errstr,"NO SIGNAL IS ABOVE THE GATE LEVEL\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!got_noise) {
|
|
|
|
|
+ if(gate > 0)
|
|
|
|
|
+ sprintf(errstr,"NO NOISE FOUND WITH GATE-LEVEL %lf\n",gate);
|
|
|
|
|
+ else
|
|
|
|
|
+ sprintf(errstr,"NO NOISE FOUND\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ fprintf(stdout,"INFO: Generating output.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ sampstart = dz->lparray[0][0];
|
|
|
|
|
+ sampend = dz->lparray[0][1];
|
|
|
|
|
+ waveset_cnt = 0;
|
|
|
|
|
+ if(ibuf[sampstart] > 0) {
|
|
|
|
|
+ initialphase = 1;
|
|
|
|
|
+ phase = 1;
|
|
|
|
|
+ dz->lparray[0][waveset_cnt++] = sampstart;
|
|
|
|
|
+ } else if (ibuf[sampstart] < 0) {
|
|
|
|
|
+ initialphase = -1;
|
|
|
|
|
+ phase = -1;
|
|
|
|
|
+ dz->lparray[0][waveset_cnt++] = sampstart;
|
|
|
|
|
+ } else
|
|
|
|
|
+ phase = 0;
|
|
|
|
|
+ /* STORE ZERO-CROSS-PAIR POSITIONS */
|
|
|
|
|
+ for(n = sampstart+1;n < sampend; n++) {
|
|
|
|
|
+ switch(phase) {
|
|
|
|
|
+ case(0):
|
|
|
|
|
+ if(ibuf[n] > 0) {
|
|
|
|
|
+ phase = 1;
|
|
|
|
|
+ initialphase = 1;
|
|
|
|
|
+ dz->lparray[0][waveset_cnt++] = n;
|
|
|
|
|
+ } else if(ibuf[n] < 0) {
|
|
|
|
|
+ phase = -1;
|
|
|
|
|
+ initialphase = -1;
|
|
|
|
|
+ dz->lparray[0][waveset_cnt++] = n;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(1):
|
|
|
|
|
+ if(ibuf[n] < 0) {
|
|
|
|
|
+ if(initialphase == -1)
|
|
|
|
|
+ dz->lparray[0][waveset_cnt++] = n;
|
|
|
|
|
+ phase = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(-1):
|
|
|
|
|
+ if(ibuf[n] > 0) {
|
|
|
|
|
+ if(initialphase == 1)
|
|
|
|
|
+ dz->lparray[0][waveset_cnt++] = n;
|
|
|
|
|
+ phase = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ if(!dz->vflag[0]) {
|
|
|
|
|
+ for(n=0;n<sampstart;n++) {
|
|
|
|
|
+ obuf[j++] = ibuf[n];
|
|
|
|
|
+ if(j >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(;;) {
|
|
|
|
|
+ n = (int)floor(drand48() * waveset_cnt); /* RANDOM READS TO AND FROM ZERO-CROSSINGS */
|
|
|
|
|
+ do {
|
|
|
|
|
+ m = (int)floor(drand48() * waveset_cnt);
|
|
|
|
|
+ } while (m == n);
|
|
|
|
|
+ if((len = dz->lparray[0][m] - dz->lparray[0][n]) < 0) {
|
|
|
|
|
+ temp = m;
|
|
|
|
|
+ m = n;
|
|
|
|
|
+ n = temp;
|
|
|
|
|
+ len = -len;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(j + len >= dz->iparam[SSS_DUR]) /* HALT AT A ZERO CROSSING */
|
|
|
|
|
+ break;
|
|
|
|
|
+ for(k= dz->lparray[0][n]; k < dz->lparray[0][m];k++) {
|
|
|
|
|
+ obuf[j++] = ibuf[k];
|
|
|
|
|
+ if(j >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->iparam[SSS_DUR] -= dz->buflen;
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!dz->vflag[0]) {
|
|
|
|
|
+ for(n=sampend;n<dz->insams[0];n++) {
|
|
|
|
|
+ obuf[j++] = ibuf[n];
|
|
|
|
|
+ if(j >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ j = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(j > 0) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,j,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** GREV **********************/
|
|
|
|
|
+
|
|
|
|
|
+int grev(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status, finished, start_negative;
|
|
|
|
|
+ int n, j=0, k, minpeakloc, envcnt, last_total_samps_read, startsearch, endsearch, obufpos;
|
|
|
|
|
+ int lastobufpos, step, expansion, lastgrainlen=0, nu_gp_dur;
|
|
|
|
|
+ double maxsamp0, maxsamp1, peakav, minpeakav, time;
|
|
|
|
|
+ int firsttrof, up, gotmaxsamp0, crossed_zero_to_positive, crossed_zero_to_negative, gp=0, read_brk = 0;
|
|
|
|
|
+ float *e, *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
|
|
|
|
|
+ int *pa;
|
|
|
|
|
+ double convertor = 1.0 / dz->infile->srate;
|
|
|
|
|
+
|
|
|
|
|
+ if(((envcnt = dz->insams[0]/dz->iparam[GREV_SAMP_WSIZE]) * dz->iparam[GREV_SAMP_WSIZE])!=dz->insams[0])
|
|
|
|
|
+ envcnt++;
|
|
|
|
|
+ if((dz->env=(float *)malloc((envcnt + 12) * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for envelope array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ e = dz->env;
|
|
|
|
|
+ if((pa =(int *)malloc((envcnt + 12) * sizeof(int)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for peak positions array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = extract_rrr_env_from_sndfile(GREV_SAMP_WSIZE,dz))<0) /* Get envel of whole sound */
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->total_samps_read = 0;
|
|
|
|
|
+ display_virtual_time(0,dz);
|
|
|
|
|
+ envcnt = dz->envend - dz->env;
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ k = 0;
|
|
|
|
|
+ pa[k++] = 0;
|
|
|
|
|
+ while(flteq(e[n],e[0])) {
|
|
|
|
|
+ n++;
|
|
|
|
|
+ if(n >= envcnt) {
|
|
|
|
|
+ sprintf(errstr,"NO PEAKS IN THE FILE\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(e[n] < e[0]) {
|
|
|
|
|
+ firsttrof = 1;
|
|
|
|
|
+ up = -1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ firsttrof = 0;
|
|
|
|
|
+ up = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* KEEP ONLY THE PEAKS AND TROUGHS OF THE ENVELOPE, AND THEIR LOCATIONS */
|
|
|
|
|
+
|
|
|
|
|
+ while (n <envcnt) { /* store peaks and troughs only */
|
|
|
|
|
+ switch(up) {
|
|
|
|
|
+ case(1):
|
|
|
|
|
+ if(e[n] < e[n-1]) {
|
|
|
|
|
+ dz->env[k] = dz->env[n-1];
|
|
|
|
|
+ pa[k] = (n-1) * dz->iparam[GREV_SAMP_WSIZE];
|
|
|
|
|
+ k++;
|
|
|
|
|
+ up = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(-1):
|
|
|
|
|
+ if(e[n] > e[n-1]) {
|
|
|
|
|
+ dz->env[k] = dz->env[n-1];
|
|
|
|
|
+ pa[k] = (n-1) * dz->iparam[GREV_SAMP_WSIZE];
|
|
|
|
|
+ k++;
|
|
|
|
|
+ up = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((envcnt = k) <= 3) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT PEAKS IN THE FILE.\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* KEEP ONLY THE (DEEP ENOUGH) TROUGHS OF THE ENVELOPE */
|
|
|
|
|
+
|
|
|
|
|
+ switch(firsttrof) {
|
|
|
|
|
+ case(0): /* if trof at start */
|
|
|
|
|
+ k = 1; /* set item at 0 NOT to be overwritten (as it is first trof) (set k=1) */
|
|
|
|
|
+ j = 1; /* search for good trofs between peaks, from (j=)1 */
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(1): /* if trof not at start */
|
|
|
|
|
+ k = 0; /* set item at 0 to be overwritten by 1st trof found (k=0) */
|
|
|
|
|
+ j = 0; /* search for good trofs between peaks, from (j=)0 */
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=j;n<envcnt-2;n++) {
|
|
|
|
|
+ peakav = dz->env[n] + dz->env[n+2];
|
|
|
|
|
+ if(peakav * dz->param[GREV_TROFRAC] >= dz->env[n+1]) { /* NB TROF_FAC alreday PRE-MULTIPLIED by 2.0 */
|
|
|
|
|
+ pa[k] = pa[n+1];
|
|
|
|
|
+ k++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((envcnt = k) <= 3) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT VALID TROUGHS IN THE FILE.\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* SEARCH WAVEFORM FOR ZERO_CROSSING AT MORE ACCURATE TROUGH */
|
|
|
|
|
+
|
|
|
|
|
+ fprintf(stdout,"INFO: Number of grains found = %d\n",envcnt);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],0,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error 1\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ last_total_samps_read = 0;
|
|
|
|
|
+ k = (int)round((double)dz->iparam[GREV_SAMP_WSIZE] * 0.5); /* search around size of envel window */
|
|
|
|
|
+ startsearch = max(pa[0] - k, 0);
|
|
|
|
|
+ endsearch = min(pa[0] + k,dz->insams[0]);
|
|
|
|
|
+ dz->total_samps_read = 0;
|
|
|
|
|
+ while(startsearch > dz->buflen) {
|
|
|
|
|
+ dz->total_samps_read += dz->buflen;
|
|
|
|
|
+ startsearch -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->total_samps_read > 0) {
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],dz->total_samps_read,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error 2\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ last_total_samps_read = dz->total_samps_read;
|
|
|
|
|
+ endsearch -= last_total_samps_read;
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ finished = 0;
|
|
|
|
|
+ while(n<envcnt) {
|
|
|
|
|
+ maxsamp0 = 0.0;
|
|
|
|
|
+ maxsamp1 = 0.0;
|
|
|
|
|
+ gotmaxsamp0 = 0;
|
|
|
|
|
+ minpeakav = HUGE;
|
|
|
|
|
+ minpeakloc = -1;
|
|
|
|
|
+ j = startsearch;
|
|
|
|
|
+ crossed_zero_to_positive = 0;
|
|
|
|
|
+ crossed_zero_to_negative = 0;
|
|
|
|
|
+ if(ibuf[j] <= 0)
|
|
|
|
|
+ start_negative = 1;
|
|
|
|
|
+ else
|
|
|
|
|
+ start_negative = 0;
|
|
|
|
|
+ do {
|
|
|
|
|
+ if(j >= dz->ssampsread) {
|
|
|
|
|
+ last_total_samps_read = dz->total_samps_read;
|
|
|
|
|
+ endsearch -= dz->buflen;
|
|
|
|
|
+ j -= dz->buflen;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->ssampsread == 0) {
|
|
|
|
|
+ finished = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!crossed_zero_to_negative) { /* before signal crosses to negative */
|
|
|
|
|
+ if(start_negative) {
|
|
|
|
|
+ if(ibuf[j] <= 0.0) {
|
|
|
|
|
+ j++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ start_negative = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!gotmaxsamp0) { /* First time only, look for first maxsamp */
|
|
|
|
|
+ if(ibuf[j] > maxsamp0) /* (after first time, it gets val passed back from 2nd maxsamp */
|
|
|
|
|
+ maxsamp0 = ibuf[j];
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ibuf[j] < 0.0) { /* if not crossed zero to -ve, look for, and mark, zero-cross to -ve */
|
|
|
|
|
+ crossed_zero_to_negative = j + last_total_samps_read;
|
|
|
|
|
+ gotmaxsamp0 = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (ibuf[j] >= 0) { /* if crossed zero to neg and we're now crossing back to +ve */
|
|
|
|
|
+ crossed_zero_to_positive = 1;
|
|
|
|
|
+ if(ibuf[j] > maxsamp1) /* look for 2nd maxsamp */
|
|
|
|
|
+ maxsamp1 = ibuf[j];
|
|
|
|
|
+ } else if (crossed_zero_to_positive) { /* having crossed from -ve to +ve, we're now -ve again, in a new cycle */
|
|
|
|
|
+ if((peakav = maxsamp0 + maxsamp1) < minpeakav) {
|
|
|
|
|
+ minpeakav = peakav;
|
|
|
|
|
+ minpeakloc = crossed_zero_to_negative;
|
|
|
|
|
+ }
|
|
|
|
|
+ maxsamp0 = maxsamp1;
|
|
|
|
|
+ crossed_zero_to_positive = 0;
|
|
|
|
|
+ crossed_zero_to_negative = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ j++;
|
|
|
|
|
+ } while(j < endsearch || minpeakloc < 0);
|
|
|
|
|
+
|
|
|
|
|
+ if(minpeakloc < 0) {
|
|
|
|
|
+ if (finished) { /* deal with endcases where waveform fails to cross zero (twice) */
|
|
|
|
|
+ if(crossed_zero_to_negative > 0)
|
|
|
|
|
+ pa[n++] = crossed_zero_to_negative;
|
|
|
|
|
+ envcnt = n;
|
|
|
|
|
+ break;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ sprintf(errstr,"FAILED TO FIND ONE OF THE LOCAL MINIMA.\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ pa[n] = minpeakloc;
|
|
|
|
|
+ n++;
|
|
|
|
|
+ startsearch = max(pa[n] - k, 0);
|
|
|
|
|
+ endsearch = min(pa[n] + k,dz->insams[0]);
|
|
|
|
|
+ if(startsearch >= dz->total_samps_read) {
|
|
|
|
|
+ while(startsearch >= dz->total_samps_read) {
|
|
|
|
|
+ last_total_samps_read = dz->total_samps_read;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(last_total_samps_read >= dz->total_samps_read) {
|
|
|
|
|
+ envcnt = n;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ startsearch -= last_total_samps_read;
|
|
|
|
|
+ endsearch -= last_total_samps_read;
|
|
|
|
|
+ while(startsearch < 0) { /* very tiny windows may cause backtracking in file */
|
|
|
|
|
+ last_total_samps_read -= dz->buflen;
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],last_total_samps_read,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error 3\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->total_samps_read = last_total_samps_read + dz->ssampsread;
|
|
|
|
|
+ startsearch += dz->buflen;
|
|
|
|
|
+ endsearch += dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],0,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error 4\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->total_samps_read = 0;
|
|
|
|
|
+ last_total_samps_read = 1; /* Value 1 forces first seek and read */
|
|
|
|
|
+ obufpos = 0;
|
|
|
|
|
+ switch(dz->mode) {
|
|
|
|
|
+ case(GREV_REVERSE):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ for(n = envcnt - (2 * gp); n>0; n-=gp) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT]) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ }
|
|
|
|
|
+ endsearch = pa[n + gp];
|
|
|
|
|
+ if((exit_status = do_envgrain_write(startsearch,endsearch,&last_total_samps_read,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GREV_REPEAT):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ if(dz->brksize[GREV_REPETS] || dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ read_brk = 1;
|
|
|
|
|
+ for(n = 0; n<=(envcnt-gp); n+=gp) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(read_brk) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ if(dz->brksize[GREV_REPETS])
|
|
|
|
|
+ dz->iparam[GREV_REPETS] = (int)round(dz->param[GREV_REPETS]);
|
|
|
|
|
+ endsearch = pa[n + gp];
|
|
|
|
|
+ for(k = 0;k < dz->iparam[GREV_REPETS];k++) {
|
|
|
|
|
+ if((exit_status = do_envgrain_write(startsearch,endsearch,&last_total_samps_read,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GREV_DELETE):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ if(dz->brksize[GREV_KEEP] || dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ read_brk = 1;
|
|
|
|
|
+ for(n = 0; n<=(envcnt-gp); n+=gp) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(read_brk) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ if(dz->brksize[GREV_KEEP])
|
|
|
|
|
+ dz->iparam[GREV_KEEP] = (int)round(dz->param[GREV_KEEP]);
|
|
|
|
|
+ endsearch = pa[n + gp];
|
|
|
|
|
+ if((n % dz->iparam[GREV_OUTOF]) < dz->iparam[GREV_KEEP]) {
|
|
|
|
|
+ if((exit_status = do_envgrain_write(startsearch,endsearch,&last_total_samps_read,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GREV_OMIT):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ if(dz->brksize[GREV_KEEP] || dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ read_brk = 1;
|
|
|
|
|
+ for(n = 0; n<=(envcnt-gp); n+=gp) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(read_brk) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ if(dz->brksize[GREV_KEEP])
|
|
|
|
|
+ dz->iparam[GREV_KEEP] = (int)round(dz->param[GREV_KEEP]);
|
|
|
|
|
+ endsearch = pa[n + gp];
|
|
|
|
|
+ if((n % dz->iparam[GREV_OUTOF]) < dz->iparam[GREV_KEEP]) {
|
|
|
|
|
+ if((exit_status = do_envgrain_write(startsearch,endsearch,&last_total_samps_read,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if((exit_status = do_envgrain_zerowrite(startsearch,endsearch,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GREV_TSTRETCH):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ if(dz->brksize[GREV_TSTR] || dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ read_brk = 1;
|
|
|
|
|
+ for(n = 0; n<=envcnt-1; n++) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(read_brk) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ endsearch = pa[n + 1];
|
|
|
|
|
+ lastobufpos = obufpos + dz->total_samps_written;
|
|
|
|
|
+ if((exit_status = do_envgrain_addwrite(startsearch,endsearch,&last_total_samps_read,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ step = obufpos + dz->total_samps_written - lastobufpos;
|
|
|
|
|
+ expansion = (int)round((double)step * dz->param[GREV_TSTR]) - step;
|
|
|
|
|
+ if(expansion > 0) {
|
|
|
|
|
+ if((exit_status = do_envgrain_zerowrite_dblbuf(0,expansion,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ } else
|
|
|
|
|
+ obufpos += expansion;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GREV_GET):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ else
|
|
|
|
|
+ read_brk = 1;
|
|
|
|
|
+
|
|
|
|
|
+ for(n = 0; n<=(envcnt-gp); n+=gp) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(read_brk) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ fprintf(dz->fp,"%d\n",startsearch);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(GREV_PUT):
|
|
|
|
|
+ if(!dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = dz->iparam[GREV_GPCNT];
|
|
|
|
|
+ else
|
|
|
|
|
+ read_brk = 1;
|
|
|
|
|
+ for(n = 0; n<=(envcnt-gp); n+=gp) {
|
|
|
|
|
+ startsearch = pa[n];
|
|
|
|
|
+ if(read_brk) {
|
|
|
|
|
+ time = (double)startsearch * convertor;
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[GREV_GPCNT])
|
|
|
|
|
+ gp = (int)round(dz->param[GREV_GPCNT]);
|
|
|
|
|
+ endsearch = pa[n + gp];
|
|
|
|
|
+ if(n > 0) {
|
|
|
|
|
+ if(n >= dz->itemcnt)
|
|
|
|
|
+ break;
|
|
|
|
|
+ nu_gp_dur = (int)round(dz->parray[GR_SYNCTIME][n] - dz->parray[GR_SYNCTIME][n-1]);
|
|
|
|
|
+ obufpos += (nu_gp_dur - lastgrainlen);
|
|
|
|
|
+ if(obufpos <= -dz->buflen) {
|
|
|
|
|
+ sprintf(errstr,"BACKTRACK TOO LARGE\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = do_envgrain_write(startsearch,endsearch,&last_total_samps_read,&obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ lastgrainlen = endsearch - startsearch;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(obufpos > 0) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_ENVGRAIN_WRITE **********************/
|
|
|
|
|
+
|
|
|
|
|
+int do_envgrain_write(int startsearch,int endsearch,int *last_total_samps_read,int *obufpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int step, n, m, limit = dz->buflen;
|
|
|
|
|
+ float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
|
|
|
|
|
+ if(startsearch > dz->total_samps_read || startsearch < *last_total_samps_read) {
|
|
|
|
|
+ step = (startsearch / dz->buflen) * dz->buflen;
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],step,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error 5\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *last_total_samps_read = step;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->total_samps_read = *last_total_samps_read + dz->ssampsread;
|
|
|
|
|
+ }
|
|
|
|
|
+ startsearch -= *last_total_samps_read;
|
|
|
|
|
+ endsearch -= *last_total_samps_read;
|
|
|
|
|
+ m = *obufpos;
|
|
|
|
|
+ if(dz->mode == GREV_PUT) {
|
|
|
|
|
+ limit *= 2;
|
|
|
|
|
+ while(m >= limit) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memcpy((char *)dz->sampbuf[1],(char *)dz->sampbuf[2],dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)dz->sampbuf[2],0,dz->buflen * sizeof(float));
|
|
|
|
|
+ m -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n=startsearch;n <endsearch;n++) {
|
|
|
|
|
+ if(n >= dz->buflen) {
|
|
|
|
|
+ *last_total_samps_read = dz->total_samps_read;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ endsearch -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ obuf[m++] = ibuf[n];
|
|
|
|
|
+ if(m >= limit) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->mode == GREV_PUT) { /* deals with bufptr < 0 */
|
|
|
|
|
+ memcpy((char *)dz->sampbuf[1],(char *)dz->sampbuf[2],dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)dz->sampbuf[2],0,dz->buflen * sizeof(float));
|
|
|
|
|
+ m = dz->buflen;
|
|
|
|
|
+ } else
|
|
|
|
|
+ m = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufpos = m;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_ENVGRAIN_ZEROWRITE **********************/
|
|
|
|
|
+
|
|
|
|
|
+int do_envgrain_zerowrite(int startsearch,int endsearch,int *obufpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, m;
|
|
|
|
|
+ float *obuf = dz->sampbuf[1];
|
|
|
|
|
+ m = *obufpos;
|
|
|
|
|
+ for(n=startsearch;n <endsearch;n++) {
|
|
|
|
|
+ if(m >= dz->buflen) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ m = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ obuf[m++] = 0.0;
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufpos = m;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_ENVGRAIN_ZEROWRITE_DBLBUF **********************/
|
|
|
|
|
+
|
|
|
|
|
+int do_envgrain_zerowrite_dblbuf(int startsearch,int endsearch,int *obufpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int n, m;
|
|
|
|
|
+ float *obuf = dz->sampbuf[1], *obuf2 = dz->sampbuf[2];
|
|
|
|
|
+ m = *obufpos;
|
|
|
|
|
+ for(n=startsearch;n <endsearch;n++) {
|
|
|
|
|
+ if(m >= dz->buflen * 2) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memcpy((char *)obuf,(char *)obuf2,dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)obuf2,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ m -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ obuf[m++] = 0.0;
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufpos = m;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** DO_ENVGRAIN_ADDWRITE **********************/
|
|
|
|
|
+
|
|
|
|
|
+int do_envgrain_addwrite(int startsearch,int endsearch,int *last_total_samps_read,int *obufpos,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int step, n, m;
|
|
|
|
|
+ float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1], *obuf2 = dz->sampbuf[2];
|
|
|
|
|
+ if(*obufpos < 0) {
|
|
|
|
|
+ sprintf(errstr,"GRAIN TOO LARGE TO BACKTRACK IN BUFFER.\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(startsearch > dz->total_samps_read || startsearch < *last_total_samps_read) {
|
|
|
|
|
+ step = (startsearch / dz->buflen) * dz->buflen;
|
|
|
|
|
+ if((sndseekEx(dz->ifd[0],step,0))<0) {
|
|
|
|
|
+ sprintf(errstr,"seek error 6\n");
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *last_total_samps_read = step;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->total_samps_read = *last_total_samps_read + dz->ssampsread;
|
|
|
|
|
+ }
|
|
|
|
|
+ startsearch -= *last_total_samps_read;
|
|
|
|
|
+ endsearch -= *last_total_samps_read;
|
|
|
|
|
+ m = *obufpos;
|
|
|
|
|
+ for(n=startsearch;n <endsearch;n++) {
|
|
|
|
|
+ if(n >= dz->buflen) {
|
|
|
|
|
+ *last_total_samps_read = dz->total_samps_read;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ endsearch -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ obuf[m++] += ibuf[n];
|
|
|
|
|
+ if(m >= dz->buflen * 2) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memcpy((char *)obuf,(char *)obuf2,dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)obuf2,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ m -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ *obufpos = m;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/****************************** TIMESTRETCH_ITERATIVE ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int timestretch_iterative3(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ float *obuf = dz->sampbuf[0];
|
|
|
|
|
+ int *pos = dz->lparray[0];
|
|
|
|
|
+ int peakcnt, startsearch, endsearch, local_minima_cnt, minimum_element_len;
|
|
|
|
|
+ int n,z = 0, outpos, samps_to_write;
|
|
|
|
|
+ char *outfilename;
|
|
|
|
|
+
|
|
|
|
|
+ int namelen = strlen(dz->wordstor[0]);
|
|
|
|
|
+ if((outfilename = (char *)malloc(namelen + 4))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient memory\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ strcpy(outfilename,dz->wordstor[0]);
|
|
|
|
|
+ fprintf(stdout,"INFO: Generating output.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ if(sloom)
|
|
|
|
|
+ display_virtual_time(0,dz);
|
|
|
|
|
+ if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->sampbuf[0][dz->insams[0]] = dz->sampbuf[0][dz->insams[0] - 1]; /* wrap around point for interpolation */
|
|
|
|
|
+ startsearch = (int)round(dz->param[RRR_START] * dz->infile->srate);
|
|
|
|
|
+ endsearch = (int)round(dz->param[RRR_END] * dz->infile->srate);
|
|
|
|
|
+
|
|
|
|
|
+ /* FIND ALL POSITIVE PEAKS : always look only at +ve vals, so all zero-crossings eventually found will be from +ve to -ve */
|
|
|
|
|
+
|
|
|
|
|
+ peakcnt = 0;
|
|
|
|
|
+ if((exit_status = find_all_positive_peaks(startsearch,endsearch,&peakcnt,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ /* FIND ALL POSITIVE-PEAK MINIMA : overwriting the arrays peak-vals & peak-position with minima-vals & minima-positions */
|
|
|
|
|
+
|
|
|
|
|
+ local_minima_cnt = 0;
|
|
|
|
|
+ if((exit_status = find_all_local_minima(peakcnt,&local_minima_cnt,dz)) < 0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ /* ELIMINATE SPURIOUS MINIMA */
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = eliminate_spurious_minima(&local_minima_cnt,&minimum_element_len,dz)) < 0)
|
|
|
|
|
+ return (exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ fprintf(stdout,"INFO: Original number of iterated segments found = %d\n",local_minima_cnt - 1);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+
|
|
|
|
|
+ /* CHECK MINIMA FOUND AGAINST INPUT ESTIMATE */
|
|
|
|
|
+
|
|
|
|
|
+ if((local_minima_cnt - 1) >= 2 * dz->iparam[RRR_GET]) {
|
|
|
|
|
+ if((exit_status = eliminate_excess_minima(&local_minima_cnt,pos,dz)) < 0)
|
|
|
|
|
+ return (exit_status);
|
|
|
|
|
+ fprintf(stdout,"INFO: Reduced to = %d\n",local_minima_cnt - 1);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ /* SEARCH FOR ZERO CROSSINGS AFTER MINIMA */
|
|
|
|
|
+
|
|
|
|
|
+ if(local_minima_cnt > 999) {
|
|
|
|
|
+ sprintf(errstr,"Found more than 999 segments. Process terminated.\n");
|
|
|
|
|
+ return(GOAL_FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = locate_zero_crossings(local_minima_cnt,dz)) < 0)
|
|
|
|
|
+ return (exit_status);
|
|
|
|
|
+
|
|
|
|
|
+ /* COPY SOUND START TO OUTBUF */
|
|
|
|
|
+
|
|
|
|
|
+ outpos = 0;
|
|
|
|
|
+ if (pos[0] > 0) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Cutting start of sound\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = write_samps(obuf,pos[0],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ outpos = pos[0];
|
|
|
|
|
+ for (n = 1; n < local_minima_cnt; n++) {
|
|
|
|
|
+ if((exit_status = headwrite(dz->ofd,dz))<0) {
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sndcloseEx(dz->ofd) < 0) {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Can't close output soundfile %s\n",outfilename);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ z++;
|
|
|
|
|
+ strcpy(outfilename,dz->wordstor[0]);
|
|
|
|
|
+ if(!sloom)
|
|
|
|
|
+ insert_new_number_at_filename_end(outfilename,n,0);
|
|
|
|
|
+ else
|
|
|
|
|
+ insert_new_number_at_filename_end(outfilename,n,1);
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = create_sized_outfile(outfilename,dz))<0) {
|
|
|
|
|
+ sprintf(errstr,"WARNING: Can't create output soundfile %s\n",outfilename);
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(n==1) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Cutting each iterated segment\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ obuf = dz->sampbuf[0] + outpos;
|
|
|
|
|
+ samps_to_write = pos[n] - pos[n-1];
|
|
|
|
|
+ if((exit_status = write_samps(obuf,samps_to_write,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ outpos = pos[n];
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = headwrite(dz->ofd,dz))<0) {
|
|
|
|
|
+ free(outfilename);
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sndcloseEx(dz->ofd) < 0) {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Can't close output soundfile %s\n",outfilename);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ z++;
|
|
|
|
|
+ if(pos[n-1] < dz->insams[0]) {
|
|
|
|
|
+ fprintf(stdout,"INFO: Cutting end of sound\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ strcpy(outfilename,dz->wordstor[0]);
|
|
|
|
|
+ if(!sloom)
|
|
|
|
|
+ insert_new_number_at_filename_end(outfilename,n,0);
|
|
|
|
|
+ else
|
|
|
|
|
+ insert_new_number_at_filename_end(outfilename,n,1);
|
|
|
|
|
+
|
|
|
|
|
+ if((exit_status = create_sized_outfile(outfilename,dz))<0) {
|
|
|
|
|
+ sprintf(errstr,"WARNING: Can't create output soundfile %s\n",outfilename);
|
|
|
|
|
+ return(SYSTEM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ obuf = dz->sampbuf[0] + outpos;
|
|
|
|
|
+ samps_to_write = dz->insams[0] - pos[n-1];
|
|
|
|
|
+ if((exit_status = write_samps(obuf,samps_to_write,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ z++;
|
|
|
|
|
+ }
|
|
|
|
|
+ fprintf(stdout,"INFO: Total no of outfiles = %d\n",z);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|