9
9
10
10
typedef struct {
11
11
/** Starting frequency. */
12
- uint16_t freq1 ;
12
+ float freq1 ;
13
13
14
14
/** Ending frequency, or zero for no frequency transition. */
15
- uint16_t freq2 ;
15
+ float freq2 ;
16
16
17
17
/** Time the tone was started. */
18
18
unsigned long long startTime ;
@@ -73,16 +73,23 @@ static int w4_min (int a, int b) {
73
73
static int lerp (int value1 , int value2 , float t ) {
74
74
return value1 + t * (value2 - value1 );
75
75
}
76
+ static float lerpf (float value1 , float value2 , float t ) {
77
+ return value1 + t * (value2 - value1 );
78
+ }
76
79
77
80
static int ramp (int value1 , int value2 , unsigned long long time1 , unsigned long long time2 ) {
78
81
if (time >= time2 ) return value2 ;
79
82
float t = (float )(time - time1 ) / (time2 - time1 );
80
83
return lerp (value1 , value2 , t );
81
84
}
85
+ static float rampf (float value1 , float value2 , unsigned long long time1 , unsigned long long time2 ) {
86
+ float t = (float )(time - time1 ) / (time2 - time1 );
87
+ return lerpf (value1 , value2 , t );
88
+ }
82
89
83
- static uint16_t getCurrentFrequency (const Channel * channel ) {
90
+ static float getCurrentFrequency (const Channel * channel ) {
84
91
if (channel -> freq2 > 0 ) {
85
- return ramp (channel -> freq1 , channel -> freq2 , channel -> startTime , channel -> releaseTime );
92
+ return rampf (channel -> freq1 , channel -> freq2 , channel -> startTime , channel -> releaseTime );
86
93
} else {
87
94
return channel -> freq1 ;
88
95
}
@@ -116,6 +123,10 @@ static float polyblep (float phase, float phaseInc) {
116
123
}
117
124
}
118
125
126
+ static float midiFreq (uint8_t note , uint8_t bend ) {
127
+ return powf (2.0f , ((float )note - 69.0f + (float )bend / 256.0f ) / 12.0f ) * 440.0f ;
128
+ }
129
+
119
130
void w4_apuInit () {
120
131
channels [3 ].noise .seed = 0x0001 ;
121
132
}
@@ -139,6 +150,7 @@ void w4_apuTone (int frequency, int duration, int volume, int flags) {
139
150
int channelIdx = flags & 0x03 ;
140
151
int mode = (flags >> 2 ) & 0x3 ;
141
152
int pan = (flags >> 4 ) & 0x3 ;
153
+ int noteMode = flags & 0x40 ;
142
154
143
155
// TODO(2022-01-08): Thread safety
144
156
Channel * channel = & channels [channelIdx ];
@@ -147,9 +159,13 @@ void w4_apuTone (int frequency, int duration, int volume, int flags) {
147
159
if (time > channel -> releaseTime && ticks != channel -> endTick ) {
148
160
channel -> phase = (channelIdx == 2 ) ? 0.25 : 0 ;
149
161
}
150
-
151
- channel -> freq1 = freq1 ;
152
- channel -> freq2 = freq2 ;
162
+ if (noteMode ) {
163
+ channel -> freq1 = midiFreq (freq1 & 0xff , freq1 >> 8 );
164
+ channel -> freq2 = (freq2 == 0 ) ? 0 : midiFreq (freq2 & 0xff , freq2 >> 8 );
165
+ } else {
166
+ channel -> freq1 = freq1 ;
167
+ channel -> freq2 = freq2 ;
168
+ }
153
169
channel -> startTime = time ;
154
170
channel -> attackTime = channel -> startTime + SAMPLE_RATE * attack /60 ;
155
171
channel -> decayTime = channel -> attackTime + SAMPLE_RATE * decay /60 ;
@@ -190,7 +206,7 @@ void w4_apuWriteSamples (int16_t* output, unsigned long frames) {
190
206
Channel * channel = & channels [channelIdx ];
191
207
192
208
if (time < channel -> releaseTime || ticks == channel -> endTick ) {
193
- uint16_t freq = getCurrentFrequency (channel );
209
+ float freq = getCurrentFrequency (channel );
194
210
int16_t volume = getCurrentVolume (channel );
195
211
int16_t sample ;
196
212
@@ -207,7 +223,7 @@ void w4_apuWriteSamples (int16_t* output, unsigned long frames) {
207
223
sample = volume * channel -> noise .lastRandom ;
208
224
209
225
} else {
210
- float phaseInc = ( float ) freq / SAMPLE_RATE ;
226
+ float phaseInc = freq / SAMPLE_RATE ;
211
227
channel -> phase += phaseInc ;
212
228
213
229
if (channel -> phase >= 1 ) {
0 commit comments