mirror of https://github.com/PrimeDecomp/prime.git
parent
411a21699f
commit
66fb9aceab
|
@ -380,7 +380,7 @@ lbl_803B13B4:
|
|||
/* 803B13D4 003AE334 93 63 02 14 */ stw r27, 0x214(r3)
|
||||
/* 803B13D8 003AE338 80 0D AE 78 */ lwz r0, synthVoice@sda21(r13)
|
||||
/* 803B13DC 003AE33C 7C 60 CA 14 */ add r3, r0, r25
|
||||
/* 803B13E0 003AE340 4B FE 97 01 */ bl synthkeystateupdate
|
||||
/* 803B13E0 003AE340 4B FE 97 01 */ bl synthKeyStateUpdate
|
||||
lbl_803B13E4:
|
||||
/* 803B13E4 003AE344 3B 39 04 04 */ addi r25, r25, 0x404
|
||||
/* 803B13E8 003AE348 3B 9C 00 01 */ addi r28, r28, 1
|
||||
|
@ -590,7 +590,7 @@ lbl_803B169C:
|
|||
/* 803B16BC 003AE61C 93 83 02 14 */ stw r28, 0x214(r3)
|
||||
/* 803B16C0 003AE620 80 0D AE 78 */ lwz r0, synthVoice@sda21(r13)
|
||||
/* 803B16C4 003AE624 7C 60 CA 14 */ add r3, r0, r25
|
||||
/* 803B16C8 003AE628 4B FE 94 19 */ bl synthkeystateupdate
|
||||
/* 803B16C8 003AE628 4B FE 94 19 */ bl synthKeyStateUpdate
|
||||
lbl_803B16CC:
|
||||
/* 803B16CC 003AE62C 3B 39 04 04 */ addi r25, r25, 0x404
|
||||
/* 803B16D0 003AE630 3B BD 00 01 */ addi r29, r29, 1
|
||||
|
|
|
@ -110,7 +110,7 @@ inpAuxB:
|
|||
.skip 0x480
|
||||
.global inpAuxA
|
||||
inpAuxA:
|
||||
.skip 0x484
|
||||
.skip 0x480
|
||||
|
||||
.section .sbss
|
||||
.balign 8
|
||||
|
@ -2289,8 +2289,8 @@ synthForceLowPrecisionUpdate:
|
|||
/* 8039AAD8 00397A38 38 21 00 10 */ addi r1, r1, 0x10
|
||||
/* 8039AADC 00397A3C 4E 80 00 20 */ blr
|
||||
|
||||
.global synthkeystateupdate
|
||||
synthkeystateupdate:
|
||||
.global synthKeyStateUpdate
|
||||
synthKeyStateUpdate:
|
||||
/* 8039AAE0 00397A40 94 21 FF F0 */ stwu r1, -0x10(r1)
|
||||
/* 8039AAE4 00397A44 7C 08 02 A6 */ mflr r0
|
||||
/* 8039AAE8 00397A48 38 80 00 02 */ li r4, 2
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
.include "macros.inc"
|
||||
|
||||
.section .bss
|
||||
.balign 8
|
||||
|
||||
.global vs
|
||||
vs:
|
||||
.skip 0x950
|
||||
|
||||
.section .text, "ax"
|
||||
|
||||
.global vsInit
|
||||
|
|
|
@ -1020,7 +1020,7 @@ lbl_803A3308:
|
|||
/* 803A330C 003A026C 7F C3 F3 78 */ mr r3, r30
|
||||
/* 803A3310 003A0270 60 00 00 20 */ ori r0, r0, 0x20
|
||||
/* 803A3314 003A0274 90 1E 01 18 */ stw r0, 0x118(r30)
|
||||
/* 803A3318 003A0278 4B FF 77 C9 */ bl synthkeystateupdate
|
||||
/* 803A3318 003A0278 4B FF 77 C9 */ bl synthKeyStateUpdate
|
||||
lbl_803A331C:
|
||||
/* 803A331C 003A027C 80 01 00 24 */ lwz r0, 0x24(r1)
|
||||
/* 803A3320 003A0280 83 E1 00 1C */ lwz r31, 0x1c(r1)
|
||||
|
@ -4331,7 +4331,7 @@ lbl_803A6150:
|
|||
/* 803A6154 003A30B4 7F E3 FB 78 */ mr r3, r31
|
||||
/* 803A6158 003A30B8 60 00 00 80 */ ori r0, r0, 0x80
|
||||
/* 803A615C 003A30BC 90 1F 01 18 */ stw r0, 0x118(r31)
|
||||
/* 803A6160 003A30C0 4B FF 49 81 */ bl synthkeystateupdate
|
||||
/* 803A6160 003A30C0 4B FF 49 81 */ bl synthKeyStateUpdate
|
||||
/* 803A6164 003A30C4 48 00 09 A0 */ b lbl_803A6B04
|
||||
.global lbl_803A6168
|
||||
lbl_803A6168:
|
||||
|
@ -5633,7 +5633,7 @@ lbl_803A7240:
|
|||
/* 803A724C 003A41AC 7F 84 E3 78 */ mr r4, r28
|
||||
/* 803A7250 003A41B0 54 06 0F FE */ srwi r6, r0, 0x1f
|
||||
/* 803A7254 003A41B4 7E 25 8B 78 */ mr r5, r17
|
||||
/* 803A7258 003A41B8 48 00 0B ED */ bl voiceAllocateFind
|
||||
/* 803A7258 003A41B8 48 00 0B ED */ bl voiceAllocate
|
||||
/* 803A725C 003A41BC 7C 7D 1B 78 */ mr r29, r3
|
||||
/* 803A7260 003A41C0 3C 1D 00 01 */ addis r0, r29, 1
|
||||
/* 803A7264 003A41C4 28 00 FF FF */ cmplwi r0, 0xffff
|
||||
|
|
|
@ -2,45 +2,68 @@
|
|||
|
||||
.section .bss
|
||||
.balign 8
|
||||
.global vidList
|
||||
vidList:
|
||||
.skip 0xF00
|
||||
.global synth_last_fxstarted
|
||||
synth_last_fxstarted:
|
||||
.obj vidList, local
|
||||
.skip 0x800
|
||||
.endobj vidList
|
||||
|
||||
.obj voicePrioSortVoices
|
||||
.skip 0x100
|
||||
.endobj voicePrioSortVoices
|
||||
|
||||
.obj voicePrioSortVoicesRoot
|
||||
.skip 0x100
|
||||
.endobj voicePrioSortVoicesRoot
|
||||
|
||||
.obj voicePrioSortRootList
|
||||
.skip 0x400
|
||||
.endobj voicePrioSortRootList
|
||||
|
||||
.obj voiceList
|
||||
.skip 0x100
|
||||
.endobj voiceList
|
||||
|
||||
.obj synth_last_fxstarted, local
|
||||
.skip 0x40
|
||||
.global synth_last_started
|
||||
synth_last_started:
|
||||
.endobj synth_last_fxstarted
|
||||
|
||||
.obj synth_last_started, local
|
||||
.skip 0x80
|
||||
.global vs
|
||||
vs:
|
||||
.skip 0x950
|
||||
.endobj synth_last_started
|
||||
|
||||
.section .sbss
|
||||
.balign 8
|
||||
.global vidFree
|
||||
vidFree:
|
||||
|
||||
.obj vidFree, local
|
||||
.skip 0x4
|
||||
.global vidRoot
|
||||
vidRoot:
|
||||
.endobj vidFree
|
||||
|
||||
.obj vidRoot, local
|
||||
.skip 0x4
|
||||
.global vidCurrentId
|
||||
vidCurrentId:
|
||||
.endobj vidRoot
|
||||
|
||||
.obj vidCurrentId, local
|
||||
.skip 0x4
|
||||
.global voicePrioSortRootListRoot
|
||||
voicePrioSortRootListRoot:
|
||||
.endobj vidCurrentId
|
||||
|
||||
.obj voicePrioSortRootListRoot
|
||||
.skip 0x2
|
||||
.global voiceMusicRunning
|
||||
voiceMusicRunning:
|
||||
.endobj voicePrioSortRootListRoot
|
||||
|
||||
.obj voiceMusicRunning
|
||||
.skip 0x1
|
||||
.global voiceFxRunning
|
||||
voiceFxRunning:
|
||||
.endobj voiceMusicRunning
|
||||
|
||||
.obj voiceFxRunning
|
||||
.skip 0x1
|
||||
.global voiceListInsert
|
||||
voiceListInsert:
|
||||
.endobj voiceFxRunning
|
||||
|
||||
.obj voiceListInsert
|
||||
.skip 0x1
|
||||
.global voiceListRoot
|
||||
voiceListRoot:
|
||||
.skip 0x7
|
||||
.endobj voiceListInsert
|
||||
|
||||
.obj voiceListRoot
|
||||
.skip 0x1
|
||||
.endobj voiceListRoot
|
||||
|
||||
.section .text, "ax"
|
||||
|
||||
|
@ -637,8 +660,8 @@ lbl_803A7E30:
|
|||
/* 803A7E3C 003A4D9C 38 21 00 10 */ addi r1, r1, 0x10
|
||||
/* 803A7E40 003A4DA0 4E 80 00 20 */ blr
|
||||
|
||||
.global voiceAllocateFind
|
||||
voiceAllocateFind:
|
||||
.global voiceAllocate
|
||||
voiceAllocate:
|
||||
/* 803A7E44 003A4DA4 94 21 FF D0 */ stwu r1, -0x30(r1)
|
||||
/* 803A7E48 003A4DA8 7C 08 02 A6 */ mflr r0
|
||||
/* 803A7E4C 003A4DAC 90 01 00 34 */ stw r0, 0x34(r1)
|
||||
|
@ -1282,7 +1305,7 @@ voiceBlock:
|
|||
/* 803A8728 003A5688 93 C1 00 18 */ stw r30, 0x18(r1)
|
||||
/* 803A872C 003A568C 93 A1 00 14 */ stw r29, 0x14(r1)
|
||||
/* 803A8730 003A5690 7C 7D 1B 78 */ mr r29, r3
|
||||
/* 803A8734 003A5694 4B FF F7 11 */ bl voiceAllocateFind
|
||||
/* 803A8734 003A5694 4B FF F7 11 */ bl voiceAllocate
|
||||
/* 803A8738 003A5698 7C 7E 1B 78 */ mr r30, r3
|
||||
/* 803A873C 003A569C 3C 1E 00 01 */ addis r0, r30, 1
|
||||
/* 803A8740 003A56A0 28 00 FF FF */ cmplwi r0, 0xffff
|
||||
|
|
|
@ -920,19 +920,19 @@ LIBS = [
|
|||
{
|
||||
"lib": "musyx",
|
||||
#"mw_version": "1.2.5",
|
||||
#"cflags": "-nodefaults -fp hard -O0 -maxerrors 1 -enum int -str reuse -nosyspath -i include -i libc -use_lmw_stmw on -inline off",
|
||||
#"cflags": "-proc gecko -fp hard -nodefaults -nosyspath -i include -i libc -g -sym on -D_DEBUG=1 -enum int -use_lmw_stmw on",
|
||||
"mw_version": "1.3.2",
|
||||
"cflags": "$cflags_musyx",
|
||||
"host": False,
|
||||
"objects": [
|
||||
"musyx/runtime/seq",
|
||||
"musyx/runtime/synth",
|
||||
["musyx/runtime/synth", False],
|
||||
["musyx/runtime/seq_api", True],
|
||||
["musyx/runtime/snd_synthapi", True, {"add_to_all": False}],
|
||||
["musyx/runtime/stream", False],
|
||||
"musyx/runtime/synthdata",
|
||||
"musyx/runtime/synthmacros",
|
||||
"musyx/runtime/synthvoice",
|
||||
["musyx/runtime/synthvoice", False],
|
||||
["musyx/runtime/synth_ac", True],
|
||||
"musyx/runtime/synth_adsr",
|
||||
["musyx/runtime/synth_vsamples", False],
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
#define _MUSYX_ASSERT
|
||||
|
||||
extern void OSPanic(const char* file, int line, const char* msg, ...);
|
||||
extern void OSReport(const char* msg, ...);
|
||||
|
||||
#ifndef ASSERT
|
||||
#ifdef _DEBUG
|
||||
#define ASSERT(cond) \
|
||||
do { \
|
||||
if (!cond) { \
|
||||
OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \
|
||||
} \
|
||||
} while (0)
|
||||
#define ASSERT(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define ASSERT(cond)
|
||||
#endif
|
||||
|
@ -18,19 +19,19 @@ extern void OSPanic(const char* file, int line, const char* msg, ...);
|
|||
|
||||
#ifndef ASSERT_MSG
|
||||
#ifdef _DEBUG
|
||||
#define ASSERT_MSG(cond, msg) \
|
||||
do { \
|
||||
if (!cond) { \
|
||||
OSPanic(__FILE__, __LINE__, msg); \
|
||||
} \
|
||||
} while (0)
|
||||
#define ASSERT_MSG(cond, msg) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
OSPanic(__FILE__, __LINE__, msg); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define ASSERT_MSG(cond, msg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MUSY_DEBUG
|
||||
#if _DEBUG
|
||||
#ifdef _DEBUG
|
||||
#define MUSY_DEBUG OSReport
|
||||
#else
|
||||
#define MUSY_DEBUG
|
||||
|
|
|
@ -15,6 +15,24 @@ typedef struct SND_STUDIO_INPUT {
|
|||
unsigned char srcStudio; // offset 0x3, size 0x1
|
||||
} SND_STUDIO_INPUT;
|
||||
|
||||
typedef struct SYNTH_VOICELIST {
|
||||
// total size: 0x4
|
||||
u8 prev; // offset 0x0, size 0x1
|
||||
u8 next; // offset 0x1, size 0x1
|
||||
u16 user; // offset 0x2, size 0x2
|
||||
} SYNTH_VOICELIST;
|
||||
extern SYNTH_VOICELIST voicePrioSortVoices[64];
|
||||
extern u8 voicePrioSortVoicesRoot[256];
|
||||
extern SYNTH_VOICELIST voicePrioSortVoices[64];
|
||||
|
||||
typedef struct SYNTH_ROOTLIST {
|
||||
// total size: 0x4
|
||||
unsigned short next; // offset 0x0, size 0x2
|
||||
unsigned short prev; // offset 0x2, size 0x2
|
||||
} SYNTH_ROOTLIST;
|
||||
|
||||
extern SYNTH_ROOTLIST voicePrioSortRootList[256];
|
||||
|
||||
typedef struct synthInfo {
|
||||
u32 mixFrq;
|
||||
u32 numSamples;
|
||||
|
@ -287,6 +305,19 @@ typedef struct SYNTH_QUEUE {
|
|||
u8 jobTabIndex;
|
||||
} SYNTH_QUEUE;
|
||||
|
||||
typedef enum {
|
||||
SYNTH_JOBTYPE_LOW = 0,
|
||||
SYNTH_JOBTYPE_ZERO = 1,
|
||||
SYNTH_JOBTYPE_EVENT = 2,
|
||||
} SYNTH_JOBTYPE;
|
||||
|
||||
typedef struct {
|
||||
// total size: 0xC
|
||||
SYNTH_QUEUE* lowPrecision; // offset 0x0, size 0x4
|
||||
SYNTH_QUEUE* event; // offset 0x4, size 0x4
|
||||
SYNTH_QUEUE* zeroOffset; // offset 0x8, size 0x4
|
||||
} SYNTH_JOBTAB;
|
||||
|
||||
typedef struct SYNTH_LFO {
|
||||
u32 time;
|
||||
u32 period;
|
||||
|
@ -294,6 +325,23 @@ typedef struct SYNTH_LFO {
|
|||
s16 lastValue;
|
||||
} SYNTH_LFO;
|
||||
|
||||
typedef struct SYNTHMasterFader {
|
||||
// total size: 0x30
|
||||
float volume; // offset 0x0, size 0x4
|
||||
float target; // offset 0x4, size 0x4
|
||||
float start; // offset 0x8, size 0x4
|
||||
float time; // offset 0xC, size 0x4
|
||||
float deltaTime; // offset 0x10, size 0x4
|
||||
float pauseVol; // offset 0x14, size 0x4
|
||||
float pauseTarget; // offset 0x18, size 0x4
|
||||
float pauseStart; // offset 0x1C, size 0x4
|
||||
float pauseTime; // offset 0x20, size 0x4
|
||||
float pauseDeltaTime; // offset 0x24, size 0x4
|
||||
unsigned long seqId; // offset 0x28, size 0x4
|
||||
unsigned char seqMode; // offset 0x2C, size 0x1
|
||||
unsigned char type; // offset 0x2D, size 0x1
|
||||
} SYNTHMasterFader;
|
||||
|
||||
typedef struct CTRL_SOURCE {
|
||||
u8 midiCtrl;
|
||||
u8 combine;
|
||||
|
@ -377,7 +425,7 @@ typedef struct SYNTH_VOICE {
|
|||
u32 parent;
|
||||
u32 id;
|
||||
VID_LIST* vidList;
|
||||
VID_LIST* vidListMaster;
|
||||
VID_LIST* vidMasterList;
|
||||
u16 allocId;
|
||||
u16 macroId;
|
||||
u8 keyGroup;
|
||||
|
@ -473,8 +521,36 @@ typedef struct SYNTH_VOICE {
|
|||
long mesgQueue[4]; // offset 0x3F0, size 0x10
|
||||
u16 curOutputVolume; // offset 0x400, size 0x2
|
||||
} SYNTH_VOICE;
|
||||
|
||||
typedef struct synthITDInfo {
|
||||
// total size: 0x2
|
||||
unsigned char music; // offset 0x0, size 0x1
|
||||
unsigned char sfx; // offset 0x1, size 0x1
|
||||
} synthITDInfo;
|
||||
|
||||
#pragma pop
|
||||
|
||||
typedef struct LAYER {
|
||||
// total size: 0xC
|
||||
unsigned short id; // offset 0x0, size 0x2
|
||||
unsigned char keyLow; // offset 0x2, size 0x1
|
||||
unsigned char keyHigh; // offset 0x3, size 0x1
|
||||
signed char transpose; // offset 0x4, size 0x1
|
||||
unsigned char volume; // offset 0x5, size 0x1
|
||||
signed short prioOffset; // offset 0x6, size 0x2
|
||||
unsigned char panning; // offset 0x8, size 0x1
|
||||
unsigned char reserved[3]; // offset 0x9, size 0x3
|
||||
} LAYER;
|
||||
|
||||
typedef struct KEYMAP {
|
||||
// total size: 0x8
|
||||
unsigned short id; // offset 0x0, size 0x2
|
||||
signed char transpose; // offset 0x2, size 0x1
|
||||
unsigned char panning; // offset 0x3, size 0x1
|
||||
signed short prioOffset; // offset 0x4, size 0x2
|
||||
unsigned char reserved[2]; // offset 0x6, size 0x2
|
||||
} KEYMAP;
|
||||
|
||||
typedef struct SAL_VOLINFO {
|
||||
// total size: 0x24
|
||||
float volL; // offset 0x0, size 0x4
|
||||
|
@ -584,8 +660,27 @@ extern SYNTH_VOICE* synthVoice;
|
|||
extern DSPvoice* dspVoice;
|
||||
typedef s32 (*SND_COMPARE)(u16*, u8*);
|
||||
|
||||
void dataInit(u32, s32); /* extern */
|
||||
void dataInitStack(); /* extern */
|
||||
typedef struct FX_TAB {
|
||||
// total size: 0xA
|
||||
unsigned short id; // offset 0x0, size 0x2
|
||||
unsigned short macro; // offset 0x2, size 0x2
|
||||
unsigned char maxVoices; // offset 0x4, size 0x1
|
||||
unsigned char priority; // offset 0x5, size 0x1
|
||||
unsigned char volume; // offset 0x6, size 0x1
|
||||
unsigned char panning; // offset 0x7, size 0x1
|
||||
unsigned char key; // offset 0x8, size 0x1
|
||||
unsigned char vGroup; // offset 0x9, size 0x1
|
||||
} FX_TAB;
|
||||
typedef struct FX_DATA {
|
||||
// total size: 0xE
|
||||
unsigned short num; // offset 0x0, size 0x2
|
||||
unsigned short reserverd; // offset 0x2, size 0x2
|
||||
struct FX_TAB fx[1]; // offset 0x4, size 0xA
|
||||
} FX_DATA;
|
||||
|
||||
void dataInit(u32, s32); /* extern */
|
||||
void dataInitStack(); /* extern */
|
||||
FX_TAB* dataGetFX(u16 fid);
|
||||
s32 hwInit(u32* frq, u16 numVoices, u16 numStudios, u32 flags); /* extern */
|
||||
void hwEnableIrq();
|
||||
void hwDisableIrq();
|
||||
|
@ -598,20 +693,21 @@ void hwExit();
|
|||
void dataExit();
|
||||
void s3dExit();
|
||||
void synthExit();
|
||||
u32 synthGetTicksPerSecond(u32 seconds);
|
||||
u32 synthGetTicksPerSecond(SYNTH_VOICE* svoice);
|
||||
u16 sndRand(void);
|
||||
s16 sndSin(u32 __x);
|
||||
s16 sndSin(u16 angle);
|
||||
u8* sndBSearch(u16* key, u8* subTab, s32 mainTab, s32 len, SND_COMPARE cmp);
|
||||
void sndConvertMs(u32* time);
|
||||
void sndConvertTicks(u32* out, u32 seconds);
|
||||
void sndConvertTicks(u32* out, SYNTH_VOICE* svoice);
|
||||
u32 sndConvert2Ms(u32 time);
|
||||
void hwActivateStudio(unsigned char studio, unsigned long isMaster, SND_STUDIO_TYPE type);
|
||||
void hwDeactivateStudio(u8);
|
||||
u32 hwIsActive(u32);
|
||||
|
||||
u32 sndGetPitch(u8 key, u32 sInfo);
|
||||
extern SND_HOOKS salHooks;
|
||||
extern u8 sndActive;
|
||||
extern s8 synthIdleWaitActive;
|
||||
extern u8 synthIdleWaitActive;
|
||||
extern SynthInfo synthInfo;
|
||||
typedef s32 (*SND_MESSAGE_CALLBACK)(u32, u32);
|
||||
typedef void (*SND_SOME_CALLBACK)();
|
||||
|
@ -662,7 +758,7 @@ typedef struct SND_STREAM_INFO {
|
|||
} SND_STREAM_INFO;
|
||||
|
||||
void streamOutputModeChanged();
|
||||
|
||||
unsigned short inpGetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set);
|
||||
/* TODO: Figure out what `unk` is */
|
||||
void hwSetSRCType(u32 v, u8 salSRCType);
|
||||
void hwSetITDMode(u32 v, u8 mode);
|
||||
|
@ -687,6 +783,8 @@ void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned
|
|||
void aramFreeStreamBuffer(u8 id);
|
||||
void* aramStoreData(void* src, unsigned long len);
|
||||
void aramRemoveData(void* aram, unsigned long len);
|
||||
|
||||
void macMakeInactive(SYNTH_VOICE* svoice, MAC_STATE);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
#include "musyx/assert.h"
|
||||
#include "musyx/musyx_priv.h"
|
||||
|
||||
u16 dspSRCCycles[3][3] = {
|
||||
{2990, 2990, 1115},
|
||||
{3300, 3300, 1115},
|
||||
{3700, 3700, 1115},
|
||||
};
|
||||
|
||||
static const u16 dspMixerCycles[32] = {
|
||||
1470, 2940, 2940, 4410, 2230, 4460, 4460, 6690, 2470, 4940, 4940, 7410, 3735, 7470, 7470, 11205,
|
||||
2940, 3386, 2940, 3386, 2940, 3386, 2940, 3386, 4940, 5687, 4940, 5687, 4940, 5687, 4940, 5687,
|
||||
};
|
||||
#ifdef _DEBUG
|
||||
static u32 dbgActiveVoicesMax = 0;
|
||||
#endif
|
||||
|
||||
extern u8 salAuxFrame;
|
||||
DSPstudioinfo dspStudio[8];
|
||||
static u32 dspARAMZeroBuffer = 0;
|
||||
u16* dspCmdLastLoad = NULL;
|
||||
|
@ -36,26 +30,23 @@ u32 salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2) {
|
|||
|
||||
salNumVoices = numVoices;
|
||||
salMaxStudioNum = numStudios;
|
||||
#line 66
|
||||
ASSERT(salMaxStudioNum <= SAL_MAX_STUDIONUM);
|
||||
dspARAMZeroBuffer = aramGetZeroBuffer();
|
||||
dspCmdList = salMalloc(1024 * sizeof(u16));
|
||||
if (dspCmdList != NULL) {
|
||||
// OSReport("Allocated dspCmdList.\n\n");
|
||||
dspSurround = salMalloc(160 * sizeof(long));
|
||||
if (dspSurround != NULL) {
|
||||
// OSReport("Allocated surround buffer.\n\n");
|
||||
if ((dspCmdList = salMalloc(1024 * sizeof(u16))) != NULL) {
|
||||
MUSY_DEBUG("Allocated dspCmdList.\n\n");
|
||||
if ((dspSurround = salMalloc(160 * sizeof(long))) != NULL) {
|
||||
MUSY_DEBUG("Allocated surround buffer.\n\n");
|
||||
memset(dspSurround, 0, 160 * sizeof(long));
|
||||
DCFlushRange(dspSurround, 160 * sizeof(long));
|
||||
dspVoice = salMalloc(salNumVoices * sizeof(DSPvoice));
|
||||
if (dspVoice != NULL) {
|
||||
// OSReport("Allocated HW voice array.\n\n");
|
||||
dspITDBuffer = salMalloc(salNumVoices * 64);
|
||||
if (dspITDBuffer != NULL) {
|
||||
// OSReport("Allocated ITD buffers for voice array.\n\n");
|
||||
if ((dspVoice = salMalloc(salNumVoices * sizeof(DSPvoice))) != NULL) {
|
||||
MUSY_DEBUG("Allocated HW voice array.\n\n");
|
||||
if ((dspITDBuffer = salMalloc(salNumVoices * 64)) != NULL) {
|
||||
MUSY_DEBUG("Allocated ITD buffers for voice array.\n\n");
|
||||
DCInvalidateRange(dspITDBuffer, salNumVoices * 64);
|
||||
itdPtr = (u32)dspITDBuffer;
|
||||
for (i = 0; i < salNumVoices; ++i) {
|
||||
// OSReport("Initializing voice %d...\n", i);
|
||||
MUSY_DEBUG("Initializing voice %d...\n", i);
|
||||
dspVoice[i].state = 0;
|
||||
dspVoice[i].postBreak = 0;
|
||||
dspVoice[i].startupBreak = 0;
|
||||
|
@ -82,20 +73,16 @@ u32 salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2) {
|
|||
}
|
||||
}
|
||||
|
||||
// OSReport("All voices initialized.\n\n");
|
||||
MUSY_DEBUG("All voices initialized.\n\n");
|
||||
|
||||
for (i = 0; i < salMaxStudioNum; ++i) {
|
||||
// OSReport("Initializing studio %d...\n", i);
|
||||
MUSY_DEBUG("Initializing studio %d...\n", i);
|
||||
dspStudio[i].state = 0;
|
||||
itdPtr = (u32)salMalloc(sizeof(_SPB));
|
||||
dspStudio[i].spb = (void*)itdPtr;
|
||||
if ((void*)itdPtr == NULL) {
|
||||
if ((dspStudio[i].spb = (_SPB*)salMalloc(sizeof(_SPB))) == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
itdPtr = (u32)salMalloc(0x3c00);
|
||||
dspStudio[i].main[0] = (void*)itdPtr;
|
||||
if ((void*)itdPtr == NULL) {
|
||||
if ((dspStudio[i].main[0] = (void*)salMalloc(0x3c00)) == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -109,22 +96,19 @@ u32 salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2) {
|
|||
dspStudio[i].auxB[1] = dspStudio[i].auxB[0] + 0x1e0;
|
||||
dspStudio[i].auxB[2] = dspStudio[i].auxB[1] + 0x1e0;
|
||||
memset(dspStudio[i].spb, 0, sizeof(_SPB));
|
||||
dspStudio[i].hostDPopSum.s = 0;
|
||||
dspStudio[i].hostDPopSum.r = 0;
|
||||
dspStudio[i].hostDPopSum.l = 0;
|
||||
dspStudio[i].hostDPopSum.sA = 0;
|
||||
dspStudio[i].hostDPopSum.rA = 0;
|
||||
dspStudio[i].hostDPopSum.lA = 0;
|
||||
dspStudio[i].hostDPopSum.sB = 0;
|
||||
dspStudio[i].hostDPopSum.rB = 0;
|
||||
dspStudio[i].hostDPopSum.lB = 0;
|
||||
dspStudio[i].hostDPopSum.l = dspStudio[i].hostDPopSum.r = dspStudio[i].hostDPopSum.s =
|
||||
0;
|
||||
dspStudio[i].hostDPopSum.lA = dspStudio[i].hostDPopSum.rA =
|
||||
dspStudio[i].hostDPopSum.sA = 0;
|
||||
dspStudio[i].hostDPopSum.lB = dspStudio[i].hostDPopSum.rB =
|
||||
dspStudio[i].hostDPopSum.sB = 0;
|
||||
DCFlushRangeNoSync(dspStudio[i].spb, sizeof(_SPB));
|
||||
}
|
||||
// OSReport("All studios are initialized.\n\n");
|
||||
salActivateStudio(0, 1, defaultStudioDPL2 != FALSE);
|
||||
// OSReport("Default studio is active.\n\n");
|
||||
dspHrtfHistoryBuffer = salMalloc(0x100);
|
||||
if (dspHrtfHistoryBuffer == NULL) {
|
||||
MUSY_DEBUG("All studios are initialized.\n\n");
|
||||
salActivateStudio(
|
||||
0, 1, defaultStudioDPL2 != FALSE ? SND_STUDIO_TYPE_RESERVED0 : SND_STUDIO_TYPE_STD);
|
||||
MUSY_DEBUG("Default studio is active.\n\n");
|
||||
if ((dspHrtfHistoryBuffer = salMalloc(0x100)) == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -168,15 +152,13 @@ void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type) {
|
|||
memset(dspStudio[studio].main[0], 0, 0x3c00);
|
||||
DCFlushRangeNoSync(dspStudio[studio].main[0], 0x3c00);
|
||||
memset(dspStudio[studio].spb, 0, sizeof(_SPB));
|
||||
dspStudio[studio].hostDPopSum.s = 0;
|
||||
dspStudio[studio].hostDPopSum.r = 0;
|
||||
dspStudio[studio].hostDPopSum.l = 0;
|
||||
dspStudio[studio].hostDPopSum.sA = 0;
|
||||
dspStudio[studio].hostDPopSum.rA = 0;
|
||||
dspStudio[studio].hostDPopSum.lA = 0;
|
||||
dspStudio[studio].hostDPopSum.sB = 0;
|
||||
dspStudio[studio].hostDPopSum.rB = 0;
|
||||
dspStudio[studio].hostDPopSum.lB = 0;
|
||||
dspStudio[studio].hostDPopSum.l = dspStudio[studio].hostDPopSum.r =
|
||||
dspStudio[studio].hostDPopSum.s = 0;
|
||||
dspStudio[studio].hostDPopSum.lA = dspStudio[studio].hostDPopSum.rA =
|
||||
dspStudio[studio].hostDPopSum.sA = 0;
|
||||
dspStudio[studio].hostDPopSum.lB = dspStudio[studio].hostDPopSum.rB =
|
||||
dspStudio[studio].hostDPopSum.sB = 0;
|
||||
|
||||
DCFlushRangeNoSync(dspStudio[studio].spb, sizeof(_SPB));
|
||||
memset(dspStudio[studio].auxA[0], 0, 0x780);
|
||||
DCFlushRangeNoSync(dspStudio[studio].auxA[0], 0x780);
|
||||
|
@ -188,10 +170,20 @@ void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type) {
|
|||
dspStudio[studio].isMaster = isMaster;
|
||||
dspStudio[studio].numInputs = 0;
|
||||
dspStudio[studio].type = type;
|
||||
dspStudio[studio].auxBHandler = NULL;
|
||||
dspStudio[studio].auxAHandler = NULL;
|
||||
dspStudio[studio].auxAHandler = dspStudio[studio].auxBHandler = NULL;
|
||||
}
|
||||
|
||||
u16 dspSRCCycles[3][3] = {
|
||||
{2990, 2990, 1115},
|
||||
{3300, 3300, 1115},
|
||||
{3700, 3700, 1115},
|
||||
};
|
||||
|
||||
static const u16 dspMixerCycles[32] = {
|
||||
1470, 2940, 2940, 4410, 2230, 4460, 4460, 6690, 2470, 4940, 4940, 7410, 3735, 7470, 7470, 11205,
|
||||
2940, 3386, 2940, 3386, 2940, 3386, 2940, 3386, 4940, 5687, 4940, 5687, 4940, 5687, 4940, 5687,
|
||||
};
|
||||
|
||||
void salDeactivateStudio(u8 studio) { dspStudio[studio].state = 0; }
|
||||
|
||||
u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u16 targetVol,
|
||||
|
@ -201,9 +193,9 @@ u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u
|
|||
|
||||
if (targetVol != *last_vol) {
|
||||
d = (s16)targetVol - (s16)*last_vol;
|
||||
if (d >= 32 && d < 160) {
|
||||
d = d >> 5;
|
||||
if (d < 5) {
|
||||
if ((s16)d >= 32 && (s16)d < 160) {
|
||||
d = (s16)d >> 5;
|
||||
if ((s16)d < 5) {
|
||||
resetFlags[d] |= resetMask;
|
||||
}
|
||||
|
||||
|
@ -212,19 +204,18 @@ u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (-32 >= d && -160 < d) {
|
||||
d = -d >> 5;
|
||||
if (-32 >= (s16)d && -160 < (s16)d) {
|
||||
d = -(s16)d >> 5;
|
||||
if (d < 5) {
|
||||
resetFlags[d] |= resetMask;
|
||||
}
|
||||
*dsp_delta = 0xFFFF;
|
||||
*last_vol -= d * 32;
|
||||
*last_vol -= (s16)d * 32;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (targetVol == 0 && d > -32) {
|
||||
*last_vol = 0;
|
||||
*dsp_vol = 0;
|
||||
if (targetVol == 0 && (s16)d > -32) {
|
||||
*dsp_vol = *last_vol = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,16 +342,13 @@ u32 salSynthSendMessage(DSPvoice* dsp_vptr, u32 mesg) {
|
|||
}
|
||||
|
||||
void salActivateVoice(DSPvoice* dsp_vptr, u8 studio) {
|
||||
DSPvoice* tmp;
|
||||
if (dsp_vptr->state != 0) {
|
||||
salDeactivateVoice(dsp_vptr);
|
||||
dsp_vptr->changed[0] |= 0x20;
|
||||
}
|
||||
|
||||
dsp_vptr->postBreak = 0;
|
||||
tmp = dspStudio[studio].voiceRoot;
|
||||
dsp_vptr->next = tmp;
|
||||
if (tmp != NULL) {
|
||||
if ((dsp_vptr->next = dspStudio[studio].voiceRoot) != NULL) {
|
||||
dsp_vptr->next->prev = dsp_vptr;
|
||||
}
|
||||
|
||||
|
@ -390,7 +378,6 @@ void salDeactivateVoice(DSPvoice* dsp_vptr) {
|
|||
}
|
||||
|
||||
void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio) {
|
||||
DSPvoice* tmp;
|
||||
if (dsp_vptr->state != 0) {
|
||||
if (dsp_vptr->prev != NULL) {
|
||||
dsp_vptr->prev->next = dsp_vptr->next;
|
||||
|
@ -402,9 +389,7 @@ void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio) {
|
|||
dsp_vptr->next->prev = dsp_vptr->prev;
|
||||
}
|
||||
|
||||
tmp = dspStudio[studio].voiceRoot;
|
||||
dsp_vptr->next = tmp;
|
||||
if (tmp != NULL) {
|
||||
if ((dsp_vptr->next = dspStudio[studio].voiceRoot) != NULL) {
|
||||
dsp_vptr->next->prev = dsp_vptr;
|
||||
}
|
||||
|
||||
|
@ -437,7 +422,7 @@ unsigned long salRemoveStudioInput(DSPstudioinfo* stp, SND_STUDIO_INPUT* desc) {
|
|||
long i; // r31
|
||||
|
||||
i = 0;
|
||||
while(i <= stp->numInputs) {
|
||||
while (i < stp->numInputs) {
|
||||
if (stp->in[i].desc == desc) {
|
||||
break;
|
||||
}
|
||||
|
@ -452,3 +437,35 @@ unsigned long salRemoveStudioInput(DSPstudioinfo* stp, SND_STUDIO_INPUT* desc) {
|
|||
--stp->numInputs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void salHandleAuxProcessing() {
|
||||
u8 st; // r29
|
||||
long* work; // r30
|
||||
DSPstudioinfo* sp; // r31
|
||||
SND_AUX_INFO info; // r1+0x8
|
||||
sp = &dspStudio[0];
|
||||
for (st = 0; st < salMaxStudioNum; ++st, ++sp) {
|
||||
|
||||
if (sp->state != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp->auxAHandler != NULL) {
|
||||
work = sp->auxA[(salAuxFrame + 2) % 3];
|
||||
info.data.bufferUpdate.left = work;
|
||||
info.data.bufferUpdate.right = work + 0xa0;
|
||||
info.data.bufferUpdate.surround = work + 0x140;
|
||||
sp->auxAHandler(0, &info, sp->auxAUser);
|
||||
DCFlushRangeNoSync(work, 0x780);
|
||||
}
|
||||
|
||||
if (sp->type == 0 && sp->auxBHandler != 0) {
|
||||
work = sp->auxB[(salAuxFrame + 2) % 3];
|
||||
info.data.bufferUpdate.left = work;
|
||||
info.data.bufferUpdate.right = work + 0xa0;
|
||||
info.data.bufferUpdate.surround = work + 0x140;
|
||||
sp->auxBHandler(0, &info, sp->auxBUser);
|
||||
DCFlushRangeNoSync(work, 0x780);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ s16 sndSintab[1024] = {
|
|||
4094, 4094, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
|
||||
};
|
||||
|
||||
#define SINTAB_ELEMENT_COUNT (sizeof(sndSintab) / sizeof(short) - 1)
|
||||
#define SINTAB_ELEMENT_COUNT (sizeof(sndSintab) / sizeof(u16) - 1)
|
||||
|
||||
u32 last_rnd = 1;
|
||||
|
||||
|
@ -80,18 +80,18 @@ u16 sndRand(void) {
|
|||
return last_rnd >> 6;
|
||||
}
|
||||
|
||||
s16 sndSin(u32 __x) {
|
||||
const u16 x = __x & 0xFFF;
|
||||
if (x < 1024) {
|
||||
return (int)sndSintab[x];
|
||||
s16 sndSin(u16 angle) {
|
||||
angle &= 0xFFF;
|
||||
if (angle < 1024) {
|
||||
return (s16)sndSintab[angle];
|
||||
}
|
||||
if (x < 2048) {
|
||||
return (int)sndSintab[SINTAB_ELEMENT_COUNT - (x & SINTAB_ELEMENT_COUNT)];
|
||||
if (angle < 2048) {
|
||||
return (s16)sndSintab[SINTAB_ELEMENT_COUNT - (angle & SINTAB_ELEMENT_COUNT)];
|
||||
}
|
||||
if (x < 3072) {
|
||||
return (int)-sndSintab[x & SINTAB_ELEMENT_COUNT];
|
||||
if (angle < 3072) {
|
||||
return (s16)-sndSintab[angle & SINTAB_ELEMENT_COUNT];
|
||||
}
|
||||
return -sndSintab[SINTAB_ELEMENT_COUNT - (x & SINTAB_ELEMENT_COUNT)];
|
||||
return -sndSintab[SINTAB_ELEMENT_COUNT - (angle & SINTAB_ELEMENT_COUNT)];
|
||||
}
|
||||
|
||||
u8* sndBSearch(u16* key, u8* subTab, s32 mainTab, s32 len, SND_COMPARE cmp) {
|
||||
|
@ -124,8 +124,8 @@ u8* sndBSearch(u16* key, u8* subTab, s32 mainTab, s32 len, SND_COMPARE cmp) {
|
|||
|
||||
void sndConvertMs(u32* time) { *time = *time * 256; }
|
||||
|
||||
void sndConvertTicks(u32* out, u32 seconds) {
|
||||
*out = (((*out << 16) / synthGetTicksPerSecond(seconds)) * 1000) / 32;
|
||||
void sndConvertTicks(u32* out, SYNTH_VOICE* svoice) {
|
||||
*out = (((*out << 16) / synthGetTicksPerSecond(svoice)) * 1000) / 32;
|
||||
}
|
||||
|
||||
u32 sndConvert2Ms(u32 time) { return time / 256; }
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
#include "musyx/assert.h"
|
||||
#include "musyx/musyx_priv.h"
|
||||
|
||||
static u32 synthTicksPerSecond[9][16];
|
||||
static SYNTH_JOBTAB synthJobTable[32];
|
||||
CTRL_DEST inpAuxA[8][4];
|
||||
CTRL_DEST inpAuxB[8][4];
|
||||
long synthGlobalVariable[16];
|
||||
synthITDInfo synthITDDefault[8];
|
||||
void* synthAuxBUser[8];
|
||||
SND_AUX_CALLBACK synthAuxBCallback[8];
|
||||
void* synthAuxAUser[8];
|
||||
SND_AUX_CALLBACK synthAuxACallback[8];
|
||||
u8 synthTrackVolume[64];
|
||||
SYNTHMasterFader synthMasterFader[32];
|
||||
SynthInfo synthInfo;
|
||||
|
||||
u8 sndActive = 0;
|
||||
static u8 synthJobTableIndex = 0;
|
||||
u64 synthRealTime;
|
||||
u8 synthIdleWaitActive;
|
||||
SND_MESSAGE_CALLBACK synthMessageCallback;
|
||||
SYNTH_VOICE* synthVoice;
|
||||
u32 synthFlags;
|
||||
u32 synthMasterFaderActiveFlags;
|
||||
u32 synthMasterFaderPauseActiveFlags;
|
||||
u8 synthAuxAMIDI[8];
|
||||
u8 synthAuxAMIDISet[8];
|
||||
u8 synthAuxBMIDI[8];
|
||||
u8 synthAuxBMIDISet[8];
|
||||
u8 synthTrackVolume[64]; // size: 0x40
|
||||
|
||||
void synthSetBpm(u32 bpm, u8 set, u8 section) {
|
||||
if (set == 0xFF) {
|
||||
set = 8;
|
||||
}
|
||||
synthTicksPerSecond[set][section] = ((bpm << 3) * 1536) / 240;
|
||||
}
|
||||
|
||||
u32 synthGetTicksPerSecond(SYNTH_VOICE* svoice) {
|
||||
return synthTicksPerSecond[svoice->midiSet == 0xFF ? 8 : svoice->midiSet][svoice->section];
|
||||
}
|
||||
|
||||
static u32 apply_portamento(SYNTH_VOICE* svoice, u32 ccents, u32 deltaTime) {
|
||||
u32 old_portCurPitch; // r31
|
||||
|
||||
if ((svoice->cFlags & 0x400) != 0 && (int)((svoice->portDuration - svoice->portTime) >> 8) > 0) {
|
||||
|
||||
old_portCurPitch = svoice->portCurPitch;
|
||||
svoice->portCurPitch += (int)deltaTime * ((int)(ccents - svoice->portCurPitch) >> 8) /
|
||||
(int)((svoice->portDuration - svoice->portTime) >> 8);
|
||||
|
||||
if ((old_portCurPitch < ccents && svoice->portCurPitch < ccents) ||
|
||||
(old_portCurPitch > ccents && (svoice->portCurPitch > ccents))) {
|
||||
ccents = svoice->portCurPitch;
|
||||
svoice->portTime += deltaTime;
|
||||
} else {
|
||||
svoice->portTime = svoice->portDuration;
|
||||
}
|
||||
}
|
||||
return ccents;
|
||||
}
|
||||
|
||||
void synthInitPortamento(SYNTH_VOICE* svoice) {
|
||||
if (svoice->cFlags & 0x20000) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (svoice->portType == 1) {
|
||||
if (!(svoice->cFlags & 0x1000)) {
|
||||
svoice->portTime = 0;
|
||||
} else {
|
||||
svoice->portTime = svoice->portDuration;
|
||||
}
|
||||
} else {
|
||||
svoice->portTime = svoice->portDuration;
|
||||
}
|
||||
|
||||
svoice->portCurPitch = svoice->lastNote << 16;
|
||||
}
|
||||
|
||||
static u32 do_voice_portamento(u8 key, u8 midi, u8 midiSet, u32 isMaster, u32* rejected) {
|
||||
u32 i; // r30
|
||||
u32 vid; // r29
|
||||
u32 id; // r27
|
||||
SYNTH_VOICE* sv; // r31
|
||||
SYNTH_VOICE* last_sv; // r28
|
||||
u32 legatoVoiceIsStarting; // r26
|
||||
}
|
||||
|
||||
static u32 check_portamento(u8 key, u8 midi, u8 midiSet, u32 newVID, u32* vid) {
|
||||
u32 rejected; // r1+0x14
|
||||
|
||||
if (inpGetMidiCtrl(65, midi, midiSet) > 8064) {
|
||||
*vid = do_voice_portamento(key & 0x7f, midi, midiSet, newVID, &rejected);
|
||||
return !rejected;
|
||||
}
|
||||
*vid = 0xFFFFFFFF;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 StartLayer(u16 layerID, s16 prio, u8 maxVoices, u16 allocId, u8 key, u8 vol, u8 panning,
|
||||
u8 midi, u8 midiSet, u8 section, u16 step, u16 trackid, u32 vidFlag,
|
||||
u8 vGroup, u8 studio, u32 itd) {
|
||||
u16 n; // r1+0x38
|
||||
u32 vid; // r26
|
||||
u32 new_id; // r1+0x34
|
||||
u32 id; // r27
|
||||
LAYER* l; // r31
|
||||
long p; // r30
|
||||
long k; // r29
|
||||
u8 v; // r25
|
||||
u8 mKey; // r24
|
||||
}
|
||||
|
||||
static u32 StartKeymap(u16 keymapID, s16 prio, u8 maxVoices, u16 allocId, u8 key, u8 vol,
|
||||
u8 panning, u8 midi, u8 midiSet, u8 section, u16 step, u16 trackid,
|
||||
u32 vidFlag, u8 vGroup, u8 studio, u32 itd) {
|
||||
u8 o; // r30
|
||||
struct KEYMAP* keymap; // r31
|
||||
long p; // r26
|
||||
long k; // r29
|
||||
u32 vid; // r1+0x34
|
||||
}
|
||||
|
||||
#pragma dont_inline on
|
||||
u32 synthStartSound(u16 id, u8 prio, u8 max, u8 key, u8 vol, u8 panning, u8 midi, u8 midiSet,
|
||||
u8 section, u16 step, u16 trackid, u8 vGroup, s16 prioOffset, u8 studio,
|
||||
u32 itd) {
|
||||
u32 vid; // r1+0x34
|
||||
}
|
||||
#pragma dont_inline reset
|
||||
|
||||
static u32 convert_cents(SYNTH_VOICE* svoice, u32 ccents) {
|
||||
unsigned long curDetune; // r30
|
||||
unsigned long cpitch; // r31
|
||||
}
|
||||
|
||||
static void UpdateTimeMIDICtrl(SYNTH_VOICE* sv) {
|
||||
if (!sv->timeUsedByInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
sv->timeUsedByInput = 0;
|
||||
sv->midiDirtyFlags = 0x1fff;
|
||||
}
|
||||
|
||||
static void LowPrecisionHandler(unsigned long i) {
|
||||
unsigned long j; // r30
|
||||
long pbend; // r29
|
||||
unsigned long ccents; // r28
|
||||
unsigned long cpitch; // r26
|
||||
unsigned short Modulation; // r24
|
||||
unsigned short portamento; // r25
|
||||
unsigned long lowDeltaTime; // r27
|
||||
struct SYNTH_VOICE* sv; // r31
|
||||
unsigned long cntDelta; // r20
|
||||
unsigned long addFactor; // r19
|
||||
unsigned short adsr_start; // r1+0xE
|
||||
unsigned short adsr_delta; // r1+0xC
|
||||
long vrange; // r23
|
||||
long voff; // r22
|
||||
}
|
||||
|
||||
static void ZeroOffsetHandler(unsigned long i) {
|
||||
struct SYNTH_VOICE* sv; // r31
|
||||
unsigned long lowDeltaTime; // r26
|
||||
unsigned short Modulation; // r25
|
||||
float vol; // r62
|
||||
float auxa; // r57
|
||||
float auxb; // r56
|
||||
float f; // r59
|
||||
float voiceVol; // r60
|
||||
unsigned long volUpdate; // r30
|
||||
float lfo; // r55
|
||||
float scale; // r63
|
||||
float mscale; // r54
|
||||
long pan; // r28
|
||||
float preVol; // r58
|
||||
float postVol; // r61
|
||||
}
|
||||
|
||||
static void EventHandler(unsigned long i) {
|
||||
SYNTH_VOICE* sv; // r31
|
||||
}
|
||||
|
||||
static void synthInitJobQueue() {
|
||||
u8 i; // r31
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
synthJobTable[i].lowPrecision = NULL;
|
||||
synthJobTable[i].event = NULL;
|
||||
synthJobTable[i].zeroOffset = NULL;
|
||||
}
|
||||
|
||||
synthJobTableIndex = 0;
|
||||
}
|
||||
|
||||
#pragma dont_inline on
|
||||
void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, unsigned long deltaTime) {
|
||||
SYNTH_QUEUE* newJq; // r31
|
||||
SYNTH_QUEUE** root; // r30
|
||||
u8 jobTabIndex; // r29
|
||||
SYNTH_JOBTAB* jobTab; // r28
|
||||
}
|
||||
#pragma dont_inline reset
|
||||
|
||||
void synthStartSynthJobHandling(SYNTH_VOICE* svoice) {
|
||||
svoice->lastLowCallTime = synthRealTime;
|
||||
svoice->lastZeroCallTime = synthRealTime;
|
||||
synthAddJob(svoice, SYNTH_JOBTYPE_LOW, 0);
|
||||
synthAddJob(svoice, SYNTH_JOBTYPE_ZERO, 0);
|
||||
}
|
||||
|
||||
void synthForceLowPrecisionUpdate(SYNTH_VOICE* svoice) {
|
||||
synthAddJob(svoice, SYNTH_JOBTYPE_LOW, 0);
|
||||
synthAddJob(svoice, SYNTH_JOBTYPE_ZERO, 0);
|
||||
}
|
||||
|
||||
void synthKeyStateUpdate(SYNTH_VOICE* svoice) { synthAddJob(svoice, SYNTH_JOBTYPE_EVENT, 0); }
|
||||
|
||||
void HandleJobQueue(SYNTH_QUEUE** queueRoot, void (*handler)(unsigned long)) {
|
||||
SYNTH_QUEUE* jq; // r31
|
||||
SYNTH_QUEUE* nextJq; // r30
|
||||
|
||||
jq = *queueRoot;
|
||||
while (jq != NULL) {
|
||||
nextJq = jq->next;
|
||||
jq->jobTabIndex = 0xff;
|
||||
if (!synthVoice[jq->voice].block) {
|
||||
handler(jq->voice);
|
||||
}
|
||||
jq = nextJq;
|
||||
}
|
||||
|
||||
*queueRoot = NULL;
|
||||
}
|
||||
|
||||
void HandleVoices() {
|
||||
SYNTH_JOBTAB* jTab = &synthJobTable[synthJobTableIndex]; // r31
|
||||
HandleJobQueue(&jTab->lowPrecision, LowPrecisionHandler);
|
||||
HandleJobQueue(&jTab->event, EventHandler);
|
||||
HandleJobQueue(&jTab->zeroOffset, ZeroOffsetHandler);
|
||||
synthJobTableIndex = synthJobTableIndex + 1 & 0x1f;
|
||||
}
|
||||
|
||||
void HandleFaderTermination(SYNTHMasterFader* smf) {
|
||||
|
||||
switch (smf->seqMode) {
|
||||
case 1:
|
||||
seqStop(smf->seqId);
|
||||
break;
|
||||
case 2:
|
||||
seqPause(smf->seqId);
|
||||
break;
|
||||
case 3:
|
||||
seqMute(smf->seqId, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void synthHandle(unsigned long deltaTime) {
|
||||
unsigned long i; // r29
|
||||
unsigned long s; // r30
|
||||
SYNTHMasterFader* smf; // r31
|
||||
unsigned long testFlag; // r27
|
||||
SND_AUX_INFO info; // r1+0x18
|
||||
}
|
||||
|
||||
unsigned char synthFXGetMaxVoices(u16 fid) {
|
||||
FX_TAB* fx;
|
||||
if ((fx = dataGetFX(fid)) != NULL) {
|
||||
return fx->maxVoices;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 synthFXStart(u16 fid, u8 vol, u8 pan, u8 studio, u32 itd) {
|
||||
FX_TAB* fx;
|
||||
u32 v;
|
||||
v = 0xFFFFFFFF;
|
||||
if ((fx = dataGetFX(fid)) != NULL) {
|
||||
if (vol == 0xFF) {
|
||||
vol = fx->volume;
|
||||
}
|
||||
|
||||
if (pan == 0xFF) {
|
||||
pan = fx->panning;
|
||||
}
|
||||
|
||||
v = synthStartSound(fx->macro, fx->priority, fx->maxVoices, fx->key | 0x80, vol, pan, 0xFF,
|
||||
0xFF, 0, 0, 0xFF, fx->vGroup, 0, studio, itd);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
|
@ -1,21 +1,285 @@
|
|||
#include "musyx/assert.h"
|
||||
#include "musyx/musyx_priv.h"
|
||||
|
||||
static VS vs;
|
||||
|
||||
void vsInit() {
|
||||
u32 i;
|
||||
vs._0 = 0;
|
||||
vs.numBuffers = 0;
|
||||
for (i = 0; i < 64; i++) {
|
||||
vs._908[i] = 0xFF;
|
||||
vs.voices[i] = 0xFF;
|
||||
}
|
||||
|
||||
vs._948 = 0;
|
||||
vs._94c = 0;
|
||||
vs.nextInstID = 0;
|
||||
vs.callback = NULL;
|
||||
}
|
||||
|
||||
void vsSampleStartNotify() {
|
||||
u16 vsNewInstanceID() {
|
||||
u8 i; // r31
|
||||
u16 instID; // r29
|
||||
do {
|
||||
instID = vs.nextInstID++;
|
||||
i = 0;
|
||||
for (; i < vs.numBuffers; ++i) {
|
||||
if (vs.streamBuffer[i].state != 0 && vs.streamBuffer[i].info.instID == instID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (i != vs.numBuffers);
|
||||
|
||||
return instID;
|
||||
}
|
||||
|
||||
void vsSampleEndNotify() {
|
||||
u8 vsAllocateBuffer() {
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < vs.numBuffers; ++i) {
|
||||
if (vs.streamBuffer[i].state != 0) {
|
||||
continue;
|
||||
}
|
||||
vs.streamBuffer[i].state = 1;
|
||||
vs.streamBuffer[i].last = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void vsFreeBuffer(u8 bufferIndex) {
|
||||
vs.streamBuffer[bufferIndex].state = 0;
|
||||
vs.voices[vs.streamBuffer[bufferIndex].voice] = 0xFF;
|
||||
}
|
||||
|
||||
u32 vsSampleStartNotify(unsigned char voice) {
|
||||
u8 sb; // r29
|
||||
u8 i; // r28
|
||||
u32 addr; // r27
|
||||
|
||||
for (i = 0; i < vs.numBuffers; ++i) {
|
||||
if (vs.streamBuffer[i].state != 0 && vs.streamBuffer[i].voice == voice) {
|
||||
vsFreeBuffer(i);
|
||||
}
|
||||
}
|
||||
|
||||
sb = vs.voices[voice] = vsAllocateBuffer();
|
||||
if (sb != 0xFF) {
|
||||
addr = aramGetStreamBufferAddress(vs.voices[voice], 0);
|
||||
hwSetVirtualSampleLoopBuffer(voice, addr, vs.bufferLength);
|
||||
vs.streamBuffer[sb].info.smpID = hwGetSampleID(voice);
|
||||
vs.streamBuffer[sb].info.instID = vsNewInstanceID();
|
||||
vs.streamBuffer[sb].smpType = hwGetSampleType(voice);
|
||||
vs.streamBuffer[sb].voice = voice;
|
||||
if (vs.callback != NULL) {
|
||||
vs.callback(0, &vs.streamBuffer[sb].info);
|
||||
|
||||
return (vs.streamBuffer[sb].info.instID << 8) | voice;
|
||||
}
|
||||
hwSetVirtualSampleLoopBuffer(voice, 0, 0);
|
||||
} else {
|
||||
hwSetVirtualSampleLoopBuffer(voice, 0, 0);
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void vsSampleEndNotify(unsigned long pubID) {
|
||||
u8 sb;
|
||||
u8 voice;
|
||||
|
||||
if (pubID != 0xFFFFFFFF) {
|
||||
u8 id = (u8)pubID;
|
||||
sb = vs.voices[id];
|
||||
if (sb != 0xFF) {
|
||||
if (vs.streamBuffer[sb].info.instID == ((pubID >> 8) & 0xFFFF)) {
|
||||
if (vs.callback != NULL) {
|
||||
vs.callback(2, &vs.streamBuffer[sb].info);
|
||||
}
|
||||
vsFreeBuffer(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vsUpdateBuffer(struct VS_BUFFER* sb, unsigned long cpos) {
|
||||
u32 len; // r29
|
||||
u32 off; // r27
|
||||
|
||||
if (sb->last == cpos) {
|
||||
return;
|
||||
}
|
||||
if ((s32)sb->last < cpos) {
|
||||
if ((s8)sb->smpType != 5) {
|
||||
cpos = cpos;
|
||||
} else {
|
||||
sb->info.data.update.off1 = (sb->last / 14) * 8;
|
||||
sb->info.data.update.len1 = cpos - sb->last;
|
||||
sb->info.data.update.off2 = 0;
|
||||
sb->info.data.update.len2 = 0;
|
||||
if ((len = vs.callback(1, &sb->info)) != 0) {
|
||||
off = sb->last + len;
|
||||
sb->last = off - (off / vs.bufferLength) * vs.bufferLength;
|
||||
}
|
||||
}
|
||||
} else if (cpos == 0) {
|
||||
if ((s8)sb->smpType != 5) {
|
||||
cpos = cpos;
|
||||
} else {
|
||||
sb->info.data.update.off1 = (sb->last / 14) * 8;
|
||||
sb->info.data.update.len1 = vs.bufferLength - sb->last;
|
||||
sb->info.data.update.off2 = 0;
|
||||
sb->info.data.update.len2 = 0;
|
||||
if ((len = vs.callback(1, &sb->info)) != 0) {
|
||||
off = sb->last + len;
|
||||
sb->last = off - (off / vs.bufferLength) * vs.bufferLength;
|
||||
}
|
||||
}
|
||||
} else if ((s8)sb->smpType != 5) {
|
||||
cpos = cpos;
|
||||
} else {
|
||||
sb->info.data.update.off1 = (sb->last / 14) * 8;
|
||||
sb->info.data.update.len1 = vs.bufferLength - sb->last;
|
||||
sb->info.data.update.off2 = 0;
|
||||
sb->info.data.update.len2 = cpos;
|
||||
if ((len = vs.callback(1, &sb->info)) != 0) {
|
||||
off = sb->last + len;
|
||||
sb->last = off - (off / vs.bufferLength) * vs.bufferLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vsSampleUpdates() {
|
||||
u32 i; // r29
|
||||
u32 cpos; // r27
|
||||
u32 realCPos; // r28
|
||||
VS_BUFFER* sb; // r31
|
||||
u32 nextSamples; // r26
|
||||
}
|
||||
|
||||
unsigned long sndVirtualSampleAllocateBuffers(unsigned char numInstances,
|
||||
unsigned long numSamples) {
|
||||
long i; // r31
|
||||
unsigned long len; // r28
|
||||
#line 437
|
||||
ASSERT_MSG(sndActive, "Sound system is not initialized.");
|
||||
ASSERT_MSG(numInstances <= 64, "Parameter exceeded maximum number of instances allowable");
|
||||
#line 159
|
||||
hwDisableIrq();
|
||||
vs.numBuffers = numInstances;
|
||||
len = sndStreamAllocLength(numSamples, 1);
|
||||
vs.bufferLength = (len / 8) * 14;
|
||||
|
||||
for (i = 0; i < vs.numBuffers; ++i) {
|
||||
if ((vs.streamBuffer[i].hwId = aramAllocateStreamBuffer(len)) == 0xFF) {
|
||||
break;
|
||||
}
|
||||
vs.streamBuffer[i].state = 0;
|
||||
vs.voices[vs.streamBuffer[i].voice] = 0xFF;
|
||||
}
|
||||
|
||||
if (i >= vs.numBuffers) {
|
||||
hwEnableIrq();
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((i - 1) > 0) {
|
||||
aramFreeStreamBuffer(vs.streamBuffer[i - 1].hwId);
|
||||
--i;
|
||||
}
|
||||
|
||||
hwEnableIrq();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sndVirtualSampleFreeBuffers() {
|
||||
u8 i; // r31
|
||||
#line 481
|
||||
ASSERT_MSG(sndActive, "Sound system is not initialized.");
|
||||
|
||||
for (i = 0; i < vs.numBuffers; ++i) {
|
||||
aramFreeStreamBuffer(vs.streamBuffer[i].hwId);
|
||||
}
|
||||
|
||||
vs.numBuffers = 0;
|
||||
}
|
||||
|
||||
void sndVirtualSampleSetCallback(unsigned long (*callback)(unsigned char,
|
||||
struct SND_VIRTUALSAMPLE_INFO*)) {
|
||||
#line 0x1ed
|
||||
ASSERT_MSG(sndActive, "Sound system is not initialized.");
|
||||
vs.callback = callback;
|
||||
}
|
||||
|
||||
void vsARAMDMACallback(unsigned long user) {
|
||||
if (vs.callback == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
vs.callback(3, &((VS_BUFFER*)user)->info);
|
||||
}
|
||||
|
||||
void sndVirtualSampleARAMUpdate(unsigned short instID, void* base, unsigned long off1,
|
||||
unsigned long len1, unsigned long off2, unsigned long len2) {
|
||||
u8 i;
|
||||
#line 0x203
|
||||
ASSERT_MSG(sndActive, "Sound system is not initialized.");
|
||||
|
||||
hwDisableIrq();
|
||||
|
||||
for (i = 0; i < vs.numBuffers; ++i) {
|
||||
if (vs.streamBuffer[i].state == 0 || vs.streamBuffer[i].info.instID != instID) {
|
||||
continue;
|
||||
}
|
||||
if ((s32)vs.streamBuffer[i].smpType != 5) {
|
||||
i = i;
|
||||
} else {
|
||||
off1 = (off1 / 14) * 8;
|
||||
len1 = ((len1 + 13) / 14) * 8;
|
||||
off2 = (off2 / 14) * 8;
|
||||
len2 = ((len2 + 13) / 14) * 8;
|
||||
}
|
||||
|
||||
if (len1 != 0) {
|
||||
hwFlushStream(base, off1, len1, vs.streamBuffer[i].hwId, vsARAMDMACallback,
|
||||
&vs.streamBuffer[i]);
|
||||
}
|
||||
if (len2 != 0) {
|
||||
hwFlushStream(base, off2, len2, vs.streamBuffer[i].hwId, vsARAMDMACallback,
|
||||
&vs.streamBuffer[i]);
|
||||
}
|
||||
|
||||
if (vs.streamBuffer[i].smpType == 5) {
|
||||
hwSetStreamLoopPS(vs.streamBuffer[i].voice, *(u32*)(OSCachedToUncached(base)) >> 24);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
hwEnableIrq();
|
||||
}
|
||||
|
||||
void sndVirtualSampleEndPlayback(unsigned short instID) {
|
||||
u8 i; // r30
|
||||
VS_BUFFER* stream; // r31
|
||||
u32 cpos; // r28
|
||||
|
||||
hwDisableIrq();
|
||||
|
||||
for (i = 0; i < vs.numBuffers; ++i) {
|
||||
if (vs.streamBuffer[i].state == 0 || vs.streamBuffer[i].info.instID != instID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
stream = &vs.streamBuffer[i];
|
||||
cpos = hwGetPos(i);
|
||||
|
||||
if (stream->last < cpos) {
|
||||
stream->finalGoodSamples = vs.bufferLength - (cpos - stream->last);
|
||||
} else {
|
||||
stream->finalGoodSamples = stream->last - cpos;
|
||||
}
|
||||
|
||||
stream->finalLast = cpos;
|
||||
stream->state = 2;
|
||||
break;
|
||||
}
|
||||
hwEnableIrq();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,492 @@
|
|||
#include "musyx/assert.h"
|
||||
#include "musyx/musyx_priv.h"
|
||||
|
||||
void voiceResetLastStarted(SYNTH_VOICE* svoice);
|
||||
|
||||
static VID_LIST vidList[128];
|
||||
static u8 synth_last_started[8][16];
|
||||
static u8 synth_last_fxstarted[64];
|
||||
SYNTH_VOICELIST voiceList[64];
|
||||
SYNTH_ROOTLIST voicePrioSortRootList[256];
|
||||
u8 voicePrioSortVoicesRoot[256];
|
||||
SYNTH_VOICELIST voicePrioSortVoices[64];
|
||||
static u32 vidCurrentId = 0;
|
||||
static VID_LIST* vidRoot = NULL;
|
||||
static VID_LIST* vidFree = NULL;
|
||||
u16 voicePrioSortRootListRoot = 0;
|
||||
u8 voiceMusicRunning = 0;
|
||||
u8 voiceFxRunning = 0;
|
||||
u8 voiceListInsert = 0;
|
||||
u8 voiceListRoot = 0;
|
||||
|
||||
void vidInit() {
|
||||
int i;
|
||||
VID_LIST* lvl;
|
||||
vidCurrentId = 0;
|
||||
vidRoot = NULL;
|
||||
vidFree = vidList;
|
||||
for (lvl = NULL, i = 0; i < 128; lvl = &vidList[i], ++i) {
|
||||
vidList[i].prev = lvl;
|
||||
if (lvl != NULL) {
|
||||
lvl->next = &vidList[i];
|
||||
}
|
||||
}
|
||||
lvl->next = NULL;
|
||||
}
|
||||
|
||||
VID_LIST* get_vidlist(u32 vid) {
|
||||
VID_LIST* vl = vidRoot;
|
||||
while (vl != NULL) {
|
||||
if (vl->vid == vid) {
|
||||
return vl;
|
||||
}
|
||||
if (vl->vid > vid) {
|
||||
break;
|
||||
}
|
||||
vl = vl->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 get_newvid() {
|
||||
u32 vid; // r31
|
||||
do {
|
||||
vid = vidCurrentId++;
|
||||
} while (vid == 0xFFFFFFFF);
|
||||
|
||||
return vid;
|
||||
}
|
||||
|
||||
void vidRemove(VID_LIST** vidList) {
|
||||
if ((*vidList)->prev != NULL) {
|
||||
(*vidList)->prev->next = (*vidList)->next;
|
||||
} else {
|
||||
vidRoot = (*vidList)->next;
|
||||
}
|
||||
|
||||
if ((*vidList)->next != NULL) {
|
||||
(*vidList)->next->prev = (*vidList)->prev;
|
||||
}
|
||||
|
||||
(*vidList)->next = vidFree;
|
||||
|
||||
if (vidFree != NULL) {
|
||||
vidFree->prev = *vidList;
|
||||
}
|
||||
|
||||
(*vidList)->prev = NULL;
|
||||
vidFree = *vidList;
|
||||
*vidList = NULL;
|
||||
}
|
||||
|
||||
void vidRemoveVoiceReferences(SYNTH_VOICE* svoice) {
|
||||
if (svoice->id == 0xFFFFFFFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
voiceResetLastStarted(svoice);
|
||||
if (svoice->parent != 0xFFFFFFFF) {
|
||||
synthVoice[svoice->parent & 0xFF].child = svoice->child;
|
||||
if (svoice->child != 0xFFFFFFFF) {
|
||||
synthVoice[svoice->child & 0xFF].parent = svoice->parent;
|
||||
}
|
||||
|
||||
vidRemove(&svoice->vidList);
|
||||
} else if (svoice->child != 0xFFFFFFFF) {
|
||||
svoice->vidList->root = svoice->child;
|
||||
synthVoice[svoice->child & 0xFF].parent = 0xFFFFFFFF;
|
||||
synthVoice[svoice->child & 0xFF].vidMasterList = svoice->vidMasterList;
|
||||
if (svoice->vidList != svoice->vidMasterList) {
|
||||
vidRemove(&svoice->vidList);
|
||||
}
|
||||
|
||||
svoice->vidMasterList = svoice->vidList = NULL;
|
||||
} else if (svoice->vidList != svoice->vidMasterList) {
|
||||
vidRemove(&svoice->vidList);
|
||||
vidRemove(&svoice->vidMasterList);
|
||||
} else {
|
||||
vidRemove(&svoice->vidList);
|
||||
svoice->vidMasterList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long vidMakeRoot(struct SYNTH_VOICE* svoice) {
|
||||
svoice->vidMasterList = svoice->vidList;
|
||||
return svoice->vidList->vid;
|
||||
}
|
||||
|
||||
u32 vidMakeNew(SYNTH_VOICE* svoice, u32 isMaster) {
|
||||
u32 vid; // r29
|
||||
VID_LIST* nvl; // r30
|
||||
VID_LIST* lvl; // r28
|
||||
VID_LIST* vl; // r31
|
||||
|
||||
vid = get_newvid();
|
||||
lvl = NULL;
|
||||
nvl = vidRoot;
|
||||
|
||||
while (nvl != NULL) {
|
||||
if (nvl->vid > vid) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nvl->vid == vid) {
|
||||
vid = get_newvid();
|
||||
}
|
||||
|
||||
lvl = nvl;
|
||||
nvl = nvl->next;
|
||||
}
|
||||
|
||||
if ((vl = vidFree) == NULL) {
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if ((vidFree = vidFree->next) != NULL) {
|
||||
vidFree->prev = NULL;
|
||||
}
|
||||
|
||||
if (lvl == NULL) {
|
||||
vidRoot = vl;
|
||||
} else {
|
||||
lvl->next = vl;
|
||||
}
|
||||
|
||||
vl->prev = lvl;
|
||||
vl->next = nvl;
|
||||
|
||||
if (nvl != NULL) {
|
||||
nvl->prev = vl;
|
||||
}
|
||||
|
||||
vl->vid = vid;
|
||||
vl->root = svoice->id;
|
||||
svoice->vidMasterList = isMaster ? vl : NULL;
|
||||
svoice->vidList = vl;
|
||||
|
||||
if (isMaster != 0) {
|
||||
return vid;
|
||||
}
|
||||
|
||||
return svoice->id;
|
||||
}
|
||||
|
||||
u32 vidGetInternalId(u32 vid) {
|
||||
VID_LIST* vl;
|
||||
|
||||
if (vid != 0xffffffff) {
|
||||
if ((vl = get_vidlist(vid)) != NULL) {
|
||||
return vl->root;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
void voiceInitPrioSort() {
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < synthInfo.voiceNum; ++i) {
|
||||
voicePrioSortVoices[i].user = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
voicePrioSortVoicesRoot[i] = 0xff;
|
||||
}
|
||||
|
||||
voicePrioSortRootListRoot = 0xffff;
|
||||
}
|
||||
|
||||
void voiceRemovePriority(SYNTH_VOICE* svoice) {
|
||||
SYNTH_VOICELIST* vps = &voicePrioSortVoices[svoice->id & 0xFF]; // r31
|
||||
SYNTH_ROOTLIST* rps; // r30
|
||||
if (vps->user != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vps->prev != 0xff) {
|
||||
voicePrioSortVoices[vps->prev].next = vps->next;
|
||||
} else {
|
||||
voicePrioSortVoicesRoot[svoice->prio] = vps->next;
|
||||
}
|
||||
|
||||
if (vps->next != 0xff) {
|
||||
voicePrioSortVoices[vps->next].prev = vps->prev;
|
||||
} else if (vps->prev == 0xFF) {
|
||||
rps = &voicePrioSortRootList[svoice->prio];
|
||||
|
||||
if (rps->prev != 0xFFFF) {
|
||||
voicePrioSortRootList[rps->prev].next = rps->next;
|
||||
|
||||
} else {
|
||||
voicePrioSortRootListRoot = rps->next;
|
||||
}
|
||||
|
||||
if (rps->next != 0xFFFF) {
|
||||
voicePrioSortRootList[rps->next].prev = rps->prev;
|
||||
}
|
||||
}
|
||||
|
||||
vps->user = 0;
|
||||
}
|
||||
|
||||
#pragma dont_inline on
|
||||
void voiceSetPriority(SYNTH_VOICE* svoice, u8 prio) {
|
||||
u16 i; // r29
|
||||
u16 li; // r25
|
||||
SYNTH_VOICELIST* vps; // r27
|
||||
u32 v; // r26
|
||||
}
|
||||
|
||||
u32 voiceAllocate(u8 priority, u8 maxVoices, u16 allocId, u8 fxFlag) {
|
||||
long i; // r31
|
||||
long num; // r26
|
||||
long voice; // r30
|
||||
u16 p; // r29
|
||||
u32 type_alloc; // r25
|
||||
SYNTH_VOICELIST* sfv; // r27
|
||||
}
|
||||
#pragma dont_inline reset
|
||||
|
||||
void voiceFree(SYNTH_VOICE* svoice) {
|
||||
u32 i; // r29
|
||||
SYNTH_VOICELIST* sfv; // r30
|
||||
#line 628
|
||||
ASSERT(svoice->id != 0xFFFFFFFF);
|
||||
#line 256
|
||||
macMakeInactive(svoice, MAC_STATE_STOPPED);
|
||||
voiceRemovePriority(svoice);
|
||||
svoice->addr = NULL;
|
||||
svoice->prio = 0;
|
||||
sfv = &voiceList[(i = svoice->id & 0xFF)];
|
||||
if (sfv->user == 0) {
|
||||
sfv->user = 1;
|
||||
if (voiceListRoot != 0xFF) {
|
||||
sfv->next = 0xFF;
|
||||
sfv->prev = voiceListInsert;
|
||||
voiceList[voiceListInsert].next = i;
|
||||
} else {
|
||||
sfv->next = 0xFF;
|
||||
sfv->prev = 0xFF;
|
||||
voiceListRoot = i;
|
||||
}
|
||||
|
||||
voiceListInsert = i;
|
||||
if (svoice->fxFlag != 0) {
|
||||
--voiceFxRunning;
|
||||
} else {
|
||||
--voiceMusicRunning;
|
||||
}
|
||||
}
|
||||
|
||||
svoice->id = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void voiceInitFreeList() {
|
||||
u32 i; // r31
|
||||
|
||||
for (i = 0; i < synthInfo.voiceNum; ++i) {
|
||||
voiceList[i].prev = i - 1;
|
||||
voiceList[i].next = i + 1;
|
||||
voiceList[i].user = 1;
|
||||
}
|
||||
|
||||
voiceList[0].prev = 0xff;
|
||||
voiceList[synthInfo.voiceNum - 1].next = 0xff;
|
||||
voiceListRoot = 0;
|
||||
voiceListInsert = synthInfo.voiceNum - 1;
|
||||
}
|
||||
|
||||
void synthInitAllocationAids() {
|
||||
voiceInitFreeList();
|
||||
voiceInitPrioSort();
|
||||
voiceFxRunning = 0;
|
||||
voiceMusicRunning = 0;
|
||||
}
|
||||
|
||||
u32 voiceBlock(unsigned char prio) {
|
||||
u32 voice = voiceAllocate(prio, 0xFF, 0xFFFF, 1);
|
||||
|
||||
if (voice != 0xFFFFFFFF) {
|
||||
synthVoice[voice].block = 1;
|
||||
synthVoice[voice].fxFlag = 1;
|
||||
#ifdef PRIME1
|
||||
synthVoice[voice].allocId = 0xFFFF;
|
||||
#endif
|
||||
vidRemoveVoiceReferences(&synthVoice[voice]);
|
||||
synthVoice[voice].id = voice | 0xFFFFFF00;
|
||||
|
||||
if (hwIsActive(voice)) {
|
||||
hwBreak(voice);
|
||||
}
|
||||
|
||||
macMakeInactive(&synthVoice[voice], MAC_STATE_STOPPED);
|
||||
synthVoice[voice].addr = NULL;
|
||||
voiceSetPriority(&synthVoice[voice], prio);
|
||||
}
|
||||
|
||||
return voice;
|
||||
}
|
||||
|
||||
void voiceUnblock(u32 voice) {
|
||||
if (voice == 0xFFFFFFFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hwIsActive(voice)) {
|
||||
hwBreak(voice);
|
||||
}
|
||||
|
||||
synthVoice[voice].id = voice;
|
||||
voiceFree(&synthVoice[voice]);
|
||||
synthVoice[voice].block = 0;
|
||||
}
|
||||
|
||||
void voiceKill(u32 vi) {
|
||||
SYNTH_VOICE* sv = &synthVoice[vi]; // r31
|
||||
if (sv->addr != NULL) {
|
||||
vidRemoveVoiceReferences(sv);
|
||||
sv->cFlags &= ~3;
|
||||
sv->age = 0;
|
||||
voiceFree(sv);
|
||||
}
|
||||
|
||||
if (sv->block != 0) {
|
||||
streamKill(vi);
|
||||
}
|
||||
|
||||
hwBreak(vi);
|
||||
}
|
||||
|
||||
long voiceKillSound(u32 voiceid) {
|
||||
long ret;
|
||||
u32 next_voiceid;
|
||||
u32 i;
|
||||
u32 vid;
|
||||
|
||||
ret = -1;
|
||||
|
||||
if (sndActive != FALSE) {
|
||||
i = vidGetInternalId(voiceid);
|
||||
|
||||
while (i != 0xFFFFFFFF) {
|
||||
vid = i & 0xFF;
|
||||
next_voiceid = synthVoice[vid].child;
|
||||
if (i == synthVoice[vid].id) {
|
||||
voiceKill(vid);
|
||||
ret = 0;
|
||||
}
|
||||
i = next_voiceid;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void synthKillAllVoices(unsigned char musiconly) {
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < synthInfo.voiceNum; ++i) {
|
||||
if (synthVoice[i].addr != NULL) {
|
||||
if (musiconly == 0 || (musiconly != 0 && synthVoice[i].fxFlag == 0)) {
|
||||
voiceKill(i);
|
||||
}
|
||||
} else {
|
||||
voiceKill(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void synthKillVoicesByMacroReferences(u16* ref) {
|
||||
u32 i; // r31
|
||||
u16 id; // r29
|
||||
|
||||
for (i = 0; i < synthInfo.voiceNum; ++i) {
|
||||
if (synthVoice[i].addr == NULL && synthVoice[i].block == 0) {
|
||||
voiceKill(i);
|
||||
}
|
||||
}
|
||||
|
||||
while (*ref != 0xFFFF) {
|
||||
if ((*ref & 0x8000)) {
|
||||
id = *ref & 0x3fff;
|
||||
while (id <= ref[1]) {
|
||||
for (i = 0; i < synthInfo.voiceNum; ++i) {
|
||||
if (synthVoice[i].addr != NULL && id == synthVoice[i].macroId) {
|
||||
voiceKill(i);
|
||||
}
|
||||
}
|
||||
++id;
|
||||
}
|
||||
ref += 2;
|
||||
} else {
|
||||
for (i = 0; i < synthInfo.voiceNum; ++i) {
|
||||
if (synthVoice[i].addr != NULL && *ref == synthVoice[i].macroId) {
|
||||
voiceKill(i);
|
||||
}
|
||||
}
|
||||
++ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 voiceIsLastStarted(SYNTH_VOICE* svoice) {
|
||||
u32 i; // r31
|
||||
|
||||
if (svoice->id != 0xFFFFFFFF && svoice->midi != 0xFF) {
|
||||
i = svoice->id & 0xFF;
|
||||
if (svoice->midiSet == 0xFF) {
|
||||
if (synth_last_fxstarted[i] == i) {
|
||||
return TRUE;
|
||||
}
|
||||
} else if (synth_last_started[svoice->midiSet][svoice->midi] == i) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void voiceSetLastStarted(SYNTH_VOICE* svoice) {
|
||||
u32 i; // r31
|
||||
|
||||
if (svoice->id != 0xFFFFFFFF && svoice->midi != 0xFF) {
|
||||
i = svoice->id & 0xFF;
|
||||
if (svoice->midiSet == 0xFF) {
|
||||
synth_last_fxstarted[i] = i;
|
||||
} else {
|
||||
synth_last_started[svoice->midiSet][svoice->midi] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void voiceResetLastStarted(struct SYNTH_VOICE* svoice) {
|
||||
u32 i;
|
||||
|
||||
if ((svoice->id != 0xffffffff) && (svoice->midi != 0xff)) {
|
||||
i = svoice->id & 0xff;
|
||||
if (svoice->midiSet == 0xff) {
|
||||
if (synth_last_fxstarted[i] == i) {
|
||||
synth_last_fxstarted[i] = 0xff;
|
||||
}
|
||||
} else if (i == synth_last_started[svoice->midiSet][svoice->midi]) {
|
||||
synth_last_started[svoice->midiSet][svoice->midi] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void voiceInitLastStarted() {
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
for (j = 0; j < 16; ++j) {
|
||||
synth_last_started[i][j] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; ++j) {
|
||||
synth_last_fxstarted[j] = 0xFF;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue