ref: 5164b5505f256c06eb3a84f4d8a8a93055af9d41
dir: /src/dither.c/
/* * libSoX dithering noise effect file. * * July 5, 1991 * Copyright 1991 Lance Norskog And Sundry Contributors * This source code is freely redistributable and may be used for * any purpose. This copyright notice must be maintained. * Lance Norskog And Sundry Contributors are not responsible for * the consequences of using this software. * * TODO: does triangular noise, could do local shaping * */ #include <stdlib.h> #include <math.h> #include "sox_i.h" typedef struct dither { double amount; } * dither_t; assert_static(sizeof(struct dither) <= SOX_MAX_EFFECT_PRIVSIZE, /* else */ dither_PRIVSIZE_too_big); static int getopts(eff_t effp, int n, char * * argv) { dither_t dither = (dither_t) effp->priv; if (n > 1) { sox_fail(effp->h->usage); return SOX_EOF; } dither->amount = sqrt(2.); /* M_SQRT2 missing in some places */ /* Default to half a bit. */ if (n == 1) { double amount; char dummy; int scanned = sscanf(*argv, "%lf %c", &amount, &dummy); if (scanned == 1 && amount > 0) dither->amount *= amount; else { sox_fail(effp->h->usage); return SOX_EOF; } } return SOX_SUCCESS; } static int start(eff_t effp) { dither_t dither = (dither_t) effp->priv; if (effp->outinfo.encoding == SOX_ENCODING_ULAW || effp->outinfo.encoding == SOX_ENCODING_ALAW) { dither->amount *= 16; return SOX_SUCCESS; } else if (effp->outinfo.size == SOX_SIZE_BYTE) { dither->amount *= 256; return SOX_SUCCESS; } else if (effp->outinfo.size == SOX_SIZE_16BIT) return SOX_SUCCESS; return SOX_EFF_NULL; /* Dithering not needed at >= 24 bits */ } static int flow(eff_t effp, const sox_sample_t * ibuf, sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp) { dither_t dither = (dither_t)effp->priv; sox_size_t len = min(*isamp, *osamp); *isamp = *osamp = len; while (len--) { /* 16 signed bits of triangular noise */ int tri16 = ((rand() % 32768) + (rand() % 32768)) - 32767; double l = *ibuf++ + tri16 * dither->amount; *obuf++ = SOX_ROUND_CLIP_COUNT(l, effp->clips); } return SOX_SUCCESS; } sox_effect_t const * sox_dither_effect_fn(void) { static sox_effect_t driver = { "dither", "Usage: dither [amount]", SOX_EFF_MCHAN, getopts, start, flow, 0, 0, 0 }; return &driver; } sox_effect_t const * sox_mask_effect_fn(void) { static sox_effect_t driver = { "mask", "Usage: mask [amount]", SOX_EFF_MCHAN | SOX_EFF_DEPRECATED, getopts, start, flow, 0, 0, 0 }; return &driver; }