pimp_render.cpp 16.6 KB
Newer Older
1
2
#include <stdio.h>

Erik Faye-Lund's avatar
Erik Faye-Lund committed
3
#include "../include/pimpmobile.h"
4
#include "pimp_internal.h"
5
#include "pimp_render.h"
6
#include "pimp_debug.h"
Erik Faye-Lund's avatar
Erik Faye-Lund committed
7
#include "pimp_mixer.h"
Erik Faye-Lund's avatar
Erik Faye-Lund committed
8
#include "pimp_math.h"
9

10
// #define PRINT_PATTERNS
11

Erik Faye-Lund's avatar
Erik Faye-Lund committed
12
/* need to move these to a separate channel state header (?) */
13
STATIC void porta_up(pimp_channel_state *chan, s32 period_low_clamp)
14
{
15
16
	ASSERT(chan != 0);

17
18
	chan->final_period -= chan->porta_speed;
	if (chan->final_period < period_low_clamp) chan->final_period = period_low_clamp;
19
20
}

21
STATIC void porta_down(pimp_channel_state *chan, s32 period_high_clamp)
22
{
23
24
	ASSERT(chan != 0);

25
26
	chan->final_period += chan->porta_speed;
	if (chan->final_period > period_high_clamp) chan->final_period = period_high_clamp;
27
28
}

29
STATIC void porta_note(pimp_channel_state *chan)
30
{
31
32
	ASSERT(chan != 0);

33
	if (chan->final_period > chan->porta_target)
34
	{
35
36
		chan->final_period -= chan->porta_speed;
		if (chan->final_period < chan->porta_target) chan->final_period = chan->porta_target;
37
	}
38
	else if (chan->final_period < chan->porta_target)
39
	{
40
41
		chan->final_period += chan->porta_speed;
		if (chan->final_period > chan->porta_target) chan->final_period = chan->porta_target;
42
43
44
	}
}

Erik Faye-Lund's avatar
Erik Faye-Lund committed
45
46
STATIC int __pimp_channel_get_volume(pimp_channel_state *chan)
{
47
48
	ASSERT(chan != 0);
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
49
50
51
52
	int volume = chan->volume;
	
	if (chan->vol_env.env != 0)
	{
53
		/* envelope */
Erik Faye-Lund's avatar
Erik Faye-Lund committed
54
		volume = (volume * __pimp_envelope_sample(&chan->vol_env)) >> 8;
55
		__pimp_envelope_advance_tick(&chan->vol_env, chan->sustain);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
56
		
57
		/* fadeout  */
Erik Faye-Lund's avatar
Erik Faye-Lund committed
58
59
60
61
62
63
64
		volume = (volume * chan->fadeout) >> 16;
		chan->fadeout -= chan->instrument->volume_fadeout;
		if (chan->fadeout <= 0)
		{
			// TODO: kill sample
			chan->fadeout = 0;
		}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
65
	}
66
67
68
69
70
	else
	{
		if (!chan->sustain) volume = 0;
	}
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
71
72
73
	return volume;
}

