[Speex-dev] Re: just noise

zmorris at mac.com zmorris at mac.com
Sat Apr 21 14:53:04 PDT 2007


On Apr 21, 2007, at 12:36 PM, zmorris at mac.com wrote:

> Hi, I tried both the stable and beta versions of the speex source  
> code download on Mac OS 10.4.9.  I just do:
>
> ...
>
> However, when I play the output file, I get the header and a second  
> of audio, but the rest is just noise.

I figured it out, the problem is that WAV files are little endian and  
I am on powerpc, so the sample byte order must be swapped.  That  
still isn't the whole story, and I will explain how it's still not  
working, but first you need to update your example at:

http://www.speex.org/docs/manual/speex-manual/ 
node13.html#SECTION000131000000000000000

To say something along the lines of "when using the example with WAV  
files on a big endian architecture like powerpc, you must swap the  
byte order of the samples with the following code:"

////////////////////////////////////////
/* Define to 1 if your processor stores words with the most  
significant byte
    first (like Motorola and SPARC, unlike Intel and VAX). */
#define WORDS_BIGENDIAN 1

unsigned short be_short(unsigned short s)
{
    unsigned short ret=s;
#ifndef WORDS_BIGENDIAN
    ret =  s>>8;
    ret += s<<8;
#endif
    return ret;
}

unsigned short le_short(unsigned short s)
{
    unsigned short ret=s;
#ifdef WORDS_BIGENDIAN
    ret =  s>>8;
    ret += s<<8;
#endif
    return ret;
}
////////////////////////////////////////

These functions should really be inline or macros, and I believe the  
| operator is faster than + on RISC because it can be executed faster  
alongside << and >> in the pipeline but I could be wrong.  Then you  
need to change the 2 lines that convert the samples to floats to say:

////////////////////////////////////////
/*Copy the 16 bits values to float so Speex can work on them*/
for (i=0;i<FRAME_SIZE;i++)
	input[i] = le_short( in[i] );

/*Copy from float to short (16 bits) for output*/
for (i=0;i<FRAME_SIZE;i++)
	out[i] = le_short( output[i] );
////////////////////////////////////////

Also, endian issues are so important that they need to be discussed  
in the manual more.  You should probably mention:

#include <arpa/inet.h>

// from transmitting on network
ntohs()
htons()

from sockets, and:

#include <CoreFoundation/CFByteOrder.h>

// for import/export wav
CFSwapInt16LittleToHost()
CFSwapInt16HostToLittle()

// from transmitting on network
CFSwapInt16LittleToHost()
CFSwapInt16HostToLittle()

on Mac, right there on the example page.  Also, please discuss the  
format of the compressed bits from squeex, because it's not clear to  
me if they are already big endian for sending over the network.

The real kicker is that after doing this, I am still getting noise!   
I can make out the voice but it sounds 50% noisy now, and it's not  
the minimal noise that is always present.  This is full-blown-every- 
other-sample-is-wrong noise.

To trace it to this point, I downloaded and installed libogg from:

http://xiph.org/downloads/

so that I could use speexenc and speexdec from the console, which  
worked perfectly.  Then I traced it back to where it was reading  
samples and found the endian conversion.  I will have to backtrack  
even further now to find out exactly why my test still isn't working,  
and it is becoming quite a waste of time.  I've lost 2 days to this  
so far and it's looking like that might become 3.  This is all with  
1.2beta1 so I will try 1.0.5 and see if it fixes the noise problem.

One way around all of this is to include more projects and not just  
focus on win32.  An xcode project showing the example would be a good  
start.  Adding a few lines to handle the WAV header would be ideal.

--Zack


More information about the Speex-dev mailing list