gzdoom-gles/dumb/src/core/rendduh.c
Randy Heit 01f59fa85f - Added an alternate module replay engine that uses foo_dumb's replayer, a
heavily customized version of DUMB (Dynamic Universal Music Bibliotheque).
  It has been slightly modified by me:
  * Added support for Ogg Vorbis-compressed samples in XM files ala FMOD.
  * Removed excessive mallocs from the replay core.
  * Rerolled the loops in resample.c. Unrolling them made the object file
    ~250k large while providing little benefit. Even at ~100k, I think it's
    still larger than it ought to be, but I'll live with it for now.
  Other than that, it's essentially the same thing you'd hear in foobar2000,
  minus some subsong detection features. Release builds of the library look
  like they might even be slightly faster than FMOD, which is a plus.
- Fixed: Timidity::font_add() did not release the file reader it created.
- Fixed: The SF2 loader did not free the sample headers in its destructor.


SVN r995 (trunk)
2008-05-29 23:33:07 +00:00

184 lines
4.5 KiB
C

/* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . .
* | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \
* / . \
* rendduh.c - Functions for rendering a DUH into / / \ \
* an end-user sample format. | < / \_
* | \/ /\ /
* By entheh. \_ / > /
* | \ / /
* | ' /
* \__/
*/
#include <stdlib.h>
#include <limits.h>
#include "dumb.h"
#include "internal/dumb.h"
/* On the x86, we can use some tricks to speed stuff up */
#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
// Can't we detect Linux and other x86 platforms here? :/
#define FAST_MID(var, min, max) { \
var -= (min); \
var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
var += (min); \
var -= (max); \
var &= var >> (sizeof(var) * CHAR_BIT - 1); \
var += (max); \
}
#define CONVERT8(src, pos, signconv) { \
signed int f = (src + 0x8000) >> 16; \
FAST_MID(f, -128, 127); \
((char*)sptr)[pos] = (char)f ^ signconv; \
}
#define CONVERT16(src, pos, signconv) { \
signed int f = (src + 0x80) >> 8; \
FAST_MID(f, -32768, 32767); \
((short*)sptr)[pos] = (short)(f ^ signconv); \
}
#else
#define CONVERT8(src, pos, signconv) \
{ \
signed int f = (src + 0x8000) >> 16; \
f = MID(-128, f, 127); \
((char *)sptr)[pos] = (char)f ^ signconv; \
}
#define CONVERT16(src, pos, signconv) \
{ \
signed int f = (src + 0x80) >> 8; \
f = MID(-32768, f, 32767); \
((short *)sptr)[pos] = (short)(f ^ signconv); \
}
#endif
/* DEPRECATED */
DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, int32 pos)
{
return duh_start_sigrenderer(duh, 0, n_channels, pos);
}
int32 DUMBEXPORT duh_render(
DUH_SIGRENDERER *sigrenderer,
int bits, int unsign,
float volume, float delta,
int32 size, void *sptr
)
{
int32 n;
sample_t **sampptr;
int n_channels;
ASSERT(bits == 8 || bits == 16);
ASSERT(sptr);
if (!sigrenderer)
return 0;
n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
ASSERT(n_channels > 0);
/* This restriction will be removed when need be. At the moment, tightly
* optimised loops exist for exactly one or two channels.
*/
ASSERT(n_channels <= 2);
sampptr = allocate_sample_buffer(n_channels, size);
if (!sampptr)
return 0;
dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
if (bits == 16) {
int signconv = unsign ? 0x8000 : 0x0000;
for (n = 0; n < size * n_channels; n++) {
CONVERT16(sampptr[0][n], n, signconv);
}
} else {
char signconv = unsign ? 0x80 : 0x00;
for (n = 0; n < size * n_channels; n++) {
CONVERT8(sampptr[0][n], n, signconv);
}
}
destroy_sample_buffer(sampptr);
return size;
}
/* DEPRECATED */
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
{
return duh_sigrenderer_get_n_channels(dr);
}
/* DEPRECATED */
int32 duh_renderer_get_position(DUH_SIGRENDERER *dr)
{
return duh_sigrenderer_get_position(dr);
}
/* DEPRECATED */
void duh_end_renderer(DUH_SIGRENDERER *dr)
{
duh_end_sigrenderer(dr);
}
/* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
{
return sigrenderer;
}
/* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
{
return dr;
}
/* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
{
return dr;
}