soundeditor/atsa/atsa.c

213 lines
5.6 KiB
C

/* atsa.c
* atsa: ATS analysis implementation
* Oscar Pablo Di Liscia / Pete Moss / Juan Pampin
* Adaptations for libsndfile sound IO by jpmeuret@free.fr
*/
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <sndfile.h>
#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;
}