From f49ae1ab7a35e7d1c855d66a60d68b9dd9b57682 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Dec 2012 18:32:59 +1100 Subject: [PATCH] sound: allow a digit in file name to attenutate volume. Signed-off-by: NeilBrown --- sound/sound.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/sound/sound.c b/sound/sound.c index f2f0b4d..b83dbe2 100644 --- a/sound/sound.c +++ b/sound/sound.c @@ -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); -- 2.39.5