mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-17 06:30:44 +01:00
155 lines
3.2 KiB
C
155 lines
3.2 KiB
C
|
/*
|
||
|
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 );
|
||
|
}
|