1 /*************************************************************************/
2 /*  cp_player_data_control.cpp                                           */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #include "cp_player_data.h"
32 
play_start_pattern(int p_pattern)33 void CPPlayer::play_start_pattern(int p_pattern) {
34 
35 	play_start(p_pattern, -1, -1);
36 }
37 
play_start_song()38 void CPPlayer::play_start_song() {
39 
40 	play_start(-1, -1, -1);
41 }
42 
play_start_song_from_order(int p_order)43 void CPPlayer::play_start_song_from_order(int p_order) {
44 
45 	play_start(-1, p_order, -1);
46 }
47 
play_start_song_from_order_and_row(int p_order,int p_row)48 void CPPlayer::play_start_song_from_order_and_row(int p_order, int p_row) {
49 
50 	play_start(-1, p_order, p_row);
51 }
52 
play_start(int p_pattern,int p_order,int p_row,bool p_lock)53 void CPPlayer::play_start(int p_pattern, int p_order, int p_row, bool p_lock) {
54 
55 	if (control.play_mode != PLAY_NOTHING) play_stop();
56 
57 	reset();
58 
59 	if (p_pattern != -1) {
60 
61 		control.play_mode = PLAY_PATTERN;
62 		control.position.current_pattern = p_pattern;
63 		control.position.current_row = (p_row != -1) ? p_row : 0;
64 
65 	} else {
66 
67 		control.position.current_order = get_song_next_order_idx(song, (p_order == -1) ? p_order : p_order - 1);
68 		if (control.position.current_order != -1) {
69 
70 			control.play_mode = PLAY_SONG;
71 			control.position.current_pattern = song->get_order(control.position.current_order);
72 			control.position.current_row = (p_row != -1) ? p_row : 0;
73 		}
74 	}
75 
76 	control.reached_end = (control.play_mode == PLAY_NOTHING);
77 }
78 
play_stop()79 void CPPlayer::play_stop() {
80 
81 	int i;
82 
83 	control.play_mode = PLAY_NOTHING;
84 
85 	for (i = 0; i < control.max_voices; i++) {
86 
87 		voice[i].reset();
88 		mixer->stop_voice(i);
89 	}
90 
91 	for (i = 0; i < CPPattern::WIDTH; i++) {
92 
93 		control.channel[i].reset();
94 	}
95 
96 	reset();
97 }
98 
play_note(int p_channel,CPNote note,bool p_reserve)99 void CPPlayer::play_note(int p_channel, CPNote note, bool p_reserve) {
100 
101 	if (control.play_mode == PLAY_NOTHING) {
102 
103 		control.ticks_counter = 0;
104 	}
105 
106 	/*control.channel[p_channel].reset();
107 	control.channel[p_channel].channel_volume=song->get_channel_volume(p_channel);
108 	control.channel[p_channel].channel_panning=((int)song->get_channel_pan( p_channel)*255/64);*/
109 	if (p_reserve) {
110 		control.channel[p_channel].mute = false;
111 		control.channel[p_channel].reserved = true;
112 	} else {
113 
114 		control.channel[p_channel].reserved = false;
115 	}
116 	process_note(p_channel, note);
117 }
118 
get_voice_volume(int p_voice)119 int CPPlayer::get_voice_volume(int p_voice) {
120 
121 	return voice[p_voice].display_volume;
122 }
123 
get_voice_envelope_pos(int p_voice,CPEnvelope * p_envelope)124 int CPPlayer::get_voice_envelope_pos(int p_voice, CPEnvelope *p_envelope) {
125 
126 	int i, tmp_index = -1;
127 
128 	i = p_voice;
129 
130 	if ((song->has_instruments()) && (voice[i].instrument_ptr != NULL) && (voice[i].fadeout_volume > 0)) {
131 
132 		if ((p_envelope == voice[i].instrument_ptr->get_volume_envelope()) && (voice[i].instrument_ptr->get_volume_envelope()->is_enabled())) {
133 
134 			tmp_index = voice[i].volume_envelope_ctrl.pos_index;
135 		}
136 
137 		if ((p_envelope == voice[i].instrument_ptr->get_pan_envelope()) && (voice[i].instrument_ptr->get_pan_envelope()->is_enabled())) {
138 
139 			tmp_index = voice[i].panning_envelope_ctrl.pos_index;
140 		}
141 
142 		if ((p_envelope == voice[i].instrument_ptr->get_pitch_filter_envelope()) && (voice[i].instrument_ptr->get_pitch_filter_envelope()->is_enabled())) {
143 
144 			tmp_index = voice[i].pitch_envelope_ctrl.pos_index;
145 		}
146 	}
147 
148 	return tmp_index;
149 }
150 
goto_next_order()151 void CPPlayer::goto_next_order() {
152 
153 	if (control.play_mode != PLAY_SONG) return;
154 
155 	control.position.current_row = 0;
156 
157 	control.position.current_order = get_song_next_order_idx(song, control.position.current_order);
158 
159 	if (control.position.current_order == -1) {
160 
161 		reset();
162 	}
163 
164 	control.position.current_pattern = song->get_order(control.position.current_order);
165 }
goto_previous_order()166 void CPPlayer::goto_previous_order() {
167 
168 	if (control.play_mode != PLAY_SONG) return;
169 
170 	int next_order, current_order;
171 
172 	control.position.current_row = 0;
173 
174 	current_order = control.position.current_order;
175 
176 	next_order = get_song_next_order_idx(song, current_order);
177 
178 	while ((next_order != control.position.current_order) && (next_order != -1)) {
179 
180 		current_order = next_order;
181 		next_order = get_song_next_order_idx(song, current_order);
182 	}
183 
184 	if (next_order == -1) {
185 
186 		reset();
187 	} else {
188 
189 		control.position.current_order = current_order;
190 		control.position.current_pattern = song->get_order(control.position.current_order);
191 	}
192 }
193 
get_channel_voice(int p_channel)194 int CPPlayer::get_channel_voice(int p_channel) {
195 
196 	if (control.channel[p_channel].slave_voice == NULL)
197 		return -1;
198 	else
199 		return control.channel[p_channel].slave_voice_index;
200 }
201 
get_voice_sample_name(int p_voice)202 const char *CPPlayer::get_voice_sample_name(int p_voice) {
203 
204 	const char *name = NULL;
205 
206 	if (!voice[p_voice].sample_ptr) name = voice[p_voice].sample_ptr->get_name();
207 
208 	return name;
209 }
210 
is_voice_active(int p_voice)211 bool CPPlayer::is_voice_active(int p_voice) {
212 
213 	return !(((voice[p_voice].kick == KICK_NOTHING) || (voice[p_voice].kick == KICK_ENVELOPE)) && !mixer->is_voice_active(p_voice));
214 }
215 
get_voice_envelope_pos(int p_voice,CPInstrument::EnvelopeType p_env_type)216 int CPPlayer::get_voice_envelope_pos(int p_voice, CPInstrument::EnvelopeType p_env_type) {
217 
218 	if (!is_voice_active(p_voice))
219 		return -1;
220 
221 	Voice_Control::Envelope_Control *env = 0;
222 
223 	switch (p_env_type) {
224 
225 		case CPInstrument::VOLUME_ENVELOPE: env = &voice[p_voice].volume_envelope_ctrl; break;
226 		case CPInstrument::PAN_ENVELOPE: env = &voice[p_voice].panning_envelope_ctrl; break;
227 		case CPInstrument::PITCH_ENVELOPE: env = &voice[p_voice].pitch_envelope_ctrl; break;
228 	}
229 
230 	if (!env)
231 		return -1;
232 
233 	if (!env->active || env->terminated)
234 		return -1;
235 
236 	return env->pos_index;
237 }
238 
get_voice_envelope(int p_voice,CPInstrument::EnvelopeType p_env_type)239 CPEnvelope *CPPlayer::get_voice_envelope(int p_voice, CPInstrument::EnvelopeType p_env_type) {
240 
241 	CPInstrument *ins = voice[p_voice].instrument_ptr;
242 
243 	if (!ins)
244 		return 0;
245 
246 	switch (p_env_type) {
247 
248 		case CPInstrument::VOLUME_ENVELOPE: return ins->get_volume_envelope();
249 		case CPInstrument::PAN_ENVELOPE: return ins->get_pan_envelope();
250 		case CPInstrument::PITCH_ENVELOPE: return ins->get_pitch_filter_envelope();
251 	};
252 
253 	return 0;
254 }
255 
get_voice_instrument_name(int p_voice)256 const char *CPPlayer::get_voice_instrument_name(int p_voice) {
257 
258 	const char *name = NULL;
259 
260 	if (voice[p_voice].instrument_ptr != NULL) name = voice[p_voice].instrument_ptr->get_name();
261 
262 	return name;
263 }
set_filters_enabled(bool p_enable)264 void CPPlayer::set_filters_enabled(bool p_enable) {
265 
266 	control.filters = p_enable;
267 }
268 
get_voice_sample_index(int p_voice)269 int CPPlayer::get_voice_sample_index(int p_voice) {
270 
271 	return voice[p_voice].sample_index;
272 }
273