mirror of
https://github.com/linux-speakup/espeakup.git
synced 2026-08-21 07:14:18 +02:00
Support setting ALSA volume in addition to espeak volume
This allows to make sure to reach the maximum volume permitted by the hardware. This makes the default volume (5) set ALSA volume to 80%, like the default ALSA scripts do. This is not enabled by default, since users will probably want to use a mixer to fine-tune their volume. But for e.g. installation images, this allows to spare the use of a mixer and just use the speakup volume control.
This commit is contained in:
parent
e69d61b2d8
commit
53665b8eab
3 changed files with 94 additions and 1 deletions
2
Makefile
2
Makefile
|
|
@ -6,7 +6,7 @@ DEPFLAGS = -MMD
|
|||
WARNFLAGS = -Wall
|
||||
CFLAGS += ${DEPFLAGS} ${WARNFLAGS}
|
||||
|
||||
LDLIBS = -lespeak -lpthread
|
||||
LDLIBS = -lespeak -lpthread -lasound -lm
|
||||
|
||||
INSTALL = install
|
||||
BINMODE = 0755
|
||||
|
|
|
|||
6
cli.c
6
cli.c
|
|
@ -30,11 +30,15 @@ extern char *pidPath;
|
|||
/* default voice */
|
||||
extern char *defaultVoice;
|
||||
|
||||
/* Whether to drive ALSA volume */
|
||||
extern int alsaVolume;
|
||||
|
||||
/* command line options */
|
||||
const char *shortOptions = "P:V:adhv";
|
||||
const struct option longOptions[] = {
|
||||
{"pid-path", required_argument, NULL, 'P'},
|
||||
{"default-voice", required_argument, NULL, 'V'},
|
||||
{"alsa-volume", no_argument, &alsaVolume, 1},
|
||||
{"acsint", no_argument, NULL, 'a'},
|
||||
{"debug", no_argument, NULL, 'd'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
|
|
@ -48,6 +52,7 @@ static void show_help()
|
|||
printf("Options are as follows:\n");
|
||||
printf(" --pid-path=path, -P path\t\tSet path for pid file.\n");
|
||||
printf(" --default-voice=voice, -V voice\tSet default voice.\n");
|
||||
printf(" --alsa-volume\t\t\t\tDrive the ALSA volume.\n");
|
||||
printf(" --debug, -d\t\t\t\tDebug mode (stay in the foreground).\n");
|
||||
printf(" --help, -h\t\t\t\tShow this help.\n");
|
||||
printf(" --version, -v\t\t\t\tDisplay the software version.\n");
|
||||
|
|
@ -93,6 +98,7 @@ void process_cli(int argc, char **argv)
|
|||
show_version();
|
||||
break;
|
||||
case -1:
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
show_help();
|
||||
|
|
|
|||
87
espeak.c
87
espeak.c
|
|
@ -22,6 +22,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "espeakup.h"
|
||||
|
||||
|
|
@ -31,6 +33,7 @@ const int defaultPitch = 5;
|
|||
const int defaultRate = 2;
|
||||
const int defaultVolume = 5;
|
||||
char *defaultVoice = NULL;
|
||||
int alsaVolume = 0;
|
||||
|
||||
/* multipliers and offsets */
|
||||
const int frequencyMultiplier = 11;
|
||||
|
|
@ -135,6 +138,86 @@ static espeak_ERROR set_voice(struct synth_t *s, char *voice)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void set_alsa_volume(int vol)
|
||||
{
|
||||
snd_mixer_t *m;
|
||||
snd_mixer_elem_t *e;
|
||||
int err;
|
||||
|
||||
err = snd_mixer_open(&m, 0);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr, "ALSA mixer open error: %s\n", snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
err = snd_mixer_attach(m, "default");
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr, "ALSA mixer attach error: %s\n", snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
err = snd_mixer_selem_register(m, NULL, NULL);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr, "ALSA mixer load error: %s\n", snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
err = snd_mixer_load(m);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr, "ALSA mixer load error: %s\n", snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Turn vol value to volume %.
|
||||
* We do not want to soften that much with ALSA, espeak is already
|
||||
* doing it. We want the default value (5) to be the usual default
|
||||
* volume (80%), and make higher values increase ALSA volume, up to
|
||||
* 100%. */
|
||||
|
||||
int volume = (vol+1) * 50 / 10 + 50;
|
||||
|
||||
for (e = snd_mixer_first_elem(m); e; e = snd_mixer_elem_next(e))
|
||||
{
|
||||
if (snd_mixer_elem_get_type(e) != SND_MIXER_ELEM_SIMPLE)
|
||||
continue;
|
||||
if (snd_mixer_selem_is_enumerated(e))
|
||||
continue;
|
||||
|
||||
if (snd_mixer_selem_has_playback_switch(e)) {
|
||||
snd_mixer_selem_set_playback_switch_all(e, 1);
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_playback_volume(e)) {
|
||||
long min, max, set;
|
||||
|
||||
err = snd_mixer_selem_get_playback_dB_range(e, &min, &max);
|
||||
if (err == 0 && min < max) {
|
||||
if (max - min < 2400) {
|
||||
/* 24dB amplitude is too small for using a logscale */
|
||||
set = min + volume * (max-min) / 100;
|
||||
} else {
|
||||
/* Use a logscale */
|
||||
double volf = volume / 100.;
|
||||
if (min != SND_CTL_TLV_DB_GAIN_MUTE)
|
||||
{
|
||||
double minf = pow(10, (min-max) / 6000.);
|
||||
volf = volf * (1 - minf) + minf;
|
||||
}
|
||||
set = 6000. * log10(volf) + max;
|
||||
}
|
||||
snd_mixer_selem_set_playback_dB_all(e, set, 0);
|
||||
} else {
|
||||
/* No dB setting, try a linear scale */
|
||||
snd_mixer_selem_get_playback_volume_range(e, &min, &max);
|
||||
set = min + volume * (max-min) / 100;
|
||||
snd_mixer_selem_set_playback_volume_all(e, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static espeak_ERROR set_volume(struct synth_t *s, int vol,
|
||||
enum adjust_t adj)
|
||||
{
|
||||
|
|
@ -147,7 +230,11 @@ static espeak_ERROR set_volume(struct synth_t *s, int vol,
|
|||
rc = espeak_SetParameter(espeakVOLUME, (vol + 1) * volumeMultiplier,
|
||||
0);
|
||||
if (rc == EE_OK)
|
||||
{
|
||||
s->volume = vol;
|
||||
if (alsaVolume)
|
||||
set_alsa_volume(vol);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue