#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include <AudioTypePcm.h>
#include <libaudio.h>
#define irint(d) ((int)d)
AudioTypePcm::
AudioTypePcm()
{
hdr.Clear();
hdr.samples_per_unit = 1;
hdr.encoding = LINEAR;
}
Boolean AudioTypePcm::
CanConvert(
AudioHdr h) const
{
if (h.samples_per_unit != 1)
return (FALSE);
switch (h.encoding) {
case LINEAR:
switch (h.bytes_per_unit) {
case 1: case 2: case 4:
break;
default:
return (FALSE);
}
break;
case FLOAT:
switch (h.bytes_per_unit) {
case 4: case 8:
break;
default:
return (FALSE);
}
break;
case ULAW:
case ALAW:
switch (h.bytes_per_unit) {
case 1:
break;
default:
return (FALSE);
}
break;
default:
return (FALSE);
}
return (TRUE);
}
inline double AudioTypePcm::
char2dbl(char B)
{
return ((unsigned char)B == 0x80 ? -1. : (double)B / 127.);
}
inline double AudioTypePcm::
short2dbl(short S)
{
return ((unsigned short)S == 0x8000 ? -1. : (double)S / 32767.);
}
inline double AudioTypePcm::
long2dbl(long L)
{
return ((unsigned long)L == 0x80000000 ? -1. : (double)L / 2147483647.);
}
inline long AudioTypePcm::
dbl2long(double D, long C)
{
return (D >= 1. ? C : D <= -1. ? -C : (long)irint(D * (double)C));
}
inline void AudioTypePcm::
char2short(char *&F, short *&T) { *T++ = ((short)*F++) << 8; }
inline void AudioTypePcm::
char2long(char *&F, long *&T) { *T++ = ((long)*F++) << 24; }
inline void AudioTypePcm::
char2float(char *&F, float *&T) { *T++ = char2dbl(*F++); }
inline void AudioTypePcm::
char2double(char *&F, double *&T) { *T++ = char2dbl(*F++); }
inline void AudioTypePcm::
char2ulaw(char *&F, ulaw *&T) { *T++ = audio_c2u(*F); F++; }
inline void AudioTypePcm::
char2alaw(char *&F, alaw *&T) { *T++ = audio_c2a(*F); F++; }
inline void AudioTypePcm::
short2char(short *&F, char *&T) { *T++ = (char)(*F++ >> 8); }
inline void AudioTypePcm::
short2long(short *&F, long *&T) { *T++ = ((long)*F++) << 16; }
inline void AudioTypePcm::
short2float(short *&F, float *&T) { *T++ = short2dbl(*F++); }
inline void AudioTypePcm::
short2double(short *&F, double *&T) { *T++ = short2dbl(*F++); }
inline void AudioTypePcm::
short2ulaw(short *&F, ulaw *&T) { *T++ = audio_s2u(*F); F++; }
inline void AudioTypePcm::
short2alaw(short *&F, alaw *&T) { *T++ = audio_s2a(*F); F++; }
inline void AudioTypePcm::
long2char(long *&F, char *&T) { *T++ = (char)(*F++ >> 24); }
inline void AudioTypePcm::
long2short(long *&F, short *&T) { *T++ = (short)(*F++ >> 16); }
inline void AudioTypePcm::
long2float(long *&F, float *&T) { *T++ = long2dbl(*F++); }
inline void AudioTypePcm::
long2double(long *&F, double *&T) { *T++ = long2dbl(*F++); }
inline void AudioTypePcm::
long2ulaw(long *&F, ulaw *&T) { *T++ = audio_l2u(*F); F++; }
inline void AudioTypePcm::
long2alaw(long *&F, alaw *&T) { *T++ = audio_l2a(*F); F++; }
inline void AudioTypePcm::
float2char(float *&F, char *&T) { *T++ = (char)dbl2long(*F++, 127); }
inline void AudioTypePcm::
float2short(float *&F, short *&T) { *T++ = (short)dbl2long(*F++, 32767); }
inline void AudioTypePcm::
float2long(float *&F, long *&T) { *T++ = dbl2long(*F++, 2147483647); }
inline void AudioTypePcm::
float2double(float *&F, double *&T) { *T++ = *F++; }
inline void AudioTypePcm::
float2ulaw(float *&F, ulaw *&T) { *T++ = audio_s2u(dbl2long(*F++, 32767)); }
inline void AudioTypePcm::
float2alaw(float *&F, alaw *&T) { *T++ = audio_s2a(dbl2long(*F++, 32767)); }
inline void AudioTypePcm::
double2char(double *&F, char *&T) { *T++ = (char)dbl2long(*F++, 127); }
inline void AudioTypePcm::
double2short(double *&F, short *&T) { *T++ = (short)dbl2long(*F++, 32767); }
inline void AudioTypePcm::
double2long(double *&F, long *&T) { *T++ = dbl2long(*F++, 2147483647); }
inline void AudioTypePcm::
double2float(double *&F, float *&T) { *T++ = *F++; }
inline void AudioTypePcm::
double2ulaw(double *&F, ulaw *&T) { *T++ = audio_s2u(dbl2long(*F++, 32767)); }
inline void AudioTypePcm::
double2alaw(double *&F, alaw *&T) { *T++ = audio_s2a(dbl2long(*F++, 32767)); }
inline void AudioTypePcm::
ulaw2char(ulaw *&F, char *&T) { *T++ = audio_u2c(*F); F++; }
inline void AudioTypePcm::
ulaw2alaw(ulaw *&F, alaw *&T) { *T++ = audio_u2a(*F); F++; }
inline void AudioTypePcm::
ulaw2short(ulaw *&F, short *&T) { *T++ = audio_u2s(*F); F++; }
inline void AudioTypePcm::
ulaw2long(ulaw *&F, long *&T) { *T++ = audio_u2l(*F); F++; }
inline void AudioTypePcm::
ulaw2float(ulaw *&F, float *&T) { *T++ = short2dbl(audio_u2s(*F)); F++; }
inline void AudioTypePcm::
ulaw2double(ulaw *&F, double *&T) { *T++ = short2dbl(audio_u2s(*F)); F++; }
inline void AudioTypePcm::
alaw2char(alaw *&F, char *&T) { *T++ = audio_a2c(*F); F++; }
inline void AudioTypePcm::
alaw2short(alaw *&F, short *&T) { *T++ = audio_a2s(*F); F++; }
inline void AudioTypePcm::
alaw2long(alaw *&F, long *&T) { *T++ = audio_a2l(*F); F++; }
inline void AudioTypePcm::
alaw2float(alaw *&F, float *&T) { *T++ = short2dbl(audio_a2s(*F)); F++; }
inline void AudioTypePcm::
alaw2double(alaw *&F, double *&T) { *T++ = short2dbl(audio_a2s(*F)); F++; }
inline void AudioTypePcm::
alaw2ulaw(alaw*& F, ulaw*& T) { *T++ = audio_a2u(*F); F++; }
AudioError AudioTypePcm::
Convert(
AudioBuffer*& inbuf,
AudioHdr outhdr)
{
AudioBuffer* outbuf;
AudioHdr inhdr;
Double length;
size_t frames;
void* inptr;
void* outptr;
AudioError err;
inhdr = inbuf->GetHeader();
length = inbuf->GetLength();
if (Undefined(length))
return (AUDIO_ERR_BADARG);
if ((err = inhdr.Validate()) || (err = outhdr.Validate()))
return (err);
if ((inhdr.sample_rate != outhdr.sample_rate) ||
(inhdr.samples_per_unit != outhdr.samples_per_unit) ||
(inhdr.samples_per_unit != 1) ||
(inhdr.channels != outhdr.channels))
return (AUDIO_ERR_HDRINVAL);
if (!inbuf->isReferenced() &&
(outhdr.bytes_per_unit <= inhdr.bytes_per_unit)) {
outbuf = inbuf;
} else {
outbuf = new AudioBuffer(length, "(PCM conversion buffer)");
if (outbuf == 0)
return (AUDIO_UNIXERROR);
err = outbuf->SetHeader(outhdr);
if (err != AUDIO_SUCCESS) {
delete outbuf;
return (err);
}
}
inptr = inbuf->GetAddress();
outptr = outbuf->GetAddress();
frames = (size_t)inhdr.Time_to_Samples(length)
* inhdr.channels;
#define COPY(N) if (inptr != outptr) memcpy(outptr, inptr, frames * N)
#ifdef __STDC__
#define MOVE(F, T) { \
F* ip = (F*)inptr; T* op = (T*)outptr; \
while (frames-- > 0) F ## 2 ## T(ip, op); \
}
#else
#define MOVE(F, T) { \
F* ip = (F*)inptr; T* op = (T*)outptr; \
while (frames-- > 0) F 2 T(ip, op);\
}
#endif
switch (inhdr.encoding) {
case LINEAR:
switch (outhdr.encoding) {
case LINEAR:
switch (inhdr.bytes_per_unit) {
case 1:
switch (outhdr.bytes_per_unit) {
case 1: COPY(1); break;
case 2: MOVE(char, short); break;
case 4: MOVE(char, long); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case 2:
switch (outhdr.bytes_per_unit) {
case 1: MOVE(short, char); break;
case 2: COPY(2); break;
case 4: MOVE(short, long); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case 4:
switch (outhdr.bytes_per_unit) {
case 1: MOVE(long, char); break;
case 2: MOVE(long, short); break;
case 4: COPY(4); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case FLOAT:
switch (inhdr.bytes_per_unit) {
case 1:
switch (outhdr.bytes_per_unit) {
case 4: MOVE(char, float); break;
case 8: MOVE(char, double); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case 2:
switch (outhdr.bytes_per_unit) {
case 4: MOVE(short, float); break;
case 8: MOVE(short, double); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case 4:
switch (outhdr.bytes_per_unit) {
case 4: MOVE(long, float); break;
case 8: MOVE(long, double); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ULAW:
switch (inhdr.bytes_per_unit) {
case 1: MOVE(char, ulaw); break;
case 2: MOVE(short, ulaw); break;
case 4: MOVE(long, ulaw); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ALAW:
switch (inhdr.bytes_per_unit) {
case 1: MOVE(char, alaw); break;
case 2: MOVE(short, alaw); break;
case 4: MOVE(long, alaw); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case FLOAT:
switch (outhdr.encoding) {
case LINEAR:
switch (inhdr.bytes_per_unit) {
case 4:
switch (outhdr.bytes_per_unit) {
case 1: MOVE(float, char); break;
case 2: MOVE(float, short); break;
case 4: MOVE(float, long); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case 8:
switch (outhdr.bytes_per_unit) {
case 1: MOVE(double, char); break;
case 2: MOVE(double, short); break;
case 4: MOVE(double, long); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case FLOAT:
switch (inhdr.bytes_per_unit) {
case 4:
switch (outhdr.bytes_per_unit) {
case 4: COPY(4); break;
case 8: MOVE(float, double); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case 8:
switch (outhdr.bytes_per_unit) {
case 4: MOVE(double, float); break;
case 8: COPY(8); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ULAW:
switch (inhdr.bytes_per_unit) {
case 4: MOVE(float, ulaw); break;
case 8: MOVE(double, ulaw); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ALAW:
switch (inhdr.bytes_per_unit) {
case 4: MOVE(float, alaw); break;
case 8: MOVE(double, alaw); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ULAW:
switch (outhdr.encoding) {
case LINEAR:
switch (outhdr.bytes_per_unit) {
case 1: MOVE(ulaw, char); break;
case 2: MOVE(ulaw, short); break;
case 4: MOVE(ulaw, long); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case FLOAT:
switch (outhdr.bytes_per_unit) {
case 4: MOVE(ulaw, float); break;
case 8: MOVE(ulaw, double); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ULAW:
COPY(1); break;
case ALAW:
MOVE(ulaw, alaw); break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ALAW:
switch (outhdr.encoding) {
case LINEAR:
switch (outhdr.bytes_per_unit) {
case 1: MOVE(alaw, char); break;
case 2: MOVE(alaw, short); break;
case 4: MOVE(alaw, long); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case FLOAT:
switch (outhdr.bytes_per_unit) {
case 4: MOVE(alaw, float); break;
case 8: MOVE(alaw, double); break;
default: err = AUDIO_ERR_HDRINVAL; break;
}
break;
case ALAW:
COPY(1); break;
case ULAW:
MOVE(alaw, ulaw); break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
break;
default:
err = AUDIO_ERR_HDRINVAL; break;
}
if (err) {
if (outbuf != inbuf)
delete outbuf;
return (err);
}
if (outbuf == inbuf) {
(void) inbuf->SetHeader(outhdr);
} else {
inbuf->Reference();
inbuf->Dereference();
outbuf->SetLength(length);
inbuf = outbuf;
}
return (AUDIO_SUCCESS);
}
AudioError AudioTypePcm::
Flush(
AudioBuffer*& )
{
return (AUDIO_SUCCESS);
}