/* atsa.c * atsa: ATS analysis implementation * Oscar Pablo Di Liscia / Pete Moss / Juan Pampin * Adaptations for libsndfile sound IO by jpmeuret@free.fr */ #include #include #include #include #include "atsa.h" static int load_samples(char* filename, double*** samples, off_t* frames, int* channels, int* s_rate); static int save_sound(ATS_SOUND* sound, char* filename, double SMR_thres, int type); static int save_residual(double** residual, int frames, int s_rate); /* main_anal * ========= * main analysis function * soundfile: path to input file * out_file: path to output ats file * anargs: pointer to analysis parameters * returns error status */ int main_anal(char *soundfile, char *ats_outfile, ANARGS *anargs) { int chan; off_t frames; int channels; int s_rate; double** samples = 0; double** residual = 0; int res_frames; ATS_SOUND* sound = 0; if (!load_samples(soundfile, &samples, &frames, &channels, &s_rate)) { if ((sound = tracker(anargs, samples[0], s_rate, frames, &residual, &res_frames))) { if (!save_sound(sound, ats_outfile, anargs->SMR_thres, anargs->type)) { if (save_residual(residual, res_frames, s_rate)) { fprintf(stderr, "Could not save residual"); return 1; } } else { fprintf(stderr, "Could not save ATS sound"); return 1; } } else { fprintf(stderr, "Partials analysis failed"); return 1; } if (residual) { for (chan = 0; chan < 2; chan++) if (residual[chan]) free(residual[chan]); free(residual); } /* free ATS_SOUND memory */ free_sound(sound); /* finally sound */ free(sound); } if (samples) { for (chan = 0; chan < channels; chan++) if (samples[chan]) free(samples[chan]); free(samples); } return 0; } /* This will be the length of the buffer used to hold samples while ** we process them. */ #define BUFFER_LEN 1024 static int load_samples(char* filename, double*** samples, off_t* frames, int* channels, int* s_rate) { /* This is a buffer of double precision floating point values ** which will hold our data while we process it. */ static double data[BUFFER_LEN] ; /* A SNDFILE is very much like a FILE in the Standard C library. The ** sf_open_read and sf_open_write functions return an SNDFILE* pointer ** when they sucessfully open the specified file. */ SNDFILE* infile; /* A pointer to an SF_INFO stutct is passed to sf_open_read and sf_open_write ** which fill this struct with information about the file. */ SF_INFO sfinfo ; /* Here's where we open the input file. We pass sf_open_read the file name and ** a pointer to an SF_INFO struct. ** On successful open, sf_open_read returns a SNDFILE* pointer which is used ** for all subsequent operations on that file. ** If an error occurs during sf_open_read, the function returns a NULL pointer. */ if (! (infile = sf_open(filename, SFM_READ, &sfinfo))) { /* Open failed so print an error message. */ printf ("Not able to open input file %s.\n", filename) ; /* Print the error message fron libsndfile. */ sf_perror (NULL) ; return 1 ; } ; /* warn about multi-channel sound files */ if (sfinfo.channels > 1) { fprintf(stderr, "Error: file has %d channels, must be mono!\n", sfinfo.channels); return 1; } /* Allocate the sound arrays */ int chan; *samples = (double**)malloc(sfinfo.channels * sizeof(double*)); for (chan = 0; chan < sfinfo.channels; chan++) *samples[chan] = (double*)malloc(sfinfo.frames * sizeof(double)); /* While there are samples in the input file, read them */ sf_count_t fram, frame_count; int samp; while ((frame_count = sf_readf_double (infile, data, BUFFER_LEN))) { samp = 0; for (fram = 0; fram < frame_count; fram++) for (chan = 0; chan < sfinfo.channels; chan++) *samples[chan][fram] = data[samp++]; } /* Close input file. */ sf_close (infile); *frames = sfinfo.frames; *channels = sfinfo.channels; *s_rate = sfinfo.samplerate; return 0 ; } static int save_sound(ATS_SOUND* sound, char* filename, double SMR_thres, int type) { if(!sound) return(-2); fprintf(stderr,"done!\n"); fprintf(stderr,"saving sound...\n"); ats_save(sound, filename, SMR_thres, type); fprintf(stderr, "done!\n"); return 0; } static int save_residual(double** residual, int frames, int s_rate) { static char* filename = "residual.wav"; /* A SNDFILE is very much like a FILE in the Standard C library. The ** sf_open_read and sf_open_write functions return an SNDFILE* pointer ** when they sucessfully open the specified file. */ SNDFILE* outfile; /* A pointer to an SF_INFO struct is passed to sf_open_read and sf_open_write ** which fill this struct with information about the file. */ SF_INFO sfinfo ; sfinfo.samplerate = s_rate; sfinfo.channels = 2; sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; /* Open the output file. */ if (! (outfile = sf_open(filename, SFM_WRITE, &sfinfo))) { printf ("Not able to open output file %s.\n", filename) ; sf_perror (NULL) ; return 1 ; } /* While there are residual samples, write them to the output file */ sf_count_t fram; int chan; for (fram = 0; fram < frames; fram++) for (chan = 0; chan < sfinfo.channels; chan++) sf_write_double (outfile, &residual[chan][fram], 1) ; /* Close output file. */ sf_close (outfile); return 0; }