mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-12-05 01:24:19 +01:00
547 lines
12 KiB
C
547 lines
12 KiB
C
|
/*
|
||
|
* Copyright (c) 2002, 2003, 2004, 2005, 2007 by Christian Nowak <chnowak@web.de>
|
||
|
* Last update: 20th October, 2007
|
||
|
*/
|
||
|
|
||
|
#include "mixer.h"
|
||
|
|
||
|
#define DO_LOOPING \
|
||
|
if (forward) \
|
||
|
{ \
|
||
|
playpos += incval; \
|
||
|
if (playpos >= loop_end) \
|
||
|
{ \
|
||
|
if (looped) \
|
||
|
{ \
|
||
|
if (pingpong) \
|
||
|
{ \
|
||
|
forward = !forward; \
|
||
|
playpos -= incval; \
|
||
|
} else \
|
||
|
playpos -= loop_end - loop_start; \
|
||
|
} else \
|
||
|
{ \
|
||
|
playpos = loop_end; \
|
||
|
vinfo->playing = FALSE; \
|
||
|
break; \
|
||
|
} \
|
||
|
} \
|
||
|
} else \
|
||
|
{ \
|
||
|
playpos -= incval; \
|
||
|
if (/*playpos <= loop_start*/playpos - loop_start <= incval) \
|
||
|
{ \
|
||
|
if (looped) \
|
||
|
{ \
|
||
|
if (pingpong) \
|
||
|
{ \
|
||
|
forward = !forward; \
|
||
|
playpos += incval; \
|
||
|
} else \
|
||
|
playpos += loop_end - loop_start; \
|
||
|
} else \
|
||
|
{ \
|
||
|
playpos = loop_start; \
|
||
|
vinfo->playing = FALSE; \
|
||
|
break; \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define DO_LOOPING_OLD \
|
||
|
playpos += incval; \
|
||
|
if (playpos >= loop_end) \
|
||
|
{ \
|
||
|
if (looped) \
|
||
|
{ \
|
||
|
playpos -= loop_end-loop_start; \
|
||
|
} else \
|
||
|
{ \
|
||
|
playpos = loop_end; \
|
||
|
vinfo->playing = FALSE; \
|
||
|
break; \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define DO_LOOPING_PINGPONG \
|
||
|
playpos += incval; \
|
||
|
if (forward && playpos >= loop_end) \
|
||
|
{ \
|
||
|
if (looped) \
|
||
|
{ \
|
||
|
incval = -incval; \
|
||
|
forward = FALSE; \
|
||
|
} else \
|
||
|
{ \
|
||
|
playpos = loop_end; \
|
||
|
vinfo->playing = FALSE; \
|
||
|
break; \
|
||
|
} \
|
||
|
} else \
|
||
|
if (!forward && playpos <= loop_start) \
|
||
|
{ \
|
||
|
if (looped) \
|
||
|
{ \
|
||
|
incval = -incval; \
|
||
|
forward = TRUE; \
|
||
|
} else \
|
||
|
{ \
|
||
|
playpos = loop_start; \
|
||
|
vinfo->playing = FALSE; \
|
||
|
break; \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
int mix_destbufsize(int flags) {
|
||
|
|
||
|
int size = 1;
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO)
|
||
|
size *= 2;
|
||
|
if (flags & MIXER_DEST_16BIT)
|
||
|
size *= 2;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
int clearbuf_final(int flags, void *dest, int nSamples) {
|
||
|
|
||
|
if (flags & MIXER_USE_S32) {
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO) {
|
||
|
|
||
|
clearbuf_s32((s32*)dest, 2, nSamples);
|
||
|
} else {
|
||
|
|
||
|
clearbuf_s32((s32*)dest, 1, nSamples);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
int mix_final_1616bit(int flags, void *dest, int nSamples, MOD_VOICEINFO16 *vinfo, u8 mainvol) {
|
||
|
|
||
|
if (flags & MIXER_USE_S32) {
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO) {
|
||
|
|
||
|
if (vinfo->sampleInfo->bit_16) {
|
||
|
|
||
|
mix_s16m_to_s32s_1616bit((s32*)dest, nSamples, vinfo, mainvol);
|
||
|
} else {
|
||
|
|
||
|
mix_s8m_to_s32s_1616bit((s32*)dest, nSamples, vinfo, mainvol);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
if (vinfo->sampleInfo->bit_16) {
|
||
|
|
||
|
mix_s16m_to_s32m_1616bit((s32*)dest, nSamples, vinfo, mainvol);
|
||
|
} else {
|
||
|
|
||
|
mix_s8m_to_s32m_1616bit((s32*)dest, nSamples, vinfo, mainvol);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
int copybuf_final(int flags, void *dest, void *src, int nSamples) {
|
||
|
|
||
|
if (flags & MIXER_USE_S32) {
|
||
|
|
||
|
if (flags & MIXER_DEST_SIGNED) {
|
||
|
|
||
|
if (flags & MIXER_DEST_16BIT) {
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO) {
|
||
|
|
||
|
copybuf_s32_to_s16((s16*)dest, (s32*)src, 2, nSamples);
|
||
|
} else {
|
||
|
|
||
|
copybuf_s32_to_s16((s16*)dest, (s32*)src, 1, nSamples);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO) {
|
||
|
|
||
|
copybuf_s32_to_s8((s8*)dest, (s32*)src, 2, nSamples);
|
||
|
} else {
|
||
|
|
||
|
copybuf_s32_to_s8((s8*)dest, (s32*)src, 1, nSamples);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
if (flags & MIXER_DEST_16BIT) {
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO) {
|
||
|
|
||
|
copybuf_s32_to_u16((u16*)dest, (s32*)src, 2, nSamples);
|
||
|
} else {
|
||
|
|
||
|
copybuf_s32_to_u16((u16*)dest, (s32*)src, 1, nSamples);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
if (flags & MIXER_DEST_STEREO) {
|
||
|
|
||
|
copybuf_s32_to_u8((u8*)dest, (s32*)src, 2, nSamples);
|
||
|
} else {
|
||
|
|
||
|
copybuf_s32_to_u8((u8*)dest, (s32*)src, 1, nSamples);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
/* Mix s8 mono -> s32 mono, 16.16bit fixed point */
|
||
|
int mix_s8m_to_s32m_1616bit(s32 *dest, int nSamples, MOD_VOICEINFO16 *vinfo, u8 mainvol) {
|
||
|
|
||
|
int k;
|
||
|
s32 volume;
|
||
|
MIXER_TYPE playpos = vinfo->playpos;
|
||
|
MIXER_TYPE incval = vinfo->incval;
|
||
|
MIXER_TYPE loop_end = ((MIXER_TYPE)vinfo->sampleInfo->loop_end) << MIXER_SHIFT;
|
||
|
MIXER_TYPE loop_start = ((MIXER_TYPE)vinfo->sampleInfo->loop_start) << MIXER_SHIFT;
|
||
|
BOOL looped = vinfo->sampleInfo->looped;
|
||
|
BOOL forward = vinfo->forward;
|
||
|
BOOL pingpong = vinfo->sampleInfo->pingpong;
|
||
|
s8 *sampledata = vinfo->sampleInfo->sampledata;
|
||
|
|
||
|
if (!vinfo->playing)
|
||
|
return nSamples;
|
||
|
|
||
|
volume = ((s32)vinfo->volume * (s32)mainvol * (s32)vinfo->envVolume) >> 12;
|
||
|
|
||
|
for (k = 0; k < nSamples; k++) {
|
||
|
|
||
|
s32 value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
dest[k] += value * volume;
|
||
|
DO_LOOPING;
|
||
|
}
|
||
|
|
||
|
vinfo->playpos = playpos;
|
||
|
vinfo->forward = forward;
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
/* Mix s16 mono -> s32 mono, 16.16bit fixed point */
|
||
|
int mix_s16m_to_s32m_1616bit(s32 *dest, int nSamples, MOD_VOICEINFO16 *vinfo, u8 mainvol) {
|
||
|
|
||
|
int k;
|
||
|
s32 volume;
|
||
|
MIXER_TYPE playpos = vinfo->playpos;
|
||
|
MIXER_TYPE incval = vinfo->incval;
|
||
|
MIXER_TYPE loop_end = ((MIXER_TYPE)vinfo->sampleInfo->loop_end) << MIXER_SHIFT;
|
||
|
MIXER_TYPE loop_start = ((MIXER_TYPE)vinfo->sampleInfo->loop_start) << MIXER_SHIFT;
|
||
|
BOOL looped = vinfo->sampleInfo->looped;
|
||
|
BOOL forward = vinfo->forward;
|
||
|
BOOL pingpong = vinfo->sampleInfo->pingpong;
|
||
|
s16 *sampledata = vinfo->sampleInfo->sampledata;
|
||
|
|
||
|
if (!vinfo->playing)
|
||
|
return nSamples;
|
||
|
|
||
|
volume = ((s32)vinfo->volume * (s32)mainvol * (s32)vinfo->envVolume) >> 12;
|
||
|
|
||
|
for (k = 0; k <nSamples; k++) {
|
||
|
|
||
|
s32 value = (s32)((s16*)sampledata)[playpos >> MIXER_SHIFT];
|
||
|
dest[k] += value * volume;
|
||
|
DO_LOOPING;
|
||
|
}
|
||
|
|
||
|
vinfo->playpos = playpos;
|
||
|
vinfo->forward = forward;
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
/* Mix s8 mono -> s32 stereo, 16.16bit fixed point */
|
||
|
int mix_s8m_to_s32s_1616bit(s32 *dest, int nSamples, MOD_VOICEINFO16 *vinfo, u8 mainvol) {
|
||
|
|
||
|
int k;
|
||
|
s32 volume;
|
||
|
u8 lvolume, rvolume;
|
||
|
MIXER_TYPE playpos = vinfo->playpos;
|
||
|
MIXER_TYPE incval = vinfo->incval;
|
||
|
MIXER_TYPE loop_end = ((MIXER_TYPE)vinfo->sampleInfo->loop_end) << MIXER_SHIFT;
|
||
|
MIXER_TYPE loop_start = ((MIXER_TYPE)vinfo->sampleInfo->loop_start) << MIXER_SHIFT;
|
||
|
BOOL looped = vinfo->sampleInfo->looped;
|
||
|
BOOL forward = vinfo->forward;
|
||
|
BOOL pingpong = vinfo->sampleInfo->pingpong;
|
||
|
s8 * sampledata = vinfo->sampleInfo->sampledata;
|
||
|
s32 panning;
|
||
|
|
||
|
int mxamount = nSamples >> 3;
|
||
|
int mxrest = nSamples & ((1 << 3) - 1);
|
||
|
|
||
|
if (!vinfo->playing)
|
||
|
return nSamples;
|
||
|
|
||
|
volume = ((s32)vinfo->volume * (s32)mainvol * (s32)vinfo->envVolume) >> 12;
|
||
|
|
||
|
panning = ((s32)(vinfo->panning >> 2) - 32) + ((s32)vinfo->envPanning - 32);
|
||
|
if (panning > 32)
|
||
|
panning = 32;
|
||
|
if (panning < -32)
|
||
|
panning = -32;
|
||
|
panning += 32;
|
||
|
|
||
|
lvolume = (((u32)64 - panning) * volume) >> 6;
|
||
|
rvolume = (((u32)panning) * volume) >> 6;
|
||
|
|
||
|
for (k = 0; k < mxamount; k++) {
|
||
|
|
||
|
s32 value;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
}
|
||
|
|
||
|
for (k = 0; k < mxrest; k++) {
|
||
|
|
||
|
s32 value;
|
||
|
|
||
|
value = ((s32)(s16)((s8*)sampledata)[playpos >> MIXER_SHIFT]) << 8;
|
||
|
(*(dest++)) += value * lvolume;
|
||
|
(*(dest++)) += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
}
|
||
|
|
||
|
vinfo->playpos = playpos;
|
||
|
vinfo->forward = forward;
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
/* Mix s16 mono -> s32 stereo, 16.16bit fixed point */
|
||
|
int mix_s16m_to_s32s_1616bit(s32 *dest, int nSamples, MOD_VOICEINFO16 *vinfo, u8 mainvol) {
|
||
|
|
||
|
int k;
|
||
|
s32 volume;
|
||
|
u8 lvolume, rvolume;
|
||
|
MIXER_TYPE playpos = vinfo->playpos;
|
||
|
MIXER_TYPE incval = vinfo->incval;
|
||
|
MIXER_TYPE loop_end = ((MIXER_TYPE)vinfo->sampleInfo->loop_end) << MIXER_SHIFT;
|
||
|
MIXER_TYPE loop_start = ((MIXER_TYPE)vinfo->sampleInfo->loop_start) << MIXER_SHIFT;
|
||
|
BOOL looped = vinfo->sampleInfo->looped;
|
||
|
BOOL forward = vinfo->forward;
|
||
|
BOOL pingpong = vinfo->sampleInfo->pingpong;
|
||
|
s16 * sampledata = vinfo->sampleInfo->sampledata;
|
||
|
|
||
|
if (!vinfo->playing)
|
||
|
return nSamples;
|
||
|
|
||
|
volume = ((s32)vinfo->volume * (s32)mainvol * (s32)vinfo->envVolume) >> 12;
|
||
|
|
||
|
lvolume = (((u32)64-(vinfo->panning >> 2))*volume) >> 6;
|
||
|
rvolume = (((u32)(vinfo->panning >> 2))*volume) >> 6;
|
||
|
|
||
|
for (k = 0; k < nSamples * 2; k += 2) {
|
||
|
|
||
|
s32 value = (s32)((s16*)sampledata)[playpos >> MIXER_SHIFT];
|
||
|
dest[k] += value * lvolume;
|
||
|
dest[k + 1] += value * rvolume;
|
||
|
DO_LOOPING;
|
||
|
}
|
||
|
|
||
|
vinfo->playpos = playpos;
|
||
|
vinfo->forward = forward;
|
||
|
|
||
|
return nSamples;
|
||
|
}
|
||
|
|
||
|
void clearbuf_s32(s32 *dest, int channels, int nSamples) {
|
||
|
|
||
|
int k;
|
||
|
int mxamount;
|
||
|
int mxrest;
|
||
|
|
||
|
mxamount = (nSamples * channels) >> 3;
|
||
|
mxrest = (nSamples * channels) & ((1 << 3) - 1);
|
||
|
|
||
|
for (k = 0; k < mxamount; k++) {
|
||
|
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
(*(dest++)) = 0;
|
||
|
}
|
||
|
|
||
|
for (k = 0; k < mxrest; k++) {
|
||
|
|
||
|
(*(dest++)) = 0;
|
||
|
}
|
||
|
|
||
|
/* for (k = 0; k < nSamples * channels; k++)
|
||
|
dest[k] = 0;*/
|
||
|
}
|
||
|
|
||
|
void copybuf_s32_to_s16(s16 *dest, s32 *src, int channels, int nSamples) {
|
||
|
|
||
|
int k;
|
||
|
|
||
|
for (k = 0; k < nSamples*channels; k++) {
|
||
|
|
||
|
s32 value = src[k] >> 8;
|
||
|
|
||
|
if (value < -32768)
|
||
|
value = -32768;
|
||
|
else if (value > 32767)
|
||
|
value = 32767;
|
||
|
|
||
|
dest[k] = (s16)value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define CLIP_S32(a) \
|
||
|
if (a < -32768) a = 32768; else if (a > 32767) a = 32767;
|
||
|
|
||
|
void copybuf_s32_to_u16(u16 *dest, s32 *src, int channels, int nSamples) {
|
||
|
|
||
|
int k;
|
||
|
int mxamount;
|
||
|
int mxrest;
|
||
|
|
||
|
mxamount = (nSamples * channels) >> 3;
|
||
|
mxrest = (nSamples * channels) & ((1 << 3) - 1);
|
||
|
|
||
|
for (k = 0; k < mxamount; k++) {
|
||
|
|
||
|
s32 value;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
}
|
||
|
|
||
|
for (k = 0; k < mxrest; k++) {
|
||
|
|
||
|
s32 value;
|
||
|
|
||
|
value = (*(src++)) >> 7;
|
||
|
CLIP_S32(value);
|
||
|
(*(dest++)) = ((u16)(s16)value) ^ 0x8000;
|
||
|
}
|
||
|
|
||
|
/* for (k=0; k<nSamples*channels; k++)
|
||
|
{
|
||
|
s32 value = src[k]>>7;
|
||
|
if (value<-32768)
|
||
|
value = -32768;
|
||
|
else
|
||
|
if (value>32767)
|
||
|
value = 32767;
|
||
|
dest[k] = ((u16)(s16)value)^0x8000;
|
||
|
}*/
|
||
|
}
|
||
|
|
||
|
void copybuf_s32_to_s8(s8 *dest, s32 *src, int channels, int nSamples) {
|
||
|
|
||
|
int k;
|
||
|
|
||
|
for (k = 0; k < nSamples * channels; k++) {
|
||
|
|
||
|
s32 value = src[k] >> 16;
|
||
|
|
||
|
if (value < -128)
|
||
|
value = -128;
|
||
|
else if (value > 127)
|
||
|
value = 127;
|
||
|
dest[k] = (s8)value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void copybuf_s32_to_u8(u8 *dest, s32 *src, int channels, int nSamples) {
|
||
|
|
||
|
int k;
|
||
|
|
||
|
for (k = 0; k < nSamples * channels; k++) {
|
||
|
|
||
|
s32 value = src[k] >> 16;
|
||
|
|
||
|
if (value < -128)
|
||
|
value = -128;
|
||
|
else if (value > 127)
|
||
|
value = 127;
|
||
|
dest[k] = ((u8)(s8)value) ^ 0x80;
|
||
|
}
|
||
|
}
|