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
int buf_size;
int period_bytes;
int sample_bytes;
+ int attenuate; /* shift left */
int present;
int pcm_format, channels, rate;
};
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) {
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--;
}
}
+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,
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);