Sigrid Solveig Haflínudóttirfix warnings6bc6a9b3 years agoHistory
399 lines · 11.7 KB · C
RawDownload
/* Ari Moisio <armoi@sci.fi> Aug 29 2000, based on skeleton effect * Written by Chris Bagwell (cbagwell@sprynet.com) - March 16, 1999 * * Copyright 1999 Chris Bagwell And Sundry Contributors * This source code is freely redistributable and may be used for * any purpose.  This copyright notice must be maintained. * Chris Bagwell And Sundry Contributors are not responsible for * the consequences of using this software. */ #include "sox_i.h" /* Fade curves */#define FADE_QUARTER    'q'     /* Quarter of sine wave, 0 to pi/2 */#define FADE_HALF       'h'     /* Half of sine wave, pi/2 to 1.5 * pi                                * scaled so that -1 means no output                                * and 1 means 0 db attenuation. */#define FADE_LOG        'l'     /* Logarithmic curve. Fades -100 db                                * in given time. */#define FADE_TRI        't'     /* Linear slope. */#define FADE_PAR        'p'     /* Inverted parabola. */ #include <string.h> /* Private data for fade file */typedef struct { /* These are measured as samples */    uint64_t in_start, in_stop, out_start, out_stop, samplesdone;    char *in_stop_str, *out_start_str, *out_stop_str;    char in_fadetype, out_fadetype;    char do_out;    int endpadwarned;} priv_t; /* prototypes */static double fade_gain(uint64_t index, uint64_t range, int fadetype); /* * Process options * * Don't do initialization now. * The 'info' fields are not yet filled in. */ static int sox_fade_getopts(sox_effect_t * effp, int argc, char **argv){     priv_t * fade = (priv_t *) effp->priv;    char t_char[2];    int t_argno;    uint64_t samples;    const char *n;  --argc, ++argv;     if (argc < 1 || argc > 4)         return lsx_usage(effp);     /* because sample rate is unavailable at this point we store the     * string off for later computations.     */     if (sscanf(argv[0], "%1[qhltp]", t_char))    {        fade->in_fadetype = *t_char;        fade->out_fadetype = *t_char;         argv++;        argc--;    }    else    {        /* No type given. */        fade->in_fadetype = 'l';        fade->out_fadetype = 'l';    }     fade->in_stop_str = lsx_strdup(argv[0]);    /* Do a dummy parse to see if it will fail */    n = lsx_parsesamples(0., fade->in_stop_str, &samples, 't');    if (!n || *n)      return lsx_usage(effp);     fade->in_stop = samples;    fade->out_start_str = fade->out_stop_str = 0;     for (t_argno = 1; t_argno < argc && t_argno < 3; t_argno++)    {        /* See if there is fade-in/fade-out times/curves specified. */        if(t_argno == 1)        {            fade->out_stop_str = lsx_strdup(argv[t_argno]);             /* Do a dummy parse to see if it will fail */            n = lsx_parseposition(0., fade->out_stop_str, NULL, (uint64_t)0, (uint64_t)0, '=');            if (!n || *n)              return lsx_usage(effp);            fade->out_stop = samples;        }        else        {            fade->out_start_str = lsx_strdup(argv[t_argno]);             /* Do a dummy parse to see if it will fail */            n = lsx_parsesamples(0., fade->out_start_str, &samples, 't');            if (!n || *n)              return lsx_usage(effp);            fade->out_start = samples;        }    } /* End for(t_argno) */     return(SOX_SUCCESS);} /* * Prepare processing. * Do all initializations. */static int sox_fade_start(sox_effect_t * effp){    priv_t * fade = (priv_t *) effp->priv;    sox_bool truncate = sox_false;    uint64_t samples;    uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?      effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;     /* converting time values to samples */    fade->in_start = 0;    if (lsx_parsesamples(effp->in_signal.rate, fade->in_stop_str,                        &samples, 't') == NULL)      return lsx_usage(effp);     fade->in_stop = samples;    fade->do_out = 0;    /* See if user specified a stop time */    if (fade->out_stop_str)    {        fade->do_out = 1;        if (!lsx_parseposition(effp->in_signal.rate, fade->out_stop_str,                            &samples, (uint64_t)0, in_length, '=') ||            samples == SOX_UNKNOWN_LEN) {          lsx_fail("audio length is unknown");          return SOX_EOF;        }        fade->out_stop = samples;         if (!(truncate = !!fade->out_stop)) {          fade->out_stop = effp->in_signal.length != SOX_UNKNOWN_LEN ?              effp->in_signal.length / effp->in_signal.channels :              0;          if (!fade->out_stop) {            lsx_fail("cannot fade out: audio length is neither known nor given");            return SOX_EOF;          }        }         /* See if user wants to fade out. */        if (fade->out_start_str)        {            if (lsx_parsesamples(effp->in_signal.rate, fade->out_start_str,                        &samples, 't') == NULL)              return lsx_usage(effp);            /* Fade time is relative to stop time. */            fade->out_start = fade->out_stop - samples;        }        else            /* If user doesn't specify fade out length then             * use same length as input side.  This is stored             * in in_stop.             */            fade->out_start = fade->out_stop - fade->in_stop;    }    else        /* If not specified then user wants to process all         * of file.  Use a value of zero to indicate this.         */        fade->out_stop = 0;     if (fade->out_start) {              /* Sanity check */      if (fade->in_stop > fade->out_start)        --fade->in_stop;                /* 1 sample grace for rounding error. */      if (fade->in_stop > fade->out_start) {        lsx_fail("fade-out overlaps fade-in");        return SOX_EOF;      }    }     fade->samplesdone = fade->in_start;    fade->endpadwarned = 0;     lsx_debug("in_start = %" PRIu64 " in_stop = %" PRIu64 " "      "out_start = %" PRIu64 " out_stop = %" PRIu64,      fade->in_start, fade->in_stop, fade->out_start, fade->out_stop);     if (fade->in_start == fade->in_stop && !truncate &&        fade->out_start == fade->out_stop)      return SOX_EFF_NULL;     effp->out_signal.length = truncate ?        fade->out_stop * effp->in_signal.channels : effp->in_signal.length;     return SOX_SUCCESS;} /* * Processed signed long samples from ibuf to obuf. * Return number of samples processed. */static int sox_fade_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,                 size_t *isamp, size_t *osamp){    priv_t * fade = (priv_t *) effp->priv;    /* len is total samples, chcnt counts channels */    int len, t_output, more_output = 1;    sox_sample_t t_ibuf;    size_t chcnt = 0;     len = ((*isamp > *osamp) ? *osamp : *isamp);     *osamp = 0;    *isamp = 0;     for(; len && more_output; len--)    {        t_ibuf = *ibuf;         if ((fade->samplesdone >= fade->in_start) &&            (!fade->do_out || fade->samplesdone < fade->out_stop))        { /* something to generate output */             if (fade->samplesdone < fade->in_stop)            { /* fade-in phase, increase gain */                *obuf = t_ibuf *                    fade_gain(fade->samplesdone - fade->in_start,                              fade->in_stop - fade->in_start,                              fade->in_fadetype);            } /* endif fade-in */            else if (!fade->do_out || fade->samplesdone < fade->out_start)            { /* steady gain phase */                *obuf = t_ibuf;            } /* endif  steady phase */            else            { /* fade-out phase, decrease gain */                *obuf = t_ibuf *                    fade_gain(fade->out_stop - fade->samplesdone,                              fade->out_stop - fade->out_start,                              fade->out_fadetype);            } /* endif fade-out */             if (!(!fade->do_out || fade->samplesdone < fade->out_stop))                more_output = 0;             t_output = 1;        }        else        { /* No output generated */            t_output = 0;        } /* endif something to output */         *isamp += 1;        ibuf++;         if (t_output)        { /* Output generated, update pointers and counters */            obuf++;            *osamp += 1;        } /* endif t_output */         /* Process next channel */        chcnt++;        if (chcnt >= effp->in_signal.channels)        { /* all channels of this sample processed */            chcnt = 0;            fade->samplesdone += 1;        } /* endif all channels */    } /* endfor */     /* If not more samples will be returned, let application know     * this.     */    if (fade->do_out && fade->samplesdone >= fade->out_stop)        return SOX_EOF;    else        return SOX_SUCCESS;} /* * Drain out remaining samples if the effect generates any. */static int sox_fade_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp){    priv_t * fade = (priv_t *) effp->priv;    int len;    size_t t_chan = 0;     len = *osamp;    len -= len % effp->in_signal.channels;    *osamp = 0;     if (fade->do_out && fade->samplesdone < fade->out_stop &&        !(fade->endpadwarned))    { /* Warning about padding silence into end of sample */        lsx_warn("End time past end of audio. Padding with silence");        fade->endpadwarned = 1;    } /* endif endpadwarned */     for (;len && (fade->do_out &&                  fade->samplesdone < fade->out_stop); len--)    {        *obuf = 0;        obuf++;        *osamp += 1;         t_chan++;        if (t_chan >= effp->in_signal.channels)        {            fade->samplesdone += 1;            t_chan = 0;        } /* endif channels */    } /* endfor */     if (fade->do_out && fade->samplesdone >= fade->out_stop)        return SOX_EOF;    else        return SOX_SUCCESS;} /* * Do anything required when you stop reading samples. *      (free allocated memory, etc.) */static int lsx_kill(sox_effect_t * effp){    priv_t * fade = (priv_t *) effp->priv;     free(fade->in_stop_str);    free(fade->out_start_str);    free(fade->out_stop_str);    return (SOX_SUCCESS);} /* Function returns gain value 0.0 - 1.0 according index / range ratio* and -1.0 if  type is invalid* todo: to optimize performance calculate gain every now and then and interpolate */static double fade_gain(uint64_t index, uint64_t range, int type){    double retval, findex;     /* TODO: does it really have to be contrained to [0.0, 1.0]? */    findex = max(0.0, min(1.0, 1.0 * index / range));     switch (type) {    case FADE_TRI :             /* triangle */      retval = findex;      break;     case FADE_QUARTER :         /* quarter of sinewave */      retval = sin(findex * M_PI / 2);      break;     case FADE_HALF :          /* half of sinewave... eh cosine wave */      retval = (1 - cos(findex * M_PI )) / 2 ;      break;     case FADE_LOG :             /* logarithmic */      /* 5 means 100 db attenuation. */      /* TODO: should this be adopted with bit depth */      retval =  pow(0.1, (1 - findex) * 5);      break;     case FADE_PAR :             /* inverted parabola */      retval = (1 - (1 - findex)  * (1 - findex));      break;     /* TODO: more fade curves? */    default :                  /* Error indicating wrong fade curve */      retval = -1.0;      break;    }     return retval;} static sox_effect_handler_t sox_fade_effect = {  "fade",  "[ type ] fade-in-length [ stop-position [ fade-out-length ] ]\n"  "       Time is in hh:mm:ss.frac format.\n"  "       Fade type one of q, h, t, l or p.",  SOX_EFF_MCHAN | SOX_EFF_LENGTH,  sox_fade_getopts,  sox_fade_start,  sox_fade_flow,  sox_fade_drain,  NULL,  lsx_kill, sizeof(priv_t)}; const sox_effect_handler_t *lsx_fade_effect_fn(void){    return &sox_fade_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