74
STATIC void __pimp_mod_context_update_row(pimp_mod_context *ctx)
75
{
76
	ASSERT(ctx != 0);
77
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
78
79
80
	ctx->report_row   = ctx->curr_row;
	ctx->report_order = ctx->curr_order;
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
81
	for (u32 c = 0; c < ctx->mod->channel_count; ++c)
82
	{
83
		pimp_channel_state *chan = &ctx->channels[c];
Erik Faye-Lund's avatar
Erik Faye-Lund committed
84
		volatile pimp_mixer_channel_state &mc   = ctx->mixer->channels[c];
85
		
86
		const pimp_pattern_entry *note = &get_pattern_data(ctx->curr_pattern)[ctx->curr_row * ctx->mod->channel_count + c];
87
		
Erik Faye-Lund's avatar
Erik Faye-Lund committed
88
#ifdef PRINT_PATTERNS
89
		print_pattern_entry(*note);
90
#endif
91
		
92
93
94
		chan->effect           = note->effect_byte;
		chan->effect_param     = note->effect_parameter;
		chan->volume_command   = note->volume_command;
95
		
96
97
98
		bool period_dirty = false;
		bool volume_dirty = false;
		
99
		if (note->note == KEY_OFF)
100
		{
101
102
			chan->sustain = false;
			volume_dirty  = true; // we need to update volume if note off killed note
103
		}
104
		else
105
		{
106
			if (note->instrument > 0)
107
			{
108
109
110
111
112
113
				chan->instrument = __pimp_module_get_instrument(ctx->mod, note->instrument - 1);
				chan->sample  = get_sample(chan->instrument, chan->instrument->sample_map[note->note]);
				
				chan->vol_env.env = get_vol_env(chan->instrument);
				__pimp_envelope_reset(&chan->vol_env);
				chan->sustain = true;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
114
				chan->fadeout = 1 << 16;
115
116
117
				
				chan->volume = chan->sample->volume;
				volume_dirty = true;
118
			}
119
			
120
			if (note->note > 0)
121
			{
122
123
124
125
126
127
				if (
					chan->instrument != 0 &&
					chan->effect != EFF_PORTA_NOTE &&
					chan->effect != EFF_PORTA_NOTE_VOLUME_SLIDE &&
					!(chan->effect == EFF_MULTI_FX && chan->effect_param ==  EFF_NOTE_DELAY)
					)
128
				{
129
					if (chan->instrument->sample_count == 0)
130
					{
131
132
133
134
135
136
						/* TODO: this should be handeled in the converter, and as an assert. */
						
						// stupid musician, tried to play an empty instrument...
						mc.sample_data = NULL;
						mc.sample_cursor = 0;
						mc.sample_cursor_delta = 0;
137
138
139
					}
					else
					{
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
						chan->sample = get_sample(chan->instrument, chan->instrument->sample_map[note->note]);
						mc.sample_cursor = 0;
						mc.sample_data = ctx->sample_bank + chan->sample->data_ptr;
						mc.sample_length = chan->sample->length;
						mc.loop_type = (pimp_mixer_loop_type)chan->sample->loop_type;
						mc.loop_start = chan->sample->loop_start;
						mc.loop_end = chan->sample->loop_start + chan->sample->loop_length;
						
						if (ctx->mod->flags & FLAG_LINEAR_PERIODS)
						{
							chan->period = __pimp_get_linear_period(((s32)note->note) + chan->sample->rel_note, chan->sample->fine_tune);
						}
						else
						{
							chan->period = __pimp_get_amiga_period(((s32)note->note) + chan->sample->rel_note, chan->sample->fine_tune);
						}
						
						chan->final_period = chan->period;
						period_dirty = true;
159
					}
160
161
162
163
164
				}
				
				if (chan->effect == EFF_SAMPLE_OFFSET)
				{
					mc.sample_cursor = (chan->effect_param * 256) << 12;
165
					
166
167
168
169
170
					if (mc.sample_cursor > (mc.sample_length << 12))
					{
						if (ctx->mod->flags & FLAG_SAMPLE_OFFSET_CLAMP) mc.sample_cursor = mc.sample_length << 12;
						else mc.sample_data = NULL; // kill sample
					}
171
				}
172

173
			}
174
175
		}
		
Erik Faye-Lund's avatar
Erik Faye-Lund committed
176
177
		if (note->instrument > 0)
		{
178
			chan->volume = chan->sample->volume;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
179
180
			volume_dirty = true;
		}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
181

182
		switch (note->volume_command >> 4)
183
		{
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
  0       Do nothing
$10-$50   Set volume Value-$10
  :          :        :
  :          :        :
$60-$6f   Volume slide down
$70-$7f   Volume slide up
$80-$8f   Fine volume slide down
$90-$9f   Fine volume slide up
$a0-$af   Set vibrato speed
$b0-$bf   Vibrato
$c0-$cf   Set panning
$d0-$df   Panning slide left
$e0-$ef   Panning slide right
$f0-$ff   Tone porta
*/
Erik Faye-Lund's avatar
Erik Faye-Lund committed
200
201
			case 0x0:
			break;
202
203
204
205
206
207
208
209
			case 0x1:
			case 0x2:
			case 0x3:
			case 0x4:
			case 0x5:
				if (note->volume_command > 0x50)
				{
					/* something else */
210
					DEBUG_PRINT(("unsupported volume-command %02X\n", note->volume_command));
211
212
213
				}
				else
				{
214
					chan->volume = note->volume_command - 0x10;
215
//					DEBUG_PRINT(("setting volume to: %02X\n", chan->volume));
216
217
218
					volume_dirty = true;
				}
			break;
219
			case 0x6: break;
220
221
222
223
224
225
226
227
228
229
230
231
232
233
			case 0x7: break;
			
			case 0x8:
				chan->volume -= chan->volume_command & 0xF;
				if (chan->volume < 0) chan->volume = 0;
				volume_dirty = true;
			break;
			
			case 0x9:
				chan->volume += chan->volume_command & 0xF;
				if (chan->volume > 64) chan->volume = 64;
				volume_dirty = true;
			break;
			
234
235
			
			default:
236
				DEBUG_PRINT(("unsupported volume-command %02X\n", note->volume_command));
237
		}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
238
		
239
		switch (chan->effect)
240
		{
241
242
243
			case EFF_NONE: break;
			
			case EFF_PORTA_UP:
244
				if (chan->effect_param != 0) chan->porta_speed = chan->effect_param * 4;
245
246
247
			break;
			
			case EFF_PORTA_DOWN:
248
				if (chan->effect_param != 0) chan->porta_speed = chan->effect_param * 4;
249
250
251
252
253
			break;
			
			case EFF_PORTA_NOTE:
				if (note->note > 0)
				{
254
					// no fine tune or relative note here, boooy
255
256
					if (ctx->mod->flags & FLAG_LINEAR_PERIODS) chan->porta_target = __pimp_get_linear_period(note->note + chan->sample->rel_note, 0);
					else chan->porta_target = __pimp_get_amiga_period(note->note, 0);
257
258
					
					/* clamp porta-target period (should not be done for S3M) */
259
260
					if (chan->porta_target > ctx->mod->period_high_clamp) chan->porta_target = ctx->mod->period_high_clamp;
					if (chan->porta_target < ctx->mod->period_low_clamp)  chan->porta_target = ctx->mod->period_low_clamp;
261
				}
262
				if (chan->effect_param != 0) chan->porta_speed = chan->effect_param * 4;
263
			break;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
264
/*
265
266
267
268
269
270
271
			case EFF_VIBRATO: break; */
			
			case EFF_PORTA_NOTE_VOLUME_SLIDE:
				/* TODO: move to a separate function ? */
				if (note->note > 0)
				{
					// no fine tune or relative note here, boooy
272
273
					if (ctx->mod->flags & FLAG_LINEAR_PERIODS) chan->porta_target = __pimp_get_linear_period(note->note + chan->sample->rel_note, 0);
					else chan->porta_target = __pimp_get_amiga_period(note->note, 0);
274
275
					
					/* clamp porta-target period (should not be done for S3M) */
276
277
					if (chan->porta_target > ctx->mod->period_high_clamp) chan->porta_target = ctx->mod->period_high_clamp;
					if (chan->porta_target < ctx->mod->period_low_clamp)  chan->porta_target = ctx->mod->period_low_clamp;
278
279
				}
				
280
				if (chan->effect_param & 0xF0)
281
				{
282
					chan->volume_slide_speed = chan->effect_param >> 4;
283
				}
284
				else if (chan->effect_param & 0x0F)
285
				{
286
					chan->volume_slide_speed = -(chan->effect_param & 0xF);
287
288
289
				}
			break;
/*
Erik Faye-Lund's avatar
Erik Faye-Lund committed
290
291
292
293
			case EFF_VIBRATO_VOLUME_SLIDE: break;
			case EFF_TREMOLO: break;
			case EFF_SET_PAN: break;
*/
294
			case EFF_SAMPLE_OFFSET: break;
295
			
296
			case EFF_VOLUME_SLIDE:
297
				if (chan->effect_param & 0xF0)
298
				{
299
					chan->volume_slide_speed = chan->effect_param >> 4;
300
				}
301
				else if (chan->effect_param & 0x0F)
302
				{
303
					chan->volume_slide_speed = -(chan->effect_param & 0xF);
304
305
				}
			break;
306
			
Erik Faye-Lund's avatar
Erik Faye-Lund committed
307
308
309
/*			case EFF_JUMP_ORDER: break; */

			case EFF_SET_VOLUME:
310
311
				chan->volume = chan->effect_param;
				if (chan->volume > 64) chan->volume = 64;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
312
313
314
315
				volume_dirty = true;
			break;

			case EFF_BREAK_ROW:
Erik Faye-Lund's avatar
Erik Faye-Lund committed
316
317
318
319
320
				__pimp_mod_context_set_pos(
					ctx,
					(chan->effect_param >> 4) * 10 + (chan->effect_param & 0xF) - 1, // row
					ctx->curr_order + 1 // order
				);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
321
322
			break;
			
323
			case EFF_MULTI_FX:
324
				switch (chan->effect_param >> 4)
325
				{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
326
					case EFF_AMIGA_FILTER: break;
327
328

					case EFF_FINE_PORTA_UP:
Erik Faye-Lund's avatar
Erik Faye-Lund committed
329
						porta_up(chan, ctx->mod->period_low_clamp);
330
331
332
333
						period_dirty = true;
					break;
					
					case EFF_FINE_PORTA_DOWN:
Erik Faye-Lund's avatar
Erik Faye-Lund committed
334
						porta_down(chan, ctx->mod->period_high_clamp);
335
336
						period_dirty = true;
					break;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
337
					
338
					case EFF_RETRIG_NOTE:
339
						if ((note->effect_parameter & 0xF) != 0) chan->note_retrig = note->effect_parameter & 0xF;
340
341
					break;
					
342
					case EFF_FINE_VOLUME_SLIDE_UP:
343
344
						chan->volume += chan->effect_param & 0xF;
						if (chan->volume > 64) chan->volume = 64;
345
						volume_dirty = true;
346
					break;
347
348
					
					case EFF_FINE_VOLUME_SLIDE_DOWN:
349
350
						chan->volume -= chan->effect_param & 0xF;
						if (chan->volume < 0) chan->volume = 0;
351
						volume_dirty = true;
352
					break;
353
					
354
					case EFF_NOTE_DELAY:
355
356
						chan->note_delay = chan->effect_param & 0xF;
						chan->note = note->note;
357
					break;
358
359
					
					default:
360
						DEBUG_PRINT(("unsupported effect E%X\n", chan->effect_param >> 4));
361
362
				}
			break;
363
			
364
			case EFF_TEMPO:
365
366
				if (note->effect_parameter < 0x20) ctx->curr_tempo = chan->effect_param;
				else __pimp_mod_context_set_bpm(ctx, chan->effect_param);
367
368
			break;
			
Erik Faye-Lund's avatar
Erik Faye-Lund committed
369
370
371
372
373
374
375
/*
			case EFF_SET_GLOBAL_VOLUME: break;
			case EFF_GLOBAL_VOLUME_SLIDE: break;
			case EFF_KEY_OFF: break;
			case EFF_SET_ENVELOPE_POSITION: break;
			case EFF_PAN_SLIDE: break;
*/
376
			case EFF_MULTI_RETRIG:
377
				if ((note->effect_parameter & 0xF0) != 0) DEBUG_PRINT(("multi retrig x-parameter != 0 not supported\n"));
378
				if ((note->effect_parameter & 0xF) != 0) chan->note_retrig = note->effect_parameter & 0xF;
379
380
381
			break;
			
/*			case EFF_TREMOR: break; */
Erik Faye-Lund's avatar
Erik Faye-Lund committed
382
383
			
			case EFF_SYNC_CALLBACK:
384
				if (ctx->callback != NULL) ctx->callback(0, chan->effect_param);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
385
386
387
388
389
390
391
392
			break;
			
/*
			case EFF_ARPEGGIO: break;
			case EFF_SET_TEMPO: break;
			case EFF_SET_BPM: break;
*/
			
393
			default:
394
				DEBUG_PRINT(("unsupported effect %02X\n", chan->effect));
Erik Faye-Lund's avatar
Erik Faye-Lund committed
395
				ASSERT(0);
396
		}
397
398
399
		
		if (period_dirty)
		{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
400
			if (ctx->mod->flags & FLAG_LINEAR_PERIODS)
401
			{
402
				mc.sample_cursor_delta = __pimp_get_linear_delta(chan->final_period);
403
404
405
			}
			else
			{
406
				mc.sample_cursor_delta = __pimp_get_amiga_delta(chan->final_period);
407
408
409
			}
		}
		
410
		if (volume_dirty || chan->vol_env.env != 0)
411
		{
412
			mc.volume = (__pimp_channel_get_volume(chan) * ctx->global_volume) >> 8;
413
		}
414
	}
415
416

#ifdef PRINT_PATTERNS	
417
	iprintf("\n");
418
419
#endif

Erik Faye-Lund's avatar
Erik Faye-Lund committed
420
421
422
	ctx->curr_tick = 0;
	ctx->curr_row++;
	if (ctx->curr_row == ctx->curr_pattern->row_count)
423
	{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
424
425
426
		ctx->curr_row = 0;
		ctx->curr_order++;
		if (ctx->curr_order >= ctx->mod->order_count) ctx->curr_order = ctx->mod->order_repeat;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
427
		ctx->curr_pattern = __pimp_module_get_pattern(ctx->mod, __pimp_module_get_order(ctx->mod, ctx->curr_order));
428
	}
429
430
}

