[Vorbis-dev] endian problems with AIFF and WAV

dave at 661.org dave at 661.org
Wed Dec 4 02:22:04 PST 2013


I have a test program that loads an AIFF or WAV file with libsndfile and 
plays then using libao.  After running around in circles for a while, I 
found and fixed the problem, but I'm still confused as to why the solution 
works.  Would someone please explain this to me so I don't trip over this 
again later in my project?

I used sf_open_fd() to get a SNDFILE* pointer and an AF_INFO struct.  In 
that struct I find out what bit resolution the samples are.  I put that 
number into ao_sample_format format.bits, fill a buffer using 
sf_read_int() and then call ao_play().  Doing this with a file containing 
8-bit samples, the result was the file playing at at half-pitch and twice 
as long as normal.  But, if I manually plug in format.bits = 32, the files 
play fine.

Here's the program:

/* compile with "gcc -o foo foo.c -lao -ldl -lm -lsndfile" */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ao/ao.h>
#include <sndfile.h>
#include <math.h>

ao_device *device;
ao_sample_format format;

int main(int argc, char *argv[])
{
     int default_driver;
     int frames_read;
     int *buffer;

     SNDFILE     *sndfile;
     SF_INFO     sf_info;
     FILE 	*fp;

     if (argc != 2) {
 	printf("usage: %s <filename>\n", argv[0]);
 	exit(1);
     }

     ao_initialize();
     default_driver = ao_default_driver_id();

     fp = fopen(argv[1], "rb");
     if (fp == NULL) {
 	printf("Cannot open %s.\n", argv[1]);
 	exit(2);
     }

     sf_info.format = 0;
     sndfile = sf_open_fd(fileno(fp), SFM_READ, &sf_info, 1);

     memset(&format, 0, sizeof(format));

     if ((sf_info.format & SF_ENDIAN_LITTLE) == SF_ENDIAN_LITTLE) format.byte_format = AO_FMT_LITTLE;
     if ((sf_info.format & SF_ENDIAN_BIG) == SF_ENDIAN_BIG) format.byte_format = AO_FMT_BIG;
     if ((sf_info.format & SF_FORMAT_PCM_S8) == SF_FORMAT_PCM_S8) format.bits = 8;
     if ((sf_info.format & SF_FORMAT_PCM_16) == SF_FORMAT_PCM_16) format.bits = 16;
     if ((sf_info.format & SF_FORMAT_PCM_24) == SF_FORMAT_PCM_24) format.bits = 24;
     if ((sf_info.format & SF_FORMAT_PCM_32) == SF_FORMAT_PCM_32) format.bits = 32;
     if ((sf_info.format & SF_FORMAT_PCM_U8) == SF_FORMAT_PCM_U8) format.bits = 8;

//    format.bits = 32;

     printf("%x\n", sf_info.format);
     printf("bits: %d\n", format.bits);

     format.channels = sf_info.channels;
     format.rate = sf_info.samplerate;

     device = ao_open_live(default_driver, &format, NULL /* no options */);
     if (device == NULL) {
         printf("Error opening sound device.\n");
         exit(1);
     }

     buffer = malloc(sizeof(int) * sf_info.frames * sf_info.channels);
     frames_read = sf_read_int(sndfile, buffer, sf_info.frames * sizeof(int));

     ao_play(device, (char *)buffer, sf_info.frames * sizeof(int));
     ao_close(device);
     ao_shutdown();
     sf_close(sndfile);
     return 0;
}


More information about the Vorbis-dev mailing list