xash3d-fwgs/engine/common/soundlib/libmpg/index.c

155 lines
3.2 KiB
C
Raw Normal View History

2018-04-17 02:57:04 +02:00
/*
index.c - compact version of famous library mpg123
Copyright (C) 2017 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "mpg123.h"
#include "index.h"
// the next expected frame offset, one step ahead.
static mpg_off_t fi_next( frame_index_t *fi )
{
return (mpg_off_t)fi->fill*fi->step;
}
// shrink down the used index to the half.
// be careful with size = 1 ... there's no shrinking possible there.
static void fi_shrink( frame_index_t *fi )
{
if( fi->fill < 2 )
{
return; // won't shrink below 1.
}
else
{
size_t c;
// double the step, half the fill. Should work as well for fill%2 = 1
fi->step *= 2;
fi->fill /= 2;
// move the data down.
for( c = 0; c < fi->fill; ++c )
fi->data[c] = fi->data[2*c];
}
fi->next = fi_next( fi );
}
void fi_init( frame_index_t *fi )
{
fi->data = NULL;
fi->step = 1;
fi->fill = 0;
fi->size = 0;
fi->grow_size = 0;
fi->next = fi_next( fi );
}
void fi_exit( frame_index_t *fi )
{
if( fi->size && fi->data != NULL )
free( fi->data );
fi_init( fi ); // be prepared for further fun, still.
}
int fi_resize( frame_index_t *fi, size_t newsize )
{
mpg_off_t *newdata = NULL;
if( newsize == fi->size )
return 0;
if( newsize > 0 && newsize < fi->size )
{
// when we reduce buffer size a bit, shrink stuff.
while( fi->fill > newsize )
fi_shrink( fi );
}
newdata = realloc( fi->data, newsize * sizeof( mpg_off_t ));
if( newsize == 0 || newdata != NULL )
{
fi->data = newdata;
fi->size = newsize;
if( fi->fill > fi->size )
fi->fill = fi->size;
fi->next = fi_next( fi );
return 0;
}
else
{
return -1;
}
}
void fi_add( frame_index_t *fi, mpg_off_t pos )
{
if( fi->fill == fi->size )
{
mpg_off_t framenum = fi->fill*fi->step;
// index is full, we need to shrink... or grow.
// store the current frame number to check later if we still want it.
// if we want not / cannot grow, we shrink.
if( !( fi->grow_size && fi_resize( fi, fi->size+fi->grow_size ) == 0 ))
fi_shrink( fi );
// now check if we still want to add this frame (could be that not, because of changed step).
if( fi->next != framenum )
return;
}
// when we are here, we want that frame.
if( fi->fill < fi->size ) // safeguard for size = 1, or just generally
{
fi->data[fi->fill] = pos;
fi->fill++;
fi->next = fi_next( fi );
}
}
int fi_set( frame_index_t *fi, mpg_off_t *offsets, mpg_off_t step, size_t fill )
{
if( fi_resize( fi, fill ) == -1 )
return -1;
fi->step = step;
if( offsets != NULL )
{
memcpy( fi->data, offsets, fill * sizeof( mpg_off_t ));
fi->fill = fill;
}
else
{
// allocation only, no entries in index yet
fi->fill = 0;
}
fi->next = fi_next( fi );
return 0;
}
void fi_reset( frame_index_t *fi )
{
fi->fill = 0;
fi->step = 1;
fi->next = fi_next( fi );
}