mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-09 23:53:28 -04:00
pcm_sink: allow per-sink swvol/hwvol selection
Change-Id: I5b0a66f2e41ca32a2d6c88bda3ffe0db0df08ce0
This commit is contained in:
parent
51d7d56803
commit
9a7ffac2e4
30 changed files with 91 additions and 29 deletions
|
|
@ -552,9 +552,9 @@ sound.c
|
|||
pcm_sampr.c
|
||||
pcm.c
|
||||
pcm_mixer.c
|
||||
#ifdef HAVE_SW_VOLUME_CONTROL
|
||||
#ifdef WANT_SWVOL
|
||||
pcm_sw_volume.c
|
||||
#endif /* HAVE_SW_VOLUME_CONTROL */
|
||||
#endif /* WANT_SWVOL */
|
||||
#ifdef HAVE_RECORDING
|
||||
enc_base.c
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
|
|
|||
|
|
@ -696,4 +696,12 @@ AUDIOHW_SETTING(STEREO_WIDTH, "%", 0, 5, 0, 250, 100)
|
|||
# define PCM_NATIVE_BITDEPTH 16
|
||||
#endif
|
||||
|
||||
#ifndef PCM_NATIVE_VOLUME_TYPE
|
||||
#if !defined(HAVE_SW_VOLUME_CONTROL) || defined(PCM_SW_VOLUME_UNBUFFERED)
|
||||
#define PCM_NATIVE_VOLUME_TYPE PCM_SINK_HWVOL
|
||||
#else
|
||||
#define PCM_NATIVE_VOLUME_TYPE PCM_SINK_SWVOL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _AUDIOHW_H_ */
|
||||
|
|
|
|||
|
|
@ -1494,4 +1494,12 @@ Lyre prototype 1 */
|
|||
#define ucschar_t unsigned short
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SW_VOLUME_CONTROL
|
||||
#define WANT_SWVOL
|
||||
#endif
|
||||
|
||||
#if defined(PCM_NATIVE_BITDEPTH) && (PCM_NATIVE_BITDEPTH > 16)
|
||||
#define WANT_SWVOL_32
|
||||
#endif
|
||||
|
||||
#endif /* __CONFIG_H__ */
|
||||
|
|
|
|||
|
|
@ -45,21 +45,22 @@
|
|||
#define PCM_FACTOR_UNITY (1u << PCM_SW_VOLUME_FRACBITS)
|
||||
#endif /* PCM_SW_VOLUME_FRACBITS */
|
||||
|
||||
#ifdef HAVE_SDL_AUDIO
|
||||
#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
|
||||
#else /* PCM_SW_VOLUME_UNBUFFERED */
|
||||
#define pcm_copy_buffer memcpy
|
||||
#endif
|
||||
#endif /* PCM_SW_VOLUME_UNBUFFERED */
|
||||
#endif /* HAVE_SDL_AUDIO */
|
||||
|
||||
#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 */
|
||||
|
||||
void pcm_sync_pcm_factors(void);
|
||||
#endif /* HAVE_SW_VOLUME_CONTROL */
|
||||
|
|
@ -126,20 +127,15 @@ 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)
|
||||
{
|
||||
#if defined(HAVE_SW_VOLUME_CONTROL) && !defined(PCM_SW_VOLUME_UNBUFFERED)
|
||||
#ifdef WANT_SWVOL
|
||||
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
|
||||
pcm_play_dma_status_callback_int_swvol(enum pcm_dma_status status);
|
||||
if (pcm_current_sink_caps()->volume_type == PCM_SINK_SWVOL)
|
||||
return pcm_play_dma_status_callback_int_swvol(status);
|
||||
#endif /* WANT_SWVOL */
|
||||
return pcm_play_call_status_cb(status);
|
||||
#endif /* HAVE_SW_VOLUME_CONTROL && !PCM_SW_VOLUME_UNBUFFERED */
|
||||
}
|
||||
|
||||
#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_stop_int(void);
|
||||
#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. */
|
||||
bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
||||
|
|
|
|||
|
|
@ -23,10 +23,16 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#define PCM_SINK_HWVOL 0
|
||||
#ifdef WANT_SWVOL
|
||||
#define PCM_SINK_SWVOL 1
|
||||
#endif
|
||||
|
||||
struct pcm_sink_caps {
|
||||
const unsigned long* samprs;
|
||||
uint16_t num_samprs;
|
||||
uint16_t default_freq;
|
||||
uint8_t num_samprs;
|
||||
uint8_t default_freq;
|
||||
uint8_t volume_type;
|
||||
};
|
||||
|
||||
struct pcm_sink_ops {
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@
|
|||
** the library or a hardware necessity. Normally, it shouldn't be used and
|
||||
** only the port developer can properly decide.
|
||||
**/
|
||||
#ifdef HAVE_SW_VOLUME_CONTROL
|
||||
#ifdef WANT_SWVOL
|
||||
|
||||
#include <audiohw.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define PCM_MUTE_LEVEL INT_MIN
|
||||
|
||||
|
|
@ -41,6 +42,11 @@ void pcm_set_prescaler(int prescale);
|
|||
/* Set the per-channel volume cut/gain for all PCM playback */
|
||||
void pcm_set_master_volume(int vol_l, int vol_r);
|
||||
|
||||
#endif /* HAVE_SW_VOLUME_CONTROL */
|
||||
void pcm_play_dma_start_int_swvol(const void *addr, size_t size);
|
||||
void pcm_play_dma_stop_int_swvol(void);
|
||||
enum pcm_dma_status pcm_play_dma_status_callback_int_swvol(enum pcm_dma_status status);
|
||||
bool pcm_play_dma_complete_callback_swvol(enum pcm_dma_status status,
|
||||
const void **addr, size_t *size);
|
||||
#endif /* WANT_SWVOL */
|
||||
|
||||
#endif /* PCM_SW_VOLUME_H */
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "general.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_mixer.h"
|
||||
#include "pcm_sw_volume.h"
|
||||
|
||||
/**
|
||||
* Aspects implemented in the target-specific portion:
|
||||
|
|
@ -105,12 +106,15 @@ struct pcm_sink* pcm_get_current_sink(void)
|
|||
return sinks[cur_sink];
|
||||
}
|
||||
|
||||
#if !defined(HAVE_SW_VOLUME_CONTROL) || defined(PCM_SW_VOLUME_UNBUFFERED)
|
||||
/** Standard hw volume/unbuffered control functions - otherwise, see
|
||||
** pcm_sw_volume.c **/
|
||||
static inline void pcm_play_dma_start_int(const void *addr, size_t size)
|
||||
{
|
||||
#ifdef HAVE_SW_VOLUME_CONTROL
|
||||
#ifdef WANT_SWVOL
|
||||
if (sinks[cur_sink]->caps.volume_type == PCM_SINK_SWVOL) {
|
||||
pcm_play_dma_start_int_swvol(addr, size);
|
||||
return;
|
||||
}
|
||||
/* Smoothed transition might not have happened so sync now */
|
||||
pcm_sync_pcm_factors();
|
||||
#endif
|
||||
|
|
@ -119,12 +123,23 @@ static inline void pcm_play_dma_start_int(const void *addr, size_t size)
|
|||
|
||||
static inline void pcm_play_dma_stop_int(void)
|
||||
{
|
||||
#ifdef WANT_SWVOL
|
||||
if (sinks[cur_sink]->caps.volume_type == PCM_SINK_SWVOL) {
|
||||
pcm_play_dma_stop_int_swvol();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
sinks[cur_sink]->ops.stop();
|
||||
}
|
||||
|
||||
bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
||||
const void **addr, size_t *size)
|
||||
{
|
||||
#ifdef WANT_SWVOL
|
||||
if (sinks[cur_sink]->caps.volume_type == PCM_SINK_SWVOL) {
|
||||
return pcm_play_dma_complete_callback_swvol(status, addr, size);
|
||||
}
|
||||
#endif
|
||||
/* Check status callback first if error */
|
||||
if (status < PCM_DMAST_OK)
|
||||
status = pcm_play_dma_status_callback(status);
|
||||
|
|
@ -137,7 +152,6 @@ bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
|||
pcm_play_stop_int();
|
||||
return false;
|
||||
}
|
||||
#endif /* !HAVE_SW_VOLUME_CONTROL || PCM_SW_VOLUME_UNBUFFERED */
|
||||
|
||||
void pcm_play_stop_int(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ void pcm_sync_pcm_factors(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef PCM_SW_VOLUME_UNBUFFERED
|
||||
#ifdef WANT_SWVOL
|
||||
/* source buffer from client */
|
||||
static const void * volatile src_buf_addr = NULL;
|
||||
static size_t volatile src_buf_rem = 0;
|
||||
|
|
@ -227,7 +227,7 @@ static unsigned int frame_count, frame_err, frame_frac;
|
|||
|
||||
/** Overrides of certain functions in pcm.c and pcm-internal.h **/
|
||||
|
||||
bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
||||
bool pcm_play_dma_complete_callback_swvol(enum pcm_dma_status status,
|
||||
const void **addr, size_t *size)
|
||||
{
|
||||
/* Check status callback first if error */
|
||||
|
|
@ -268,7 +268,7 @@ static void update_frame_params(size_t size)
|
|||
|
||||
/* Obtain the next buffer and prepare it for pcm driver playback */
|
||||
enum pcm_dma_status
|
||||
pcm_play_dma_status_callback_int(enum pcm_dma_status status)
|
||||
pcm_play_dma_status_callback_int_swvol(enum pcm_dma_status status)
|
||||
{
|
||||
if (status != PCM_DMAST_STARTED)
|
||||
return status;
|
||||
|
|
@ -327,7 +327,7 @@ static void start_pcm(bool reframe)
|
|||
pcm_get_current_sink()->ops.play(pcm_dbl_buf[1], pcm_dbl_buf_size[1]);
|
||||
}
|
||||
|
||||
void pcm_play_dma_start_int(const void *addr, size_t size)
|
||||
void pcm_play_dma_start_int_swvol(const void *addr, size_t size)
|
||||
{
|
||||
src_buf_addr = addr;
|
||||
/* divide by 2 for 32 bit, optimize away to 1 for 16 bit */
|
||||
|
|
@ -335,14 +335,14 @@ void pcm_play_dma_start_int(const void *addr, size_t size)
|
|||
start_pcm(true);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop_int(void)
|
||||
void pcm_play_dma_stop_int_swvol(void)
|
||||
{
|
||||
pcm_get_current_sink()->ops.stop();
|
||||
src_buf_addr = NULL;
|
||||
src_buf_rem = 0;
|
||||
}
|
||||
|
||||
#endif /* PCM_SW_VOLUME_UNBUFFERED */
|
||||
#endif /* WANT_SWVOL */
|
||||
|
||||
|
||||
/** Internal **/
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = audiohw_preinit,
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -517,6 +517,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -309,6 +309,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "audiohw.h"
|
||||
|
||||
extern JNIEnv *env_ptr;
|
||||
|
||||
|
|
@ -220,6 +221,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -364,6 +364,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "audiohw.h"
|
||||
|
||||
#include "sound/asound.h"
|
||||
#include "tinyalsa/asoundlib.h"
|
||||
|
|
@ -458,6 +459,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -775,6 +775,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -449,6 +449,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ struct pcm_sink builtin_pcm_sink = {
|
|||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
.volume_type = PCM_NATIVE_VOLUME_TYPE,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ struct pcm_sink iap_pcm_sink = {
|
|||
.samprs = samprs,
|
||||
.num_samprs = ARRAYLEN(samprs),
|
||||
.default_freq = 0,
|
||||
.volume_type = PCM_SINK_HWVOL,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_nop,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue