[Speex-dev] Re: just noise
zmorris at mac.com
zmorris at mac.com
Sat Apr 21 16:49:45 PDT 2007
On Apr 21, 2007, at 3:53 PM, zmorris at mac.com wrote:
> 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:
OK I finally figured out the second noise problem. It's a riddle
wrapped in a mystery inside an enigma. Judging by the somewhat odd
structure of le_short() and be_short(), I think this keeps coming up
over and over again. Even Apple's byte swapping macros fail under
certain circumstances, and here's why:
1. Logical shifting must be used, not arithmetic (or else the high
bit is wrong)
2. Conversion from short to float must be signed, not unsigned (or
else the line level is wrong)
3. The order of operations must be written just-so, or gcc stumbles
over the conversion from short to float
The offending line was this one:
for (i=0;i<FRAME_SIZE;i++)
input[i] = le_short( in[i] );
This always fails with the current le_short() function. Here are
updated versions, in both macro and inline form. You can leave
inline off of the function version and it still works fine:
////////////////////////////////////////
/* 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
#ifdef WORDS_BIGENDIAN
#define le_short( s ) ((short) ((unsigned short) (s) << 8) |
((unsigned short) (s) >> 8))
#define be_short( s ) ((short) (s))
#else
#define le_short( s ) ((short) (s))
#define be_short( s ) ((short) ((unsigned short) (s) << 8) |
((unsigned short) (s) >> 8))
#endif
inline short le_short( unsigned short s )
{
#ifdef WORDS_BIGENDIAN
return( (s << 8) | (s >> 8) );
#endif
return s;
}
inline short be_short( unsigned short s )
{
#ifndef WORDS_BIGENDIAN
return( (s << 8) | (s >> 8) );
#endif
return s;
}
////////////////////////////////////////
Now I am sorry to rant a moment, but I am getting too old for this
stuff. Whenever I am speaking with fellow programmers, they love to
jump to the conclusion that the problem is mine and that there is
nothing wrong with the code. I am experienced enough to know that
there are multitudes of reasons why things fail and that yes, even
vanilla code examples often fail. I tried your sample code and it
didn't work, plain and simple.
UNIX is like this through and through. Whenever I try something, I
just know it won't work, like I knew this wouldn't work. The fault
is almost never mine (at least not through incompetence, because I
follow directions explicitly), but is cause by assumptions about the
infrastructure by myself and others. For all its benefits, the unix
mindset can easily condemn us to a life of servitude, baby sitting
our computers instead of getting real work done.
Anyway, I hope this series of emails shows the importance of
providing full examples for the target environments. If you ever
want speex to catch on in the mainstream, everyday people need to be
able to drop it in, but at this point only hackers can really do
that. I mean the kind of hackers willing to spend 2 days to fix 2
lines of code that should "just work."
So I thank you from the bottom of my heart for making such a
brilliant piece of software as speex, I really appreciate what you
guys stand for :) I just hope that you get some time to step back
and polish up the sample code and manual just a hair. I know how it
goes when you have to spend all of your time on development to keep
something even just working, so this rant is not directed at anyone
in particular :)
--Zack
More information about the Speex-dev
mailing list