xbox-kernel/private/ntos/ani2/DEV.C
2020-09-30 17:17:25 +02:00

692 lines
16 KiB
C

/*************************************************************************
* *
* This file contains the tables and definitions for *
* the synthesis specific DEVice *
* The device tables are in devtab.c *
**************************************************************************
*
* The following variables and tables must be defined:
*
* max_tracks: 1 byte, max # of synthesis channels
* dev_init: function called to initialize device
* do_watchdog function called to kick watchdog timer
* dtimer_int function called to disable timer interrupt
* etimer_int function called to enable timer interrupt
* send_dev_function:
* function called to send a byte of data to the synthesis
* device (sound call callable)
* The data is in the global, "a_value" and the address is
* in the global, "b_value."
**************************************************************************/
#define _base_
extern struct DSPpatch *Patches[];
extern unsigned short Noise8192[];
#include <dsound.h>
#include "sosdsp.h"
#include "sos.h"
#include "bootsnd.h"
#include <xtl.h>
#include "dsptables.h"
#define MAX_BUFFERS 16
#ifdef STARTUPANIMATION
#pragma data_seg("INIT_RW")
#pragma code_seg("INIT")
#pragma bss_seg("INIT_RW")
#pragma const_seg("INIT_RD")
#pragma comment(linker, "/merge:INIT_RD=INIT")
#pragma comment(linker, "/merge:INIT_RW=INIT")
#endif
LPDIRECTSOUND8 m_pDSound; // DirectSound object
LPDIRECTSOUNDBUFFER8 m_pDSBuffer[MAX_BUFFERS]; // DirectSoundBuffer
extern WCHAR StringBuffer[];
#define MIN(a,b) (((signed) a) < ((signed) b) ? (a) : (b))
/*
* track_status has the necessary items to restore the state of
* a track after a track of a higher level on the same channel
* ends
*/
#define MAX_TRACKS 16
#define MAX_PROCESSES 30
#define MAX_LEVELS 2
uchar channel_level[MAX_TRACKS];/* current level for each chan*/
struct track_info track_status[(MAX_LEVELS) * MAX_TRACKS];
struct process queue_list[MAX_PROCESSES]; /* pre-allocated process packets */
extern struct sound * _base_ current_call; /* pointer to current sound call */
extern uchar sound_call_table;
const unsigned short max_processes = MAX_PROCESSES;
extern uchar a_value, b_value;
unsigned int dsp_address;
unsigned int dsp_data;
extern ushort value_16_bit;
extern uchar current_channel;
extern uchar master_music_volume; /* main attenuation for music */
extern uchar master_effect_volume; /* main attenuation for f/x */
extern uchar music_atten; /* music attenuation */
extern uchar init_call;
extern uchar current_level; /* global level of current process */
extern struct track_info * _base_ ti; /* track info pointer */
extern uchar pan_table[]; /* panning table (8-bit) */
void put_dsp(void);
extern reset_dsp();
void init_dsp(void);
void put_fifo(unsigned char);
const unsigned char max_tracks = MAX_TRACKS;
extern void (* const call_fcns[])();
int volume_dsp(uchar, uchar, uchar *,uchar);
int silence_dsp(uchar);
int note_on_dsp();
int slur_dsp();
int note_off_dsp();
int patch_dsp(unsigned short);
int pan_dsp(uchar , signed char, uchar *);
int vp_filter();
int (* const filter_functions[])() = {
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter,
vp_filter
};
int (* const silence_functions[])() = {
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
silence_dsp,
};
/**************************************************************************
* *
* The note_on functions turn a note on. They assume that *
* the global, "a_value" has the current channel # and that *
* the global "value_16_bit" has the 16 bit pitch (iiiiiiii.ffffffff *
* and "b_value" has the integer part of the pitch *
*************************************************************************/
int (* const note_on_functions[])() = {
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
note_on_dsp,
};
int (* const slur_functions[])() = {
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
slur_dsp,
};
/*************************************************************************
* *
* The note_off functions turn a note off. They assume that *
* the global, "a_value" has the current channel. *
*************************************************************************/
int (* const note_off_functions[])() = {
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
note_off_dsp,
};
int (* const patch_functions[]) () = {
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
patch_dsp,
};
int (* const volume_functions[])() = {
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
volume_dsp,
};
int (* const pan_functions[])() = {
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
pan_dsp,
};
int (* const user_1_var_evf_functions[])() = {
pan_dsp
};
int (* const user_2_var_evf_functions[])() = {
pan_dsp
};
//
// write data from global var dsp_data to x memory space "dsp_address"
//
void put_dsp()
{
// LPVOID pvXramBuffer;
// pvXramBuffer = (LPVOID) (dsp_address);
// memcpy(pvXramBuffer,pvData,dwDataSize);
// *(PDWORD) (GPXMEM + dsp_address) = dsp_data;
}
WriteDSPDatablock
(
DWORD dwDSPAddress,
LPCVOID pvData,
DWORD dwDataSize
)
{
LPVOID pvXramBuffer;
//
// poke directly the XRAM offset
//
pvXramBuffer = (LPVOID) (GPXMEM + dwDSPAddress);
memcpy(pvXramBuffer,pvData,dwDataSize);
return 1;
}
ReadDSPDatablock
(
DWORD dwDSPAddress,
LPVOID pvData,
DWORD dwDataSize
)
{
LPVOID pvXramBuffer;
//
// copy fx data
//
pvXramBuffer = (LPVOID) (GPXMEM + dwDSPAddress);
memcpy(pvData,pvXramBuffer,dwDataSize);
return 1;
}
ReadDSPProgblock
(
DWORD dwDSPAddress,
LPVOID pvData,
DWORD dwDataSize
)
{
LPVOID pvXramBuffer;
//
// copy fx data
//
pvXramBuffer = (LPVOID) (GPPMEM + dwDSPAddress);
memcpy(pvData,pvXramBuffer,dwDataSize);
return 1;
}
// return dsp data
int get_dsp(unsigned int addr)
{
// return( (*PDWORD) (GPXMEM + dsp_address) );
return(1);
}
silence_dsp(unsigned char chan)
{
return(1);
}
note_on_dsp()
{
DWORD dwFreq;
struct DSPpatch *addr;
#if DBG
// dwFreq = pitch_table_dsp[value_16_bit>>8];
// swprintf( StringBuffer, L"Current Pitch: 0x%x", dwFreq);
#endif
dwFreq = (DWORD) ( ((value_16_bit >> 8) - 60) * (4096/12) );
dwFreq += ((((DWORD) value_16_bit & 0xff) * 341) / 255);
// IDirectSoundBuffer_StopEx(m_pDSBuffer[current_channel], 0, DSBSTOPEX_ENVELOPE);
IDirectSoundBuffer_SetPitch(m_pDSBuffer[current_channel], dwFreq);
addr = Patches[ti->patch];
if (addr->LoopEnable)
IDirectSoundBuffer_Play(m_pDSBuffer[current_channel], 0,0,DSBPLAY_LOOPING);
else
IDirectSoundBuffer_Play(m_pDSBuffer[current_channel], 0,0,0);
return(1);
}
slur_dsp()
{
DWORD dwFreq;
dwFreq = (DWORD) ( ((value_16_bit >> 8) - 60) * (4096/12) );
dwFreq += ((((DWORD) value_16_bit & 0xff) * 341) / 255);
#if DBG
// swprintf( StringBuffer, L"Current Pitch Slur: 0x%x", dwFreq);
#endif
IDirectSoundBuffer_SetPitch(m_pDSBuffer[current_channel], dwFreq);
return(1);
}
note_off_dsp()
{
IDirectSoundBuffer_StopEx(m_pDSBuffer[current_channel], 0, DSBSTOPEX_ENVELOPE);
return(1);
}
vp_filter()
{
DSFILTERDESC fdesc;
fdesc.dwMode = DSFILTER_MODE_DLS2;
fdesc.dwQCoefficient = 0;
fdesc.adwCoefficients[0] = ti->filtercutoff + 32768;
fdesc.adwCoefficients[1] = ti->filterres;
fdesc.adwCoefficients[2] = ti->filtercutoff + 32768;
fdesc.adwCoefficients[3] = ti->filterres;
IDirectSoundBuffer_SetFilter(m_pDSBuffer[current_channel], &fdesc);
return(1);
}
patch_dsp(unsigned short pat)
{
struct DSPpatch *addr;
addr = Patches[pat];
IDirectSoundBuffer_SetEG(m_pDSBuffer[current_channel], addr->lpAmpEnvelope);
IDirectSoundBuffer_SetEG(m_pDSBuffer[current_channel], addr->lpMultiEnvelope);
IDirectSoundBuffer_SetBufferData(m_pDSBuffer[current_channel], addr->Start, addr->Length );
IDirectSoundBuffer_SetLoopRegion( m_pDSBuffer[current_channel],0, addr->Length );
IDirectSoundBuffer_SetCurrentPosition(m_pDSBuffer[current_channel], 0 );
return(1);
}
pan_dsp(uchar chan, signed char pan, uchar *patch)
{
uchar mod;
unsigned int vol_mul;
unsigned int tmp;
char tmp_pan;
vol_mul = 0x7fff;
if (current_level >= 1) {
/* mod = master_effect_volume;*/
// vol_mul = volume_table_dsp[master_music_volume];
}
else {
/* mod = 0;*/
// tmp = volume_table_dsp[music_atten];
// vol_mul = volume_table_dsp[master_music_volume];
// vol_mul = (long)((long)tmp * (long)vol_mul) >>15;
}
mod = 0;
tmp_pan = ti->pan >> 3;
tmp_pan += 16; /* set range 0 - 31 */
tmp = 1;
// tmp = volume_table_dsp[MIN(127,ti->volume + mod)];
tmp = (long)((long)tmp * (long)vol_mul) >>15;
/* tmp >>= 7;*/
dsp_data = (long) ((long)tmp * (long)pan_table[tmp_pan]) >> 7;
/* dsp_data = (char)tmp * pan_table[tmp_pan];*/
// a_value = VOLUME_L_ADDRESS(chan);
put_dsp();
dsp_data = (long) ((long)tmp * (long)pan_table[31 - tmp_pan]) >> 7;
/* dsp_data = (char)tmp * pan_table[31 - tmp_pan];*/
// a_value = VOLUME_R_ADDRESS(chan);
put_dsp();
return(1);
}
// initialize stuff for the dsp.
// write sine wave into high x memory.
// also create 16 dsound buffers that we'll use
// for our sounds.
static long holdrand = 1L;
void __cdecl srand(unsigned int seed)
{
holdrand = (long)seed;
}
int __cdecl rand(void)
{
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
dev_init()
{
DSBUFFERDESC dsbdesc;
WAVEFORMATEX wfFirst;
DWORD dwMixBinMask = DSMIXBIN_FRONT_LEFT | DSMIXBIN_FRONT_RIGHT | DSMIXBIN_FXSEND_0;
long lVolumes[3];
int j;
double dtmp;
double FMc = 4.0;
double FMm = 2.0;
int i;
srand(1003);
for (i = 0; i < 8192; i++) {
Noise8192[i] = (unsigned short) rand();
}
for (i = 0; i < 128; i++) {
Sin128[i] = (unsigned short)(32767*sin(2.0*3.14159*(double)i/128.0));
}
j = 0;
for (i = 0; i < 32768; i++) {
if (i < 16384)
j++;
else
j--;
dtmp = (double)j/16384.0 * sin(FMm * 2.0*3.14159*(double)i/128.0);
FM32768[i] = (unsigned short)(32767*sin(dtmp + FMc * 2.0*3.14159*(double)i/128.0));
}
for (i = 0; i < 128; i++) { // create sawtooth wave
Saw128[i] = (unsigned short) (65536 * ((float)(i-64) /128.0));
}
for (i = 0; i < 0x5540; i++) { // size of glock sound..make 16-bit
ThunEl16[i] = (ThunEl16Data[i]) << 8;
}
for (i = 0,j=0x5540; i < 0x5540; i++,j--) { // size of glock sound..make 16-bit
ReverseThunEl16[i] = ThunEl16[j];
}
for (i = 0; i < 3768; i++) { // size of glock sound..make 16-bit
Glock[i] = (GlockData[i]^0x80) << 8;
}
for (i = 0; i < 6719; i++) { // size of glock sound..make 16-bit
Bubble[i] = (BubbleData[i]^0x80) << 8;
}
if( FAILED( DirectSoundCreate( NULL, &m_pDSound, NULL ) ) )
return (0);
ZeroMemory( &dsbdesc, sizeof( DSBUFFERDESC ) );
dsbdesc.dwSize = sizeof( DSBUFFERDESC );
wfFirst.wFormatTag = WAVE_FORMAT_PCM;
wfFirst.nChannels = 1;
wfFirst.nSamplesPerSec = 48000;
wfFirst.wBitsPerSample = 16;
wfFirst.nBlockAlign = wfFirst.nChannels * wfFirst.wBitsPerSample/8;
wfFirst.nAvgBytesPerSec = wfFirst.nSamplesPerSec * wfFirst.nBlockAlign;
dsbdesc.dwFlags = 0;
dsbdesc.dwBufferBytes = 0;
dsbdesc.lpwfxFormat = &wfFirst;
dsbdesc.dwMixBinMask = dwMixBinMask;
for (i = 0; i < MAX_BUFFERS; i++) {
if (i%2) {
lVolumes[0] = -600;
lVolumes[1] = 0;
lVolumes[2] = -2800;
dwMixBinMask = DSMIXBIN_FRONT_LEFT | DSMIXBIN_FRONT_RIGHT;
dsbdesc.dwMixBinMask = dwMixBinMask;
}
else {
lVolumes[0] = 0;
lVolumes[1] = -600;
lVolumes[2] = -2800;
dwMixBinMask = DSMIXBIN_FRONT_LEFT | DSMIXBIN_FRONT_RIGHT;
dsbdesc.dwMixBinMask = dwMixBinMask;
}
if ((i == 3) || (i == 5)) {
lVolumes[0] = 0;
lVolumes[1] = -100;
lVolumes[2] = 00;
dwMixBinMask = DSMIXBIN_FRONT_LEFT | DSMIXBIN_FRONT_RIGHT | DSMIXBIN_FXSEND_0;
dsbdesc.dwMixBinMask = dwMixBinMask;
}
if( FAILED( DirectSoundCreateBuffer( &dsbdesc, &m_pDSBuffer[i]) ) )
return E_FAIL;
IDirectSoundBuffer_SetMixBinVolumes(m_pDSBuffer[i], dwMixBinMask, lVolumes);
}
// ReadDSPDatablock(0xa00*4, databack, sizeof(databack) );
put_fifo(0x1);
return(1);
}
//
// free dsound buffers and dsound object we created
//
dev_cleanup()
{
int i;
for (i = 0; i < MAX_BUFFERS; i++) {
IDirectSoundBuffer_Release(m_pDSBuffer[i]);
}
IDirectSound_Release(m_pDSound);
}
do_watchdog()
{
}
dtimer_int()
{
}
etimer_int()
{
}
send_dev_function()
{
}
/*************************************************************************
* *
* Adjust the volume of that patch, "patch_addr" on channel, *
* "chan" by the amount volume + whatever the global volume is *
* for "level" *
* *
*************************************************************************/
volume_dsp(
uchar op_level,
uchar sound_level,
uchar *patch_addr,
uchar chan)
{
IDirectSoundBuffer_SetVolume(m_pDSBuffer[current_channel], (-1*op_level*30) + 200);
return(1);
}
call_user_function()
{
}
extern f_end();
user_silence_function()
{
#if DBG
// swprintf( StringBuffer, L"Current Sound: %S", "SilenceFunction");
#endif
}
uchar pan_table[] = {
1,2,3,4,5,6,7,8
};