1 /* OpenCP Module Player
2  * copyright (c) 2019 Stian Skjelstad <stian.skjelstad@gmail.com>
3  *
4  * Renderer routine. Heavily based on https://github.com/pete-gordon/hivelytracker/tree/master/hvl2wav
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include "config.h"
22 #include <math.h>
23 #include <string.h>
24 #include "types.h"
25 #include "player.h"
26 
27 int32_t __attribute__ ((visibility ("internal"))) stereopan_left[5]  = { 128,  96,  64,  32,   0 };
28 int32_t __attribute__ ((visibility ("internal"))) stereopan_right[5] = { 128, 160, 193, 225, 255 };
29 
30 /*
31 ** Waves
32 */
33 int8_t __attribute__ ((visibility ("internal"))) waves[WAVES_SIZE];
34 //static int16 waves2[WAVES_SIZE];
35 
36 static const int16_t vib_tab[] =
37 {
38 	   0,   24,   49,   74,   97,  120,  141,  161,  180,  197,  212,  224,  235,  244,  250,  253,
39 	 255,  253,  250,  244,  235,  224,  212,  197,  180,  161,  141,  120,   97,   74,   49,   24,
40 	   0,  -24,  -49,  -74,  -97, -120, -141, -161, -180, -197, -212, -224, -235, -244, -250, -253,
41 	-255, -253, -250, -244, -235, -224, -212, -197, -180, -161, -141, -120,  -97,  -74,  -49,  -24
42 };
43 
44 static const uint16_t period_tab[] =
45 {
46 	0x0000, 0x0D60, 0x0CA0, 0x0BE8, 0x0B40, 0x0A98, 0x0A00, 0x0970,
47 	0x08E8, 0x0868, 0x07F0, 0x0780, 0x0714, 0x06B0, 0x0650, 0x05F4,
48 	0x05A0, 0x054C, 0x0500, 0x04B8, 0x0474, 0x0434, 0x03F8, 0x03C0,
49 	0x038A, 0x0358, 0x0328, 0x02FA, 0x02D0, 0x02A6, 0x0280, 0x025C,
50 	0x023A, 0x021A, 0x01FC, 0x01E0, 0x01C5, 0x01AC, 0x0194, 0x017D,
51 	0x0168, 0x0153, 0x0140, 0x012E, 0x011D, 0x010D, 0x00FE, 0x00F0,
52 	0x00E2, 0x00D6, 0x00CA, 0x00BE, 0x00B4, 0x00AA, 0x00A0, 0x0097,
53 	0x008F, 0x0087, 0x007F, 0x0078, 0x0071
54 };
55 
56 static uint32_t panning_left[256], panning_right[256];
57 
58 static void hvl_GenPanningTables (void)
59 {
60 	uint32_t i;
61 	double aa, ab;
62 
63 	// Sine based panning table
64 	aa = M_PI_2;                    // Quarter of the way through the sinewave == top peak
65 	ab = 0.0f;                      // Start of the climb from zero
66 
67 	for( i=0; i<256; i++ )
68 	{
69 		panning_left[i]  = (uint32_t)(sin(aa)*255.0f);
70 		panning_right[i] = (uint32_t)(sin(ab)*255.0f);
71 
72 		aa += (M_PI_2)/256.0f;
73 		ab += (M_PI_2)/256.0f;
74 	}
75 	panning_left[255] = 0;
76 	panning_right[0] = 0;
77 }
78 
79 #include "hvl_genwaves.inc.c"
80 
81 static void hvl_reset_some_stuff( struct hvl_tune *ht )
82 {
83 	uint32_t i;
84 
85 	for ( i=0; i<MAX_CHANNELS; i++ )
86 	{
87 		ht->ht_Voices[i].vc_Instrument = 0;
88 
89 		ht->ht_Voices[i].vc_SamplePos = 0;
90 		ht->ht_Voices[i].vc_Track = 0;
91 		ht->ht_Voices[i].vc_Transpose = 0;
92 		ht->ht_Voices[i].vc_NextTrack = 0;
93 		ht->ht_Voices[i].vc_NextTranspose = 0;
94 		ht->ht_Voices[i].vc_ADSRVolume = 0;
95 		ht->ht_Voices[i].vc_InstrPeriod = 0;
96 		ht->ht_Voices[i].vc_TrackPeriod = 0;
97 		ht->ht_Voices[i].vc_VibratoPeriod = 0;
98 		ht->ht_Voices[i].vc_NoteMaxVolume = 0;
99 		ht->ht_Voices[i].vc_PerfSubVolume = 0;
100 		ht->ht_Voices[i].vc_TrackMasterVolume = 0;
101 		ht->ht_Voices[i].vc_NewWaveform = 0;
102 		ht->ht_Voices[i].vc_Waveform = 0;
103 		ht->ht_Voices[i].vc_PlantSquare = 0;
104 		ht->ht_Voices[i].vc_PlantPeriod = 0;
105 		ht->ht_Voices[i].vc_IgnoreSquare = 0;
106 		ht->ht_Voices[i].vc_TrackOn = 0;
107 		ht->ht_Voices[i].vc_FixedNote = 0;
108 		ht->ht_Voices[i].vc_VolumeSlideUp = 0;
109 		ht->ht_Voices[i].vc_VolumeSlideDown = 0;
110 		ht->ht_Voices[i].vc_HardCut = 0;
111 		ht->ht_Voices[i].vc_HardCutRelease = 0;
112 		ht->ht_Voices[i].vc_HardCutReleaseF = 0;
113 		ht->ht_Voices[i].vc_PeriodSlideSpeed = 0;
114 		ht->ht_Voices[i].vc_PeriodSlidePeriod = 0;
115 		ht->ht_Voices[i].vc_PeriodSlideLimit = 0;
116 		ht->ht_Voices[i].vc_PeriodSlideOn = 0;
117 		ht->ht_Voices[i].vc_PeriodSlideWithLimit = 0;
118 		ht->ht_Voices[i].vc_PeriodPerfSlideSpeed = 0;
119 		ht->ht_Voices[i].vc_PeriodPerfSlidePeriod = 0;
120 		ht->ht_Voices[i].vc_PeriodPerfSlideOn = 0;
121 		ht->ht_Voices[i].vc_VibratoDelay = 0;
122 		ht->ht_Voices[i].vc_VibratoCurrent = 0;
123 		ht->ht_Voices[i].vc_VibratoDepth = 0;
124 		ht->ht_Voices[i].vc_VibratoSpeed = 0;
125 		ht->ht_Voices[i].vc_SquareOn = 0;
126 		ht->ht_Voices[i].vc_SquareInit = 0;
127 		ht->ht_Voices[i].vc_SquareLowerLimit = 0;
128 		ht->ht_Voices[i].vc_SquareUpperLimit = 0;
129 		ht->ht_Voices[i].vc_SquarePos = 0;
130 		ht->ht_Voices[i].vc_SquareSign = 0;
131 		ht->ht_Voices[i].vc_SquareSlidingIn = 0;
132 		ht->ht_Voices[i].vc_SquareReverse = 0;
133 		ht->ht_Voices[i].vc_FilterOn = 0;
134 		ht->ht_Voices[i].vc_FilterInit = 0;
135 		ht->ht_Voices[i].vc_FilterLowerLimit = 0;
136 		ht->ht_Voices[i].vc_FilterUpperLimit = 0;
137 		ht->ht_Voices[i].vc_FilterPos = 0;
138 		ht->ht_Voices[i].vc_FilterSign = 0;
139 		ht->ht_Voices[i].vc_FilterSpeed = 0;
140 		ht->ht_Voices[i].vc_FilterSlidingIn = 0;
141 		ht->ht_Voices[i].vc_IgnoreFilter = 0;
142 		ht->ht_Voices[i].vc_PerfCurrent = 0;
143 		ht->ht_Voices[i].vc_PerfSpeed = 0;
144 		ht->ht_Voices[i].vc_WaveLength = 0;
145 		ht->ht_Voices[i].vc_NoteDelayOn = 0;
146 		ht->ht_Voices[i].vc_NoteCutOn = 0;
147 		ht->ht_Voices[i].vc_AudioPeriod = 0;
148 		ht->ht_Voices[i].vc_AudioVolume = 0;
149 		ht->ht_Voices[i].vc_VoiceVolume = 0;
150 		ht->ht_Voices[i].vc_VoicePeriod = 0;
151 		ht->ht_Voices[i].vc_VoiceNum = 0;
152 		ht->ht_Voices[i].vc_WNRandom = 0;
153 		ht->ht_Voices[i].vc_SquareWait = 0;
154 		ht->ht_Voices[i].vc_FilterWait = 0;
155 		ht->ht_Voices[i].vc_PerfWait = 0;
156 		ht->ht_Voices[i].vc_NoteDelayWait = 0;
157 		ht->ht_Voices[i].vc_NoteCutWait = 0;
158 		ht->ht_Voices[i].vc_PerfList = 0;
159 		ht->ht_Voices[i].vc_RingSamplePos = 0;
160 		ht->ht_Voices[i].vc_RingDelta = 0;
161 		ht->ht_Voices[i].vc_RingPlantPeriod = 0;
162 		ht->ht_Voices[i].vc_RingAudioPeriod = 0;
163 		ht->ht_Voices[i].vc_RingNewWaveform = 0;
164 		ht->ht_Voices[i].vc_RingWaveform = 0;
165 		ht->ht_Voices[i].vc_RingFixedPeriod = 0;
166 		ht->ht_Voices[i].vc_RingBasePeriod = 0;
167 
168 		ht->ht_Voices[i].vc_RingMixSource = NULL;
169 		ht->ht_Voices[i].vc_RingAudioSource = NULL;
170 
171 		memset(&ht->ht_Voices[i].vc_SquareTempBuffer, 0, 0x80);
172 		memset(&ht->ht_Voices[i].vc_ADSR, 0, sizeof (struct hvl_envelope));
173 		memset(&ht->ht_Voices[i].vc_VoiceBuffer, 0 ,0x281);
174 		memset(&ht->ht_Voices[i].vc_RingVoiceBuffer, 0 ,0x281);
175 
176 		ht->ht_Voices[i].vc_Delta = 1;
177 		ht->ht_Voices[i].vc_OverrideTranspose = 1000;  // 1.5
178 		ht->ht_Voices[i].vc_WNRandom          = 0x280;
179 		ht->ht_Voices[i].vc_VoiceNum          = i;
180 		ht->ht_Voices[i].vc_TrackMasterVolume = 0x40;
181 		ht->ht_Voices[i].vc_TrackOn           = 1;
182 		ht->ht_Voices[i].vc_MixSource         = ht->ht_Voices[i].vc_VoiceBuffer;
183 	}
184 
185 	ht->ht_defpanleft  = stereopan_left[ht->ht_defstereo];
186 	ht->ht_defpanright = stereopan_right[ht->ht_defstereo];
187 }
188 
189 /* half-public */
190 void __attribute__ ((visibility ("internal"))) hvl_InitReplayer( void )
191 {
192 	hvl_GenPanningTables ();
193 	hvl_GenSawtooth ( &waves[WO_SAWTOOTH_04], 0x04 );
194 	hvl_GenSawtooth ( &waves[WO_SAWTOOTH_08], 0x08 );
195 	hvl_GenSawtooth ( &waves[WO_SAWTOOTH_10], 0x10 );
196 	hvl_GenSawtooth ( &waves[WO_SAWTOOTH_20], 0x20 );
197 	hvl_GenSawtooth ( &waves[WO_SAWTOOTH_40], 0x40 );
198 	hvl_GenSawtooth ( &waves[WO_SAWTOOTH_80], 0x80 );
199 	hvl_GenTriangle ( &waves[WO_TRIANGLE_04], 0x04 );
200 	hvl_GenTriangle ( &waves[WO_TRIANGLE_08], 0x08 );
201 	hvl_GenTriangle ( &waves[WO_TRIANGLE_10], 0x10 );
202 	hvl_GenTriangle ( &waves[WO_TRIANGLE_20], 0x20 );
203 	hvl_GenTriangle ( &waves[WO_TRIANGLE_40], 0x40 );
204 	hvl_GenTriangle ( &waves[WO_TRIANGLE_80], 0x80 );
initialize_windowaggregate(WindowAggState * winstate,WindowStatePerFunc perfuncstate,WindowStatePerAgg peraggstate)205 	hvl_GenSquare ( &waves[WO_SQUARES] );
206 	hvl_GenWhiteNoise ( &waves[WO_WHITENOISE], WHITENOISELEN );
207 	hvl_GenFilterWaves ( &waves[WO_TRIANGLE_04], &waves[WO_LOWPASSES], &waves[WO_HIGHPASSES] );
208 }
209 
210 /* half-public */
211 int __attribute__ ((visibility ("internal"))) hvl_InitSubsong ( struct hvl_tune *ht, uint32_t nr )
212 {
213 	uint32_t PosNr, i;
214 
215 	if ( nr > ht->ht_SubsongNr )
216 	{
217 		return FALSE;
218 	}
219 
220 	ht->ht_SongNum = nr;
221 
222 	PosNr = 0;
223 	if ( nr )
224 	{
225 		PosNr = ht->ht_Subsongs[nr-1];
226 	}
227 
228 	ht->ht_PosNr          = PosNr;
229 	ht->ht_PosJump        = 0;
230 	ht->ht_PatternBreak   = 0;
231 	ht->ht_NoteNr         = 0;
232 	ht->ht_PosJumpNote    = 0;
233 	ht->ht_Tempo          = 6;
234 	ht->ht_StepWaitFrames = 0;
235 	ht->ht_GetNewPosition = 1;
236 	ht->ht_SongEndReached = 0;
237 	ht->ht_PlayingTime    = 0;
238 
239 	for ( i=0; i<MAX_CHANNELS; i+=4 )
advance_windowaggregate(WindowAggState * winstate,WindowStatePerFunc perfuncstate,WindowStatePerAgg peraggstate)240 	{
241 		ht->ht_Voices[i+0].vc_Pan          = ht->ht_defpanleft;
242 		ht->ht_Voices[i+0].vc_SetPan       = ht->ht_defpanleft; // 1.4
243 		ht->ht_Voices[i+0].vc_PanMultLeft  = panning_left[ht->ht_defpanleft];
244 		ht->ht_Voices[i+0].vc_PanMultRight = panning_right[ht->ht_defpanleft];
245 		ht->ht_Voices[i+1].vc_Pan          = ht->ht_defpanright;
246 		ht->ht_Voices[i+1].vc_SetPan       = ht->ht_defpanright; // 1.4
247 		ht->ht_Voices[i+1].vc_PanMultLeft  = panning_left[ht->ht_defpanright];
248 		ht->ht_Voices[i+1].vc_PanMultRight = panning_right[ht->ht_defpanright];
249 		ht->ht_Voices[i+2].vc_Pan          = ht->ht_defpanright;
250 		ht->ht_Voices[i+2].vc_SetPan       = ht->ht_defpanright; // 1.4
251 		ht->ht_Voices[i+2].vc_PanMultLeft  = panning_left[ht->ht_defpanright];
252 		ht->ht_Voices[i+2].vc_PanMultRight = panning_right[ht->ht_defpanright];
253 		ht->ht_Voices[i+3].vc_Pan          = ht->ht_defpanleft;
254 		ht->ht_Voices[i+3].vc_SetPan       = ht->ht_defpanleft;  // 1.4
255 		ht->ht_Voices[i+3].vc_PanMultLeft  = panning_left[ht->ht_defpanleft];
256 		ht->ht_Voices[i+3].vc_PanMultRight = panning_right[ht->ht_defpanleft];
257 	}
258 
259 	hvl_reset_some_stuff ( ht );
260 
261 	return TRUE;
262 }
263 
264 static void hvl_process_stepfx_1 ( struct hvl_tune *ht, struct hvl_voice *voice, int32_t FX, int32_t FXParam )
265 {
266 	switch ( FX )
267 	{
268 		case 0x0:  // Position Jump HI
269 			if ( ((FXParam&0x0f) > 0) && ((FXParam&0x0f) <= 9) )
270 			{
271 				ht->ht_PosJump = FXParam & 0xf;
272 			}
273 			break;
274 
275 		case 0x5:  // Volume Slide + Tone Portamento
276 		case 0xa:  // Volume Slide
277 			voice->vc_VolumeSlideDown = FXParam & 0x0f;
278 			voice->vc_VolumeSlideUp   = FXParam >> 4;
279 			break;
280 
281 		case 0x7:  // Panning
282 			if ( FXParam > 127 )
283 			{
284 				FXParam -= 256;
285 			}
286 			voice->vc_Pan          = (FXParam+128);
287 			voice->vc_SetPan       = (FXParam+128); // 1.4
288 			voice->vc_PanMultLeft  = panning_left[voice->vc_Pan];
289 			voice->vc_PanMultRight = panning_right[voice->vc_Pan];
290 			break;
291 
292 		case 0xb: // Position jump
293 			ht->ht_PosJump      = ht->ht_PosJump*100 + (FXParam & 0x0f) + (FXParam >> 4)*10;
294 			ht->ht_PatternBreak = 1;
295 			if ( ht->ht_PosJump <= ht->ht_PosNr )
296 			{
297 			        ht->ht_SongEndReached = 1;
298 			}
299 			break;
300 
301 		case 0xd: // Pattern break
302 			ht->ht_PosJump      = ht->ht_PosNr+1;
303 			ht->ht_PosJumpNote  = (FXParam & 0x0f) + (FXParam>>4)*10;
304 			ht->ht_PatternBreak = 1;
305 			if ( ht->ht_PosJumpNote >  ht->ht_TrackLength )
306 			{
307 				ht->ht_PosJumpNote = 0;
308 			}
309 			break;
310 
311 		case 0xe: // Extended commands
312 			switch ( FXParam >> 4 )
313 			{
314 				case 0xc: // Note cut
315 					if ( (FXParam & 0x0f) < ht->ht_Tempo )
316 					{
317 						voice->vc_NoteCutWait = FXParam & 0x0f;
318 						if ( voice->vc_NoteCutWait )
319 						{
320 							voice->vc_NoteCutOn      = 1;
321 							voice->vc_HardCutRelease = 0;
322 						}
323 					}
324 					break;
325 
326 				// 1.6: 0xd case removed
327 			}
328 			break;
329 
330 		case 0xf: // Speed
331 			ht->ht_Tempo = FXParam;
332 			if ( FXParam == 0 )
333 			{
334 				ht->ht_SongEndReached = 1;
335 			}
336 			break;
337 	}
338 }
339 
340 static void hvl_process_stepfx_2 ( struct hvl_tune *ht, struct hvl_voice *voice, int32_t FX, int32_t FXParam, int32_t *Note )
341 {
342 	switch ( FX )
343 	{
344 		case 0x9: // Set squarewave offset
345 			voice->vc_SquarePos    = FXParam >> (5 - voice->vc_WaveLength);
346 			voice->vc_PlantSquare  = 1;
347 			voice->vc_IgnoreSquare = 1;
348 			break;
349 
350 		case 0x3: // Tone portamento
351 			if ( FXParam != 0 )
352 			{
353 				voice->vc_PeriodSlideSpeed = FXParam;
354 			}
355 		case 0x5: // Tone portamento + volume slide
356 			if ( *Note )
357 			{
358 				int32_t new, diff;
359 
360 				new   = period_tab[*Note];
361 				diff  = period_tab[voice->vc_TrackPeriod];
362 				diff -= new;
363 				new   = diff + voice->vc_PeriodSlidePeriod;
364 
365 				if( new )
366 				{
367 					voice->vc_PeriodSlideLimit = -diff;
368 				}
369 			}
370 			voice->vc_PeriodSlideOn        = 1;
371 			voice->vc_PeriodSlideWithLimit = 1;
372 			*Note = 0;
373 			break;
374 	}
375 }
376 
377 static void hvl_process_stepfx_3 ( struct hvl_tune *ht, struct hvl_voice *voice, int32_t FX, int32_t FXParam )
378 {
379 	int32_t i;
380 
381 	switch ( FX )
382 	{
383 		case 0x01: // Portamento up (period slide down)
384 			voice->vc_PeriodSlideSpeed     = -FXParam;
385 			voice->vc_PeriodSlideOn        = 1;
386 			voice->vc_PeriodSlideWithLimit = 0;
387 			break;
388 		case 0x02: // Portamento down
389 			voice->vc_PeriodSlideSpeed     = FXParam;
390 			voice->vc_PeriodSlideOn        = 1;
391 			voice->vc_PeriodSlideWithLimit = 0;
392 			break;
393 		case 0x04: // Filter override
394 			if ( ( FXParam == 0 ) || ( FXParam == 0x40 ) )
395 			{
396 				break;
397 			}
398 			if ( FXParam < 0x40 )
399 			{
400 				voice->vc_IgnoreFilter = FXParam;
401 				break;
402 			}
403 			if ( FXParam > 0x7f )
404 			{
405 				break;
406 			}
407 			voice->vc_FilterPos = FXParam - 0x40;
408 			break;
409 		case 0x0c: // Volume
410 			FXParam &= 0xff;
411 			if ( FXParam <= 0x40 )
412 			{
413 				voice->vc_NoteMaxVolume = FXParam;
414 				break;
415 			}
416 
advance_windowaggregate_base(WindowAggState * winstate,WindowStatePerFunc perfuncstate,WindowStatePerAgg peraggstate)417 			if ( (FXParam -= 0x50) < 0 )
418 			{
419 				break;  // 1.6
420 			}
421 
422 			if ( FXParam <= 0x40 )
423 			{
424 				for( i=0; i<ht->ht_Channels; i++ )
425 				{
426 					ht->ht_Voices[i].vc_TrackMasterVolume = FXParam;
427 				}
428 				break;
429 			}
430 
431 			if ( (FXParam -= 0xa0-0x50) < 0 )
432 			{
433 				break; // 1.6
434 			}
435 
436 			if ( FXParam <= 0x40 )
437 			{
438 				voice->vc_TrackMasterVolume = FXParam;
439 			}
440 			break;
441 
442 		case 0xe: // Extended commands;
443 			switch ( FXParam >> 4 )
444 			{
445 				case 0x1: // Fineslide up
446 					voice->vc_PeriodSlidePeriod -= (FXParam & 0x0f); // 1.8
447 					voice->vc_PlantPeriod = 1;
448 					break;
449 
450 				case 0x2: // Fineslide down
451 					voice->vc_PeriodSlidePeriod += (FXParam & 0x0f); // 1.8
452 					voice->vc_PlantPeriod = 1;
453 					break;
454 
455 				case 0x4: // Vibrato control
456 					voice->vc_VibratoDepth = FXParam & 0x0f;
457 					break;
458 
459 				case 0x0a: // Fine volume up
460 					voice->vc_NoteMaxVolume += FXParam & 0x0f;
461 
462 					if ( voice->vc_NoteMaxVolume > 0x40 )
463 					{
464 						voice->vc_NoteMaxVolume = 0x40;
465 					}
466 					break;
467 
468 				case 0x0b: // Fine volume down
469 					voice->vc_NoteMaxVolume -= FXParam & 0x0f;
470 
471 					if ( voice->vc_NoteMaxVolume < 0 )
472 					{
473 						voice->vc_NoteMaxVolume = 0;
474 					}
475 					break;
476 
477 				case 0x0f: // Misc flags (1.5)
478 					if( ht->ht_Version < 1 )
479 					{
480 						break;
481 					}
482 					switch ( FXParam & 0xf )
483 					{
484 						case 1:
485 							voice->vc_OverrideTranspose = voice->vc_Transpose;
486 							break;
487 					}
488 					break;
489 			}
490 			break;
491 	}
492 }
493 
494 static void hvl_process_step ( struct hvl_tune *ht, struct hvl_voice *voice )
495 {
496 	int32_t  Note, Instr, donenotedel;
497 	struct   hvl_step *Step;
498 
499 	if ( voice->vc_TrackOn == 0 )
500 	{
501 		return;
502 	}
503 
504 	voice->vc_VolumeSlideUp = 0;
505 	voice->vc_VolumeSlideDown = 0;
506 
507 	Step = &ht->ht_Tracks
508 		[
509 			ht->ht_Positions
510 			[
511 				ht->ht_PosNr
512 			].pos_Track
513 			[
514 				voice->vc_VoiceNum
515 			]
516 		][
517 			ht->ht_NoteNr
518 		];
519 
520 	Note    = Step->stp_Note;
521 	Instr   = Step->stp_Instrument;
522 
523 	// --------- 1.6: from here --------------
524 
525 	donenotedel = 0;
526 
527 	// Do notedelay here
528 	if ( ((Step->stp_FX&0xf)==0xe) && ((Step->stp_FXParam&0xf0)==0xd0) )
529 	{
530 		if ( voice->vc_NoteDelayOn )
531 		{
532 			voice->vc_NoteDelayOn = 0;
533 			donenotedel = 1;
534 		} else {
535 			if ( (Step->stp_FXParam&0x0f) < ht->ht_Tempo )
536 			{
537 				voice->vc_NoteDelayWait = Step->stp_FXParam & 0x0f;
538 				if( voice->vc_NoteDelayWait )
539 				{
540 					voice->vc_NoteDelayOn = 1;
541 					return;
542 				}
543 			}
544 		}
545 	}
546 
547 	if ( (donenotedel==0) && ((Step->stp_FXb&0xf)==0xe) && ((Step->stp_FXbParam&0xf0)==0xd0) )
548 	{
549 		if ( voice->vc_NoteDelayOn )
550 		{
551 			voice->vc_NoteDelayOn = 0;
552 		} else {
553 			if ( (Step->stp_FXbParam&0x0f) < ht->ht_Tempo )
554 			{
555 				voice->vc_NoteDelayWait = Step->stp_FXbParam & 0x0f;
556 				if ( voice->vc_NoteDelayWait )
557 				{
558 					voice->vc_NoteDelayOn = 1;
559 					return;
560 				}
561 			}
562 		}
563 	}
564 
565 	// --------- 1.6: to here --------------
566 
567 	if ( Note )
568 	{
569 		voice->vc_OverrideTranspose = 1000; // 1.5
570 	}
571 
572 	hvl_process_stepfx_1( ht, voice, Step->stp_FX &0xf, Step->stp_FXParam );
573 	hvl_process_stepfx_1( ht, voice, Step->stp_FXb&0xf, Step->stp_FXbParam );
574 
575 	if ( ( Instr ) && ( Instr <= ht->ht_InstrumentNr ) )
576 	{
577 		struct hvl_instrument *Ins;
578 		int16_t SquareLower, SquareUpper, d6, d3, d4;
579 
finalize_windowaggregate(WindowAggState * winstate,WindowStatePerFunc perfuncstate,WindowStatePerAgg peraggstate,Datum * result,bool * isnull)580 		/* 1.4: Reset panning to last set position */
581 		voice->vc_Pan          = voice->vc_SetPan;
582 		voice->vc_PanMultLeft  = panning_left[voice->vc_Pan];
583 		voice->vc_PanMultRight = panning_right[voice->vc_Pan];
584 
585 		voice->vc_PeriodSlideSpeed  = 0;
586 		voice->vc_PeriodSlidePeriod = 0;
587 		voice->vc_PeriodSlideLimit  = 0;
588 
589 		voice->vc_PerfSubVolume    = 0x40;
590 		voice->vc_ADSRVolume       = 0;
591 		voice->vc_Instrument       = Ins = &ht->ht_Instruments[Instr];
592 		voice->vc_SamplePos        = 0;
593 
594 		voice->vc_ADSR.aFrames     = Ins->ins_Envelope.aFrames;
595 		voice->vc_ADSR.aVolume     = Ins->ins_Envelope.aFrames ? Ins->ins_Envelope.aVolume * 256 / voice->vc_ADSR.aFrames : Ins->ins_Envelope.aVolume * 256;
596 		voice->vc_ADSR.dFrames     = Ins->ins_Envelope.dFrames;
597 		voice->vc_ADSR.dVolume     = Ins->ins_Envelope.dFrames ? (Ins->ins_Envelope.dVolume-Ins->ins_Envelope.aVolume) * 256 / voice->vc_ADSR.dFrames : Ins->ins_Envelope.dVolume * 256; // XXX
598 		voice->vc_ADSR.sFrames     = Ins->ins_Envelope.sFrames;
599 		voice->vc_ADSR.rFrames     = Ins->ins_Envelope.rFrames;
600 		voice->vc_ADSR.rVolume     = Ins->ins_Envelope.rFrames ? (Ins->ins_Envelope.rVolume-Ins->ins_Envelope.dVolume) * 256 / voice->vc_ADSR.rFrames : Ins->ins_Envelope.rVolume * 256; // XXX
601 
602 		voice->vc_WaveLength       = Ins->ins_WaveLength;
603 		voice->vc_NoteMaxVolume    = Ins->ins_Volume;
604 
605 		voice->vc_VibratoCurrent   = 0;
606 		voice->vc_VibratoDelay     = Ins->ins_VibratoDelay;
607 		voice->vc_VibratoDepth     = Ins->ins_VibratoDepth;
608 		voice->vc_VibratoSpeed     = Ins->ins_VibratoSpeed;
609 		voice->vc_VibratoPeriod    = 0;
610 
611 		voice->vc_HardCutRelease   = Ins->ins_HardCutRelease;
612 		voice->vc_HardCut          = Ins->ins_HardCutReleaseFrames;
613 
614 		voice->vc_IgnoreSquare    = 0;
615 		voice->vc_SquareSlidingIn = 0;
616 		voice->vc_SquareWait      = 0;
617 		voice->vc_SquareOn        = 0;
618 
619 		SquareLower = Ins->ins_SquareLowerLimit >> (5 - voice->vc_WaveLength);
620 		SquareUpper = Ins->ins_SquareUpperLimit >> (5 - voice->vc_WaveLength);
621 
622 		if ( SquareUpper < SquareLower )
623 		{
624 			int16_t t = SquareUpper;
625 			SquareUpper = SquareLower;
626 			SquareLower = t;
627 		}
628 
629 		voice->vc_SquareUpperLimit = SquareUpper;
630 		voice->vc_SquareLowerLimit = SquareLower;
631 
632 		voice->vc_IgnoreFilter    = 0;
633 		voice->vc_FilterWait      = 0;
634 		voice->vc_FilterOn        = 0;
635 		voice->vc_FilterSlidingIn = 0;
636 
637 		d6 = Ins->ins_FilterSpeed;
638 		d3 = Ins->ins_FilterLowerLimit;
639 		d4 = Ins->ins_FilterUpperLimit;
640 
641 		if ( d3 & 0x80 )
642 		{
643 			d6 |= 0x20;
644 		}
645 		if ( d4 & 0x80 )
646 		{
647 			d6 |= 0x40;
648 		}
649 
650 		voice->vc_FilterSpeed = d6;
651 		d3 &= ~0x80;
652 		d4 &= ~0x80;
653 
654 		if ( d3 > d4 )
655 		{
656 			int16_t t = d3;
657 			d3 = d4;
658 			d4 = t;
659 		}
660 
661 		voice->vc_FilterUpperLimit = d4;
eval_windowaggregates(WindowAggState * winstate)662 		voice->vc_FilterLowerLimit = d3;
663 		voice->vc_FilterPos        = 32;
664 
665 		voice->vc_PerfWait  = voice->vc_PerfCurrent = 0;
666 		voice->vc_PerfSpeed = Ins->ins_PList.pls_Speed;
667 		voice->vc_PerfList  = &voice->vc_Instrument->ins_PList;
668 
669 		voice->vc_RingMixSource   = NULL;   // No ring modulation
670 		voice->vc_RingSamplePos   = 0;
671 		voice->vc_RingPlantPeriod = 0;
672 		voice->vc_RingNewWaveform = 0;
673 	}
674 
675 	voice->vc_PeriodSlideOn = 0;
676 
677 	hvl_process_stepfx_2 ( ht, voice, Step->stp_FX&0xf,  Step->stp_FXParam,  &Note );
678 	hvl_process_stepfx_2 ( ht, voice, Step->stp_FXb&0xf, Step->stp_FXbParam, &Note );
679 
680 	if ( Note )
681 	{
682 		voice->vc_TrackPeriod = Note;
683 		voice->vc_PlantPeriod = 1;
684 	}
685 
686 	hvl_process_stepfx_3 ( ht, voice, Step->stp_FX&0xf,  Step->stp_FXParam );
687 	hvl_process_stepfx_3 ( ht, voice, Step->stp_FXb&0xf, Step->stp_FXbParam );
688 }
689 
690 static void hvl_plist_command_parse ( struct hvl_tune *ht, struct hvl_voice *voice, int32_t FX, int32_t FXParam )
691 {
692 	switch ( FX )
693 	{
694 		case 0:
695 			if ( ( FXParam > 0 ) && ( FXParam < 0x40 ) )
696 			{
697 				if ( voice->vc_IgnoreFilter )
698 				{
699 					voice->vc_FilterPos    = voice->vc_IgnoreFilter;
700 					voice->vc_IgnoreFilter = 0;
701 				} else {
702 					voice->vc_FilterPos    = FXParam;
703 				}
704 				voice->vc_NewWaveform = 1;
705 			}
706 			break;
707 
708 		case 1:
709 			voice->vc_PeriodPerfSlideSpeed = FXParam;
710 			voice->vc_PeriodPerfSlideOn    = 1;
711 			break;
712 
713 		case 2:
714 			voice->vc_PeriodPerfSlideSpeed = -FXParam;
715 			voice->vc_PeriodPerfSlideOn    = 1;
716 			break;
717 
718 		case 3:
719 			if ( voice->vc_IgnoreSquare == 0 )
720 			{
721 				voice->vc_SquarePos = FXParam >> (5-voice->vc_WaveLength);
722 			} else {
723 				voice->vc_IgnoreSquare = 0;
724 			}
725 			break;
726 
727 		case 4:
728 			if ( FXParam == 0 )
729 			{
730 				voice->vc_SquareInit = (voice->vc_SquareOn ^= 1);
731 				voice->vc_SquareSign = 1;
732 			} else {
733 				if ( FXParam & 0x0f )
734 				{
735 					voice->vc_SquareInit = (voice->vc_SquareOn ^= 1);
736 					voice->vc_SquareSign = 1;
737 					if (( FXParam & 0x0f ) == 0x0f )
738 					{
739 						voice->vc_SquareSign = -1;
740 					}
741 				}
742 				if ( FXParam & 0xf0 )
743 				{
744 					voice->vc_FilterInit = (voice->vc_FilterOn ^= 1);
745 					voice->vc_FilterSign = 1;
746 					if (( FXParam & 0xf0 ) == 0xf0 )
747 					{
748 						voice->vc_FilterSign = -1;
749 					}
750 				}
751 			}
752 			break;
753 
754 		case 5:
755 			voice->vc_PerfCurrent = FXParam;
756 			break;
757 
758 		case 7:
759 			// Ring modulate with triangle
760 			if (( FXParam >= 1 ) && ( FXParam <= 0x3C ))
761 			{
762 				voice->vc_RingBasePeriod  = FXParam;
763 				voice->vc_RingFixedPeriod = 1;
764 			} else if (( FXParam >= 0x81 ) && ( FXParam <= 0xBC ))
765 			{
766 				voice->vc_RingBasePeriod  = FXParam-0x80;
767 				voice->vc_RingFixedPeriod = 0;
768 			} else {
769 				voice->vc_RingBasePeriod  = 0;
770 				voice->vc_RingFixedPeriod = 0;
771 				voice->vc_RingNewWaveform = 0;
772 				voice->vc_RingAudioSource = NULL; // turn it off
773 				voice->vc_RingMixSource   = NULL;
774 				break;
775 			}
776 			voice->vc_RingWaveform    = 0;
777 			voice->vc_RingNewWaveform = 1;
778 			voice->vc_RingPlantPeriod = 1;
779 			break;
780 
781 		case 8:  // Ring modulate with sawtooth
782 			if (( FXParam >= 1 ) && ( FXParam <= 0x3C ))
783 			{
784 				voice->vc_RingBasePeriod  = FXParam;
785 				voice->vc_RingFixedPeriod = 1;
786 			} else if (( FXParam >= 0x81 ) && ( FXParam <= 0xBC ))
787 			{
788 				voice->vc_RingBasePeriod  = FXParam-0x80;
789 				voice->vc_RingFixedPeriod = 0;
790 			} else {
791 				voice->vc_RingBasePeriod  = 0;
792 				voice->vc_RingFixedPeriod = 0;
793 				voice->vc_RingNewWaveform = 0;
794 				voice->vc_RingAudioSource = NULL;
795 				voice->vc_RingMixSource   = NULL;
796 				break;
797 			}
798 
799 			voice->vc_RingWaveform    = 1;
800 			voice->vc_RingNewWaveform = 1;
801 			voice->vc_RingPlantPeriod = 1;
802 			break;
803 
804 			/* New in HivelyTracker 1.4 */
805 		case 9:
806 			if ( FXParam > 127 )
807 			{
808 				FXParam -= 256;
809 			}
810 			voice->vc_Pan          = (FXParam+128);
811 			voice->vc_PanMultLeft  = panning_left[voice->vc_Pan];
812 			voice->vc_PanMultRight = panning_right[voice->vc_Pan];
813 			break;
814 
815 		case 12:
816 			if ( FXParam <= 0x40 )
817 			{
818 				voice->vc_NoteMaxVolume = FXParam;
819 				break;
820 			}
821 
822 			if ( (FXParam -= 0x50) < 0 )
823 			{
824 				break;
825 			}
826 
827 			if ( FXParam <= 0x40 )
828 			{
829 				voice->vc_PerfSubVolume = FXParam;
830 				break;
831 			}
832 
833 			if ( (FXParam -= 0xa0-0x50) < 0 )
834 			{
835 				break;
836 			}
837 
838 			if ( FXParam <= 0x40 )
839 			{
840 				voice->vc_TrackMasterVolume = FXParam;
841 			}
842 			break;
843 
844 		case 15:
845 			voice->vc_PerfSpeed = voice->vc_PerfWait = FXParam;
846 			break;
847 	}
848 }
849 
850 static void hvl_process_frame ( struct hvl_tune *ht, struct hvl_voice *voice )
851 {
852 	static const uint8_t Offsets[] = {
853 		0x00,
854 		0x04,
855 		0x04 + 0x08,
856 		0x04 + 0x08 + 0x10,
857 		0x04 + 0x08 + 0x10 + 0x20,
858 		0x04 + 0x08 + 0x10 + 0x20 + 0x40
859 	};
860 
861 	if ( voice->vc_TrackOn == 0 )
862 	{
863 		return;
864 	}
865 
866 	if ( voice->vc_NoteDelayOn )
867 	{
868 		if ( voice->vc_NoteDelayWait <= 0 )
869 		{
870 			hvl_process_step ( ht, voice );
871 		} else {
872 			voice->vc_NoteDelayWait--;
873 		}
874 	}
875 
876 	if ( voice->vc_HardCut )
877 	{
878 		int32_t nextinst;
879 
880 		if ( ht->ht_NoteNr+1 < ht->ht_TrackLength )
881 		{
882 			nextinst = ht->ht_Tracks[voice->vc_Track][ht->ht_NoteNr+1].stp_Instrument;
883 		} else {
884 			nextinst = ht->ht_Tracks[voice->vc_NextTrack][0].stp_Instrument;
885 		}
886 
887 		if ( nextinst )
888 		{
889 			int32_t d1;
890 
891 			d1 = ht->ht_Tempo - voice->vc_HardCut;
892 
893 			if ( d1 < 0 )
894 			{
895 				d1 = 0;
896 			}
897 
898 			if ( !voice->vc_NoteCutOn )
899 			{
900 				voice->vc_NoteCutOn       = 1;
901 				voice->vc_NoteCutWait     = d1;
902 				voice->vc_HardCutReleaseF = -(d1-ht->ht_Tempo);
903 			} else {
904 				voice->vc_HardCut = 0;
905 			}
906 		}
907 	}
908 
909 	if ( voice->vc_NoteCutOn )
910 	{
911 		if ( voice->vc_NoteCutWait <= 0 )
912 		{
913 			voice->vc_NoteCutOn = 0;
914 
915 			if ( voice->vc_HardCutRelease )
916 			{
917 				voice->vc_ADSR.rVolume = -(voice->vc_ADSRVolume - (voice->vc_Instrument->ins_Envelope.rVolume << 8)) / voice->vc_HardCutReleaseF;
918 				voice->vc_ADSR.rFrames = voice->vc_HardCutReleaseF;
919 				voice->vc_ADSR.aFrames = voice->vc_ADSR.dFrames = voice->vc_ADSR.sFrames = 0;
920 			} else {
921 				voice->vc_NoteMaxVolume = 0;
922 			}
923 		} else {
924 			voice->vc_NoteCutWait--;
925 		}
926 	}
927 
928 	// ADSR envelope
929 	if ( voice->vc_ADSR.aFrames )
930 	{
931 		voice->vc_ADSRVolume += voice->vc_ADSR.aVolume;
932 
933 		if ( --voice->vc_ADSR.aFrames <= 0 )
934 		{
935 			voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.aVolume << 8;
936 		}
937 	} else if ( voice->vc_ADSR.dFrames )
938 	{
939 		voice->vc_ADSRVolume += voice->vc_ADSR.dVolume;
940 
941 		if ( --voice->vc_ADSR.dFrames <= 0 )
942 		{
943 			voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.dVolume << 8;
944 		}
945 	} else if ( voice->vc_ADSR.sFrames )
946 	{
947 		voice->vc_ADSR.sFrames--;
948 	} else if ( voice->vc_ADSR.rFrames )
949 	{
950 		voice->vc_ADSRVolume += voice->vc_ADSR.rVolume;
951 
952 		if ( --voice->vc_ADSR.rFrames <= 0 )
953 		{
954 			voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.rVolume << 8;
955 		}
956 	}
957 
958 	// VolumeSlide
959 	voice->vc_NoteMaxVolume = voice->vc_NoteMaxVolume + voice->vc_VolumeSlideUp - voice->vc_VolumeSlideDown;
960 
961 	if ( voice->vc_NoteMaxVolume < 0 )
962 	{
963 		voice->vc_NoteMaxVolume = 0;
964 	} else if ( voice->vc_NoteMaxVolume > 0x40 )
965 	{
966 		voice->vc_NoteMaxVolume = 0x40;
967 	}
968 
969 	// Portamento
970 	if ( voice->vc_PeriodSlideOn )
971 	{
972 		if ( voice->vc_PeriodSlideWithLimit )
973 		{
974 			int32_t  d0, d2;
975 
976 			d0 = voice->vc_PeriodSlidePeriod - voice->vc_PeriodSlideLimit;
977 			d2 = voice->vc_PeriodSlideSpeed;
978 
979 			if ( d0 > 0 )
980 			{
981 				d2 = -d2;
982 			}
983 
984 			if ( d0 )
985 			{
986 				int32_t d3;
987 
988 				d3 = (d0 + d2) ^ d0;
989 
990 				if ( d3 >= 0 )
991 				{
992 					d0 = voice->vc_PeriodSlidePeriod + d2;
993 				} else {
994 					d0 = voice->vc_PeriodSlideLimit;
995 				}
996 
997 				voice->vc_PeriodSlidePeriod = d0;
998 				voice->vc_PlantPeriod = 1;
999 			}
1000 		} else {
1001 			voice->vc_PeriodSlidePeriod += voice->vc_PeriodSlideSpeed;
1002 			voice->vc_PlantPeriod = 1;
1003 		}
1004 	}
1005 
1006 	// Vibrato
1007 	if ( voice->vc_VibratoDepth )
1008 	{
1009 		if ( voice->vc_VibratoDelay <= 0 )
1010 		{
1011 			voice->vc_VibratoPeriod = (vib_tab[voice->vc_VibratoCurrent] * voice->vc_VibratoDepth) >> 7;
1012 			voice->vc_PlantPeriod = 1;
1013 			voice->vc_VibratoCurrent = (voice->vc_VibratoCurrent + voice->vc_VibratoSpeed) & 0x3f;
1014 		} else {
1015 			voice->vc_VibratoDelay--;
1016 		}
1017 	}
1018 
1019 	// PList
1020 	if ( voice->vc_PerfList != 0 )
1021 	{
1022 		if ( voice->vc_Instrument && voice->vc_PerfCurrent < voice->vc_Instrument->ins_PList.pls_Length )
1023 		{
1024 			if ( --voice->vc_PerfWait <= 0 )
1025 			{
1026 				uint32_t i;
1027 				int32_t cur;
1028 
1029 				cur = voice->vc_PerfCurrent++;
1030 				voice->vc_PerfWait = voice->vc_PerfSpeed;
1031 
eval_windowfunction(WindowAggState * winstate,WindowStatePerFunc perfuncstate,Datum * result,bool * isnull)1032 				if ( voice->vc_PerfList->pls_Entries[cur].ple_Waveform )
1033 				{
1034 					voice->vc_Waveform             = voice->vc_PerfList->pls_Entries[cur].ple_Waveform-1;
1035 					voice->vc_NewWaveform          = 1;
1036 					voice->vc_PeriodPerfSlideSpeed = voice->vc_PeriodPerfSlidePeriod = 0;
1037 				}
1038 
1039 				// Holdwave
1040 				voice->vc_PeriodPerfSlideOn = 0;
1041 
1042 				for( i=0; i<2; i++ )
1043 				{
1044 					hvl_plist_command_parse ( ht, voice, voice->vc_PerfList->pls_Entries[cur].ple_FX[i]&0xff, voice->vc_PerfList->pls_Entries[cur].ple_FXParam[i]&0xff );
1045 				}
1046 
1047 				// GetNote
1048 				if ( voice->vc_PerfList->pls_Entries[cur].ple_Note )
1049 				{
1050 					voice->vc_InstrPeriod = voice->vc_PerfList->pls_Entries[cur].ple_Note;
1051 					voice->vc_PlantPeriod = 1;
1052 					voice->vc_FixedNote   = voice->vc_PerfList->pls_Entries[cur].ple_Fixed;
1053 				}
1054 			}
1055 		} else {
1056 			if ( voice->vc_PerfWait )
1057 			{
1058 				voice->vc_PerfWait--;
1059 			} else {
1060 				voice->vc_PeriodPerfSlideSpeed = 0;
1061 			}
1062 		}
1063 	}
1064 
1065 	// PerfPortamento
1066 	if ( voice->vc_PeriodPerfSlideOn )
1067 	{
1068 		voice->vc_PeriodPerfSlidePeriod -= voice->vc_PeriodPerfSlideSpeed;
1069 
1070 		if ( voice->vc_PeriodPerfSlidePeriod )
1071 		{
1072 			voice->vc_PlantPeriod = 1;
1073 		}
1074 	}
1075 
1076 	if ( voice->vc_Waveform == 3-1 && voice->vc_SquareOn ) /* SQUARE */
1077 	{
begin_partition(WindowAggState * winstate)1078 		if ( --voice->vc_SquareWait <= 0 )
1079 		{
1080 			int32_t d1, d2, d3;
1081 
1082 			d1 = voice->vc_SquareLowerLimit;
1083 			d2 = voice->vc_SquareUpperLimit;
1084 			d3 = voice->vc_SquarePos;
1085 
1086 			if ( voice->vc_SquareInit )
1087 			{
1088 				voice->vc_SquareInit = 0;
1089 
1090 				if ( d3 <= d1 )
1091 				{
1092 					voice->vc_SquareSlidingIn = 1;
1093 					voice->vc_SquareSign = 1;
1094 				} else if ( d3 >= d2 )
1095 				{
1096 					voice->vc_SquareSlidingIn = 1;
1097 					voice->vc_SquareSign = -1;
1098 				}
1099 			}
1100 
1101 			// NoSquareInit
1102 			if ( d1 == d3 || d2 == d3 )
1103 			{
1104 				if ( voice->vc_SquareSlidingIn )
1105 				{
1106 					voice->vc_SquareSlidingIn = 0;
1107 				} else {
1108 					voice->vc_SquareSign = -voice->vc_SquareSign;
1109 				}
1110 			}
1111 
1112 			d3 += voice->vc_SquareSign;
1113 			voice->vc_SquarePos   = d3;
1114 			voice->vc_PlantSquare = 1;
1115 			voice->vc_SquareWait  = voice->vc_Instrument->ins_SquareSpeed;
1116 		}
1117 	}
1118 
1119 	if ( voice->vc_FilterOn && --voice->vc_FilterWait <= 0 )
1120 	{
1121 		uint32_t i, FMax;
1122 		int32_t d1, d2, d3;
1123 
1124 		d1 = voice->vc_FilterLowerLimit;
1125 		d2 = voice->vc_FilterUpperLimit;
1126 		d3 = voice->vc_FilterPos;
1127 
1128 		if ( voice->vc_FilterInit )
1129 		{
1130 			voice->vc_FilterInit = 0;
1131 			if ( d3 <= d1 )
1132 			{
1133 				voice->vc_FilterSlidingIn = 1;
1134 				voice->vc_FilterSign      = 1;
1135 			} else if ( d3 >= d2 )
1136 			{
1137 				voice->vc_FilterSlidingIn = 1;
1138 				voice->vc_FilterSign      = -1;
1139 			}
1140 		}
1141 
1142 		// NoFilterInit
1143 		FMax = (voice->vc_FilterSpeed < 3) ? (5-voice->vc_FilterSpeed) : 1;
1144 
1145 		for ( i=0; i<FMax; i++ )
1146 		{
1147 			if ( ( d1 == d3 ) || ( d2 == d3 ) )
1148 			{
1149 				if ( voice->vc_FilterSlidingIn )
1150 				{
1151 					voice->vc_FilterSlidingIn = 0;
1152 				} else {
1153 					voice->vc_FilterSign = -voice->vc_FilterSign;
1154 				}
1155 			}
1156 			d3 += voice->vc_FilterSign;
1157 		}
1158 
1159 		if( d3 < 1 )
1160 		{
1161 			d3 = 1;
1162 		}
1163 		if( d3 > 63 )
1164 		{
1165 			d3 = 63;
1166 		}
1167 		voice->vc_FilterPos   = d3;
1168 		voice->vc_NewWaveform = 1;
1169 		voice->vc_FilterWait  = voice->vc_FilterSpeed - 3;
1170 
1171 		if ( voice->vc_FilterWait < 1 )
1172 		{
1173 			voice->vc_FilterWait = 1;
1174 		}
1175 	}
1176 
1177 	if ( voice->vc_Waveform == 3-1 || voice->vc_PlantSquare ) /* SQUARE */
1178 	{
1179 		// CalcSquare
1180 		uint32_t  i;
1181 		int32_t   Delta;
1182 		int8_t   *SquarePtr;
1183 		int32_t  X;
1184 
1185 		SquarePtr = &waves[WO_SQUARES+(voice->vc_FilterPos-0x20)*(0xfc+0xfc+0x80*0x1f+0x80+0x280*3)];
1186 		X = voice->vc_SquarePos << (5 - voice->vc_WaveLength);
1187 
1188 		if ( X > 0x20 )
1189 		{
1190 			X = 0x40 - X;
1191 			voice->vc_SquareReverse = 1;
1192 		}
1193 
1194 		// OkDownSquare
1195 		if( X > 0 )
1196 		{
1197 			SquarePtr += (X-1) << 7;
1198 		}
1199 
1200 		Delta = 32 >> voice->vc_WaveLength;
1201 		ht->ht_WaveformTab[2] = voice->vc_SquareTempBuffer;
1202 
1203 		for ( i=0; i<(1<<voice->vc_WaveLength)*4; i++ )
1204 		{
1205 			voice->vc_SquareTempBuffer[i] = *SquarePtr;
1206 			SquarePtr += Delta;
1207 		}
1208 
1209 		voice->vc_NewWaveform = 1;
1210 		voice->vc_Waveform    = 3-1; /* SQUARE */
1211 		voice->vc_PlantSquare = 0;
1212 	}
1213 
1214 	if ( voice->vc_Waveform == 4-1 ) /* WHITENOISE */
1215 	{
1216 		voice->vc_NewWaveform = 1;
1217 	}
1218 
1219 	if ( voice->vc_RingNewWaveform )
1220 	{
1221 		int8_t *rasrc;
1222 
1223 		if ( voice->vc_RingWaveform > 1 )
1224 		{
1225 			voice->vc_RingWaveform = 1;
1226 		}
1227 
1228 		rasrc = ht->ht_WaveformTab[voice->vc_RingWaveform]; /* RingWaveform is either TRIANGLE or SAWTOOTH */
1229 		rasrc += Offsets[voice->vc_WaveLength];
1230 
1231 		voice->vc_RingAudioSource = rasrc;
1232 	}
1233 
1234 	if ( voice->vc_NewWaveform )
1235 	{
1236 		int8_t *AudioSource;
1237 
spool_tuples(WindowAggState * winstate,int64 pos)1238 		AudioSource = ht->ht_WaveformTab[voice->vc_Waveform];
1239 
1240 		if ( voice->vc_Waveform != 3-1 ) /* SQUARE_WAVEFORM */
1241 		{
1242 			AudioSource += (voice->vc_FilterPos-0x20)*(0xfc+0xfc+0x80*0x1f+0x80+0x280*3);
1243 		}
1244 
1245 		if ( voice->vc_Waveform < 3-1) /* TRIANGLE or SAWTOOTH */
1246 		{
1247 			// GetWLWaveformlor2
1248 			AudioSource += Offsets[voice->vc_WaveLength];
1249 		}
1250 
1251 		if ( voice->vc_Waveform == 4-1 ) /* WHITENOISE */
1252 		{
1253 			// AddRandomMoving
1254 			AudioSource += ( voice->vc_WNRandom & (2*0x280-1) ) & ~1;
1255 			// GoOnRandom
1256 			voice->vc_WNRandom += 2239384;
1257 			voice->vc_WNRandom  = ((((voice->vc_WNRandom >> 8) | (voice->vc_WNRandom << 24)) + 782323) ^ 75) - 6735;
1258 		}
1259 
1260 		voice->vc_AudioSource = AudioSource;
1261 	}
1262 
1263 	// Ring modulation period calculation
1264 	if ( voice->vc_RingAudioSource )
1265 	{
1266 		voice->vc_RingAudioPeriod = voice->vc_RingBasePeriod;
1267 
1268 		if ( !(voice->vc_RingFixedPeriod) )
1269 		{
1270 			if ( voice->vc_OverrideTranspose != 1000 )  // 1.5
1271 			{
1272 				voice->vc_RingAudioPeriod += voice->vc_OverrideTranspose + voice->vc_TrackPeriod - 1;
1273 			} else {
1274 				voice->vc_RingAudioPeriod += voice->vc_Transpose + voice->vc_TrackPeriod - 1;
1275 			}
1276 		}
1277 
1278 		if ( voice->vc_RingAudioPeriod > 5*12 )
1279 		{
1280 			voice->vc_RingAudioPeriod = 5*12;
1281 		}
1282 
1283 		if ( voice->vc_RingAudioPeriod < 0 )
1284 		{
1285 			voice->vc_RingAudioPeriod = 0;
1286 		}
1287 
1288 		voice->vc_RingAudioPeriod = period_tab[voice->vc_RingAudioPeriod];
1289 
1290 		if ( !(voice->vc_RingFixedPeriod) )
1291 		{
1292 			voice->vc_RingAudioPeriod += voice->vc_PeriodSlidePeriod;
1293 		}
1294 		voice->vc_RingAudioPeriod += voice->vc_PeriodPerfSlidePeriod + voice->vc_VibratoPeriod;
1295 
1296 		if ( voice->vc_RingAudioPeriod > 0x0d60 )
1297 		{
1298 			voice->vc_RingAudioPeriod = 0x0d60;
1299 		}
1300 
1301 		if ( voice->vc_RingAudioPeriod < 0x0071 )
1302 		{
1303 			voice->vc_RingAudioPeriod = 0x0071;
1304 		}
1305 	}
1306 
1307 	// Normal period calculation
1308 	voice->vc_AudioPeriod = voice->vc_InstrPeriod;
1309 
1310   	if ( !(voice->vc_FixedNote) )
release_partition(WindowAggState * winstate)1311 	{
1312 		if ( voice->vc_OverrideTranspose != 1000 ) // 1.5
1313 		{
1314 			voice->vc_AudioPeriod += voice->vc_OverrideTranspose + voice->vc_TrackPeriod - 1;
1315 		} else {
1316 			voice->vc_AudioPeriod += voice->vc_Transpose + voice->vc_TrackPeriod - 1;
1317 		}
1318 	}
1319 
1320 	if ( voice->vc_AudioPeriod > 5*12 )
1321 	{
1322 		voice->vc_AudioPeriod = 5*12;
1323 	}
1324 
1325 	if ( voice->vc_AudioPeriod < 0 )
1326 	{
1327 		voice->vc_AudioPeriod = 0;
1328 	}
1329 
1330 	voice->vc_AudioPeriod = period_tab[voice->vc_AudioPeriod];
1331 
1332 	if ( !(voice->vc_FixedNote) )
1333 	{
1334 		voice->vc_AudioPeriod += voice->vc_PeriodSlidePeriod;
1335 	}
1336 
1337 	voice->vc_AudioPeriod += voice->vc_PeriodPerfSlidePeriod + voice->vc_VibratoPeriod;
1338 
1339 	if ( voice->vc_AudioPeriod > 0x0d60 )
1340 	{
1341 		voice->vc_AudioPeriod = 0x0d60;
1342 	}
1343 
1344 	if ( voice->vc_AudioPeriod < 0x0071 )
1345 	{
1346 		voice->vc_AudioPeriod = 0x0071;
1347 	}
1348 
1349 	voice->vc_AudioVolume = (((((((voice->vc_ADSRVolume >> 8) * voice->vc_NoteMaxVolume) >> 6) * voice->vc_PerfSubVolume) >> 6) * voice->vc_TrackMasterVolume) >> 6);
1350 }
1351 
1352 static void hvl_set_audio ( struct hvl_voice *voice, double freqf )
1353 {
1354 	if ( voice->vc_TrackOn == 0 )
1355 	{
1356 		voice->vc_VoiceVolume = 0;
1357 		return;
1358 	}
1359 
1360 	voice->vc_VoiceVolume = voice->vc_AudioVolume;
row_is_in_frame(WindowAggState * winstate,int64 pos,TupleTableSlot * slot)1361 
1362 	if ( voice->vc_PlantPeriod )
1363 	{
1364 		double freq2;
1365 		uint32_t  delta;
1366 
1367 		voice->vc_PlantPeriod = 0;
1368 		voice->vc_VoicePeriod = voice->vc_AudioPeriod;
1369 
1370 		freq2 = Period2Freq( voice->vc_AudioPeriod );
1371 		delta = (uint32_t)(freq2 / freqf);
1372 
1373 		if ( delta > (0x280<<16) )
1374 		{
1375 			delta -= (0x280<<16);
1376 		}
1377 		if ( delta == 0 )
1378 		{
1379 			delta = 1;
1380 		}
1381 		voice->vc_Delta = delta;
1382 	}
1383 
1384 	if ( voice->vc_NewWaveform )
1385 	{
1386 		int8_t *src;
1387 
1388 		src = voice->vc_AudioSource;
1389 
1390 		if ( voice->vc_Waveform == 4-1 ) /* WHITENOISE */
1391 		{
1392 			memcpy ( &voice->vc_VoiceBuffer[0], src, 0x280 );
1393 		} else {
1394 			uint32_t i, WaveLoops;
1395 
1396 			WaveLoops = (1 << (5 - voice->vc_WaveLength)) * 5;
1397 
1398 			for ( i=0; i<WaveLoops; i++ )
1399 			{
1400 				memcpy( &voice->vc_VoiceBuffer[i*4*(1<<voice->vc_WaveLength)], src, 4*(1<<voice->vc_WaveLength) );
1401 			}
1402 		}
1403 
1404 		voice->vc_VoiceBuffer[0x280] = voice->vc_VoiceBuffer[0];
1405 		voice->vc_MixSource          = voice->vc_VoiceBuffer;
1406 	}
1407 
1408 	/* Ring Modulation */
1409 	if ( voice->vc_RingPlantPeriod )
1410 	{
1411 		double   freq2;
1412 		uint32_t delta;
1413 
1414 		voice->vc_RingPlantPeriod = 0;
1415 		freq2 = Period2Freq( voice->vc_RingAudioPeriod );
1416 		delta = (uint32_t)(freq2 / freqf);
1417 
1418 		if ( delta > (0x280<<16) )
1419 		{
1420 			delta -= (0x280<<16);
1421 		}
1422 		if ( delta == 0 )
1423 		{
1424 			delta = 1;
1425 		}
1426 		voice->vc_RingDelta = delta;
1427 	}
1428 
1429 	if ( voice->vc_RingNewWaveform )
1430 	{
1431 		int8_t  *src;
1432 		uint32_t i, WaveLoops;
1433 
1434 		src = voice->vc_RingAudioSource;
1435 
1436 		WaveLoops = (1 << (5 - voice->vc_WaveLength)) * 5;
1437 
1438 		for ( i=0; i<WaveLoops; i++ )
1439 		{
1440 			memcpy( &voice->vc_RingVoiceBuffer[i*4*(1<<voice->vc_WaveLength)], src, 4*(1<<voice->vc_WaveLength) );
1441 		}
1442 
1443 		voice->vc_RingVoiceBuffer[0x280] = voice->vc_RingVoiceBuffer[0];
1444 		voice->vc_RingMixSource          = voice->vc_RingVoiceBuffer;
1445 	}
1446 }
1447 
1448 static void hvl_play_irq ( struct hvl_tune *ht )
1449 {
1450 	uint32_t i;
1451 
1452 	if ( ht->ht_StepWaitFrames <= 0 )
1453 	{
1454 		if ( ht->ht_GetNewPosition )
1455 		{
1456 			int32_t nextpos = (ht->ht_PosNr+1==ht->ht_PositionNr)?0:(ht->ht_PosNr+1);
1457 
1458 			for ( i=0; i<ht->ht_Channels; i++ )
1459 			{
1460 				ht->ht_Voices[i].vc_Track         = ht->ht_Positions[ht->ht_PosNr].pos_Track[i];
update_frameheadpos(WindowAggState * winstate)1461 				ht->ht_Voices[i].vc_Transpose     = ht->ht_Positions[ht->ht_PosNr].pos_Transpose[i];
1462 				ht->ht_Voices[i].vc_NextTrack     = ht->ht_Positions[nextpos].pos_Track[i];
1463 				ht->ht_Voices[i].vc_NextTranspose = ht->ht_Positions[nextpos].pos_Transpose[i];
1464 			}
1465 			ht->ht_GetNewPosition = 0;
1466 		}
1467 
1468 		for ( i=0; i<ht->ht_Channels; i++ )
1469 		{
1470 			hvl_process_step ( ht, &ht->ht_Voices[i] );
1471 		}
1472 
1473 		ht->ht_StepWaitFrames = ht->ht_Tempo;
1474 	}
1475 
1476 	for ( i=0; i<ht->ht_Channels; i++ )
1477 	{
1478 		hvl_process_frame ( ht, &ht->ht_Voices[i] );
1479 	}
1480 
1481 	ht->ht_PlayingTime++;
1482 	if ( ht->ht_Tempo > 0 && --ht->ht_StepWaitFrames <= 0 )
1483 	{
1484 		if ( !ht->ht_PatternBreak )
1485 		{
1486 			ht->ht_NoteNr++;
1487 			if ( ht->ht_NoteNr >= ht->ht_TrackLength )
1488 			{
1489 				ht->ht_PosJump      = ht->ht_PosNr+1;
1490 				ht->ht_PosJumpNote  = 0;
1491 				ht->ht_PatternBreak = 1;
1492 			}
1493 		}
1494 
1495 		if ( ht->ht_PatternBreak )
1496 		{
1497 			ht->ht_PatternBreak = 0;
1498 			ht->ht_PosNr        = ht->ht_PosJump;
1499 			ht->ht_NoteNr       = ht->ht_PosJumpNote;
1500 			if ( ht->ht_PosNr == ht->ht_PositionNr )
1501 			{
1502 				ht->ht_SongEndReached = 1;
1503 				ht->ht_PosNr          = ht->ht_Restart;
1504 			}
1505 			ht->ht_PosJumpNote  = 0;
1506 			ht->ht_PosJump      = 0;
1507 
1508 			ht->ht_GetNewPosition = 1;
1509 		}
1510 	}
1511 
1512 	for ( i=0; i<ht->ht_Channels; i++ )
1513 	{
1514 		hvl_set_audio ( &ht->ht_Voices[i], ht->ht_Frequency );
1515 	}
1516 }
1517 
1518 static void
1519 hvl_mixchunk (struct hvl_tune *ht, int16_t *buf, size_t samples)
1520 {
1521 	int8_t   *src[MAX_CHANNELS];
1522 	int8_t   *rsrc[MAX_CHANNELS];
1523 	uint32_t  delta[MAX_CHANNELS];
1524 	uint32_t  rdelta[MAX_CHANNELS];
1525 	int32_t   vol[MAX_CHANNELS];
1526 	uint32_t  pos[MAX_CHANNELS];
1527 	uint32_t  rpos[MAX_CHANNELS];
1528 	uint32_t  cnt;
1529 	int32_t   panl[MAX_CHANNELS];
1530 	int32_t   panr[MAX_CHANNELS];
1531 //	uint32_t  vu[MAX_CHANNELS];
1532 	int32_t   j;
1533 	uint32_t  i, chans, loops;
1534 
1535 	chans = ht->ht_Channels;
1536 	for ( i=0; i<chans; i++ )
1537 	{
1538 		delta[i] = ht->ht_Voices[i].vc_Delta;
1539 		vol[i]   = ht->ht_Voices[i].vc_VoiceVolume;
1540 		pos[i]   = ht->ht_Voices[i].vc_SamplePos;
1541 		src[i]   = ht->ht_Voices[i].vc_MixSource;
1542 		panl[i]  = ht->ht_Voices[i].vc_PanMultLeft;
1543 		panr[i]  = ht->ht_Voices[i].vc_PanMultRight;
1544 
1545 	/* Ring Modulation */
1546 		rdelta[i]= ht->ht_Voices[i].vc_RingDelta;
1547 		rpos[i]  = ht->ht_Voices[i].vc_RingSamplePos;
1548 		rsrc[i]  = ht->ht_Voices[i].vc_RingMixSource;
1549 
1550 //		vu[i] = 0;
1551 	}
1552 
1553 	do
1554 	{
1555 		loops = samples;
1556 		for ( i=0; i<chans; i++ )
1557 		{
1558 			if ( pos[i] >= (0x280 << 16))
1559 			{
1560 				pos[i] -= 0x280<<16;
1561 			}
1562 			cnt = ((0x280<<16) - pos[i] - 1) / delta[i] + 1;
1563 			if ( cnt < loops )
1564 			{
1565 				loops = cnt;
1566 			}
1567 
1568 			if ( rsrc[i] )
1569 			{
1570 				if ( rpos[i] >= (0x280<<16))
1571 				{
1572 					rpos[i] -= 0x280<<16;
1573 				}
1574 				cnt = ((0x280<<16) - rpos[i] - 1) / rdelta[i] + 1;
1575 				if ( cnt < loops )
1576 				{
1577 					loops = cnt;
1578 				}
1579 			}
1580 		}
1581 
1582 		samples -= loops;
1583 
1584 		// Inner loop
1585 		do
1586 		{
1587 			for ( i=0; i<chans; i++ )
1588 			{
1589 				if ( rsrc[i] )
1590 				{
1591 					/* Ring Modulation */
1592 					j = ((src[i][pos[i]>>16]*rsrc[i][rpos[i]>>16])>>7)*vol[i];
1593 					rpos[i] += rdelta[i];
1594 				} else {
1595 					j = src[i][pos[i]>>16]*vol[i];
1596 				}
1597 				/*
1598 				if ( abs( j ) > vu[i] )
1599 				{
1600 					vu[i] = abs( j );
1601 				}
1602 				*/
1603 
1604 				*(buf++) = (j * panl[i]) >> 7;
1605 				*(buf++) = (j * panr[i]) >> 7;
1606 				pos[i] += delta[i];
1607 			}
1608 #if 1
1609 			/* clear non-used channels, just to be nice to the caller */
1610 			for ( ; i < MAX_CHANNELS; i++)
1611 			{
1612 				*(buf++) = 0;
1613 				*(buf++) = 0;
1614 			}
1615 #else
1616 /* Possible micro-optimalization */
1617 			buf += 2 * (MAX_CHANNELS - chans);
1618 #endif
1619 
1620 			loops--;
1621 		} while ( loops > 0 );
1622 	} while ( samples > 0 );
1623 
1624 	for ( i=0; i<chans; i++ )
1625 	{
1626 		ht->ht_Voices[i].vc_SamplePos = pos[i];
1627 		ht->ht_Voices[i].vc_RingSamplePos = rpos[i];
1628 //		ht->ht_Voices[i].vc_VUMeter = vu[i];
1629 	}
1630 }
1631 
1632 void __attribute__ ((visibility ("internal"))) hvl_DecodeFrame (struct hvl_tune *ht, int16_t *buf, size_t buflen)
1633 {
1634 	uint32_t pos = 0;
1635 	uint32_t newpos;
1636 	int i;
1637 
1638 	for(i=1; pos < buflen; i++)
1639 	{
1640 		hvl_play_irq ( ht );
1641 
1642 		newpos = buflen * i / ht->ht_SpeedMultiplier;
1643 
1644 		if (newpos == pos)
1645 		{
1646 			continue;
1647 		}
1648 		hvl_mixchunk (ht, buf, newpos - pos);
1649 		buf += (newpos - pos) * 2 * MAX_CHANNELS; // stereo
1650 		pos = newpos;
1651 	}
1652 }
1653 
1654 #if 0
1655 int32_t __attribute__ ((visibility ("internal"))) hvl_mix_findloudest ( struct hvl_tune *ht, uint32_ samples )
1656 {
1657 	int8_t   *src[MAX_CHANNELS];
1658 	int8_t   *rsrc[MAX_CHANNELS];
1659 	uint32_t  delta[MAX_CHANNELS];
1660 	uint32_t  rdelta[MAX_CHANNELS];
1661 	int32_t   vol[MAX_CHANNELS];
1662 	uint32_t  pos[MAX_CHANNELS];
1663 	uint32_t  rpos[MAX_CHANNELS];
1664 	uint32_t  cnt;
1665 	int32_t   panl[MAX_CHANNELS];
1666 	int32_t   panr[MAX_CHANNELS];
1667 	int32_t   a=0, b=0, j;
1668 	uint32_t  loud;
1669 	uint32_t  i, chans, loops;
1670 
1671 	loud = 0;
1672 
1673 	chans = ht->ht_Channels;
1674 	for ( i=0; i<chans; i++ )
1675 	{
1676 		delta[i] = ht->ht_Voices[i].vc_Delta;
1677 		vol[i]   = ht->ht_Voices[i].vc_VoiceVolume;
1678 		pos[i]   = ht->ht_Voices[i].vc_SamplePos;
1679 		src[i]   = ht->ht_Voices[i].vc_MixSource;
1680 		panl[i]  = ht->ht_Voices[i].vc_PanMultLeft;
1681 		panr[i]  = ht->ht_Voices[i].vc_PanMultRight;
1682 		/* Ring Modulation */
1683 		rdelta[i]= ht->ht_Voices[i].vc_RingDelta;
1684 		rpos[i]  = ht->ht_Voices[i].vc_RingSamplePos;
1685 		rsrc[i]  = ht->ht_Voices[i].vc_RingMixSource;
1686 	}
1687 
1688 	do
1689 	{
1690 		loops = samples;
1691 		for ( i=0; i<chans; i++ )
1692 		{
1693 			if ( pos[i] >= (0x280 << 16))
1694 			{
1695 				pos[i] -= 0x280<<16;
1696 			}
1697 			cnt = ((0x280<<16) - pos[i] - 1) / delta[i] + 1;
1698 			if ( cnt < loops )
1699 			{
1700 				loops = cnt;
1701 			}
1702 
1703 			if ( rsrc[i] )
1704 			{
1705 				if ( rpos[i] >= (0x280<<16))
1706 				{
1707 					rpos[i] -= 0x280<<16;
1708 				}
1709 				cnt = ((0x280<<16) - rpos[i] - 1) / rdelta[i] + 1;
1710 				if ( cnt < loops )
update_frametailpos(WindowAggState * winstate)1711 				{
1712 					loops = cnt;
1713 				}
1714 			}
1715 		}
1716 
1717 		samples -= loops;
1718 
1719 		// Inner loop
1720 		do
1721 		{
1722 			a=0;
1723 			b=0;
1724 			for ( i=0; i<chans; i++ )
1725 			{
1726 				if ( rsrc[i] )
1727 				{
1728 					/* Ring Modulation */
1729 					j = ((src[i][pos[i]>>16]*rsrc[i][rpos[i]>>16])>>7)*vol[i];
1730           				rpos[i] += rdelta[i];
1731 				} else {
1732 					j = src[i][pos[i]>>16]*vol[i];
1733 				}
1734 				a += (j * panl[i]) >> 7;
1735 				b += (j * panr[i]) >> 7;
1736 				pos[i] += delta[i];
1737 			}
1738 
1739 //			a = (a*ht->ht_mixgain)>>8;
1740 //			b = (b*ht->ht_mixgain)>>8;
1741 			a = abs ( a );
1742 			b = abs ( b );
1743 
1744 			if ( a > loud )
1745 			{
1746 				loud = a;
1747 			}
1748 			if ( b > loud )
1749 			{
1750 				loud = b;
1751 			}
1752 
1753 			loops--;
1754 		} while ( loops > 0 );
1755 	} while ( samples > 0 );
1756 
1757 	for ( i=0; i<chans; i++ )
1758 	{
1759 		ht->ht_Voices[i].vc_SamplePos = pos[i];
1760 		ht->ht_Voices[i].vc_RingSamplePos = rpos[i];
1761 	}
1762 
1763 	return loud;
1764 }
1765 
1766 int32_t __attribute__ ((visibility ("internal"))) hvl_FindLoudest ( struct hvl_tune *ht, int32_t maxframes, BOOL usesongend )
1767 {
1768 	uint32_t rsamp, rloop;
1769 	uint32_t samples, loops, loud, n;
1770 	int32_t frm;
1771 
1772 	rsamp = ht->ht_Frequency/50/ht->ht_SpeedMultiplier;
1773 	rloop = ht->ht_SpeedMultiplier;
1774 
1775 	loud = 0;
1776 
1777 	ht->ht_SongEndReached = 0;
1778 
1779 	frm = 0;
1780 	while ( frm < maxframes )
1781 	{
1782 		if ( ( usesongend ) && ( ht->ht_SongEndReached ) )
1783 		{
1784 			break;
1785 		}
1786 
1787 		samples = rsamp;
1788 		loops   = rloop;
1789 
1790 		do
1791 		{
1792 			hvl_play_irq ( ht );
1793 			n = hvl_mix_findloudest ( ht, samples );
1794 			if ( n > loud )
1795 			{
1796 				loud = n;
1797 			}
1798 			loops--;
1799 		} while ( loops );
1800 
1801 		frm++;
1802 	}
1803 
1804 	return loud;
1805 }
1806 #endif
1807