summaryrefslogtreecommitdiff
path: root/drivers/chibi/cp_player_data.h
blob: 282592b8f4e95853151a05b0c0bf99070c89257b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
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
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
/*************************************************************************/
/*  cp_player_data.h                                                     */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#ifndef CP_PLAYER_DATA_H
#define CP_PLAYER_DATA_H

#include "cp_config.h"
#include "cp_song.h"
#include "cp_mixer.h"
#include "cp_tables.h"

/**CPPlayer Data
  *@author Juan Linietsky
  */

/******************************
 player_data.h
 ------------------------

The player and its data.
I hope you dont get sick reading this
********************************/

//Default pan values


class CPPlayer {

	enum {
		PAN_SURROUND=512,
		PAN_RIGHT=255,
		PAN_LEFT=0,
		PAN_CENTER=128
	};


	CPSong *song;

	CPMixer *mixer;

        struct Filter_Control {

		int32_t it_reso;
		int32_t it_cutoff;
		int32_t envelope_cutoff;
		int32_t final_cutoff;
		
		void process();
		void set_filter_parameters(int *p_cutoff,uint8_t *p_reso);

        };

	//tells you if a channel is doing
	//noteoff/notekill/notefade/etc
	enum {
	
		END_NOTE_NOTHING=0,
		END_NOTE_OFF=1,
		END_NOTE_FADE=2,
		END_NOTE_KILL=4
	};
	
	//Tells you what should a channel restart
	enum {
	
		KICK_NOTHING,
		KICK_NOTE,
		KICK_NOTEOFF,
		KICK_ENVELOPE
	};

	enum {
		
		MAX_VOICES=256
	};
	
	struct Channel_Control;

        struct Voice_Control {

		struct Envelope_Control {

			int pos_index;
			int status;
			int value;
			bool sustain_looping;
			bool looping;
			bool terminated;
			bool active;
			bool kill;

		};

                Filter_Control filter;
                uint16_t reverb_send;
                uint16_t chorus_send;

		CPInstrument* instrument_ptr;
		CPSample*     sample_ptr;

//		Sample_Data *sample_data;

		int32_t period;		

		int32_t sample_start_index;        /* The starting byte index in the sample */

		bool has_master_channel;
		int master_channel_index;
                int instruement_index;

		int instrument_index;
		int sample_index;
		int8_t NNA_type;

		int note_end_flags;

		uint8_t       sample;       /* which instrument number */

 		int16_t output_volume;       /* output volume (vol + sampcol + instvol) */
		int8_t  channel_volume;      /* channel's "global" volume */
		uint16_t fadeout_volume;      /* fading volume rate */
		int32_t total_volume;     /* total volume of channel (before global mixings) */
		uint8_t       kick;         /* if true = sample has to be restarted */
	
		uint8_t       note;         /* the audible note (as heard, direct rep of period) */

		int16_t       panning;      /* panning position */
		
		uint8_t       nna;          /* New note action type + master/slave flags */
		uint8_t       volflg;       /* volume envelope settings */
		uint8_t       panflg;       /* panning envelope settings */
		uint8_t       pitflg;       /* pitch envelope settings */
		uint8_t       keyoff;       /* if true = fade out and stuff */
		int16_t       handle;       /* which sample-handle */
		int32_t       start;        /* The start byte index in the sample */
	
	/* Below here is info NOT in MP_CONTROL!! */
		//ENVPR       venv;
		//ENVPR       penv;
		//ENVPR       cenv;

		Envelope_Control volume_envelope_ctrl;
		Envelope_Control panning_envelope_ctrl;
		Envelope_Control pitch_envelope_ctrl;
	
		uint16_t       auto_vibrato_pos;      /* autovibrato pos */
		uint16_t       auto_vibrato_sweep_pos;      /* autovibrato sweep pos */
		
		int16_t       masterchn;
		uint16_t       masterperiod;
	
		Channel_Control* master_channel;       /* index of "master" effects channel */

		void start_envelope(CPEnvelope *p_envelope,Envelope_Control *p_envelope_ctrl,Envelope_Control *p_from_env);
		bool process_envelope(CPEnvelope *p_envelope,Envelope_Control *p_envelope_ctrl);

		uint16_t display_volume;
		
		Voice_Control() {
			
			reset();
		}

		void reset();
	        void update_info_from_master_channel();
		

	};


	struct Channel_Control {

		/* NOTE info */
		uint8_t  note;                      /* the audible note as heard, direct rep of period */	
		uint8_t  real_note;                 /* the note that indexes the audible */
		int32_t sample_start_index;        /* The starting byte index in the sample */
		uint8_t  old_note;

		uint8_t kick;
		
                Filter_Control filter;
                uint16_t reverb_send;
                uint16_t chorus_send;

		
		int note_end_flags;

		/* INSTRUMENT INFO */

		CPInstrument* instrument_ptr;
		CPSample*     sample_ptr;

		uint8_t  instrument_index;
		uint8_t  sample_index;
		bool new_instrument;

		/* SAMPLE SPECIFIC INFO */
		int32_t base_speed;        /* what finetune to use */

		/* INSTRUMENT SPECIFIC INFO */

		int8_t NNA_type;
		int8_t duplicate_check_type;
		int8_t duplicate_check_action;

		bool volume_envelope_on;
		bool panning_envelope_on;
		bool pitch_envelope_on;

                bool has_own_period;

		bool row_has_note;

		/* VOLUME COLUMN */

		int16_t  volume;       /* amiga volume (0 t/m 64) to play the sample at */
		int16_t aux_volume;
		bool has_own_volume;
		bool mute;
		int16_t random_volume_variation; /* 0-100 - 100 has no effect */

		/* VOLUME/PAN/PITCH MODIFIERS */

		int8_t	default_volume; // CHANNEL default volume (0-64)
		int16_t  channel_volume; // CHANNEL current volume //chanvol - current!
		int16_t  output_volume; /* output volume (vol + sampcol + instvol) //volume */
		int16_t  channel_global_volume;

		uint16_t  fadeout_volume;      /* fading volume rate */

		int32_t period;       /* period to play the sample at */
		
		/* PAN */

		int16_t  panning;   /* panning position */
                int16_t  channel_panning;
		int8_t   sliding;

		uint16_t aux_period;    /* temporary period */



		/* TIMING */
		uint8_t note_delay;    /* (used for note delay) */		

		/* Slave Voice Control */

		Voice_Control *slave_voice;        /* Audio Slave of current effects control channel */
		
		struct Carry {
			
			Voice_Control::Envelope_Control vol;
			Voice_Control::Envelope_Control pan;
			Voice_Control::Envelope_Control pitch;
			bool maybe;

		} carry;


	
		uint8_t       slave_voice_index;     /* Audio Slave of current effects control channel */

		uint8_t*      row;          /* row currently playing on this channel */

		/* effect memory variables */

		uint8_t current_command;
		uint8_t current_parameter;
		uint8_t current_volume_command;
		uint8_t current_volume_parameter;
		uint8_t volcol_volume_slide;

		/* CPSample Offset */

		int32_t lo_offset;
		int32_t hi_offset;

		/* Panbrello waveform */
		uint8_t       panbrello_type;     /* current panbrello waveform */
		uint8_t       panbrello_position;      /* current panbrello position */
		int8_t       panbrello_speed;      /* "" speed */
		uint8_t       panbrello_depth;    /* "" depth */
                uint8_t	    panbrello_info;
                /* Arpegio */

		uint8_t	     arpegio_info;
                /* CPPattern Loop */

		int pattern_loop_position;
		int8_t pattern_loop_count;

                /* Vibrato */
                bool doing_vibrato;
		int8_t       vibrato_position;       /* current vibrato position */
		uint8_t       vibrato_speed;       /* "" speed */
		uint8_t       vibrato_depth;     /* "" depth */
                uint8_t	    vibrato_type;	
		/* Tremor */
		int8_t       tremor_position;
		uint8_t       tremor_speed;    /* s3m tremor ontime/offtime */
		uint8_t	    tremor_depth;
		uint8_t	    tremor_info;

		/* Tremolo */
		int8_t       tremolo_position;
		uint8_t       tremolo_speed;    /* s3m tremor ontime/offtime */
		uint8_t	    tremolo_depth;
		uint8_t	    tremolo_info;
		uint8_t	    tremolo_type;

		/* Retrig */
		int8_t       retrig_counter;  /* retrig value (0 means don't retrig) */
		uint8_t       retrig_speed;  /* last used retrig speed */
		uint8_t       retrig_volslide;  /* last used retrig slide */

		/* CPSample Offset */
		int32_t       sample_offset_hi;     /* last used high order of sample offset */
		uint16_t       sample_offset;      /* last used low order of sample-offset (effect 9) */
		uint16_t       sample_offset_fine;    /* fine sample offset memory */

		/* Portamento */
		uint16_t slide_to_period; /* period to slide to (with effect 3 or 5) */
		uint8_t portamento_speed;

	        /* Volume Slide */

		uint8_t volume_slide_info;

                /* Channel Volume Slide */

		uint8_t channel_volume_slide_info;

                /* Global Volume Slide */

                uint8_t global_volume_slide_info;

                /* Channel Pan Slide */

		uint8_t channel_pan_slide_info;

		/* Pitch Slide */

		uint8_t pitch_slide_info;
		/* Tempo Slide */

		uint8_t tempo_slide_info;

                /* S effects memory */

                uint8_t current_S_effect;
                uint8_t current_S_data;

		/* Volume column memory */

		uint8_t       volume_column_effect_mem;
		uint8_t       volume_column_data_mem;

		int64_t last_event_usecs;
		bool reserved;
		
		void reset();

		Channel_Control() { channel_global_volume=255; last_event_usecs=-1; }
	};
	
	struct Control_Variables { // control variables (dynamic version) of initial variables

		bool reached_end;
				
		char play_mode;
                bool filters;
		int global_volume;
		int speed;
		int tempo;

		int ticks_counter;

		int pattern_delay_1;
		int pattern_delay_2;

		Channel_Control channel[CPPattern::WIDTH];

		int max_voices;

		int voices_used; /* reference value */

		bool force_no_nna;
		bool external_vibrato;
		
		struct Position {

			int current_order;
			int current_pattern;
			int current_row;
			int force_next_order;
			bool forbid_jump;
		};

		int32_t random_seed;

		Position position;
		Position previous_position;

	};


	Voice_Control voice[MAX_VOICES];
		
	Control_Variables control;

	/* VOICE SETUP */
	
	void setup_voices();

	/* MIXER SETUP */
	void handle_tick();
	void update_mixer();
	
	/* NOTE / INSTRUMENT PROCESSING */

	void process_new_note(int p_track,uint8_t p_note);
	bool process_new_instrument(int p_track,uint8_t p_instrument);
	bool process_note_and_instrument(int p_track,int p_note,int p_instrument);
	
	/* EFFECT PROCESSING */
	void do_effect_S(int p_track);
	void do_panbrello(int p_track);
	void do_global_volume_slide(int p_track);
        void do_tremolo(int p_track);
        void do_retrig(int p_track);
	void do_pan_slide(int p_track);
        void do_channel_volume_slide(int p_track);
        void do_volume_slide(int p_track,int inf);
	void do_pitch_slide_down(int p_track,uint8_t inf);
	void do_pitch_slide_up(int p_track,uint8_t inf);
        void do_tremor(int p_track);
        void do_vibrato(int p_track,bool fine);
        void do_pitch_slide_to_note(int p_track);
        void run_effects(int p_track);
        void run_volume_column_effects(int p_track);
        void pre_process_effects();
        void do_arpegio(int p_track);
	uint64_t song_usecs;
	/* NNA */

	void process_NNAs();


	/* MISC UTILS */


        int find_empty_voice();
	void process_volume_column(int p_track,uint8_t p_volume);
        void process_note(int p_track,CPNote p_note);

	/* CPTables */
        static uint8_t auto_vibrato_table[128];
        static uint8_t vibrato_table[32];
        static int8_t panbrello_table[256];

	static void callback_function(void *p_userdata);

public:
        //Play modes

	enum {
	
		PLAY_NOTHING =0,
		PLAY_PATTERN =1,
		PLAY_SONG =2
	};


        int32_t get_frequency(int32_t period);
	int32_t get_period(uint16_t note,int32_t p_c5freq);
	

	int get_current_tempo() { return control.tempo; };
	int get_current_speed() { return control.speed; };

        int get_voices_used() { return control.voices_used;};
	int get_voice_envelope_pos(int p_voice,CPEnvelope *p_envelope);
	int get_voice_amount_limit() { return control.max_voices; };
	void set_voice_amount_limit(int p_limit);
	void set_reserved_voices(int p_amount);
	int get_reserved_voices_amount();
	
	bool is_voice_active(int p_voice);
	int get_channel_voice(int p_channel);
	const char* get_voice_sample_name(int p_voice);
	const char* get_voice_instrument_name(int p_voice);
	CPEnvelope* get_voice_envelope(int p_voice,CPInstrument::EnvelopeType p_env_type);
	int get_voice_envelope_pos(int p_voice,CPInstrument::EnvelopeType p_env_type);
	int get_voice_volume(int p_voice);
	
	int get_voice_sample_index(int p_voice);

	void set_virtual_channels(int p_amount);
	int get_virtual_channels() { return control.max_voices; };


	/* Play Info/Position */
        bool is_playing() { return (control.play_mode>0); };
	int get_play_mode() {return (control.play_mode);};
	int get_current_order() { return control.position.current_order; };
	int get_current_row() { return control.position.current_row; };
	int get_current_pattern() { return control.position.current_pattern; };

        void goto_next_order();
        void goto_previous_order();

	void process_tick();


	CPMixer* get_mixer_ptr() {

		return mixer;		
	}


	void reset();

	
	
	/* External player control - editor - */

        void play_start_pattern(int p_pattern);
	void play_start_song();
	void play_start_song_from_order(int p_order);
	void play_start_song_from_order_and_row(int p_order,int p_row);
        void play_start(int p_pattern, int p_order, int p_row,bool p_lock=true);

        void play_stop();
        void play_note(int p_channel,CPNote note,bool p_reserve=false);

        bool reached_end_of_song();
	
        void set_force_no_nna(bool p_force);
        void set_force_external_vibratos(bool p_force);

        void set_filters_enabled(bool p_enable);
        bool are_filters_enabled() { return control.filters; }

	void set_channel_global_volume(int p_channel,int p_volume); //0-255
	int get_channel_global_volume(int p_channel) const;

	int64_t get_channel_last_note_time_usec(int p_channel) const;

	CPSong *get_song() { return song; };


	CPPlayer(CPMixer *p_mixer,CPSong *p_song);
	~CPPlayer();
};

#endif