-
Notifications
You must be signed in to change notification settings - Fork 3
/
fm_modulate_feedback.S
126 lines (103 loc) · 2.33 KB
/
fm_modulate_feedback.S
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#ifndef __ASSEMBLY__
#define __ASSEMBLY__
#endif
#include <bf706_device.h>
#include "audioFX_config.h"
.extern __fm_sine;
.type __fm_sine,STT_OBJECT;
/* This is used if the operator uses feedback
*
* void _fm_modulate_feedback(_operator *op, q15 *buf, q15 feedbackLevel);
*/
.align 2
.global __fm_modulate_feedback;
.type __fm_modulate_feedback, STT_FUNC;
__fm_modulate_feedback:
[--SP] = ( R7:2, P5:2 );
P5 = R0;
P4 = R0; //_operator
R7 = [P4]; //_operator->current
I1 = R7;
P4 += 4;
R7 = [P4]; //_operator->cfreq
I2 = R7; //cfreq
B2 = R7;
L2 = 0;
M2 = 4;
P4 += 8;
R7 = [P4]; //_operator->volume
I3 = R7;
B3 = R7;
L3 = 0;
M3 = 2;
P4 += 4;
R0 = [P4]; //_operator->err
P4 += 4;
R6 = W[P4] (X); //_operator->lastFeedback
R7.H = __fm_sine;
R7.L = __fm_sine;
B1 = R7;
L1 = 8192; //sizeof(__fm_sine)
P3 = R1; //buf
P2 = 2 (X);
[--SP] = R2; //feedbackLevel
R7 = FM_LOOKUP_INC;
R4 = AUDIO_BUFSIZE;
R5 = FM_LOOKUP_MOD;
LC0 = R4;
LOOP fmFeedbackLoop LC0;
LOOP_BEGIN fmFeedbackLoop;
R1 = [I2++M2];
(R3:2) = ((A1:0) = R7 * R1) (IU);
R2 = PACK(R3.L, R2.H);
R2 = R2 + R0; //add previous error
R0 = R2 & R5;
R2 >>= 19; //shift out the error
R2 <<= 1;
M1 = R2;
I1 += M1;
R1 = [SP];
R2.L = R6.L * R1.L;
R2 = R2.L (X);
R2 >>>= 4;
//get sign bit
R3 = 0x80000000;
R3 = R3 & R2;
R2 = R2 << 19;
BITCLR(R2, 31); //clear sign bit
R4 = R2 | R3; //add in old sign bit
R4 >>>= 18; // % N
M1 = R4;
I1 += M1;
#ifdef INTERPOLATE_FM
R4.L = W[I1++]; // move to next for interpolation
R2.L = W[I1--]; // load value to interpolate
R3 = R0 >> 3; // get fractional error
R2.L = R2.L - R4.L; // difference = next - current
R2.H = (A1 = R2.L * R3.L) (M); // multiply by error (error is unsigned and difference is signed)
R4.L = R4.L + R2.H; // add interpolated value
#else
R4 = [I1];
#endif
R4 = R4.L (X);
I1 -= M1 || R1 = [I3++M3];
//moving average to get rid of oscillations
R4 >>>= 1;
R2 = R6 >>> 1;
R4.L = R4.L + R2.L (S);
R6 = R4.L (X); //new lastFeedback
//multiply by volume
R4.L = R4.L * R1.L || R1 = [P3];
//add to output
R4.L = R4.L + R1.L (S);
W[P3++P2] = R4.L;
LOOP_END fmFeedbackLoop;
SP += 4;
R7 = I1;
[P5] = R7; //_operator->current
P5 += 16;
[P5] = R0; //_operator->err
P5 += 4;
W[P5] = R6.L; //_operator->lastFeedback
( R7:2, P5:2 ) = [ SP ++ ];
RTS;