Sigrid Solveig Haflínudóttirfix warnings6bc6a9b3 years agoHistory
224 lines · 5.9 KB · C
RawDownload
/* noiseprof - SoX Noise Profiling Effect. * * Written by Ian Turner (vectro@vectro.org) * Copyright 1999 Ian Turner and others * * This library 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. * * This library 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 * along with this library; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA */ #include "noisered.h" #include <assert.h>#include <string.h>#include <errno.h> typedef struct {    float *sum;    int   *profilecount;     float *window;} chandata_t; typedef struct {    char* output_filename;    FILE* output_file;     chandata_t *chandata;    size_t bufdata;} priv_t; /* * Get the filename, if any. We don't open it until sox_noiseprof_start. */static int sox_noiseprof_getopts(sox_effect_t * effp, int argc, char **argv){    priv_t * data = (priv_t *) effp->priv;  --argc, ++argv;     if (argc == 1) {        data->output_filename = argv[0];    } else if (argc > 1)      return lsx_usage(effp);     return (SOX_SUCCESS);} /* * Prepare processing. * Do all initializations. */static int sox_noiseprof_start(sox_effect_t * effp){  priv_t * data = (priv_t *) effp->priv;  unsigned channels = effp->in_signal.channels;  unsigned i;   /* Note: don't fall back to stderr if stdout is unavailable   * since we already use stderr for diagnostics. */  if (!data->output_filename || !strcmp(data->output_filename, "-")) {    if (effp->global_info->global_info->stdout_in_use_by) {      lsx_fail("stdout already in use by `%s'", effp->global_info->global_info->stdout_in_use_by);      return SOX_EOF;    }    effp->global_info->global_info->stdout_in_use_by = effp->handler.name;    data->output_file = stdout;  }  else if ((data->output_file = fopen(data->output_filename, "wb")) == NULL) {    lsx_fail("Couldn't open profile file %s: %s", data->output_filename, strerror(errno));    return SOX_EOF;  }   data->chandata = lsx_calloc(channels, sizeof(*(data->chandata)));  data->bufdata = 0;  for (i = 0; i < channels; i ++) {    data->chandata[i].sum = lsx_calloc(FREQCOUNT, sizeof(float));    data->chandata[i].profilecount = lsx_calloc(FREQCOUNT, sizeof(int));    data->chandata[i].window = lsx_calloc(WINDOWSIZE, sizeof(float));  }   return SOX_SUCCESS;} /* Collect statistics from the complete window on channel chan. */static void collect_data(chandata_t* chan) {    float *out = lsx_calloc(FREQCOUNT, sizeof(float));    int i;     lsx_power_spectrum_f(WINDOWSIZE, chan->window, out);     for (i = 0; i < FREQCOUNT; i ++) {        if (out[i] > 0) {            float value = log(out[i]);            chan->sum[i] += value;            chan->profilecount[i] ++;        }    }     free(out);} /* * Grab what we can from ibuf, and process if we have a whole window. */static int sox_noiseprof_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,                    size_t *isamp, size_t *osamp){  priv_t * p = (priv_t *) effp->priv;  size_t samp = min(*isamp, *osamp);  size_t chans = effp->in_signal.channels;  size_t i, j, n = min(samp / chans, WINDOWSIZE - p->bufdata);   memcpy(obuf, ibuf, n * chans * sizeof(*obuf)); /* Pass on audio unaffected */  *isamp = *osamp = n * chans;   /* Collect data for every channel. */  for (i = 0; i < chans; i ++) {    SOX_SAMPLE_LOCALS;    chandata_t * chan = &(p->chandata[i]);    for (j = 0; j < n; j ++)      chan->window[j + p->bufdata] =        SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i + j * chans],);    if (n + p->bufdata == WINDOWSIZE)      collect_data(chan);  }   p->bufdata += n;  assert(p->bufdata <= WINDOWSIZE);  if (p->bufdata == WINDOWSIZE)    p->bufdata = 0;   return SOX_SUCCESS;} /* * Finish off the last window. */ static int sox_noiseprof_drain(sox_effect_t * effp, sox_sample_t *obuf UNUSED, size_t *osamp){    priv_t * data = (priv_t *) effp->priv;    int tracks = effp->in_signal.channels;    int i;     USED(obuf);    *osamp = 0;     if (data->bufdata == 0) {        return SOX_EOF;    }     for (i = 0; i < tracks; i ++) {        int j;        for (j = data->bufdata+1; j < WINDOWSIZE; j ++) {            data->chandata[i].window[j] = 0;        }        collect_data(&(data->chandata[i]));    }     if (data->bufdata == WINDOWSIZE || data->bufdata == 0)        return SOX_EOF;    else        return SOX_SUCCESS;} /* * Print profile and clean up. */static int sox_noiseprof_stop(sox_effect_t * effp){    priv_t * data = (priv_t *) effp->priv;    size_t i;     for (i = 0; i < effp->in_signal.channels; i ++) {        int j;        chandata_t* chan = &(data->chandata[i]);         fprintf(data->output_file, "Channel %lu: ", (unsigned long)i);         for (j = 0; j < FREQCOUNT; j ++) {            double r = chan->profilecount[j] != 0 ?                    chan->sum[j] / chan->profilecount[j] : 0;            fprintf(data->output_file, "%s%f", j == 0 ? "" : ", ", r);        }        fprintf(data->output_file, "\n");         free(chan->sum);        free(chan->profilecount);    }     free(data->chandata);     if (data->output_file != stdout)        fclose(data->output_file);     return (SOX_SUCCESS);} static sox_effect_handler_t sox_noiseprof_effect = {  "noiseprof",  "[profile-file]",  SOX_EFF_MCHAN | SOX_EFF_MODIFY,  sox_noiseprof_getopts,  sox_noiseprof_start,  sox_noiseprof_flow,  sox_noiseprof_drain,  sox_noiseprof_stop,  NULL, sizeof(priv_t)}; const sox_effect_handler_t *lsx_noiseprof_effect_fn(void){    return &sox_noiseprof_effect;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t