forked from KolibriOS/kolibrios
libmpg123 1.15.4
git-svn-id: svn://kolibrios.org@3960 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
@@ -23,14 +23,25 @@ static const int my_encodings[MPG123_ENCODINGS] =
|
||||
MPG123_ENC_UNSIGNED_16,
|
||||
MPG123_ENC_SIGNED_32,
|
||||
MPG123_ENC_UNSIGNED_32,
|
||||
MPG123_ENC_SIGNED_24,
|
||||
MPG123_ENC_UNSIGNED_24,
|
||||
/* Floating point range, see below. */
|
||||
MPG123_ENC_FLOAT_32,
|
||||
MPG123_ENC_FLOAT_64,
|
||||
/* 8 bit range, see below. */
|
||||
MPG123_ENC_SIGNED_8,
|
||||
MPG123_ENC_UNSIGNED_8,
|
||||
MPG123_ENC_ULAW_8,
|
||||
MPG123_ENC_ALAW_8
|
||||
};
|
||||
|
||||
/* Make that match the above table.
|
||||
And yes, I still don't like this kludgy stuff. */
|
||||
/* range[0] <= i < range[1] for forced floating point */
|
||||
static const int enc_float_range[2] = { 6, 8 };
|
||||
/* same for 8 bit encodings */
|
||||
static const int enc_8bit_range[2] = { 8, 12 };
|
||||
|
||||
/* Only one type of float is supported. */
|
||||
# ifdef REAL_IS_FLOAT
|
||||
# define MPG123_FLOAT_ENC MPG123_ENC_FLOAT_32
|
||||
@@ -48,6 +59,8 @@ static const int good_encodings[] =
|
||||
#ifndef NO_32BIT
|
||||
MPG123_ENC_SIGNED_32,
|
||||
MPG123_ENC_UNSIGNED_32,
|
||||
MPG123_ENC_SIGNED_24,
|
||||
MPG123_ENC_UNSIGNED_24,
|
||||
#endif
|
||||
#ifndef NO_REAL
|
||||
MPG123_FLOAT_ENC,
|
||||
@@ -84,6 +97,22 @@ void attribute_align_arg mpg123_encodings(const int **list, size_t *number)
|
||||
if(number != NULL) *number = sizeof(good_encodings)/sizeof(int);
|
||||
}
|
||||
|
||||
int attribute_align_arg mpg123_encsize(int encoding)
|
||||
{
|
||||
if(encoding & MPG123_ENC_8)
|
||||
return 1;
|
||||
else if(encoding & MPG123_ENC_16)
|
||||
return 2;
|
||||
else if(encoding & MPG123_ENC_24)
|
||||
return 3;
|
||||
else if(encoding & MPG123_ENC_32 || encoding == MPG123_ENC_FLOAT_32)
|
||||
return 4;
|
||||
else if(encoding == MPG123_ENC_FLOAT_64)
|
||||
return 8;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* char audio_caps[NUM_CHANNELS][MPG123_RATES+1][MPG123_ENCODINGS]; */
|
||||
|
||||
static int rate2num(mpg123_pars *mp, long r)
|
||||
@@ -126,14 +155,18 @@ static int freq_fit(mpg123_handle *fr, struct audioformat *nf, int f0, int f2)
|
||||
{
|
||||
nf->rate = frame_freq(fr)>>fr->p.down_sample;
|
||||
if(cap_fit(fr,nf,f0,f2)) return 1;
|
||||
nf->rate>>=1;
|
||||
if(cap_fit(fr,nf,f0,f2)) return 1;
|
||||
nf->rate>>=1;
|
||||
if(cap_fit(fr,nf,f0,f2)) return 1;
|
||||
if(fr->p.flags & MPG123_AUTO_RESAMPLE)
|
||||
{
|
||||
nf->rate>>=1;
|
||||
if(cap_fit(fr,nf,f0,f2)) return 1;
|
||||
nf->rate>>=1;
|
||||
if(cap_fit(fr,nf,f0,f2)) return 1;
|
||||
}
|
||||
#ifndef NO_NTOM
|
||||
/* If nothing worked, try the other rates, only without constrains from user.
|
||||
In case you didn't guess: We enable flexible resampling if we find a working rate. */
|
||||
if(!fr->p.force_rate && fr->p.down_sample == 0)
|
||||
if( fr->p.flags & MPG123_AUTO_RESAMPLE &&
|
||||
!fr->p.force_rate && fr->p.down_sample == 0)
|
||||
{
|
||||
int i;
|
||||
int c = nf->channels-1;
|
||||
@@ -176,13 +209,13 @@ int frame_output_format(mpg123_handle *fr)
|
||||
/* All this forcing should be removed in favour of the capabilities table... */
|
||||
if(p->flags & MPG123_FORCE_8BIT)
|
||||
{
|
||||
f0 = 6;
|
||||
f2 = 10;
|
||||
f0 = enc_8bit_range[0];
|
||||
f2 = enc_8bit_range[1];
|
||||
}
|
||||
if(p->flags & MPG123_FORCE_FLOAT)
|
||||
{
|
||||
f0 = 4;
|
||||
f2 = 6;
|
||||
f0 = enc_float_range[0];
|
||||
f2 = enc_float_range[1];
|
||||
}
|
||||
|
||||
/* force stereo is stronger */
|
||||
@@ -254,15 +287,8 @@ end: /* Here is the _good_ end. */
|
||||
fr->af.channels = nf.channels;
|
||||
fr->af.encoding = nf.encoding;
|
||||
/* Cache the size of one sample in bytes, for ease of use. */
|
||||
if(fr->af.encoding & MPG123_ENC_8)
|
||||
fr->af.encsize = 1;
|
||||
else if(fr->af.encoding & MPG123_ENC_16)
|
||||
fr->af.encsize = 2;
|
||||
else if(fr->af.encoding & MPG123_ENC_32 || fr->af.encoding == MPG123_ENC_FLOAT_32)
|
||||
fr->af.encsize = 4;
|
||||
else if(fr->af.encoding == MPG123_ENC_FLOAT_64)
|
||||
fr->af.encsize = 8;
|
||||
else
|
||||
fr->af.encsize = mpg123_encsize(fr->af.encoding);
|
||||
if(fr->af.encsize < 1)
|
||||
{
|
||||
if(NOQUIET) error1("Some unknown encoding??? (%i)", fr->af.encoding);
|
||||
|
||||
@@ -383,6 +409,15 @@ void invalidate_format(struct audioformat *af)
|
||||
af->channels = 0;
|
||||
}
|
||||
|
||||
/* Consider 24bit output needing 32bit output as temporary storage. */
|
||||
off_t samples_to_storage(mpg123_handle *fr, off_t s)
|
||||
{
|
||||
if(fr->af.encoding & MPG123_ENC_24)
|
||||
return s*4*fr->af.channels; /* 4 bytes per sample */
|
||||
else
|
||||
return samples_to_bytes(fr, s);
|
||||
}
|
||||
|
||||
/* take into account: channels, bytes per sample -- NOT resampling!*/
|
||||
off_t samples_to_bytes(mpg123_handle *fr , off_t s)
|
||||
{
|
||||
@@ -393,3 +428,94 @@ off_t bytes_to_samples(mpg123_handle *fr , off_t b)
|
||||
{
|
||||
return b / fr->af.encsize / fr->af.channels;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_32BIT
|
||||
/* Remove every fourth byte, facilitating conversion from 32 bit to 24 bit integers.
|
||||
This has to be aware of endianness, of course. */
|
||||
static void chop_fourth_byte(struct outbuffer *buf)
|
||||
{
|
||||
unsigned char *wpos = buf->data;
|
||||
unsigned char *rpos = buf->data;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
while((size_t) (rpos - buf->data + 4) <= buf->fill)
|
||||
{
|
||||
/* Really stupid: Copy, increment. Byte per byte. */
|
||||
*wpos = *rpos;
|
||||
wpos++; rpos++;
|
||||
*wpos = *rpos;
|
||||
wpos++; rpos++;
|
||||
*wpos = *rpos;
|
||||
wpos++; rpos++;
|
||||
rpos++; /* Skip the lowest byte (last). */
|
||||
}
|
||||
#else
|
||||
while((size_t) (rpos - buf->data + 4) <= buf->fill)
|
||||
{
|
||||
/* Really stupid: Copy, increment. Byte per byte. */
|
||||
rpos++; /* Skip the lowest byte (first). */
|
||||
*wpos = *rpos;
|
||||
wpos++; rpos++;
|
||||
*wpos = *rpos;
|
||||
wpos++; rpos++;
|
||||
*wpos = *rpos;
|
||||
wpos++; rpos++;
|
||||
}
|
||||
#endif
|
||||
buf->fill = wpos-buf->data;
|
||||
}
|
||||
#endif
|
||||
|
||||
void postprocess_buffer(mpg123_handle *fr)
|
||||
{
|
||||
/* Handle unsigned output formats via reshifting after decode here.
|
||||
Also handle conversion to 24 bit. */
|
||||
#ifndef NO_32BIT
|
||||
if(fr->af.encoding == MPG123_ENC_UNSIGNED_32 || fr->af.encoding == MPG123_ENC_UNSIGNED_24)
|
||||
{ /* 32bit signed -> unsigned */
|
||||
size_t i;
|
||||
int32_t *ssamples;
|
||||
uint32_t *usamples;
|
||||
ssamples = (int32_t*)fr->buffer.data;
|
||||
usamples = (uint32_t*)fr->buffer.data;
|
||||
debug("converting output to unsigned 32 bit integer");
|
||||
for(i=0; i<fr->buffer.fill/sizeof(int32_t); ++i)
|
||||
{
|
||||
/* Different strategy since we don't have a larger type at hand.
|
||||
Also watch out for silly +-1 fun because integer constants are signed in C90! */
|
||||
if(ssamples[i] >= 0)
|
||||
usamples[i] = (uint32_t)ssamples[i] + 2147483647+1;
|
||||
/* The smalles value goes zero. */
|
||||
else if(ssamples[i] == ((int32_t)-2147483647-1))
|
||||
usamples[i] = 0;
|
||||
/* Now -value is in the positive range of signed int ... so it's a possible value at all. */
|
||||
else
|
||||
usamples[i] = (uint32_t)2147483647+1 - (uint32_t)(-ssamples[i]);
|
||||
}
|
||||
/* Dumb brute force: A second pass for hacking off the last byte. */
|
||||
if(fr->af.encoding == MPG123_ENC_UNSIGNED_24)
|
||||
chop_fourth_byte(&fr->buffer);
|
||||
}
|
||||
else if(fr->af.encoding == MPG123_ENC_SIGNED_24)
|
||||
{
|
||||
/* We got 32 bit signed ... chop off for 24 bit signed. */
|
||||
chop_fourth_byte(&fr->buffer);
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_16BIT
|
||||
if(fr->af.encoding == MPG123_ENC_UNSIGNED_16)
|
||||
{
|
||||
size_t i;
|
||||
short *ssamples;
|
||||
unsigned short *usamples;
|
||||
ssamples = (short*)fr->buffer.data;
|
||||
usamples = (unsigned short*)fr->buffer.data;
|
||||
debug("converting output to unsigned 16 bit integer");
|
||||
for(i=0; i<fr->buffer.fill/sizeof(short); ++i)
|
||||
{
|
||||
long tmp = (long)ssamples[i]+32768;
|
||||
usamples[i] = (unsigned short)tmp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user