/* Let user load a function table with samples from a sound file. The file can be 16-bit integer or 32-bit floating point in either byte order, and in any of the header formats recognized by sndlib. The makegen syntax used in Minc is: frames_read = makegen(slot, 1, size, filename, inskip [, inchan, dump]) <size> is the duration (in seconds) of the sound file segment, or if it's negative, the number of sample frames to read. If <size> is zero, the whole file is slurpped in. (Beware with large files -- there is no check on memory consumption here!) <filename> is a double-quoted pathname (as in rtinput). <inskip> is the time (in seconds) to skip before reading, or if it's negative, the number of sample frames to skip before reading. If <inchan> is missing, reads all channels from the file; otherwise, reads just the channel specified by <inchan> (with zero as first chan). If <dump> is 1, then dumps the gen table to a header-less sound file, called "dumpaudio.raw," in the current directory. The file is 32-bit float, using the host byte order, <inchan> chans, and the sampling rate in the source file's header. As usual, if the slot number is positive, the table will be rescaled to fit in the range [-1,1]; if it's negative, it will not be rescaled. Returns to Minc the number of sample frames read. JGG, 07 Feb 2001 */ double gen1(struct gen *gen, char *sfname) { int i, fd, header_type, data_format, data_location, inchan; int gen_chans, gen_frames, gen_samps, file_chans, file_frames; int start_frame, bytes_per_samp, byteswap, is_float, dump; int buf_start_frame, end_frame, frames_read, buf_frames; long file_samps; off_t seek_to; float request_dur, filedur, inskip; double srate, *block, *blockp; char *buf; request_dur = gen->pvals[0]; inskip = gen->pvals[2]; if (gen->nargs > 3) inchan = (int) gen->pvals[3]; else inchan = -1; /* read all chans */ dump = gen->nargs > 4? (int) gen->pvals[4] : 0; fd = open_sound_file("gen1", sfname, &header_type, &data_format, &data_location, &srate, &file_chans, &file_samps); if (fd == -1) return die("gen1", "Can't open input file: \"%s\"!", sfname); if (srate != SR()) { rtcmix_warn("gen1", "The input file sampling rate is %g, but " "the output rate is currently %g.", srate, SR()); } file_frames = file_samps / file_chans; if (inchan == -1) gen_chans = file_chans; else gen_chans = 1; if (file_chans == 1) inchan = -1; /* more efficient copy below */ if (inchan >= file_chans) return die("gen1", "You asked for channel %d of a %d-channel file. (\"%s\")", inchan, file_chans, sfname); if (request_dur < 0.0) gen_frames = (int) -request_dur; else if (request_dur > 0.0) gen_frames = (int) (request_dur * srate); else gen_frames = file_frames; if (inskip < 0.0) start_frame = (int) -inskip; else start_frame = (int) (inskip * srate); if (start_frame + gen_frames > file_frames) gen_frames = file_frames - start_frame; gen_samps = gen_frames * gen_chans; block = (double *) malloc((size_t) (gen_samps * sizeof(double))); if (block == NULL) return die("gen1", "Not enough memory for function table %d.", gen->slot); buf = (char *) malloc((size_t) BUFSIZE); if (buf == NULL) { free(block); return die("gen1", "Not enough memory for temporary buffer."); } bytes_per_samp = mus_data_format_to_bytes_per_sample(data_format); seek_to = data_location + (start_frame * file_chans * bytes_per_samp); if (lseek(fd, seek_to, SEEK_SET) == -1) { free(block); free(buf); return die("gen1", "lseek() failed"); } #if MUS_LITTLE_ENDIAN byteswap = IS_BIG_ENDIAN_FORMAT(data_format); #else byteswap = IS_LITTLE_ENDIAN_FORMAT(data_format); #endif is_float = IS_FLOAT_FORMAT(data_format); buf_frames = (BUFSIZE / bytes_per_samp) / file_chans; end_frame = start_frame + gen_frames; blockp = block; frames_read = 0; buf_start_frame = start_frame; for ( ; buf_start_frame < end_frame; buf_start_frame += frames_read) { int samps_read; long bytes_read; if (buf_start_frame + buf_frames > end_frame) { /* last buffer */ int samps = (end_frame - buf_start_frame) * file_chans; bytes_read = read(fd, buf, samps * bytes_per_samp); } else bytes_read = read(fd, buf, BUFSIZE); if (bytes_read == -1) { free(block); free(buf); return die("gen1", "read() failed"); } if (bytes_read == 0) /* EOF, somehow */ break; samps_read = bytes_read / bytes_per_samp; frames_read = samps_read / file_chans; if (is_float) { float *bufp = (float *) buf; if (inchan == -1) { /* store all chans */ if (byteswap) { for (i = 0; i < samps_read; i++) { byte_reverse4(bufp); /* modify *bufp in place */ *blockp++ = (double) *bufp++; } } else { for (i = 0; i < samps_read; i++) *blockp++ = (double) *bufp++; } } else { /* store only inchan */ bufp += inchan; if (byteswap) { for (i = 0; i < samps_read; i += file_chans) { byte_reverse4(bufp); /* modify *bufp in place */ *blockp++ = (double) *bufp; bufp += file_chans; } } else { for (i = 0; i < samps_read; i += file_chans) { *blockp++ = (double) *bufp; bufp += file_chans; } } } } else { /* is shortint file */ short *bufp = (short *) buf; if (inchan == -1) { /* store all chans */ if (byteswap) { for (i = 0; i < samps_read; i++, bufp++) { short samp = reverse_int2(bufp); *blockp++ = (double) samp; } } else { for (i = 0; i < samps_read; i++) *blockp++ = (double) *bufp++; } } else { /* store only inchan */ bufp += inchan; if (byteswap) { for (i = 0; i < samps_read; i += file_chans) { short samp = reverse_int2(bufp); *blockp++ = (double) samp; bufp += file_chans; } } else { for (i = 0; i < samps_read; i += file_chans) { *blockp++ = (double) *bufp; bufp += file_chans; } } } } } free(buf); sndlib_close(fd, 0, 0, 0, 0); gen->array = block; gen->size = gen_samps; fnscl(gen); if (dump) dump_gen_to_raw_file(block, gen_samps); return (double) gen_frames; }
/* compute_residual * ================ * Computes the difference between the synthesis and the original sound. * the <win-samps> array contains the sample numbers in the input file corresponding to each frame * audio: pointer to analyzed data * fil_len: length of data in samples * output_file: output file path * sound: pointer to ATS_SOUND * win_samps: pointer to array of analysis windows center times * file_sampling_rate: sampling rate of analysis file */ void compute_residual(ANARGS *anargs, int fil_len, char *output_file, ATS_SOUND *sound, int *win_samps) { int i, frm, frm_1, frm_2, par, frames, partials, frm_samps, out_smp=0, ptout; double *in_buff, *synth_buff, mag, a1, a2, f1, f2, p1, p2, diff, synth; mus_sample_t **obuf; frames = sound->frames; partials = sound->partials; frm_samps = sound->frame_size; mag = TWOPI / (double)anargs->srate; /* this might fail if fil_len or frm_samps changes */ if(anargs->residual == NULL) anargs->residual = (double *)calloc(fil_len + 2*frm_samps, sizeof(double)); // fprintf(stderr, "fil_len %d, frames %d, frm_samps %d\n", fil_len, frames, frm_samps); in_buff = (double *)malloc(frm_samps * sizeof(double)); synth_buff = (double *)malloc(frm_samps * sizeof(double)); /* open output file */ if((ptout=mus_sound_open_output(output_file,anargs->srate,2,MUS_LSHORT,MUS_RIFF,"created by ATSA"))==-1) { fprintf(stderr, "\nERROR: can't open file %s for writing\n", output_file); exit(1); } /* allocate memory */ obuf = (mus_sample_t **)malloc(2*sizeof(mus_sample_t *)); obuf[0] = (mus_sample_t *)calloc(frm_samps, sizeof(mus_sample_t)); obuf[1] = (mus_sample_t *)calloc(frm_samps, sizeof(mus_sample_t)); /* compute residual frame by frame */ for(frm=1; frm<frames; frm++) { /* clean buffers up */ for(i=0; i<frm_samps; i++) in_buff[i] = synth_buff[i] = 0.0; frm_1 = frm - 1; frm_2 = frm; /* read frame from input */ read_frame(anargs->audio, fil_len, win_samps[frm_1], win_samps[frm_2], in_buff); /* compute one synthesis frame */ for(par=0; par<partials; par++) { a1 = sound->amp[par][frm_1]; a2 = sound->amp[par][frm_2]; /* have to convert the frequency into radians per sample!!! */ f1 = sound->frq[par][frm_1] * mag; f2 = sound->frq[par][frm_2] * mag; p1 = sound->pha[par][frm_1]; p2 = sound->pha[par][frm_2]; if( !( a1 <= 0.0 && a2 <= 0.0 ) ) { /* check amp 0 in frame 1 */ if(a1 <= 0.0) { f1 = f2; p1 = p2 - ( f2 * frm_samps ); while(p1 > PI) p1 -= TWOPI; while(p1 < (PI * -1)) p1 += TWOPI; } /* check amp 0 in frame 2 */ if(a2 <= 0.0) { f2 = f1; p2 = p1 + ( f1 * frm_samps ); while(p2 > PI) p2 -= TWOPI; while(p2 < (PI * -1)) p2 += TWOPI; } synth_buffer(a1, a2, f1, f2, p1, p2, synth_buff, frm_samps); } } /* write output: chan 0 residual, chan 1 synthesis */ for(i=0; i<frm_samps; i++) { synth = synth_buff[i]; diff = in_buff[i] - synth; obuf[0][i] = MUS_DOUBLE_TO_SAMPLE(diff); obuf[1][i] = MUS_DOUBLE_TO_SAMPLE(synth); anargs->residual[out_smp] = diff; out_smp++; } mus_sound_write(ptout, 0, frm_samps-1, 2, obuf); } free(in_buff); free(synth_buff); /* update header and close output file */ mus_sound_close_output(ptout,2 * out_smp * mus_data_format_to_bytes_per_sample(MUS_LSHORT)); free(obuf[0]); free(obuf[1]); free(obuf); //for(i=0; i<fil_len; i++) audio[i] = res[i]; //free(res); }
//////////////////////////////////////////////////////////////////// /////////THIS IS THE MAIN SYNTHESIS LOOP//////////////////////////// //////////////////////////////////////////////////////////////////// void do_synthesis() { int i,x,z,j,maxlen, todo, curr, next, sflag=0; float dt=0., rfreq; float frame_samps, bw=.1; int ptout; float maxamp=0.; int bframe=0, eframe=0; int nValue=0; char stamp[16]; int written; int format,header; mus_sample_t *obuf[1]; float cxval, cyval, nxval, nyval, difx, dify; TIME_DATA *tdata; int nbp; float *dospt=NULL, *rospt=NULL; RANDI *rarray=NULL; float res_band_edges[ATSA_CRITICAL_BANDS+1]=ATSA_CRITICAL_BAND_EDGES; float res_band_centers[ATSA_CRITICAL_BANDS]; char str[100]; //ATTEMPT TO CATCH TWO POSSIBLE ERRORS........ if(*ats_tittle==0) { Popup("ERROR: ATS file undefined, select it first"); return; } if(*out_tittle==0) { Popup("ERROR: Output Soundfile undefined, select it first"); return; } if(sparams->amp==0. && sparams->ramp==0.) { Popup("ERROR: Deterministic and Residual output set to zero"); return; } //OPEN OUTPUT FILE set_output_type(&format, &header); if((ptout=mus_sound_open_output(out_tittle,(int)sparams->sr,1,format,header,"created by ATSH"))==-1) { Popup("ERROR: could not open Output Soundfile for writing"); return; } //do residual data transfer if (FILE_HAS_NOISE) for(i=0; i<(int)atshed->fra; ++i) band_energy_to_res(ats_sound, i); //NOW CHECK WHAT TO DO... if(sparams->amp > 0.) sflag |= SYNTH_DET; //deterministic synthesis only if(sparams->ramp > 0.) sflag |= SYNTH_RES; //residual synthesis only tl_sr = (float)TABLE_LENGTH / sparams->sr; //needed for ioscilator... nbp = get_nbp(timenv->curve); tdata = (TIME_DATA*)malloc(nbp * sizeof(TIME_DATA)); //g_print(" \nNPOINTS= %d \n", nbp); sparams->max_stretch=0.; todo=0; //We first must calculate data of each breakpoint timenv->dur=fabs(timenv->dur); //correct if negative for(i=0; i < nbp - 1; ++i){ //get the data from the time envelope and convert it to time cxval= timenv->dur * (get_x_value(timenv->curve,i)/100.); cyval= timenv->ymin + ((timenv->ymax - timenv->ymin) * (get_y_value(timenv->curve,i)/100.)); nxval= timenv->dur * (get_x_value(timenv->curve,i+1)/100.); nyval= timenv->ymin + ((timenv->ymax - timenv->ymin) * (get_y_value(timenv->curve,i+1)/100.)); //diff=0. is a special case we must take in account //here all we do is to set it to one millisecond (arbitrarly) difx= nxval - cxval; if(difx == 0.) difx=.001; dify= nyval - cyval; if(dify == 0.) dify=.001; //find out the max. stretching factor(needed to alocate the I/O buffer) if(fabs(difx) / fabs(dify) >= sparams->max_stretch) { sparams->max_stretch=fabs(difx) / fabs(dify); } //locate the frame for the beggining and end of segments if(i == 0){ if(dify < 0.) bframe= locate_frame((int)atshed->fra-1,cyval, dify); else bframe= locate_frame(0,cyval, dify); } eframe= locate_frame(bframe, nyval, dify); //collect the data to be used tdata[i].from=bframe; tdata[i].to =eframe; tdata[i].size= (int)(abs(eframe - bframe)) + 1; tdata[i].tfac=fabs(difx) / fabs(dify); todo+=tdata[i].size; //g_print("\n from frame=%d to frame=%d", bframe,eframe); bframe=eframe; //////////////////////////////////////////////////////// } //INITIALIZE PROGRESSBAR strcpy(str,"Writing File " ); strcat(str, out_tittle); StartProgress(str, TRUE); //ALLOCATE AND CLEAN AUDIO BUFFERS maxlen= (int)ceil(maxtim * sparams->sr * sparams->max_stretch); frbuf = (float *) malloc(maxlen * sizeof(float)); for(z = 0; z < maxlen; ++z) frbuf[z]=0.; obuf[0] = (mus_sample_t *)calloc(maxlen, sizeof(mus_sample_t)); switch(sflag) { //see which memory resources do we need and allocate them case SYNTH_DET: dospt = (float *) malloc( (int)atshed->par * sizeof(float)); for(z=0; z<(int)atshed->par; ++z) dospt[z]=0.; break; case SYNTH_RES: rospt = (float *) malloc((int)ATSA_CRITICAL_BANDS * sizeof(float)); rarray= (RANDI *) malloc((int)ATSA_CRITICAL_BANDS * sizeof(RANDI)); for(z=0; z<(int)ATSA_CRITICAL_BANDS; ++z) { res_band_centers[z]= res_band_edges[z]+((res_band_edges[z+1]-res_band_edges[z])*0.5); randi_setup(sparams->sr,res_band_edges[z+1]-res_band_edges[z],&rarray[z]); rospt[z]=0.; } break; case SYNTH_BOTH: dospt = (float *) malloc( (int)atshed->par * sizeof(float)); rarray= (RANDI *) malloc( (int)atshed->par * sizeof(RANDI)); for(z=0; z<(int)atshed->par; ++z) { rfreq=(ats_sound->frq[z][tdata[0].from] < 500.? 50. : ats_sound->frq[z][tdata[0].from] * bw); randi_setup(sparams->sr,rfreq,&rarray[z]); dospt[z]=0.; } break; } //NOW DO IT... written=0; stopper=FALSE; for(i = 0; i < nbp - 1; i++) { curr=tdata[i].from; for(j=0; j < tdata[i].size; j++) { next=(tdata[i].from < tdata[i].to ? curr+1 : curr-1 ); if(next < 0 || next >= (int)atshed->fra) break; dt=fabs(ats_sound->time[0][next] - ats_sound->time[0][curr]); frame_samps=dt * sparams->sr * tdata[i].tfac ; switch (sflag) { case SYNTH_DET: { //deterministic synthesis only for(x = 0; x < (int)atshed->par; x++) { synth_deterministic_only(ats_sound->amp[x][curr], ats_sound->amp[x][next], ats_sound->frq[x][curr] * sparams->frec, ats_sound->frq[x][next] * sparams->frec, frame_samps,x, dospt); } break; } case SYNTH_RES: { //residual synthesis only for(x = 0; x < (int)ATSA_CRITICAL_BANDS; x++) { synth_residual_only(ENG_RMS(ats_sound->band_energy[x][curr], atshed->ws), ENG_RMS(ats_sound->band_energy[x][next],atshed->ws) , res_band_centers[x],frame_samps,x,rospt,&rarray[x]); } break; } case SYNTH_BOTH: { //residual and deterministic synthesis for(x = 0; x < (int)atshed->par; x++) { rfreq=(ats_sound->frq[x][curr] < 500.? 50. : ats_sound->frq[x][curr]* bw); synth_both(ats_sound->amp[x][curr], ats_sound->amp[x][next], ats_sound->frq[x][curr] * sparams->frec, ats_sound->frq[x][next] * sparams->frec, frame_samps,x, dospt, ENG_RMS(ats_sound->res[x][curr] * sparams->ramp, atshed->ws), ENG_RMS(ats_sound->res[x][next] * sparams->ramp, atshed->ws), &rarray[x]); } break; } }//end switch for(z=0; z< maxlen; ++z) { //write and clean output buffer if(z < (int)frame_samps) { obuf[0][z] = MUS_FLOAT_TO_SAMPLE(frbuf[z]); written++; if (fabs(frbuf[z]) >= maxamp) {maxamp=fabs(frbuf[z]);} } frbuf[z]=0.; } mus_sound_write(ptout, 0, frame_samps-1, 1, obuf); if(stopper==TRUE) goto finish; ++nValue; UpdateProgress(nValue,todo); curr=(tdata[i].from < tdata[i].to ? curr+1 :curr-1 ); } } //CHANGE BREAKPOINT finish: free(frbuf); switch (sflag) { case SYNTH_DET: free(dospt); break; case SYNTH_RES: free(rospt); free(rarray); break; case SYNTH_BOTH: free(dospt); free(rarray); break; } mus_sound_close_output(ptout,written * mus_data_format_to_bytes_per_sample(format)); // *info=0; // strcat(info, "DONE OK...!!! MAXAMP= "); // sprintf(stamp,"%6.4f ",maxamp); // strcat(info, stamp); // Popup(info); free(obuf[0]); free(tdata); EndProgress(); strcpy(str, "DONE! MAXAMP= "); sprintf(stamp, "%6.4f", maxamp); strcat(str, stamp); Popup(str); }