1
0
Fork 0
forked from len0rd/rockbox

Hosted PCM: Rework auto-muting code a bit

* If AUDIOHW_MUTE_ON_PAUSE, no meaningful change
     * Unconditionally unmute on playback start
     * xduoox3ii:  Mute on sample rate change
     * rocker/xduoo:  Stay muted after startup

    This avoids the nasty "pop" on startup, without doing
    the full mute-on-pause stuff that causes unacceptable
    dropouts on the X3ii.

Change-Id: I2e3ee0bb8094e288f37a0acada86a80016ce5cac
This commit is contained in:
Solomon Peachy 2020-10-12 09:29:21 -04:00
parent 9ad30869b8
commit 141e91ef1f
5 changed files with 44 additions and 22 deletions

View file

@ -56,6 +56,8 @@ static void hw_close(void)
close(fd_hw);
}
static int muted = -1;
void audiohw_mute(int mute)
{
logf("mute %d", mute);
@ -70,6 +72,7 @@ void audiohw_mute(int mute)
last_ps = 0;
erosq_get_outputs();
}
muted = mute;
}
int erosq_get_outputs(void) {
@ -95,7 +98,7 @@ int erosq_get_outputs(void) {
void erosq_set_output(int ps)
{
if (!inited) return;
if (!inited || muted) return;
if (last_ps != ps)
{
@ -119,7 +122,7 @@ void audiohw_preinit(void)
void audiohw_postinit(void)
{
logf("hw postinit");
erosq_set_output(erosq_get_outputs()); /* Unmute */
erosq_get_outputs(); // Unmutes
}
void audiohw_close(void)

View file

@ -70,7 +70,7 @@ void audiohw_postinit(void)
long int hp = 2;
/* Output port switch set to Headphones */
alsa_controls_set_ints("Output Port Switch", 1, &hp); /* Unmutes */
//alsa_controls_set_ints("Output Port Switch", 1, &hp); // Unmute happens on PCM start
}
void audiohw_close(void)

View file

@ -55,6 +55,8 @@ static void hw_close(void)
close(fd_hw);
}
static int muted = -1;
void audiohw_mute(int mute)
{
logf("mute %d", mute);
@ -69,6 +71,7 @@ void audiohw_mute(int mute)
last_ps = 0;
xduoo_get_outputs();
}
muted = mute;
}
int xduoo_get_outputs(void){
@ -102,7 +105,7 @@ int xduoo_get_outputs(void){
void xduoo_set_output(int ps)
{
if (!inited) return;
if (!inited || muted) return;
if (last_ps != ps)
{
@ -128,7 +131,7 @@ void audiohw_postinit(void)
// const char * const codec_pmdown = "/sys/devices/platform/ingenic-x3ii.0/x3ii-ak4490-i2s/pmdown_time"; // in ms, defaults 5000
logf("hw postinit");
xduoo_set_output(xduoo_get_outputs()); /* Unmute */
// xduoo_get_outputs(); // Unmute happens upon playback.
}
void audiohw_close(void)

View file

@ -6,6 +6,14 @@ AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -127, 0, -30)
AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 4, 0)
#endif
// We want this, but the codec takes over a second to unmute!
//#define AUDIOHW_MUTE_ON_PAUSE
#if defined(XDUOO_X3II)
/* The AK4490 glitches when switching sample rates */
#define AUDIOHW_MUTE_ON_SRATE_CHANGE
#endif
void audiohw_mute(int mute);
void xduoo_set_output(int ps);
int xduoo_get_outputs(void);

View file

@ -81,8 +81,8 @@ static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format *
typedef short sample_t;
#endif
static const int channels = 2; /* count of channels */
static unsigned int sample_rate = 0;
static unsigned int real_sample_rate = 0;
static unsigned int last_sample_rate = 0;
static snd_pcm_t *handle = NULL;
static snd_pcm_sframes_t buffer_size;
@ -148,17 +148,17 @@ static int set_hwparams(snd_pcm_t *handle)
goto error;
}
/* set the stream rate */
sample_rate = srate = pcm_sampr;
srate = pcm_sampr;
err = snd_pcm_hw_params_set_rate_near(handle, params, &srate, 0);
if (err < 0)
{
logf("Rate %iHz not available for playback: %s\n", sample_rate, snd_strerror(err));
logf("Rate %iHz not available for playback: %s\n", pcm_sampr, snd_strerror(err));
goto error;
}
real_sample_rate = srate;
if (real_sample_rate != sample_rate)
if (real_sample_rate != pcm_sampr)
{
logf("Rate doesn't match (requested %iHz, get %iHz)\n", sample_rate, real_sample_rate);
logf("Rate doesn't match (requested %iHz, get %iHz)\n", pcm_sampr, real_sample_rate);
err = -EINVAL;
goto error;
}
@ -517,11 +517,13 @@ void pcm_play_unlock(void)
static void pcm_dma_apply_settings_nolock(void)
{
logf("PCM DMA Settings %d %d", sample_rate, pcm_sampr);
logf("PCM DMA Settings %d %d", last_sample_rate, pcm_sampr);
if (sample_rate != pcm_sampr)
if (last_sample_rate != pcm_sampr)
{
#ifdef AUDIOHW_MUTE_ON_PAUSE
last_sample_rate = pcm_sampr;
#ifdef AUDIOHW_MUTE_ON_SRATE_CHANGE
// XXX AK4450 (xDuoo X3ii) needs to be muted when switching rates.
audiohw_mute(true);
#endif
@ -531,8 +533,10 @@ static void pcm_dma_apply_settings_nolock(void)
/* Sony NWZ linux driver uses a nonstandard mecanism to set the sampling rate */
audiohw_set_frequency(pcm_sampr);
#endif
/* (Will be unmuted by pcm resuming) */
#ifdef AUDIOHW_MUTE_ON_SRATE_CHANGE
audiohw_mute(false);
#endif
/* (Will be unmuted by pcm resuming) */
}
}
@ -560,7 +564,7 @@ void pcm_play_dma_stop(void)
snd_pcm_nonblock(handle, 0);
snd_pcm_drain(handle);
snd_pcm_nonblock(handle, 1);
sample_rate = 0;
last_sample_rate = 0;
#ifdef AUDIOHW_MUTE_ON_PAUSE
audiohw_mute(true);
#endif
@ -575,6 +579,10 @@ void pcm_play_dma_start(const void *addr, size_t size)
pcm_data = addr;
pcm_size = size;
#if !defined(AUDIOHW_MUTE_ON_PAUSE) || !defined(AUDIOHW_MUTE_ON_SRATE_CHANGE)
audiohw_mute(false);
#endif
while (1)
{
snd_pcm_state_t state = snd_pcm_state(handle);
@ -605,14 +613,14 @@ void pcm_play_dma_start(const void *addr, size_t size)
int err = async_rw(handle);
if (err < 0) {
logf("Start error: %s\n", snd_strerror(err));
return;
}
return;
}
#ifdef AUDIOHW_MUTE_ON_PAUSE
audiohw_mute(false);
audiohw_mute(false);
#endif
if (err == 0)
return;
break;
if (err == 0)
return;
break;
}
case SND_PCM_STATE_PAUSED:
{ /* paused, simply resume */