431
STATIC void __pimp_mod_context_update_tick(pimp_mod_context *ctx)
432
{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
433
	if (ctx->mod == NULL) return; // no module active (sound-effects can still be playing, though)
434

Erik Faye-Lund's avatar
Erik Faye-Lund committed
435
	if (ctx->curr_tick == ctx->curr_tempo)
436
	{
437
		__pimp_mod_context_update_row(ctx);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
438
		ctx->curr_tick++;
439
		return;
440
	}
441
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
442
	for (u32 c = 0; c < ctx->mod->channel_count; ++c)
443
	{
444
445
		pimp_channel_state *chan = &ctx->channels[c];
		pimp_mixer_channel_state &mc   = ctx->mixer->channels[c];
446
		
447
		bool period_dirty = false;
448
		bool volume_dirty = false;
449
		
450
		switch (chan->volume_command >> 4)
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
		{
/*
  0       Do nothing
$10-$50   Set volume Value-$10
  :          :        :
  :          :        :
$60-$6f   Volume slide down
$70-$7f   Volume slide up
$80-$8f   Fine volume slide down
$90-$9f   Fine volume slide up
$a0-$af   Set vibrato speed
$b0-$bf   Vibrato
$c0-$cf   Set panning
$d0-$df   Panning slide left
$e0-$ef   Panning slide right
$f0-$ff   Tone porta
*/
			case 0x0:
			case 0x1:
			case 0x2:
			case 0x3:
			case 0x4:
			case 0x5: break;
	
			case 0x6:
476
477
				chan->volume -= chan->volume_command & 0xF;
				if (chan->volume < 0) chan->volume = 0;
478
479
480
481
				volume_dirty = true;
			break;
			
			case 0x7:
482
483
				chan->volume += chan->volume_command & 0xF;
				if (chan->volume > 64) chan->volume = 64;
484
485
486
				volume_dirty = true;
			break;
			
487
488
489
			case 0x8: break;
			case 0x9: break;
			
490
			default:
491
				DEBUG_PRINT(("unsupported volume-command %02X\n", chan->volume_command));
492
		}
493
		
494
		switch (chan->effect)
495
496
497
498
		{
			case EFF_NONE: break;
			
			case EFF_PORTA_UP:
Erik Faye-Lund's avatar
Erik Faye-Lund committed
499
				porta_up(chan, ctx->mod->period_low_clamp);
500
501
502
503
				period_dirty = true;
			break;
			
			case EFF_PORTA_DOWN:
Erik Faye-Lund's avatar
Erik Faye-Lund committed
504
				porta_down(chan, ctx->mod->period_high_clamp);
505
506
507
508
				period_dirty = true;
			break;
			
			case EFF_PORTA_NOTE:
509
				porta_note(chan);
510
511
512
				period_dirty = true;
			break;
			
513
514
515
			case EFF_VIBRATO:
			break;
			
516
517
518
519
520
			case EFF_PORTA_NOTE_VOLUME_SLIDE:
				porta_note(chan);
				period_dirty = true;
				
				/* todo: move to a separate function */
521
522
523
				chan->volume += chan->volume_slide_speed;
				if (chan->volume > 64) chan->volume = 64;
				if (chan->volume < 0) chan->volume = 0;
524
525
526
				volume_dirty = true;
			break;
			
527
528
			case EFF_SAMPLE_OFFSET: break;
			
529
			case EFF_VOLUME_SLIDE:
530
531
532
				chan->volume += chan->volume_slide_speed;
				if (chan->volume > 64) chan->volume = 64;
				if (chan->volume < 0) chan->volume = 0;
533
				volume_dirty = true;
534
535
536
			break;
			
			case EFF_MULTI_FX:
537
				switch (chan->effect_param >> 4)
538
				{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
539
					case EFF_AMIGA_FILTER: break;
540
541
					
					case EFF_RETRIG_NOTE:
542
543
						chan->retrig_tick++;
						if (chan->retrig_tick == chan->note_retrig)
544
545
						{
							mc.sample_cursor = 0;
546
							chan->retrig_tick = 0;
547
548
549
						}
					break;

550
551
					case EFF_FINE_VOLUME_SLIDE_UP:
					case EFF_FINE_VOLUME_SLIDE_DOWN:
552
					break; /* fine volume slide is only done on tick0 */
553
					
554
555
					case EFF_NOTE_DELAY:
						// note on
556
						if (--chan->note_delay == 0)
557
558
						{
							// TODO: replace with a note_on-function
559
							if (chan->instrument != 0)
560
							{
561
								chan->sample = get_sample(chan->instrument, chan->instrument->sample_map[chan->note]);
562
								mc.sample_cursor = 0;
563
564
565
566
567
								mc.sample_data = ctx->sample_bank + chan->sample->data_ptr;
								mc.sample_length = chan->sample->length;
								mc.loop_type = (pimp_mixer_loop_type)chan->sample->loop_type;
								mc.loop_start = chan->sample->loop_start;
								mc.loop_end = chan->sample->loop_start + chan->sample->loop_length;
568
								
Erik Faye-Lund's avatar
Erik Faye-Lund committed
569
								if (ctx->mod->flags & FLAG_LINEAR_PERIODS)
570
								{
571
									chan->period = __pimp_get_linear_period(((s32)chan->note) + chan->sample->rel_note, chan->sample->fine_tune);
572
573
574
								}
								else
								{
575
									chan->period = __pimp_get_amiga_period(((s32)chan->note) + chan->sample->rel_note, chan->sample->fine_tune);
576
								}
577
								chan->final_period = chan->period;
578
579
580
581
								period_dirty = true;
							}
						}
					break;
582
583
584
				}
			break;
			
585
			case EFF_MULTI_RETRIG:
586
587
				chan->retrig_tick++;
				if (chan->retrig_tick == chan->note_retrig)
588
589
				{
					mc.sample_cursor = 0;
590
					chan->retrig_tick = 0;
591
592
593
				}
			break;
			
Erik Faye-Lund's avatar
Erik Faye-Lund committed
594
//				default: ASSERT(0);
595
596
		}
		
597
		// period to delta-conversion
598
599
		if (period_dirty)
		{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
600
			if (ctx->mod->flags & FLAG_LINEAR_PERIODS)
601
			{
602
				mc.sample_cursor_delta = __pimp_get_linear_delta(chan->final_period);
603
604
605
			}
			else
			{
606
				mc.sample_cursor_delta = __pimp_get_amiga_delta(chan->final_period);
607
			}
608
		}
609
		
610
//		if (c == 7) printf("%i\n", (volume_dirty) ? 1 : 0);
611
		if (volume_dirty || chan->vol_env.env != 0)
612
		{
613
			mc.volume = (__pimp_channel_get_volume(chan) * ctx->global_volume) >> 8;
614
		}
615
	}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
616
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
617
	ctx->curr_tick++;
618
619
}

Erik Faye-Lund's avatar
Erik Faye-Lund committed
620
621
622
623
624
625
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define MIN(x, y) ((x) > (y) ? (y) : (x))
#endif
626

Erik Faye-Lund's avatar
Erik Faye-Lund committed
627
void __pimp_render(pimp_mod_context *ctx, s8 *buf, u32 samples)
628
{
629
	static int remainder = 0;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
630
	while (true)
631
	{
632
		int samples_to_mix = MIN(remainder, samples);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
633
		if (samples_to_mix != 0) __pimp_mixer_mix(ctx->mixer, buf, samples_to_mix);
634
		
635
636
		buf       += samples_to_mix;
		samples   -= samples_to_mix;
637
638
		remainder -= samples_to_mix;
		
639
640
		if (samples == 0) break;
		
641
		__pimp_mod_context_update_tick(ctx);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
642
643
		
		// fixed point tick length
Erik Faye-Lund's avatar
Erik Faye-Lund committed
644
645
646
		ctx->curr_tick_len += ctx->tick_len;
		remainder           = ctx->curr_tick_len >> 8;
		ctx->curr_tick_len -= (ctx->curr_tick_len >> 8) << 8;
647
	}
648
}