]> git.neil.brown.name Git - plato.git/commitdiff
sound: allow a digit in file name to attenutate volume.
authorNeilBrown <neilb@suse.de>
Thu, 27 Dec 2012 07:32:59 +0000 (18:32 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 27 Dec 2012 07:32:59 +0000 (18:32 +1100)
Signed-off-by: NeilBrown <neil@brown.name>
sound/sound.c

index f2f0b4dbe72d702a4cf710f71f0b1c11e5cd6e3a..b83dbe25dad17c0e67f076123c0a18e415ea9662 100644 (file)
@@ -136,6 +136,7 @@ struct sound {
        int period_bytes;
        int bytes, bytes_used, last_read;
        int eof;
+       int attenuate; /* shift left */
 
        /* An audio file can contain multiple chunks.
         * Here we record the remaining bytes expected
@@ -158,6 +159,7 @@ struct dev {
        int             buf_size;
        int             period_bytes;
        int             sample_bytes;
+       int             attenuate; /* shift left */
        int             present;
        int             pcm_format, channels, rate;
 };
@@ -476,6 +478,7 @@ void set_params(struct dev *dev, struct sound *sound)
        dev->pcm_format = sound->pcm_format;
        dev->channels = sound->channels;
        dev->rate = sound->rate;
+       dev->attenuate = sound->attenuate;
        dev->sample_bytes = sound->sample_bytes;
        dev->period_bytes = sound->period_bytes;
        if (dev->buf_size < dev->period_bytes) {
@@ -535,15 +538,33 @@ struct sound *open_sound(char *dir, char *name, int ino)
        s->posn = 0;
        s->bytes = s->bytes_used = 0;
 
+       /* Filename must contain the  'scenario' name which
+        * determines mixer settings, and may contain a single
+        * digit which reduces the volume, and a millisecond offset
+        * which is digits preceeded by a hyphen.
+        * Typically it starts with a numeric priority.
+        * So:  05-ring-alert5-20
+        * Would play the sound with the 'alert' scenario and 50% volume
+        * starting 20ms from start.
+        */
        /* check for millisecond suffix */
        eos = name + strlen(name);
-       while (eos > name && isdigit(eos[-1]))
-               eos--;
-       if (eos > name && eos[-1] == '-' && eos[0]) {
-               s->posn = atol(eos);
-               eos--;
+       eos1 = eos;
+       while (eos1 > name && isdigit(eos1[-1]))
+               eos1--;
+       if (eos1 > name && eos1[-1] == '-' && eos1[0]) {
+               s->posn = atol(eos1);
+               eos = eos1 - 1;
        }
-       /* Now pick off scenario name */
+       /* Now pick off volume and scenario name */
+       if (eos > name && isdigit(eos[-1])) {
+               int n = eos[-1] - '0';
+               if (n == 0)
+                       n = 10;
+               s->attenuate = 10 - n;
+               eos--;
+       } else
+               s->attenuate = 0;
        eos1 = eos;
        while (eos1 > name && isalpha(eos1[-1]))
                eos1--;
@@ -673,9 +694,36 @@ void scan_dir(char *path, struct list_head *soundqueue)
                }
 }
 
+static void scale_buf(struct dev *dev)
+{
+       int i;
+       switch (dev->pcm_format) {
+       case SND_PCM_FORMAT_U8:
+               for (i = 0; i < dev->period_bytes; i++) {
+                       int v = dev->period_buf[i];
+                       v = v >> dev->attenuate;
+                       dev->period_buf[i] = v;
+               }
+               break;
+
+       case SND_PCM_FORMAT_S16_LE:
+               printf("period = %d\n", dev->period_bytes);
+               for (i = 0; i < dev->period_bytes / 2; i++) {
+                       int v = *(short*)(dev->period_buf+i*2);
+                       v = v >> dev->attenuate;
+                       *(short*)(dev->period_buf+i*2) = v;
+               }
+               break;
+       default:
+               break;
+       }
+}
+
 void play_buf(struct dev *dev)
 {
        if (dev->present == dev->period_bytes) {
+               if (dev->attenuate)
+                       scale_buf(dev);
                alarm(30);
                snd_pcm_writei(dev->handle,
                               dev->period_buf,
@@ -692,6 +740,8 @@ void dev_close(struct dev *dev)
        if (dev->present) {
                memset(dev->period_buf + dev->present, 0,
                       dev->period_bytes - dev->present);
+               if (dev->attenuate)
+                       scale_buf(dev);
                snd_pcm_writei(dev->handle,
                               dev->period_buf,
                               dev->period_bytes / dev->sample_bytes);