From: James Courtier-Dutton <James@superbug.demon.co.uk>
To: ALSA development <alsa-devel@alsa-project.org>
Subject: Re: [PATCH] pcm_rate.c fixes.
Date: Sun, 08 Aug 2004 16:59:42 +0100 [thread overview]
Message-ID: <41164DEE.703@superbug.demon.co.uk> (raw)
In-Reply-To: <41164197.4050001@superbug.demon.co.uk>
[-- Attachment #1: Type: text/plain, Size: 785 bytes --]
Updated patch to remove un-needed SNDERR messages.
See attached.
James Courtier-Dutton wrote:
> This should be the final patch required to pcm_rate.c. The patch is
> against the current alsa-lib CVS.
>
> This patch fixes a number of different bugs in pcm_rate.c.
> 1) Resampling now works for rate 192000 -> 8000.
> 2) zero samples are not accidentally inserted into the stream any more.
> 3) Corrects period size calculations.
> 4) Prevents avail_min and xfer_align being less than 1.
>
> This should improve the sound quality. Further improvements can be made
> by implementing polyphase filters, thereby removing aliases generally
> caused by any resampling algorithm that does not include a low pass
> filter before changing the number of samples.
>
> Cheers
>
> James
>
[-- Attachment #2: alsa-lib-pcm_rate.c-diff2.txt --]
[-- Type: text/plain, Size: 8594 bytes --]
Index: alsa-lib/src/pcm/pcm_rate.c
===================================================================
RCS file: /cvsroot/alsa/alsa-lib/src/pcm/pcm_rate.c,v
retrieving revision 1.84
diff -u -r1.84 pcm_rate.c
--- alsa-lib/src/pcm/pcm_rate.c 26 Apr 2004 07:40:13 -0000 1.84
+++ alsa-lib/src/pcm/pcm_rate.c 8 Aug 2004 15:57:43 -0000
@@ -27,8 +27,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-
-#include <limits.h>
+#include <inttypes.h>
#include <byteswap.h>
#include "pcm_local.h"
#include "pcm_plugin.h"
@@ -45,7 +44,8 @@
#ifndef DOC_HIDDEN
-#define LINEAR_DIV (1<<16)
+/* LINEAR_DIV needs to be large enough to handle resampling from 192000 -> 8000 */
+#define LINEAR_DIV (1<<19)
enum rate_type {
RATE_TYPE_LINEAR, /* linear interpolation */
@@ -58,7 +58,7 @@
struct {
int init;
int16_t old_sample, new_sample;
- int sum;
+ int64_t sum;
} linear;
} u;
} snd_pcm_rate_state_t;
@@ -168,6 +168,9 @@
assert(src_frames1 <= src_frames);
}
}
+ if (dst_frames != dst_frames1) {
+ SNDERR("dst_frames %lu, dst_frames1 %lu, src_frames %lu, src_frames1 %lu\n", dst_frames, dst_frames1, src_frames, src_frames1);
+ }
states->u.linear.old_sample = old_sample;
states->u.linear.new_sample = new_sample;
states++;
@@ -194,17 +197,18 @@
snd_pcm_uframes_t src_frames1 = 0;
snd_pcm_uframes_t dst_frames1 = 0;
int16_t sample = 0;
+ unsigned int pos = 0;
for (channel = 0; channel < channels; ++channel) {
const snd_pcm_channel_area_t *src_area = &src_areas[channel];
const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
- unsigned int pos;
- int sum;
+ int64_t sum;
const char *src;
char *dst;
int src_step, dst_step;
sum = states->u.linear.sum;
- pos = 0;
+ //int16_t old_sample = states->u.linear.old_sample;
+ pos = LINEAR_DIV/2; /* Start at 0.5 */
states->u.linear.init = 0;
src = snd_pcm_channel_area_addr(src_area, src_offset);
dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
@@ -223,26 +227,25 @@
src_frames1++;
pos += get_increment;
if (pos >= LINEAR_DIV) {
- int s = sample;
pos -= LINEAR_DIV;
- sum += s * (get_increment - pos);
- sum /= LINEAR_DIV;
- sample = sum;
goto *put;
#define PUT16_END after_put
#include "plugin_ops.h"
#undef PUT16_END
after_put:
dst += dst_step;
- sum = s * pos;
dst_frames1++;
assert(dst_frames1 <= dst_frames);
- } else
- sum += sample * get_increment;
+ }
}
+
states->u.linear.sum = sum;
+ states->u.linear.old_sample = sample;
states++;
}
+ if (dst_frames != dst_frames1) {
+ SNDERR("dst %lu, dst1 %lu, src %lu, src1 %lu pos = %u\n", dst_frames, dst_frames1, src_frames, src_frames1, pos );
+ }
}
#endif /* DOC_HIDDEN */
@@ -254,9 +257,9 @@
return 0;
/* Round toward zero */
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
- return muldiv_down(frames, LINEAR_DIV, rate->pitch);
+ return muldiv_near(frames, LINEAR_DIV, rate->pitch);
else
- return muldiv_down(frames, rate->pitch, LINEAR_DIV);
+ return muldiv_near(frames, rate->pitch, LINEAR_DIV);
}
static snd_pcm_sframes_t snd_pcm_rate_slave_frames(snd_pcm_t *pcm, snd_pcm_sframes_t frames)
@@ -264,9 +267,9 @@
snd_pcm_rate_t *rate = pcm->private_data;
/* Round toward zero */
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
- return muldiv_down(frames, rate->pitch, LINEAR_DIV);
+ return muldiv_near(frames, rate->pitch, LINEAR_DIV);
else
- return muldiv_down(frames, LINEAR_DIV, rate->pitch);
+ return muldiv_near(frames, LINEAR_DIV, rate->pitch);
}
static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
@@ -488,7 +491,7 @@
rate->func = snd_pcm_rate_shrink;
/* pitch is get_increment */
}
- rate->pitch = (((u_int64_t)dst_rate * LINEAR_DIV) + src_rate - 1) / src_rate;
+ rate->pitch = (((u_int64_t)dst_rate * LINEAR_DIV) + (src_rate / 2)) / src_rate;
assert(!rate->states);
assert(!rate->pareas);
rate->states = malloc(channels * sizeof(*rate->states));
@@ -581,56 +584,60 @@
params->boundary = boundary1;
sparams->boundary = boundary2;
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
- rate->pitch = (((u_int64_t)slave->period_size * LINEAR_DIV) + pcm->period_size - 1) / pcm->period_size;
+ rate->pitch = (((u_int64_t)slave->period_size * LINEAR_DIV) + (pcm->period_size/2) ) / pcm->period_size;
do {
- snd_pcm_uframes_t cframes;
+ snd_pcm_uframes_t cframes,cframes_test;
- cframes = snd_pcm_rate_client_frames(pcm, slave->period_size - 1);
- if (cframes == pcm->period_size - 1)
+ cframes = snd_pcm_rate_client_frames(pcm, slave->period_size );
+ if (cframes == pcm->period_size )
break;
- if (cframes > pcm->period_size - 1) {
+ if (cframes > pcm->period_size ) {
rate->pitch++;
- if ((snd_pcm_uframes_t)snd_pcm_rate_client_frames(pcm, slave->period_size - 1) < pcm->period_size - 1) {
- SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size - 1, pcm->period_size - 1);
+ cframes_test = snd_pcm_rate_client_frames(pcm, slave->period_size );
+ if (cframes_test < pcm->period_size ) {
+ SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size, pcm->period_size);
return -EIO;
}
} else {
rate->pitch--;
- if ((snd_pcm_uframes_t)snd_pcm_rate_client_frames(pcm, slave->period_size - 1) > pcm->period_size - 1) {
- SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size - 1, pcm->period_size - 1);
+ cframes_test = snd_pcm_rate_client_frames(pcm, slave->period_size );
+ if (cframes_test > pcm->period_size) {
+ SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size, pcm->period_size);
return -EIO;
}
}
} while (1);
- assert((snd_pcm_uframes_t)snd_pcm_rate_client_frames(pcm, slave->period_size - 1) == pcm->period_size - 1);
+ assert((snd_pcm_uframes_t)snd_pcm_rate_client_frames(pcm, slave->period_size ) == pcm->period_size );
} else {
- rate->pitch = (((u_int64_t)pcm->period_size * LINEAR_DIV) + slave->period_size - 1) / slave->period_size;
+ rate->pitch = (((u_int64_t)pcm->period_size * LINEAR_DIV) + (slave->period_size/2) ) / slave->period_size;
do {
snd_pcm_uframes_t cframes;
- cframes = snd_pcm_rate_slave_frames(pcm, pcm->period_size - 1);
- if (cframes == slave->period_size - 1)
+ cframes = snd_pcm_rate_slave_frames(pcm, pcm->period_size );
+ if (cframes == slave->period_size )
break;
- if (cframes > slave->period_size - 1) {
+ if (cframes > slave->period_size ) {
rate->pitch++;
- if ((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size - 1) < slave->period_size - 1) {
- SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size - 1, pcm->period_size - 1);
+ if ((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size ) < slave->period_size ) {
+ SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size, pcm->period_size);
return -EIO;
}
} else {
rate->pitch--;
- if ((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size - 1) > slave->period_size - 1) {
- SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size - 1, pcm->period_size - 1);
+ if ((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size) > slave->period_size ) {
+ SNDERR("Unable to satisfy pitch condition (%i/%i - %li/%li)\n", slave->rate, pcm->rate, slave->period_size , pcm->period_size );
return -EIO;
}
}
} while (1);
- assert((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size - 1) == slave->period_size - 1);
+ assert((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size ) == slave->period_size );
}
recalc(pcm, &sparams->avail_min);
rate->orig_avail_min = sparams->avail_min;
recalc(pcm, &sparams->xfer_align);
recalc(pcm, &sparams->start_threshold);
+ if (sparams->avail_min < 1) sparams->avail_min = 1;
+ if (sparams->xfer_align < 1) sparams->xfer_align = 1;
if (sparams->start_threshold <= slave->buffer_size) {
if (sparams->start_threshold > (slave->buffer_size / sparams->avail_min) * sparams->avail_min)
sparams->start_threshold = (slave->buffer_size / sparams->avail_min) * sparams->avail_min;
prev parent reply other threads:[~2004-08-08 15:59 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-08-08 15:07 [PATCH] pcm_rate.c fixes James Courtier-Dutton
2004-08-08 15:59 ` James Courtier-Dutton [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=41164DEE.703@superbug.demon.co.uk \
--to=james@superbug.demon.co.uk \
--cc=alsa-devel@alsa-project.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox