gtoal@tardis.computer-science.edinburgh.ac.uk (05/13/91)
Some time back I asked about playing sun audio files on the Archie;
here's a reply I got from Mark Taunton at Acorn; I've finally gotten
round to passing it on to the net...
Hi Graham,
sorry there has been a little delay, but I thought I'd write anyway.
I have previously looked into this, and after some difficulty with
getting the Sun audio format *exactly* right, I was able to play back
Sun files OK under RISC iX. The primary details of the Sun audio
format you need are:
Sample frequency is 8000 Hz (fixed), mono only. Sample format is 8
bits/sample: bit 7 = sign, bits 0..6 are BITWISE COMPLEMENT of mu255
(pseudo-exponential) representation of magnitude.
You probably know that VIDC's audio data format is bit 0 = sign,
bits 1..7 are the mu255 magnitude (not complemented).
The fact that the magnitude is complemented is what caused me grief
for a while: it renders the sound totally unrecognisable (i.e. it
sounds like just noise). If you think about the signal transformation
you can see why.
As a little extra, feel free to use the following in any way you like.
It's a simple UNIX filter, so it's up to you to adapt for RISC OS...
Cheers.
Mark.
P.S. I haven't thought hard about it, but if you *really* cared about
speed it might be minutely quicker to just complement the whole word
(*including* the sign bits) before (or after) doing the byte-wise
rotate, since not even Golden Eared people should be able to detect
the reversed polarity with this quality of signal! On the other hand,
it might not be.
P.P.S. A quick tip on improving the perceived sound quality: if you
double, triple or quadruple the playback frequency and repeat each
input sample 2, 3 or 4 times (as appropriate!) you cut down on the
amount of audible locally-generated mush considerably, allowing the
crystal-clear beauty of the original signal to shine through. ;-)
/*
* stov.c: convert SparcStation audio data on stdin
* to Archimedes (VIDC) format on stdout.
*
* Mark Taunton, January 1991.
*/
void *malloc();
#define BSZ 4096
main (int argc, char **argv)
{
unsigned char *buff = (unsigned char *)malloc (BSZ);
unsigned int xm1 = 0x01010101;
unsigned int xm2 = ~xm1; /* help compiler along */
int n;
/*
* In the following loop we convert 4 bytes at once because it's
* all pure bit twiddling: there is no arithmetic to cause
* overflow/underflow or other such nasty effects. Each byte is
* converted using the algorithm:
*
* output = (input >> 7) | (~(input << 1) & 0xFE)
*
* i.e. we rotate the byte left by 1 and bitwise complement the
* 7-bit magnitude part. On ARM the actual conversion works out
* to take all of 4 S-cycles (it could be 3 but the (RISC iX 1.21)
* compiler misses a trick), and since we are doing 4 bytes at once
* this really ain't bad! Note that we don't worry about alignment
* on any odd bytes at the end of the buffer (unlikely anyway) - we
* just convert all 4 bytes. The right number still get written.
*/
while ((n = read (0, buff, BSZ)) > 0)
{
unsigned int *wp = (unsigned int *)buff;
unsigned int *lim = (unsigned int *)(buff + ((n + 3) & ~3));
do
{
unsigned int ss = *wp;
*wp++ = ((ss >> 7) & xm1) | (xm2 & ~(ss << 1));
} while (wp != lim);
write (1, buff, n);
}
}