shithub: sox

Download patch

ref: 4a1a3de04de21a211c958ae62a77166cbc258d30
parent: 8873f38b8b4a2ef5210e6b6c870d184f005ae70e
author: robs <robs>
date: Sun Dec 17 04:25:07 EST 2006

Make dither alias for mask, add amount parameter, clipping detection, & nullification

--- a/src/mask.c
+++ b/src/mask.c
@@ -9,6 +9,8 @@
 
 /*
  * Sound Tools masking noise effect file.
+ *
+ * TODO: does triangular noise, could do local shaping
  */
 
 #include <stdlib.h>
@@ -15,102 +17,101 @@
 #include <math.h>
 #include "st_i.h"
 
-static st_effect_t st_mask_effect;
+typedef struct mask {
+  double amount;
+} * mask_t;
 
-#define HALFABIT 1.44                   /* square root of 2 */
+assert_static(sizeof(struct mask) <= ST_MAX_EFFECT_PRIVSIZE,
+              /* else */ mask_PRIVSIZE_too_big);
 
-/*
- * Problems:
- *      1) doesn't allow specification of noise depth
- *      2) does triangular noise, could do local shaping
- *      3) can run over 32 bits.
- */
-
-/*
- * Process options
- */
-static int st_mask_getopts(eff_t effp UNUSED, int n, char **argv UNUSED)
+static int st_mask_getopts(eff_t effp, int n, char * * argv)
 {
-        if (n)
-        {
-                st_fail(st_mask_effect.usage);
-                return (ST_EOF);
-        }
-        /* should take # of bits */
+  mask_t mask = (mask_t) effp->priv;
 
-        st_initrand();
-        return (ST_SUCCESS);
+  if (n > 1) {
+    st_fail(effp->h->usage);
+    return ST_EOF;
+  }
+  
+  mask->amount = M_SQRT2;   /* 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)
+      mask->amount *= amount;
+    else {
+      st_fail(effp->h->usage);
+      return ST_EOF;
+    }
+  }
+
+  return ST_SUCCESS;
 }
 
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
-static int st_mask_flow(eff_t effp, const st_sample_t *ibuf, st_sample_t *obuf, 
-                 st_size_t *isamp, st_size_t *osamp)
+static int st_mask_start(eff_t effp)
 {
-        int len, done;
-        
-        st_sample_t l;
-        st_sample_t tri16;      /* 16 signed bits of triangular noise */
+  mask_t mask = (mask_t) effp->priv;
 
-        len = ((*isamp > *osamp) ? *osamp : *isamp);
-        switch (effp->outinfo.encoding) {
-                case ST_ENCODING_ULAW:
-                case ST_ENCODING_ALAW:
-                        for(done = 0; done < len; done++) {
-                                tri16 = 
-                                  ((rand()%32768L) + (rand()%32768L)) - 32767;
+  if (effp->outinfo.encoding == ST_ENCODING_ULAW ||
+      effp->outinfo.encoding == ST_ENCODING_ALAW) {
+    mask->amount *= 16;
+    return ST_SUCCESS;
+  }
+  if (effp->outinfo.size == ST_SIZE_BYTE) {
+    mask->amount *= 256;
+    return ST_SUCCESS;
+  }
+  if (effp->outinfo.size == ST_SIZE_WORD)
+    return ST_SUCCESS;
 
-                                l = *ibuf++ + tri16*16*HALFABIT;  /* 2^4.5 */
-                                *obuf++ = l;
-                        }
-                        break;
-                default:
-                switch (effp->outinfo.size) {
-                        case ST_SIZE_BYTE:
-                        for(done = 0; done < len; done++) {
-                                tri16 = 
-                                  ((rand()%32768L) + (rand()%32768L)) - 32767;
+  return ST_EFF_NULL;   /* Dithering not needed at >= 24 bits */
+}
 
-                                l = *ibuf++ + tri16*256*HALFABIT;  /* 2^8.5 */
-                                *obuf++ = l;
-                        }
-                        break;
-                        case ST_SIZE_WORD:
-                        for(done = 0; done < len; done++) {
-                                tri16 = 
-                                  ((rand()%32768L) + (rand()%32768L)) - 32767;
+static int st_mask_flow(eff_t effp, const st_sample_t * ibuf,
+    st_sample_t * obuf, st_size_t * isamp, st_size_t * osamp)
+{
+  mask_t mask = (mask_t) effp->priv;
+  st_size_t len = *isamp > *osamp ? *osamp : *isamp;
 
-                                l = *ibuf++ + tri16*HALFABIT;  /* 2^.5 */
-                                *obuf++ = l;
-                        }
-                        break;
-                        default: /* Mask (dither) not needed at >= 24 bits */
-                        for(done = 0; done < len; done++) {
-                                *obuf++ = *ibuf++;
-                        }
-                        break;
-                }
-        }
+  *isamp = *osamp = len;
+  while (len--)
+  {                     /* 16 signed bits of triangular noise */
+    int tri16 = ((rand() % 32768L) + (rand() % 32768L)) - 32767;
+    double l = *ibuf++ + tri16 * mask->amount;
+    *obuf++ = ST_ROUND_CLIP_COUNT(l, effp->clippedCount);
+  }
+  return ST_SUCCESS;
+}
 
-        *isamp = done;
-        *osamp = done;
-        return (ST_SUCCESS);
-}
-
 static st_effect_t st_mask_effect = {
   "mask",
-  "Usage: Mask effect takes no options",
+  "Usage: mask [amount]",
   ST_EFF_MCHAN,
   st_mask_getopts,
-  st_effect_nothing,
+  st_mask_start,
   st_mask_flow,
   st_effect_nothing_drain,
   st_effect_nothing
 };
 
-const st_effect_t *st_mask_effect_fn(void)
+st_effect_t const * st_mask_effect_fn(void)
 {
-    return &st_mask_effect;
+  return &st_mask_effect;
+}
+
+static st_effect_t st_dither_effect = {
+  "dither",
+  "Usage: dither [amount]",
+  ST_EFF_MCHAN,
+  st_mask_getopts,
+  st_mask_start,
+  st_mask_flow,
+  st_effect_nothing_drain,
+  st_effect_nothing
+};
+
+st_effect_t const * st_dither_effect_fn(void)
+{
+  return &st_dither_effect;
 }
--