forked from len0rd/rockbox
Clean up peak calculating code.
Mixer needn't keep peak data around that will never be used. Just pass pcm_peaks structure to it instead of allocating for every channel. Plugin API becomes incompatible. vu_meter digital mode was still using global peak calculation; switch it to playback channel like the rest. Remove some accumulated soil peaks inside pcm.c and make it more generic. Change-Id: Ib4d268d80b6a9d09915eea1c91eab483c1a2c009
This commit is contained in:
parent
c0208f0f64
commit
e189b33ff4
10 changed files with 81 additions and 78 deletions
|
@ -154,12 +154,12 @@ void* plugin_get_buffer(size_t *buffer_size);
|
||||||
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
||||||
|
|
||||||
/* increase this every time the api struct changes */
|
/* increase this every time the api struct changes */
|
||||||
#define PLUGIN_API_VERSION 219
|
#define PLUGIN_API_VERSION 220
|
||||||
|
|
||||||
/* update this to latest version if a change to the api struct breaks
|
/* update this to latest version if a change to the api struct breaks
|
||||||
backwards compatibility (and please take the opportunity to sort in any
|
backwards compatibility (and please take the opportunity to sort in any
|
||||||
new function which are "waiting" at the end of the function table) */
|
new function which are "waiting" at the end of the function table) */
|
||||||
#define PLUGIN_MIN_API_VERSION 219
|
#define PLUGIN_MIN_API_VERSION 220
|
||||||
|
|
||||||
/* plugin return codes */
|
/* plugin return codes */
|
||||||
/* internal returns start at 0x100 to make exit(1..255) work */
|
/* internal returns start at 0x100 to make exit(1..255) work */
|
||||||
|
@ -697,7 +697,7 @@ struct plugin_api {
|
||||||
const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel,
|
const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel,
|
||||||
int *count);
|
int *count);
|
||||||
void (*mixer_channel_calculate_peaks)(enum pcm_mixer_channel channel,
|
void (*mixer_channel_calculate_peaks)(enum pcm_mixer_channel channel,
|
||||||
int *left, int *right);
|
struct pcm_peaks *peaks);
|
||||||
void (*mixer_channel_play_data)(enum pcm_mixer_channel channel,
|
void (*mixer_channel_play_data)(enum pcm_mixer_channel channel,
|
||||||
pcm_play_callback_type get_more,
|
pcm_play_callback_type get_more,
|
||||||
const void *start, size_t size);
|
const void *start, size_t size);
|
||||||
|
|
|
@ -881,8 +881,10 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
left = rb->mas_codec_readreg(0xC);
|
left = rb->mas_codec_readreg(0xC);
|
||||||
right = rb->mas_codec_readreg(0xD);
|
right = rb->mas_codec_readreg(0xD);
|
||||||
#elif (CONFIG_CODEC == SWCODEC)
|
#elif (CONFIG_CODEC == SWCODEC)
|
||||||
|
static struct pcm_peaks peaks;
|
||||||
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
||||||
&left, &right);
|
&peaks);
|
||||||
|
left = peaks.left; right = peaks.right;
|
||||||
#endif
|
#endif
|
||||||
if (osc.orientation == OSC_HORIZ)
|
if (osc.orientation == OSC_HORIZ)
|
||||||
anim_horizontal(left, right);
|
anim_horizontal(left, right);
|
||||||
|
|
|
@ -228,9 +228,11 @@ static int plugin_main(void)
|
||||||
|
|
||||||
/* Get the peaks. ( Borrowed from vu_meter ) */
|
/* Get the peaks. ( Borrowed from vu_meter ) */
|
||||||
#if (CONFIG_CODEC == SWCODEC)
|
#if (CONFIG_CODEC == SWCODEC)
|
||||||
int left_peak, right_peak;
|
static struct pcm_peaks peaks;
|
||||||
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
||||||
&left_peak, &right_peak);
|
&peaks);
|
||||||
|
#define left_peak peaks.left
|
||||||
|
#define right_peak peaks.right
|
||||||
#else
|
#else
|
||||||
int left_peak = rb->mas_codec_readreg(0xC);
|
int left_peak = rb->mas_codec_readreg(0xC);
|
||||||
int right_peak = rb->mas_codec_readreg(0xD);
|
int right_peak = rb->mas_codec_readreg(0xD);
|
||||||
|
|
|
@ -704,9 +704,11 @@ static void analog_meter(void) {
|
||||||
int left_peak = rb->mas_codec_readreg(0xC);
|
int left_peak = rb->mas_codec_readreg(0xC);
|
||||||
int right_peak = rb->mas_codec_readreg(0xD);
|
int right_peak = rb->mas_codec_readreg(0xD);
|
||||||
#elif (CONFIG_CODEC == SWCODEC)
|
#elif (CONFIG_CODEC == SWCODEC)
|
||||||
int left_peak, right_peak;
|
static struct pcm_peaks peaks;
|
||||||
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
||||||
&left_peak, &right_peak);
|
&peaks);
|
||||||
|
#define left_peak peaks.left
|
||||||
|
#define right_peak peaks.right
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(vumeter_settings.analog_use_db_scale) {
|
if(vumeter_settings.analog_use_db_scale) {
|
||||||
|
@ -762,8 +764,11 @@ static void digital_meter(void) {
|
||||||
int left_peak = rb->mas_codec_readreg(0xC);
|
int left_peak = rb->mas_codec_readreg(0xC);
|
||||||
int right_peak = rb->mas_codec_readreg(0xD);
|
int right_peak = rb->mas_codec_readreg(0xD);
|
||||||
#elif (CONFIG_CODEC == SWCODEC)
|
#elif (CONFIG_CODEC == SWCODEC)
|
||||||
int left_peak, right_peak;
|
static struct pcm_peaks peaks;
|
||||||
rb->pcm_calculate_peaks(&left_peak, &right_peak);
|
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
||||||
|
&peaks);
|
||||||
|
#define left_peak peaks.left
|
||||||
|
#define right_peak peaks.right
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(vumeter_settings.digital_use_db_scale) {
|
if(vumeter_settings.digital_use_db_scale) {
|
||||||
|
|
|
@ -619,8 +619,13 @@ void peak_meter_peek(void)
|
||||||
/* read current values */
|
/* read current values */
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#if CONFIG_CODEC == SWCODEC
|
||||||
if (pm_playback)
|
if (pm_playback)
|
||||||
|
{
|
||||||
|
static struct pcm_peaks chan_peaks; /* *MUST* be static */
|
||||||
mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
|
||||||
&pm_cur_left, &pm_cur_right);
|
&chan_peaks);
|
||||||
|
pm_cur_left = chan_peaks.left;
|
||||||
|
pm_cur_right = chan_peaks.right;
|
||||||
|
}
|
||||||
#ifdef HAVE_RECORDING
|
#ifdef HAVE_RECORDING
|
||||||
else
|
else
|
||||||
pcm_calculate_rec_peaks(&pm_cur_left, &pm_cur_right);
|
pcm_calculate_rec_peaks(&pm_cur_left, &pm_cur_right);
|
||||||
|
|
|
@ -29,13 +29,6 @@
|
||||||
({ (start) = (void *)(((uintptr_t)(start) + 3) & ~3); \
|
({ (start) = (void *)(((uintptr_t)(start) + 3) & ~3); \
|
||||||
(size) &= ~3; })
|
(size) &= ~3; })
|
||||||
|
|
||||||
struct pcm_peaks
|
|
||||||
{
|
|
||||||
long period;
|
|
||||||
long tick;
|
|
||||||
uint16_t val[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
||||||
const void *addr, int count);
|
const void *addr, int count);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#ifndef PCM_PLAYBACK_H
|
#ifndef PCM_PLAYBACK_H
|
||||||
#define PCM_PLAYBACK_H
|
#define PCM_PLAYBACK_H
|
||||||
|
|
||||||
#include <string.h> /* size_t */
|
#include <sys/types.h> /* size_t, uint32_t */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
enum pcm_dma_status
|
enum pcm_dma_status
|
||||||
|
@ -71,6 +71,16 @@ void pcm_play_data(pcm_play_callback_type get_more,
|
||||||
pcm_status_callback_type status_cb,
|
pcm_status_callback_type status_cb,
|
||||||
const void *start, size_t size);
|
const void *start, size_t size);
|
||||||
|
|
||||||
|
/* Kept internally for global PCM and used by mixer's verion of peak
|
||||||
|
calculation */
|
||||||
|
struct pcm_peaks
|
||||||
|
{
|
||||||
|
uint32_t left; /* Left peak value */
|
||||||
|
uint32_t right; /* Right peak value */
|
||||||
|
long period; /* For tracking calling period */
|
||||||
|
long tick; /* Last tick called */
|
||||||
|
};
|
||||||
|
|
||||||
void pcm_calculate_peaks(int *left, int *right);
|
void pcm_calculate_peaks(int *left, int *right);
|
||||||
const void* pcm_get_peak_buffer(int* count);
|
const void* pcm_get_peak_buffer(int* count);
|
||||||
size_t pcm_get_bytes_waiting(void);
|
size_t pcm_get_bytes_waiting(void);
|
||||||
|
|
|
@ -111,7 +111,7 @@ const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count
|
||||||
|
|
||||||
/* Calculate peak values for channel */
|
/* Calculate peak values for channel */
|
||||||
void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
|
void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
|
||||||
int *left, int *right);
|
struct pcm_peaks *peaks);
|
||||||
|
|
||||||
/* Adjust channel pointer by a given offset to support movable buffers */
|
/* Adjust channel pointer by a given offset to support movable buffers */
|
||||||
void mixer_adjust_channel_address(enum pcm_mixer_channel channel,
|
void mixer_adjust_channel_address(enum pcm_mixer_channel channel,
|
||||||
|
|
|
@ -102,9 +102,6 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
|
||||||
/* samplerate frequency selection index */
|
/* samplerate frequency selection index */
|
||||||
int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
|
int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
|
||||||
|
|
||||||
/* peak data for the global peak values - i.e. what the final output is */
|
|
||||||
static struct pcm_peaks global_peaks;
|
|
||||||
|
|
||||||
/* Called internally by functions to reset the state */
|
/* Called internally by functions to reset the state */
|
||||||
static void pcm_play_stopped(void)
|
static void pcm_play_stopped(void)
|
||||||
{
|
{
|
||||||
|
@ -125,42 +122,38 @@ static void pcm_wait_for_init(void)
|
||||||
*
|
*
|
||||||
* Used for recording and playback.
|
* Used for recording and playback.
|
||||||
*/
|
*/
|
||||||
static void pcm_peak_peeker(const int32_t *addr, int count, uint16_t peaks[2])
|
static void pcm_peak_peeker(const int16_t *p, int count,
|
||||||
|
struct pcm_peaks *peaks)
|
||||||
{
|
{
|
||||||
int peak_l = 0, peak_r = 0;
|
uint32_t peak_l = 0, peak_r = 0;
|
||||||
const int32_t * const end = addr + count;
|
const int16_t *pend = p + 2 * count;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int32_t value = *addr;
|
int32_t s;
|
||||||
int ch;
|
|
||||||
|
|
||||||
#ifdef ROCKBOX_BIG_ENDIAN
|
s = p[0];
|
||||||
ch = value >> 16;
|
|
||||||
#else
|
|
||||||
ch = (int16_t)value;
|
|
||||||
#endif
|
|
||||||
if (ch < 0)
|
|
||||||
ch = -ch;
|
|
||||||
if (ch > peak_l)
|
|
||||||
peak_l = ch;
|
|
||||||
|
|
||||||
#ifdef ROCKBOX_BIG_ENDIAN
|
if (s < 0)
|
||||||
ch = (int16_t)value;
|
s = -s;
|
||||||
#else
|
|
||||||
ch = value >> 16;
|
|
||||||
#endif
|
|
||||||
if (ch < 0)
|
|
||||||
ch = -ch;
|
|
||||||
if (ch > peak_r)
|
|
||||||
peak_r = ch;
|
|
||||||
|
|
||||||
addr += 4;
|
if ((uint32_t)s > peak_l)
|
||||||
|
peak_l = s;
|
||||||
|
|
||||||
|
s = p[1];
|
||||||
|
|
||||||
|
if (s < 0)
|
||||||
|
s = -s;
|
||||||
|
|
||||||
|
if ((uint32_t)s > peak_r)
|
||||||
|
peak_r = s;
|
||||||
|
|
||||||
|
p += 4 * 2; /* Every 4th sample, interleaved */
|
||||||
}
|
}
|
||||||
while (addr < end);
|
while (p < pend);
|
||||||
|
|
||||||
peaks[0] = peak_l;
|
peaks->left = peak_l;
|
||||||
peaks[1] = peak_r;
|
peaks->right = peak_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
||||||
|
@ -177,7 +170,7 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
||||||
else if (period > HZ/5)
|
else if (period > HZ/5)
|
||||||
period = HZ/5;
|
period = HZ/5;
|
||||||
|
|
||||||
peaks->period = (3*peaks->period + period) >> 2;
|
peaks->period = (3*peaks->period + period) / 4;
|
||||||
peaks->tick = tick;
|
peaks->tick = tick;
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
|
@ -186,29 +179,32 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
||||||
count = MIN(framecount, count);
|
count = MIN(framecount, count);
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
pcm_peak_peeker((int32_t *)addr, count, peaks->val);
|
pcm_peak_peeker(addr, count, peaks);
|
||||||
/* else keep previous peak values */
|
/* else keep previous peak values */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* peaks are zero */
|
/* peaks are zero */
|
||||||
peaks->val[0] = peaks->val[1] = 0;
|
peaks->left = peaks->right = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcm_calculate_peaks(int *left, int *right)
|
void pcm_calculate_peaks(int *left, int *right)
|
||||||
{
|
{
|
||||||
|
/* peak data for the global peak values - i.e. what the final output is */
|
||||||
|
static struct pcm_peaks peaks;
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
const void *addr = pcm_play_dma_get_peak_buffer(&count);
|
const void *addr = pcm_play_dma_get_peak_buffer(&count);
|
||||||
|
|
||||||
pcm_do_peak_calculation(&global_peaks, pcm_playing && !pcm_paused,
|
pcm_do_peak_calculation(&peaks, pcm_playing && !pcm_paused,
|
||||||
addr, count);
|
addr, count);
|
||||||
|
|
||||||
if (left)
|
if (left)
|
||||||
*left = global_peaks.val[0];
|
*left = peaks.left;
|
||||||
|
|
||||||
if (right)
|
if (right)
|
||||||
*right = global_peaks.val[1];
|
*right = peaks.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
const void* pcm_get_peak_buffer(int * count)
|
const void* pcm_get_peak_buffer(int * count)
|
||||||
|
@ -471,20 +467,20 @@ static void pcm_recording_stopped(void)
|
||||||
*/
|
*/
|
||||||
void pcm_calculate_rec_peaks(int *left, int *right)
|
void pcm_calculate_rec_peaks(int *left, int *right)
|
||||||
{
|
{
|
||||||
static uint16_t peaks[2];
|
static struct pcm_peaks peaks;
|
||||||
|
|
||||||
if (pcm_recording)
|
if (pcm_recording)
|
||||||
{
|
{
|
||||||
const void *peak_addr = pcm_rec_peak_addr;
|
const int16_t *peak_addr = pcm_rec_peak_addr;
|
||||||
const void *addr = pcm_rec_dma_get_peak_buffer();
|
const int16_t *addr = pcm_rec_dma_get_peak_buffer();
|
||||||
|
|
||||||
if (addr != NULL)
|
if (addr != NULL)
|
||||||
{
|
{
|
||||||
int count = (int)(((intptr_t)addr - (intptr_t)peak_addr) >> 2);
|
int count = (addr - peak_addr) / 2; /* Interleaved L+R */
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
pcm_peak_peeker((int32_t *)peak_addr, count, peaks);
|
pcm_peak_peeker(peak_addr, count, &peaks);
|
||||||
|
|
||||||
if (peak_addr == pcm_rec_peak_addr)
|
if (peak_addr == pcm_rec_peak_addr)
|
||||||
pcm_rec_peak_addr = addr;
|
pcm_rec_peak_addr = addr;
|
||||||
|
@ -494,15 +490,15 @@ void pcm_calculate_rec_peaks(int *left, int *right)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
peaks[0] = peaks[1] = 0;
|
peaks.left = peaks.right = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left)
|
if (left)
|
||||||
*left = peaks[0];
|
*left = peaks.left;
|
||||||
|
|
||||||
if (right)
|
if (right)
|
||||||
*right = peaks[1];
|
*right = peaks.right;
|
||||||
} /* pcm_calculate_rec_peaks */
|
}
|
||||||
|
|
||||||
bool pcm_is_recording(void)
|
bool pcm_is_recording(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,9 +60,6 @@ static size_t next_size = 0; /* Size of buffer to play next time */
|
||||||
/* Descriptors for all available channels */
|
/* Descriptors for all available channels */
|
||||||
static struct mixer_channel channels[PCM_MIXER_NUM_CHANNELS] IBSS_ATTR;
|
static struct mixer_channel channels[PCM_MIXER_NUM_CHANNELS] IBSS_ATTR;
|
||||||
|
|
||||||
/* History for channel peaks */
|
|
||||||
static struct pcm_peaks channel_peaks[PCM_MIXER_NUM_CHANNELS];
|
|
||||||
|
|
||||||
/* Packed pointer array of all playing (active) channels in "channels" array */
|
/* Packed pointer array of all playing (active) channels in "channels" array */
|
||||||
static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR;
|
static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR;
|
||||||
|
|
||||||
|
@ -389,21 +386,14 @@ const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count
|
||||||
|
|
||||||
/* Calculate peak values for channel */
|
/* Calculate peak values for channel */
|
||||||
void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
|
void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
|
||||||
int *left, int *right)
|
struct pcm_peaks *peaks)
|
||||||
{
|
{
|
||||||
struct mixer_channel *chan = &channels[channel];
|
|
||||||
struct pcm_peaks *peaks = &channel_peaks[channel];
|
|
||||||
int count;
|
int count;
|
||||||
const void *addr = mixer_channel_get_buffer(channel, &count);
|
const void *addr = mixer_channel_get_buffer(channel, &count);
|
||||||
|
|
||||||
pcm_do_peak_calculation(peaks, chan->status == CHANNEL_PLAYING,
|
pcm_do_peak_calculation(peaks,
|
||||||
|
channels[channel].status == CHANNEL_PLAYING,
|
||||||
addr, count);
|
addr, count);
|
||||||
|
|
||||||
if (left)
|
|
||||||
*left = peaks->val[0];
|
|
||||||
|
|
||||||
if (right)
|
|
||||||
*right = peaks->val[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust channel pointer by a given offset to support movable buffers */
|
/* Adjust channel pointer by a given offset to support movable buffers */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue