added apex audio system
[gbajam21] / libs / aas / AAS_MOD.c
1 /* Copyright (c) 2003-2021 James Daniels */
2 /* Distributed under the MIT License */
3 /* license terms: see LICENSE file in root or http://opensource.org/licenses/MIT */
4
5 #include "AAS_Shared.h"
6
7 AAS_s16 AAS_mod_num AAS_IN_EWRAM = -1;
8 AAS_u8 AAS_mod_num_chans AAS_IN_EWRAM = 0;
9
10 static AAS_s16 AAS_mod_num_store AAS_IN_EWRAM = -2;
11 static AAS_u16 AAS_mod_song_pos AAS_IN_EWRAM;
12 static AAS_u16 AAS_mod_line_num AAS_IN_EWRAM;
13
14 struct AAS_MOD_Channel {
15         AAS_u32 *pattern;
16         const AAS_u8 *samp_start;
17         AAS_u16 effect;
18         AAS_u16 period;
19         AAS_u16 slide_target_period;
20         AAS_u8 samp_num;
21         AAS_u8 slide_rate;
22         AAS_u8 volume;
23         AAS_u8 vibrato_rate;
24         AAS_u8 vibrato_depth;
25         AAS_u8 vibrato_pos;
26         AAS_u8 tremolo_rate;
27         AAS_u8 tremolo_depth;
28         AAS_u8 tremolo_pos;
29         AAS_s8 trigger;
30         AAS_u8 arpeggio_pos;
31         AAS_u8 note;
32 };                              /* 28 bytes */
33
34 static struct AAS_MOD_Channel AAS_mod_chan[AAS_MAX_CHANNELS] AAS_IN_EWRAM;
35
36 static AAS_s32 AAS_mod_timer AAS_IN_EWRAM;
37 static AAS_u32 AAS_mod_tempo AAS_IN_EWRAM;
38 static AAS_u8 AAS_mod_bpm AAS_IN_EWRAM;
39 static AAS_u8 AAS_mod_speed AAS_IN_EWRAM;
40 static AAS_BOOL AAS_mod_looped AAS_IN_EWRAM = AAS_FALSE;
41 static AAS_s16 AAS_mod_overall_volume AAS_IN_EWRAM = 256;
42 static AAS_u8 AAS_mod_loop_start AAS_IN_EWRAM = 0;
43 static AAS_s8 AAS_mod_loop_counter AAS_IN_EWRAM = 0;
44 static AAS_BOOL AAS_mod_loop AAS_IN_EWRAM = AAS_TRUE;
45 static AAS_u8 AAS_mod_last_filter_value AAS_IN_EWRAM = 0;
46 static AAS_BOOL AAS_mod_active_effects AAS_IN_EWRAM = AAS_FALSE;
47 static AAS_s8 AAS_mod_next_song_pos AAS_IN_EWRAM = -1;
48
49 int AAS_MOD_GetNumChannels()
50 {
51         return AAS_mod_num_chans;
52 }
53
54 int AAS_MOD_GetLastFilterValue()
55 {
56         return AAS_mod_last_filter_value;
57 }
58
59 int AAS_MOD_QueueSongPos(int song_pos)
60 {
61         if(AAS_mod_num >= 0) {
62                 if((song_pos >= 0) && (song_pos < 128)) {
63                         if(AAS_Sequence[AAS_mod_num][song_pos][0] == -1) {
64                                 return AAS_ERROR_INVALID_SONG_POS;
65                         } else {
66                                 AAS_mod_next_song_pos = song_pos;
67
68                                 return AAS_OK;
69                         }
70                 } else {
71                         return AAS_ERROR_INVALID_SONG_POS;
72                 }
73         } else {
74                 return AAS_ERROR_NO_MOD_PLAYING;
75         }
76 }
77
78 int AAS_MOD_SetSongPos(int song_pos)
79 {
80         if(AAS_mod_num >= 0) {
81                 if((song_pos >= 0) && (song_pos < 128)) {
82                         if(AAS_Sequence[AAS_mod_num][song_pos][0] == -1) {
83                                 return AAS_ERROR_INVALID_SONG_POS;
84                         } else {
85                                 struct AAS_MOD_Channel *mod_chan = AAS_mod_chan;
86                                 int chan;
87
88                                 for(chan = 0; chan < AAS_mod_num_chans; ++chan) {
89                                         mod_chan->pattern =
90                                             (AAS_u32 *) (AAS_PatternData +
91                                                          (((int)
92                                                            AAS_Sequence[AAS_mod_num][song_pos]
93                                                            [chan]) << 8));
94                                         ++mod_chan;
95                                 }
96                                 AAS_mod_line_num = 0;
97                                 AAS_mod_song_pos = song_pos;
98
99                                 return AAS_OK;
100                         }
101                 } else {
102                         return AAS_ERROR_INVALID_SONG_POS;
103                 }
104         } else {
105                 return AAS_ERROR_NO_MOD_PLAYING;
106         }
107 }
108
109 int AAS_MOD_GetSongPos()
110 {
111         if(AAS_mod_num >= 0)
112                 return AAS_mod_song_pos;
113         else
114                 return AAS_ERROR_NO_MOD_PLAYING;
115 }
116
117 int AAS_MOD_GetLineNum()
118 {
119         if(AAS_mod_num >= 0)
120                 return AAS_mod_line_num;
121         else
122                 return AAS_ERROR_NO_MOD_PLAYING;
123 }
124
125 int AAS_MOD_GetVolume()
126 {
127         return AAS_mod_overall_volume;
128 }
129
130 int AAS_MOD_SetVolume(int vol)
131 {
132         if((vol >= 0) && (vol <= 256)) {
133                 int i;
134
135                 for(i = AAS_mod_num_chans - 1; i >= 0; --i)
136                         AAS_channels[AAS_chan_rearrange[i]].volume = (AAS_mod_chan[i].volume * vol) >> AAS_volscale;
137
138                 AAS_mod_overall_volume = vol;
139
140                 return AAS_OK;
141         } else {
142                 return AAS_ERROR_VOLUME_OUT_OF_RANGE;
143         }
144 }
145
146 void AAS_MOD_Pause()
147 {
148         int i;
149
150         AAS_mod_num_store = AAS_mod_num;
151         AAS_mod_num = -1;
152
153         for(i = 0; i < AAS_mod_num_chans; ++i) {
154                 AAS_channels[AAS_chan_rearrange[i]].active = AAS_FALSE;
155         }
156 }
157
158 void AAS_MOD_Resume()
159 {
160         if(AAS_mod_num_store != -2) {
161                 struct AAS_Channel *ch;
162                 int i;
163
164                 for(i = 0; i < AAS_mod_num_chans; ++i) {
165                         ch = &AAS_channels[AAS_chan_rearrange[i]];
166
167                         if(!ch->active) {
168                                 if(ch->loop_length) {
169                                         ch->active = AAS_TRUE;
170                                 } else {
171                                         if(ch->pos < ((ch->end - (ch->delta >> 6)) - 1)) {
172                                                 ch->active = AAS_TRUE;
173                                         }
174                                 }
175                         }
176                 }
177
178                 AAS_mod_num = AAS_mod_num_store;
179         }
180 }
181
182 void AAS_MOD_Stop()
183 {
184         int i;
185         struct AAS_Channel *ch;
186
187         AAS_mod_num_store = -2;
188         AAS_mod_num = -1;
189         AAS_mod_next_song_pos = -1;
190
191         for(i = 0; i < AAS_mod_num_chans; ++i) {
192                 ch = &AAS_channels[AAS_chan_rearrange[i]];
193                 ch->active = AAS_FALSE;
194                 ch->loop_length = 0;
195                 ch->pos = 0;
196                 ch->end = 0;
197                 ch->delta = 0;
198                 AAS_mod_chan[i].tremolo_pos = 0;
199                 AAS_mod_chan[i].vibrato_pos = 0;
200                 AAS_mod_chan[i].effect = 0;
201                 AAS_mod_chan[i].volume = 0;
202                 AAS_mod_chan[i].trigger = -1;
203                 AAS_mod_chan[i].note = 0;
204                 AAS_mod_chan[i].slide_target_period = 0;
205         }
206         AAS_mod_active_effects = AAS_FALSE;
207         AAS_mod_looped = AAS_FALSE;
208         AAS_mod_loop_counter = 0;
209         AAS_mod_loop_start = 0;
210         AAS_mod_last_filter_value = 0;
211         AAS_mod_num_chans = 0;
212 }
213
214 AAS_BOOL AAS_MOD_HasLooped()
215 {
216         return AAS_mod_looped;
217 }
218
219 AAS_BOOL AAS_MOD_IsPlaying()
220 {
221         return (AAS_mod_num >= 0);
222 }
223
224 int AAS_MOD_Play(int song_num)
225 {
226         AAS_MOD_Stop();
227
228         if(AAS_initialised) {
229                 if((song_num >= 0) && (song_num < AAS_DATA_NUM_MODS) && AAS_NumChans[song_num]) {
230                         int i;
231
232                         if(AAS_volscale == 9)
233                                 i = 16;
234                         else if(AAS_volscale == 8)
235                                 i = 8;
236                         else
237                                 i = 4;
238
239                         if(AAS_NumChans[song_num] > i) {
240                                 return AAS_ERROR_NOT_ENOUGH_CHANNELS;
241                         } else {
242                                 /*AAS_mod_num = 0; */
243                                 AAS_mod_loop = AAS_TRUE;
244                                 AAS_mod_num_store = -2;
245                                 AAS_mod_song_pos = 0;
246                                 AAS_mod_num_chans = AAS_NumChans[song_num];
247
248                                 for(i = 0; i < AAS_mod_num_chans; ++i)
249                                         AAS_mod_chan[i].pattern = (AAS_u32 *) (AAS_PatternData + (((int)AAS_Sequence[song_num][0][i]) << 8));
250
251                                 AAS_mod_line_num = 0;
252                                 AAS_mod_speed = 6;
253                                 AAS_mod_bpm = 125;
254                                 AAS_mod_tempo = AAS_DivTable[AAS_mod_speed] * AAS_mod_bpm;
255                                 AAS_mod_timer = 0x7d0000 - AAS_mod_tempo;
256                                 AAS_mod_num = song_num;
257                                 return AAS_OK;
258                         }
259                 } else {
260                         return AAS_ERROR_MOD_DOES_NOT_EXIST;
261                 }
262         } else {
263                 return AAS_ERROR_CALL_SET_CONFIG_FIRST;
264         }
265 }
266
267 int AAS_MOD_SetLoop(AAS_BOOL loop)
268 {
269         if(AAS_initialised) {
270                 if(AAS_mod_num >= 0) {
271                         AAS_mod_loop = loop;
272                         return AAS_OK;
273                 } else {
274                         return AAS_ERROR_NO_MOD_PLAYING;
275                 }
276         } else {
277                 return AAS_ERROR_CALL_SET_CONFIG_FIRST;
278         }
279 }
280
281 void AAS_MOD_Interrupt()
282 {
283         if(AAS_mod_num >= 0) {
284                 AAS_mod_timer += AAS_mod_tempo;
285
286                 if(AAS_mod_timer < 0x7d0000) {
287                         if(AAS_mod_active_effects) {
288                                 const AAS_u8 *chan_rearrange = AAS_chan_rearrange;
289                                 struct AAS_MOD_Channel *mod_chan = AAS_mod_chan;
290                                 int chan, num_chans;
291
292                                 num_chans = AAS_mod_num_chans;
293
294                                 for(chan = 0; chan < num_chans; ++chan) {
295                                         int effect;
296
297                                         effect = mod_chan->effect;
298
299                                         if(effect) {
300                                                 int val, tmp, output;
301                                                 struct AAS_Channel *out_chan;
302
303                                                 tmp = chan_rearrange[chan];
304                                                 out_chan = &AAS_channels[tmp];
305                                                 output = tmp >> 3;
306
307                                                 switch (effect >> 8) {
308                                                 case 0xe:       /* extended effects */
309                                                         switch (effect & 0xf0) {
310                                                         case 0xc0:      /* note cut */
311                                                                 val = effect & 0xf;
312                                                                 --val;
313                                                                 if(val <= 0) {
314                                                                         mod_chan->effect = 0;
315                                                                         out_chan->active = AAS_FALSE;
316
317                                                                         AAS_changed[output] = AAS_TRUE;
318                                                                 } else {
319                                                                         mod_chan->effect = (effect & 0xff0) + val;
320                                                                 }
321                                                                 break;
322
323                                                         case 0x90:      /* retrigger sample */
324                                                         case 0xd0:      /* delay sample */
325                                                                 if(mod_chan->trigger >= 0) {
326                                                                         --mod_chan->trigger;
327                                                                         if(mod_chan->trigger < 0) {
328                                                                                 const struct AAS_ModSample *samp = &AAS_ModSamples[AAS_mod_num][mod_chan->samp_num];
329                                                                                 int repeat = samp->repeat;
330                                                                                 int length = samp->length;
331                                                                                 const AAS_s8 *data = AAS_SampleData + samp->data;
332
333                                                                                 mod_chan->samp_start = data;
334                                                                                 out_chan->pos = data;
335                                                                                 out_chan-> pos_fraction = 0;
336                                                                                 if(repeat == 65535)
337                                                                                         out_chan->loop_length = 0;
338                                                                                 else
339                                                                                         out_chan->loop_length = ((AAS_u32) (length - repeat)) << 1;
340                                                                                 out_chan->end = data + (length << 1);
341                                                                                 out_chan->frequency = AAS_MOD_period_conv_table[mod_chan->period];
342                                                                                 out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
343                                                                                 out_chan->active = AAS_TRUE;
344
345                                                                                 AAS_changed[output] = AAS_TRUE;
346                                                                         }
347                                                                 }
348                                                                 break;
349
350                                                         default:
351                                                                 break;
352                                                         }
353                                                         break;
354
355                                                 case 0x6:       /* vibrato + volume slide */
356                                                         val = mod_chan->vibrato_pos;
357                                                         val += mod_chan->vibrato_rate;
358                                                         if(val >= 64)
359                                                                 val -= 64;
360                                                         mod_chan->vibrato_pos = val;
361                                                         tmp = mod_chan->period + (((AAS_sin[val] * mod_chan->vibrato_depth) + 32) >> 6);
362                                                         if(tmp < 113)
363                                                                 tmp = 113;
364                                                         if(tmp > 856)
365                                                                 tmp = 856;
366                                                         out_chan->frequency = AAS_MOD_period_conv_table[tmp];
367                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
368                                                         /* Intentionally no "break;" */
369
370                                                 case 0xa:       /* volume slide */
371                                                         val = effect & 0xf0;
372                                                         if(val)
373                                                                 val >>= 4;
374                                                         else
375                                                                 val = -(effect & 0xf);
376                                                         tmp = mod_chan->volume;
377                                                         tmp += val;
378                                                         if(tmp > 64)
379                                                                 tmp = 64;
380                                                         else if(tmp < 0)
381                                                                 tmp = 0;
382                                                         mod_chan->volume = tmp;
383                                                         out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
384
385                                                         AAS_changed[output] = AAS_TRUE;
386                                                         break;
387
388                                                 case 0x1:       /* slide up */
389                                                         val = effect & 0xff;
390                                                         tmp = mod_chan->period - val;
391                                                         if(tmp < 113)
392                                                                 tmp = 113;
393                                                         mod_chan->period = tmp;
394                                                         out_chan->frequency = AAS_MOD_period_conv_table[tmp];
395                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
396
397                                                         AAS_changed[output] = AAS_TRUE;
398                                                         break;
399
400                                                 case 0x2:       /* slide down */
401                                                         val = effect & 0xff;
402                                                         tmp = mod_chan->period + val;
403                                                         if(tmp > 856)
404                                                                 tmp = 856;
405                                                         mod_chan->period = tmp;
406                                                         out_chan->frequency = AAS_MOD_period_conv_table[tmp];
407                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
408
409                                                         AAS_changed[output] = AAS_TRUE;
410                                                         break;
411
412                                                 case 0x3:       /* tone portamento */
413                                                         val = mod_chan->period;
414                                                         tmp = mod_chan->slide_target_period;
415                                                         if(val < tmp) {
416                                                                 val += mod_chan->slide_rate;
417                                                                 if(val >= tmp) {
418                                                                         mod_chan->effect = 0;
419                                                                         val = tmp;
420                                                                 }
421                                                         } else if(val > tmp) {
422                                                                 val -= mod_chan->slide_rate;
423                                                                 if(val <= tmp) {
424                                                                         mod_chan->effect = 0;
425                                                                         val = tmp;
426                                                                 }
427                                                         } else if(val == tmp) {
428                                                                 mod_chan->effect = 0;
429                                                         }
430                                                         mod_chan->period = val;
431                                                         out_chan->frequency = AAS_MOD_period_conv_table[val];
432                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
433
434                                                         AAS_changed[output] = AAS_TRUE;
435                                                         break;
436
437                                                 case 0x5:       /* tone portamento + volume slide */
438                                                         val = mod_chan->period;
439                                                         tmp = mod_chan->slide_target_period;
440                                                         if(val < tmp) {
441                                                                 val += mod_chan->slide_rate;
442                                                                 if(val >= tmp)
443                                                                         val = tmp;
444                                                         } else if(val > tmp) {
445                                                                 val -= mod_chan->slide_rate;
446                                                                 if(val <= tmp)
447                                                                         val = tmp;
448                                                         }
449                                                         mod_chan->period = val;
450                                                         out_chan->frequency = AAS_MOD_period_conv_table[val];
451                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
452
453                                                         val = effect & 0xf0;
454                                                         if(val)
455                                                                 val >>= 4;
456                                                         else
457                                                                 val = -(effect & 0xf);
458                                                         tmp = mod_chan->volume;
459                                                         tmp += val;
460                                                         if(tmp > 64)
461                                                                 tmp = 64;
462                                                         else if(tmp < 0)
463                                                                 tmp = 0;
464                                                         mod_chan->volume = tmp;
465                                                         out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
466
467                                                         AAS_changed[output] = AAS_TRUE;
468                                                         break;
469
470                                                 case 0x4:       /* vibrato */
471                                                         val = mod_chan->vibrato_pos;
472                                                         val += mod_chan->vibrato_rate;
473                                                         if(val >= 64)
474                                                                 val -= 64;
475                                                         mod_chan->vibrato_pos = val;
476                                                         tmp = mod_chan->period + (((AAS_sin[val] * mod_chan->vibrato_depth) + 32) >> 6);
477                                                         if(tmp < 113)
478                                                                 tmp = 113;
479                                                         else if(tmp > 856)
480                                                                 tmp = 856;
481                                                         out_chan->frequency = AAS_MOD_period_conv_table[tmp];
482                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
483
484                                                         AAS_changed[output] = AAS_TRUE;
485                                                         break;
486
487                                                 case 0x7:       /* tremolo */
488                                                         val = mod_chan->tremolo_pos;
489                                                         val += mod_chan->tremolo_rate;
490                                                         if(val >= 64)
491                                                                 val -= 64;
492                                                         mod_chan->tremolo_pos = val;
493                                                         tmp = mod_chan->volume + (((AAS_sin[val] * mod_chan->tremolo_depth) + 32) >> 6);
494                                                         if(tmp < 0)
495                                                                 tmp = 0;
496                                                         else if(tmp > 64)
497                                                                 tmp = 64;
498                                                         out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
499
500                                                         AAS_changed[output] = AAS_TRUE;
501                                                         break;
502
503                                                 case 0x0:       /* possible arpeggio */
504                                                         tmp = effect & 0xff;
505                                                         if(tmp) /* definite arpeggio */
506                                                         {
507                                                                 ++mod_chan->arpeggio_pos;
508                                                                 val = mod_chan->note;
509                                                                 switch (mod_chan->arpeggio_pos) {
510                                                                 case 0:
511                                                                         break;
512
513                                                                 case 1:
514                                                                         val += tmp >> 4;
515                                                                         break;
516
517                                                                 case 2:
518                                                                         val += tmp & 0xf;
519                                                                         /* Intentionally no "break;" to allow AAS_mod_arpeggio_pos[chan] to be restarted */
520
521                                                                 default:
522                                                                         mod_chan->arpeggio_pos = 0;
523                                                                         break;
524                                                                 }
525
526                                                                 if(val) {
527                                                                         out_chan->frequency = AAS_MOD_period_conv_table[AAS_period_table[AAS_ModSamples[AAS_mod_num][mod_chan->samp_num].finetune][val - 1]];
528                                                                         out_chan->delta = AAS_Min(4095, ((out_chan-> frequency * AAS_mix_scale) + 32768) >> 16);
529
530                                                                         AAS_changed[output] = AAS_TRUE;
531                                                                 }
532                                                         }
533                                                         break;
534
535                                                 default:
536                                                         break;
537                                                 }
538                                         }
539
540                                         ++mod_chan;
541                                 }
542                         }
543                 } else {
544                         const AAS_u8 *chan_rearrange = AAS_chan_rearrange;
545                         struct AAS_MOD_Channel *mod_chan = AAS_mod_chan;
546                         int chan, num_chans;
547                         int samp_num, effect, period, speed, tmp;
548                         int jump_ahead = -1;
549                         int jump_song_pos = -1;
550                         AAS_BOOL active_effects = AAS_FALSE;
551                         const struct AAS_ModSample *mod_samp = AAS_ModSamples[AAS_mod_num];
552
553                         num_chans = AAS_mod_num_chans;
554
555                         AAS_mod_timer -= 0x7d0000;
556
557                         for(chan = 0; chan < num_chans; ++chan) {
558                                 int output;
559                                 struct AAS_Channel *out_chan;
560                                 AAS_u32 dat;
561
562                                 tmp = chan_rearrange[chan];
563                                 out_chan = &AAS_channels[tmp];
564                                 output = tmp >> 3;
565
566                                 /* Tidy up after arpeggio */
567                                 effect = mod_chan->effect;
568                                 if(effect) {
569                                         if(effect < 0x100) {
570                                                 tmp = mod_chan->note;
571                                                 if(tmp) {
572                                                         out_chan->frequency = AAS_MOD_period_conv_table[AAS_period_table[mod_samp[mod_chan->samp_num].finetune][tmp - 1]];
573                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
574
575                                                         AAS_changed[output] = AAS_TRUE;
576                                                 }
577                                         }
578                                 }
579
580                                 dat = *mod_chan->pattern++;
581                                 samp_num = (dat >> 24) - 1;
582                                 period = (dat >> 12) & 0xfff;
583                                 effect = dat & 0xfff;
584
585                                 if(samp_num >= 0) {
586                                         mod_chan->samp_num = samp_num;
587                                         mod_chan->volume = tmp = mod_samp[samp_num].volume;
588                                         out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
589
590                                         AAS_changed[output] = AAS_TRUE;
591                                 } else {
592                                         samp_num = mod_chan->samp_num;
593                                 }
594
595                                 if(period) {
596                                         if(samp_num >= 0) {
597                                                 const struct AAS_ModSample *samp = &mod_samp[samp_num];
598
599                                                 mod_chan->note = period;
600                                                 period = AAS_period_table[samp->finetune][period - 1];
601
602                                                 if((effect > 0xed0) && (effect < 0xee0))        /* delay sample */
603                                                 {
604                                                         mod_chan->period = period;
605                                                         mod_chan->trigger = (effect & 0xf) - 1;
606                                                 } else {
607                                                         tmp = effect >> 8;
608
609                                                         if((tmp != 0x3) && (tmp != 0x5)) {
610                                                                 int repeat = samp->repeat;
611                                                                 int length = samp->length;
612                                                                 const AAS_s8 *data = AAS_SampleData + samp->data;
613
614                                                                 mod_chan->samp_start = data;
615                                                                 out_chan->pos = data;
616                                                                 out_chan->pos_fraction = 0;
617                                                                 mod_chan->period = period;
618                                                                 if(repeat == 65535)
619                                                                         out_chan->loop_length = 0;
620                                                                 else
621                                                                         out_chan->loop_length = ((AAS_u32) (length - repeat)) << 1;
622                                                                 out_chan->end = data + (length << 1);
623                                                                 out_chan->frequency = AAS_MOD_period_conv_table[period];
624                                                                 out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
625                                                                 out_chan->active = AAS_TRUE;
626
627                                                                 AAS_changed[output] = AAS_TRUE;
628                                                         }
629                                                 }
630                                         }
631                                 }
632
633                                 if(effect) {
634                                         switch (effect >> 8) {
635                                         case 0xf:       /* set speed */
636                                                 speed = effect & 0xff;
637                                                 if(speed > 0) {
638                                                         if(speed > 31)
639                                                                 AAS_mod_bpm = speed;
640                                                         else
641                                                                 AAS_mod_speed = speed;
642
643                                                         /*AAS_mod_tempo = (((1<<15)*AAS_mod_bpm*24)/(3000*AAS_mod_speed))<<13;  // use LUT */
644
645                                                         /* approximately: */
646                                                         /*AAS_mod_tempo = AAS_DivTable[AAS_mod_speed]*AAS_mod_bpm*33; */
647                                                         AAS_mod_tempo = AAS_DivTable[AAS_mod_speed] * AAS_mod_bpm;
648                                                 }
649                                                 effect = 0;     /* No need to process this effect again */
650                                                 break;
651
652                                         case 0xe:       /* extended effects */
653                                                 switch (effect & 0xf0) {
654                                                 case 0x00:      /* set filter (used to send messages to code instead) */
655                                                         AAS_mod_last_filter_value = effect & 0xf;
656                                                         effect = 0;     /* No need to process this effect again */
657                                                         break;
658
659                                                 case 0x10:      /* fine slide up */
660                                                         tmp = mod_chan->period - (effect & 0xf);
661                                                         if(tmp < 113)
662                                                                 tmp = 113;
663                                                         mod_chan->period = tmp;
664                                                         out_chan->frequency = AAS_MOD_period_conv_table[tmp];
665                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
666                                                         effect = 0;     /* No need to process this effect again */
667
668                                                         AAS_changed[output] = AAS_TRUE;
669                                                         break;
670
671                                                 case 0x20:      /* fine slide down */
672                                                         tmp = mod_chan->period + (effect & 0xf);
673                                                         if(tmp > 856)
674                                                                 tmp = 856;
675                                                         mod_chan->period = tmp;
676                                                         out_chan->frequency = AAS_MOD_period_conv_table[tmp];
677                                                         out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
678                                                         effect = 0;     /* No need to process this effect again */
679
680                                                         AAS_changed[output] = AAS_TRUE;
681                                                         break;
682
683                                                 case 0x60:      /* set/jump to loop */
684                                                         tmp = effect & 0xf;
685                                                         if(tmp) {
686                                                                 if(AAS_mod_loop_counter)
687                                                                         --AAS_mod_loop_counter;
688                                                                 else
689                                                                         AAS_mod_loop_counter = tmp;
690
691                                                                 if(AAS_mod_loop_counter) {
692                                                                         int i;
693                                                                         struct AAS_MOD_Channel
694                                                                             *mod_chan2 = AAS_mod_chan;
695
696                                                                         for(i = 0; i < num_chans; ++i) {
697                                                                                 mod_chan2->pattern = (AAS_u32 *)(AAS_PatternData + (((int)AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][i]) << 8));
698                                                                                 mod_chan2-> pattern += AAS_mod_loop_start;
699                                                                                 ++mod_chan2;
700                                                                         }
701                                                                         AAS_mod_line_num = AAS_mod_loop_start;
702                                                                 }
703                                                         } else {
704                                                                 AAS_mod_loop_start = AAS_mod_line_num;
705                                                         }
706                                                         effect = 0;     /* No need to process this effect again */
707                                                         break;
708
709                                                 case 0x90:      /* retrigger sample */
710                                                         mod_chan->trigger = (effect & 0xf) - 1;
711                                                         break;
712
713                                                 case 0xa0:      /* fine volume slide up */
714                                                         tmp = mod_chan->volume;
715                                                         tmp += effect & 0xf;
716                                                         if(tmp > 64)
717                                                                 tmp = 64;
718                                                         mod_chan->volume = tmp;
719                                                         out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
720                                                         effect = 0;     /* No need to process this effect again */
721
722                                                         AAS_changed[output] = AAS_TRUE;
723                                                         break;
724
725                                                 case 0xb0:      /* fine volume slide down */
726                                                         tmp = mod_chan->volume;
727                                                         tmp -= effect & 0xf;
728                                                         if(tmp < 0)
729                                                                 tmp = 0;
730                                                         mod_chan->volume = tmp;
731                                                         out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
732                                                         effect = 0;     /* No need to process this effect again */
733
734                                                         AAS_changed[output] = AAS_TRUE;
735                                                         break;
736
737                                                 case 0xc0:      /* note cut */
738                                                         if((effect & 0xf) == 0) {
739                                                                 effect = 0;
740                                                                 out_chan->active = AAS_FALSE;
741                                                                 AAS_changed[output] = AAS_TRUE;
742                                                         }
743                                                         break;
744
745                                                 case 0xe0:      /* pattern delay */
746                                                         AAS_mod_timer -= (effect & 0xf) * 0x7d0000;
747                                                         effect = 0;     /* No need to process this effect again */
748                                                         break;
749
750                                                 default:
751                                                         break;
752                                                 }
753                                                 break;
754
755                                         case 0xd:       /* pattern break */
756                                                 /*jump_ahead = (((effect>>4)&0xf)*10)+(effect&0xf); */
757                                                 jump_ahead = effect & 0xff;
758                                                 effect = 0;     /* No need to process this effect again */
759                                                 break;
760
761                                         case 0xc:       /* set volume */
762                                                 mod_chan->volume = tmp = effect & 0xff;
763                                                 out_chan->volume = (tmp * AAS_mod_overall_volume) >> AAS_volscale;
764                                                 effect = 0;     /* No need to process this effect again */
765
766                                                 AAS_changed[output] = AAS_TRUE;
767                                                 break;
768
769                                         case 0xb:       /* position jump */
770                                                 jump_song_pos = effect & 0xff;
771                                                 effect = 0;     /* No need to process this effect again */
772                                                 break;
773
774                                         case 0x9:       /* set sample offset */
775                                                 tmp = effect & 0xff;
776                                                 if(tmp) {
777                                                         const AAS_s8 *new_pos = mod_chan->samp_start + (tmp << 8);
778
779                                                         if(new_pos >= out_chan->end) {
780                                                                 out_chan->active = AAS_FALSE;
781
782                                                                 AAS_changed[output] = AAS_TRUE;
783                                                         } else
784                                                                 out_chan->pos = new_pos;
785                                                 }
786                                                 effect = 0;     /* No need to process this effect again */
787                                                 break;
788
789                                         case 0x7:       /* tremolo */
790                                                 if(effect & 0xf0)
791                                                         mod_chan->tremolo_rate = (effect & 0xf0) >> 4;
792                                                 if(effect & 0xf)
793                                                         mod_chan->tremolo_depth = effect & 0xf;
794                                                 if(effect & 0xff)
795                                                         mod_chan->tremolo_pos = 0;
796                                                 break;
797
798                                         case 0x4:       /* vibrato */
799                                                 if(effect & 0xf0)
800                                                         mod_chan->vibrato_rate = (effect & 0xf0) >> 4;
801                                                 if(effect & 0xf)
802                                                         mod_chan->vibrato_depth = effect & 0xf;
803                                                 if(effect & 0xff)
804                                                         mod_chan->vibrato_pos = 0;
805                                                 break;
806
807                                         case 0x3:       /* tone portamento */
808                                                 tmp = effect & 0xff;
809                                                 if(tmp)
810                                                         mod_chan->slide_rate = tmp;
811
812                                                 if(period)
813                                                         mod_chan->slide_target_period = period;
814                                                 else if(mod_chan->slide_target_period == 0)
815                                                         effect = 0;
816                                                 break;
817
818                                         case 0x0:       /* possible arpeggio */
819                                                 tmp = effect & 0xff;
820                                                 if(tmp) /* definite arpeggio */
821                                                 {
822                                                         tmp = mod_chan->note;
823                                                         mod_chan->arpeggio_pos = 0;
824                                                         if(tmp) {
825                                                                 out_chan->frequency = AAS_MOD_period_conv_table[AAS_period_table[mod_samp[mod_chan->samp_num].finetune][tmp - 1]];
826                                                                 out_chan->delta = AAS_Min(4095, ((out_chan->frequency * AAS_mix_scale) + 32768) >> 16);
827
828                                                                 AAS_changed[output] = AAS_TRUE;
829                                                         }
830                                                 }
831                                                 break;
832
833                                         default:
834                                                 /*printf_special( "effect:%p period:%d samp:%d\n", effect, period, samp_num ); */
835                                                 break;
836                                         }
837                                 }
838
839                                 mod_chan->effect = effect;
840                                 if(effect)
841                                         active_effects = AAS_TRUE;
842                                 ++mod_chan;
843                         }
844
845                         AAS_mod_active_effects = active_effects;
846
847                         if(jump_ahead >= 0) {
848                                 AAS_mod_loop_start = 0;
849                                 ++AAS_mod_song_pos;
850                                 if(AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][0] == -1) {
851                                         AAS_mod_looped = AAS_TRUE;
852                                         AAS_mod_song_pos = 0;
853                                         mod_chan = AAS_mod_chan;
854                                         for(chan = num_chans; chan > 0; --chan) {
855                                                 mod_chan->slide_target_period = 0;
856                                                 ++mod_chan;
857                                         }
858                                 }
859
860                                 mod_chan = AAS_mod_chan;
861                                 for(chan = 0; chan < num_chans; ++chan) {
862                                         mod_chan->pattern = (AAS_u32 *) (AAS_PatternData + (((int)AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][chan]) << 8));
863                                         mod_chan->pattern += jump_ahead;
864                                         ++mod_chan;
865                                 }
866                                 AAS_mod_line_num = jump_ahead;
867                         } else if(jump_song_pos >= 0) {
868                                 AAS_mod_loop_start = 0;
869                                 if(jump_song_pos < 128) {
870                                         AAS_mod_song_pos = jump_song_pos;
871                                         if(AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][0] == -1) {
872                                                 AAS_mod_looped = AAS_TRUE;
873                                                 mod_chan = AAS_mod_chan;
874                                                 for(chan = num_chans; chan > 0; --chan) {
875                                                         mod_chan->slide_target_period = 0;
876                                                         ++mod_chan;
877                                                 }
878                                                 AAS_mod_song_pos = 0;
879                                         }
880                                 } else {
881                                         AAS_mod_looped = AAS_TRUE;
882                                         mod_chan = AAS_mod_chan;
883                                         for(chan = num_chans; chan > 0; --chan) {
884                                                 mod_chan->slide_target_period = 0;
885                                                 ++mod_chan;
886                                         }
887                                         AAS_mod_song_pos = 0;
888                                 }
889
890                                 mod_chan = AAS_mod_chan;
891                                 for(chan = 0; chan < num_chans; ++chan) {
892                                         mod_chan->pattern = (AAS_u32*)(AAS_PatternData + (((int)AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][chan]) << 8));
893                                         ++mod_chan;
894                                 }
895                                 AAS_mod_line_num = 0;
896                         } else {
897                                 ++AAS_mod_line_num;
898                                 if(AAS_mod_line_num > 63) {
899                                         AAS_mod_line_num = 0;
900                                         AAS_mod_loop_start = 0;
901
902                                         if(AAS_mod_next_song_pos == -1) {
903                                                 ++AAS_mod_song_pos;
904                                         } else {
905                                                 AAS_mod_song_pos = AAS_mod_next_song_pos;
906                                                 AAS_mod_next_song_pos = -1;
907                                         }
908
909                                         if(AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][0] == -1) {
910                                                 AAS_mod_looped = AAS_TRUE;
911                                                 mod_chan = AAS_mod_chan;
912                                                 for(chan = num_chans; chan > 0; --chan) {
913                                                         mod_chan->slide_target_period = 0;
914                                                         ++mod_chan;
915                                                 }
916                                                 AAS_mod_song_pos = AAS_RestartPos[AAS_mod_num];
917                                         }
918
919                                         mod_chan = AAS_mod_chan;
920                                         for(chan = 0; chan < num_chans; ++chan) {
921                                                 mod_chan->pattern = (AAS_u32*)(AAS_PatternData + (((int)AAS_Sequence[AAS_mod_num][AAS_mod_song_pos][chan]) << 8));
922                                                 ++mod_chan;
923                                         }
924                                 }
925                         }
926
927                         if(AAS_mod_looped)
928                                 if(!AAS_mod_loop)
929                                         AAS_MOD_Stop();
930                 }
931         }
932 }