1
0
Fork 0
forked from len0rd/rockbox

Provide high resolution volume and prescaler to hosted targets.

HAVE_SW_VOLUME_CONTROL is required and at this time only affects the
SDL targets using pcm-sdl.c.

Enables balance control in SDL targets, unless mono volume is in use.

Compiles software volume control as unbuffered when
PCM_SW_VOLUME_UNBUFFERED is defined. This avoids the overhead and
extra latency introduced by the double buffer when it is not needed.
Use this config when the target's PCM driver is buffered and sufficient
latency exists to perform safely the volume scaling.

Simulated targets that are double-buffered when made as native targets
remain so in the sim in order to run the same code.

Change-Id: Ifa77d2d3ae7376c65afecdfc785a084478cb5ffb
Reviewed-on: http://gerrit.rockbox.org/457
Reviewed-by: Michael Sevakis <jethead71@rockbox.org>
Tested-by: Michael Sevakis <jethead71@rockbox.org>
This commit is contained in:
Michael Sevakis 2013-04-23 03:20:49 -04:00
parent 370ed6de7c
commit 08199cd6cb
9 changed files with 189 additions and 106 deletions

View file

@ -27,13 +27,36 @@
#ifdef HAVE_SW_VOLUME_CONTROL
/* Default settings - architecture may have other optimal values */
#define PCM_FACTOR_BITS 15 /* Allows -73 to +6dB gain, sans 64-bit math */
#define PCM_PLAY_DBL_BUF_SAMPLES 1024 /* Max 4KByte chunks */
#define PCM_DBL_BUF_BSS /* In DRAM, uncached may be better */
#define PCM_FACTOR_MIN 0x00000 /* Minimum final factor */
#define PCM_FACTOR_MAX 0x10000 /* Maximum final factor */
#ifndef PCM_SW_VOLUME_FRACBITS
/* Allows -73 to +6dB gain, sans large integer math */
#define PCM_SW_VOLUME_FRACBITS (15)
#endif
/* Constants selected based on integer math overflow avoidance */
#if PCM_SW_VOLUME_FRACBITS <= 16
#define PCM_FACTOR_MAX 0x00010000u
#define PCM_FACTOR_UNITY (1u << PCM_SW_VOLUME_FRACBITS)
#elif PCM_SW_VOLUME_FRACBITS <= 31
#define PCM_FACTOR_MAX 0x80000000u
#define PCM_FACTOR_UNITY (1u << PCM_SW_VOLUME_FRACBITS)
#endif /* PCM_SW_VOLUME_FRACBITS */
#ifdef PCM_SW_VOLUME_UNBUFFERED
/* Copies buffer with volume scaling applied */
void pcm_sw_volume_copy_buffer(void *dst, const void *src, size_t size);
#define pcm_copy_buffer pcm_sw_volume_copy_buffer
#else /* !PCM_SW_VOLUME_UNBUFFERED */
#ifdef HAVE_SDL_AUDIO
#define pcm_copy_buffer memcpy
#endif
#ifndef PCM_PLAY_DBL_BUF_SAMPLES
#define PCM_PLAY_DBL_BUF_SAMPLES 1024 /* Max 4KByte chunks */
#endif
#ifndef PCM_DBL_BUF_BSS
#define PCM_DBL_BUF_BSS /* In DRAM, uncached may be better */
#endif
#endif /* PCM_SW_VOLUME_UNBUFFERED */
#define PCM_FACTOR_UNITY (1 << PCM_FACTOR_BITS)
#endif /* HAVE_SW_VOLUME_CONTROL */
#define PCM_SAMPLE_SIZE (2 * sizeof (int16_t))
@ -84,22 +107,22 @@ static FORCE_INLINE enum pcm_dma_status pcm_play_call_status_cb(
static FORCE_INLINE enum pcm_dma_status
pcm_play_dma_status_callback(enum pcm_dma_status status)
{
#ifdef HAVE_SW_VOLUME_CONTROL
#if defined(HAVE_SW_VOLUME_CONTROL) && !defined(PCM_SW_VOLUME_UNBUFFERED)
extern enum pcm_dma_status
pcm_play_dma_status_callback_int(enum pcm_dma_status status);
return pcm_play_dma_status_callback_int(status);
#else
return pcm_play_call_status_cb(status);
#endif /* HAVE_SW_VOLUME_CONTROL */
#endif /* HAVE_SW_VOLUME_CONTROL && !PCM_SW_VOLUME_UNBUFFERED */
}
#ifdef HAVE_SW_VOLUME_CONTROL
#if defined(HAVE_SW_VOLUME_CONTROL) && !defined(PCM_SW_VOLUME_UNBUFFERED)
void pcm_play_dma_start_int(const void *addr, size_t size);
void pcm_play_dma_pause_int(bool pause);
void pcm_play_dma_stop_int(void);
void pcm_play_stop_int(void);
const void *pcm_play_dma_get_peak_buffer_int(int *count);
#endif /* HAVE_SW_VOLUME_CONTROL */
#endif /* HAVE_SW_VOLUME_CONTROL && !PCM_SW_VOLUME_UNBUFFERED */
/* Called by the bottom layer ISR when more data is needed. Returns true
* if a new buffer is available, false otherwise. */