erosq: Switch to 32-bit PCM output, and do volume scaling in driver

Should improve audio output quality, especially at lower volumes.

Change-Id: I31c38f05fe4b554b092511f0fe7aaad9f346f6c5
This commit is contained in:
Solomon Peachy 2021-04-08 23:58:49 -04:00
parent e86d90905b
commit 1e2a9a651c
4 changed files with 14 additions and 12 deletions

View file

@ -169,6 +169,10 @@ void audiohw_set_frequency(int fsel)
(void)fsel; (void)fsel;
} }
/* min/max for pcm volume */
const int min_pcm = -430;
const int max_pcm = 0;
void audiohw_set_volume(int vol_l, int vol_r) void audiohw_set_volume(int vol_l, int vol_r)
{ {
logf("hw vol %d %d", vol_l, vol_r); logf("hw vol %d %d", vol_l, vol_r);
@ -179,7 +183,7 @@ void audiohw_set_volume(int vol_l, int vol_r)
vol_r_hw = vol_r; vol_r_hw = vol_r;
if (lineout_inserted()) { if (lineout_inserted()) {
/* On the EROS Q/K hardware, line out is _very_ hot /* On the EROS Q/K hardware, full scale line out is _very_ hot
at ~5.8Vpp. As the hardware provides no way to reduce at ~5.8Vpp. As the hardware provides no way to reduce
output gain, we have to back off on the PCM signal output gain, we have to back off on the PCM signal
to avoid blowing out the signal. to avoid blowing out the signal.
@ -190,10 +194,9 @@ void audiohw_set_volume(int vol_l, int vol_r)
r = vol_r_hw; r = vol_r_hw;
} }
/* SW volume for <= 1.0 gain, HW at unity, < -740 == MUTE */ int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm);
int sw_volume_l = l <= -740 ? PCM_MUTE_LEVEL : MIN(l, 0); int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm);
int sw_volume_r = r <= -740 ? PCM_MUTE_LEVEL : MIN(r, 0); pcm_set_mixer_volume(sw_volume_l / 10, sw_volume_r / 10);
pcm_set_master_volume(sw_volume_l, sw_volume_r);
} }
void audiohw_set_lineout_volume(int vol_l, int vol_r) void audiohw_set_lineout_volume(int vol_l, int vol_r)
@ -212,7 +215,7 @@ void audiohw_set_lineout_volume(int vol_l, int vol_r)
r = vol_r_hw; r = vol_r_hw;
} }
int sw_volume_l = l <= -740 ? PCM_MUTE_LEVEL : MIN(l, 0); int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm);
int sw_volume_r = r <= -740 ? PCM_MUTE_LEVEL : MIN(r, 0); int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm);
pcm_set_master_volume(sw_volume_l, sw_volume_r); pcm_set_mixer_volume(sw_volume_l / 10, sw_volume_r / 10);
} }

View file

@ -36,8 +36,7 @@
/* Audio codec */ /* Audio codec */
#define HAVE_EROSQ_LINUX_CODEC #define HAVE_EROSQ_LINUX_CODEC
/* Rockbox has to handle the volume level */ #define HAVE_ALSA_32BIT
#define HAVE_SW_VOLUME_CONTROL
/* We don't have hardware controls */ /* We don't have hardware controls */
#define HAVE_SW_TONE_CONTROLS #define HAVE_SW_TONE_CONTROLS

View file

@ -3,7 +3,7 @@
#define AUDIOHW_CAPS (LINEOUT_CAP) #define AUDIOHW_CAPS (LINEOUT_CAP)
AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -43, 0, -20)
//#define AUDIOHW_NEEDS_INITIAL_UNMUTE //#define AUDIOHW_NEEDS_INITIAL_UNMUTE

View file

@ -277,7 +277,7 @@ static int dig_vol_mult_r = 2 << 16; /* multiplicative factor to apply to each s
void pcm_set_mixer_volume(int vol_db_l, int vol_db_r) void pcm_set_mixer_volume(int vol_db_l, int vol_db_r)
{ {
if(vol_db_l > 0 || vol_db_r > 0 || vol_db_l < -43 || vol_db_r < -43) if(vol_db_l > 0 || vol_db_r > 0 || vol_db_l < -43 || vol_db_r < -43)
panicf("invalid pcm alsa volume"); panicf("invalid pcm alsa volume %d %d", vol_db_l, vol_db_r);
if(format != SND_PCM_FORMAT_S32_LE) if(format != SND_PCM_FORMAT_S32_LE)
panicf("this function assumes 32-bit sample size"); panicf("this function assumes 32-bit sample size");
vol_db_l += 48; /* -42dB .. 0dB => 5dB .. 48dB */ vol_db_l += 48; /* -42dB .. 0dB => 5dB .. 48dB */