Proposed patch for bug #766 (Bad audio quality (possibly in resampling) in Linux)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Great insight, thanks! Just tested it on an affected system and it
works! The patch has just been checked in to SVN trunk changeset 3085.

Honestly, this ticket was a headache. So thanks again!

BR,
nanang


On Sat, Jan 30, 2010 at 5:16 AM, Bram Kuijvenhoven
<mailinglists.bram at kuijvenhoven.net> wrote:
> Hi,
>
> Attached is a proposed patch for bug #766 (Bad audio quality (possibly in
> resampling) in Linux).
>
> The cause is indeed in the resampling code
> (third_party/resample/src/resamplesubs.c):
>
> ? Yend = Ystart + (unsigned)(nx * pFactor);
>
> where pFactor is a double holding the result of 1.0 * rate_out / rate_in,
> and nx is the size of a source frame (in samples).
>
> Since pFactor holds only a binary floating-point approximation to the sample
> rate conversion factor (e.g. 1/6) and since the C-style cast (unsigned)
> performs truncation instead of rounding, the result is that sometimes Yend -
> Ystart is one sample less than intended, causing the last sample of the
> output frame to contain garbage (often a zero). Always be careful with
> floating-point calculations, especially in combination with looping
> constructs!
>
> The attached patch fixes it by turning the above into proper rounding:
>
> ? Yend = Ystart + (unsigned)(nx * pFactor + 0.5);
>
> Though the bug does not appear with my compiler (GCC 4.3.2 on Linux) when
> doing
>
> ? Yend = Ystart + (unsigned)(nx * 1.0 * dest_rate / source_rate);
>
> this may still cause problems on other platforms since the correct outcome
> probably only results from the extra precision available in floating point
> registers (80-bit) compared to doubles (64-bit). Therefore, the patch also
> makes similar adjustments to code in conference.c and resample_resample.c.
>
> Regards,
>
> Bram
>
> Index: pjmedia/src/pjmedia/resample_resample.c
> ===================================================================
> --- pjmedia/src/pjmedia/resample_resample.c ? ? (revision 3083)
> +++ pjmedia/src/pjmedia/resample_resample.c ? ? (working copy)
> @@ -123,7 +123,7 @@
>
> ? ? ? ?/* Allocate temporary output buffer */
> ? ? ? ?size = (unsigned) (resample->frame_size * sizeof(pj_int16_t) *
> - ? ? ? ? ? ? ? ? ? ? ? ? ?resample->factor / channel_count);
> + ? ? ? ? ? ? ? ? ? ? ? ? ?resample->factor / channel_count + 0.5);
> ? ? ? ?resample->tmp_buffer = (pj_int16_t*) pj_pool_alloc(pool, size);
> ? ? ? ?PJ_ASSERT_RETURN(resample->tmp_buffer, PJ_ENOMEM);
> ? ? }
> @@ -245,7 +245,7 @@
> ? ? ? ? ? ?unsigned mono_frm_sz_out;
>
> ? ? ? ? ? ?mono_frm_sz_in ?= resample->frame_size / resample->channel_cnt;
> - ? ? ? ? ? mono_frm_sz_out = (unsigned)(mono_frm_sz_in * resample->factor);
> + ? ? ? ? ? mono_frm_sz_out = (unsigned)(mono_frm_sz_in * resample->factor +
> 0.5);
>
> ? ? ? ? ? ?/* Deinterleave input */
> ? ? ? ? ? ?dst_buf = resample->in_buffer[i] + resample->xoff*2;
> Index: pjmedia/src/pjmedia/conference.c
> ===================================================================
> --- pjmedia/src/pjmedia/conference.c ? ?(revision 3083)
> +++ pjmedia/src/pjmedia/conference.c ? ?(working copy)
> @@ -372,7 +372,7 @@
> ? ? ? ?//conf_port->rx_buf_cap = (unsigned)(conf_port->samples_per_frame +
> ? ? ? ?// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? conf->samples_per_frame *
> ? ? ? ?// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? conf_port->clock_rate * 1.0 /
> - ? ? ? // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? conf->clock_rate);
> + ? ? ? // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? conf->clock_rate + 0.5);
> ? ? ? ?conf_port->rx_buf_cap = conf_port->clock_rate * buff_ptime / 1000;
> ? ? ? ?if (conf_port->channel_count > conf->channel_count)
> ? ? ? ? ? ?conf_port->rx_buf_cap *= conf_port->channel_count;
> @@ -1437,7 +1437,7 @@
> ? ? ? ? */
>
> ? ? ? ?samples_req = (unsigned) (count * 1.0 *
> - ? ? ? ? ? ? ? ? ? ? cport->clock_rate / conf->clock_rate);
> + ? ? ? ? ? ? ? ? ? ? cport->clock_rate / conf->clock_rate + 0.5);
>
> ? ? ? ?while (cport->rx_buf_count < samples_req) {
>
> @@ -1509,7 +1509,7 @@
> ? ? ? ? ? ?pjmedia_resample_run( cport->rx_resample,cport->rx_buf, frame);
>
> ? ? ? ? ? ?src_count = (unsigned)(count * 1.0 * cport->clock_rate /
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?conf->clock_rate);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?conf->clock_rate + 0.5);
> ? ? ? ? ? ?cport->rx_buf_count -= src_count;
> ? ? ? ? ? ?if (cport->rx_buf_count) {
> ? ? ? ? ? ? ? ?pjmedia_move_samples(cport->rx_buf, cport->rx_buf+src_count,
> @@ -1693,7 +1693,7 @@
> ? ? ? ?pjmedia_resample_run( cport->tx_resample, buf,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cport->tx_buf + cport->tx_buf_count );
> ? ? ? ?dst_count = (unsigned)(conf->samples_per_frame * 1.0 *
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cport->clock_rate / conf->clock_rate);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cport->clock_rate / conf->clock_rate + 0.5);
> ? ? } else {
> ? ? ? ?/* Same clock rate.
> ? ? ? ? * Just copy the samples to tx_buffer.
> Index: third_party/resample/src/resamplesubs.c
> ===================================================================
> --- third_party/resample/src/resamplesubs.c ? ? (revision 3083)
> +++ third_party/resample/src/resamplesubs.c ? ? (working copy)
> @@ -118,9 +118,13 @@
> ? ? dtb = dt*(1<<Np) + 0.5; ? ? /* Fixed-point representation */
>
> ? ? Ystart = Y;
> - ? ?Yend = Ystart + (unsigned)(nx * pFactor);
> + ? ?Yend = Ystart + (unsigned)(nx * pFactor + 0.5);
> ? ? endTime = time + (1<<Np)*(RES_WORD)nx;
> - ? ?while (time < endTime)
> +
> + ? ?// Integer round down in dtb calculation may cause (endTime % dtb > 0),
> + ? ?// so it may cause resample write pass the output buffer (Y >= Yend).
> + ? ?// while (time < endTime)
> + ? ?while (Y < Yend)
> ? ? {
> ? ? ? ?iconst = (time) & Pmask;
> ? ? ? ?xp = &X[(time)>>Np]; ? ? ?/* Ptr to current input sample */
> @@ -257,7 +261,7 @@
> ? ? dtb = dt*(1<<Np) + 0.5; ? ? /* Fixed-point representation */
>
> ? ? Ystart = Y;
> - ? ?Yend = Ystart + (unsigned)(nx * pFactor);
> + ? ?Yend = Ystart + (unsigned)(nx * pFactor + 0.5);
> ? ? endTime = time + (1<<Np)*(RES_WORD)nx;
>
> ? ? // Integer round down in dtb calculation may cause (endTime % dtb > 0),
> @@ -305,7 +309,7 @@
> ? ? dhb = dh*(1<<Na) + 0.5; ? ? /* Fixed-point representation */
>
> ? ? Ystart = Y;
> - ? ?Yend = Ystart + (unsigned)(nx * pFactor);
> + ? ?Yend = Ystart + (unsigned)(nx * pFactor + 0.5);
> ? ? endTime = time + (1<<Np)*(RES_WORD)nx;
>
> ? ? // Integer round down in dtb calculation may cause (endTime % dtb > 0),
>
> _______________________________________________
> Visit our blog: http://blog.pjsip.org
>
> pjsip mailing list
> pjsip at lists.pjsip.org
> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
>
>



[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux