/* Creates a new file and writes a header with the given characteristics. <type> is a sndlib constant for header type (e.g. MUS_AIFF). <format> is a sndlib constant for sound data format (e.g. snd_16_linear). (These constants are defined in sndlib.h.) Caller is responsible for checking that the header type and data format are compatible, and that the header type is one that sndlib can write (is WRITEABLE_HEADER_TYPE()). Writes no comment. NOTE: This will truncate an existing file with <sfname>, so check first! On success, returns a standard file descriptor, and leaves the file position pointer at the end of the header. On failure, returns -1. Caller can check errno then. */ int sndlib_create(char *sfname, /* file name */ int type, /* file type, e.g. AIFF */ int format, /* data format, e.g., MU-LAW */ int srate, /* sampling rate in Hz */ int chans, /* 1 for mono, 2 for stereo */ char *comment) { int fd, loc; assert(sfname != NULL && strlen(sfname) <= FILENAME_MAX); mus_header_initialize(); // make sure relevant parts of sndlib are initialized //resample-1.8: sndlib_write_header(fd, 0, type, format, srate, chans, comment, &loc) //resample-1.8: mus_file_open_descriptors(fd, format, mus_header_data_format_to_bytes_per_sample(),loc); // int mus_file_open_descriptors(int tfd, const char *arg, int df, int ds, off_t dl, int dc, int dt); fd = mus_sound_open_output(sfname, srate, chans, format, type, "created by resample"); return fd; }
/* 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); }