1
0
Fork 0
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:
Michael Sevakis 2012-05-02 20:53:07 -04:00
parent c0208f0f64
commit e189b33ff4
10 changed files with 81 additions and 78 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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)
{ {

View file

@ -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 */