Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
2d9a0_len_890.c
Go to the documentation of this file.
1#include "common.h"
2#include "audio.h"
3
5 s32 i;
6
7 for (i = 0; i < ARRAY_COUNT(globals->voices); i++) {
8 AuVoice* voice = &globals->voices[i];
9
10 if (voice->stopPending) {
12 voice->stopPending = FALSE;
13 voice->cmdPtr = NULL;
15 }
16 }
17}
18
19void au_init_voices(AuGlobals* globals) {
20 s32 i;
21
22 for (i = 0; i < ARRAY_COUNT(globals->voices); i++) {
23 AuVoice* voice = &globals->voices[i];
24
25 voice->cmdPtr = NULL;
26 voice->unk_20 = 0;
27 voice->volChangeTime = 0;
28 voice->timeLeft = 0;
29 voice->timeIntervalIndex = 0;
30 voice->unk_3C = 0;
31 voice->envelopeFlags = 0;
32 voice->relativeReleaseVolumes = FALSE;
33 voice->releaseVolumeMult = 0x80;
34 }
35}
36
38 AuVoice* voice;
39 s8 var_a0;
40 s16 currentAmp;
41 s32 i;
42
43 for (i = 0; i < ARRAY_COUNT(globals->voices); i++) {
44 voice = &globals->voices[i];
45 if (voice->cmdPtr == NULL) {
46 continue;
47 }
49 // client volume changed on previous frame
51 continue;
52 }
54 // client released the key
55 voice->envelopeFlags &= ~AU_VOICE_ENV_FLAG_KEY_RELEASED;
57 voice->cmdPtr = (u8*)voice->envelope.cmdListRelease;
58
59 // the key can be released before press cmdlist processed completely, we must handle this case properly
60 if (voice->timeLeft > AU_5750) {
61 voice->initialAmp = voice->initialAmp + (s32) (voice->rate * (f32) (voice->volChangeTime - voice->timeLeft));
62 } else {
63 voice->initialAmp = voice->targetAmp;
64 }
65
66 voice->timeIntervalIndex = *voice->cmdPtr++;
67 var_a0 = *voice->cmdPtr;
68 if (*(s8*)voice->cmdPtr++ < 0) {
69 // in this case release volumes are relative to last press volume
70 var_a0 &= 0x7F;
71 voice->relativeReleaseVolumes = TRUE;
72 voice->releaseVolumeMult = voice->initialAmp;
73 }
74 voice->targetAmp = var_a0;
75
77 voice->volChangeTime = voice->timeLeft;
79 voice->envelopeFlags &= ~AU_VOICE_ENV_FLAG_VOL_CHANGED;
80 if (voice->timeLeft > AU_5750) {
81 voice->timeLeft -= AU_5750;
83 currentAmp = voice->initialAmp + (s32) (voice->rate * (voice->volChangeTime - voice->timeLeft));
84 } else {
85 currentAmp = voice->targetAmp;
86 }
87 voice->delta = AUDIO_SAMPLES;
88 } else {
89 voice->delta = au_voice_get_delta(voice->volChangeTime);
90 currentAmp = voice->targetAmp;
91 }
92 voice->p_volume = (((currentAmp * voice->clientVolume * voice->releaseVolumeMult) >> 0xE) * voice->volMult) >> 7;
94 } else {
95 if (voice->timeLeft == -1) {
96 // keep current volume, this is 'sustain' phase
98 voice->envelopeFlags &= ~AU_VOICE_ENV_FLAG_VOL_CHANGED;
99 voice->p_volume = (((voice->initialAmp * voice->clientVolume * voice->releaseVolumeMult) >> 0xE) * voice->volMult) >> 7;
101 }
102 } else {
103 voice->timeLeft -= AU_5750;
104 if (voice->timeLeft <= 0) {
105 if (*voice->cmdPtr == ENV_CMD_END) {
107 // if we reached the end after key release, stop the voice completely
108 voice->envelopeFlags = 0;
109 voice->cmdPtr = NULL;
110 voice->stopPending = TRUE;
111 } else {
112 // we reached the end of press cmdlist, keep the last volume until the key is released
113 voice->timeLeft = -1;
114 voice->volChangeTime = -1;
115 voice->timeIntervalIndex = ENV_TIME_300MS; // doesn't seem to affect anything
116 voice->delta = AUDIO_SAMPLES;
117 voice->rate = 0.0f;
118 voice->initialAmp = voice->targetAmp;
119 }
120 } else {
121 // get next envelope point
122 voice->timeIntervalIndex = au_voice_step(voice);
123 voice->initialAmp = voice->targetAmp;
124 voice->targetAmp = (*voice->cmdPtr++) & 0x7F;
126 voice->volChangeTime = voice->timeLeft;
127 if (voice->volChangeTime != 0) {
128 voice->rate = ((f32) voice->targetAmp - (f32) voice->initialAmp) / (f32) voice->volChangeTime;
129 } else {
130 voice->rate = 0.0f;
131 }
133 voice->envelopeFlags &= ~AU_VOICE_ENV_FLAG_VOL_CHANGED;
134 if (voice->timeLeft > AU_5750) {
135 voice->timeLeft -= AU_5750;
137 currentAmp = voice->initialAmp + (s32) (voice->rate * (voice->volChangeTime - voice->timeLeft));
138 } else {
139 currentAmp = voice->targetAmp;
140 }
141 voice->delta = AUDIO_SAMPLES;
142 } else {
143 voice->delta = au_voice_get_delta(voice->volChangeTime);
144 currentAmp = voice->targetAmp;
145 }
146 voice->p_volume = (((currentAmp * voice->clientVolume * voice->releaseVolumeMult) >> 0xE) * voice->volMult) >> 7;
148 }
149 } else {
150 // we are between two envelope points, do nothing, just handle client volume change
152 voice->envelopeFlags &= ~AU_VOICE_ENV_FLAG_VOL_CHANGED;
153 if (voice->timeLeft > AU_5750) {
154 voice->timeLeft -= AU_5750;
156 currentAmp = voice->initialAmp + (s32) (voice->rate * (voice->volChangeTime - voice->timeLeft));
157 } else {
158 currentAmp = voice->targetAmp;
159 }
160 voice->delta = AUDIO_SAMPLES;
161 voice->p_volume = (((currentAmp * voice->clientVolume * voice->releaseVolumeMult) >> 0xE) * voice->volMult) >> 7;
163 }
164 }
165 }
166 }
167 }
168}
169
171 voice->p_volume = (((voice->targetAmp * voice->clientVolume * voice->releaseVolumeMult) >> 14) * voice->volMult) >> 7;
172 voice->delta = au_voice_get_delta(voice->timeLeft);
173 voice->envelopeFlags &= ~AU_VOICE_ENV_FLAG_HANDLED_VOL_CHANGE;
175}
176
177s32 au_voice_get_delta(s32 msecs) {
178 return (msecs / AU_5750) * AUDIO_SAMPLES;
179}
180
181void au_voice_start(AuVoice* voice, EnvelopeData* envData) {
182 s32 intervalIndex;
183
184 voice->envelope.cmdListPress = envData->cmdListPress;
185 voice->cmdPtr = voice->envelope.cmdListPress;
186 voice->envelope.cmdListRelease = envData->cmdListRelease;
187 voice->volMult = 0x80;
188 voice->loopStart = NULL;
189
190 intervalIndex = au_voice_step(voice);
191 voice->envelopeFlags = 0;
192 voice->initialAmp = 0;
193 voice->targetAmp = *voice->cmdPtr++;
194 voice->timeIntervalIndex = intervalIndex;
195 voice->volChangeTime = AuEnvelopeIntervals[intervalIndex];
196 voice->timeLeft = voice->volChangeTime;
197
198 voice->p_volume = (voice->targetAmp * voice->clientVolume * voice->volMult) >> 14;
199 voice->delta = au_voice_get_delta(voice->volChangeTime);
200 if (voice->volChangeTime != 0) {
201 voice->rate = ((f32) voice->targetAmp - (f32) voice->initialAmp) / voice->volChangeTime;
202 } else {
203 voice->rate = 0.0f;
204 }
205 voice->relativeReleaseVolumes = FALSE;
206 voice->releaseVolumeMult = 0x80;
207}
208
209// performs special commands and returns interval index
211 u32 op;
212 u8 arg;
213
214 while (TRUE) {
215 if (((s8)(op = *voice->cmdPtr++)) >= 0) {
216 break;
217 }
218 switch ((u8)op) {
220 arg = *voice->cmdPtr++;
221 if (arg > 0x80) {
222 arg = 0x80;
223 }
224 voice->volMult = arg;
225 break;
227 voice->volMult += (s8) *voice->cmdPtr++;
228 if (voice->volMult > 0x80) {
229 voice->volMult = 0x80;
230 } else if (voice->volMult < 0) {
231 voice->volMult = 0;
232 }
233 break;
235 voice->loopCounter = *voice->cmdPtr++; // 0 means infinite loop
236 voice->loopStart = voice->cmdPtr;
237 break;
238 case ENV_CMD_END_LOOP:
239 voice->cmdPtr++;
240 if (voice->loopCounter == 0 || --voice->loopCounter != 0) {
241 voice->cmdPtr = voice->loopStart;
242 }
243 break;
244 default:
245 voice->cmdPtr++;
246 break;
247 }
248 }
249 return op;
250}
251
252
void au_init_voices(AuGlobals *globals)
void au_voice_after_volume_change(AuVoice *voice)
void au_voice_set_vol_changed(AuVoice *voice)
void au_update_voices(AuGlobals *globals)
s32 au_voice_get_delta(s32 msecs)
void au_voice_start(AuVoice *voice, EnvelopeData *envData)
void au_update_stopped_voices(AuGlobals *globals)
u8 au_voice_step(AuVoice *voice)
void au_syn_stop_voice(u8 voiceIdx)
Definition 31650.c:301
u8 * cmdListPress
Definition audio.h:533
AuVoice voices[24]
Definition audio.h:938
u8 * cmdListRelease
Definition audio.h:534
EnvelopeData envelope
Definition audio.h:721
@ ENV_CMD_END
Definition audio.h:130
@ ENV_CMD_SET_MULTIPLIER
Definition audio.h:129
@ ENV_CMD_ADD_MULTIPLIER
Definition audio.h:128
@ ENV_CMD_START_LOOP
Definition audio.h:127
@ ENV_CMD_END_LOOP
Definition audio.h:126
s32 AuEnvelopeIntervals[]
Definition sfx_player.c:341
u8 relativeReleaseVolumes
Definition audio.h:735
#define AUDIO_SAMPLES
Definition audio.h:44
u8 loopCounter
Definition audio.h:729
s32 volMult
Definition audio.h:727
u8 timeIntervalIndex
Definition audio.h:732
@ AU_VOICE_SYNC_FLAG_PARAMS
Definition audio.h:81
f32 rate
Definition audio.h:726
s16 clientVolume
Definition audio.h:737
s32 volChangeTime
Definition audio.h:724
u8 syncFlags
Definition audio.h:739
u8 unk_3C
Definition audio.h:733
u8 releaseVolumeMult
Definition audio.h:736
u8 stopPending
Definition audio.h:738
u8 envelopeFlags
Definition audio.h:734
u8 initialAmp
Definition audio.h:730
#define AU_5750
Definition audio.h:22
s16 p_volume
Definition audio.h:716
@ AU_PRIORITY_FREE
Definition audio.h:65
s32 delta
Definition audio.h:715
@ AU_VOICE_ENV_FLAG_KEY_RELEASED
Definition audio.h:75
@ AU_VOICE_ENV_FLAG_STOP
Definition audio.h:73
@ AU_VOICE_ENV_FLAG_VOL_CHANGED
Definition audio.h:76
@ AU_VOICE_ENV_FLAG_HANDLED_VOL_CHANGE
Definition audio.h:74
@ ENV_TIME_300MS
Definition audio.h:193
u8 * loopStart
Definition audio.h:728
s32 unk_20
Definition audio.h:723
u8 priority
Definition audio.h:741
u8 targetAmp
Definition audio.h:731
u8 * cmdPtr
Definition audio.h:722
s32 timeLeft
Definition audio.h:725
#define ARRAY_COUNT(arr)
Definition macros.h:40