forked from len0rd/rockbox
The peak meter on iRiver didn't look right to me and the code seemed to be
making it a lot more complicated that it needed to be, so I threw in some new code. This should be easy to adjust for different CPU loads, and I set it up to use a little less than what was there. If this causes any trouble, please roll it back. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7238 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
c5ebc8e4e4
commit
27c83252e2
1 changed files with 58 additions and 77 deletions
|
|
@ -89,87 +89,68 @@ static void dma_stop(void)
|
||||||
pcm_paused = false;
|
pcm_paused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PEEK_SAMPLE_COUNT 64
|
/*
|
||||||
static long calculate_channel_peak_average(int channel, unsigned short *addr,
|
* This function goes directly into the DMA buffer to calculate the left and
|
||||||
long size)
|
* right peak values. To avoid missing peaks it tries to look forward a full
|
||||||
{
|
* refresh period (1/20 sec) although it's always possible that the entire
|
||||||
int i;
|
* period will not be visible. To reduce CPU load it only looks at every
|
||||||
long min, max;
|
* third sample, and this can be reduced even further if needed (even every
|
||||||
int count, min_count, max_count;
|
* tenth sample would still be pretty accurate).
|
||||||
unsigned long average, zero_point;
|
*/
|
||||||
|
|
||||||
addr = &addr[channel];
|
#define PEAK_SAMPLES 2205 /* 44100 sample rate / 20 Hz refresh */
|
||||||
average = 0;
|
#define PEAK_STRIDE 3 /* every 3rd sample is plenty... */
|
||||||
|
|
||||||
if (pcm_playing && !pcm_paused && addr != NULL && size)
|
|
||||||
{
|
|
||||||
/* Calculate the zero point and remove DC offset (should be around 32768) */
|
|
||||||
zero_point = 0;
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
zero_point += addr[i*2];
|
|
||||||
zero_point /= i;
|
|
||||||
|
|
||||||
/*for (i = 0; i < size; i++) {
|
|
||||||
long peak = addr[i*2] - 32768;
|
|
||||||
if (peak < 0)
|
|
||||||
peak = 0;
|
|
||||||
average += peak;
|
|
||||||
}
|
|
||||||
average /= i;*/
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
while (size > PEEK_SAMPLE_COUNT)
|
|
||||||
{
|
|
||||||
min = zero_point;
|
|
||||||
max = zero_point;
|
|
||||||
min_count = 1;
|
|
||||||
max_count = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < PEEK_SAMPLE_COUNT; i++)
|
|
||||||
{
|
|
||||||
unsigned long value = *addr;
|
|
||||||
if (value < zero_point) {
|
|
||||||
min += value;
|
|
||||||
min_count++;
|
|
||||||
}
|
|
||||||
if (value > zero_point) {
|
|
||||||
max += value;
|
|
||||||
max_count++;
|
|
||||||
}
|
|
||||||
addr = &addr[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
min /= min_count;
|
|
||||||
max /= max_count;
|
|
||||||
|
|
||||||
size -= PEEK_SAMPLE_COUNT;
|
|
||||||
average += (max - min) / 2;
|
|
||||||
//average += (max - zero_point) + (zero_point - min);
|
|
||||||
//average += zero_point - min;
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count)
|
|
||||||
{
|
|
||||||
average /= count;
|
|
||||||
/* I don't know why this is needed. Should be fixed. */
|
|
||||||
average = zero_point - average;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return average;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcm_calculate_peaks(int *left, int *right)
|
void pcm_calculate_peaks(int *left, int *right)
|
||||||
{
|
{
|
||||||
unsigned short *addr = (unsigned short *)SAR0;
|
long samples = (BCR0 & 0xffffff) / 4;
|
||||||
long size = MIN(512, (BCR0 & 0xffffff) / 2);
|
short *addr = (short *) (SAR0 & ~3);
|
||||||
|
|
||||||
if (left != NULL)
|
if (samples > PEAK_SAMPLES)
|
||||||
*left = calculate_channel_peak_average(0, addr, size);
|
samples = PEAK_SAMPLES;
|
||||||
if (right != NULL)
|
|
||||||
*right = calculate_channel_peak_average(1, addr, size);;
|
samples /= PEAK_STRIDE;
|
||||||
|
|
||||||
|
if (left && right) {
|
||||||
|
int left_peak = 0, right_peak = 0, value;
|
||||||
|
|
||||||
|
while (samples--) {
|
||||||
|
if ((value = addr [0]) > left_peak)
|
||||||
|
left_peak = value;
|
||||||
|
else if (-value > left_peak)
|
||||||
|
left_peak = -value;
|
||||||
|
|
||||||
|
if ((value = addr [PEAK_STRIDE | 1]) > right_peak)
|
||||||
|
right_peak = value;
|
||||||
|
else if (-value > right_peak)
|
||||||
|
right_peak = -value;
|
||||||
|
|
||||||
|
addr += PEAK_STRIDE * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
*left = left_peak;
|
||||||
|
*right = right_peak;
|
||||||
|
}
|
||||||
|
else if (left || right) {
|
||||||
|
int peak_value = 0, value;
|
||||||
|
|
||||||
|
if (right)
|
||||||
|
addr += (PEAK_STRIDE | 1);
|
||||||
|
|
||||||
|
while (samples--) {
|
||||||
|
if ((value = addr [0]) > peak_value)
|
||||||
|
peak_value = value;
|
||||||
|
else if (-value > peak_value)
|
||||||
|
peak_value = -value;
|
||||||
|
|
||||||
|
addr += PEAK_STRIDE * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left)
|
||||||
|
*left = peak_value;
|
||||||
|
else
|
||||||
|
*right = peak_value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sets frequency of input to DAC */
|
/* sets frequency of input to DAC */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue