Bug#549899: libvorbis0a: Incorrect encoding on powerpc (probably also mips(el), ia64 and hppa)

Erik de Castro Lopo erikd at mega-nerd.com
Tue Oct 6 07:25:44 UTC 2009


Package: libvorbis0a
Version: 1.2.0.dfsg-6
Severity: normal

The attached test program passes on i386 and amd64 but fails on powerpc. This test
program also passes with version 1.2.3 of libvorbis0a currently in unstable.

This problem was originally uncovered by the libsndfile test suite. See:

    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=518037#89

CHeers,
Erik

-- System Information:
Debian Release: squeeze/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: powerpc (ppc)

Kernel: Linux 2.6.30-1-powerpc
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=ANSI_X3.4-1968) (ignored: LC_ALL set to POSIX)
Shell: /bin/sh linked to /bin/dash

Versions of packages libvorbis0a depends on:
ii  libc6                       2.9-25       GNU C Library: Shared libraries
ii  libogg0                     1.1.4~dfsg-1 Ogg bitstream library

libvorbis0a recommends no packages.

libvorbis0a suggests no packages.

-- no debconf information
-------------- next part --------------
/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

 function: utility functions for vorbis codec test suite.
 last mod: $Id: util.c 13293 2007-07-24 00:09:47Z erikd $

 ********************************************************************/

/*
Compile with:

gcc -Wall -Werror vorbis-test.c -lvorbisenc -o vorbis-test

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <errno.h>

#include <vorbis/codec.h>
#include <vorbis/vorbisenc.h>

#define DATA_LEN  2048
#define ARRAY_LEN(x)    (sizeof(x)/sizeof(x[0]))
#define MAX(a,b)        ((a) > (b) ? (a) : (b))

void
gen_windowed_sine (float *data, int len, float maximum)
{    int k ;

    memset (data, 0, len * sizeof (float)) ;

    len /= 2 ;

    for (k = 0 ; k < len ; k++)
    {    data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;

        /* Apply Hanning Window. */
        data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
        }

    return ;
}

void
set_data_in (float * data, unsigned len, float value)
{        unsigned k ;

        for (k = 0 ; k < len ; k++)
                data [k] = value ;
}

/* The following function is basically a hacked version of the code in
 * examples/encoder_example.c */
void
write_vorbis_data_or_die (const char *filename, int srate, const float * data, int count)
{
  FILE * file ;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;
  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  int eos = 0, ret;

  if ((file = fopen (filename, "wb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  /********** Encode setup ************/

  vorbis_info_init (&vi);

  ret = vorbis_encode_init_vbr (&vi,1,srate,0.8);
  if (ret) {
    printf ("vorbis_encode_init_vbr return %d\n", ret) ;
    exit (1) ;
  }

  vorbis_comment_init (&vc);
  vorbis_comment_add_tag (&vc,"ENCODER","test/util.c");
  vorbis_analysis_init (&vd,&vi);
  vorbis_block_init (&vd,&vb);

  ogg_stream_init (&os,12345678);

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout (&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin (&os,&header);
    ogg_stream_packetin (&os,&header_comm);
    ogg_stream_packetin (&os,&header_code);

    /* Ensures the audio data will start on a new page. */
    while (!eos){
        int result = ogg_stream_flush (&os,&og);
        if (result == 0)
            break;
        fwrite (og.header,1,og.header_len,file);
        fwrite (og.body,1,og.body_len,file);
    }

  }

  {
    /* expose the buffer to submit data */
    float **buffer = vorbis_analysis_buffer (&vd,count);

    memcpy (buffer [0], data, count * sizeof (float)) ;

    /* tell the library how much we actually submitted */
    vorbis_analysis_wrote (&vd,count);
    vorbis_analysis_wrote (&vd,0);
  }

  while (vorbis_analysis_blockout (&vd,&vb) == 1) {
    vorbis_analysis (&vb,NULL);
    vorbis_bitrate_addblock (&vb);

    while (vorbis_bitrate_flushpacket (&vd,&op)) {
      ogg_stream_packetin (&os,&op);

      while (!eos) {
          int result = ogg_stream_pageout (&os,&og);
          if (result == 0)
              break;
          fwrite (og.header,1,og.header_len,file);
          fwrite (og.body,1,og.body_len,file);

          if (ogg_page_eos (&og))
              eos = 1;
      }
    }
  }

  ogg_stream_clear (&os);
  vorbis_block_clear (&vb);
  vorbis_dsp_clear (&vd);
  vorbis_comment_clear (&vc);
  vorbis_info_clear (&vi);

 fclose (file) ;
}

/* The following function is basically a hacked version of the code in
 * examples/decoder_example.c */
void
read_vorbis_data_or_die (const char *filename, int srate, float * data, int count)
{
  ogg_sync_state   oy;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;

  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  FILE *file;
  char *buffer;
  int  bytes;
  int eos = 0;
  int i;
  int read_total = 0 ;

  if ((file = fopen (filename, "rb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  ogg_sync_init (&oy);

  {
    buffer = ogg_sync_buffer (&oy,4096);
    bytes = fread (buffer,1,4096,file);
    ogg_sync_wrote (&oy,bytes);

    if(ogg_sync_pageout (&oy,&og) != 1) {
      if(bytes < 4096) {
        printf ("Out of data.\n") ;
          goto done_decode ;
      }

      fprintf (stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit (1);
    }

    ogg_stream_init (&os,ogg_page_serialno(&og));

    vorbis_info_init (&vi);
    vorbis_comment_init (&vc);
    if (ogg_stream_pagein (&os,&og) < 0) {
      fprintf (stderr,"Error reading first page of Ogg bitstream data.\n");
      exit (1);
    }

    if (ogg_stream_packetout(&os,&op) != 1) {
      fprintf (stderr,"Error reading initial header packet.\n");
      exit (1);
    }

    if (vorbis_synthesis_headerin (&vi,&vc,&op) < 0) {
      fprintf (stderr,"This Ogg bitstream does not contain Vorbis "
          "audio data.\n");
      exit (1);
    }

    i = 0;
    while ( i < 2) {
      while (i < 2) {
        int result = ogg_sync_pageout (&oy,&og);
        if(result == 0)
          break;
        if(result==1) {
          ogg_stream_pagein(&os,&og);

        while (i < 2) {
          result = ogg_stream_packetout (&os,&op);
          if (result == 0)
            goto done_decode;
          if (result < 0) {
            fprintf (stderr,"Corrupt secondary header.  Exiting.\n");
            exit(1);
          }
        vorbis_synthesis_headerin (&vi,&vc,&op);
        i++;
        }
      }
    }

    buffer = ogg_sync_buffer (&oy,4096);
    bytes = fread (buffer,1,4096,file);
    if (bytes == 0 && i < 2) {
      fprintf (stderr,"End of file before finding all Vorbis headers!\n");
      exit (1);
    }

    ogg_sync_wrote (&oy,bytes);
  }

  if (vi.rate != srate) {
    printf ("\n\nError : File '%s' has sample rate of %ld when it should be %d.\n\n", filename, vi.rate, srate);
    exit (1) ;
  }
  if (vi.channels != 1) {
    printf ("\n\nError : File '%s' has %d channels, but should be mono.\n\n", filename, vi.channels);
    exit (1) ;
  }

  vorbis_synthesis_init (&vd,&vi);
  vorbis_block_init (&vd,&vb);

  while(!eos) {
    while (!eos) {
      int result = ogg_sync_pageout (&oy,&og);
      if (result == 0)
        break;
      if (result < 0) {
        fprintf (stderr,"Corrupt or missing data in bitstream; "
            "continuing...\n");
      } else {
        ogg_stream_pagein (&os,&og);
        while (1) {
          result = ogg_stream_packetout (&os,&op);

          if (result == 0)
            break;
          if (result < 0) {
            /* no reason to complain; already complained above */
          } else {
              float **pcm;
            int samples;

            if (vorbis_synthesis (&vb,&op) == 0)
              vorbis_synthesis_blockin(&vd,&vb);
            while ((samples = vorbis_synthesis_pcmout (&vd,&pcm)) > 0 && read_total < count) {
              int bout = samples < count ? samples : count;
              bout = read_total + bout > count ? count - read_total : bout;

              memcpy (data + read_total, pcm[0], bout * sizeof (float)) ;

              vorbis_synthesis_read (&vd,bout);
              read_total += bout ;
            }
          }
        }

        if (ogg_page_eos (&og)) eos = 1;
      }
    }

      if (!eos) {
        buffer = ogg_sync_buffer (&oy,4096);
        bytes = fread (buffer,1,4096,file);
        ogg_sync_wrote (&oy,bytes);
        if (bytes == 0) eos = 1;
      }
    }

    ogg_stream_clear (&os);

    vorbis_block_clear (&vb);
    vorbis_dsp_clear (&vd);
    vorbis_comment_clear (&vc);
    vorbis_info_clear (&vi);

  }
done_decode:

  /* OK, clean up the framer */
  ogg_sync_clear (&oy);

  fclose (file) ;
}

static int check_output (const float * data_in, unsigned len);

int
main(void){
  static float data_out [DATA_LEN] ;
  static float data_in [DATA_LEN] ;

  /* Do safest and most used sample rates first. */
  int sample_rates [] = { 44100, 48000, 32000, 22050, 16000, 96000 } ;
  unsigned k ;
  int errors = 0 ;

  gen_windowed_sine (data_out, ARRAY_LEN (data_out), 0.95);

  for (k = 0 ; k < ARRAY_LEN (sample_rates); k ++) {
        char filename [64] ;
        snprintf (filename, sizeof (filename), "vorbis_%u.ogg", sample_rates [k]);

        printf ("    %-20s : ", filename);
        fflush (stdout);

        /* Set to know value. */
        set_data_in (data_in, ARRAY_LEN (data_in), 3.141);

        write_vorbis_data_or_die (filename, sample_rates [k], data_out, ARRAY_LEN (data_out));
        read_vorbis_data_or_die (filename, sample_rates [k], data_in, ARRAY_LEN (data_in));

        if (check_output (data_in, ARRAY_LEN (data_in)) != 0)
          errors ++ ;
        else {
          puts ("ok");
      remove (filename);
        }
  }

  if (errors)
    exit (1);

  return 0;
}

static int
check_output (const float * data_in, unsigned len)
{
  float max_abs = 0.0 ;
  unsigned k ;

  for (k = 0 ; k < len ; k++) {
    float temp = fabs (data_in [k]);
    max_abs = MAX (max_abs, temp);
  }
        
  if (max_abs < 0.9) {
    printf ("Error : max_abs (%f) too small.\n", max_abs);
    return 1 ;
  } else if (max_abs > 1.0) {
    printf ("Error : max_abs (%f) too big.\n", max_abs);
    return 1 ;
  }

  return 0 ;
}



More information about the pkg-xiph-maint mailing list