1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
#include "libaudio.h"
#include "synthInternals.h"
#include "stdbool.h"
#include "stddef.h"
#include "ultra64/convert.h"
Acmd* alResamplePull(void* filter, s16* outp, s32 outCnt, s32 sampleOffset, Acmd* p) {
ALResampler* f = (ALResampler*)filter;
Acmd* ptr = p;
s16 inp;
s32 inCount;
ALFilter* source = f->filter.source;
s32 incr;
f32 finCount;
inp = AL_DECODER_OUT;
if (outCnt == 0) {
return ptr;
}
// check if resampler is required
if (f->upitch != 0) {
ptr = (*source->handler)(source, &inp, outCnt, sampleOffset, p);
aDMEMMove(ptr++, inp, *outp, outCnt << 1);
} else {
// clip to maximum allowable pitch
// FIXME: should we check for some minimum as well?
if (f->ratio > MAX_RATIO) {
f->ratio = MAX_RATIO;
}
// quantize the pitch
f->ratio = (s32)(f->ratio * UNITY_PITCH);
f->ratio = f->ratio / UNITY_PITCH;
// determine how many samples to generate
finCount = f->delta + f->ratio * (f32)outCnt;
inCount = (s32)finCount;
f->delta = finCount - (f32)inCount;
// ask all filters upstream from us to build their command lists.
ptr = (*source->handler)(source, &inp, inCount, sampleOffset, p);
// construct our portion of the command list
incr = (s32)(f->ratio * UNITY_PITCH);
aSetBuffer(ptr++, 0, inp, *outp, outCnt << 1);
aResample(ptr++, f->first, incr, osVirtualToPhysical(f->state));
f->first = false;
}
return ptr;
}
s32 alResampleParam(void* filter, s32 paramID, void* param) {
ALFilter* f = (ALFilter*)filter;
ALResampler* r = (ALResampler*)filter;
union {
f32 f;
s32 i;
} data;
switch (paramID) {
case AL_FILTER_SET_SOURCE:
f->source = (ALFilter*)param;
break;
case AL_FILTER_RESET:
r->delta = 0.0f;
r->first = true;
r->motion = AL_STOPPED;
r->upitch = 0;
if (f->source != NULL) {
(*f->source->setParam)(f->source, AL_FILTER_RESET, 0);
}
break;
case AL_FILTER_START:
r->motion = AL_PLAYING;
if (f->source != NULL) {
(*f->source->setParam)(f->source, AL_FILTER_START, 0);
}
break;
case AL_FILTER_SET_PITCH:
data.i = (s32)param;
r->ratio = data.f;
break;
case AL_FILTER_SET_UNITY_PITCH:
r->upitch = 1;
break;
default:
if (f->source != NULL) {
(*f->source->setParam)(f->source, paramID, param);
}
break;
}
return 0;
}
|