From e6dc51a0f764dcd7cd07482c022c1e92e6a4da3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Fri, 14 Oct 2016 19:14:40 +0200 Subject: chibi: Move to a module --- drivers/SCsub | 1 - drivers/chibi/SCsub | 5 - drivers/chibi/cp_config.h | 52 -- drivers/chibi/cp_envelope.cpp | 369 --------- drivers/chibi/cp_envelope.h | 129 --- drivers/chibi/cp_file_access_wrapper.h | 96 --- drivers/chibi/cp_instrument.cpp | 344 -------- drivers/chibi/cp_instrument.h | 219 ----- drivers/chibi/cp_loader.h | 64 -- drivers/chibi/cp_loader_it.cpp | 216 ----- drivers/chibi/cp_loader_it.h | 125 --- drivers/chibi/cp_loader_it_info.cpp | 268 ------ drivers/chibi/cp_loader_it_instruments.cpp | 224 ----- drivers/chibi/cp_loader_it_patterns.cpp | 166 ---- drivers/chibi/cp_loader_it_samples.cpp | 620 -------------- drivers/chibi/cp_loader_mod.cpp | 482 ----------- drivers/chibi/cp_loader_mod.h | 52 -- drivers/chibi/cp_loader_s3m.cpp | 413 ---------- drivers/chibi/cp_loader_s3m.h | 111 --- drivers/chibi/cp_loader_xm.cpp | 752 ----------------- drivers/chibi/cp_loader_xm.h | 89 -- drivers/chibi/cp_mixer.h | 115 --- drivers/chibi/cp_note.h | 102 --- drivers/chibi/cp_order.h | 43 - drivers/chibi/cp_pattern.cpp | 574 ------------- drivers/chibi/cp_pattern.h | 94 --- drivers/chibi/cp_player_data.cpp | 151 ---- drivers/chibi/cp_player_data.h | 582 ------------- drivers/chibi/cp_player_data_control.cpp | 324 -------- drivers/chibi/cp_player_data_effects.cpp | 1232 ---------------------------- drivers/chibi/cp_player_data_envelopes.cpp | 89 -- drivers/chibi/cp_player_data_events.cpp | 679 --------------- drivers/chibi/cp_player_data_filter.cpp | 89 -- drivers/chibi/cp_player_data_nna.cpp | 144 ---- drivers/chibi/cp_player_data_notes.cpp | 345 -------- drivers/chibi/cp_player_data_utils.cpp | 138 ---- drivers/chibi/cp_sample.cpp | 203 ----- drivers/chibi/cp_sample.h | 112 --- drivers/chibi/cp_sample_defs.h | 97 --- drivers/chibi/cp_sample_manager.cpp | 78 -- drivers/chibi/cp_sample_manager.h | 99 --- drivers/chibi/cp_song.cpp | 957 --------------------- drivers/chibi/cp_song.h | 261 ------ drivers/chibi/cp_tables.cpp | 254 ------ drivers/chibi/cp_tables.h | 67 -- drivers/chibi/event_stream_chibi.cpp | 872 -------------------- drivers/chibi/event_stream_chibi.h | 314 ------- drivers/register_driver_types.cpp | 6 - modules/chibi/SCsub | 7 + modules/chibi/config.py | 6 + modules/chibi/cp_config.h | 52 ++ modules/chibi/cp_envelope.cpp | 369 +++++++++ modules/chibi/cp_envelope.h | 129 +++ modules/chibi/cp_file_access_wrapper.h | 96 +++ modules/chibi/cp_instrument.cpp | 344 ++++++++ modules/chibi/cp_instrument.h | 219 +++++ modules/chibi/cp_loader.h | 64 ++ modules/chibi/cp_loader_it.cpp | 216 +++++ modules/chibi/cp_loader_it.h | 125 +++ modules/chibi/cp_loader_it_info.cpp | 268 ++++++ modules/chibi/cp_loader_it_instruments.cpp | 224 +++++ modules/chibi/cp_loader_it_patterns.cpp | 166 ++++ modules/chibi/cp_loader_it_samples.cpp | 620 ++++++++++++++ modules/chibi/cp_loader_mod.cpp | 482 +++++++++++ modules/chibi/cp_loader_mod.h | 52 ++ modules/chibi/cp_loader_s3m.cpp | 413 ++++++++++ modules/chibi/cp_loader_s3m.h | 111 +++ modules/chibi/cp_loader_xm.cpp | 752 +++++++++++++++++ modules/chibi/cp_loader_xm.h | 89 ++ modules/chibi/cp_mixer.h | 115 +++ modules/chibi/cp_note.h | 102 +++ modules/chibi/cp_order.h | 43 + modules/chibi/cp_pattern.cpp | 574 +++++++++++++ modules/chibi/cp_pattern.h | 94 +++ modules/chibi/cp_player_data.cpp | 151 ++++ modules/chibi/cp_player_data.h | 582 +++++++++++++ modules/chibi/cp_player_data_control.cpp | 324 ++++++++ modules/chibi/cp_player_data_effects.cpp | 1232 ++++++++++++++++++++++++++++ modules/chibi/cp_player_data_envelopes.cpp | 89 ++ modules/chibi/cp_player_data_events.cpp | 679 +++++++++++++++ modules/chibi/cp_player_data_filter.cpp | 89 ++ modules/chibi/cp_player_data_nna.cpp | 144 ++++ modules/chibi/cp_player_data_notes.cpp | 345 ++++++++ modules/chibi/cp_player_data_utils.cpp | 138 ++++ modules/chibi/cp_sample.cpp | 203 +++++ modules/chibi/cp_sample.h | 112 +++ modules/chibi/cp_sample_defs.h | 97 +++ modules/chibi/cp_sample_manager.cpp | 78 ++ modules/chibi/cp_sample_manager.h | 99 +++ modules/chibi/cp_song.cpp | 957 +++++++++++++++++++++ modules/chibi/cp_song.h | 261 ++++++ modules/chibi/cp_tables.cpp | 254 ++++++ modules/chibi/cp_tables.h | 67 ++ modules/chibi/event_stream_chibi.cpp | 872 ++++++++++++++++++++ modules/chibi/event_stream_chibi.h | 314 +++++++ modules/chibi/register_types.cpp | 41 + modules/chibi/register_types.h | 30 + 97 files changed, 12890 insertions(+), 12818 deletions(-) delete mode 100644 drivers/chibi/SCsub delete mode 100644 drivers/chibi/cp_config.h delete mode 100644 drivers/chibi/cp_envelope.cpp delete mode 100644 drivers/chibi/cp_envelope.h delete mode 100644 drivers/chibi/cp_file_access_wrapper.h delete mode 100644 drivers/chibi/cp_instrument.cpp delete mode 100644 drivers/chibi/cp_instrument.h delete mode 100644 drivers/chibi/cp_loader.h delete mode 100644 drivers/chibi/cp_loader_it.cpp delete mode 100644 drivers/chibi/cp_loader_it.h delete mode 100644 drivers/chibi/cp_loader_it_info.cpp delete mode 100644 drivers/chibi/cp_loader_it_instruments.cpp delete mode 100644 drivers/chibi/cp_loader_it_patterns.cpp delete mode 100644 drivers/chibi/cp_loader_it_samples.cpp delete mode 100644 drivers/chibi/cp_loader_mod.cpp delete mode 100644 drivers/chibi/cp_loader_mod.h delete mode 100644 drivers/chibi/cp_loader_s3m.cpp delete mode 100644 drivers/chibi/cp_loader_s3m.h delete mode 100644 drivers/chibi/cp_loader_xm.cpp delete mode 100644 drivers/chibi/cp_loader_xm.h delete mode 100644 drivers/chibi/cp_mixer.h delete mode 100644 drivers/chibi/cp_note.h delete mode 100644 drivers/chibi/cp_order.h delete mode 100644 drivers/chibi/cp_pattern.cpp delete mode 100644 drivers/chibi/cp_pattern.h delete mode 100644 drivers/chibi/cp_player_data.cpp delete mode 100644 drivers/chibi/cp_player_data.h delete mode 100644 drivers/chibi/cp_player_data_control.cpp delete mode 100644 drivers/chibi/cp_player_data_effects.cpp delete mode 100644 drivers/chibi/cp_player_data_envelopes.cpp delete mode 100644 drivers/chibi/cp_player_data_events.cpp delete mode 100644 drivers/chibi/cp_player_data_filter.cpp delete mode 100644 drivers/chibi/cp_player_data_nna.cpp delete mode 100644 drivers/chibi/cp_player_data_notes.cpp delete mode 100644 drivers/chibi/cp_player_data_utils.cpp delete mode 100644 drivers/chibi/cp_sample.cpp delete mode 100644 drivers/chibi/cp_sample.h delete mode 100644 drivers/chibi/cp_sample_defs.h delete mode 100644 drivers/chibi/cp_sample_manager.cpp delete mode 100644 drivers/chibi/cp_sample_manager.h delete mode 100644 drivers/chibi/cp_song.cpp delete mode 100644 drivers/chibi/cp_song.h delete mode 100644 drivers/chibi/cp_tables.cpp delete mode 100644 drivers/chibi/cp_tables.h delete mode 100644 drivers/chibi/event_stream_chibi.cpp delete mode 100644 drivers/chibi/event_stream_chibi.h create mode 100644 modules/chibi/SCsub create mode 100644 modules/chibi/config.py create mode 100644 modules/chibi/cp_config.h create mode 100644 modules/chibi/cp_envelope.cpp create mode 100644 modules/chibi/cp_envelope.h create mode 100644 modules/chibi/cp_file_access_wrapper.h create mode 100644 modules/chibi/cp_instrument.cpp create mode 100644 modules/chibi/cp_instrument.h create mode 100644 modules/chibi/cp_loader.h create mode 100644 modules/chibi/cp_loader_it.cpp create mode 100644 modules/chibi/cp_loader_it.h create mode 100644 modules/chibi/cp_loader_it_info.cpp create mode 100644 modules/chibi/cp_loader_it_instruments.cpp create mode 100644 modules/chibi/cp_loader_it_patterns.cpp create mode 100644 modules/chibi/cp_loader_it_samples.cpp create mode 100644 modules/chibi/cp_loader_mod.cpp create mode 100644 modules/chibi/cp_loader_mod.h create mode 100644 modules/chibi/cp_loader_s3m.cpp create mode 100644 modules/chibi/cp_loader_s3m.h create mode 100644 modules/chibi/cp_loader_xm.cpp create mode 100644 modules/chibi/cp_loader_xm.h create mode 100644 modules/chibi/cp_mixer.h create mode 100644 modules/chibi/cp_note.h create mode 100644 modules/chibi/cp_order.h create mode 100644 modules/chibi/cp_pattern.cpp create mode 100644 modules/chibi/cp_pattern.h create mode 100644 modules/chibi/cp_player_data.cpp create mode 100644 modules/chibi/cp_player_data.h create mode 100644 modules/chibi/cp_player_data_control.cpp create mode 100644 modules/chibi/cp_player_data_effects.cpp create mode 100644 modules/chibi/cp_player_data_envelopes.cpp create mode 100644 modules/chibi/cp_player_data_events.cpp create mode 100644 modules/chibi/cp_player_data_filter.cpp create mode 100644 modules/chibi/cp_player_data_nna.cpp create mode 100644 modules/chibi/cp_player_data_notes.cpp create mode 100644 modules/chibi/cp_player_data_utils.cpp create mode 100644 modules/chibi/cp_sample.cpp create mode 100644 modules/chibi/cp_sample.h create mode 100644 modules/chibi/cp_sample_defs.h create mode 100644 modules/chibi/cp_sample_manager.cpp create mode 100644 modules/chibi/cp_sample_manager.h create mode 100644 modules/chibi/cp_song.cpp create mode 100644 modules/chibi/cp_song.h create mode 100644 modules/chibi/cp_tables.cpp create mode 100644 modules/chibi/cp_tables.h create mode 100644 modules/chibi/event_stream_chibi.cpp create mode 100644 modules/chibi/event_stream_chibi.h create mode 100644 modules/chibi/register_types.cpp create mode 100644 modules/chibi/register_types.h diff --git a/drivers/SCsub b/drivers/SCsub index edab83cd86..4ae42a33d5 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -21,7 +21,6 @@ if ("builtin_zlib" in env and env["builtin_zlib"] == "yes"): if (env["platform"] == "windows"): SConscript("rtaudio/SCsub"); SConscript("nrex/SCsub"); -SConscript("chibi/SCsub"); if (env["tools"]=="yes"): SConscript("convex_decomp/SCsub"); diff --git a/drivers/chibi/SCsub b/drivers/chibi/SCsub deleted file mode 100644 index 9fbb467baa..0000000000 --- a/drivers/chibi/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -Import('env') - -env.add_source_files(env.drivers_sources,"*.cpp") - -Export('env') diff --git a/drivers/chibi/cp_config.h b/drivers/chibi/cp_config.h deleted file mode 100644 index 2ad704ace7..0000000000 --- a/drivers/chibi/cp_config.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* cp_config.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_CONFIG_H -#define CP_CONFIG_H - - -#include "typedefs.h" -#include "error_macros.h" -#include "math_funcs.h" -#include "os/memory.h" -#include "os/copymem.h" - -#define CP_PRINTERR(m_err) ERR_PRINT(m_err) -#define CP_ERR_COND(m_cond) ERR_FAIL_COND(m_cond) -#define CP_ERR_COND_V(m_cond,m_ret) ERR_FAIL_COND_V(m_cond,m_ret) -#define CP_FAIL_INDEX(m_index,m_size) ERR_FAIL_INDEX(m_index,m_size) -#define CP_FAIL_INDEX_V(m_index,m_size,m_ret) ERR_FAIL_INDEX_V(m_index,m_size,m_ret) -#define cp_intabs(m_val) ABS(m_val) - -#define CP_ALLOC(m_mem) memalloc(m_mem) -#define CP_REALLOC(m_mem,m_size) memrealloc(m_mem,m_size) -#define CP_FREE(m_mem) memfree(m_mem) - -#define cp_memzero(m_mem,m_size) zeromem(m_mem,m_size) - -#endif // CP_CONFIG_H diff --git a/drivers/chibi/cp_envelope.cpp b/drivers/chibi/cp_envelope.cpp deleted file mode 100644 index 9892b6d4b0..0000000000 --- a/drivers/chibi/cp_envelope.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/*************************************************************************/ -/* cp_envelope.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_envelope.h" - - -CPEnvelope::CPEnvelope() { - - - reset(); -} - -void CPEnvelope::reset() { - - - - on=false; - carry=false; - loop_on=false; - loop_begin_node=0; - loop_end_node=0; - sustain_loop_on=false; - sustain_loop_begin_node=0; - sustain_loop_end_node=0; - node_count=0; - -} - -int CPEnvelope::get_height_at_pos(int pos) { - - if (node_count && pos>node[node_count-1].tick_offset) - return node[node_count-1].value; - - int begin_x,begin_y; - int end_x,end_y,xdif; - int count=0; - int limit=-1; - - if (node_count<2) return NO_POINT; - - while ((count=pos) limit=count; - count++; - } - - if (pos==0) return node[0].value; - - if (limit==-1) return NO_POINT; - - begin_x=node[limit-1].tick_offset; - end_x=node[limit].tick_offset; - begin_y=node[limit-1].value; - end_y=node[limit].value; - - xdif=end_x-begin_x; - return begin_y+((pos-begin_x)*(end_y-begin_y))/(xdif?xdif:1); -} - -/* -int CPEnvelope::get_fx_height_at_pos(int pos) { - - if (node_count && pos>node[node_count-1].tick_offset) - return node[node_count-1].value<=pos) limit=count; - count++; - } - - if (pos==0) return node[0].value<node[node_count-1].tick_offset) - return node[node_count-1].value; - - int begin_x,begin_y; - int end_x,end_y,xdif; - int count=0; - int limit=-1; - - if (node_count<2) return NO_POINT; - - while ((count=pos) limit=count; - count++; - } - - if (pos==0) return node[0].value; - - if (limit==-1) return NO_POINT; - - begin_x=node[limit-1].tick_offset; - end_x=node[limit].tick_offset; - begin_y=node[limit-1].value; - end_y=node[limit].value; - - xdif=end_x-begin_x; - return begin_y+((pos-begin_x)*(end_y-begin_y))/(xdif?xdif:1); -} - -void CPEnvelope::set_position(int p_node,int p_x,int p_y) { - - if (p_node>=node_count) return; - - - - if (p_node==0) { - - p_x=0; - - } else if (p_x<=node[p_node-1].tick_offset) { - - p_x=node[p_node-1].tick_offset+1; - - } else if ((p_node<(node_count-1)) && (p_x>=node[p_node+1].tick_offset)) { - - p_x=node[p_node+1].tick_offset-1; - } - - if (p_x>=9999) p_x=9999; - - if (p_y>max_value) p_y=max_value; - if (p_y=node[i].tick_offset)) i++; - - new_node=i; - node_count++; - - if (p_move_loops) { - if (loop_begin_node>=new_node) loop_begin_node++; - if (loop_end_node>=new_node) loop_end_node++; - if (sustain_loop_begin_node>=new_node) sustain_loop_begin_node++; - if (sustain_loop_end_node>=new_node) sustain_loop_end_node++; - } - for (i=node_count-1;i>new_node;i--) node[i]=node[i-1]; - - - - set_position(new_node,p_x,p_y); - - - - return new_node; - -} - -void CPEnvelope::set_loop_begin(int pos) { - - if ((pos<0) || (pos>=node_count)) return; - - - - loop_begin_node=pos; - - if (loop_end_node=node_count)) return; - - - - loop_end_node=pos; - - if (loop_end_node=node_count)) return; - - - - sustain_loop_begin_node=pos; - - if (sustain_loop_end_node=node_count)) return; - - - - sustain_loop_end_node=pos; - - if (sustain_loop_end_node=node_count)) return; - - - - int i; - - if (loop_begin_node>=p_node) loop_begin_node--; - if (loop_end_node>=p_node) loop_end_node--; - if (sustain_loop_begin_node>=p_node) sustain_loop_begin_node--; - if (sustain_loop_end_node>=p_node) sustain_loop_end_node--; - - for (i=p_node;i=node_count) - return node[node_count-1]; - - return node[p_idx]; - -} - - diff --git a/drivers/chibi/cp_envelope.h b/drivers/chibi/cp_envelope.h deleted file mode 100644 index d1ada53f7d..0000000000 --- a/drivers/chibi/cp_envelope.h +++ /dev/null @@ -1,129 +0,0 @@ -/*************************************************************************/ -/* cp_envelope.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_ENVELOPE_H -#define CP_ENVELOPE_H - -#include "cp_config.h" - -/**envelope? - *@author Juan Linietsky - */ - -/****************************** - envelope.h - ---------- - -Proovides an envelope, and basic functions -for it that can be used for both player -and interface -********************************/ - - -class CPEnvelope { - enum { - - MAX_POINTS=25 - }; - - struct Point { - - uint16_t tick_offset; - int16_t value; - }; - - Point node[MAX_POINTS]; - - int8_t node_count; - - bool on; - bool carry; - - bool loop_on; - - uint8_t loop_begin_node; - uint8_t loop_end_node; - - bool sustain_loop_on; - uint8_t sustain_loop_begin_node; - uint8_t sustain_loop_end_node; - - - int8_t max_value; - int8_t min_value; - - -public: - enum { - - NO_POINT=-5000, - }; - - void set_max(int8_t p_max) { max_value=p_max; } - int8_t get_max() { return max_value; } - void set_min(int8_t p_min) { min_value=p_min; } - int8_t get_min() { return min_value; } - - uint8_t get_node_count(); - const Point& get_node(int p_idx); - - void set_position(int p_node,int p_x,int p_y); - int add_position(int p_x,int p_y,bool p_move_loops=true); - void del_position(int p_node); - - void set_loop_enabled(bool p_enabled); - bool is_loop_enabled(); - void set_loop_begin(int pos); - void set_loop_end(int pos); - uint8_t get_loop_begin(); - uint8_t get_loop_end(); - - void set_sustain_loop_enabled(bool p_enabled); - bool is_sustain_loop_enabled(); - void set_sustain_loop_begin(int pos); - void set_sustain_loop_end(int pos); - uint8_t get_sustain_loop_begin(); - uint8_t get_sustain_loop_end(); - - void set_enabled(bool p_enabled); - bool is_enabled(); - - void set_carry_enabled(bool p_enabled); - bool is_carry_enabled(); - - void reset(); - int get_height_at_pos(int pos); - float get_interp_height_at_pos(float pos); - - - CPEnvelope(); - -}; - -#endif diff --git a/drivers/chibi/cp_file_access_wrapper.h b/drivers/chibi/cp_file_access_wrapper.h deleted file mode 100644 index 5b361c0ea8..0000000000 --- a/drivers/chibi/cp_file_access_wrapper.h +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************/ -/* cp_file_access_wrapper.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_FILE_ACCESS_WRAPPER_H -#define CP_FILE_ACCESS_WRAPPER_H - -#include "cp_config.h" - -class CPFileAccessWrapper { -public: - - enum ModeFlags { - - READ=1, - WRITE=2, - READ_WRITE=3, - }; - - enum Error { - - OK, - ERROR_FILE_NOT_FOUND, - ERROR_FILE_BAD_DRIVE, - ERROR_FILE_BAD_PATH, - ERROR_FILE_NO_PERMISSION, - ERROR_ALREADY_IN_USE, - ERROR_INVALID_PARAMETERS, - ERROR_OPENING_FILE, - ERROR_READING_FILE, - ERROR_WRITING_FILE - }; - - virtual Error open(const char *p_filename, int p_mode_flags)=0; - virtual void close()=0; - - virtual void seek(uint32_t p_position)=0; - virtual void seek_end()=0; - virtual uint32_t get_pos()=0; - - virtual bool eof_reached()=0; - - virtual uint8_t get_byte()=0; - virtual void get_byte_array(uint8_t *p_dest,int p_elements)=0; - virtual void get_word_array(uint16_t *p_dest,int p_elements)=0; - - virtual uint16_t get_word()=0; - virtual uint32_t get_dword()=0; - - // use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) - // It's not about the current CPU type but file formats. - // this flags get reset to false (little endian) on each open - virtual void set_endian_conversion(bool p_swap)=0; - virtual bool is_open()=0; - - virtual Error get_error()=0; - - virtual void store_byte(uint8_t p_dest)=0; - virtual void store_byte_array(const uint8_t *p_dest,int p_elements)=0; - - virtual void store_word(uint16_t p_dest)=0; - virtual void store_dword(uint32_t p_dest)=0; - - - - virtual ~CPFileAccessWrapper(){} - -}; - - - -#endif diff --git a/drivers/chibi/cp_instrument.cpp b/drivers/chibi/cp_instrument.cpp deleted file mode 100644 index 7a732e33a4..0000000000 --- a/drivers/chibi/cp_instrument.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/*************************************************************************/ -/* cp_instrument.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_instrument.h" -#include "cp_song.h" -#include "cp_note.h" - - - -const char *CPInstrument::get_name() { - - return name; - -} -void CPInstrument::set_name(const char *p_name) { - - - if (p_name==NULL) { - name[0]=0; - return; - } - - - bool done=false; - for (int i=0;i=CPNote::NOTES); - CP_ERR_COND(p_sample_id>CPSong::MAX_SAMPLES && p_sample_id!=CPNote::EMPTY); - data.sample_number[p_note]=p_sample_id; - - -} -uint8_t CPInstrument::get_sample_number(uint8_t p_note) { - - CP_ERR_COND_V(p_note>=CPNote::NOTES,0); - return data.sample_number[p_note]; -} - -void CPInstrument::set_note_number(uint8_t p_note,uint8_t p_note_id) { - - CP_ERR_COND(p_note>=CPNote::NOTES); - CP_ERR_COND(p_note_id>=CPNote::NOTES && p_note_id!=CPNote::EMPTY); - data.note_number[p_note]=p_note_id; - -} -uint8_t CPInstrument::get_note_number(uint8_t p_note) { - - CP_ERR_COND_V(p_note>=CPNote::NOTES,0); - return data.note_number[p_note]; - -} - -void CPInstrument::set_NNA_type(NNA_Type p_NNA_type) { - - data.NNA_type=p_NNA_type; -} -CPInstrument::NNA_Type CPInstrument::get_NNA_type() { - - return data.NNA_type; -} - -void CPInstrument::set_DC_type(DC_Type p_DC_type) { - - data.DC_type=p_DC_type; -} -CPInstrument::DC_Type CPInstrument::get_DC_type() { - - return data.DC_type; - -} - -void CPInstrument::set_DC_action(DC_Action p_DC_action) { - - data.DC_action=p_DC_action; -} -CPInstrument::DC_Action CPInstrument::get_DC_action() { - - return data.DC_action; -} - -/* Volume */ - -void CPInstrument::set_volume_global_amount(uint8_t p_amount) { - - CP_ERR_COND(p_amount>MAX_VOLUME); - data.volume.global_amount=p_amount; - -} -uint8_t CPInstrument::get_volume_global_amount() { - - return data.volume.global_amount; -} - -void CPInstrument::set_volume_fadeout(uint16_t p_amount) { - CP_ERR_COND(p_amount>MAX_FADEOUT); - data.volume.fadeout=p_amount; -} -uint16_t CPInstrument::get_volume_fadeout() { - - return data.volume.fadeout; -} -void CPInstrument::set_volume_random_variation(uint8_t p_amount) { - - CP_ERR_COND(p_amount>MAX_VOLUME_RANDOM); - data.volume.random_variation=p_amount; -} -uint8_t CPInstrument::get_volume_random_variation() { - - return data.volume.random_variation; -} - -/* Panning */ - -void CPInstrument::set_pan_default_amount(uint8_t p_amount) { - - CP_ERR_COND(p_amount>MAX_PAN); - data.pan.default_amount=p_amount; -} -uint8_t CPInstrument::get_pan_default_amount() { - - return data.pan.default_amount; -} - -void CPInstrument::set_pan_default_enabled(bool p_enabled) { - - data.pan.use_default=p_enabled; -} -bool CPInstrument::is_pan_default_enabled() { - - return data.pan.use_default; - -} - -void CPInstrument::set_pan_pitch_separation(int8_t p_amount) { - - CP_ERR_COND(p_amount<-32); - CP_ERR_COND(p_amount>32); - data.pan.pitch_separation=p_amount; -} -int8_t CPInstrument::get_pan_pitch_separation() { - - return data.pan.pitch_separation; -} - -void CPInstrument::set_pan_pitch_center(uint8_t p_amount) { - - CP_ERR_COND(p_amount>=CPNote::NOTES); - data.pan.pitch_center=p_amount; -} -uint8_t CPInstrument::get_pan_pitch_center() { - - return data.pan.pitch_center; -} - -void CPInstrument::set_pan_random_variation(uint8_t p_amount) { - - CP_ERR_COND(p_amount>MAX_PAN_RANDOM); - data.pan.random_variation=p_amount; -} -uint8_t CPInstrument::get_pan_random_variation() { - - return data.pan.random_variation; -} - -/* Pitch / Filter */ - -void CPInstrument::set_pitch_use_as_filter(bool p_enabled) { - - data.pitch.use_as_filter=p_enabled; -} -bool CPInstrument::is_pitch_use_as_filter() { - - return data.pitch.use_as_filter; -} - -void CPInstrument::set_filter_use_default_cutoff(bool p_enabled) { - - data.pitch.use_default_cutoff=p_enabled; - -} -bool CPInstrument::filter_use_default_cutoff() { - - return data.pitch.use_default_cutoff; -} - -void CPInstrument::set_filter_default_cutoff(uint8_t p_amount) { - - CP_ERR_COND(p_amount>MAX_FILTER_CUTOFF); - data.pitch.default_cutoff=p_amount; -} -uint8_t CPInstrument::get_filter_default_cutoff() { - - return data.pitch.default_cutoff; -} - -void CPInstrument::set_filter_use_default_resonance(bool p_enabled) { - - data.pitch.use_default_resonance=p_enabled; -} -bool CPInstrument::filter_use_default_resonance() { - - return data.pitch.use_default_resonance; -} - -void CPInstrument::set_filter_default_resonance(uint8_t p_amount) { - - CP_ERR_COND(p_amount>MAX_FILTER_RESONANCE); - data.pitch.default_resonance=p_amount; - -} -uint8_t CPInstrument::get_filter_default_resonance() { - - return data.pitch.default_resonance; -} - -/* Envelopes */ - - -CPEnvelope* CPInstrument::get_volume_envelope() { - - return &data.volume.envelope; -} -CPEnvelope* CPInstrument::get_pan_envelope() { - - return &data.pan.envelope; -} -CPEnvelope* CPInstrument::get_pitch_filter_envelope() { - - return &data.pitch.envelope; - - -} - - -void CPInstrument::reset() { - - name[0]=0; - - data.NNA_type=NNA_NOTE_CUT; - data.DC_action=DCA_NOTE_CUT; - data.DC_type=DCT_DISABLED; - - for (int i=0;i -*/ -class CPLoader { - -public: - - enum Error { - FILE_OK, - FILE_UNRECOGNIZED, - FILE_CANNOT_OPEN, - FILE_CORRUPTED, - FILE_OUT_OF_MEMORY, - }; - - - virtual bool can_load_song()=0; - virtual bool can_load_sample()=0; - virtual bool can_load_instrument()=0; - - virtual Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset)=0; - virtual Error load_sample(const char *p_file,CPSample *p_sample)=0; - virtual Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx)=0; - - - virtual ~CPLoader() {} - -}; - -#endif diff --git a/drivers/chibi/cp_loader_it.cpp b/drivers/chibi/cp_loader_it.cpp deleted file mode 100644 index 20a3960a23..0000000000 --- a/drivers/chibi/cp_loader_it.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/*************************************************************************/ -/* cp_loader_it.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_loader_it.h" - -bool CPLoader_IT::can_load_song() { return true; } -bool CPLoader_IT::can_load_sample() { return true; } -bool CPLoader_IT::can_load_instrument() { return true; } - -CPLoader::Error CPLoader_IT::load_song(const char *p_file,CPSong *p_song, bool p_sampleset) { - - - song=p_song; - - if (file->open( p_file, CPFileAccessWrapper::READ )!=CPFileAccessWrapper::OK) - return CPLoader::FILE_CANNOT_OPEN; - - - Error err; - - char aux_identifier[4]; - file->get_byte_array((uint8_t*)aux_identifier,4); - - if ( aux_identifier[0]!='I' || - aux_identifier[1]!='M' || - aux_identifier[2]!='P' || - aux_identifier[3]!='M') { - - - CP_PRINTERR("IT CPLoader CPSong: Failed Identifier"); - return FILE_UNRECOGNIZED; - } - - - if (p_sampleset) { - - song->reset(false,true,true,false); - - if ((err=load_header(true))) { - file->close(); - return err; - } - - if ((err=load_samples())) { - file->close(); - return err; - } - - if ((err=load_instruments())) { - file->close(); - return err; - } - - return FILE_OK; - } - - song->reset(); - - if ((err=load_header(false))) { - file->close(); - return err; - } - - if ((err=load_orders())) { - file->close(); - return err; - } - - if ((err=load_patterns())) { - file->close(); - return err; - } - - if ((err=load_samples())) { - file->close(); - return err; - } - - if ((err=load_effects())) { - file->close(); - return err; - } - - if ((err=load_instruments())) { - file->close(); - return err; - } - - if ((err=load_message())) { - file->close(); - return err; - } - - file->close(); - return FILE_OK; - -} - - - - -CPLoader::Error CPLoader_IT::load_sample(const char *p_file,CPSample *p_sample) { - - if (file->open( p_file, CPFileAccessWrapper::READ )!=CPFileAccessWrapper::OK) - return CPLoader::FILE_CANNOT_OPEN; - - p_sample->reset(); - CPLoader::Error res=load_sample(p_sample); - - file->close(); - - return res; -} -CPLoader::Error CPLoader_IT::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { - - CP_FAIL_INDEX_V(p_instr_idx,CPSong::MAX_INSTRUMENTS,CPLoader::FILE_CANNOT_OPEN); - - if (file->open( p_file, CPFileAccessWrapper::READ )!=CPFileAccessWrapper::OK) - return CPLoader::FILE_CANNOT_OPEN; - - - p_song->get_instrument( p_instr_idx )->reset(); - - - int samples=0; - CPLoader::Error res=load_instrument( p_song->get_instrument( p_instr_idx ), &samples ); - - if (res) { - file->close(); - return res; - } - - - char exchange[CPSong::MAX_SAMPLES]; - for (int i=0;iseek( 554+i*80 ); //i think this should work?! seems to.. but i'm not sure - - /* find free sample */ - - int free_idx=-1; - for (int s=0;sget_sample( s )->get_sample_data().is_null()) { - free_idx=s; - break; - } - } - if (free_idx==-1) - break; //can't seem to be able to load more samples - - exchange[i]=free_idx; - res=load_sample( p_song->get_sample( free_idx ) ); - - if (res) { - - file->close(); - return res; - } - } - - for (int i=0;iget_instrument(p_instr_idx)->get_sample_number(i); - - if (smp>=CPSong::MAX_SAMPLES) - continue; - - if (smp<0) - continue; - - smp=exchange[smp]; - - song->get_instrument(p_instr_idx)->set_sample_number(i,smp); - - } - - file->close(); - - return res; - -} - -CPLoader_IT::CPLoader_IT(CPFileAccessWrapper *p_file) { - - file=p_file; - -} diff --git a/drivers/chibi/cp_loader_it.h b/drivers/chibi/cp_loader_it.h deleted file mode 100644 index 38a1cdd9c4..0000000000 --- a/drivers/chibi/cp_loader_it.h +++ /dev/null @@ -1,125 +0,0 @@ -/*************************************************************************/ -/* cp_loader_it.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_LOADER_IT_H -#define CP_LOADER_IT_H - -#include "cp_loader.h" -/** - *@author Juan Linietsky - */ - -/****************************** - loader_it.h - ---------- -Impulse Tracker Module CPLoader! -It lacks support for old -instrument files methinks... -and some other things like -midi. -********************************/ - -class AuxSampleData; //used for internal crap - -class CPLoader_IT : public CPLoader { - - - - CPFileAccessWrapper *file; - CPSong *song; - - struct IT_Header { - uint8_t blank01[2]; - uint16_t ordnum; - uint16_t insnum; - uint16_t smpnum; - uint16_t patnum; - uint16_t cwt; /* Created with tracker (y.xx = 0x0yxx) */ - uint16_t cmwt; /* Compatible with tracker ver > than val. */ - uint16_t flags; - uint16_t special; /* bit 0 set = song message attached */ - uint16_t msglength; - uint32_t msgoffset; - bool is_chibi; - }; - - /* Variables to store temp data */ - IT_Header header; - - /* CPSong Info Methods */ - Error load_header(bool p_dont_set); - Error load_orders(); - Error load_message(); - - /* CPPattern Methods */ - Error load_patterns(); - - /* CPSample Methods */ - - Error load_samples(); - Error load_sample(CPSample *p_sample); - CPSample_ID load_sample_data(AuxSampleData& p_sample_data); - - // CPSample decompression - - uint32_t read_n_bits_from_IT_compressed_block(uint8_t p_bits_to_read); - bool read_IT_compressed_block (bool p_16bits); - void free_IT_compressed_block (); - bool load_sample_8bits_IT_compressed(void *p_dest_buffer,int p_buffsize); - bool load_sample_16bits_IT_compressed(void *p_dest_buffer,int p_buffsize); - uint32_t *source_buffer; /* source buffer */ - uint32_t *source_position; /* actual reading position */ - uint8_t source_remaining_bits; /* bits remaining in read dword */ - uint8_t* pat_data; - - /* CPInstruments Methods */ - Error load_effects(); - Error load_instruments(); - Error load_instrument(CPInstrument *p_instrument,int *p_samples=0); - void load_envelope(CPEnvelope *p_envelope,bool*p_has_filter_flag=0); - - -public: - - - bool can_load_song(); - bool can_load_sample(); - bool can_load_instrument(); - - Error load_song(const char *p_file,CPSong *p_song, bool p_sampleset=false); - Error load_sample(const char *p_file,CPSample *p_sample); - Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx); - - CPLoader_IT(CPFileAccessWrapper *p_file); - -}; - - - -#endif diff --git a/drivers/chibi/cp_loader_it_info.cpp b/drivers/chibi/cp_loader_it_info.cpp deleted file mode 100644 index 0360f7f9a4..0000000000 --- a/drivers/chibi/cp_loader_it_info.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/*************************************************************************/ -/* cp_loader_it_info.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_loader_it.h" - - - -CPLoader::Error CPLoader_IT::load_header(bool p_dont_set) { - - - char aux_songname[26]; - - file->get_byte_array((uint8_t*)aux_songname,26); - if (!p_dont_set) - song->set_name( aux_songname ); - - uint8_t aux_hlmin=file->get_byte(); - uint8_t aux_hlmaj=file->get_byte(); - - if (aux_hlmin==0) aux_hlmin=4; - if (aux_hlmaj==0) aux_hlmaj=16; - - if (!p_dont_set) { - song->set_row_highlight_minor( aux_hlmin ); - song->set_row_highlight_major( aux_hlmaj ); - } - - header.ordnum=file->get_word(); - header.insnum=file->get_word(); - header.smpnum=file->get_word(); - header.patnum=file->get_word(); - - header.cwt=file->get_word(); /* Created with tracker (y.xx = 0x0yxx) */ - header.cmwt=file->get_word(); /* Compatible with tracker ver > than val. */ - header.flags=file->get_word(); - - if (!p_dont_set) { - song->set_stereo( header.flags & 1 ); - song->set_linear_slides( header.flags & 8 ); - song->set_old_effects( header.flags & 16 ); - song->set_compatible_gxx( header.flags & 32 ); - song->set_instruments( header.flags & 4 ); - } - - - header.special=file->get_word(); - if (!p_dont_set) { - - song->set_global_volume( file->get_byte() ); - song->set_mixing_volume( file->get_byte() ); - song->set_speed( file->get_byte() ); - song->set_tempo( file->get_byte() ); - song->set_stereo_separation( file->get_byte() ); - - } else { - - file->get_byte(); // skip - file->get_byte(); // skip - file->get_byte(); // skip - file->get_byte(); // skip - file->get_byte(); // skip - } - file->get_byte(); // ZERO Byte - header.msglength=file->get_word(); - header.msgoffset=file->get_dword(); - char chibi[4]; - file->get_byte_array((uint8_t*)chibi,4); - header.is_chibi=(chibi[0]=='C' && chibi[1]=='H' && chibi[2]=='B' && chibi[3]=='I'); - - for (int i=0;i<64;i++) { - - uint8_t panbyte=file->get_byte(); - - uint8_t pan_dst=(panbyte<65) ? panbyte : 32; - bool surround_dst=(panbyte==100); - bool mute_dst=(panbyte>=128); - - if (!p_dont_set) { - song->set_channel_pan( i, pan_dst ); - song->set_channel_surround( i, surround_dst ); - song->set_channel_mute( i, mute_dst ); - } - } - for (int i=0;i<64;i++) { - unsigned char cv = file->get_byte(); - if (!p_dont_set) - song->set_channel_volume( i, cv ); - } - - CP_ERR_COND_V( file->eof_reached(),FILE_CORRUPTED ); - CP_ERR_COND_V( file->get_error(),FILE_CORRUPTED ); - - return FILE_OK; -} - -CPLoader::Error CPLoader_IT::load_effects() { - - if (!header.is_chibi) - return FILE_OK; //no effects, regular IT file - - /* GOTO End of IT header */ - file->seek(0xC0+header.ordnum+header.insnum*4+header.smpnum*4+header.patnum*4); - - - if (file->get_byte()>0) //not made with this version, ignore extended info - return FILE_OK; - - /* Chibitracker Extended info */ - - switch(file->get_byte()) { - - case CPSong::REVERB_MODE_ROOM: { - - song->set_reverb_mode( CPSong::REVERB_MODE_ROOM ); - } break; - case CPSong::REVERB_MODE_STUDIO_SMALL: { - - song->set_reverb_mode( CPSong::REVERB_MODE_STUDIO_SMALL ); - - } break; - case CPSong::REVERB_MODE_STUDIO_MEDIUM: { - - song->set_reverb_mode( CPSong::REVERB_MODE_STUDIO_MEDIUM ); - - } break; - case CPSong::REVERB_MODE_STUDIO_LARGE: { - - song->set_reverb_mode( CPSong::REVERB_MODE_STUDIO_LARGE ); - - } break; - case CPSong::REVERB_MODE_HALL: { - - song->set_reverb_mode( CPSong::REVERB_MODE_HALL ); - - } break; - case CPSong::REVERB_MODE_SPACE_ECHO: { - - song->set_reverb_mode( CPSong::REVERB_MODE_SPACE_ECHO ); - - } break; - - case CPSong::REVERB_MODE_ECHO: { - - song->set_reverb_mode( CPSong::REVERB_MODE_ECHO ); - - } break; - case CPSong::REVERB_MODE_DELAY: { - - song->set_reverb_mode( CPSong::REVERB_MODE_DELAY ); - - } break; - case CPSong::REVERB_MODE_HALF_ECHO: { - - song->set_reverb_mode( CPSong::REVERB_MODE_HALF_ECHO ); - - } break; - - } - - //chorus - song->set_chorus_speed_hz10( file->get_byte() ); - song->set_chorus_delay_ms( file->get_byte() ); - song->set_chorus_depth_ms10( file->get_byte() ); - song->set_chorus_separation_ms( file->get_byte() ); - - for (int i=0;iset_channel_reverb(i,file->get_byte()); - } - for (int i=0;iset_channel_chorus(i,file->get_byte()); - } - - return FILE_OK; - -} - -CPLoader::Error CPLoader_IT::load_message() { - - - if (!(header.special & 1)) { - - return FILE_OK; - } - - - file->seek(header.msgoffset); - - //(void*)tmpmsg=malloc(header.msglength+1); - - char message[8000]; - - - char *tmpmsg = message; - - file->get_byte_array((uint8_t*)tmpmsg,header.msglength); - tmpmsg[header.msglength]=0; - - for (int i=0;iset_message(tmpmsg); - - return FILE_OK; -} - -CPLoader::Error CPLoader_IT::load_orders() { - - file->seek(0xC0); - - - for (int i=0;iget_byte(); - CPOrder order=CP_ORDER_NONE; - - - if (i>=CPSong::MAX_ORDERS) - continue; - if (aux_order==254) { - - order=CP_ORDER_BREAK; - - } else if (aux_order<200) { - - order=aux_order; - //nothing! - - } - song->set_order(i,order); - - } - - if (file->eof_reached() || file->get_error()) { - - - return FILE_CORRUPTED; - - } - - return FILE_OK; -} - - - diff --git a/drivers/chibi/cp_loader_it_instruments.cpp b/drivers/chibi/cp_loader_it_instruments.cpp deleted file mode 100644 index ccb24bd81c..0000000000 --- a/drivers/chibi/cp_loader_it_instruments.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/*************************************************************************/ -/* cp_loader_it_instruments.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_loader_it.h" - -enum EnvFlags { - ENV_ON=1, - ENV_LOOP=2, - ENV_SUSLOOP=4, - ENV_CARRY=8, - ENV_FILTER=128 -}; - -void CPLoader_IT::load_envelope(CPEnvelope *p_envelope,bool*p_has_filter_flag) { - - uint8_t flags=file->get_byte(); - uint8_t points=file->get_byte(); - uint8_t begin=file->get_byte(); - uint8_t end=file->get_byte(); - uint8_t susbegin=file->get_byte(); - uint8_t susend=file->get_byte(); - - p_envelope->reset(); - - for (int i=0;i<25;i++) { - - uint8_t height=file->get_byte(); - int8_t &signed_height=(int8_t&)height; - uint16_t tick=file->get_word(); - - if (i>=points) - continue; - p_envelope->add_position( tick, signed_height ); - - } - - p_envelope->set_enabled( flags & ENV_ON ); - p_envelope->set_carry_enabled( flags & ENV_CARRY); - - p_envelope->set_loop_enabled( flags & ENV_LOOP ); - p_envelope->set_loop_begin( begin ); - p_envelope->set_loop_end( end ); - - p_envelope->set_sustain_loop_enabled( flags & ENV_SUSLOOP ); - p_envelope->set_sustain_loop_begin( susbegin ); - p_envelope->set_sustain_loop_end( susend ); - - if (p_has_filter_flag) - *p_has_filter_flag=flags&ENV_FILTER; - - file->get_byte(); //zerobyte - - //fill with stuff if the envelope hass less than 2 points - while(p_envelope->get_node_count()<2) { - - p_envelope->add_position( 30*p_envelope->get_node_count(), p_envelope->get_min()==0 ? 64 : 0, false ); - } -} - - -CPLoader::Error CPLoader_IT::load_instrument(CPInstrument *p_instrument,int *p_samples) { - - - - char aux_header[4]; - - file->get_byte_array((uint8_t*)aux_header,4); - - - if ( aux_header[0]!='I' || - aux_header[1]!='M' || - aux_header[2]!='P' || - aux_header[3]!='I') { - CP_PRINTERR("IT CPLoader CPInstrument: Failed Identifier"); - - return FILE_UNRECOGNIZED; - } - - - - // Ignore deprecated 8.3 filename field - for (int i=0;i<12;i++) file->get_byte(); - - //Ignore zerobyte - file->get_byte(); /* (byte) CPInstrument type (always 0) */ - - switch( file->get_byte() ) { /* New CPNote Action [0,1,2,3] */ - case 0: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_CUT ) ; break; - case 1: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_CONTINUE ) ; break; - case 2: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_OFF ) ; break; - case 3: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_FADE ) ; break; - }; - switch( file->get_byte() ) { // Duplicate Check Type - case 0: p_instrument->set_DC_type( CPInstrument::DCT_DISABLED ); break ; - case 1: p_instrument->set_DC_type( CPInstrument::DCT_NOTE ); break ; - case 2: p_instrument->set_DC_type( CPInstrument::DCT_SAMPLE ); break ; - case 3: p_instrument->set_DC_type( CPInstrument::DCT_INSTRUMENT ); break ; - } - switch( file->get_byte() ) { //Duplicate Check Action - case 0: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_CUT ); break ; - case 1: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_OFF ); break ; - case 2: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_FADE ); break ; - } - - int fade = file->get_word(); - //intf("AFADE: %i\n",fade); - if (fade>CPInstrument::MAX_FADEOUT) //needs to be clipped because of horrible modplug doings - fade=CPInstrument::MAX_FADEOUT; - - p_instrument->set_volume_fadeout( fade ); - p_instrument->set_pan_pitch_separation( file->get_byte() ); - p_instrument->set_pan_pitch_center( file->get_byte() ); - p_instrument->set_volume_global_amount( file->get_byte() ); - uint8_t pan=file->get_byte(); - p_instrument->set_pan_default_amount(pan&0x7F); - p_instrument->set_pan_default_enabled( !(pan&0x80) ); - p_instrument->set_volume_random_variation( file->get_byte() ); - p_instrument->set_pan_random_variation( file->get_byte() ); - - - - file->get_word(); //empty (version) - uint8_t samples=file->get_byte(); - if (p_samples) - *p_samples=samples; - file->get_byte(); //empty - char aux_name[26]; - file->get_byte_array((uint8_t*)aux_name,26); - p_instrument->set_name(aux_name); - - uint8_t cutoff=file->get_byte(); - - p_instrument->set_filter_default_cutoff(cutoff&0x7F); - p_instrument->set_filter_use_default_cutoff(cutoff&0x80); - - uint8_t resonance=file->get_byte(); - - p_instrument->set_filter_default_resonance(resonance&0x7F); - p_instrument->set_filter_use_default_resonance(resonance&0x80); - - file->get_dword(); //MIDI, IGNORED! - - /* CPNote -> CPSample table */ - for (uint8_t i=0;iget_byte(); - if (note>=CPNote::NOTES) - note=0; - p_instrument->set_note_number(i,note); - - uint8_t samp=file->get_byte(); - if (samp==0 || samp>99) - samp=CPNote::EMPTY; - else - samp--; - - - p_instrument->set_sample_number(i,samp); - - - } - - - load_envelope( p_instrument->get_volume_envelope() ); - load_envelope( p_instrument->get_pan_envelope() ); - bool use_as_filter; - load_envelope( p_instrument->get_pitch_filter_envelope(), &use_as_filter ); - p_instrument->set_pitch_use_as_filter( use_as_filter ); - - return FILE_OK; - -} - - -CPLoader::Error CPLoader_IT::load_instruments() { - - - for (int i=0;iseek(0xC0+header.ordnum+i*4); - uint32_t final_location=file->get_dword(); - file->seek( final_location ); - - Error err=load_instrument( song->get_instrument( i ) ); - if (err) - return err; - - } - - return FILE_OK; - - if (file->eof_reached() || file->get_error()) - return FILE_CORRUPTED; -} - - diff --git a/drivers/chibi/cp_loader_it_patterns.cpp b/drivers/chibi/cp_loader_it_patterns.cpp deleted file mode 100644 index d951a91620..0000000000 --- a/drivers/chibi/cp_loader_it_patterns.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/*************************************************************************/ -/* cp_loader_it_patterns.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_loader_it.h" - - -CPLoader::Error CPLoader_IT::load_patterns() { - - - for (int i=0;i=CPSong::MAX_PATTERNS) - break; - - /* Position where pattern offsets are stored */ - file->seek(0xC0+header.ordnum+header.insnum*4+header.smpnum*4+i*4); - uint32_t pattern_offset=file->get_dword(); - - if (pattern_offset==0) { - - continue; - } - - uint16_t pat_size; - uint16_t pat_length; - - int row=0,flag,channel,j; - uint8_t aux_byte; - uint32_t reserved; - uint8_t chan_mask[64]; //mask cache for each - CPNote last_value[64]; //last value of each - - for (j=0;j<64;j++) { - - chan_mask[j]=0; - last_value[j].clear(); - } - - file->seek(pattern_offset); - - pat_size=file->get_word(); - pat_length=file->get_word(); - reserved=file->get_dword(); - - song->get_pattern(i)->set_length( pat_length ); - - do { - - aux_byte=file->get_byte(); - flag=aux_byte; - - if ( flag==0 ) { - - row++; - } else { - - channel=(flag-1) & 63; - - if ( flag & 128 ) { - - aux_byte=file->get_byte(); - chan_mask[channel]=aux_byte; - } - - CPNote note; //note used for reading - - if ( chan_mask[channel]&1 ) { // read note - - aux_byte=file->get_byte(); - - if ( aux_byte<120 ) - note.note=aux_byte; - else if ( aux_byte==255 ) - note.note=CPNote::OFF; - else if ( aux_byte==254 ) - note.note=CPNote::CUT; - - last_value[channel].note=note.note; - } - - - if ( chan_mask[channel]&2 ) { - - aux_byte=file->get_byte(); - if ( aux_byte<100 ) - note.instrument=aux_byte-1; - - last_value[channel].instrument=note.instrument; - } - if ( chan_mask[channel]&4 ) { - - aux_byte=file->get_byte(); - if ( aux_byte<213 ) - note.volume=aux_byte; - - last_value[channel].volume=note.volume; - } - if ( chan_mask[channel]&8 ) { - - aux_byte=file->get_byte(); - if ( aux_byte>0 ) - note.command=aux_byte-1; - - - last_value[channel].command=note.command; - - note.parameter=file->get_byte(); - - last_value[channel].parameter=note.parameter; - } - - if ( chan_mask[channel]&16 ) { - - note.note=last_value[channel].note; - } - - if ( chan_mask[channel]&32 ) { - - note.instrument=last_value[channel].instrument; - } - if ( chan_mask[channel]&64 ) { - - note.volume=last_value[channel].volume; - } - if ( chan_mask[channel]&128 ) { - - note.command=last_value[channel].command; - note.parameter=last_value[channel].parameter; - } - - song->get_pattern(i)->set_note(channel,row,note); - } - - - } while(rowget_byte_array((uint8_t*)aux_header,4); - - if ( aux_header[0]!='I' || - aux_header[1]!='M' || - aux_header[2]!='P' || - aux_header[3]!='S') { - - //CP_PRINTERR("IT CPLoader CPSample: Failed Identifier"); - return FILE_UNRECOGNIZED; - } - - - // Ignore deprecated 8.3 filename - for (int i=0;i<12;i++) file->get_byte(); - - file->get_byte(); //ignore zerobyte - - p_sample->set_global_volume( file->get_byte() ); - - /* SAMPLE FLAGS */ - uint8_t flags=file->get_byte(); - aux_sample_data.loop_enabled=flags&IT_SAMPLE_LOOPED; - aux_sample_data.pingpong_enabled=flags&IT_SAMPLE_LOOP_IS_PINGPONG; - aux_sample_data.is16bit=flags&IT_SAMPLE_16BITS; - aux_sample_data.exists=flags&IT_SAMPLE_EXISTS; - aux_sample_data.stereo=flags&IT_SAMPLE_STEREO; - aux_sample_data.compressed=flags&IT_SAMPLE_COMPRESSED; - - p_sample->set_default_volume(file->get_byte()); - /* SAMPLE NAME */ - char aux_name[26]; - file->get_byte_array((uint8_t*)aux_name,26); - p_sample->set_name(aux_name); - - // ?? - uint8_t convert_flag=file->get_byte(); - // PAN - uint8_t pan=file->get_byte(); - p_sample->set_pan( pan&0x7F ); - p_sample->set_pan_enabled( pan & 0x80 ); - - aux_sample_data.length=file->get_dword(); - - - aux_sample_data.loop_begin= file->get_dword(); - aux_sample_data.loop_end= file->get_dword(); - aux_sample_data.c5spd=file->get_dword(); - /*p_sample->data.set_sustain_loop_begin=*/file->get_dword(); - /*p_sample->data.sustain_loop_end=*/file->get_dword(); - aux_sample_data.fileofs=file->get_dword(); - p_sample->set_vibrato_speed( file->get_byte() ); - p_sample->set_vibrato_depth( file->get_byte() ); - p_sample->set_vibrato_rate( file->get_byte() ); - switch( file->get_byte() ) { - /* Vibrato Wave: 0=sine, 1=rampdown, 2=square, 3=random */ - case 0: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break; - case 1: p_sample->set_vibrato_type( CPSample::VIBRATO_SAW ); break; - case 2: p_sample->set_vibrato_type( CPSample::VIBRATO_SQUARE ); break; - case 3: p_sample->set_vibrato_type( CPSample::VIBRATO_RANDOM ); break; - default: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break; - } - - //printf("Name %s - Flags: fileofs :%i - c5spd %i - len %i 16b %i - data?: %i\n",p_sample->get_name(),aux_sample_data.fileofs,aux_sample_data.c5spd, aux_sample_data.length, aux_sample_data.is16bit,aux_sample_data.exists); - CPSample_ID samp_id; - - if (aux_sample_data.exists) { - samp_id=load_sample_data(aux_sample_data); - CPSampleManager::get_singleton()->set_c5_freq(samp_id,aux_sample_data.c5spd); - CPSampleManager::get_singleton()->set_loop_begin( samp_id,aux_sample_data.loop_begin ); - CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end ); - CPSample_Loop_Type loop_type=aux_sample_data.loop_enabled?( aux_sample_data.pingpong_enabled? CP_LOOP_BIDI: CP_LOOP_FORWARD):CP_LOOP_NONE; - CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end ); - CPSampleManager::get_singleton()->set_loop_type( samp_id, loop_type); - - } - - //printf("Loaded id is null?: %i\n",samp_id.is_null()); - p_sample->set_sample_data(samp_id); - if (!samp_id.is_null()) { - - // printf("Loaded ID: stereo: %i len %i 16bit %i\n",CPSampleManager::get_singleton()->is_stereo(samp_id), CPSampleManager::get_singleton()->get_size( samp_id), CPSampleManager::get_singleton()->is_16bits( samp_id) ); - } - - CP_ERR_COND_V( file->eof_reached(),FILE_CORRUPTED ); - CP_ERR_COND_V( file->get_error(),FILE_CORRUPTED ); - - return FILE_OK; - -} - -CPSample_ID CPLoader_IT::load_sample_data(AuxSampleData& p_sample_data) { - - - int aux_sample_properties = (p_sample_data.is16bit?IT_SAMPLE_16BITS:0)|(p_sample_data.compressed?IT_SAMPLE_COMPRESSED:0)|(p_sample_data.stereo?IT_SAMPLE_STEREO:0); - - file->seek(p_sample_data.fileofs); - - CPSampleManager *sm=CPSampleManager::get_singleton(); - - CPSample_ID id; - - switch (aux_sample_properties) { - - case (0): // 8 bits, mono - case (IT_SAMPLE_16BITS): // 16 bits mono - case (IT_SAMPLE_STEREO): // 8 bits stereo - case (IT_SAMPLE_16BITS|IT_SAMPLE_STEREO): { // 16 bits mono - - id=sm->create(p_sample_data.is16bit,p_sample_data.stereo,p_sample_data.length); - if (id.is_null()) - break; - - sm->lock_data(id); - - int16_t *ptr16 = (int16_t*)sm->get_data(id); - int8_t *ptr8=(int8_t*)ptr16; - - int chans=p_sample_data.stereo?2:1; - - if (p_sample_data.is16bit) { - - for (int c=0;cget_word(); - } - } - } else { - - for (int c=0;cget_byte(); - } - } - - } - - sm->unlock_data(id); - - } break; - case (IT_SAMPLE_COMPRESSED): { // 8 bits compressed - - - id=sm->create(false,false,p_sample_data.length); - if (id.is_null()) - break; - sm->lock_data(id); - - if ( load_sample_8bits_IT_compressed((void*)sm->get_data( id),p_sample_data.length) ) { - - sm->unlock_data(id); - sm->destroy(id); - - break; - } - - sm->unlock_data(id); - - - } break; - case (IT_SAMPLE_16BITS|IT_SAMPLE_COMPRESSED): { // 16 bits compressed - - - id=sm->create(true,false,p_sample_data.length); - if (id.is_null()) - break; - sm->lock_data(id); - - if ( load_sample_16bits_IT_compressed((void*)sm->get_data(id),p_sample_data.length) ) { - - sm->unlock_data(id); - sm->destroy(id); - break; - } - - sm->unlock_data(id); - - } break; - default: { - - // I dont know how to handle stereo compressed, does that exist? - } break; - - } - - - return id; -} - - -CPLoader::Error CPLoader_IT::load_samples() { - - for (int i=0;iseek(0xC0+header.ordnum+header.insnum*4+i*4); - - uint32_t final_location=file->get_dword(); - file->seek( final_location ); - - - Error err=load_sample(song->get_sample(i)); - CP_ERR_COND_V(err,err); - - } - - if (file->eof_reached() || file->get_error()) - return FILE_CORRUPTED; - - return FILE_OK; -} -/* * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE - - -The following sample decompression code is based on xmp's code.(http://xmp.helllabs.org) which is based in openCP code. - -* NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE */ - -uint32_t CPLoader_IT::read_n_bits_from_IT_compressed_block (uint8_t p_bits_to_read) { - - uint32_t aux_return_value; - uint32_t val; - - uint8_t *buffer=(uint8_t*)source_position; - if ( p_bits_to_read <= source_remaining_bits ) { - - val=buffer[3]; - val<<=8; - val|=buffer[2]; - val<<=8; - val|=buffer[1]; - val<<=8; - val|=buffer[0]; - - aux_return_value = val & ((1 << p_bits_to_read) - 1); - val >>= p_bits_to_read; - source_remaining_bits -= p_bits_to_read; - - buffer[3]=val>>24; - buffer[2]=(val>>16)&0xFF; - buffer[1]=(val>>8)&0xFF; - buffer[0]=(val)&0xFF; - - } else { - aux_return_value=buffer[3]; - aux_return_value<<=8; - aux_return_value|=buffer[2]; - aux_return_value<<=8; - aux_return_value|=buffer[1]; - aux_return_value<<=8; - aux_return_value|=buffer[0]; - - uint32_t nbits = p_bits_to_read - source_remaining_bits; - source_position++; - - buffer+=4; - val=buffer[3]; - val<<=8; - val|=buffer[2]; - val<<=8; - val|=buffer[1]; - val<<=8; - val|=buffer[0]; - aux_return_value |= ((val & ((1 << nbits) - 1)) << source_remaining_bits); - val >>= nbits; - source_remaining_bits = 32 - nbits; - buffer[3]=val>>24; - buffer[2]=(val>>16)&0xFF; - buffer[1]=(val>>8)&0xFF; - buffer[0]=(val)&0xFF; - - } - - return aux_return_value; -} - -bool CPLoader_IT::read_IT_compressed_block (bool p_16bits) { - - uint16_t size; - - size=file->get_word(); - - if (file->eof_reached() || file->get_error()) return true; - - pat_data = (uint8_t*)CP_ALLOC( 4* ((size >> 2) + 2) ); - if (!pat_data) - return true; - - - source_buffer=(uint32_t*)pat_data; - file->get_byte_array((uint8_t*)source_buffer,size); - - if (file->eof_reached() || file->get_error()) { - - free_IT_compressed_block(); - return true; - } - - source_position = source_buffer; - source_remaining_bits = 32; - - return false; -} - -void CPLoader_IT::free_IT_compressed_block () { - - - if (pat_data) { - CP_FREE(pat_data); - pat_data=NULL; - } - -} - -bool CPLoader_IT::load_sample_8bits_IT_compressed(void *p_dest_buffer,int p_buffsize) { - - int8_t *dest_buffer; /* destination buffer which will be returned */ - uint16_t block_length; /* length of compressed data block in samples */ - uint16_t block_position; /* position in block */ - uint8_t bit_width; /* actual "bit width" */ - uint16_t aux_value; /* value read from file to be processed */ - int8_t d1, d2; /* integrator buffers (d2 for it2.15) */ - int8_t *dest_position; /* position in output buffer */ - int8_t v; /* sample value */ - bool it215; // is this an it215 module? - - dest_buffer = (int8_t *) p_dest_buffer; - - if (dest_buffer==NULL) - return true; - - for (int i=0;i read new width; */ - bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; - /* and expand it */ - continue; /* ... next value */ - } - - } else if ( bit_width < 9 ) { /* method 2 (7-8 bits) */ - - uint8_t border = (0xFF >> (9 - bit_width)) - 4; - /* lower border for width chg */ - - if ( aux_value > border && aux_value <= (border + 8) ) { - - aux_value -= border; /* convert width to 1-8 */ - bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; - /* and expand it */ - continue; /* ... next value */ - } - - - } else if ( bit_width == 9 ) { /* method 3 (9 bits) */ - - if ( aux_value & 0x100 ) { /* bit 8 set? */ - - bit_width = (aux_value + 1) & 0xff; /* new width... */ - continue; /* ... and next value */ - } - - } else { /* illegal width, abort */ - - - free_IT_compressed_block(); - CP_PRINTERR("CPSample has illegal BitWidth "); - return true; - } - - /* now expand value to signed byte */ - if ( bit_width < 8 ) { - - uint8_t tmp_shift = 8 - bit_width; - - v=(aux_value << tmp_shift); - v>>=tmp_shift; - - } else v = (int8_t) aux_value; - - /* integrate upon the sample values */ - d1 += v; - d2 += d1; - - /* ... and store it into the buffer */ - *(dest_position++) = it215 ? d2 : d1; - block_position++; - - } - - /* now subtract block lenght from total length and go on */ - free_IT_compressed_block(); - p_buffsize -= block_length; - } - - - return false; -} - -bool CPLoader_IT::load_sample_16bits_IT_compressed(void *p_dest_buffer,int p_buffsize) { - - int16_t *dest_buffer; /* destination buffer which will be returned */ - uint16_t block_length; /* length of compressed data block in samples */ - uint16_t block_position; /* position in block */ - uint8_t bit_width; /* actual "bit width" */ - uint32_t aux_value; /* value read from file to be processed */ - int16_t d1, d2; /* integrator buffers (d2 for it2.15) */ - int16_t *dest_position; /* position in output buffer */ - int16_t v; /* sample value */ - - bool it215; // is this an it215 module? - - dest_buffer = (int16_t *) p_dest_buffer; - - if (dest_buffer==NULL) - return true; - - for (int i=0;i read new width; */ - bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; - /* and expand it */ - continue; /* ... next value */ - } - - } else if ( bit_width < 17 ) { - - uint16_t border = (0xFFFF >> (17 - bit_width)) - 8; - - if ( (int)aux_value > (int)border && (int)aux_value <= ((int)border + 16) ) { - - aux_value -= border; /* convert width to 1-8 */ - bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; - /* and expand it */ - continue; /* ... next value */ - } - - - } else if ( bit_width == 17 ) { - - if ( aux_value & 0x10000 ) { /* bit 8 set? */ - - bit_width = (aux_value + 1) & 0xff; /* new width... */ - continue; /* ... and next value */ - } - - } else { /* illegal width, abort */ - - CP_PRINTERR("CPSample has illegal BitWidth "); - - free_IT_compressed_block(); - - return true; - } - - /* now expand value to signed byte */ - if ( bit_width < 16 ) { - - uint8_t tmp_shift = 16 - bit_width; - - v=(aux_value << tmp_shift); - v>>=tmp_shift; - - } else v = (int16_t) aux_value; - - /* integrate upon the sample values */ - d1 += v; - d2 += d1; - - /* ... and store it into the buffer */ - *(dest_position++) = it215 ? d2 : d1; - block_position++; - - } - - /* now subtract block lenght from total length and go on */ - free_IT_compressed_block(); - p_buffsize -= block_length; - } - - - return false; - -} - - - diff --git a/drivers/chibi/cp_loader_mod.cpp b/drivers/chibi/cp_loader_mod.cpp deleted file mode 100644 index f867b77914..0000000000 --- a/drivers/chibi/cp_loader_mod.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/*************************************************************************/ -/* cp_loader_mod.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_loader_mod.h" - - -static bool tag_equal_to(const char *p_tag, const char *p_string) { - - return( p_tag[0]==p_string[0] && - p_tag[1]==p_string[1] && - p_tag[2]==p_string[2] && - p_tag[3]==p_string[3]); -} -/* ProTracker period table */ -uint16_t period_table[6*12] = { - 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907, - 856,808,762,720,678,640,604,570,538,508,480,453, - 428,404,381,360,339,320,302,285,269,254,240,226, - 214,202,190,180,170,160,151,143,135,127,120,113, - 107,101,95,90,85,80,75,71,67,63,60,56, - 53,50,47,45,42,40,37,35,33,31,30,28 -}; - - -CPLoader::Error CPLoader_MOD::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) { - - if (file->open(p_file,CPFileAccessWrapper::READ)) { - //printf("Can't open file! %s\n",p_file); - return FILE_CANNOT_OPEN; - }; - - /* FIRST OF ALL, one needs to read the .mod file format tag */ - file->seek( 1080 ); //located at 1080 - - char format_tag[4]; - - file->get_byte_array( (uint8_t*)format_tag, 4 ); - - int channels=-1; - - /** THE PAIN!! - COMPARE TAGS */ - - /* Classic 4-chan */ - if (tag_equal_to(format_tag,"M.K.") ) - channels=4; - if (tag_equal_to(format_tag,"FLT4") ) - channels=4; - if (tag_equal_to(format_tag,"M!K!") ) - channels=4; - - /* 8 Channel MODS */ - - if (tag_equal_to(format_tag,"FLT8") ) - channels=2; - - if (tag_equal_to(format_tag,"CD81") ) - channels=2; - - /* Custom channel MODS */ - - for (int i=1;i<=32;i++) { - - if (i<10) { // up to 9 channels mods - - /* Old Take Tracker */ - char old_take_tracker[4]={'T','D','Z',char('0'+i)}; - - if (tag_equal_to(format_tag,old_take_tracker)) { - - channels=i; - break; - } - - /* Contemplates many XCHN Formats */ - char xchn[4]={char('0'+i),'C','H','N'}; - - if (tag_equal_to(format_tag,xchn)) { - - channels=i; - break; - } - } - - /* Fast Tracker */ - char fast_tracker[4]={char('0'+(i/10)),char('0'+(i%10)),'C','H'}; - - if (tag_equal_to(format_tag,fast_tracker)) { - - channels=i; - break; - } - - } - - - if (channels==-1) { - - file->close(); - return FILE_UNRECOGNIZED; - } - - - - /** Load CPSong INFO */ - - file->seek( 0 ); //go to begining of file - - file->set_endian_conversion( true ); - p_song->reset(); - p_song->set_instruments( false ); - - char name[21]; - - file->get_byte_array( (uint8_t*)name,20); - name[20]=0; - - p_song->set_name(name); - p_song->set_old_effects( true ); - p_song->set_linear_slides( false ); - p_song->set_compatible_gxx( true ); - - - - CPSampleManager *sm=CPSampleManager::get_singleton(); - - int instruments=31; - - for (int i=0;iget_byte_array( (uint8_t*)sample_name,22); - sample_name[22]=0; - - uint32_t sample_len=file->get_word(); - sample_len<<=1; - - uint8_t fine_nibble=file->get_byte()&0xF; - - - //(int8_t)(fine_nibble & 7) - (int8_t)(fine_nibble & 8); //yesso's genius trick - // boo, I can't use it :( but i leave it here because of how cool it is - uint8_t linear_volume=file->get_byte(); //0 .. ? - - uint32_t loop_begin=file->get_word(); //0 .. ? - loop_begin<<=1; - uint32_t loop_end=file->get_word(); //0 .. ? - loop_end<<=1; - - if (sample_len>0) { - - CPSample_ID sid=sm->create( false, false, sample_len ); - - if (sid.is_null()) { - - file->close(); - return FILE_OUT_OF_MEMORY; - } - - if (loop_end>2) { - sm->set_loop_begin( sid, loop_begin ); - sm->set_loop_end( sid, loop_end+loop_begin ); - sm->set_loop_type( sid,CP_LOOP_FORWARD ); - } - static const uint16_t fine_to_freq[16]={ - 8363,8413,8463,8529,8581,8651,8723,8757, - 7895,7941,7985,8046,8107,8169,8232,8280 - }; - - sm->set_c5_freq( sid, fine_to_freq[fine_nibble] ); - p_song->get_sample(i)->set_sample_data(sid); - } - - p_song->get_sample(i)->set_name(sample_name); - p_song->get_sample(i)->set_default_volume( linear_volume ); - - - - } - - /* pan for MODs */ - for (int i=0;iset_channel_pan( i, (((i&3)==1) || ((i&3)==2)) ? 0: 64); - - - uint8_t order_count=file->get_byte(); -// uint8_t loop_to=file->get_byte(); - - - int pattern_count=0; - - for (int i=0;i<128;i++) { - - uint8_t order=file->get_byte(); - - - if (iset_order(i,order); - - /* Determine the amount of patterns */ - if ((order+1)>pattern_count) - pattern_count=order+1; - } else - p_song->set_order( i, CP_ORDER_NONE ); - } - - if (instruments==31) - file->get_dword(); // identiefier, now skip it - - for (int i=0;iget_dword(); - - CPNote note; - - note.instrument=(note_w>>12)&0xF; - note.instrument|=(note_w>>24)&0xF0; - - if (note.instrument==0) - note.instrument=CPNote::EMPTY; - else - note.instrument--; - - note.parameter=note_w&0xFF; - - int cmd=(note_w>>8)&0xF; - - uint32_t period=(note_w>>16)&0xFFF; - - if (period>0 && period<0xFFF) { - - //period>>=2; - //period<<=1; - for (int n=0; n<6*12; n++) { - - if (period >= period_table[n]) { - - if ((period!=period_table[n]) && (n)) - { - uint32_t p1 = period_table[n-1]; - uint32_t p2 = period_table[n]; - if (p1 - period < (period - p2)) { - - note.note=n+36; - break; - } - } - note.note=n+1+36; - break; - } - } - if (note.note==CPNote::EMPTY) - note.note=6*12+36; - - note.note--; - } - - - switch(cmd) { - - case 0x0: { - - if (note.parameter>0) - note.command='J'-'A'; - } break; - case 0x1: { - note.command='F'-'A'; - } break; - case 0x2: { - - note.command='E'-'A'; - } break; - case 0x3: { - - note.command='G'-'A'; - } break; - case 0x4: { - - note.command='H'-'A'; - } break; - case 0x5: { - note.command='L'-'A'; - } break; - case 0x6: { - - note.command='K'-'A'; - } break; - case 0x7: { - note.command='R'-'A'; - } break; - case 0x8: { - - note.command='X'-'A'; - } break; - case 0x9: { - - note.command='O'-'A'; - - } break; - case 0xA: { - - note.command='D'-'A'; - - } break; - case 0xB: { - - note.command='B'-'A'; - - } break; - case 0xC: { - - note.volume=note.parameter; - if (note.volume>64) - note.volume=64; - note.parameter=0; - - } break; - case 0xD: { - - note.command='C'-'A'; - note.parameter=(note.parameter>>4)*10 + (note.parameter&0xF); - - } break; - case 0xE: { //SPECIAL EFFECT! - - note.command='S'-'A'; - - switch(note.parameter>>4) { - - case 0x1: { - - note.command='F'-'A'; - note.parameter=0xF0|(note.parameter&0xF); - } break; - case 0x2: { - - note.command='E'-'A'; - note.parameter=0xF0|(note.parameter&0xF); - } break; - case 0x4: { - - note.command='S'-'A'; - note.parameter=0x30|(note.parameter&0x3); - - } break; - case 0x6: { - - note.command='S'-'A'; - note.parameter=0xB0|(note.parameter&0xF); - - } break; - case 0x7: { - note.command='S'-'A'; - note.parameter=0x40|(note.parameter&0x3); - - } break; - case 0x8: { - - note.command='S'-'A'; // wow, it's the same! - - } break; - case 0x9: { - note.command='Q'-'A'; - note.parameter=(note.parameter&0xF); - - } break; - case 0xA: { - - note.command='D'-'A'; - note.parameter=0xF|((note.parameter&0xF)<<4); - - } break; - case 0xB: { - note.command='D'-'A'; - note.parameter=0xF0|(note.parameter&0xF); - - } break; - case 0xC: - case 0xD: { - - note.command='S'-'A'; //wow, they are the same! - - } break; - case 0xE: { - note.command='S'-'A'; - note.parameter=0x60|(note.parameter&0xF); - - } break; - - default: { - - note.command=CPNote::EMPTY; - note.parameter=0; - } break; - - } - } break; - case 0xF: { - - if (note.parameter<32) - note.command='A'-'A'; - else - note.command='T'-'A'; - - } break; - } - - p_song->get_pattern(i)->set_note( column,line, note ); - } - } - } - - - - for (int i=0;iget_sample(i)->get_sample_data(); - if (sid.is_null()) { - continue; //empty sample, not stored? - } - sm->lock_data(sid); - uint8_t *dataptr = (uint8_t*)sm->get_data(sid); - - int len=sm->get_size(sid); - for (int s=0;sget_byte(); - //d-=128; //convert to signed - int8_t*ds=(int8_t*)&d; - dataptr[s]=*ds; - - } - sm->unlock_data(sid); - } - - file->close(); - - return FILE_OK; - - -} - - -CPLoader_MOD::CPLoader_MOD(CPFileAccessWrapper *p_file) { - - file=p_file; -} - - -CPLoader_MOD::~CPLoader_MOD() -{ -} - - diff --git a/drivers/chibi/cp_loader_mod.h b/drivers/chibi/cp_loader_mod.h deleted file mode 100644 index 636f4f00f2..0000000000 --- a/drivers/chibi/cp_loader_mod.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* cp_loader_mod.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_LOADER_MOD_H -#define CP_LOADER_MOD_H -#include "cp_loader.h" -/** - @author Juan Linietsky -*/ -class CPLoader_MOD : public CPLoader { - - CPFileAccessWrapper *file; -public: - - bool can_load_song() { return true; } - bool can_load_sample() { return false; } - bool can_load_instrument() { return false; } - - Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset); - Error load_sample(const char *p_file,CPSample *p_sample) { return FILE_UNRECOGNIZED; } - Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { return FILE_UNRECOGNIZED; } - - CPLoader_MOD(CPFileAccessWrapper *p_file); - ~CPLoader_MOD(); -}; - -#endif diff --git a/drivers/chibi/cp_loader_s3m.cpp b/drivers/chibi/cp_loader_s3m.cpp deleted file mode 100644 index 0fc15c1e2f..0000000000 --- a/drivers/chibi/cp_loader_s3m.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/*************************************************************************/ -/* cp_loader_s3m.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_loader_s3m.h" - -#define BITBOOL(m_exp) ((m_exp)?1:0) - - -CPLoader::Error CPLoader_S3M::load_header() { - - int i; - - - file->get_byte_array((uint8_t*)header.songname,28); - header.t1a=file->get_byte(); - header.type=file->get_byte(); - file->get_byte_array((uint8_t*)header.unused1,2); - header.ordnum=file->get_word(); - header.insnum=file->get_word(); - header.patnum=file->get_word(); - header.flags=file->get_word(); - header.tracker=file->get_word(); - header.fileformat=file->get_word(); - file->get_byte_array((uint8_t*)header.scrm,4); - header.scrm[4]=0; - - if (header.scrm[0]!='S' || header.scrm[1]!='C' || header.scrm[2]!='R' || header.scrm[3]!='M') - return FILE_UNRECOGNIZED; - - header.mastervol=file->get_byte(); - header.initspeed=file->get_byte(); - header.inittempo=file->get_byte(); - header.mastermult=file->get_byte(); - header.ultraclick=file->get_byte(); - header.pantable=file->get_byte(); - file->get_byte_array((uint8_t*)header.unused2,8); - header.special=file->get_word(); - file->get_byte_array((uint8_t*)header.channels,32); - - file->get_byte_array((uint8_t*)header.orderlist,header.ordnum); - - header.scrm[4]=0; - if (header.scrm[0]!='S' || header.scrm[1]!='C' || header.scrm[2]!='R' || header.scrm[3]!='M') //again? - return FILE_UNRECOGNIZED; - //sample parapointers - for (i=0;iget_word(); - parapointer=(parapointer*16); - sample_parapointers[i]=parapointer; - } - //pattern - for (i=0;iget_word(); - parapointer=(parapointer*16); - pattern_parapointers[i]=parapointer; - } - - if (header.pantable==252) { - - file->get_byte_array((uint8_t*)header.pannings,32); - } - - return FILE_OK; - - -} - - -void CPLoader_S3M::set_header() { - - - - - song->set_name( header.songname ); -// song->variables.filename= - - song->set_row_highlight_minor( 4 ); - song->set_row_highlight_major( 16 ); - song->set_mixing_volume( header.mastervol ); - song->set_linear_slides( false ); - song->set_old_effects( !(header.flags&64) ); - song->set_compatible_gxx( true ); - - song->set_global_volume( header.mastermult ); - song->set_speed( header.initspeed ); - song->set_tempo( header.inittempo ); - - //[TODO] Set Panning Positions.. ? - - for (int i=0;iset_order(i,header.orderlist[i]); - -} - -CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) { - - - - int type=file->get_byte(); - - char filename[13]; - file->get_byte_array((uint8_t*)filename,12); - filename[12]=0; - - - uint32_t samplepos=(uint32_t)file->get_byte() << 16; - samplepos|=file->get_word(); - samplepos*=16; -// printf("sample at %i\n",samplepos); - /**/ - int sample_size=file->get_dword(); - - - int loop_begin=file->get_dword(); - int loop_end=file->get_dword(); - - int def_volume=file->get_byte();; - int dsk=file->get_byte(); - int pack=file->get_byte(); - - int flags=file->get_byte(); - int c2speed=file->get_dword(); - - file->get_dword(); //useless crap - file->get_dword(); - file->get_dword(); - - - char name[29]; - file->get_byte_array((uint8_t*)name,28); - name[28]=0; - - p_sample->set_default_volume(def_volume); - p_sample->set_name(name); - - char scrs[5]; - file->get_byte_array((uint8_t*)scrs,4); - scrs[4]=0; - - - - bool data_is_16bits=flags&4; - bool data_is_stereo=flags&2; - - if (type==0) { - //empty sample - return FILE_OK; - } - - - if ((type!=1) || scrs[0]!='S' || scrs[1]!='C' || scrs[2]!='R' || scrs[3]!='S' ) { -// printf("type: %i, %c%c%c%c\n",type,scrs[0],scrs[1],scrs[2],scrs[3]); - CP_PRINTERR("Not an S3M CPSample!"); - return FILE_CORRUPTED; - } - - //p_sample->data.set_c5_freq(p_sample->c2spd<<1); - - file->seek(samplepos); - - int real_sample_size=sample_size<create( data_is_16bits, data_is_stereo, sample_size ); - - if (id.is_null()) - return FILE_OUT_OF_MEMORY; - - sm->lock_data(id); - void *dataptr = sm->get_data(id); - - int chans = (data_is_stereo?2:1); - for (int c=0;cget_word(); - s-=32768; //toggle sign - - int16_t *v=(int16_t*)&s; - ((int16_t*)dataptr)[i*chans+c]=*v; - } else { - - - int8_t *v; - uint8_t s=file->get_byte(); - s-=128; //toggle sign - v=(int8_t*)&s; - ((int8_t*)dataptr)[i*chans+c]=*v; - - } - - } - - } - - sm->unlock_data(id); - - - sm->set_loop_begin( id, loop_begin ); - sm->set_loop_end( id, loop_end ); - sm->set_loop_type( id, (flags&1) ? CP_LOOP_FORWARD : CP_LOOP_NONE ); - sm->set_c5_freq( id, c2speed << 1 ); - p_sample->set_sample_data(id); - - /* Scream tracker previous to 3.10 seems to be buggy, as in, wont save what is after the sample loop, including the loop end point. Because of this I must fix it by habd */ - if (flags&1) { - - for (int c=0;c<(data_is_stereo?2:1);c++) { - sm->set_data( id, loop_end, sm->get_data( id, loop_begin,c ),c ); - - } - } - - - return FILE_OK; - -} - - -CPLoader::Error CPLoader_S3M::load_pattern(CPPattern *p_pattern) { - - int row=0,flag,ch; - CPNote n; - int length,accum=0; - - length=file->get_word(); - p_pattern->set_length(64); - - /* clear pattern data */ - while((row<64) && (accum<=length) ) { - flag=file->get_byte(); - accum++; - - n.clear(); - if(flag) { - // ch=remap[flag&31]; -// ch=remap[flag&31]; -// if(ch!=-1) -// n=s3mbuf[(64U*ch)+row]; -// else -// n=&dummy; - - ch=flag&31; - - if(flag&32) { - n.note=file->get_byte(); - if (n.note==255) { - - n.note=CPNote::EMPTY; - } else if (n.note==254) { - - n.note=CPNote::CUT; - } else { - - n.note=((n.note>>4)*12)+(n.note&0xF); - } - - n.instrument=file->get_byte()-1; - accum+=2; - - } - if(flag&64) { - n.volume=file->get_byte(); - if (n.volume>64) n.volume=64; - accum++; - - } - if(flag&128) { - n.command=file->get_byte()-1; - n.parameter=file->get_byte(); - accum+=2; - } - - p_pattern->set_note(ch,row,n); - } else row++; - } - return FILE_OK; - - -} - -CPLoader::Error CPLoader_S3M::load_sample(const char *p_file,CPSample *p_sample) { - - return FILE_UNRECOGNIZED; -} -CPLoader::Error CPLoader_S3M::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { - - return FILE_UNRECOGNIZED; - -} - - -CPLoader::Error CPLoader_S3M::load_samples() { - - int i; - - for(i=0;iseek(sample_parapointers[i]); - load_sample(song->get_sample(i)); - sample_count++; - } - - return FILE_OK; -} - -CPLoader::Error CPLoader_S3M::load_patterns() { - - int i; - - Error err; - for(i=0;iseek(pattern_parapointers[i]); - - err=load_pattern(song->get_pattern(i) ); - CP_ERR_COND_V(err,err); - - - pattern_count++; - } - return FILE_OK; - -} - -CPLoader::Error CPLoader_S3M::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) { - - song=p_song; - - if (file->open(p_file,CPFileAccessWrapper::READ)) { - //printf("Can't open file! %s\n",p_file); - return FILE_CANNOT_OPEN; - }; - - sample_count=0; - pattern_count=0; - - //printf("LOADING HEADER\n"); - CPLoader::Error err; - if ((err=load_header())) { - file->close(); - CP_ERR_COND_V(err,err); - - } - - song->reset(); //file type recognized, reset song! - - set_header(); - - //printf("LOADING SAMPLES\n"); - - if ((err=load_samples())) { - file->close(); - - CP_ERR_COND_V(err,err); - } - - //printf("LOADING PATTERNS\n"); - - if ((err=load_patterns())) { - - file->close(); - return err; - } - - file->close(); - - return FILE_OK; -} - - - -CPLoader_S3M::CPLoader_S3M(CPFileAccessWrapper *p_file){ - - file=p_file; - -} -CPLoader_S3M::~CPLoader_S3M(){ -} - diff --git a/drivers/chibi/cp_loader_s3m.h b/drivers/chibi/cp_loader_s3m.h deleted file mode 100644 index 175e5e80fe..0000000000 --- a/drivers/chibi/cp_loader_s3m.h +++ /dev/null @@ -1,111 +0,0 @@ -/*************************************************************************/ -/* cp_loader_s3m.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_LOADER_S3M_H -#define CP_LOADER_S3M_H - -#include "cp_loader.h" - -/** - *@author Juan Linietsky - */ -/****************************** - loader_s3m.h - ---------- -Scream Tracker Module CPLoader! -It lacks support for -individual sample loading -and reorganizing the columns. -********************************/ - - - - -class CPLoader_S3M : public CPLoader { - - struct S3M_Header { - char songname[28]; - uint8_t t1a; - uint8_t type; - uint8_t unused1[2]; - uint16_t ordnum; - uint16_t insnum; - uint16_t patnum; - uint16_t flags; - uint16_t tracker; - uint16_t fileformat; - char scrm[5]; - uint8_t mastervol; - uint8_t initspeed; - uint8_t inittempo; - uint8_t mastermult; - uint8_t ultraclick; - uint8_t pantable; - uint8_t unused2[8]; - uint16_t special; - uint8_t channels[32]; - uint8_t pannings[32]; - uint8_t orderlist[300]; - }; - - - int sample_parapointers[CPSong::MAX_SAMPLES]; - int pattern_parapointers[CPSong::MAX_PATTERNS]; - - Error load_header(); - void set_header(); - Error load_sample(CPSample *p_sample); - Error load_pattern(CPPattern *p_pattern); - Error load_patterns(); - - Error load_samples(); - - S3M_Header header; - int sample_count; - int pattern_count; - - CPFileAccessWrapper *file; - CPSong *song; -public: - - bool can_load_song() { return true; } - bool can_load_sample() { return false; } - bool can_load_instrument() { return false; } - - Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset); - Error load_sample(const char *p_file,CPSample *p_sample); - Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx); - - CPLoader_S3M(CPFileAccessWrapper *p_file); - ~CPLoader_S3M(); -}; - - - -#endif diff --git a/drivers/chibi/cp_loader_xm.cpp b/drivers/chibi/cp_loader_xm.cpp deleted file mode 100644 index bff8615a32..0000000000 --- a/drivers/chibi/cp_loader_xm.cpp +++ /dev/null @@ -1,752 +0,0 @@ -/*************************************************************************/ -/* cp_loader_xm.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_loader_xm.h" -#include "cp_tables.h" - -#define ABORT_LOAD { file->close(); return FILE_CORRUPTED; } - - - - -CPLoader::Error CPLoader_XM::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) { - - song=p_song; - - if (file->open(p_file,CPFileAccessWrapper::READ)) { - - return FILE_CANNOT_OPEN; - }; - - - /************************************** - LOAD HEADER - ***************************************/ - - file->get_byte_array(header.idtext,17); - header.idtext[17]=0; - - file->get_byte_array(header.songname,20); - - - - header.songname[20]=0; - header.hex1a=file->get_byte(); - if (header.hex1a!=0x1A) { //XM "magic" byte.. this sucks :) - - file->close(); - return FILE_UNRECOGNIZED; - - } - - - //magic byte sucks, but can't do much about it.. - - song->reset(); //must reset the song - - song->set_name( (const char*)header.songname ); - - file->get_byte_array(header.trackername,20); - header.trackername[20]=0; - - - header.version=file->get_word(); - - header.headersize=file->get_dword(); - - header.songlength=file->get_word(); - - header.restart_pos=file->get_word(); - - header.channels_used=file->get_word(); - - header.patterns_used=file->get_word(); - - header.instruments_used=file->get_word(); - - song->set_linear_slides( file->get_word() ); - - song->set_speed( file->get_word() ); - - song->set_tempo( file->get_word() ); - song->set_instruments( true ); - - file->get_byte_array(header.orderlist,256); - - for (int i=0;i199) - break; - song->set_order(i,header.orderlist[i]); - } - - /************************************** - LOAD PATTERNS - ***************************************/ - - for (int i=0;iget_dword(); //length - aux=file->get_byte(); //packing type - rows=aux=file->get_word(); //rows! - - song->get_pattern(i)->set_length( aux ); - - aux=file->get_word(); //packed size - if (aux==0) - continue; - //unpaaack! - for(int j=0;j<(int)rows;j++) - for(int k=0;kget_byte(); //packing type - if (!(aux_byte&0x80)) { - - aux_note.note=aux_byte; - aux_byte=0xFE; //if bit 7 not set, read all of them except the note - } - - if (aux_byte&1) aux_note.note=file->get_byte(); - if (aux_byte&2) aux_note.instrument=file->get_byte(); - if (aux_byte&4) aux_note.volume=file->get_byte(); - if (aux_byte&8) aux_note.command=file->get_byte(); - if (aux_byte&16) aux_note.parameter=file->get_byte(); - - if (aux_note.note!=CPNote::EMPTY) { - - if (aux_note.note==97) aux_note.note=CPNote::OFF; - else { - aux_note.note+=11; //octave minus one (XM C-0 is 1, not zero ) - } - } - if (aux_note.instrument!=CPNote::EMPTY) { - - if ((aux_note.instrument>0) && (aux_note.instrument<100)) - aux_note.instrument--; - else - aux_note.instrument=CPNote::EMPTY; - } - if (aux_note.volume!=CPNote::EMPTY) { - - if (aux_note.volume<0x10) {} - else if (aux_note.volume<0x50) { - - aux_note.volume-=0x10; - - } else if (aux_note.volume<0x60) { - // - aux_note.volume=CPNote::EMPTY; - - } else if (aux_note.volume<0x70) { - //60 -- volume slide down - aux_note.volume-=0x60; - if (aux_note.volume>9) aux_note.volume=9; - aux_note.volume+=95; - - } else if (aux_note.volume<0x80) { - //70 -- volume slide up - aux_note.volume-=0x70; - if (aux_note.volume>9) aux_note.volume=9; - aux_note.volume+=85; - - - } else if (aux_note.volume<0x90) { - //80 -- fine volume slide down - aux_note.volume-=0x80; - if (aux_note.volume>9) aux_note.volume=9; - aux_note.volume+=75; - - - } else if (aux_note.volume<0xA0) { - //9 -- fine volume slide up - - aux_note.volume-=0x90; - if (aux_note.volume>9) aux_note.volume=9; - - aux_note.volume+=65; - - - - } else if (aux_note.volume<0xB0) { - //A -- set vibrato speed - aux_note.volume=CPNote::EMPTY; - - } else if (aux_note.volume<0xC0) { - //B -- vibrato - aux_note.volume-=0xB0; - if (aux_note.volume>9) aux_note.volume=9; - aux_note.volume+=203; - - - } else if (aux_note.volume<0xD0) { - //C -- set panning - int aux=aux_note.volume-=0xC0; - aux=aux*65/0xF; - aux_note.volume=128+aux; - - } else if (aux_note.volume<0xE0) { - aux_note.volume=CPNote::EMPTY; - - - } else if (aux_note.volume<0xF0) { - aux_note.volume=CPNote::EMPTY; - - - } else { - //F -- tone porta - aux_note.volume-=0xF0; - aux_note.volume*=9; - aux_note.volume/=0xF; - aux_note.volume+=193; - } - } - if (aux_note.command!=CPNote::EMPTY) { - - switch(aux_note.command) { - - case 0x0: - aux_note.command='J'-'A'; - break; - case 0x1: - aux_note.command='F'-'A'; - break; - case 0x2: - aux_note.command='E'-'A'; - break; - case 0x3: - aux_note.command='G'-'A'; - break; - case 0x4: - aux_note.command='H'-'A'; - break; - case 0x5: - aux_note.command='L'-'A'; - break; - case 0x6: - aux_note.command='K'-'A'; - break; - case 0x7: - aux_note.command='R'-'A'; - break; - case 0x8: - aux_note.command='X'-'A'; - break; - case 0x9: - aux_note.command='O'-'A'; - break; - case 0xa: - aux_note.command='D'-'A'; - break; - case 0xb: - aux_note.command='B'-'A'; - break; - case 0xc: - //printf("XM Import: Warning! effect C (set volume) not implemented!\n"); - break; - case 0xd: - aux_note.command='C'-'A'; - break; - - case 0xe: /* Extended effects */ - - aux_note.command='S'-'A'; - switch(aux_note.parameter>>4) { - case 0x1: /* XM fine porta up */ - if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } - aux_note.command='F'-'A'; - aux_note.parameter=0xF0|(aux_note.parameter&0xF); - break; - case 0x2: /* XM fine porta down */ - if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } - aux_note.command='E'-'A'; - aux_note.parameter=0xF0|(aux_note.parameter&0xF); - break; - case 0xa: /* XM fine volume up */ - if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } - aux_note.command='D'-'A'; - aux_note.parameter=0x0F|((aux_note.parameter&0xF)<<4); - - break; - case 0xb: /* XM fine volume down */ - if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } - aux_note.command='D'-'A'; - aux_note.parameter=0xF0|(aux_note.parameter&0xF); - - break; - case 0x9: /* XM fine volume down */ - if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } - aux_note.command='Q'-'A'; - aux_note.parameter=0x00|(aux_note.parameter&0xF); - break; - - case 0xc: //notecut - - aux_note.parameter=0xC0|(aux_note.parameter&0xF); - break; - - case 0xd: //notedelay - - aux_note.parameter=0xD0|(aux_note.parameter&0xF); - break; - - case 0xe: //patterndelay - - aux_note.parameter=0xE0|(aux_note.parameter&0xF); - break; - } - - break; - case 0xf: - if (aux_note.parameter<32) { - aux_note.command='A'-'A'; - } else { - aux_note.command='T'-'A'; - } - break; - case 'G'-55: - aux_note.command='V'-'A'; - break; - case 'H'-55: - aux_note.command='W'-'A'; - break; - case 'K'-55: - if (aux_note.note!=CPNote::EMPTY) break; - aux_note.note=CPNote::OFF; - break; - case 'P'-55: - aux_note.command='P'-'A'; - break; - case 'R'-55: - aux_note.command='Q'-'A'; - break; - case 'T'-55: - aux_note.command='I'-'A'; - break; - default: { - - aux_note.command=CPNote::EMPTY; - } - } - - - } - - song->get_pattern( i)->set_note( k,j,aux_note ); - } - } - - /************************************** - LOAD INSTRUMENTS! - ***************************************/ - - for (int i=0;iget_instrument(i); - uint32_t cpos=file->get_pos(); - //printf("pos is %i\n",cpos); - - - -/* +4 */ uint32_t hsize=file->get_dword(); //header length - - char instrname[23]; - instrname[22]=0; - - file->get_byte_array((uint8_t*)instrname,22); -//XM_LOAD_DEBUG printf("name is %s\n",instrname); - -/* +27 */ aux=file->get_byte(); //byte that must be ignored -//XM_LOAD_DEBUG printf("header size is %i\n",hsize); - -/* +29 */ sampnum=file->get_word(); - -//XM_LOAD_DEBUG printf("samples %i\n",sampnum); - - - instrument.set_name( instrname ); -// printf("Header Len: %i, CPInstrument %i, %i samples , name: s,\n",hsize,i,sampnum,instrname); - - if (sampnum==0) { - //aux=file->get_dword(); //Why is this for? -- for nothing, skipped - if (hsize) { - - file->seek( cpos+hsize ); //skip header if size has been specified - } - continue; - } - -/* +33 */ file->get_dword(); - - if (Error result=load_instrument_internal(&instrument,false,cpos,hsize,sampnum)) { - - CP_PRINTERR("Error loading instrument"); - file->close(); - return result; - } - - } -// - file->close(); - return FILE_OK; -} - -CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr,bool p_xi,int p_cpos, int p_hsize, int p_sampnum) { - - int sampnum; - uint32_t aux; - uint8_t notenumb[96]; - uint16_t panenv[24],volenv[24]; - int volpoints,panpoints; - int vol_loop_begin,vol_loop_end,vol_sustain_loop; - int pan_loop_begin,pan_loop_end,pan_sustain_loop; - char instrname[23]; - int sample_index[16]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; //-1 means no index! - - instrname[22]=0; - - -/* +129 */ file->get_byte_array((uint8_t*)notenumb,96); - for (int j=0;j<24;j++) { - volenv[j]=file->get_word(); - } - for (int j=0;j<24;j++) { - panenv[j]=file->get_word(); - } - -/* +177 */ -/* +225 */ -/* +226 */ volpoints=file->get_byte(); -/* +227 */ panpoints=file->get_byte(); -/* +230 */ vol_sustain_loop=file->get_byte(); -/* +228 */ vol_loop_begin=file->get_byte(); -/* +229 */ vol_loop_end=file->get_byte(); - -//XM_LOAD_DEBUG printf("1- volpoints: %i, panpoints: %i, susloop: %i, loop begin: %i, loop end %i\n",volpoints,panpoints,vol_sustain_loop,vol_loop_begin,vol_loop_end); - pan_sustain_loop=file->get_byte(); -/* +231 */ pan_loop_begin=file->get_byte(); -/* +232 */ pan_loop_end=file->get_byte(); - - - -/* +234 */ aux=file->get_byte(); - p_instr->get_volume_envelope()->reset(); - p_instr->get_volume_envelope()->set_enabled(aux&1); - p_instr->get_volume_envelope()->set_sustain_loop_enabled((aux&2)?true:false); - p_instr->get_volume_envelope()->set_loop_enabled((aux&4)?true:false); -/* +235 */ aux=file->get_byte(); - p_instr->get_pan_envelope()->reset(); - p_instr->get_pan_envelope()->set_enabled(aux&1); - p_instr->get_pan_envelope()->set_sustain_loop_enabled((aux&2)?true:false); - p_instr->get_pan_envelope()->set_loop_enabled((aux&4)?true:false); - -/* +239 */ aux=file->get_dword(); // sadly, cant use those -/* +241 */ p_instr->set_volume_fadeout( file->get_word() >> 4 ); -/* +243 */ aux=file->get_word(); // reserved! - - - - for (int j=0;jget_volume_envelope()->add_position(ofs,val); - - } - - //make sure minimum is 2 - while (p_instr->get_volume_envelope()->get_node_count()<2) { - - p_instr->get_volume_envelope()->add_position( p_instr->get_volume_envelope()->get_node_count()*20,64 ); - } - - for (int j=0;jget_pan_envelope()->add_position(ofs,val-32); - } - - //make sure minimum is 2 - while (p_instr->get_pan_envelope()->get_node_count()<2) { - - p_instr->get_pan_envelope()->add_position( p_instr->get_pan_envelope()->get_node_count()*20,0 ); - } - - - p_instr->get_volume_envelope()->set_loop_begin(vol_loop_begin); - p_instr->get_volume_envelope()->set_loop_end(vol_loop_end); - p_instr->get_volume_envelope()->set_sustain_loop_end(vol_sustain_loop); - p_instr->get_volume_envelope()->set_sustain_loop_begin(vol_sustain_loop); - p_instr->get_pan_envelope()->set_loop_begin(pan_loop_begin); - p_instr->get_pan_envelope()->set_loop_end(pan_loop_end); - p_instr->get_pan_envelope()->set_sustain_loop_end(pan_sustain_loop); - p_instr->get_pan_envelope()->set_sustain_loop_begin(pan_sustain_loop); - - - if (!p_xi) { - - if ((file->get_pos()-p_cpos)get_pos()-p_cpos)); - //printf("extra: %i\n",p_hsize-(file->get_pos()-p_cpos)); - file->get_byte_array((uint8_t*)junkbuster,p_hsize-(file->get_pos()-p_cpos)); - } - - sampnum=p_sampnum; - } else { - - uint8_t junkbuster[500]; - file->get_byte_array((uint8_t*)junkbuster,20); //14 bytes? - - sampnum=file->get_word(); - - } - - - CPSampleManager *sm=CPSampleManager::get_singleton(); - - /*SAMPLE!!*/ - - for (int j=0;j16) ABORT_LOAD; - - - int s_idx=-1; - for (int s=0;sget_sample(s)->get_sample_data().is_null()) { - //empty sample! - s_idx=s; - break; - } - } - - if (s_idx==-1) ABORT_LOAD; - //printf("free sample: %i\n",s_idx); - - - CPSample& sample=*song->get_sample(s_idx); - - int sample_size=file->get_dword(); - int tmp_loop_begin=file->get_dword(); - - int tmp_loop_end=file->get_dword(); - - sample.set_default_volume(file->get_byte()); - - uint8_t ftb=file->get_byte(); - int8_t *fts=(int8_t*)&ftb; - int finetune=*fts; - uint32_t flags=file->get_byte(); - - if (flags&16) { // is 16 bits.. at flag 16.. fun :) - - tmp_loop_end/=2; - tmp_loop_begin/=2; - sample_size/=2; - } - - - CPSample_ID sample_data=sm->create( flags&16, false, sample_size ); - - sample.set_sample_data(sample_data); - sm->set_loop_begin(sample_data,tmp_loop_begin); - sm->set_loop_end(sample_data,tmp_loop_end+tmp_loop_begin); - - sm->set_loop_type( sample_data, (flags&3)?( (flags&2) ? CP_LOOP_BIDI : CP_LOOP_FORWARD ):CP_LOOP_NONE ); - - - - sample.set_pan_enabled(true); - sample.set_pan(file->get_byte()*64/255); - uint8_t noteb=file->get_byte(); - int8_t *notes=(int8_t*)¬eb; - int note_offset=*notes; - note_offset+=48; - //note_offset+=60; - - - - //int linear_period=10*12*16*4 - (note_offset)*16*4 - finetune/2; - //int freq=(int)(8363*pow(2.0,(double)(6*12*16*4 - linear_period) / (double)(12*16*4))); - - //sm->set_c5_freq( sample_data, freq); - sm->set_c5_freq( sample_data, CPTables::get_linear_frequency(CPTables::get_linear_period(note_offset<<1,finetune)) ); - //printf("NOTE %i,fine %i\n",note_offset,finetune); - - char auxb; - auxb=file->get_byte(); //reserved? - file->get_byte_array((uint8_t*)instrname,22); - sample.set_name(instrname); - - sample_index[j]=s_idx; - } - - /*SAMPLE __DATA__!!*/ - - for (int j=0;jget_sample(sample_index[j]); - CPSample_ID sid=sample->get_sample_data(); - - sm->lock_data(sid); - - void*dataptr=sm->get_data(sid); - - if (sm->is_16bits( sid)) { - - int16_t old=0; - - - for (int k=0;kget_size(sid);k++) { - - int16_t newsample; - int16_t sampleval=file->get_word(); - newsample=sampleval+old; - old=newsample; - - ((int16_t*)dataptr)[k]=newsample; - //sm->set_data( sid, k, newsample ); - } - } else { - - int8_t old=0; - - - for (int k=0;kget_size(sid);k++) { - - int8_t newsample; - int8_t sampleval=file->get_byte(); - newsample=sampleval+old; - old=newsample; - - ((int8_t*)dataptr)[k]=newsample; - - //sm->set_data( sid, k, (int16_t)newsample << 8 ); - - } - } - - sm->unlock_data(sid); - - } - - for (int j=0;j<96;j++) { - - int val=notenumb[j]; - if ((val<0) || (val>15)) continue; - else val=sample_index[val]; - if (val==-1) continue; - p_instr->set_sample_number( 12+j,val ); - } - - - return FILE_OK; -} - - - -CPLoader::Error CPLoader_XM::load_sample(const char *p_file,CPSample *p_sample) { - - return FILE_UNRECOGNIZED; -} - - -/* Compute CPInstrument Info */ -CPLoader::Error CPLoader_XM::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { - - if ( file->open(p_file,CPFileAccessWrapper::READ) ) return FILE_CANNOT_OPEN; - //int i; - song=p_song; - CPInstrument& instr=*p_song->get_instrument( p_instr_idx ); - int aux; - - - char buffer[500]; - file->get_byte_array((uint8_t*)buffer,0x15); - buffer[8]=0; - if ( buffer[0]!='E' || - buffer[1]!='x' || - buffer[2]!='t' || - buffer[3]!='e' || - buffer[4]!='n' || - buffer[5]!='d' || - buffer[6]!='e' || - buffer[7]!='d') { - file->close(); - return FILE_UNRECOGNIZED; - } - - file->get_byte_array((uint8_t*)buffer,0x16); - buffer[0x16]=0; - instr.set_name(buffer); - aux=file->get_byte(); //says ignore ti - /*if(aux!=0x1a) { I'm not sure. this is supposed to be ignored... - - file->close(); - return FILE_UNRECOGNIZED; - } */ - - file->get_byte_array((uint8_t*)buffer,0x14); //somethingaboutthename - aux=file->get_word(); //version or blahblah - - if (load_instrument_internal(&instr,true,0,0)) { - - file->close(); - return FILE_CORRUPTED; - } - - file->close(); //ook, we got it.. - - - return FILE_OK; - -} - - - -CPLoader_XM::CPLoader_XM(CPFileAccessWrapper *p_file){ - - file=p_file; -} -CPLoader_XM::~CPLoader_XM(){ -} - diff --git a/drivers/chibi/cp_loader_xm.h b/drivers/chibi/cp_loader_xm.h deleted file mode 100644 index 9ae480cc8f..0000000000 --- a/drivers/chibi/cp_loader_xm.h +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************/ -/* cp_loader_xm.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_LOADER_XM_H -#define CP_LOADER_XM_H - -#include "cp_loader.h" - - -/** - *@author red - */ - - - - -class CPLoader_XM : public CPLoader { - - - struct XM_Header { - - uint8_t idtext[18]; - uint8_t songname[21]; - uint8_t hex1a; // ? - uint8_t trackername[21]; - uint16_t version; - uint32_t headersize; //from here - - uint16_t songlength; //pattern ordertable - uint16_t restart_pos; - uint16_t channels_used; - uint16_t patterns_used; - uint16_t instruments_used; - uint16_t use_linear_freq; - uint16_t tempo; - uint16_t speed; - uint8_t orderlist[256]; - - } header; - - CPFileAccessWrapper *file; - - Error load_instrument_internal(CPInstrument *pint,bool p_xi,int p_cpos, int p_hsize, int p_sampnumb=-1); - CPSong *song; - -public: - - bool can_load_song() { return true; } - bool can_load_sample() { return false; } - bool can_load_instrument() { return true; } - - Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset); - Error load_sample(const char *p_file,CPSample *p_sample); - Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx); - - - CPLoader_XM(CPFileAccessWrapper *p_file); - ~CPLoader_XM(); -}; - - - -#endif diff --git a/drivers/chibi/cp_mixer.h b/drivers/chibi/cp_mixer.h deleted file mode 100644 index 7ad22ac146..0000000000 --- a/drivers/chibi/cp_mixer.h +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************/ -/* cp_mixer.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_MIXER_H -#define CP_MIXER_H - -#include "cp_sample_defs.h" - -/**Abstract base class representing a mixer - *@author Juan Linietsky - */ - - -/****************************** - mixer.h - ---------- - -Abstract base class for the mixer. -This is what the player uses to setup -voices and stuff.. this way -it can be abstracted to hardware -devices or other stuff.. -********************************/ - -class CPSample_ID; /* need this */ - -class CPMixer { -public: - - enum { - - FREQUENCY_BITS=8 - - }; - - enum ReverbMode { - REVERB_MODE_ROOM, - REVERB_MODE_STUDIO_SMALL, - REVERB_MODE_STUDIO_MEDIUM, - REVERB_MODE_STUDIO_LARGE, - REVERB_MODE_HALL, - REVERB_MODE_SPACE_ECHO, - REVERB_MODE_ECHO, - REVERB_MODE_DELAY, - REVERB_MODE_HALF_ECHO - }; - - /* Callback */ - - virtual void set_callback_interval(int p_interval_us)=0; //in usecs, for tracker it's 2500000/tempo - virtual void set_callback(void (*p_callback)(void*),void *p_userdata)=0; - - /* Voice Control */ - - virtual void setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) =0; - virtual void stop_voice(int p_voice_index) =0; - virtual void set_voice_frequency(int p_voice_index,int32_t p_freq) =0; //in freq*FREQUENCY_BITS - virtual void set_voice_panning(int p_voice_index,int p_pan) =0; - virtual void set_voice_volume(int p_voice_index,int p_vol) =0; - virtual void set_voice_filter(int p_filter,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance )=0; - virtual void set_voice_reverb_send(int p_voice_index,int p_reverb)=0; - virtual void set_voice_chorus_send(int p_voice_index,int p_chorus)=0; /* 0 - 255 */ - - virtual void set_reverb_mode(ReverbMode p_mode)=0; - virtual void set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10)=0; - - - /* Info retrieving */ - - virtual int32_t get_voice_sample_pos_index(int p_voice_index) =0; - virtual int get_voice_panning(int p_voice_index) =0; - virtual int get_voice_volume(int p_voice_index) =0; - virtual CPSample_ID get_voice_sample_id(int p_voice_index) =0; - virtual bool is_voice_active(int p_voice_index) =0; - virtual int get_active_voice_count()=0; - virtual int get_total_voice_count()=0; - - - virtual uint32_t get_mix_frequency()=0; //if mixer is not software, return 0 - - /* Methods below only work with software mixers, meant for software-based sound drivers, hardware mixers ignore them */ - virtual int32_t process(int32_t p_frames)=0; /* Call this to process N frames, returns how much it was processed */ - virtual int32_t *get_mixdown_buffer_ptr()=0; /* retrieve what was mixed */ - virtual void set_mix_frequency(int32_t p_mix_frequency)=0; - - virtual ~CPMixer() {} -}; - -#endif diff --git a/drivers/chibi/cp_note.h b/drivers/chibi/cp_note.h deleted file mode 100644 index 5cfa3f11ec..0000000000 --- a/drivers/chibi/cp_note.h +++ /dev/null @@ -1,102 +0,0 @@ -/*************************************************************************/ -/* cp_note.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_NOTE_H -#define CP_NOTE_H - -#include "cp_config.h" - -struct CPNote { - - enum { - - NOTES=120, - OFF=254, - CUT=253, - EMPTY=255, - SCRIPT=252, - }; - - - uint8_t note; - uint8_t instrument; - uint8_t volume; - uint8_t command; - uint8_t parameter; - unsigned int script_source_sign; - bool cloned; - - void clear() { - - note=EMPTY; - instrument=EMPTY; - volume=EMPTY; - command=EMPTY; - parameter=0; - script_source_sign='\0'; - cloned=false; - } - - void raise() { - - if (note<(NOTES-1)) - note++; - else if (note==SCRIPT && parameter<0xFF) - parameter++; - } - - void lower() { - - if ((note>0) && (note0) - parameter--; - - } - - bool operator== (const CPNote &rvalue) { - - return ( - (note==rvalue.note) && - (instrument==rvalue.instrument) && - (volume==rvalue.volume) && - (command==rvalue.command) && - (parameter==rvalue.parameter) - ); - } - - bool is_empty() const { return (note==EMPTY && instrument==EMPTY && volume==EMPTY && command==EMPTY && parameter==0 && !cloned); } - CPNote() { - - clear(); - } -}; - - -#endif - diff --git a/drivers/chibi/cp_order.h b/drivers/chibi/cp_order.h deleted file mode 100644 index 03ecc00bba..0000000000 --- a/drivers/chibi/cp_order.h +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************/ -/* cp_order.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_ORDER_H -#define CP_ORDER_H - - -#include "cp_config.h" - -enum CPOrderType { - CP_ORDER_NONE=255, - CP_ORDER_BREAK=254 -}; - -typedef uint8_t CPOrder; - -#endif - diff --git a/drivers/chibi/cp_pattern.cpp b/drivers/chibi/cp_pattern.cpp deleted file mode 100644 index 83e165bf87..0000000000 --- a/drivers/chibi/cp_pattern.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/*************************************************************************/ -/* cp_pattern.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_pattern.h" - -void CPPattern::clear() { - - if (event_count>0) { - - - CP_FREE(events); - events=NULL; - event_count=0; - } - - length=DEFAULT_LEN; - -} - - -bool CPPattern::resize_event_list_to(uint32_t p_events) { - - - //Module is slow in some cpus, so this should be fast enough - uint32_t new_size=((p_events-1)&(~((1<=p_target_pos) - break; - - } */ - - //return pos_idx; -} - -bool CPPattern::erase_event_at_pos(uint16_t p_pos) { - - if (event_count==0) - return false; - - - - Event *event_list=events; - - int32_t pos_idx = get_event_pos(p_pos); - if (pos_idx==-1) { - CP_ERR_COND_V(pos_idx==-1,true); - } - - if (pos_idx==event_count || event_list[pos_idx].pos!=p_pos) { - /* Nothing to Erase */ - return false; - } - - for (int32_t i=pos_idx;i<(event_count-1);i++) { - - event_list[i]=event_list[i+1]; - } - - - resize_event_list_to(event_count-1); - - return false; -} - -bool CPPattern::set_note(uint8_t p_column, uint16_t p_row,const CPNote& p_note) { - - CP_ERR_COND_V(p_column>=WIDTH,true); - CP_ERR_COND_V(p_row>=length,true); - - int32_t new_pos; - uint16_t target_pos=p_row*WIDTH+p_column; - - - - if (p_note.is_empty()) { - bool res=erase_event_at_pos(target_pos); - - return res;; - } - - Event *event_list=0; - - if (event_count==0) { - /* If no events, create the first */ - - if (resize_event_list_to(1)) { - - CP_PRINTERR("Can't resize event list to 1"); - return true; - } - - event_list=events; - if (event_list==0) { - - - CP_PRINTERR("Can't get event list"); - return true; - } - - new_pos=0; - - } else { - /* Prepare to add */ - - event_list=events; - if (event_list==0) { - - - CP_PRINTERR("Can't get event list"); - return true; - } - - int32_t pos_idx = get_event_pos(target_pos); - - if (pos_idx==-1) { - - - CP_PRINTERR("Can't find add position"); - return true; - } - - - if (pos_idx==event_count || event_list[pos_idx].pos!=target_pos) { - /* If the note being modified didnt exist, then we add it */ - - //resize, and return if out of mem - if (resize_event_list_to( event_count+1)) { - - - CP_PRINTERR("Can't resize event list"); - return true; - } - event_list=events; - if (event_list==0) { - - - CP_PRINTERR("Can't get event list"); - return true; - } - - //make room for new pos, this wont do a thing if pos_idx was ==event_count - for(int32_t i=(event_count-1);i>pos_idx;i--) { - event_list[i]=event_list[i-1]; - - } - - } /* Else it means that position is taken, so we just modify it! */ - - - new_pos=pos_idx; - } - - event_list[new_pos].pos=target_pos; - event_list[new_pos].note=p_note.note; - event_list[new_pos].instrument=p_note.instrument; - event_list[new_pos].volume=p_note.volume; - event_list[new_pos].command=p_note.command; - event_list[new_pos].parameter=p_note.parameter; - event_list[new_pos].script_source_sign=p_note.script_source_sign; - event_list[new_pos].cloned=p_note.cloned; - - - - - return false; - -} -CPNote CPPattern::get_note(uint8_t p_column,uint16_t p_row) { - - if (p_column==CPNote::EMPTY) return CPNote(); - - CP_ERR_COND_V(p_column>=WIDTH,CPNote()); - CP_ERR_COND_V(p_row>=length,CPNote()); - - if (event_count==0) - return CPNote(); - - - Event *event_list=events; - - CP_ERR_COND_V(event_list==0,CPNote()); - - uint16_t target_pos=p_row*WIDTH+p_column; - int32_t pos_idx = get_event_pos(target_pos); - if (pos_idx==-1) { - - CP_PRINTERR("Can't find event pos"); - return CPNote(); - } - - if (pos_idx>=event_count || event_list[pos_idx].pos!=target_pos) { - /* no note found */ - - return CPNote(); - } - - CPNote n; - n.note=event_list[pos_idx].note; - n.instrument=event_list[pos_idx].instrument; - n.volume=event_list[pos_idx].volume; - n.command=event_list[pos_idx].command; - n.parameter=event_list[pos_idx].parameter; - n.script_source_sign=event_list[pos_idx].script_source_sign; - n.cloned=event_list[pos_idx].cloned; - - - return n; - -} - -CPNote CPPattern::get_transformed_script_note(uint8_t p_column,uint16_t p_row ) { - - CPNote n = get_note( p_column, p_row ); - - // get source channel and note - - int channel = get_scripted_note_target_channel( p_column, p_row ); - CPNote src_n = get_note( channel, 0 ); - - if ( src_n.note == CPNote::SCRIPT ) return CPNote(); - - script_transform_note( src_n, n ); - - return src_n; - -} - -int CPPattern::get_scripted_note_target_channel(uint8_t p_column, uint16_t p_row) { - - CPNote n = get_note( p_column, p_row ); - - if ( n.note != CPNote::SCRIPT ) return CPNote::EMPTY; - - int channel = n.instrument; - - if ( n.script_source_sign == '\0' ) { - - if ( channel < 0 || channel >= CPPattern::WIDTH ) return CPNote::EMPTY; - - } else { - - channel = p_column + ( ( n.script_source_sign=='+') ? 1 : -1 ) * (channel+1); - if ( channel < 0 || channel >= CPPattern::WIDTH ) return CPNote::EMPTY; - - } - - return channel; -} - -void CPPattern::scripted_clone(uint8_t p_column, uint16_t p_row) { - - int channel = get_scripted_note_target_channel( p_column, p_row ); - int src_row = 1; - CPNote script_n = get_note( p_column, p_row ); - - for ( int row = p_row+1; row < length; ++row ) { - - CPNote src_n = get_note( channel, src_row ); - CPNote target_n = get_note( p_column, row ); - - if ( target_n.note != CPNote::SCRIPT ) { - if ( src_n.note == CPNote::SCRIPT ) { - src_n = CPNote(); - channel = CPNote::EMPTY; - } - - script_transform_note( src_n, script_n ); - - src_n.cloned = true; - set_note( p_column, row, src_n ); - - } else { - - return; - - } - - src_row++; - } - -} - -void CPPattern::scripted_clone_remove(uint8_t p_column, uint16_t p_row) { - - if ( get_note( p_column, p_row ).cloned ) - set_note( p_column, p_row, CPNote() ); - - for ( int row = p_row+1; row < length; ++row ) { - - CPNote target_n = get_note( p_column, row ); - - if ( target_n.note != CPNote::SCRIPT ) { - - set_note( p_column, row, CPNote() ); - - } else { - - return; - - } - - } - -} - -void CPPattern::script_transform_note(CPNote& n, const CPNote& p_note) { - - // set instrument - - if ( n.note < CPNote::NOTES && p_note.volume != CPNote::EMPTY ) { - - n.instrument = p_note.volume; - - } - - // transpose - - if ( n.note < CPNote::NOTES && p_note.command != CPNote::EMPTY ) { - - int transpose = ( p_note.parameter & 0xF ) + ( p_note.parameter / 0x10 ) * 12; - - if ( p_note.command == '^' ) { - - if ( n.note >= CPNote::NOTES-transpose ) - n.note = CPNote::NOTES-1; - else - n.note += transpose; - - } else if ( p_note.command == 'v' ) { - - if ( n.note <= transpose ) - n.note = 0; - else - n.note -= transpose; - - } - } - -} - -bool CPPattern::update_scripted_clones_sourcing_channel( int channel ) { - - bool updated = false; - - for ( int x = 0; x < WIDTH; ++x ) { - - for (int y = 0; y < length; ++y ) { - - if ( channel == get_scripted_note_target_channel( x, y ) ) { - - scripted_clone( x, y ); - updated = true; - } - - } - - } - - return updated; -} - -void CPPattern::set_length(uint16_t p_rows) { - - - - if (event_count==0) { - - if (p_rows>=MIN_ROWS) - length=p_rows; - - - return; - - } - - if (p_rowsclear(); - p_pattern->length=length; - - - if (!event_count) - return; - - - - int bufsiz=MemPool_Wrapper::get_singleton()->get_mem_size( mem_handle ); - MemPool_Handle aux_mem_handle=MemPool_Wrapper::get_singleton()->alloc_mem( bufsiz ); - - if (aux_mem_handle.is_null()) { - - CP_PRINTERR("own handle is null"); - - return; - } - - - if (MemPool_Wrapper::get_singleton()->lock_mem(aux_mem_handle)) { - CP_PRINTERR("Unable to lock aux new handle"); - - return; - - } - - if (MemPool_Wrapper::get_singleton()->lock_mem(mem_handle)) { - - CP_PRINTERR("Unable to lock own handle"); - - return; - } - - uint8_t* srcuint8_tt8_t*)MemPool_Wrapper::get_singleton()->get_mem(mem_handle); - uint8_t* dstuint8_tt8_t*)MemPool_Wrapper::get_singleton()->get_mem(aux_mem_handle); - - for (int i=0;iunlock_mem(mem_handle); - MemPool_Wrapper::get_singleton()->unlock_mem(aux_mem_handle); - - p_pattern->mem_handle=aux_mem_handle; - p_pattern->event_count=event_count; - - -} -#endif -uint16_t CPPattern::get_length() { - - - return length; -} -CPPattern::CPPattern() { - - - length=DEFAULT_LEN; - event_count=0; - clear(); - -} -bool CPPattern::is_empty() { - - return events==NULL; -} - -CPPattern::~CPPattern() { - - clear(); -} diff --git a/drivers/chibi/cp_pattern.h b/drivers/chibi/cp_pattern.h deleted file mode 100644 index 4065caa5e5..0000000000 --- a/drivers/chibi/cp_pattern.h +++ /dev/null @@ -1,94 +0,0 @@ -/*************************************************************************/ -/* cp_pattern.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_PATTERN_H -#define CP_PATTERN_H - -#include "cp_note.h" - -class CPPattern { -public: - - - enum { - WIDTH=64, - DEFAULT_LEN=64, - RESIZE_EVERY_BITS=4, - MIN_ROWS=1, //otherwise clipboard wont work - MAX_LEN=256 - - }; - -private: - struct Event { - - uint16_t pos; //column*WIDTH+row - uint8_t note; - uint8_t instrument; - uint8_t volume; - uint8_t command; - uint8_t parameter; - unsigned int script_source_sign; - bool cloned; - }; - - uint16_t length; - uint32_t event_count; - Event* events; - - int32_t get_event_pos(uint16_t p_target_pos); - bool erase_event_at_pos(uint16_t p_pos); - - bool resize_event_list_to(uint32_t p_events); - - void operator=(const CPPattern& p_pattern); //no operator= -public: - - bool is_empty(); - void clear(); - - bool set_note(uint8_t p_column, uint16_t p_row,const CPNote& p_note); //true if no more memory - CPNote get_note(uint8_t p_column,uint16_t p_row); - - CPNote get_transformed_script_note(uint8_t p_column, uint16_t p_row); - int get_scripted_note_target_channel(uint8_t p_column, uint16_t p_row); - void scripted_clone(uint8_t p_column, uint16_t p_row); - void scripted_clone_remove(uint8_t p_column, uint16_t p_row); - void script_transform_note(CPNote& n, const CPNote& p_note); - bool update_scripted_clones_sourcing_channel(int channel); - - //void copy_to(CPPattern *p_pattern) const; - void set_length(uint16_t p_rows); - uint16_t get_length(); - CPPattern(); - ~CPPattern(); - - -}; - -#endif diff --git a/drivers/chibi/cp_player_data.cpp b/drivers/chibi/cp_player_data.cpp deleted file mode 100644 index 3f3e9a5202..0000000000 --- a/drivers/chibi/cp_player_data.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/*************************************************************************/ -/* cp_player_data.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" -#include - - -CPPlayer::CPPlayer(CPMixer *p_mixer,CPSong *p_song){ - - song=p_song; - mixer=p_mixer; - control.max_voices=p_mixer->get_total_voice_count()-1; //leave one for the sample - control.force_no_nna=false; - control.external_vibrato=false; - control.filters=true; - control.random_seed=128364; //anything - control.play_mode=0; - set_virtual_channels(p_mixer->get_total_voice_count()); - mixer->set_callback( &CPPlayer::callback_function, this ); - - reset(); -} -CPPlayer::~CPPlayer(){ -} - -void CPPlayer::set_virtual_channels(int p_amount) { - - if (p_amount<1) return; - if (p_amount>mixer->get_total_voice_count()) - return; - - control.max_voices=p_amount; - -} - - -void CPPlayer::callback_function(void *p_userdata) { - - CPPlayer*pd=(CPPlayer*)p_userdata; - pd->process_tick(); - -} - -void CPPlayer::process_tick() { - - handle_tick(); - mixer->set_callback_interval( 2500000/control.tempo ); - song_usecs+=2500000/control.tempo; -} - -void CPPlayer::reset() { - - if ( mixer==NULL ) return ; - if ( song==NULL ) return ; - - int i; - - for (i=0;istop_voice(i); - } - - for (i=0;iget_channel_volume(i); - control.channel[i].channel_panning=((int)song->get_channel_pan( i)*PAN_RIGHT/64); - if (song->is_channel_surround(i)) - control.channel[i].channel_panning=PAN_SURROUND; - control.channel[i].mute=song->is_channel_mute( i ); - control.channel[i].chorus_send=song->get_channel_chorus(i)*0xFF/64; - control.channel[i].reverb_send=song->get_channel_reverb(i)*0xFF/64; - } - - - control.speed=song->get_speed(); - control.tempo=song->get_tempo(); - control.global_volume=song->get_global_volume(); - - control.position.current_pattern=0; - control.position.current_row=0; - control.position.current_order=0; - control.position.force_next_order=-1; - control.ticks_counter=control.speed; - control.position.forbid_jump=false; - - song_usecs=0; - -} - -int64_t CPPlayer::get_channel_last_note_time_usec(int p_channel) const { - - CP_FAIL_INDEX_V(p_channel,64,-1); - return control.channel[p_channel].last_event_usecs; - -} - -void CPPlayer::set_channel_global_volume(int p_channel,int p_volume) { - - CP_FAIL_INDEX(p_channel,64); - control.channel[p_channel].channel_global_volume=CLAMP(p_volume,0,255); - -} - -int CPPlayer::get_channel_global_volume(int p_channel) const{ - - CP_FAIL_INDEX_V(p_channel,64,-1); - return control.channel[p_channel].channel_global_volume; - -} - -bool CPPlayer::reached_end_of_song() { - - return control.reached_end; - -} -void CPPlayer::set_force_external_vibratos(bool p_force) { - - control.external_vibrato=p_force; -} -void CPPlayer::set_force_no_nna(bool p_force) { - - control.force_no_nna=p_force; -} diff --git a/drivers/chibi/cp_player_data.h b/drivers/chibi/cp_player_data.h deleted file mode 100644 index 282592b8f4..0000000000 --- a/drivers/chibi/cp_player_data.h +++ /dev/null @@ -1,582 +0,0 @@ -/*************************************************************************/ -/* 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 diff --git a/drivers/chibi/cp_player_data_control.cpp b/drivers/chibi/cp_player_data_control.cpp deleted file mode 100644 index d9aaed904f..0000000000 --- a/drivers/chibi/cp_player_data_control.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_control.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" - -void CPPlayer::play_start_pattern(int p_pattern) { - - play_start(p_pattern,-1,-1); -} - -void CPPlayer::play_start_song() { - - play_start(-1,-1,-1); -} - -void CPPlayer::play_start_song_from_order(int p_order) { - - play_start(-1,p_order,-1); -} - -void CPPlayer::play_start_song_from_order_and_row(int p_order,int p_row) { - - play_start(-1,p_order,p_row); -} - -void CPPlayer::play_start(int p_pattern, int p_order, int p_row,bool p_lock) { - - - if (control.play_mode!=PLAY_NOTHING) play_stop(); - - - reset(); - - if (p_pattern!=-1) { - - control.play_mode=PLAY_PATTERN; - control.position.current_pattern=p_pattern; - control.position.current_row=(p_row!=-1)?p_row:0; - - } else { - - control.position.current_order=get_song_next_order_idx(song,(p_order==-1)?p_order:p_order-1); - if (control.position.current_order!=-1) { - - control.play_mode=PLAY_SONG; - control.position.current_pattern=song->get_order(control.position.current_order); - control.position.current_row=(p_row!=-1)?p_row:0; - } - } - - - control.reached_end=(control.play_mode==PLAY_NOTHING); - - -} - -void CPPlayer::play_stop() { - - int i; - - - control.play_mode=PLAY_NOTHING; - - for (i=0;istop_voice(i); - } - - for (i=0;iget_channel_volume(p_channel); - control.channel[p_channel].channel_panning=((int)song->get_channel_pan( p_channel)*255/64);*/ - if (p_reserve) { - control.channel[p_channel].mute=false; - control.channel[p_channel].reserved=true; - } else { - - control.channel[p_channel].reserved=false; - - } - process_note(p_channel,note); - - - -} - - -int CPPlayer::get_voice_volume(int p_voice) { - - return voice[p_voice].display_volume; -} - - -int CPPlayer::get_voice_envelope_pos(int p_voice,CPEnvelope *p_envelope) { - - int i,tmp_index=-1; - - i=p_voice; - - - - - if ((song->has_instruments()) && (voice[i].instrument_ptr!=NULL) && (voice[i].fadeout_volume>0)) { - - if ((p_envelope==voice[i].instrument_ptr->get_volume_envelope()) && (voice[i].instrument_ptr->get_volume_envelope()->is_enabled())) { - - tmp_index=voice[i].volume_envelope_ctrl.pos_index; - } - - if ((p_envelope==voice[i].instrument_ptr->get_pan_envelope()) && (voice[i].instrument_ptr->get_pan_envelope()->is_enabled())) { - - tmp_index=voice[i].panning_envelope_ctrl.pos_index; - } - - if ((p_envelope==voice[i].instrument_ptr->get_pitch_filter_envelope()) && (voice[i].instrument_ptr->get_pitch_filter_envelope()->is_enabled())) { - - - tmp_index=voice[i].pitch_envelope_ctrl.pos_index; - } - - } - - - - return tmp_index; -} - -void CPPlayer::goto_next_order() { - - - if (control.play_mode!=PLAY_SONG) return; - - - - control.position.current_row=0; - - - control.position.current_order=get_song_next_order_idx(song, control.position.current_order); - - - - if (control.position.current_order==-1) { - - reset(); - } - - control.position.current_pattern=song->get_order(control.position.current_order); - - -} -void CPPlayer::goto_previous_order() { - - if (control.play_mode!=PLAY_SONG) return; - - - int next_order,current_order; - - control.position.current_row=0; - - current_order=control.position.current_order; - - next_order=get_song_next_order_idx(song, current_order); - - while ((next_order!=control.position.current_order) && (next_order!=-1)) { - - current_order=next_order; - next_order=get_song_next_order_idx(song, current_order); - } - - if (next_order==-1) { - - reset(); - } else { - - control.position.current_order=current_order; - control.position.current_pattern=song->get_order(control.position.current_order); - - } - - - -} - -int CPPlayer::get_channel_voice(int p_channel) { - - if (control.channel[p_channel].slave_voice==NULL) return -1; - else return control.channel[p_channel].slave_voice_index; -} - -const char* CPPlayer::get_voice_sample_name(int p_voice) { - - const char *name = NULL; - - - - if (!voice[p_voice].sample_ptr) name=voice[p_voice].sample_ptr->get_name(); - - - - return name; - -} - - -bool CPPlayer::is_voice_active(int p_voice) { - - return !( ((voice[p_voice].kick==KICK_NOTHING)||(voice[p_voice].kick==KICK_ENVELOPE))&&!mixer->is_voice_active(p_voice) ); - -} - - - -int CPPlayer::get_voice_envelope_pos(int p_voice,CPInstrument::EnvelopeType p_env_type) { - - if (!is_voice_active(p_voice)) - return -1; - - Voice_Control::Envelope_Control *env=0; - - switch (p_env_type) { - - case CPInstrument::VOLUME_ENVELOPE: env=&voice[p_voice].volume_envelope_ctrl; break; - case CPInstrument::PAN_ENVELOPE: env=&voice[p_voice].panning_envelope_ctrl; break; - case CPInstrument::PITCH_ENVELOPE: env=&voice[p_voice].pitch_envelope_ctrl; break; - - } - - if (!env) - return -1; - - if (!env->active || env->terminated) - return -1; - - return env->pos_index; -} - - -CPEnvelope* CPPlayer::get_voice_envelope(int p_voice,CPInstrument::EnvelopeType p_env_type) { - - CPInstrument *ins=voice[p_voice].instrument_ptr; - - if (!ins) - return 0; - - switch( p_env_type ) { - - - case CPInstrument::VOLUME_ENVELOPE: return ins->get_volume_envelope(); - case CPInstrument::PAN_ENVELOPE: return ins->get_pan_envelope(); - case CPInstrument::PITCH_ENVELOPE: return ins->get_pitch_filter_envelope(); - }; - - return 0; - -} - -const char * CPPlayer::get_voice_instrument_name(int p_voice) { - - - - const char *name = NULL; - - - - if (voice[p_voice].instrument_ptr!=NULL) name=voice[p_voice].instrument_ptr->get_name(); - - - - return name; - -} -void CPPlayer::set_filters_enabled(bool p_enable){ - - control.filters=p_enable; -} - -int CPPlayer::get_voice_sample_index(int p_voice) { - - return voice[p_voice].sample_index; -} diff --git a/drivers/chibi/cp_player_data_effects.cpp b/drivers/chibi/cp_player_data_effects.cpp deleted file mode 100644 index 3a52a3b91b..0000000000 --- a/drivers/chibi/cp_player_data_effects.cpp +++ /dev/null @@ -1,1232 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_effects.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" - - - -/********************** - complex effects -***********************/ -#define RANDOM_MAX 2147483647 - -static inline int32_t cp_random_generate(int32_t *seed) { - int32_t k; - int32_t s = (int32_t)(*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - (*seed) = (int32_t)s; - return (int32_t)(s & RANDOM_MAX); -} - - - -void CPPlayer::do_vibrato(int p_track,bool fine) { - - uint8_t q; - uint16_t temp=0; - - if ((control.ticks_counter==0) && control.channel[p_track].row_has_note) control.channel[p_track].vibrato_position=0; - - q=(control.channel[p_track].vibrato_position>>2)&0x1f; - - switch (control.channel[p_track].vibrato_type) { - case 0: /* sine */ - temp=vibrato_table[q]; - break; - case 1: /* square wave */ - temp=255; - break; - case 2: /* ramp down */ - q<<=3; - if (control.channel[p_track].vibrato_position<0) q=255-q; - temp=q; - break; - case 3: /* random */ - temp=cp_random_generate(&control.random_seed) %256;//getrandom(256); - break; - } - - temp*=control.channel[p_track].vibrato_depth; - - if (song->has_old_effects()) { - - temp>>=7; - } else { - - temp>>=8; - } - - if (!fine) temp<<=2; - - if (control.channel[p_track].vibrato_position>=0) { - - control.channel[p_track].period=control.channel[p_track].aux_period+temp; - } else { - - control.channel[p_track].period=control.channel[p_track].aux_period-temp; - } - - if (!song->has_old_effects() || control.ticks_counter) control.channel[p_track].vibrato_position+=control.channel[p_track].vibrato_speed; -} - - -void CPPlayer::do_pitch_slide_down(int p_track,uint8_t inf) { - - uint8_t hi,lo; - - if (inf) control.channel[p_track].pitch_slide_info=inf; - else inf=control.channel[p_track].pitch_slide_info; - - hi=inf>>4; - lo=inf&0xf; - - if (hi==0xf) { - - if (!control.ticks_counter) control.channel[p_track].aux_period+=(uint16_t)lo<<2; - } else if (hi==0xe) { - - if (!control.ticks_counter) control.channel[p_track].aux_period+=lo; - } else { - - if (control.ticks_counter) control.channel[p_track].aux_period+=(uint16_t)inf<<2; - } -} - -void CPPlayer::do_pitch_slide_up(int p_track,uint8_t inf) { - - uint8_t hi,lo; - - if (inf) control.channel[p_track].pitch_slide_info=inf; - else inf=control.channel[p_track].pitch_slide_info; - - hi=inf>>4; - lo=inf&0xf; - - if (hi==0xf) { - - if (!control.ticks_counter) control.channel[p_track].aux_period-=(uint16_t)lo<<2; - } else if (hi==0xe) { - - if (!control.ticks_counter) control.channel[p_track].aux_period-=lo; - } else { - - if (control.ticks_counter) control.channel[p_track].aux_period-=(uint16_t)inf<<2; - } -} - -void CPPlayer::do_pitch_slide_to_note(int p_track) { - - if (control.ticks_counter) { - int dist; - - /* We have to slide a->period towards a->wantedperiod, compute the - difference between those two values */ - dist=control.channel[p_track].period-control.channel[p_track].slide_to_period; - - /* if they are equal or if portamentospeed is too big... */ - if ((!dist)||((control.channel[p_track].portamento_speed<<2)>cp_intabs(dist))) { - /* ... make tmpperiod equal tperiod */ - control.channel[p_track].aux_period=control.channel[p_track].period=control.channel[p_track].slide_to_period; - } else { - - if (dist>0) { - - control.channel[p_track].aux_period-=control.channel[p_track].portamento_speed<<2; - control.channel[p_track].period-=control.channel[p_track].portamento_speed<<2; /* dist>0 slide up */ - } else { - control.channel[p_track].aux_period+=control.channel[p_track].portamento_speed<<2; - control.channel[p_track].period+=control.channel[p_track].portamento_speed<<2; /* dist<0 slide down */ - } - } - - } else { - - control.channel[p_track].aux_period=control.channel[p_track].period; - } -} - -void CPPlayer::do_tremor(int p_track) { - - uint8_t on,off,inf; - - inf=control.channel[p_track].current_parameter; - - if (inf) { - control.channel[p_track].tremor_info=inf; - } else { - inf= control.channel[p_track].tremor_info; - if (!inf) return; - } - - //if (!control.ticks_counter) return; - - on=(inf>>4); - off=(inf&0xf); - - control.channel[p_track].tremor_position%=(on+off); - control.channel[p_track].volume=(control.channel[p_track].tremor_position>4; - - pan=(control.channel[p_track].panning==PAN_SURROUND)?PAN_CENTER:control.channel[p_track].panning; - - if (!hi) - pan+=lo<<2; - else - if (!lo) { - pan-=hi<<2; - } else - if (hi==0xf) { - if (!control.ticks_counter) pan+=lo<<2; - } else - if (lo==0xf) { - if (!control.ticks_counter) pan-=hi<<2; - } - //this sets both chan & voice paning - control.channel[p_track].panning=(panPAN_RIGHT?PAN_RIGHT:pan); - control.channel[p_track].channel_panning=control.channel[p_track].panning; -} - -void CPPlayer::do_volume_slide(int p_track,int inf) { - - uint8_t hi,lo; - - lo=inf&0xf; - hi=inf>>4; - - if (!lo) { - - if ((control.ticks_counter)) control.channel[p_track].aux_volume+=hi; - - } else if (!hi) { - - if ((control.ticks_counter)) control.channel[p_track].aux_volume-=lo; - - } else if (lo==0xf) { - - if (!control.ticks_counter) control.channel[p_track].aux_volume+=(hi?hi:0xf); - } else if (hi==0xf) { - - if (!control.ticks_counter) control.channel[p_track].aux_volume-=(lo?lo:0xf); - } else return; - - if (control.channel[p_track].aux_volume<0) { - - control.channel[p_track].aux_volume=0; - } else if (control.channel[p_track].aux_volume>64) { - - control.channel[p_track].aux_volume=64; - } -} - -void CPPlayer::do_channel_volume_slide(int p_track) { - - uint8_t lo, hi,inf; - - inf=control.channel[p_track].current_parameter; - - if (inf) control.channel[p_track].channel_volume_slide_info=inf; - inf=control.channel[p_track].channel_volume_slide_info; - - lo=inf&0xf; - hi=inf>>4; - - if (!hi) - control.channel[p_track].channel_volume-=lo; - else - if (!lo) { - control.channel[p_track].channel_volume+=hi; - } else - if (hi==0xf) { - if (!control.ticks_counter) control.channel[p_track].channel_volume-=lo; - } else - if (lo==0xf) { - if (!control.ticks_counter) control.channel[p_track].channel_volume+=hi; - } - - if (control.channel[p_track].channel_volume<0) control.channel[p_track].channel_volume=0; - if (control.channel[p_track].channel_volume>64) control.channel[p_track].channel_volume=64; -} - -void CPPlayer::do_tremolo(int p_track) { - - uint8_t q; - int16_t temp=0; - - if ((control.ticks_counter==0) && control.channel[p_track].row_has_note) control.channel[p_track].tremolo_position=0; - - q=(control.channel[p_track].tremolo_position>>2)&0x1f; - - switch (control.channel[p_track].tremolo_type) { - case 0: /* sine */ - temp=vibrato_table[q]; - break; - case 1: /* ramp down */ - q<<=3; - if (control.channel[p_track].tremolo_position<0) q=255-q; - temp=q; - break; - case 2: /* square wave */ - temp=255; - break; - case 3: /* random */ - temp=cp_random_generate(&control.random_seed) % 256;//getrandom(256); - break; - } - - temp*=control.channel[p_track].tremolo_depth; - temp>>=7; - - - - if (control.channel[p_track].tremolo_position>=0) { - - - control.channel[p_track].volume=control.channel[p_track].aux_volume+temp; - if (control.channel[p_track].volume>64) control.channel[p_track].volume=64; - } else { - - control.channel[p_track].volume=control.channel[p_track].aux_volume-temp; - if (control.channel[p_track].volume<0) control.channel[p_track].volume=0; - } - - /*if (control.ticks_counter)*/ control.channel[p_track].tremolo_position+=control.channel[p_track].tremolo_speed; - -} - -void CPPlayer::do_arpegio(int p_track) { - - uint8_t note,dat; - //note=control.channel[p_track].note; - note=0; - - if (control.channel[p_track].current_parameter) { - - control.channel[p_track].arpegio_info=control.channel[p_track].current_parameter; - } - - dat=control.channel[p_track].arpegio_info; - - if (dat) { - - switch (control.ticks_counter%3) { - - case 1: { - - note+=(dat>>4); - - } break; - case 2: { - - note+=(dat&0xf); - } break; - } - - if (song->has_linear_slides()) { - - control.channel[p_track].period=control.channel[p_track].aux_period-cp_intabs(get_period((uint16_t)46,0)-get_period((uint16_t)44,0))*note; - } else if (control.channel[p_track].sample_ptr) { - - control.channel[p_track].period=get_period( (((uint16_t)control.channel[p_track].note)+note)<<1,CPSampleManager::get_singleton()->get_c5_freq( (control.channel[p_track].sample_ptr->get_sample_data()))); - } - - control.channel[p_track].has_own_period=true; - } - - -} - - -void CPPlayer::do_retrig(int p_track) { - - uint8_t inf; - - inf=control.channel[p_track].current_parameter; - - if (inf) { - - control.channel[p_track].retrig_volslide=inf>>4; - control.channel[p_track].retrig_speed=inf&0xf; - } - - /* only retrigger if low nibble > 0 */ - if ( control.channel[p_track].retrig_speed>0) { - - if ( !control.channel[p_track].retrig_counter ) { - /* when retrig counter reaches 0, reset counter and restart the - sample */ - if (control.channel[p_track].kick!=KICK_NOTE) control.channel[p_track].kick=KICK_NOTEOFF; - control.channel[p_track].retrig_counter=control.channel[p_track].retrig_speed; - - - if ((control.ticks_counter)/*||(pf->flags&UF_S3MSLIDES)*/) { - switch (control.channel[p_track].retrig_volslide) { - case 1: - case 2: - case 3: - case 4: - case 5: - control.channel[p_track].aux_volume-=(1<<(control.channel[p_track].retrig_volslide-1)); - break; - case 6: - control.channel[p_track].aux_volume=(2*control.channel[p_track].aux_volume)/3; - break; - case 7: - control.channel[p_track].aux_volume>>=1; - break; - case 9: - case 0xa: - case 0xb: - case 0xc: - case 0xd: - control.channel[p_track].aux_volume+=(1<<(control.channel[p_track].retrig_volslide-9)); - break; - case 0xe: - control.channel[p_track].aux_volume=(3*control.channel[p_track].aux_volume)>>1; - break; - case 0xf: - control.channel[p_track].aux_volume=control.channel[p_track].aux_volume<<1; - break; - } - if (control.channel[p_track].aux_volume<0) control.channel[p_track].aux_volume=0; - else if (control.channel[p_track].aux_volume>64) control.channel[p_track].aux_volume=64; - } - } - control.channel[p_track].retrig_counter--; /* countdown */ - } -} - -void CPPlayer::do_global_volume_slide(int p_track) { - - uint8_t lo,hi,inf; - - inf=control.channel[p_track].current_parameter; - - if (inf) control.channel[p_track].global_volume_slide_info=inf; - inf=control.channel[p_track].global_volume_slide_info; - - lo=inf&0xf; - hi=inf>>4; - - if (!lo) { - if (control.ticks_counter) control.global_volume+=hi; - } else - if (!hi) { - if (control.ticks_counter) control.global_volume-=lo; - } else - if (lo==0xf) { - if (!control.ticks_counter) control.global_volume+=hi; - } else - if (hi==0xf) { - if (!control.ticks_counter) control.global_volume-=lo; - } - - if (control.global_volume<0) control.global_volume=0; - if (control.global_volume>128) control.global_volume=128; -} - -void CPPlayer::do_panbrello(int p_track) { - - uint8_t q; - int32_t temp=0; - - q=control.channel[p_track].panbrello_position; - - switch (control.channel[p_track].panbrello_type) { - case 0: {/* sine */ - temp=panbrello_table[q]; - } break; - case 1: {/* square wave */ - temp=(q<0x80)?64:0; - } break; - case 2: {/* ramp down */ - q<<=3; - temp=q; - } break; - case 3: {/* random */ - if (control.channel[p_track].panbrello_position>=control.channel[p_track].panbrello_speed) { - control.channel[p_track].panbrello_position=0; - temp=cp_random_generate(&control.random_seed)%256;//getrandom(256); - } - } break; - } - - - - temp=temp*(int)control.channel[p_track].panbrello_depth/0xF; - temp<<=1; - if (control.channel[p_track].channel_panning!=PAN_SURROUND) - temp+=control.channel[p_track].channel_panning; - - control.channel[p_track].panning=(tempPAN_RIGHT?PAN_RIGHT:temp); - control.channel[p_track].panbrello_position+=control.channel[p_track].panbrello_speed; -} - -/****************** - S effect -*******************/ - - -void CPPlayer::do_effect_S(int p_track) { - - uint8_t inf,c,dat; - - dat=control.channel[p_track].current_parameter; - - inf=dat&0xf; - c=dat>>4; - - if (!dat) { - c=control.channel[p_track].current_S_effect; - inf=control.channel[p_track].current_S_data; - } else { - control.channel[p_track].current_S_effect=c; - control.channel[p_track].current_S_data=inf; - } - - switch (c) { - case 1: {/* S1x set glissando voice */ - // this is unsupported in IT! - - control.channel[p_track].chorus_send=inf*0xFF/0xF; - - }break; - case 2: /* S2x set finetune */ - //Also not supported! - break; - case 3: /* S3x set vibrato waveform */ - if (inf<4) control.channel[p_track].vibrato_type=inf; - break; - case 4: /* S4x set tremolo waveform */ - if (inf<4) control.channel[p_track].tremolo_type=inf; - break; - case 5: /* S5x panbrello */ - if (inf<4) control.channel[p_track].panbrello_type=inf; - break; - case 6: {/* S6x delay x number of frames (patdly) */ - - if (control.ticks_counter) break; - if (!control.pattern_delay_2) control.pattern_delay_1=inf+1; /* only once, when vbtick=0 */ - - } break; - case 7: /* S7x instrument / NNA commands */ - - if (!song->has_instruments()) - break; - switch(inf) { - - case 0x3: { - - control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_CUT; - } break; - case 0x4: { - - control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_CONTINUE; - } break; - case 0x5: { - - control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_OFF; - } break; - case 0x6: { - - control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_FADE; - } break; - case 0x7: { - - if (control.channel[p_track].slave_voice) - control.channel[p_track].slave_voice->volume_envelope_ctrl.active=false; - } break; - case 0x8: { - - if (control.channel[p_track].slave_voice) - control.channel[p_track].slave_voice->volume_envelope_ctrl.active=true; - - } break; - case 0x9: { - - if (control.channel[p_track].slave_voice) - control.channel[p_track].slave_voice->panning_envelope_ctrl.active=false; - - } break; - case 0xA: { - - if (control.channel[p_track].slave_voice) - control.channel[p_track].slave_voice->panning_envelope_ctrl.active=true; - - } break; - case 0xB: { - if (control.channel[p_track].slave_voice) - control.channel[p_track].slave_voice->pitch_envelope_ctrl.active=false; - - } break; - case 0xC: { - - if (control.channel[p_track].slave_voice) - control.channel[p_track].slave_voice->pitch_envelope_ctrl.active=true; - - } break; - - } break; - - break; - case 8: {/* S8x set panning position */ - -// if (pf->panflag) { - if (inf<=8) inf<<=4; - else inf*=17; - control.channel[p_track].panning=control.channel[p_track].channel_panning=inf; -// } - } break; - - case 9: { /* S9x set surround sound */ - //if (pf->panflag) - control.channel[p_track].panning=control.channel[p_track].channel_panning=PAN_SURROUND; - } break; - case 0xA:{ /* SAy set high order sample offset yxx00h */ - - if (control.channel[p_track].current_parameter) control.channel[p_track].hi_offset=(int32_t)inf<<16; - control.channel[p_track].sample_start_index=control.channel[p_track].hi_offset|control.channel[p_track].lo_offset; - } break; - case 0xB: { /* SBx pattern loop */ - if (control.ticks_counter) break; - - if (inf) { /* set reppos or repcnt ? */ - /* set repcnt, so check if repcnt already is set, which means we - are already looping */ - if (control.channel[p_track].pattern_loop_count>0) - control.channel[p_track].pattern_loop_count--; /* already looping, decrease counter */ - else { - control.channel[p_track].pattern_loop_count=inf; /* not yet looping, so set repcnt */ - } - - if (control.channel[p_track].pattern_loop_count>0) { /* jump to reppos if repcnt>0 */ - - control.position=control.previous_position; // This will also anulate any Cxx or break.. - - control.position.current_row=control.channel[p_track].pattern_loop_position; - control.position.forbid_jump=true; - } - - } else { - - - control.channel[p_track].pattern_loop_position=control.position.current_row-1; - } - - } break; - case 0xC: { /* SCx notecut */ - - if (control.ticks_counter>=inf) { - - control.channel[p_track].aux_volume=0; - control.channel[p_track].note_end_flags|=END_NOTE_OFF; - control.channel[p_track].note_end_flags|=END_NOTE_KILL; - } - } break; - case 0xD: {/* SDx notedelay */ - - if (!control.ticks_counter) { - - control.channel[p_track].note_delay=inf; - - } else if (control.channel[p_track].note_delay) { - - control.channel[p_track].note_delay--; - } - - } break; - case 0xF: {/* SEx patterndelay */ - - if (control.ticks_counter) break; - if (!control.pattern_delay_2) control.pattern_delay_1=inf+1; /* only once, when vbtick=0 */ - - } break; - } -} - - - - - - - - -/********************* - volume effects -**********************/ - -void CPPlayer::run_volume_column_effects(int p_track) { - - uint8_t param=control.channel[p_track].current_volume_parameter; - - - switch ('A'+control.channel[p_track].current_volume_command) { - - case 'A': { - - if (param>0) control.channel[p_track].volcol_volume_slide=param; - else param=control.channel[p_track].volcol_volume_slide; - - do_volume_slide(p_track,param*0x10+0xF); - - } break; - case 'B': { - - if (param>0) control.channel[p_track].volcol_volume_slide=param; - else param=control.channel[p_track].volcol_volume_slide; - - do_volume_slide(p_track,0xF0+param); - - } break; - case 'C': { - - if (param>0) control.channel[p_track].volcol_volume_slide=param; - else param=control.channel[p_track].volcol_volume_slide; - - do_volume_slide(p_track,param*0x10); - } break; - case 'D': { - - if (param>0) control.channel[p_track].volcol_volume_slide=param; - else param=control.channel[p_track].volcol_volume_slide; - do_volume_slide(p_track,param); - - } break; - case 'E': { - - do_pitch_slide_down(p_track,param<<2); - } break; - case 'F': { - - do_pitch_slide_up(p_track,param<<2); - } break; - case 'G': { - - const uint8_t slide_table[]={0,1,4,8,16,32,64,96,128,255}; - if (param) { - - control.channel[p_track].portamento_speed=slide_table[param]; - } - - if (control.channel[p_track].period && (control.channel[p_track].old_note<=120)) { - - if ( (!control.ticks_counter) && (control.channel[p_track].new_instrument) ){ - - //control.channel[p_track].kick=KICK_NOTE; - //control.channel[p_track].sample_start_index=0; // < am i stupid? - } else { - - control.channel[p_track].kick=(control.channel[p_track].kick==KICK_NOTE)?KICK_ENVELOPE:KICK_NOTHING; - do_pitch_slide_to_note(p_track); - control.channel[p_track].has_own_period=true; - } - - } - } break; - case 'H': { - - - if (!control.ticks_counter) { - if (param&0x0f) control.channel[p_track].vibrato_depth=param; - } - control.channel[p_track].doing_vibrato=true; - if (control.external_vibrato) break; - if (control.channel[p_track].period) { - - do_vibrato(p_track,false); - control.channel[p_track].has_own_period=true; - } - - } break; - } -} -/********************* - table -**********************/ - - -void CPPlayer::run_effects(int p_track) { - - switch ('A'+control.channel[p_track].current_command) { - - case 'A': { - - if ((control.ticks_counter>0) || (control.pattern_delay_2>0)) break; - - int new_speed; - - new_speed=control.channel[p_track].current_parameter % 128; - - if (new_speed>0) { - control.speed=new_speed; - control.ticks_counter=0; - } - } break; - case 'B': { - - int next_order; - - if (control.ticks_counter || control.position.forbid_jump) break; - - control.position.current_row=0; - - if (control.play_mode==PLAY_PATTERN) break; - - next_order=get_song_next_order_idx(song, (int)control.channel[p_track].current_parameter-1); - - if (next_order!=-1) { - // Do we have a "next order?" - control.position.current_pattern=song->get_order(next_order); - control.position.force_next_order=next_order; - - } else { - // no, probably the user deleted the orderlist. - control.play_mode=PLAY_NOTHING; - reset(); - } - } break; - case 'C': { - - int next_order; - - if (control.ticks_counter || control.position.forbid_jump) break; - - control.position.current_row=control.channel[p_track].current_parameter; - - if (control.play_mode==PLAY_PATTERN) { - - if (control.position.current_row>=song->get_pattern(control.position.current_pattern)->get_length()) { - - control.position.current_row=0; - } - - break; - } - - next_order=get_song_next_order_idx(song, (int)control.position.current_order); - - if (next_order!=-1) { - // Do we have a "next order?" - control.position.current_pattern=song->get_order(next_order); - - if (control.position.current_row>=song->get_pattern(song->get_order(next_order))->get_length()) { - - control.position.current_row=0; - } - - control.position.force_next_order=next_order; - - } else { - // no, probably the user deleted the orderlist. - control.play_mode=PLAY_NOTHING; - reset(); - } - - } break; - case 'D': { - - uint8_t inf ; - //explicitslides=1; - inf=control.channel[p_track].current_parameter; - - if (inf) control.channel[p_track].volume_slide_info=inf; - else inf=control.channel[p_track].volume_slide_info; - - do_volume_slide(p_track,inf); - - } break; - case 'E': { - - uint8_t inf; - - inf=control.channel[p_track].current_parameter; - do_pitch_slide_down(p_track,inf); - - } break; - case 'F': { - - uint8_t inf; - - inf=control.channel[p_track].current_parameter; - do_pitch_slide_up(p_track,inf); - - } break; - case 'G': { - - if (control.channel[p_track].current_parameter) { - - control.channel[p_track].portamento_speed=control.channel[p_track].current_parameter; - } - - if (control.channel[p_track].period && (control.channel[p_track].old_note<=120)) { - - if ( (!control.ticks_counter) && (control.channel[p_track].new_instrument) ){ - - - control.channel[p_track].kick=KICK_NOTE; - control.channel[p_track].sample_start_index=0; - - } else { - - control.channel[p_track].kick=(control.channel[p_track].kick==KICK_NOTE)?KICK_ENVELOPE:KICK_NOTHING; - } - - do_pitch_slide_to_note(p_track); - control.channel[p_track].has_own_period=true; - } - - } break; - case 'H': { - - uint8_t dat; - - control.channel[p_track].doing_vibrato=true; - - dat=control.channel[p_track].current_parameter; - - if (!control.ticks_counter) { - if (dat&0x0f) control.channel[p_track].vibrato_depth=dat&0xf; - if (dat&0xf0) control.channel[p_track].vibrato_speed=(dat&0xf0)>>2; - } - - if (control.external_vibrato) break; - - if (control.channel[p_track].period) { - - do_vibrato(p_track,false); - control.channel[p_track].has_own_period=true; - } - - } break; - case 'I': { - - do_tremor(p_track); - control.channel[p_track].has_own_volume=true; - } break; - case 'J': { - - do_arpegio(p_track); - } break; - case 'K': { - - uint8_t inf ; - //explicitslides=1; - inf=control.channel[p_track].current_parameter; - - control.channel[p_track].doing_vibrato=true; - - - if (inf) control.channel[p_track].volume_slide_info=inf; - else inf=control.channel[p_track].volume_slide_info; - - do_volume_slide(p_track,inf); - - if (control.external_vibrato) break; - - if (control.channel[p_track].period) { - - do_vibrato(p_track,false); - control.channel[p_track].has_own_period=true; - } - - } break; - case 'L': { - uint8_t inf ; - //explicitslides=1; - inf=control.channel[p_track].current_parameter; - - if (inf) control.channel[p_track].volume_slide_info=inf; - else inf=control.channel[p_track].volume_slide_info; - - do_volume_slide(p_track,inf); - - if (control.channel[p_track].period && (control.channel[p_track].old_note<=120)) { - if ( (!control.ticks_counter) && (control.channel[p_track].new_instrument) ){ - - control.channel[p_track].kick=KICK_NOTE; - control.channel[p_track].sample_start_index=0; - - } else { - - control.channel[p_track].kick=(control.channel[p_track].kick==KICK_NOTE)?KICK_ENVELOPE:KICK_NOTHING; - } - - do_pitch_slide_to_note(p_track); - control.channel[p_track].has_own_period=true; - } - } break; - case 'M': { - control.channel[p_track].channel_volume=control.channel[p_track].current_parameter; - if (control.channel[p_track].channel_volume>64) control.channel[p_track].channel_volume=64; - else if (control.channel[p_track].channel_volume<0) control.channel[p_track].channel_volume=0; - } break; - case 'N': { - - do_channel_volume_slide(p_track); - } - case 'O': { - - if (!control.ticks_counter) { - - if (control.channel[p_track].current_parameter) control.channel[p_track].lo_offset=(uint16_t)control.channel[p_track].current_parameter<<8; - control.channel[p_track].sample_start_index=control.channel[p_track].hi_offset|control.channel[p_track].lo_offset; - - //if ((control.channel[p_track].sample_ptr!=NULL)&&(control.channel[p_track].sample_start_index>control.channel[p_track].sample_ptr->data.size)) { - //TODO, O effect - //a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length; - //} - } - } break; - case 'P': { - - do_pan_slide(p_track); - } break; - case 'Q': { - do_retrig(p_track); - - } break; - case 'R': { - - - uint8_t dat; - - if (control.channel[p_track].current_parameter) { - - control.channel[p_track].tremolo_info=control.channel[p_track].current_parameter; - } - - dat=control.channel[p_track].tremolo_info; - - if (!control.ticks_counter && dat) { - - if (dat&0x0f) control.channel[p_track].tremolo_depth=dat&0xf; - if (dat&0xf0) control.channel[p_track].tremolo_speed=(dat&0xf0)>>2; - } - - do_tremolo(p_track); - control.channel[p_track].has_own_volume=true; - - } break; - case 'S': { - - do_effect_S(p_track); - } break; - case 'T': { - uint8_t dat; - int16_t temp=control.tempo; - - if (control.pattern_delay_2) return; - - if (control.channel[p_track].current_parameter) { - - control.channel[p_track].tempo_slide_info=control.channel[p_track].current_parameter; - } - - dat=control.channel[p_track].tempo_slide_info; - - if (dat>=0x20) { - - if (control.ticks_counter) break; - control.tempo=dat; - } else { - - if (!control.ticks_counter) break; - - if (dat&0x10) { - - temp+=(dat&0x0f); - } else { - - temp-=dat; - } - control.tempo=(temp>255)?255:(temp<0x20?0x20:temp); - } - - } break; - case 'U': { - - uint8_t dat; - - dat=control.channel[p_track].current_parameter; - control.channel[p_track].doing_vibrato=true; - if (!control.ticks_counter) { - if (dat&0x0f) control.channel[p_track].vibrato_depth=dat&0xf; - if (dat&0xf0) control.channel[p_track].vibrato_speed=(dat&0xf0)>>2; - } - - if (control.external_vibrato) break; - - if (control.channel[p_track].period) { - - do_vibrato(p_track,true); - control.channel[p_track].has_own_period=true; - } - } break; - case 'V': { - - control.global_volume=control.channel[p_track].current_parameter; - if (control.global_volume>128) control.global_volume=128; - } break; - case 'W': { - do_global_volume_slide(p_track); - } break; - case 'X': { - //sets both channel and current - control.channel[p_track].channel_panning=control.channel[p_track].current_parameter; - control.channel[p_track].panning=control.channel[p_track].current_parameter; - } break; - case 'Y': { - - uint8_t dat; - - if (control.channel[p_track].current_parameter) { - - control.channel[p_track].panbrello_info=control.channel[p_track].current_parameter; - } - - dat=control.channel[p_track].panbrello_info; - - if (!control.ticks_counter) { - - if (dat&0x0f) control.channel[p_track].panbrello_depth=(dat&0xf); - if (dat&0xf0) control.channel[p_track].panbrello_speed=(dat&0xf0)>>4; - } - - //if (pf->panflag) - if (control.channel[p_track].panning!=PAN_SURROUND)do_panbrello(p_track); - - } break; - case 'Z': { - //I DO! cuttoff! - uint16_t dat=control.channel[p_track].current_parameter; - - if (dat<0x80) { - - control.channel[p_track].filter.it_cutoff=dat*2; - if (control.channel[p_track].filter.it_cutoff>0x80) - control.channel[p_track].filter.it_cutoff++; - } else if (dat<0x90) { - - control.channel[p_track].filter.it_reso=(dat-0x80)*0x10; - } else { - - control.channel[p_track].reverb_send=(dat-0x90)*255/0x6F; - } - - } break; - - } - -} - -void CPPlayer::pre_process_effects() { - -// MP_VOICE *aout; - int i; - - for (i=0;icontrol[mp_channel]; - - // if ((aout=a->slave)) { - // a->fadevol=aout->fadevol; - // a->period=aout->period; - // if (a->kick==KICK_KEYOFF) a->keyoff=aout->keyoff; - //} - - //if (!a->row) continue; - //UniSetRow(a->row); - control.channel[i].has_own_period=false; - control.channel[i].has_own_volume=false; - control.channel[i].doing_vibrato=false; - //explicitslides=0; - //pt_playeffects(); - if (control.ticks_counterflags&UF_BGSLIDES) { - // if (!explicitslides && a->sliding) - // DoS3MVolSlide(0); - // else if (a->tmpvolume) a->sliding=explicitslides; - //} - - if (!control.channel[i].has_own_period) control.channel[i].period=control.channel[i].aux_period; - if (!control.channel[i].has_own_volume) control.channel[i].volume=control.channel[i].aux_volume; - - if ((control.channel[i].sample_ptr!=NULL) && !(song->has_instruments() && (control.channel[i].instrument_ptr==NULL))) { - - if (song->has_instruments()) { - - control.channel[i].output_volume= - (control.channel[i].volume*control.channel[i].sample_ptr->get_global_volume()*control.channel[i].instrument_ptr->get_volume_global_amount())/2048; - control.channel[i].output_volume=control.channel[i].output_volume*control.channel[i].random_volume_variation/100; - - } else { - - control.channel[i].output_volume= - (control.channel[i].volume*control.channel[i].sample_ptr->get_global_volume())>>4; - - } - - if (control.channel[i].output_volume>256) { - - control.channel[i].output_volume=256; - - } else if (control.channel[i].output_volume<0) { - - control.channel[i].output_volume=0; - } - - - } - } - -} diff --git a/drivers/chibi/cp_player_data_envelopes.cpp b/drivers/chibi/cp_player_data_envelopes.cpp deleted file mode 100644 index 96af42d19f..0000000000 --- a/drivers/chibi/cp_player_data_envelopes.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_envelopes.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" - - -void CPPlayer::Voice_Control::start_envelope(CPEnvelope *p_envelope,Envelope_Control *p_envelope_ctrl,Envelope_Control *p_from_env) { - - - if (p_from_env && p_envelope->is_carry_enabled() && !p_from_env->terminated) { - - - *p_envelope_ctrl=*p_from_env; - } else { - p_envelope_ctrl->pos_index=0; - p_envelope_ctrl->status=1; - p_envelope_ctrl->sustain_looping=p_envelope->is_sustain_loop_enabled(); - p_envelope_ctrl->looping=p_envelope->is_loop_enabled(); - p_envelope_ctrl->terminated=false; - p_envelope_ctrl->kill=false; - p_envelope_ctrl->value=p_envelope->get_height_at_pos(p_envelope_ctrl->pos_index); - } -} - -bool CPPlayer::Voice_Control::process_envelope(CPEnvelope *p_envelope,Envelope_Control *p_envelope_ctrl) { - - if (!p_envelope_ctrl->active) - return false; - - if (note_end_flags&END_NOTE_OFF) p_envelope_ctrl->sustain_looping=false; - - p_envelope_ctrl->value=p_envelope->get_height_at_pos(p_envelope_ctrl->pos_index); - if (p_envelope_ctrl->value==CPEnvelope::NO_POINT) - return false; - - - p_envelope_ctrl->pos_index++; - - if (p_envelope_ctrl->sustain_looping) { - - if (p_envelope_ctrl->pos_index>p_envelope->get_node(p_envelope->get_sustain_loop_end()).tick_offset) { - - p_envelope_ctrl->pos_index=p_envelope->get_node(p_envelope->get_sustain_loop_begin()).tick_offset; - } - - } else if (p_envelope_ctrl->looping) { - - if (p_envelope_ctrl->pos_index>p_envelope->get_node(p_envelope->get_loop_end()).tick_offset) { - - p_envelope_ctrl->pos_index=p_envelope->get_node(p_envelope->get_loop_begin()).tick_offset; - } - - } - - if (p_envelope_ctrl->pos_index>p_envelope->get_node(p_envelope->get_node_count()-1).tick_offset) { - - p_envelope_ctrl->terminated=true; - p_envelope_ctrl->pos_index=p_envelope->get_node(p_envelope->get_node_count()-1).tick_offset; - if (p_envelope->get_node(p_envelope->get_node_count()-1).value==0) p_envelope_ctrl->kill=true; - } - - return true; -} diff --git a/drivers/chibi/cp_player_data_events.cpp b/drivers/chibi/cp_player_data_events.cpp deleted file mode 100644 index fb5090461b..0000000000 --- a/drivers/chibi/cp_player_data_events.cpp +++ /dev/null @@ -1,679 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_events.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" -#include "cp_sample_manager.h" -#include "stdio.h" -/* - setup_voices(): - -This will go throught all the REAL channels, if it finds a channel -that needs to be restarted or assigned a new VIRTUAL channel, then it -will just find one and do it. - -*/ - - -#define C5FREQ 261.6255653006 -static const int32_t C5FREQ_MIXER = ((int32_t)(C5FREQ*(float)(1<has_instruments() && !control.force_no_nna) { - - if (control.channel[i].slave_voice==NULL) { // no slave?? - - int newchn; - if ((newchn=find_empty_voice())!=-1) { - - control.channel[i].slave_voice_index=newchn; - control.channel[i].slave_voice=&voice[newchn]; - } - } - - } else { - if (islave_voice=NULL; - - } - //notify the voice that the current channel is the master - v.master_channel=&control.channel[i]; - //set the voice as slave of the current channel - control.channel[i].slave_voice=&v; - //master channel index of the voice - v.master_channel_index=i; - v.has_master_channel=true; - } - - } else { - // nope.. - // so if we DO have a slave voice then use it. - if ( control.channel[i].slave_voice!=NULL ) { - - voice_index=control.channel[i].slave_voice_index; - } - } - //assuming this channel has a slave voice.. - if (voice_index>=0) { - - // IMPROVE: Code a method for this: - voice[voice_index].update_info_from_master_channel(); - } - - control.channel[i].kick=KICK_NOTHING; - } -} -void CPPlayer::Voice_Control::reset() { - - cp_memzero(this,sizeof(*this)); - - instrument_ptr=NULL; - sample_ptr=NULL; - has_master_channel=false; - instrument_index=-1; - reverb_send=0; - chorus_send=0; - filter.it_cutoff=255; - filter.it_reso=0; - display_volume=0; - - -} - -void CPPlayer::Channel_Control::reset() { - - int prev_gv =channel_global_volume; - cp_memzero(this,sizeof(*this)); - - slave_voice=NULL; - slave_voice_index=255; - - mute=false; - old_note=255; - real_note=255; - instrument_index=255; - filter.it_cutoff=255; - filter.it_reso=0; - reverb_send=0; - chorus_send=0; - reserved=false; - carry.maybe=false; - last_event_usecs=-1; - channel_global_volume=prev_gv; -} - -void CPPlayer::Voice_Control::update_info_from_master_channel() { - - instrument_ptr=master_channel->instrument_ptr; - sample_ptr=master_channel->sample_ptr; - - instrument_index=master_channel->instrument_index; - sample_index=master_channel->sample_index; - - note=master_channel->note; - output_volume=master_channel->output_volume; - - channel_volume=master_channel->channel_volume; - - panning=master_channel->panning; - - kick=master_channel->kick; - note_end_flags=master_channel->note_end_flags; - period=master_channel->period; - - volume_envelope_ctrl.active=master_channel->volume_envelope_on; - panning_envelope_ctrl.active=master_channel->panning_envelope_on; - pitch_envelope_ctrl.active=master_channel->pitch_envelope_on; - - - NNA_type=master_channel->NNA_type; - reverb_send=master_channel->reverb_send; - chorus_send=master_channel->chorus_send; - -// last_note_type=master_channel->last_note_type; - - sample_start_index=master_channel->sample_start_index; - filter=master_channel->filter; - -} - - -void CPPlayer::update_mixer() { - - int tmp_mixer_period; - int32_t tmp_vibrato_value,tmp_vibrato_depth,tmp_volenv_value; - uint64_t tmpvol; // 64bits should be the only way to avoid getting notes raped out - int i; - - - control.voices_used=0; - - for (i=0;i50000) { - - v.period=50000; - } - - - if ((v.kick==KICK_NOTE)||(v.kick==KICK_NOTEOFF)) { - - int real_start_index; - - if (v.sample_start_index==-1) { - - real_start_index=0; - - } else { - - real_start_index=v.sample_start_index; - } - - mixer->setup_voice(i,v.sample_ptr->get_sample_data(),real_start_index); - v.fadeout_volume=1024; //IT Docs it is 1024 internally - v.auto_vibrato_sweep_pos=0; - - - - } - - - /* Start Envelopes */ - if ( song->has_instruments() && ((v.kick==KICK_NOTE)||(v.kick==KICK_ENVELOPE))) { - -// Voice_Control *carry=0; - - - if (v.has_master_channel && v.master_channel->carry.maybe) { - - v.start_envelope(v.instrument_ptr->get_volume_envelope(),&v.volume_envelope_ctrl,&v.master_channel->carry.vol); - v.start_envelope(v.instrument_ptr->get_pan_envelope(),&v.panning_envelope_ctrl,&v.master_channel->carry.pan); - v.start_envelope(v.instrument_ptr->get_pitch_filter_envelope(),&v.pitch_envelope_ctrl,&v.master_channel->carry.pitch); - - } else { - - v.start_envelope(v.instrument_ptr->get_volume_envelope(),&v.volume_envelope_ctrl,NULL); - v.start_envelope(v.instrument_ptr->get_pan_envelope(),&v.panning_envelope_ctrl,NULL); - v.start_envelope(v.instrument_ptr->get_pitch_filter_envelope(),&v.pitch_envelope_ctrl,NULL); - - } - - - } - - v.kick=KICK_NOTHING; - - if (song->has_instruments()) { - - if (!v.process_envelope(v.instrument_ptr->get_volume_envelope(),&v.volume_envelope_ctrl)) - v.volume_envelope_ctrl.value=64; - - if (!v.process_envelope(v.instrument_ptr->get_pan_envelope(),&v.panning_envelope_ctrl)) - v.panning_envelope_ctrl.value=0; - - if (!v.process_envelope(v.instrument_ptr->get_pitch_filter_envelope(),&v.pitch_envelope_ctrl)) - v.pitch_envelope_ctrl.value=0; - - - if (v.volume_envelope_ctrl.terminated) { - - if (v.volume_envelope_ctrl.kill) { - - v.fadeout_volume=0; - } else { - - v.note_end_flags|=END_NOTE_FADE; - } - } - - } - - if (song->has_instruments()) { - - tmp_volenv_value=v.volume_envelope_ctrl.value; - } else { - - tmp_volenv_value=64; - - } - - /*printf("fadeout %i\n",(int)v.fadeout_volume); - printf("channel %i\n",(int)v.channel_volume); - printf("output %i\n",(int)v.output_volume); - printf("env %i\n",(int)tmp_volenv_value); - printf("cgb %i\n",(int)v.master_channel->channel_global_volume); -*/ - - - tmpvol=(uint64_t)v.fadeout_volume; /* max 1024 - 10 bits */ - tmpvol*=(uint64_t)v.channel_volume; /* * max 64 - 6 bits */ - tmpvol*=(uint64_t)v.output_volume; /* * max 256 - 8 bits */ - tmpvol*=(uint64_t)tmp_volenv_value; /* max 64 - 6 bits*/ - tmpvol*=(uint64_t)v.master_channel->channel_global_volume; - v.display_volume=tmpvol>>22; //volume used for display purposes , 0 -- 256 - - tmpvol*=(uint64_t)song->get_mixing_volume(); /* max 128 - 7 bits */ - tmpvol*=(uint64_t)control.global_volume; /* max 128 - 7 bits*/ - /* total 10+6+8+6+7+7=44 bits */ - - tmpvol>>=43; /* Move back to 8 bits range , 44-19+8=43*/ - - if (tmpvol>CP_VOL_MAX) - tmpvol=CP_VOL_MAX; - - //printf("volume check - fade %i, channel %i, output %i, env %i, mix %i, global %i -- final %i\n",v.fadeout_volume, v.channel_volume,v.output_volume,tmp_volenv_value, song->get_mixing_volume(),control.global_volume,tmpvol); - - v.total_volume=tmpvol; - - - if ((v.master_channel!=NULL) && song->is_channel_mute( v.master_channel_index ) && !v.master_channel->reserved) { - - mixer->set_voice_volume(i,0); - } else { - mixer->set_voice_volume(i,tmpvol); - if (v.fadeout_volume>0) control.voices_used++; - } - - - if (!song->is_stereo()) { - - mixer->set_voice_panning(i,PAN_CENTER); - - } else if (v.panning==PAN_SURROUND) { - - mixer->set_voice_panning(i,PAN_SURROUND); - } else if (song->has_instruments()) { - - int newpan,real_modifier; - - - real_modifier=(v.panning_envelope_ctrl.value*(PAN_CENTER-cp_intabs(v.panning-PAN_CENTER)))/32; - - newpan=v.panning+real_modifier; - - newpan=(newpanPAN_RIGHT)?PAN_RIGHT:newpan; - //printf("panenv val: %i, finalpan val %i\n",v.panning_envelope_ctrl.value,newpan); - - mixer->set_voice_panning(i,newpan); - } else { - mixer->set_voice_panning(i,v.panning); - } - - - - /* VIBRATO */ - - if ( (v.period>0) && (v.sample_ptr->get_vibrato_depth()>0) ) { - - switch (v.sample_ptr->get_vibrato_type()) { - case CPSample::VIBRATO_SINE: - tmp_vibrato_value=auto_vibrato_table[v.auto_vibrato_pos&127]; - if (v.auto_vibrato_pos & 0x80) tmp_vibrato_value=-tmp_vibrato_value; - break; - case CPSample::VIBRATO_SQUARE: - tmp_vibrato_value=64; - if (v.auto_vibrato_pos & 0x80) tmp_vibrato_value=-tmp_vibrato_value; - break; - case CPSample::VIBRATO_SAW: - tmp_vibrato_value=63-(((v.auto_vibrato_pos+128)&255)>>1); - break; - default: - tmp_vibrato_value=(((v.auto_vibrato_pos+128)&255)>>1)-64; - break; - } - } else { - - tmp_vibrato_value=0; - } - - if ((v.auto_vibrato_sweep_pos>>8)get_vibrato_depth()) { - - v.auto_vibrato_sweep_pos+=v.sample_ptr->get_vibrato_speed(); //FIXME - speed? i think so - tmp_vibrato_depth=v.auto_vibrato_sweep_pos; - - } else { - - tmp_vibrato_depth=v.sample_ptr->get_vibrato_depth()<<8; - } - - tmp_vibrato_value=(tmp_vibrato_value*tmp_vibrato_depth)>>16; - if (song->has_linear_slides()) - tmp_vibrato_value>>=1; - v.period-=tmp_vibrato_value; - - - /* update vibrato position */ - v.auto_vibrato_pos=(v.auto_vibrato_pos+v.sample_ptr->get_vibrato_rate())&0xff; - - - /* process pitch envelope */ - tmp_mixer_period=v.period; - - if (v.pitch_envelope_ctrl.active) { - - long aux_pitch_diff; - int pe_value=v.pitch_envelope_ctrl.value; - - if (!v.instrument_ptr->is_pitch_use_as_filter()) { - - - if (((uint16_t)v.note<<1)+pe_value<=0) - pe_value=-(v.note<<1); - - int smp_c5=CPSampleManager::get_singleton()->get_c5_freq( v.sample_ptr->get_sample_data()); - - int base=get_period(((uint16_t)v.note<<1),smp_c5); - int env=get_period(((uint16_t)v.note<<1)+pe_value,smp_c5); - /* - int env_next=(pe_value<0)?get_period(((uint16_t)(v.note-1)<<1)+pe_value,smp_c5):get_period(((uint16_t)(v.note+1)<<1)+pe_value,smp_c5); - - env=env+(abs(v.pitch_envelope_ctrl.value)&((1<stop_voice(i); - - } else { - - - int32_t freq=get_frequency(tmp_mixer_period); - int32_t tracker_c5=get_frequency(get_period(60<<1,CPSampleManager::get_singleton()->get_c5_freq( v.sample_ptr->get_sample_data()))); - - freq=(int32_t)((uint64_t)freq*(uint64_t)C5FREQ_MIXER/(uint64_t)tracker_c5); //numbers may become very high - mixer->set_voice_frequency(i,freq); - - /* if keyfade, start substracting fadeoutspeed from fadevol: */ - if ((song->has_instruments())&&(v.note_end_flags & END_NOTE_FADE)) { - - if (v.fadeout_volume>=(v.instrument_ptr->get_volume_fadeout())) { - - v.fadeout_volume-=(v.instrument_ptr->get_volume_fadeout()); - } else { - - v.fadeout_volume=0; - } - } - - /*FILTARSSSSSSSS*/ - - - - v.filter.envelope_cutoff=filter_env; - v.filter.process(); - - if ((v.filter.final_cutoff<0xFF) && (control.filters)) { - - //int final_cutoff; - //uint8_t final_reso; - - //v.filter.set_filter_parameters( &final_cutoff, &final_reso ); - - mixer->set_voice_filter(i,true,v.filter.final_cutoff,v.filter.it_reso); - } else { - - - mixer->set_voice_filter(i,false,0,0); - } - - /* RAIVERV */ - - mixer->set_voice_reverb_send(i,v.reverb_send); - - /* CHAURUZ */ - - mixer->set_voice_chorus_send(i,v.chorus_send); - - } - } - - - switch(song->get_reverb_mode()) { - - case CPSong::REVERB_MODE_ROOM: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_ROOM ); - } break; - case CPSong::REVERB_MODE_STUDIO_SMALL: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_STUDIO_SMALL ); - - } break; - case CPSong::REVERB_MODE_STUDIO_MEDIUM: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_STUDIO_MEDIUM ); - - } break; - case CPSong::REVERB_MODE_STUDIO_LARGE: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_STUDIO_LARGE ); - - } break; - case CPSong::REVERB_MODE_HALL: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_HALL ); - - } break; - case CPSong::REVERB_MODE_SPACE_ECHO: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_SPACE_ECHO ); - - } break; - case CPSong::REVERB_MODE_ECHO: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_ECHO ); - - } break; - case CPSong::REVERB_MODE_DELAY: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_DELAY ); - - } break; - case CPSong::REVERB_MODE_HALF_ECHO: { - - mixer->set_reverb_mode( CPMixer::REVERB_MODE_HALF_ECHO ); - - } break; - - } - - mixer->set_chorus_params(song->get_chorus_delay_ms(),song->get_chorus_separation_ms(),song->get_chorus_depth_ms10(),song->get_chorus_speed_hz10() ); - - -} - - - - - - - - -void CPPlayer::handle_tick() { - - int i; - - - if ( mixer==NULL ) return; - if ( song==NULL ) return; - - - /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */ - - if (control.ticks_counter>=control.speed) { // time to process... ***THE ROW***! - - /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is - the command memory. */ - -// if (control.pattern_delay_1) { - -// control.pattern_delay_2=control.pattern_delay_1; -// control.pattern_delay_1=0; -// } -// if (control.pattern_delay_2) { -// patterndelay active -// if (--control.pattern_delay_2) -// so turn back pf->patpos by 1 -// if (pf->patpos) pf->patpos--; -// } - - if (control.play_mode!=PLAY_NOTHING) { - - control.ticks_counter=0; - - - if (control.position.force_next_order>=0) { - - control.position.current_order=control.position.force_next_order; - } - - control.position.force_next_order=-1; - - control.previous_position=control.position; // for those special cases... - control.position.forbid_jump=false; - - for (i=0;iget_pattern(control.position.current_pattern)->get_note(i,control.position.current_row)); - } - - control.position.current_row++; - - if ( control.position.current_row>=song->get_pattern(control.position.current_pattern)->get_length() ) { - - if (control.play_mode==PLAY_SONG) { - - int next_order; - - next_order=get_song_next_order_idx(song,control.position.current_order); - - if (next_order!=-1) { - // Do we have a "next order?" - control.position.current_pattern=song->get_order(next_order); - if (next_order<=control.position.current_order) - control.reached_end=true; - control.position.current_order=next_order; - - } else { - // no, probably the user deleted the orderlist. - control.play_mode=PLAY_NOTHING; - reset(); - control.reached_end=true; - } - } - control.position.current_row=0; - } - - } - - - } - - - - pre_process_effects(); - process_NNAs(); - setup_voices(); - - /* now set up the actual hardware channel playback information */ - update_mixer(); - - control.ticks_counter++; -} diff --git a/drivers/chibi/cp_player_data_filter.cpp b/drivers/chibi/cp_player_data_filter.cpp deleted file mode 100644 index 30db807eed..0000000000 --- a/drivers/chibi/cp_player_data_filter.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_filter.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - - -#include "cp_player_data.h" - -static float filter_cutoff[256] = { - 130, 132, 134, 136, 138, 140, 142, 144, - 146, 148, 151, 153, 155, 157, 160, 162, - 164, 167, 169, 172, 174, 177, 179, 182, - 184, 187, 190, 193, 195, 198, 201, 204, - 207, 210, 213, 216, 220, 223, 226, 229, - 233, 236, 239, 243, 246, 250, 254, 257, - 261, 265, 269, 273, 277, 281, 285, 289, - 293, 297, 302, 306, 311, 315, 320, 324, - 329, 334, 339, 344, 349, 354, 359, 364, - 369, 375, 380, 386, 391, 397, 403, 409, - 415, 421, 427, 433, 440, 446, 452, 459, - 466, 472, 479, 486, 493, 501, 508, 515, - 523, 530, 538, 546, 554, 562, 570, 578, - 587, 595, 604, 613, 622, 631, 640, 649, - 659, 668, 678, 688, 698, 708, 718, 729, - 739, 750, 761, 772, 783, 795, 806, 818, - 830, 842, 854, 867, 880, 892, 905, 918, - 932, 945, 959, 973, 987, 1002, 1016, 1031, - 1046, 1061, 1077, 1092, 1108, 1124, 1141, 1157, - 1174, 1191, 1209, 1226, 1244, 1262, 1280, 1299, - 1318, 1337, 1357, 1376, 1396, 1417, 1437, 1458, - 1479, 1501, 1523, 1545, 1567, 1590, 1613, 1637, - 1661, 1685, 1709, 1734, 1760, 1785, 1811, 1837, - 1864, 1891, 1919, 1947, 1975, 2004, 2033, 2062, - 2093, 2123, 2154, 2185, 2217, 2249, 2282, 2315, - 2349, 2383, 2418, 2453, 2489, 2525, 2561, 2599, - 2637, 2675, 2714, 2753, 2793, 2834, 2875, 2917, - 2959, 3003, 3046, 3091, 3135, 3181, 3227, 3274, - 3322, 3370, 3419, 3469, 3520, 3571, 3623, 3675, - 3729, 3783, 3838, 3894, 3951, 4008, 4066, 4125, - 4186, 4246, 4308, 4371, 4434, 4499, 4564, 4631, - 4698, 4766, 4836, 4906, 4978, 5050, 5123, 5198 -}; - - -void CPPlayer::Filter_Control::process() { - - - final_cutoff=it_cutoff; - if (envelope_cutoff>=0) { - - envelope_cutoff=envelope_cutoff*255/64; - final_cutoff=final_cutoff*envelope_cutoff/255; - if (final_cutoff>=0xFF) final_cutoff=0xFE; - - } - -} - -void CPPlayer::Filter_Control::set_filter_parameters(int *p_cutoff,uint8_t *p_reso) { - - - - *p_cutoff=filter_cutoff[final_cutoff]; - *p_reso=it_reso; -} diff --git a/drivers/chibi/cp_player_data_nna.cpp b/drivers/chibi/cp_player_data_nna.cpp deleted file mode 100644 index 844f043694..0000000000 --- a/drivers/chibi/cp_player_data_nna.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_nna.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" - -void CPPlayer::process_NNAs() { - - int i; - - if (!song->has_instruments()) return; - - for (i=0;ikick==KICK_NOTE) { - - bool k=false; - - if (aux_chn_ctrl->slave_voice!=NULL) { - - Voice_Control *aux_voc_ctrl; - - aux_voc_ctrl=aux_chn_ctrl->slave_voice; - - if (aux_chn_ctrl->instrument_index==aux_chn_ctrl->slave_voice->instrument_index) { //maybe carry - - aux_chn_ctrl->carry.pan=aux_chn_ctrl->slave_voice->panning_envelope_ctrl; - aux_chn_ctrl->carry.vol=aux_chn_ctrl->slave_voice->volume_envelope_ctrl; - aux_chn_ctrl->carry.pitch=aux_chn_ctrl->slave_voice->pitch_envelope_ctrl; - aux_chn_ctrl->carry.maybe=true; - } else - aux_chn_ctrl->carry.maybe=false; - - if (aux_voc_ctrl->NNA_type != CPInstrument::NNA_NOTE_CUT) { - /* Make sure the old MP_VOICE channel knows it has no - master now ! */ - - - - aux_chn_ctrl->slave_voice=NULL; - /* assume the channel is taken by NNA */ - aux_voc_ctrl->has_master_channel=false; - - switch (aux_voc_ctrl->NNA_type) { - case CPInstrument::NNA_NOTE_CONTINUE: { - - } break; - case CPInstrument::NNA_NOTE_OFF: { - - - aux_voc_ctrl->note_end_flags|=END_NOTE_OFF; - - if (!aux_voc_ctrl->volume_envelope_ctrl.active || aux_voc_ctrl->instrument_ptr->get_volume_envelope()->is_loop_enabled()) { - aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; - } - } break; - case CPInstrument::NNA_NOTE_FADE: { - - aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; - } break; - } - } - } - - if (aux_chn_ctrl->duplicate_check_type!=CPInstrument::DCT_DISABLED) { - int i; - - for (i=0;iis_voice_active(i)|| - (voice[i].master_channel!=aux_chn_ctrl) || - (aux_chn_ctrl->instrument_index!=voice[i].instrument_index)) - continue; - - Voice_Control *aux_voc_ctrl; - - aux_voc_ctrl=&voice[i]; - - k=false; - switch (aux_chn_ctrl->duplicate_check_type) { - case CPInstrument::DCT_NOTE: - if (aux_chn_ctrl->note==aux_voc_ctrl->note) - k=true; - break; - case CPInstrument::DCT_SAMPLE: - if (aux_chn_ctrl->sample_ptr==aux_voc_ctrl->sample_ptr) - k=true; - break; - case CPInstrument::DCT_INSTRUMENT: - k=true; - break; - } - if (k) { - switch (aux_chn_ctrl->duplicate_check_action) { - case CPInstrument::DCA_NOTE_CUT: { - aux_voc_ctrl->fadeout_volume=0; - } break; - case CPInstrument::DCA_NOTE_OFF: { - - aux_voc_ctrl->note_end_flags|=END_NOTE_OFF; - - if (!aux_voc_ctrl->volume_envelope_ctrl.active || aux_chn_ctrl->instrument_ptr->get_volume_envelope()->is_loop_enabled()) { - - aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; - } - - } break; - case CPInstrument::DCA_NOTE_FADE: { - aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; - } break; - } - } - } - - } - } /* if (aux_chn_ctrl->kick==KICK_NOTE) */ - } -} diff --git a/drivers/chibi/cp_player_data_notes.cpp b/drivers/chibi/cp_player_data_notes.cpp deleted file mode 100644 index 621be019e1..0000000000 --- a/drivers/chibi/cp_player_data_notes.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_notes.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" -#include "cp_sample_manager.h" - -#define RANDOM_MAX 2147483647 - -static inline int32_t cp_random_generate(int32_t *seed) { - int32_t k; - int32_t s = (int32_t)(*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - (*seed) = (int32_t)s; - return (int32_t)(s & RANDOM_MAX); -} - - -void CPPlayer::process_new_note(int p_track,uint8_t p_note) { // if there's really a new note.... - - if (control.channel[p_track].real_note!=255) { - control.channel[p_track].old_note=control.channel[p_track].real_note; - - } - - control.channel[p_track].real_note=p_note; - - control.channel[p_track].kick=KICK_NOTE; - - control.channel[p_track].sample_start_index=-1; - control.channel[p_track].sliding=0; - control.channel[p_track].row_has_note=true; - control.channel[p_track].last_event_usecs=song_usecs; - - if (control.channel[p_track].panbrello_type) control.channel[p_track].panbrello_position=0; -} - -bool CPPlayer::process_new_instrument(int p_track,uint8_t p_instrument) { - -// bool different_instrument=false; - ERR_FAIL_INDEX_V(p_instrument,CPSong::MAX_INSTRUMENTS,false); - - if ( song->has_instruments() ) { - - - control.channel[p_track].instrument_ptr=song->get_instrument(p_instrument); - } else { - - control.channel[p_track].instrument_ptr=NULL; - } - - control.channel[p_track].retrig_counter=0; - control.channel[p_track].tremor_position=0; - control.channel[p_track].sample_offset_fine=0; - int old_instr_index=control.channel[p_track].instrument_index; - control.channel[p_track].instrument_index=p_instrument; - - return (old_instr_index!=p_instrument); - - -} - - - // returns if it was able to process -bool CPPlayer::process_note_and_instrument(int p_track,int p_note,int p_instrument) { - - bool aux_result; - aux_result=false; - CPSample *aux_sample=0; // current sample - int dest_sample_index; - bool new_instrument=false; - - control.channel[p_track].row_has_note=false; // wise man says.. "we dont have a note... until we really know we have a note". - control.channel[p_track].new_instrument=false; - - if ( (p_note<0) && (p_instrument<0) ) return aux_result; // nothing to do here - if ( (p_note==255) && (p_instrument==255) ) return aux_result; - - if ( (p_note>=0) && (p_note<120) ) { - - process_new_note(p_track,p_note); - - } else if (p_note==CPNote::CUT) { - - control.channel[p_track].aux_volume=0; - control.channel[p_track].note_end_flags|=END_NOTE_OFF; - control.channel[p_track].note_end_flags|=END_NOTE_KILL; - return aux_result; - - } else if ((p_note==CPNote::OFF) && (song->has_instruments())) { - - if (control.channel[p_track].instrument_ptr!=NULL) { - - control.channel[p_track].note_end_flags|=END_NOTE_OFF; - - if (!control.channel[p_track].instrument_ptr->get_volume_envelope()->is_enabled() || control.channel[p_track].instrument_ptr->get_volume_envelope()->is_loop_enabled()) { - - control.channel[p_track].note_end_flags|=END_NOTE_FADE; - } - } - - return aux_result; - } else return aux_result; // invalid note! - - - if ( (p_instrument>=0) && (p_instrumenthas_instruments() ) { - // If we're in instrument mode... - if ( control.channel[p_track].instrument_ptr->get_sample_number(control.channel[p_track].real_note) >= CPSong::MAX_SAMPLES) { - - control.channel[p_track].kick=KICK_NOTHING; - return aux_result; - - } else { - dest_sample_index=control.channel[p_track].instrument_ptr->get_sample_number(control.channel[p_track].real_note); - control.channel[p_track].note=control.channel[p_track].instrument_ptr->get_note_number(control.channel[p_track].real_note); - } - - } else { - // If we're in sample mode... - dest_sample_index=control.channel[p_track].instrument_index; - control.channel[p_track].note=control.channel[p_track].real_note; - } - - control.channel[p_track].sample_index=dest_sample_index; - aux_sample=song->get_sample(dest_sample_index); - - if (!CPSampleManager::get_singleton()->check( aux_sample->get_sample_data() )) { - /* INVALID SAMPLE */ - control.channel[p_track].kick=KICK_NOTHING; - return aux_result; - - } - - aux_sample=song->get_sample(dest_sample_index); - } else { - - - if (!control.channel[p_track].sample_ptr) - return aux_result; - - if (song->has_instruments()) { - - if (!control.channel[p_track].instrument_ptr) - return aux_result; - - control.channel[p_track].note=control.channel[p_track].instrument_ptr->get_note_number(control.channel[p_track].real_note); - - } else { - - control.channel[p_track].note=control.channel[p_track].real_note; - - } - - aux_sample=control.channel[p_track].sample_ptr; - - } - - - - if (p_instrument>=CPSong::MAX_INSTRUMENTS && control.channel[p_track].sample_ptr!=aux_sample) { - - control.channel[p_track].new_instrument=(control.channel[p_track].period>0); - } - - control.channel[p_track].sample_ptr=aux_sample; - - /* channel or instrument determined panning ? */ - - control.channel[p_track].panning=control.channel[p_track].channel_panning; - - /* set filter,if any ? */ - - - if (aux_sample->is_pan_enabled()) { - - control.channel[p_track].panning=(int)aux_sample->get_pan()*255/64; - - } else if ( song->has_instruments() && (control.channel[p_track].instrument_ptr->is_pan_default_enabled()) ) { - - control.channel[p_track].panning=(int)control.channel[p_track].instrument_ptr->get_pan_default_amount()*255/64; - } - - - if (song->has_instruments()) { - - - /* Pitch-Pan Separation */ - if ((control.channel[p_track].instrument_ptr->get_pan_pitch_separation()!=0) && (control.channel[p_track].channel_panning!=PAN_SURROUND)){ - - control.channel[p_track].panning+=((control.channel[p_track].real_note-control.channel[p_track].instrument_ptr->get_pan_pitch_center())*control.channel[p_track].instrument_ptr->get_pan_pitch_separation())/8; - - if (control.channel[p_track].panningPAN_RIGHT) control.channel[p_track].panning=PAN_RIGHT; - } - - /* Random Volume Variation */ - if (control.channel[p_track].instrument_ptr->get_volume_random_variation()>0) { - - control.channel[p_track].random_volume_variation=100-(cp_random_generate(&control.random_seed) % control.channel[p_track].instrument_ptr->get_volume_random_variation()); - - } else { - - control.channel[p_track].random_volume_variation=100; - } - - - /* Random Pan Variation */ - if ((control.channel[p_track].instrument_ptr->get_pan_random_variation()>0) && (control.channel[p_track].panning!=PAN_SURROUND)){ - - int aux_pan_modifier; - - aux_pan_modifier=(cp_random_generate(&control.random_seed) % (control.channel[p_track].instrument_ptr->get_pan_random_variation() << 2)); - if ((cp_random_generate(&control.random_seed) % 2)==1) aux_pan_modifier=0-aux_pan_modifier; /* it's 5am, let me sleep :) */ - - control.channel[p_track].panning+=aux_pan_modifier; - - if (control.channel[p_track].panningPAN_RIGHT) control.channel[p_track].panning=PAN_RIGHT; - - - } - - /*filter*/ - - if (control.channel[p_track].instrument_ptr->filter_use_default_cutoff()) { - - control.channel[p_track].filter.it_cutoff=control.channel[p_track].instrument_ptr->get_filter_default_cutoff()*2; - - } - - if (control.channel[p_track].instrument_ptr->filter_use_default_resonance()) { - - control.channel[p_track].filter.it_reso=control.channel[p_track].instrument_ptr->get_filter_default_resonance()*2; - - } - - /*envelopes*/ - - - control.channel[p_track].volume_envelope_on=control.channel[p_track].instrument_ptr->get_volume_envelope()->is_enabled(); - control.channel[p_track].panning_envelope_on=control.channel[p_track].instrument_ptr->get_pan_envelope()->is_enabled(); - control.channel[p_track].pitch_envelope_on=control.channel[p_track].instrument_ptr->get_pitch_filter_envelope()->is_enabled(); - control.channel[p_track].NNA_type=control.channel[p_track].instrument_ptr->get_NNA_type(); - control.channel[p_track].duplicate_check_type=control.channel[p_track].instrument_ptr->get_DC_type(); - control.channel[p_track].duplicate_check_action=control.channel[p_track].instrument_ptr->get_DC_action(); - - - } else { - - control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_CUT; - control.channel[p_track].duplicate_check_type=CPInstrument::DCT_DISABLED; - control.channel[p_track].duplicate_check_action=CPInstrument::DCA_NOTE_CUT; - } - - - if (p_instrumentget_default_volume(); - - } - - - control.channel[p_track].slide_to_period=control.channel[p_track].aux_period=get_period((uint16_t)(control.channel[p_track].note)<<1,CPSampleManager::get_singleton()->get_c5_freq( (aux_sample->get_sample_data()))); - - control.channel[p_track].note_end_flags=END_NOTE_NOTHING; /* clears flags */ - - return true; -} - -void CPPlayer::process_volume_column(int p_track,uint8_t p_volume) { - - control.channel[p_track].current_volume_command=CPNote::EMPTY; - control.channel[p_track].current_volume_parameter=CPNote::EMPTY; - - if (p_volume<65) { // VOLUME - - control.channel[p_track].aux_volume=p_volume; - } else if (p_volume<125) { // Volume Command - - - control.channel[p_track].current_volume_command=(p_volume-65) / 10; - control.channel[p_track].current_volume_parameter=(p_volume-65) % 10; - } else if (p_volume<193) { // PAN - - control.channel[p_track].channel_panning=(p_volume-128)*PAN_RIGHT/64; - control.channel[p_track].panning=control.channel[p_track].channel_panning; - - } else if (p_volume<213) { //More volume Commands - - control.channel[p_track].current_volume_command=((p_volume-193) / 10)+6; - control.channel[p_track].current_volume_parameter=(p_volume-193) % 10; - } -} - - -void CPPlayer::process_note(int p_track,CPNote p_note) { - - if ( p_note.note!=CPNote::SCRIPT ) { - - process_note_and_instrument(p_track,p_note.note,p_note.instrument); - process_volume_column(p_track,p_note.volume); - control.channel[p_track].current_command=p_note.command; - control.channel[p_track].current_parameter=p_note.parameter; - - } else { - - CPNote n = song->get_pattern( control.position.current_pattern )->get_transformed_script_note( p_track, control.position.current_row ); - process_note( p_track, n ); - - song->get_pattern( control.position.current_pattern )->scripted_clone( p_track, control.position.current_row ); - } -} diff --git a/drivers/chibi/cp_player_data_utils.cpp b/drivers/chibi/cp_player_data_utils.cpp deleted file mode 100644 index 170a849863..0000000000 --- a/drivers/chibi/cp_player_data_utils.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*************************************************************************/ -/* cp_player_data_utils.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ - -#include "cp_player_data.h" -uint8_t CPPlayer::vibrato_table[32]={ - 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253, - 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24 -}; - -uint8_t CPPlayer::auto_vibrato_table[128]={ - 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23, - 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, - 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, - 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63, - 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59, - 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46, - 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25, - 24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1 -}; - - -int8_t CPPlayer::panbrello_table[256]={ - 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, - 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, - 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, - 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, - 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26, - 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2, - 0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23, - -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44, - -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59, - -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64, - -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60, - -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46, - -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26, - -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2 -}; - - - - - - -int32_t CPPlayer::get_period(uint16_t p_note,int32_t p_c5speed) { - - if (song->has_linear_slides()) { - - return CPTables::get_linear_period(p_note,0); - } else { - - - return CPTables::get_log_period(p_note>>1,p_c5speed >>1); - } -} - - -int32_t CPPlayer::get_frequency(int32_t period) { - - if (song->has_linear_slides()) { - - return CPTables::get_linear_frequency(period); - } else { - - return CPTables::get_old_frequency(period); - } -} - -int CPPlayer::find_empty_voice() { - - int i; - int min_priority,min_priority_chan=0,priority; - - for (i=0;iis_voice_active(i) ) { - - return i; - - } - } - - // todo more - - for (i=0;iget_loop_type( voice[i].sample_ptr->get_sample_data())!=CP_LOOP_NONE)?1:0); - - if ((voice[i].has_master_channel)&&(&voice[i]==voice[i].master_channel->slave_voice)) { - - priority<<=2; - - } - - if ((i==0) || (priority8000*7) return -1; /* what the fuck is this? */ - - return min_priority_chan; -} - diff --git a/drivers/chibi/cp_sample.cpp b/drivers/chibi/cp_sample.cpp deleted file mode 100644 index 55c2c910a5..0000000000 --- a/drivers/chibi/cp_sample.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/*************************************************************************/ -/* cp_sample.cpp */ -/*************************************************************************/ -/* 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. */ -/*************************************************************************/ -#include "cp_sample.h" - -const char * CPSample::get_name() const { - - return name; -} -void CPSample::set_name(const char *p_name) { - - if (p_name==NULL) { - name[0]=0; - return; - } - - - bool done=false; - for (int i=0;icopy_to( p_sample.id, id ); -} - - - - - -void CPSample::reset() { - - - name[0]=0; - - default_volume=64; - global_volume=64; - - pan_enabled=false; - pan=32; - - vibrato_type=VIBRATO_SINE; - vibrato_speed=0; - vibrato_depth=0; - vibrato_rate=0; - - if (!id.is_null() && CPSampleManager::get_singleton()) - CPSampleManager::get_singleton()->destroy( id ); - - id=CPSample_ID(); - -} - -CPSample::CPSample(const CPSample&p_from) { - - reset(); - copy_from(p_from); -} -CPSample::CPSample() { - - reset(); -} - -CPSample::~CPSample() { - - reset(); -} diff --git a/drivers/chibi/cp_sample.h b/drivers/chibi/cp_sample.h deleted file mode 100644 index 4b3d218106..0000000000 --- a/drivers/chibi/cp_sample.h +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************/ -/* cp_sample.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 CPSAMPLE_H -#define CPSAMPLE_H - - -#include "cp_config.h" -#include "cp_sample_manager.h" -class CPSample { - -public: - enum VibratoType { - VIBRATO_SINE, - VIBRATO_SAW, - VIBRATO_SQUARE, - VIBRATO_RANDOM - - }; - -private: - - enum { NAME_MAX_LEN=26 }; - - char name[NAME_MAX_LEN]; - - uint8_t default_volume; /* 0.. 64 */ - uint8_t global_volume; /* 0.. 64 */ - - bool pan_enabled; - uint8_t pan; /* 0.. 64 */ - - VibratoType vibrato_type; - uint8_t vibrato_speed; /* 0.. 64 */ - uint8_t vibrato_depth; /* 0.. 64 */ - uint8_t vibrato_rate; /* 0.. 64 */ - - CPSample_ID id; - - void copy_from(const CPSample &p_sample); -public: - - - void operator=(const CPSample &p_sample); - - const char * get_name() const; - void set_name(const char *p_name); - - void set_default_volume(uint8_t p_vol); - uint8_t get_default_volume() const; - - void set_global_volume(uint8_t p_vol); - uint8_t get_global_volume() const; - - void set_pan_enabled(bool p_vol); - bool is_pan_enabled() const; - - void set_pan(uint8_t p_pan); - uint8_t get_pan() const; - - void set_vibrato_type(VibratoType p_vibrato_type); - VibratoType get_vibrato_type() const; - - void set_vibrato_speed(uint8_t p_vibrato_speed) ; - uint8_t get_vibrato_speed() const; - - void set_vibrato_depth(uint8_t p_vibrato_depth); - uint8_t get_vibrato_depth() const; - - void set_vibrato_rate(uint8_t p_vibrato_rate); - uint8_t get_vibrato_rate() const; - - void set_sample_data(CPSample_ID); - CPSample_ID get_sample_data() const; - - void reset(); - - CPSample(const CPSample&p_from); - CPSample(); - ~CPSample(); - -}; - - - - -#endif diff --git a/drivers/chibi/cp_sample_defs.h b/drivers/chibi/cp_sample_defs.h deleted file mode 100644 index 169963c98e..0000000000 --- a/drivers/chibi/cp_sample_defs.h +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************/ -/* cp_sample_defs.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_SAMPLE_DEFS_H -#define CP_SAMPLE_DEFS_H - -#include "cp_config.h" - -enum CPSample_Loop_Type { - - CP_LOOP_NONE, - CP_LOOP_FORWARD, - CP_LOOP_BIDI -}; - -//#define INVALID_SAMPLE_ID -1 - -#define CP_MIXING_FRAC_BITS_MACRO 13 -#define CP_MIXING_FRAC_BITS_TEXT "13" -// 1<<9 - 1 -#define CP_MIXING_FRAC_BITS_MASK_TEXT "8191" - -enum CPMixConstants { - CP_MIXING_FRAC_BITS=CP_MIXING_FRAC_BITS_MACRO, - CP_MIXING_FRAC_LENGTH=(1<MAX_SPEED); - - initial_variables.speed=p_speed; - -} /* 1 .. 255 */ -int CPSong::get_speed() { - - return initial_variables.speed; - -} /* 1 .. 255 */ - -void CPSong::set_tempo(int p_tempo) { - - CP_ERR_COND( p_tempoMAX_TEMPO ); - - initial_variables.tempo=p_tempo; - -} /* MIN_TEMPO .. MAX_TEMPO */ -int CPSong::get_tempo() { - - return initial_variables.tempo; - - -} /* MIN_TEMPO .. MAX_TEMPO */ - -void CPSong::set_channel_pan(int p_channel,int p_pan) { - - CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); - CP_FAIL_INDEX(p_pan,CHANNEL_MAX_PAN+1); - - initial_variables.channel[p_channel].pan=p_pan; - -} /* 0 .. CHANNEL_MAX_PAN */ -int CPSong::get_channel_pan(int p_channel) { - - CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); - - return initial_variables.channel[p_channel].pan; -} - -void CPSong::set_channel_volume(int p_channel,int p_volume) { - - CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); - CP_FAIL_INDEX(p_volume,CHANNEL_MAX_VOLUME+1); - - - initial_variables.channel[p_channel].volume=p_volume; - - -} /* 0 .. CHANNEL_MAX_VOLUME */ - - -int CPSong::get_channel_volume(int p_channel) { - - CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); - - return initial_variables.channel[p_channel].volume; - -} - -void CPSong::set_channel_chorus(int p_channel,int p_chorus) { - - CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); - CP_FAIL_INDEX(p_chorus,CHANNEL_MAX_CHORUS+1); - - - initial_variables.channel[p_channel].chorus=p_chorus; - - -} /* 0 .. CHANNEL_MAX_CHORUS */ - - -int CPSong::get_channel_chorus(int p_channel) { - - CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); - - return initial_variables.channel[p_channel].chorus; - -} - -void CPSong::set_channel_reverb(int p_channel,int p_reverb) { - - CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); - CP_FAIL_INDEX(p_reverb,CHANNEL_MAX_REVERB+1); - - - initial_variables.channel[p_channel].reverb=p_reverb; - - -} /* 0 .. CHANNEL_MAX_CHORUS */ - - -int CPSong::get_channel_reverb(int p_channel) { - - CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); - - return initial_variables.channel[p_channel].reverb; - -} - -void CPSong::set_channel_surround(int p_channel,bool p_surround) { - - CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); - initial_variables.channel[p_channel].surround=p_surround; - -} -bool CPSong::is_channel_surround(int p_channel) { - - CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,false); - - return initial_variables.channel[p_channel].surround; - - -} - -void CPSong::set_channel_mute(int p_channel,bool p_mute) { - - CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); - - initial_variables.channel[p_channel].mute=p_mute; - -} -bool CPSong::is_channel_mute(int p_channel) { - - CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,false); - - return initial_variables.channel[p_channel].mute; - -} - -/* arrays of stuff */ - -CPPattern* CPSong::get_pattern(int p_pattern) { - - CP_FAIL_INDEX_V(p_pattern,MAX_PATTERNS, NULL); - - return &pattern[p_pattern]; - -} -CPSample* CPSong::get_sample(int p_sample) { - - CP_FAIL_INDEX_V(p_sample,MAX_SAMPLES,NULL); - - return &sample[p_sample]; - - -} -CPInstrument* CPSong::get_instrument(int p_instrument) { - - - CP_FAIL_INDEX_V(p_instrument,MAX_INSTRUMENTS,NULL); - - return &instrument[p_instrument]; - -} - -int CPSong::get_order(int p_order) { - - CP_FAIL_INDEX_V(p_order,MAX_ORDERS,CP_ORDER_NONE); - - - return order[p_order]; - -} -void CPSong::set_order(int p_order,int p_pattern) { - - CP_FAIL_INDEX(p_order,MAX_ORDERS); - - order[p_order]=p_pattern; - -} - - -void CPSong::clear_instrument_with_samples(int p_instrument) { - - CPInstrument *ins = get_instrument( p_instrument ); - if (!ins) - return; - - for (int i=0;iget_sample_number( i ) ); - - if (!s) - continue; - - if (s->get_sample_data().is_null()) - continue; - - s->reset(); - } - ins->reset(); -} - -void CPSong::make_instrument_from_sample(int p_sample) { - - if (!has_instruments()) - return; - CP_ERR_COND(!get_sample( p_sample )); - - for (int i=0;iget_sample_number(n)set_sample_number(n,p_sample); - ins->set_note_number(n,n); - } - - ins->set_name( get_sample( p_sample )->get_name() ); - break; - } - -} - -void CPSong::make_instruments_from_samples() { - - for (int i=0;ireset(); - - CPSample *s=get_sample( i ); - - if (!s) - continue; - - ins->set_name( s->get_name() ); - - if (s->get_sample_data().is_null()) - continue; - - - - - for(int j=0;jset_sample_number( j, i ); - - - - } -} - -void CPSong::reset(bool p_clear_patterns,bool p_clear_samples,bool p_clear_instruments,bool p_clear_variables) { - - if (p_clear_variables) { - variables.name[0]=0; - variables.message[0]=0; - variables.row_highlight_major=16; - variables.row_highlight_minor=4; - variables.mixing_volume=48; - variables.old_effects=false; - if (p_clear_instruments) //should not be cleared, if not clearing instruments!! - variables.use_instruments=false; - variables.stereo_separation=128; - variables.use_linear_slides=true; - variables.use_stereo=true; - - initial_variables.global_volume=128; - initial_variables.speed=6; - initial_variables.tempo=125; - - for (int i=0;ireset(); - } - - if (p_clear_instruments) { - for (int i=0;ireset(); - } - - if (p_clear_patterns) { - for (int i=0;iclear(); - - for (int i=0;iis_empty()) - continue; - - for (int j=0;jclear(); - } - -} -void CPSong::cleanup_unused_instruments(){ - - if (!has_instruments()) - return; - - bool instr_found[MAX_INSTRUMENTS]; - for (int i=0;iis_empty()) - continue; - - for (int row=0;rowget_length();row++) { - - - for (int col=0;colget_note( col,row ); - - if (n.instrumentreset(); - - -} -void CPSong::cleanup_unused_samples(){ - - if (!has_instruments()) - return; - - bool sample_found[MAX_SAMPLES]; - for (int i=0;iis_empty()) - continue; - - - for (int row=0;rowget_length();row++) { - - - for (int col=0;colget_note( col,row ); - - if (n.instrument>=MAX_SAMPLES) - continue; - - if (has_instruments()) { - - for (int nt=0;ntget_sample_number(nt); - if (smpreset(); - -} -void CPSong::cleanup_unused_orders(){ - - bool finito=false; - for (int j=0;jset_pan_default_enabled( false ); //die! - - for (int i=0;iset_pan_enabled( false ); //die! - -} - - -void CPSong::clear_all_default_vol(){ - - for (int i=0;iset_default_volume( 64 ); //die! - for (int i=0;iset_volume_global_amount( CPInstrument::MAX_VOLUME ); - -} - - -int CPSong::get_order_in_use_count() { - - - int order_count = 0; - - for (int i=(MAX_ORDERS-1);i>=0;i--) { - - - if (get_order(i)!=CP_ORDER_NONE) { - order_count=i+1; - break; - } - } - - return order_count; -} -int CPSong::get_pattern_in_use_count() { - - - int pattern_count=0; - - for (int i=(CPSong::MAX_PATTERNS-1);i>=0;i--) { - - - if (!get_pattern(i)->is_empty()) { - pattern_count=i+1; - break; - } - } - - return pattern_count; -} - -int CPSong::get_instrument_in_use_count() { - - int instrument_count=0; - - for (int i=(CPSong::MAX_INSTRUMENTS-1);i>=0;i--) { - - CPInstrument *ins = get_instrument(i); - bool in_use=false; - - for (int s = 0 ; s < CPNote::NOTES ; s++ ) { - - int smp_idx = ins->get_sample_number(s); - if (smp_idx<0 || smp_idx>=CPSong::MAX_SAMPLES) - continue; - - if (!get_sample(smp_idx)->get_sample_data().is_null()) { - in_use=true; - break; - } - - } - - if (in_use) { - instrument_count=i+1; - break; - } - } - - return instrument_count; -} -#include -int CPSong::get_channels_in_use() { - - int max=0; - - for (int p=0;pis_empty()) - continue; - - - for (int c=(CPPattern::WIDTH-1);c>=0;c--) { - - if (cget_length();r++) { - - CPNote n = pat->get_note( c, r ); - if (!n.is_empty()) { - has_note=true; - break; - } - } - - if (has_note) { - - max=c+1; - } - } - } - - return max; -} - - -void CPSong::separate_in_one_sample_instruments(int p_instrument) { - - CP_ERR_COND( !variables.use_instruments ); - CP_FAIL_INDEX( p_instrument, MAX_INSTRUMENTS ); - - int remapped_count=0; - - signed char remap[MAX_SAMPLES]; - - for (int i=0;iget_sample_number(i); - - // check for unusable sample - if (sn<0 || sn>=MAX_SAMPLES || get_sample(sn)->get_sample_data().is_null()) - continue; - printf("sample %i\n",sn); - if ( remap[sn] !=-1 ) { - printf("already mapped to %i\n",remap[sn]); - continue; - } - - printf("isn't remapped\n"); - - // find remap - - for (int j=0;jis_empty()) - continue; - - printf("map to %i\n",j); - - //copy - *get_instrument(j)=*ins; - - // assign samples - for (int k=0;kset_note_number(k,k); - get_instrument(j)->set_sample_number(k,sn); - } - remap[sn]=j; - remapped_count++; - break; - } - - CP_ERR_COND(remap[sn]==-1); // no more free instruments - } - - printf("remapped %i\n",remapped_count); - - if (remapped_count<2) { - //undo if only one is remapped - for (int i=0;ireset(); - } - } - return; - } - - /* remap all song */ - - for (int p=0;pis_empty()) - continue; - - - for (int c=0;cget_length();r++) { - - CPNote n = pat->get_note(c,r); - if (n.noteget_sample_number(n.note); - if (remap[sn]==-1) - pat->set_note(c,r,CPNote()); - else { - - n.instrument=remap[sn]; - pat->set_note(c,r,n); - } - } - } - } - } - - ins->reset(); - -} - - -CPSong::CPSong() { - - reset(); -} -CPSong::~CPSong() { - -} - - - - -int get_song_next_order_idx(CPSong *p_song, int p_order_idx) { - - int baseorder,order_counter; - - order_counter=-1; - - baseorder=p_order_idx; - - do { - - baseorder++; - if ( baseorder>(CPSong::MAX_ORDERS-1) ) baseorder=0; - order_counter++; - - } while ( (p_song->get_order(baseorder)>=(CPSong::MAX_PATTERNS) ) && (order_counter>1); - return t; -} - -static int s3m_period_table[12]={1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907}; - - -int32_t CPTables::get_log_period(uint16_t note,int32_t p_c5freq) { - - return (8363L * 16 * s3m_period_table[note%12] >> (note/12)) / p_c5freq; - -} - -/* -int32_t CPTables::get_log_period(uint16_t note,int32_t p_c5freq) -{ - uint16_t n,o; - uint16_t p1,p2; - int32_t i; - - n=note%(2*OCTAVE); - o=note/(2*OCTAVE); - i=(n<<2); // n*8 + fine/16 - - if (i<0) - i=0; - - if (i>102) - i=102; - - - p1=log_table[i]; - p2=log_table[i+1]; - - - return (Interpolate(fine>>4,0,15,p1,p2)>>o); - -} */ - -int32_t CPTables::get_old_period(uint16_t note,int32_t speed) { - - uint16_t n,o,res; - -// if (!speed) { - - // return 4242; /* <- prevent divide overflow */ - // } - - n=note%(2*OCTAVE); - o=note/(2*OCTAVE); - - res=((8363L*(int32_t)old_period_table[n])>>o)/((old_period_table[17]>>1)+(speed<<2)); /*/(128-speed)*/; - - return res; -} - -int32_t CPTables::get_linear_frequency(int32_t period) { - - int32_t shift_value=(((int32_t)period/768)-2); - if (shift_value>0) { - - return linear_period_to_freq_tab[period%768]>>shift_value; - } else { - shift_value=0-shift_value; - return linear_period_to_freq_tab[period%768]<rid = AudioServer::get_singleton()->sample_create(sf,p_stereo,p_len); - sd->stereo=p_stereo; - sd->len=p_len; - sd->is16=p_16bits; - sd->mixfreq=44100; - sd->loop_begin=0; - sd->loop_end=0; - sd->loop_type=CP_LOOP_NONE; - sd->locks=0; -#ifdef DEBUG_ENABLED - valid.insert(sd); -#endif - CPSample_ID sid; - sid._private=sd; - return sid; -} - -void CPSampleManagerImpl::recreate(CPSample_ID p_id,bool p_16bits,bool p_stereo,int32_t p_len){ - - AudioServer::SampleFormat sf=p_16bits?AudioServer::SAMPLE_FORMAT_PCM16:AudioServer::SAMPLE_FORMAT_PCM8; - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - AudioServer::get_singleton()->free(sd->rid); - sd->rid = AudioServer::get_singleton()->sample_create(sf,p_stereo,p_len); - sd->stereo=p_stereo; - sd->len=p_len; - sd->is16=p_16bits; - sd->mixfreq=44100; - sd->loop_begin=0; - sd->loop_end=0; - sd->loop_type=CP_LOOP_NONE; -} -void CPSampleManagerImpl::destroy(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); - valid.erase(sd); -#endif - AudioServer::get_singleton()->free(sd->rid); - - memdelete(sd); -} -bool CPSampleManagerImpl::check(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - return valid.has(sd); -#else - return _getsd(p_id)!=NULL; -#endif -} - -void CPSampleManagerImpl::set_c5_freq(CPSample_ID p_id,int32_t p_freq){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - sd->mixfreq=p_freq; - AudioServer::get_singleton()->sample_set_mix_rate(sd->rid,p_freq); - -} -void CPSampleManagerImpl::set_loop_begin(CPSample_ID p_id,int32_t p_begin){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - sd->loop_begin=p_begin; - AudioServer::get_singleton()->sample_set_loop_begin(sd->rid,p_begin); - -} -void CPSampleManagerImpl::set_loop_end(CPSample_ID p_id,int32_t p_end){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - sd->loop_end=p_end; - AudioServer::get_singleton()->sample_set_loop_end(sd->rid,p_end); - -} -void CPSampleManagerImpl::set_loop_type(CPSample_ID p_id,CPSample_Loop_Type p_type){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - - sd->loop_type=p_type; - AudioServer::get_singleton()->sample_set_loop_format(sd->rid,AudioServer::SampleLoopFormat(p_type)); - - -} -void CPSampleManagerImpl::set_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - - ERR_FAIL(); -} - - -int32_t CPSampleManagerImpl::get_loop_begin(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - return sd->loop_begin; - -} -int32_t CPSampleManagerImpl::get_loop_end(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - return sd->loop_end; -} -CPSample_Loop_Type CPSampleManagerImpl::get_loop_type(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),CP_LOOP_NONE); -#endif - - return sd->loop_type; -} -int32_t CPSampleManagerImpl::get_c5_freq(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - return sd->mixfreq; -} -int32_t CPSampleManagerImpl::get_size(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - return sd->len; - -} -bool CPSampleManagerImpl::is_16bits(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),false); -#endif - - return sd->is16; - -} -bool CPSampleManagerImpl::is_stereo(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),false); -#endif - return sd->stereo; - - -} -bool CPSampleManagerImpl::lock_data(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - sd->locks++; - if (sd->locks==1) { - sd->lock=AudioServer::get_singleton()->sample_get_data(sd->rid); - sd->w=sd->lock.write(); - } - - return true; -} -void *CPSampleManagerImpl::get_data(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - ERR_FAIL_COND_V(sd->locks==0,0); - return sd->w.ptr(); -} - -int16_t CPSampleManagerImpl::get_data(CPSample_ID p_id, int p_sample, int p_channel){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!valid.has(sd),0); -#endif - - ERR_FAIL_V(0); - lock_data(p_id); - - int sofs = sd->stereo ? 2:1; - uint16_t v=0; - if (sd->is16) { - int16_t *p=(int16_t*)sd->w.ptr(); - v=p[p_sample*sofs+p_channel]; - } else { - int8_t *p=(int8_t*)sd->w.ptr(); - v=p[p_sample*sofs+p_channel]; - } - - unlock_data(p_id); - - return v; -} -void CPSampleManagerImpl::set_data(CPSample_ID p_id, int p_sample, int16_t p_data,int p_channel){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - - ERR_FAIL(); - lock_data(p_id); - - int sofs = sd->stereo ? 2:1; - if (sd->is16) { - int16_t *p=(int16_t*)sd->w.ptr(); - p[p_sample*sofs+p_channel]=p_data; - } else { - int8_t *p=(int8_t*)sd->w.ptr(); - p[p_sample*sofs+p_channel]=p_data; - } - - unlock_data(p_id); - -} -void CPSampleManagerImpl::unlock_data(CPSample_ID p_id){ - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - - ERR_FAIL_COND(sd->locks==0); - - sd->locks--; - if (sd->locks==0) { - sd->w=DVector::Write(); - AudioServer::get_singleton()->sample_set_data(sd->rid,sd->lock); - sd->lock=DVector(); - } -} - -void CPSampleManagerImpl::get_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len) { - - SampleData *sd=_getsd(p_id); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(!valid.has(sd)); -#endif - - ERR_FAIL(); -} - - -/** MIXER **/ - -void CPMixerImpl::set_callback_interval(int p_interval_us) { - - callback_interval=p_interval_us; -} - -void CPMixerImpl::set_callback(void (*p_callback)(void*),void *p_userdata) { - - callback=p_callback; - userdata=p_userdata; -} - -void CPMixerImpl::setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) { - - Voice &v=voices[p_voice_index]; - if (v.channel!=AudioMixer::INVALID_CHANNEL) { - mixer->channel_free(v.channel); - } - v.channel=mixer->channel_alloc(sample_manager->get_rid(p_sample_id)); - v.freq_mult = sample_manager->get_c5_freq(p_sample_id)/261.6255653006; - v.sample = p_sample_id; -} - -void CPMixerImpl::stop_voice(int p_voice_index) { - - Voice &v=voices[p_voice_index]; - if (v.channel==AudioMixer::INVALID_CHANNEL) - return; - - mixer->channel_free(v.channel); - v.channel=AudioMixer::INVALID_CHANNEL; - -} - -void CPMixerImpl::set_voice_frequency(int p_voice_index,int32_t p_freq) { - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - float f = p_freq / 256.0; - f*=pitch_scale; - mixer->channel_set_mix_rate(v.channel,f * v.freq_mult ); -} - -void CPMixerImpl::set_voice_panning(int p_voice_index,int p_pan) { - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - if (p_pan==CP_PAN_SURROUND) - p_pan=CP_PAN_CENTER; - float p = p_pan / 256.0; - mixer->channel_set_pan(v.channel,p); - -} - -void CPMixerImpl::set_voice_volume(int p_voice_index,int p_vol) { - - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - float vol = p_vol/512.0; - vol*=voice_scale; - mixer->channel_set_volume(v.channel,vol); - mixer->channel_set_reverb(v.channel,reverb_type,vol*v.reverb); -} - -void CPMixerImpl::set_voice_filter(int p_voice_index,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance ){ - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - -} - -void CPMixerImpl::set_voice_reverb_send(int p_voice_index,int p_reverb){ - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - v.reverb=p_reverb/255.0; - //mixer->channel_set_reverb(v.channel,reverb_type,p_reverb/255.0); - -} - -void CPMixerImpl::set_voice_chorus_send(int p_voice_index,int p_chorus){ - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - mixer->channel_set_chorus(v.channel,p_chorus/255.0); - -} - - -void CPMixerImpl::set_reverb_mode(ReverbMode p_mode){ - -// Voice &v=voices[p_voice_index]; -// ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - switch(p_mode) { - case CPMixer::REVERB_MODE_STUDIO_SMALL: reverb_type=AudioMixer::REVERB_SMALL; break; - case CPMixer::REVERB_MODE_STUDIO_MEDIUM: reverb_type=AudioMixer::REVERB_MEDIUM; break; - case CPMixer::REVERB_MODE_STUDIO_LARGE: reverb_type=AudioMixer::REVERB_LARGE; break; - case CPMixer::REVERB_MODE_HALL: reverb_type=AudioMixer::REVERB_HALL; break; - default: reverb_type=AudioMixer::REVERB_SMALL; break; - } - -} - -void CPMixerImpl::set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10){ - -// Voice &v=voices[p_voice_index]; -// ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); - -} - - - -/* Info retrieving */ - -int32_t CPMixerImpl::get_voice_sample_pos_index(int p_voice_index) { - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND_V(v.channel==AudioMixer::INVALID_CHANNEL,0); - return 0; - -} - -int CPMixerImpl::get_voice_panning(int p_voice_index) { - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND_V(!is_voice_active(p_voice_index),0); - return mixer->channel_get_pan(v.channel)*CP_PAN_RIGHT; - -} - -int CPMixerImpl::get_voice_volume(int p_voice_index) { - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND_V(!is_voice_active(p_voice_index),0); - return mixer->channel_get_volume(v.channel); - - -} - -CPSample_ID CPMixerImpl::get_voice_sample_id(int p_voice_index) { - - Voice &v=voices[p_voice_index]; - ERR_FAIL_COND_V(v.channel==AudioMixer::INVALID_CHANNEL,CPSample_ID()); - return v.sample; - - -} - -bool CPMixerImpl::is_voice_active(int p_voice_index){ - - Voice &v=voices[p_voice_index]; - if (v.channel==AudioMixer::INVALID_CHANNEL) - return false; - if (!mixer->channel_is_valid(v.channel)) - v.channel=AudioMixer::INVALID_CHANNEL; - - return v.channel!=AudioMixer::INVALID_CHANNEL; -} - -void CPMixerImpl::process_usecs(int p_usec,float p_volume,float p_pitch_scale,float p_tempo_scale) { - - ERR_FAIL_COND(callback_interval==0); - //update this somewhere - pitch_scale=p_pitch_scale; - tempo_scale=p_tempo_scale; - voice_scale = AudioServer::get_singleton()->get_event_voice_global_volume_scale()*p_volume; - while(p_usec) { - - if (p_usec>=callback_timeout) { - - p_usec-=callback_timeout; - callback_timeout=0; - if (callback) { - callback(userdata); - } - callback_timeout=callback_interval*(1.0/p_tempo_scale); - - } else { - - callback_timeout-=p_usec; - p_usec=0; - } - } -} - - -CPMixerImpl::CPMixerImpl(AudioMixer *p_mixer) { - - callback_interval=1; - callback_timeout=0; - userdata=0; - callback=0; - tempo_scale=1.0; - pitch_scale=1.0; - mixer=p_mixer; - voice_scale = AudioServer::get_singleton()->get_event_voice_global_volume_scale(); - reverb_type = AudioMixer::REVERB_SMALL; - -} - -/** FILE ACCESS WRAPPER **/ - - -CPFileAccessWrapperImpl::Error CPFileAccessWrapperImpl::open(const char *p_filename, int p_mode_flags) { - - ERR_FAIL_COND_V(p_mode_flags&WRITE,ERROR_WRITING_FILE); - close(); - f = FileAccess::open(String::utf8(p_filename),p_mode_flags); - if (!f) - return ERROR_FILE_NOT_FOUND; - return OK; -} - -void CPFileAccessWrapperImpl::close(){ - - if (f) - memdelete(f); - f=NULL; - - -} - -void CPFileAccessWrapperImpl::seek(uint32_t p_position){ - - f->seek(p_position); -} -void CPFileAccessWrapperImpl::seek_end(){ - - f->seek_end(); -} -uint32_t CPFileAccessWrapperImpl::get_pos(){ - - return f->get_pos(); -} - -bool CPFileAccessWrapperImpl::eof_reached(){ - - return f->eof_reached(); -} - -uint8_t CPFileAccessWrapperImpl::get_byte(){ - - return f->get_8(); -} -void CPFileAccessWrapperImpl::get_byte_array(uint8_t *p_dest,int p_elements){ - - f->get_buffer(p_dest,p_elements); -} -void CPFileAccessWrapperImpl::get_word_array(uint16_t *p_dest,int p_elements){ - - for(int i=0;iget_16(); - } - -} - -uint16_t CPFileAccessWrapperImpl::get_word(){ - - return f->get_16(); -} -uint32_t CPFileAccessWrapperImpl::get_dword(){ - - return f->get_32(); -} - -void CPFileAccessWrapperImpl::set_endian_conversion(bool p_swap){ - - f->set_endian_swap(p_swap); -} -bool CPFileAccessWrapperImpl::is_open(){ - - return f!=NULL; -} - -CPFileAccessWrapperImpl::Error CPFileAccessWrapperImpl::get_error(){ - - return (f->get_error()!=::OK)?ERROR_READING_FILE:OK; -} - -void CPFileAccessWrapperImpl::store_byte(uint8_t p_dest){ - -} -void CPFileAccessWrapperImpl::store_byte_array(const uint8_t *p_dest,int p_elements){ - -} - -void CPFileAccessWrapperImpl::store_word(uint16_t p_dest){ - -} -void CPFileAccessWrapperImpl::store_dword(uint32_t p_dest){ - -} - -//////////////////////////////////////////////// - - -Error EventStreamPlaybackChibi::_play() { - - last_order=0; - loops=0; - player->play_start_song(); - total_usec=0; - - return OK; -} - -bool EventStreamPlaybackChibi::_update(AudioMixer* p_mixer, uint64_t p_usec){ - - total_usec+=p_usec; - mixer.process_usecs(p_usec,volume,pitch_scale,tempo_scale); - int order=player->get_current_order(); - if (orderplay_stop(); -} - -void EventStreamPlaybackChibi::set_paused(bool p_paused){ - -} -bool EventStreamPlaybackChibi::is_paused() const{ - - return false; -} -void EventStreamPlaybackChibi::set_loop(bool p_loop){ - - loop=p_loop; - -} -bool EventStreamPlaybackChibi::is_loop_enabled() const{ - - return loop; -} - -int EventStreamPlaybackChibi::get_loop_count() const{ - - //return player->is - return loops; -} - -float EventStreamPlaybackChibi::get_pos() const{ - - return double(total_usec)/1000000.0; -} -void EventStreamPlaybackChibi::seek_pos(float p_time){ - - WARN_PRINT("seek_pos unimplemented."); -} - -void EventStreamPlaybackChibi::set_volume(float p_volume) { - - volume=p_volume; -} - -float EventStreamPlaybackChibi::get_volume() const{ - - return volume; -} - -void EventStreamPlaybackChibi::set_pitch_scale(float p_pitch_scale) { - - pitch_scale=p_pitch_scale; -} - -float EventStreamPlaybackChibi::get_pitch_scale() const{ - - return pitch_scale; -} - -void EventStreamPlaybackChibi::set_tempo_scale(float p_tempo_scale) { - - tempo_scale=p_tempo_scale; -} - -float EventStreamPlaybackChibi::get_tempo_scale() const{ - - return tempo_scale; -} - - -void EventStreamPlaybackChibi::set_channel_volume(int p_channel,float p_volume) { - - - if (p_channel>=64) - return; - player->set_channel_global_volume(p_channel,p_volume*256); -} - - - -float EventStreamPlaybackChibi::get_channel_volume(int p_channel) const{ - - return player->get_channel_global_volume(p_channel)/256.0; - -} - -float EventStreamPlaybackChibi::get_last_note_time(int p_channel) const { - - - double v = (player->get_channel_last_note_time_usec(p_channel))/1000000.0; - if (v<0) - v=-1; - return v; -} - -EventStreamPlaybackChibi::EventStreamPlaybackChibi(Ref p_stream) : mixer(_get_mixer()) { - - stream=p_stream; - player = memnew( CPPlayer(&mixer,&p_stream->song) ); - loop=false; - last_order=0; - loops=0; - volume=1.0; - pitch_scale=1.0; - tempo_scale=1.0; -} -EventStreamPlaybackChibi::~EventStreamPlaybackChibi(){ - - player->play_stop(); - memdelete(player); -} - -//////////////////////////////////////////////////// - -Ref EventStreamChibi::instance_playback() { - - return Ref( memnew(EventStreamPlaybackChibi(Ref(this))) ); -} - -String EventStreamChibi::get_stream_name() const{ - - return song.get_name(); - -} - - - -float EventStreamChibi::get_length() const{ - - return 1; -} - - -EventStreamChibi::EventStreamChibi() { - - -} - - - -////////////////////////////////////////////////////////////////// - - - - -RES ResourceFormatLoaderChibi::load(const String &p_path, const String& p_original_path, Error *r_error) { - - if (r_error) - *r_error=ERR_FILE_CANT_OPEN; - String el = p_path.extension().to_lower(); - - CPFileAccessWrapperImpl f; - - if (el=="it") { - - Ref esc( memnew( EventStreamChibi ) ); - CPLoader_IT loader(&f); - CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false); - ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); - if (r_error) - *r_error=OK; - - return esc; - - } else if (el=="xm") { - - Ref esc( memnew( EventStreamChibi ) ); - CPLoader_XM loader(&f); - CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); - ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); - if (r_error) - *r_error=OK; - return esc; - - } else if (el=="s3m") { - - Ref esc( memnew( EventStreamChibi ) ); - CPLoader_S3M loader(&f); - CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); - ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); - if (r_error) - *r_error=OK; - - return esc; - - } else if (el=="mod") { - - Ref esc( memnew( EventStreamChibi ) ); - CPLoader_MOD loader(&f); - CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); - ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); - if (r_error) - *r_error=OK; - return esc; - } - - return RES(); - -} - -void ResourceFormatLoaderChibi::get_recognized_extensions(List *p_extensions) const { - - p_extensions->push_back("it"); - p_extensions->push_back("xm"); - p_extensions->push_back("s3m"); - p_extensions->push_back("mod"); -} -bool ResourceFormatLoaderChibi::handles_type(const String& p_type) const { - - return (p_type=="EventStreamChibi" || p_type=="EventStream"); -} - -String ResourceFormatLoaderChibi::get_resource_type(const String &p_path) const { - String el = p_path.extension().to_lower(); - if (el=="it" || el=="s3m" || el=="xm" || el=="mod") - return "EventStreamChibi"; - return ""; -} - -///////////////////////////////////////////////////////////////// -void initialize_chibi() { - - sample_manager = memnew( CPSampleManagerImpl ); - resource_loader = memnew( ResourceFormatLoaderChibi ); - ObjectTypeDB::register_type(); - ResourceLoader::add_resource_format_loader( resource_loader ); -} - -void finalize_chibi() { - - memdelete( sample_manager ); - memdelete( resource_loader ); -} - diff --git a/drivers/chibi/event_stream_chibi.h b/drivers/chibi/event_stream_chibi.h deleted file mode 100644 index cc7b0ace86..0000000000 --- a/drivers/chibi/event_stream_chibi.h +++ /dev/null @@ -1,314 +0,0 @@ -/*************************************************************************/ -/* event_stream_chibi.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 EVENT_STREAM_CHIBI_H -#define EVENT_STREAM_CHIBI_H - -#include "scene/resources/event_stream.h" -#include "cp_sample_manager.h" -#include "cp_mixer.h" -#include "cp_song.h" -#include "cp_file_access_wrapper.h" -#include "cp_player_data.h" -#include "resource.h" -#include "servers/audio_server.h" -#include "os/file_access.h" -#include "io/resource_loader.h" - -/** SAMPLE MANAGER **/ - -class CPSampleManagerImpl : public CPSampleManager { - - struct SampleData { - - RID rid; - bool stereo; - bool is16; - int len; - int mixfreq; - int loop_begin; - int loop_end; - int locks; - DVector lock; - DVector::Write w; - CPSample_Loop_Type loop_type; - }; - - - _FORCE_INLINE_ SampleData* _getsd(CPSample_ID p_id) { - - return ((SampleData*)p_id._private); - } - Set valid; - -public: - - _FORCE_INLINE_ RID get_rid(CPSample_ID p_id) { return _getsd(p_id)->rid; } - virtual CPSample_ID create(bool p_16bits,bool p_stereo,int32_t p_len); - virtual void recreate(CPSample_ID p_id,bool p_16bits,bool p_stereo,int32_t p_len); - virtual void destroy(CPSample_ID p_id); - virtual bool check(CPSample_ID p_id); // return false if invalid - - virtual void set_c5_freq(CPSample_ID p_id,int32_t p_freq); - virtual void set_loop_begin(CPSample_ID p_id,int32_t p_begin); - virtual void set_loop_end(CPSample_ID p_id,int32_t p_end); - virtual void set_loop_type(CPSample_ID p_id,CPSample_Loop_Type p_type); - virtual void set_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len); - - - virtual int32_t get_loop_begin(CPSample_ID p_id); - virtual int32_t get_loop_end(CPSample_ID p_id); - virtual CPSample_Loop_Type get_loop_type(CPSample_ID p_id); - virtual int32_t get_c5_freq(CPSample_ID p_id); - virtual int32_t get_size(CPSample_ID p_id); - virtual bool is_16bits(CPSample_ID p_id); - virtual bool is_stereo(CPSample_ID p_id); - virtual bool lock_data(CPSample_ID p_id); - virtual void *get_data(CPSample_ID p_id); /* WARNING: Not all sample managers -may be able to implement this, it depends on the mixer in use! */ - virtual int16_t get_data(CPSample_ID p_id, int p_sample, int p_channel=0); /// Does not need locking - virtual void set_data(CPSample_ID p_id, int p_sample, int16_t p_data,int p_channel=0); /// Does not need locking - virtual void unlock_data(CPSample_ID p_id); - - virtual void get_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len); - -}; - - -/** MIXER **/ - -class CPMixerImpl : public CPMixer { - - enum { - MAX_VOICES=64 - }; - - struct Voice { - - AudioMixer::ChannelID channel; - CPSample_ID sample; - float freq_mult; - float reverb; - Voice() { reverb=0.0; } - }; - - Voice voices[MAX_VOICES]; - - - int callback_interval; - int callback_timeout; - void (*callback)(void*); - void *userdata; - float voice_scale; - float tempo_scale; - float pitch_scale; - AudioMixer::ReverbRoomType reverb_type; - AudioMixer *mixer; -public: - - void process_usecs(int p_usec,float p_volume,float p_pitch_scale,float p_tempo_scale); - - /* Callback */ - - virtual void set_callback_interval(int p_interval_us); //in usecs, for tracker it's 2500000/tempo - virtual void set_callback(void (*p_callback)(void*),void *p_userdata); - - /* Voice Control */ - - virtual void setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) ; - virtual void stop_voice(int p_voice_index) ; - virtual void set_voice_frequency(int p_voice_index,int32_t p_freq) ; //in freq*FREQUENCY_BITS - virtual void set_voice_panning(int p_voice_index,int p_pan) ; - virtual void set_voice_volume(int p_voice_index,int p_vol) ; - virtual void set_voice_filter(int p_filter,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance ); - virtual void set_voice_reverb_send(int p_voice_index,int p_reverb); - virtual void set_voice_chorus_send(int p_voice_index,int p_chorus); /* 0 - 255 */ - - virtual void set_reverb_mode(ReverbMode p_mode); - virtual void set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10); - - - /* Info retrieving */ - - virtual int32_t get_voice_sample_pos_index(int p_voice_index) ; - virtual int get_voice_panning(int p_voice_index) ; - virtual int get_voice_volume(int p_voice_index) ; - virtual CPSample_ID get_voice_sample_id(int p_voice_index) ; - virtual bool is_voice_active(int p_voice_index); - virtual int get_active_voice_count() { return 0; } - virtual int get_total_voice_count() { return MAX_VOICES; } - - - virtual uint32_t get_mix_frequency() { return 0; } - - /* Methods below only work with software mixers, meant for software-based sound drivers, hardware mixers ignore them */ - virtual int32_t process(int32_t p_frames) { return 0; } - virtual int32_t *get_mixdown_buffer_ptr() { return NULL; } - virtual void set_mix_frequency(int32_t p_mix_frequency) {}; - - CPMixerImpl(AudioMixer *p_mixer=NULL); - virtual ~CPMixerImpl() {} -}; - -/** FILE ACCESS **/ - -class CPFileAccessWrapperImpl : public CPFileAccessWrapper { - - FileAccess *f; -public: - - - virtual Error open(const char *p_filename, int p_mode_flags); - virtual void close(); - - virtual void seek(uint32_t p_position); - virtual void seek_end(); - virtual uint32_t get_pos(); - - virtual bool eof_reached(); - - virtual uint8_t get_byte(); - virtual void get_byte_array(uint8_t *p_dest,int p_elements); - virtual void get_word_array(uint16_t *p_dest,int p_elements); - - virtual uint16_t get_word(); - virtual uint32_t get_dword(); - - virtual void set_endian_conversion(bool p_swap); - virtual bool is_open(); - - virtual Error get_error(); - - virtual void store_byte(uint8_t p_dest); - virtual void store_byte_array(const uint8_t *p_dest,int p_elements); - - virtual void store_word(uint16_t p_dest); - virtual void store_dword(uint32_t p_dest); - - CPFileAccessWrapperImpl() { f=NULL; } - virtual ~CPFileAccessWrapperImpl(){ if (f) memdelete(f); } - -}; - - - -///////////////////// - -class EventStreamChibi; - -class EventStreamPlaybackChibi : public EventStreamPlayback { - - OBJ_TYPE(EventStreamPlaybackChibi,EventStreamPlayback); - - CPMixerImpl mixer; - uint64_t total_usec; - Ref stream; - mutable CPPlayer *player; - bool loop; - int last_order; - int loops; - virtual Error _play(); - virtual bool _update(AudioMixer* p_mixer, uint64_t p_usec); - virtual void _stop(); - float volume; - float tempo_scale; - float pitch_scale; - - -public: - - - virtual void set_paused(bool p_paused); - virtual bool is_paused() const; - - virtual void set_loop(bool p_loop); - virtual bool is_loop_enabled() const; - - virtual int get_loop_count() const; - - virtual float get_pos() const; - virtual void seek_pos(float p_time); - - virtual void set_volume(float p_vol); - virtual float get_volume() const; - - virtual void set_pitch_scale(float p_pitch_scale); - virtual float get_pitch_scale() const; - - virtual void set_tempo_scale(float p_tempo_scale); - virtual float get_tempo_scale() const; - - virtual void set_channel_volume(int p_channel,float p_volume); - virtual float get_channel_volume(int p_channel) const; - - virtual float get_last_note_time(int p_channel) const; - - EventStreamPlaybackChibi(Ref p_stream=Ref()); - ~EventStreamPlaybackChibi(); -}; - - -class EventStreamChibi : public EventStream { - - OBJ_TYPE(EventStreamChibi,EventStream); - -friend class ResourceFormatLoaderChibi; -friend class EventStreamPlaybackChibi; - //I think i didn't know what const was when i wrote this more than a decade ago - //so it goes mutable :( - mutable CPSong song; - - -public: - - virtual Ref instance_playback(); - - virtual String get_stream_name() const; - - virtual float get_length() const; - - virtual int get_channel_count() const { return 64; } //tracker limit - - EventStreamChibi(); -}; - - -class ResourceFormatLoaderChibi : public ResourceFormatLoader { - -public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; - -}; - -void initialize_chibi(); -void finalize_chibi(); - -#endif // EVENT_STREAM_CHIBI_H diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index 31d53e0185..7486d4f217 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -31,7 +31,6 @@ #include "core/math/geometry.h" #include "png/image_loader_png.h" #include "png/resource_saver_png.h" -#include "chibi/event_stream_chibi.h" #ifdef TOOLS_ENABLED #include "convex_decomp/b2d_decompose.h" @@ -70,14 +69,9 @@ void unregister_core_driver_types() { void register_driver_types() { #ifdef TOOLS_ENABLED - Geometry::_decompose_func=b2d_decompose; #endif - - initialize_chibi(); } void unregister_driver_types() { - - finalize_chibi(); } diff --git a/modules/chibi/SCsub b/modules/chibi/SCsub new file mode 100644 index 0000000000..e39554977a --- /dev/null +++ b/modules/chibi/SCsub @@ -0,0 +1,7 @@ +Import('env') +Import('env_modules') + +env_chibi = env_modules.Clone() + +# Godot source files +env_chibi.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/chibi/config.py b/modules/chibi/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/chibi/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/chibi/cp_config.h b/modules/chibi/cp_config.h new file mode 100644 index 0000000000..2ad704ace7 --- /dev/null +++ b/modules/chibi/cp_config.h @@ -0,0 +1,52 @@ +/*************************************************************************/ +/* cp_config.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_CONFIG_H +#define CP_CONFIG_H + + +#include "typedefs.h" +#include "error_macros.h" +#include "math_funcs.h" +#include "os/memory.h" +#include "os/copymem.h" + +#define CP_PRINTERR(m_err) ERR_PRINT(m_err) +#define CP_ERR_COND(m_cond) ERR_FAIL_COND(m_cond) +#define CP_ERR_COND_V(m_cond,m_ret) ERR_FAIL_COND_V(m_cond,m_ret) +#define CP_FAIL_INDEX(m_index,m_size) ERR_FAIL_INDEX(m_index,m_size) +#define CP_FAIL_INDEX_V(m_index,m_size,m_ret) ERR_FAIL_INDEX_V(m_index,m_size,m_ret) +#define cp_intabs(m_val) ABS(m_val) + +#define CP_ALLOC(m_mem) memalloc(m_mem) +#define CP_REALLOC(m_mem,m_size) memrealloc(m_mem,m_size) +#define CP_FREE(m_mem) memfree(m_mem) + +#define cp_memzero(m_mem,m_size) zeromem(m_mem,m_size) + +#endif // CP_CONFIG_H diff --git a/modules/chibi/cp_envelope.cpp b/modules/chibi/cp_envelope.cpp new file mode 100644 index 0000000000..9892b6d4b0 --- /dev/null +++ b/modules/chibi/cp_envelope.cpp @@ -0,0 +1,369 @@ +/*************************************************************************/ +/* cp_envelope.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_envelope.h" + + +CPEnvelope::CPEnvelope() { + + + reset(); +} + +void CPEnvelope::reset() { + + + + on=false; + carry=false; + loop_on=false; + loop_begin_node=0; + loop_end_node=0; + sustain_loop_on=false; + sustain_loop_begin_node=0; + sustain_loop_end_node=0; + node_count=0; + +} + +int CPEnvelope::get_height_at_pos(int pos) { + + if (node_count && pos>node[node_count-1].tick_offset) + return node[node_count-1].value; + + int begin_x,begin_y; + int end_x,end_y,xdif; + int count=0; + int limit=-1; + + if (node_count<2) return NO_POINT; + + while ((count=pos) limit=count; + count++; + } + + if (pos==0) return node[0].value; + + if (limit==-1) return NO_POINT; + + begin_x=node[limit-1].tick_offset; + end_x=node[limit].tick_offset; + begin_y=node[limit-1].value; + end_y=node[limit].value; + + xdif=end_x-begin_x; + return begin_y+((pos-begin_x)*(end_y-begin_y))/(xdif?xdif:1); +} + +/* +int CPEnvelope::get_fx_height_at_pos(int pos) { + + if (node_count && pos>node[node_count-1].tick_offset) + return node[node_count-1].value<=pos) limit=count; + count++; + } + + if (pos==0) return node[0].value<node[node_count-1].tick_offset) + return node[node_count-1].value; + + int begin_x,begin_y; + int end_x,end_y,xdif; + int count=0; + int limit=-1; + + if (node_count<2) return NO_POINT; + + while ((count=pos) limit=count; + count++; + } + + if (pos==0) return node[0].value; + + if (limit==-1) return NO_POINT; + + begin_x=node[limit-1].tick_offset; + end_x=node[limit].tick_offset; + begin_y=node[limit-1].value; + end_y=node[limit].value; + + xdif=end_x-begin_x; + return begin_y+((pos-begin_x)*(end_y-begin_y))/(xdif?xdif:1); +} + +void CPEnvelope::set_position(int p_node,int p_x,int p_y) { + + if (p_node>=node_count) return; + + + + if (p_node==0) { + + p_x=0; + + } else if (p_x<=node[p_node-1].tick_offset) { + + p_x=node[p_node-1].tick_offset+1; + + } else if ((p_node<(node_count-1)) && (p_x>=node[p_node+1].tick_offset)) { + + p_x=node[p_node+1].tick_offset-1; + } + + if (p_x>=9999) p_x=9999; + + if (p_y>max_value) p_y=max_value; + if (p_y=node[i].tick_offset)) i++; + + new_node=i; + node_count++; + + if (p_move_loops) { + if (loop_begin_node>=new_node) loop_begin_node++; + if (loop_end_node>=new_node) loop_end_node++; + if (sustain_loop_begin_node>=new_node) sustain_loop_begin_node++; + if (sustain_loop_end_node>=new_node) sustain_loop_end_node++; + } + for (i=node_count-1;i>new_node;i--) node[i]=node[i-1]; + + + + set_position(new_node,p_x,p_y); + + + + return new_node; + +} + +void CPEnvelope::set_loop_begin(int pos) { + + if ((pos<0) || (pos>=node_count)) return; + + + + loop_begin_node=pos; + + if (loop_end_node=node_count)) return; + + + + loop_end_node=pos; + + if (loop_end_node=node_count)) return; + + + + sustain_loop_begin_node=pos; + + if (sustain_loop_end_node=node_count)) return; + + + + sustain_loop_end_node=pos; + + if (sustain_loop_end_node=node_count)) return; + + + + int i; + + if (loop_begin_node>=p_node) loop_begin_node--; + if (loop_end_node>=p_node) loop_end_node--; + if (sustain_loop_begin_node>=p_node) sustain_loop_begin_node--; + if (sustain_loop_end_node>=p_node) sustain_loop_end_node--; + + for (i=p_node;i=node_count) + return node[node_count-1]; + + return node[p_idx]; + +} + + diff --git a/modules/chibi/cp_envelope.h b/modules/chibi/cp_envelope.h new file mode 100644 index 0000000000..d1ada53f7d --- /dev/null +++ b/modules/chibi/cp_envelope.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* cp_envelope.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_ENVELOPE_H +#define CP_ENVELOPE_H + +#include "cp_config.h" + +/**envelope? + *@author Juan Linietsky + */ + +/****************************** + envelope.h + ---------- + +Proovides an envelope, and basic functions +for it that can be used for both player +and interface +********************************/ + + +class CPEnvelope { + enum { + + MAX_POINTS=25 + }; + + struct Point { + + uint16_t tick_offset; + int16_t value; + }; + + Point node[MAX_POINTS]; + + int8_t node_count; + + bool on; + bool carry; + + bool loop_on; + + uint8_t loop_begin_node; + uint8_t loop_end_node; + + bool sustain_loop_on; + uint8_t sustain_loop_begin_node; + uint8_t sustain_loop_end_node; + + + int8_t max_value; + int8_t min_value; + + +public: + enum { + + NO_POINT=-5000, + }; + + void set_max(int8_t p_max) { max_value=p_max; } + int8_t get_max() { return max_value; } + void set_min(int8_t p_min) { min_value=p_min; } + int8_t get_min() { return min_value; } + + uint8_t get_node_count(); + const Point& get_node(int p_idx); + + void set_position(int p_node,int p_x,int p_y); + int add_position(int p_x,int p_y,bool p_move_loops=true); + void del_position(int p_node); + + void set_loop_enabled(bool p_enabled); + bool is_loop_enabled(); + void set_loop_begin(int pos); + void set_loop_end(int pos); + uint8_t get_loop_begin(); + uint8_t get_loop_end(); + + void set_sustain_loop_enabled(bool p_enabled); + bool is_sustain_loop_enabled(); + void set_sustain_loop_begin(int pos); + void set_sustain_loop_end(int pos); + uint8_t get_sustain_loop_begin(); + uint8_t get_sustain_loop_end(); + + void set_enabled(bool p_enabled); + bool is_enabled(); + + void set_carry_enabled(bool p_enabled); + bool is_carry_enabled(); + + void reset(); + int get_height_at_pos(int pos); + float get_interp_height_at_pos(float pos); + + + CPEnvelope(); + +}; + +#endif diff --git a/modules/chibi/cp_file_access_wrapper.h b/modules/chibi/cp_file_access_wrapper.h new file mode 100644 index 0000000000..5b361c0ea8 --- /dev/null +++ b/modules/chibi/cp_file_access_wrapper.h @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* cp_file_access_wrapper.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_FILE_ACCESS_WRAPPER_H +#define CP_FILE_ACCESS_WRAPPER_H + +#include "cp_config.h" + +class CPFileAccessWrapper { +public: + + enum ModeFlags { + + READ=1, + WRITE=2, + READ_WRITE=3, + }; + + enum Error { + + OK, + ERROR_FILE_NOT_FOUND, + ERROR_FILE_BAD_DRIVE, + ERROR_FILE_BAD_PATH, + ERROR_FILE_NO_PERMISSION, + ERROR_ALREADY_IN_USE, + ERROR_INVALID_PARAMETERS, + ERROR_OPENING_FILE, + ERROR_READING_FILE, + ERROR_WRITING_FILE + }; + + virtual Error open(const char *p_filename, int p_mode_flags)=0; + virtual void close()=0; + + virtual void seek(uint32_t p_position)=0; + virtual void seek_end()=0; + virtual uint32_t get_pos()=0; + + virtual bool eof_reached()=0; + + virtual uint8_t get_byte()=0; + virtual void get_byte_array(uint8_t *p_dest,int p_elements)=0; + virtual void get_word_array(uint16_t *p_dest,int p_elements)=0; + + virtual uint16_t get_word()=0; + virtual uint32_t get_dword()=0; + + // use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) + // It's not about the current CPU type but file formats. + // this flags get reset to false (little endian) on each open + virtual void set_endian_conversion(bool p_swap)=0; + virtual bool is_open()=0; + + virtual Error get_error()=0; + + virtual void store_byte(uint8_t p_dest)=0; + virtual void store_byte_array(const uint8_t *p_dest,int p_elements)=0; + + virtual void store_word(uint16_t p_dest)=0; + virtual void store_dword(uint32_t p_dest)=0; + + + + virtual ~CPFileAccessWrapper(){} + +}; + + + +#endif diff --git a/modules/chibi/cp_instrument.cpp b/modules/chibi/cp_instrument.cpp new file mode 100644 index 0000000000..7a732e33a4 --- /dev/null +++ b/modules/chibi/cp_instrument.cpp @@ -0,0 +1,344 @@ +/*************************************************************************/ +/* cp_instrument.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_instrument.h" +#include "cp_song.h" +#include "cp_note.h" + + + +const char *CPInstrument::get_name() { + + return name; + +} +void CPInstrument::set_name(const char *p_name) { + + + if (p_name==NULL) { + name[0]=0; + return; + } + + + bool done=false; + for (int i=0;i=CPNote::NOTES); + CP_ERR_COND(p_sample_id>CPSong::MAX_SAMPLES && p_sample_id!=CPNote::EMPTY); + data.sample_number[p_note]=p_sample_id; + + +} +uint8_t CPInstrument::get_sample_number(uint8_t p_note) { + + CP_ERR_COND_V(p_note>=CPNote::NOTES,0); + return data.sample_number[p_note]; +} + +void CPInstrument::set_note_number(uint8_t p_note,uint8_t p_note_id) { + + CP_ERR_COND(p_note>=CPNote::NOTES); + CP_ERR_COND(p_note_id>=CPNote::NOTES && p_note_id!=CPNote::EMPTY); + data.note_number[p_note]=p_note_id; + +} +uint8_t CPInstrument::get_note_number(uint8_t p_note) { + + CP_ERR_COND_V(p_note>=CPNote::NOTES,0); + return data.note_number[p_note]; + +} + +void CPInstrument::set_NNA_type(NNA_Type p_NNA_type) { + + data.NNA_type=p_NNA_type; +} +CPInstrument::NNA_Type CPInstrument::get_NNA_type() { + + return data.NNA_type; +} + +void CPInstrument::set_DC_type(DC_Type p_DC_type) { + + data.DC_type=p_DC_type; +} +CPInstrument::DC_Type CPInstrument::get_DC_type() { + + return data.DC_type; + +} + +void CPInstrument::set_DC_action(DC_Action p_DC_action) { + + data.DC_action=p_DC_action; +} +CPInstrument::DC_Action CPInstrument::get_DC_action() { + + return data.DC_action; +} + +/* Volume */ + +void CPInstrument::set_volume_global_amount(uint8_t p_amount) { + + CP_ERR_COND(p_amount>MAX_VOLUME); + data.volume.global_amount=p_amount; + +} +uint8_t CPInstrument::get_volume_global_amount() { + + return data.volume.global_amount; +} + +void CPInstrument::set_volume_fadeout(uint16_t p_amount) { + CP_ERR_COND(p_amount>MAX_FADEOUT); + data.volume.fadeout=p_amount; +} +uint16_t CPInstrument::get_volume_fadeout() { + + return data.volume.fadeout; +} +void CPInstrument::set_volume_random_variation(uint8_t p_amount) { + + CP_ERR_COND(p_amount>MAX_VOLUME_RANDOM); + data.volume.random_variation=p_amount; +} +uint8_t CPInstrument::get_volume_random_variation() { + + return data.volume.random_variation; +} + +/* Panning */ + +void CPInstrument::set_pan_default_amount(uint8_t p_amount) { + + CP_ERR_COND(p_amount>MAX_PAN); + data.pan.default_amount=p_amount; +} +uint8_t CPInstrument::get_pan_default_amount() { + + return data.pan.default_amount; +} + +void CPInstrument::set_pan_default_enabled(bool p_enabled) { + + data.pan.use_default=p_enabled; +} +bool CPInstrument::is_pan_default_enabled() { + + return data.pan.use_default; + +} + +void CPInstrument::set_pan_pitch_separation(int8_t p_amount) { + + CP_ERR_COND(p_amount<-32); + CP_ERR_COND(p_amount>32); + data.pan.pitch_separation=p_amount; +} +int8_t CPInstrument::get_pan_pitch_separation() { + + return data.pan.pitch_separation; +} + +void CPInstrument::set_pan_pitch_center(uint8_t p_amount) { + + CP_ERR_COND(p_amount>=CPNote::NOTES); + data.pan.pitch_center=p_amount; +} +uint8_t CPInstrument::get_pan_pitch_center() { + + return data.pan.pitch_center; +} + +void CPInstrument::set_pan_random_variation(uint8_t p_amount) { + + CP_ERR_COND(p_amount>MAX_PAN_RANDOM); + data.pan.random_variation=p_amount; +} +uint8_t CPInstrument::get_pan_random_variation() { + + return data.pan.random_variation; +} + +/* Pitch / Filter */ + +void CPInstrument::set_pitch_use_as_filter(bool p_enabled) { + + data.pitch.use_as_filter=p_enabled; +} +bool CPInstrument::is_pitch_use_as_filter() { + + return data.pitch.use_as_filter; +} + +void CPInstrument::set_filter_use_default_cutoff(bool p_enabled) { + + data.pitch.use_default_cutoff=p_enabled; + +} +bool CPInstrument::filter_use_default_cutoff() { + + return data.pitch.use_default_cutoff; +} + +void CPInstrument::set_filter_default_cutoff(uint8_t p_amount) { + + CP_ERR_COND(p_amount>MAX_FILTER_CUTOFF); + data.pitch.default_cutoff=p_amount; +} +uint8_t CPInstrument::get_filter_default_cutoff() { + + return data.pitch.default_cutoff; +} + +void CPInstrument::set_filter_use_default_resonance(bool p_enabled) { + + data.pitch.use_default_resonance=p_enabled; +} +bool CPInstrument::filter_use_default_resonance() { + + return data.pitch.use_default_resonance; +} + +void CPInstrument::set_filter_default_resonance(uint8_t p_amount) { + + CP_ERR_COND(p_amount>MAX_FILTER_RESONANCE); + data.pitch.default_resonance=p_amount; + +} +uint8_t CPInstrument::get_filter_default_resonance() { + + return data.pitch.default_resonance; +} + +/* Envelopes */ + + +CPEnvelope* CPInstrument::get_volume_envelope() { + + return &data.volume.envelope; +} +CPEnvelope* CPInstrument::get_pan_envelope() { + + return &data.pan.envelope; +} +CPEnvelope* CPInstrument::get_pitch_filter_envelope() { + + return &data.pitch.envelope; + + +} + + +void CPInstrument::reset() { + + name[0]=0; + + data.NNA_type=NNA_NOTE_CUT; + data.DC_action=DCA_NOTE_CUT; + data.DC_type=DCT_DISABLED; + + for (int i=0;i +*/ +class CPLoader { + +public: + + enum Error { + FILE_OK, + FILE_UNRECOGNIZED, + FILE_CANNOT_OPEN, + FILE_CORRUPTED, + FILE_OUT_OF_MEMORY, + }; + + + virtual bool can_load_song()=0; + virtual bool can_load_sample()=0; + virtual bool can_load_instrument()=0; + + virtual Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset)=0; + virtual Error load_sample(const char *p_file,CPSample *p_sample)=0; + virtual Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx)=0; + + + virtual ~CPLoader() {} + +}; + +#endif diff --git a/modules/chibi/cp_loader_it.cpp b/modules/chibi/cp_loader_it.cpp new file mode 100644 index 0000000000..20a3960a23 --- /dev/null +++ b/modules/chibi/cp_loader_it.cpp @@ -0,0 +1,216 @@ +/*************************************************************************/ +/* cp_loader_it.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_loader_it.h" + +bool CPLoader_IT::can_load_song() { return true; } +bool CPLoader_IT::can_load_sample() { return true; } +bool CPLoader_IT::can_load_instrument() { return true; } + +CPLoader::Error CPLoader_IT::load_song(const char *p_file,CPSong *p_song, bool p_sampleset) { + + + song=p_song; + + if (file->open( p_file, CPFileAccessWrapper::READ )!=CPFileAccessWrapper::OK) + return CPLoader::FILE_CANNOT_OPEN; + + + Error err; + + char aux_identifier[4]; + file->get_byte_array((uint8_t*)aux_identifier,4); + + if ( aux_identifier[0]!='I' || + aux_identifier[1]!='M' || + aux_identifier[2]!='P' || + aux_identifier[3]!='M') { + + + CP_PRINTERR("IT CPLoader CPSong: Failed Identifier"); + return FILE_UNRECOGNIZED; + } + + + if (p_sampleset) { + + song->reset(false,true,true,false); + + if ((err=load_header(true))) { + file->close(); + return err; + } + + if ((err=load_samples())) { + file->close(); + return err; + } + + if ((err=load_instruments())) { + file->close(); + return err; + } + + return FILE_OK; + } + + song->reset(); + + if ((err=load_header(false))) { + file->close(); + return err; + } + + if ((err=load_orders())) { + file->close(); + return err; + } + + if ((err=load_patterns())) { + file->close(); + return err; + } + + if ((err=load_samples())) { + file->close(); + return err; + } + + if ((err=load_effects())) { + file->close(); + return err; + } + + if ((err=load_instruments())) { + file->close(); + return err; + } + + if ((err=load_message())) { + file->close(); + return err; + } + + file->close(); + return FILE_OK; + +} + + + + +CPLoader::Error CPLoader_IT::load_sample(const char *p_file,CPSample *p_sample) { + + if (file->open( p_file, CPFileAccessWrapper::READ )!=CPFileAccessWrapper::OK) + return CPLoader::FILE_CANNOT_OPEN; + + p_sample->reset(); + CPLoader::Error res=load_sample(p_sample); + + file->close(); + + return res; +} +CPLoader::Error CPLoader_IT::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { + + CP_FAIL_INDEX_V(p_instr_idx,CPSong::MAX_INSTRUMENTS,CPLoader::FILE_CANNOT_OPEN); + + if (file->open( p_file, CPFileAccessWrapper::READ )!=CPFileAccessWrapper::OK) + return CPLoader::FILE_CANNOT_OPEN; + + + p_song->get_instrument( p_instr_idx )->reset(); + + + int samples=0; + CPLoader::Error res=load_instrument( p_song->get_instrument( p_instr_idx ), &samples ); + + if (res) { + file->close(); + return res; + } + + + char exchange[CPSong::MAX_SAMPLES]; + for (int i=0;iseek( 554+i*80 ); //i think this should work?! seems to.. but i'm not sure + + /* find free sample */ + + int free_idx=-1; + for (int s=0;sget_sample( s )->get_sample_data().is_null()) { + free_idx=s; + break; + } + } + if (free_idx==-1) + break; //can't seem to be able to load more samples + + exchange[i]=free_idx; + res=load_sample( p_song->get_sample( free_idx ) ); + + if (res) { + + file->close(); + return res; + } + } + + for (int i=0;iget_instrument(p_instr_idx)->get_sample_number(i); + + if (smp>=CPSong::MAX_SAMPLES) + continue; + + if (smp<0) + continue; + + smp=exchange[smp]; + + song->get_instrument(p_instr_idx)->set_sample_number(i,smp); + + } + + file->close(); + + return res; + +} + +CPLoader_IT::CPLoader_IT(CPFileAccessWrapper *p_file) { + + file=p_file; + +} diff --git a/modules/chibi/cp_loader_it.h b/modules/chibi/cp_loader_it.h new file mode 100644 index 0000000000..38a1cdd9c4 --- /dev/null +++ b/modules/chibi/cp_loader_it.h @@ -0,0 +1,125 @@ +/*************************************************************************/ +/* cp_loader_it.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_LOADER_IT_H +#define CP_LOADER_IT_H + +#include "cp_loader.h" +/** + *@author Juan Linietsky + */ + +/****************************** + loader_it.h + ---------- +Impulse Tracker Module CPLoader! +It lacks support for old +instrument files methinks... +and some other things like +midi. +********************************/ + +class AuxSampleData; //used for internal crap + +class CPLoader_IT : public CPLoader { + + + + CPFileAccessWrapper *file; + CPSong *song; + + struct IT_Header { + uint8_t blank01[2]; + uint16_t ordnum; + uint16_t insnum; + uint16_t smpnum; + uint16_t patnum; + uint16_t cwt; /* Created with tracker (y.xx = 0x0yxx) */ + uint16_t cmwt; /* Compatible with tracker ver > than val. */ + uint16_t flags; + uint16_t special; /* bit 0 set = song message attached */ + uint16_t msglength; + uint32_t msgoffset; + bool is_chibi; + }; + + /* Variables to store temp data */ + IT_Header header; + + /* CPSong Info Methods */ + Error load_header(bool p_dont_set); + Error load_orders(); + Error load_message(); + + /* CPPattern Methods */ + Error load_patterns(); + + /* CPSample Methods */ + + Error load_samples(); + Error load_sample(CPSample *p_sample); + CPSample_ID load_sample_data(AuxSampleData& p_sample_data); + + // CPSample decompression + + uint32_t read_n_bits_from_IT_compressed_block(uint8_t p_bits_to_read); + bool read_IT_compressed_block (bool p_16bits); + void free_IT_compressed_block (); + bool load_sample_8bits_IT_compressed(void *p_dest_buffer,int p_buffsize); + bool load_sample_16bits_IT_compressed(void *p_dest_buffer,int p_buffsize); + uint32_t *source_buffer; /* source buffer */ + uint32_t *source_position; /* actual reading position */ + uint8_t source_remaining_bits; /* bits remaining in read dword */ + uint8_t* pat_data; + + /* CPInstruments Methods */ + Error load_effects(); + Error load_instruments(); + Error load_instrument(CPInstrument *p_instrument,int *p_samples=0); + void load_envelope(CPEnvelope *p_envelope,bool*p_has_filter_flag=0); + + +public: + + + bool can_load_song(); + bool can_load_sample(); + bool can_load_instrument(); + + Error load_song(const char *p_file,CPSong *p_song, bool p_sampleset=false); + Error load_sample(const char *p_file,CPSample *p_sample); + Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx); + + CPLoader_IT(CPFileAccessWrapper *p_file); + +}; + + + +#endif diff --git a/modules/chibi/cp_loader_it_info.cpp b/modules/chibi/cp_loader_it_info.cpp new file mode 100644 index 0000000000..0360f7f9a4 --- /dev/null +++ b/modules/chibi/cp_loader_it_info.cpp @@ -0,0 +1,268 @@ +/*************************************************************************/ +/* cp_loader_it_info.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_loader_it.h" + + + +CPLoader::Error CPLoader_IT::load_header(bool p_dont_set) { + + + char aux_songname[26]; + + file->get_byte_array((uint8_t*)aux_songname,26); + if (!p_dont_set) + song->set_name( aux_songname ); + + uint8_t aux_hlmin=file->get_byte(); + uint8_t aux_hlmaj=file->get_byte(); + + if (aux_hlmin==0) aux_hlmin=4; + if (aux_hlmaj==0) aux_hlmaj=16; + + if (!p_dont_set) { + song->set_row_highlight_minor( aux_hlmin ); + song->set_row_highlight_major( aux_hlmaj ); + } + + header.ordnum=file->get_word(); + header.insnum=file->get_word(); + header.smpnum=file->get_word(); + header.patnum=file->get_word(); + + header.cwt=file->get_word(); /* Created with tracker (y.xx = 0x0yxx) */ + header.cmwt=file->get_word(); /* Compatible with tracker ver > than val. */ + header.flags=file->get_word(); + + if (!p_dont_set) { + song->set_stereo( header.flags & 1 ); + song->set_linear_slides( header.flags & 8 ); + song->set_old_effects( header.flags & 16 ); + song->set_compatible_gxx( header.flags & 32 ); + song->set_instruments( header.flags & 4 ); + } + + + header.special=file->get_word(); + if (!p_dont_set) { + + song->set_global_volume( file->get_byte() ); + song->set_mixing_volume( file->get_byte() ); + song->set_speed( file->get_byte() ); + song->set_tempo( file->get_byte() ); + song->set_stereo_separation( file->get_byte() ); + + } else { + + file->get_byte(); // skip + file->get_byte(); // skip + file->get_byte(); // skip + file->get_byte(); // skip + file->get_byte(); // skip + } + file->get_byte(); // ZERO Byte + header.msglength=file->get_word(); + header.msgoffset=file->get_dword(); + char chibi[4]; + file->get_byte_array((uint8_t*)chibi,4); + header.is_chibi=(chibi[0]=='C' && chibi[1]=='H' && chibi[2]=='B' && chibi[3]=='I'); + + for (int i=0;i<64;i++) { + + uint8_t panbyte=file->get_byte(); + + uint8_t pan_dst=(panbyte<65) ? panbyte : 32; + bool surround_dst=(panbyte==100); + bool mute_dst=(panbyte>=128); + + if (!p_dont_set) { + song->set_channel_pan( i, pan_dst ); + song->set_channel_surround( i, surround_dst ); + song->set_channel_mute( i, mute_dst ); + } + } + for (int i=0;i<64;i++) { + unsigned char cv = file->get_byte(); + if (!p_dont_set) + song->set_channel_volume( i, cv ); + } + + CP_ERR_COND_V( file->eof_reached(),FILE_CORRUPTED ); + CP_ERR_COND_V( file->get_error(),FILE_CORRUPTED ); + + return FILE_OK; +} + +CPLoader::Error CPLoader_IT::load_effects() { + + if (!header.is_chibi) + return FILE_OK; //no effects, regular IT file + + /* GOTO End of IT header */ + file->seek(0xC0+header.ordnum+header.insnum*4+header.smpnum*4+header.patnum*4); + + + if (file->get_byte()>0) //not made with this version, ignore extended info + return FILE_OK; + + /* Chibitracker Extended info */ + + switch(file->get_byte()) { + + case CPSong::REVERB_MODE_ROOM: { + + song->set_reverb_mode( CPSong::REVERB_MODE_ROOM ); + } break; + case CPSong::REVERB_MODE_STUDIO_SMALL: { + + song->set_reverb_mode( CPSong::REVERB_MODE_STUDIO_SMALL ); + + } break; + case CPSong::REVERB_MODE_STUDIO_MEDIUM: { + + song->set_reverb_mode( CPSong::REVERB_MODE_STUDIO_MEDIUM ); + + } break; + case CPSong::REVERB_MODE_STUDIO_LARGE: { + + song->set_reverb_mode( CPSong::REVERB_MODE_STUDIO_LARGE ); + + } break; + case CPSong::REVERB_MODE_HALL: { + + song->set_reverb_mode( CPSong::REVERB_MODE_HALL ); + + } break; + case CPSong::REVERB_MODE_SPACE_ECHO: { + + song->set_reverb_mode( CPSong::REVERB_MODE_SPACE_ECHO ); + + } break; + + case CPSong::REVERB_MODE_ECHO: { + + song->set_reverb_mode( CPSong::REVERB_MODE_ECHO ); + + } break; + case CPSong::REVERB_MODE_DELAY: { + + song->set_reverb_mode( CPSong::REVERB_MODE_DELAY ); + + } break; + case CPSong::REVERB_MODE_HALF_ECHO: { + + song->set_reverb_mode( CPSong::REVERB_MODE_HALF_ECHO ); + + } break; + + } + + //chorus + song->set_chorus_speed_hz10( file->get_byte() ); + song->set_chorus_delay_ms( file->get_byte() ); + song->set_chorus_depth_ms10( file->get_byte() ); + song->set_chorus_separation_ms( file->get_byte() ); + + for (int i=0;iset_channel_reverb(i,file->get_byte()); + } + for (int i=0;iset_channel_chorus(i,file->get_byte()); + } + + return FILE_OK; + +} + +CPLoader::Error CPLoader_IT::load_message() { + + + if (!(header.special & 1)) { + + return FILE_OK; + } + + + file->seek(header.msgoffset); + + //(void*)tmpmsg=malloc(header.msglength+1); + + char message[8000]; + + + char *tmpmsg = message; + + file->get_byte_array((uint8_t*)tmpmsg,header.msglength); + tmpmsg[header.msglength]=0; + + for (int i=0;iset_message(tmpmsg); + + return FILE_OK; +} + +CPLoader::Error CPLoader_IT::load_orders() { + + file->seek(0xC0); + + + for (int i=0;iget_byte(); + CPOrder order=CP_ORDER_NONE; + + + if (i>=CPSong::MAX_ORDERS) + continue; + if (aux_order==254) { + + order=CP_ORDER_BREAK; + + } else if (aux_order<200) { + + order=aux_order; + //nothing! + + } + song->set_order(i,order); + + } + + if (file->eof_reached() || file->get_error()) { + + + return FILE_CORRUPTED; + + } + + return FILE_OK; +} + + + diff --git a/modules/chibi/cp_loader_it_instruments.cpp b/modules/chibi/cp_loader_it_instruments.cpp new file mode 100644 index 0000000000..ccb24bd81c --- /dev/null +++ b/modules/chibi/cp_loader_it_instruments.cpp @@ -0,0 +1,224 @@ +/*************************************************************************/ +/* cp_loader_it_instruments.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_loader_it.h" + +enum EnvFlags { + ENV_ON=1, + ENV_LOOP=2, + ENV_SUSLOOP=4, + ENV_CARRY=8, + ENV_FILTER=128 +}; + +void CPLoader_IT::load_envelope(CPEnvelope *p_envelope,bool*p_has_filter_flag) { + + uint8_t flags=file->get_byte(); + uint8_t points=file->get_byte(); + uint8_t begin=file->get_byte(); + uint8_t end=file->get_byte(); + uint8_t susbegin=file->get_byte(); + uint8_t susend=file->get_byte(); + + p_envelope->reset(); + + for (int i=0;i<25;i++) { + + uint8_t height=file->get_byte(); + int8_t &signed_height=(int8_t&)height; + uint16_t tick=file->get_word(); + + if (i>=points) + continue; + p_envelope->add_position( tick, signed_height ); + + } + + p_envelope->set_enabled( flags & ENV_ON ); + p_envelope->set_carry_enabled( flags & ENV_CARRY); + + p_envelope->set_loop_enabled( flags & ENV_LOOP ); + p_envelope->set_loop_begin( begin ); + p_envelope->set_loop_end( end ); + + p_envelope->set_sustain_loop_enabled( flags & ENV_SUSLOOP ); + p_envelope->set_sustain_loop_begin( susbegin ); + p_envelope->set_sustain_loop_end( susend ); + + if (p_has_filter_flag) + *p_has_filter_flag=flags&ENV_FILTER; + + file->get_byte(); //zerobyte + + //fill with stuff if the envelope hass less than 2 points + while(p_envelope->get_node_count()<2) { + + p_envelope->add_position( 30*p_envelope->get_node_count(), p_envelope->get_min()==0 ? 64 : 0, false ); + } +} + + +CPLoader::Error CPLoader_IT::load_instrument(CPInstrument *p_instrument,int *p_samples) { + + + + char aux_header[4]; + + file->get_byte_array((uint8_t*)aux_header,4); + + + if ( aux_header[0]!='I' || + aux_header[1]!='M' || + aux_header[2]!='P' || + aux_header[3]!='I') { + CP_PRINTERR("IT CPLoader CPInstrument: Failed Identifier"); + + return FILE_UNRECOGNIZED; + } + + + + // Ignore deprecated 8.3 filename field + for (int i=0;i<12;i++) file->get_byte(); + + //Ignore zerobyte + file->get_byte(); /* (byte) CPInstrument type (always 0) */ + + switch( file->get_byte() ) { /* New CPNote Action [0,1,2,3] */ + case 0: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_CUT ) ; break; + case 1: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_CONTINUE ) ; break; + case 2: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_OFF ) ; break; + case 3: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_FADE ) ; break; + }; + switch( file->get_byte() ) { // Duplicate Check Type + case 0: p_instrument->set_DC_type( CPInstrument::DCT_DISABLED ); break ; + case 1: p_instrument->set_DC_type( CPInstrument::DCT_NOTE ); break ; + case 2: p_instrument->set_DC_type( CPInstrument::DCT_SAMPLE ); break ; + case 3: p_instrument->set_DC_type( CPInstrument::DCT_INSTRUMENT ); break ; + } + switch( file->get_byte() ) { //Duplicate Check Action + case 0: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_CUT ); break ; + case 1: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_OFF ); break ; + case 2: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_FADE ); break ; + } + + int fade = file->get_word(); + //intf("AFADE: %i\n",fade); + if (fade>CPInstrument::MAX_FADEOUT) //needs to be clipped because of horrible modplug doings + fade=CPInstrument::MAX_FADEOUT; + + p_instrument->set_volume_fadeout( fade ); + p_instrument->set_pan_pitch_separation( file->get_byte() ); + p_instrument->set_pan_pitch_center( file->get_byte() ); + p_instrument->set_volume_global_amount( file->get_byte() ); + uint8_t pan=file->get_byte(); + p_instrument->set_pan_default_amount(pan&0x7F); + p_instrument->set_pan_default_enabled( !(pan&0x80) ); + p_instrument->set_volume_random_variation( file->get_byte() ); + p_instrument->set_pan_random_variation( file->get_byte() ); + + + + file->get_word(); //empty (version) + uint8_t samples=file->get_byte(); + if (p_samples) + *p_samples=samples; + file->get_byte(); //empty + char aux_name[26]; + file->get_byte_array((uint8_t*)aux_name,26); + p_instrument->set_name(aux_name); + + uint8_t cutoff=file->get_byte(); + + p_instrument->set_filter_default_cutoff(cutoff&0x7F); + p_instrument->set_filter_use_default_cutoff(cutoff&0x80); + + uint8_t resonance=file->get_byte(); + + p_instrument->set_filter_default_resonance(resonance&0x7F); + p_instrument->set_filter_use_default_resonance(resonance&0x80); + + file->get_dword(); //MIDI, IGNORED! + + /* CPNote -> CPSample table */ + for (uint8_t i=0;iget_byte(); + if (note>=CPNote::NOTES) + note=0; + p_instrument->set_note_number(i,note); + + uint8_t samp=file->get_byte(); + if (samp==0 || samp>99) + samp=CPNote::EMPTY; + else + samp--; + + + p_instrument->set_sample_number(i,samp); + + + } + + + load_envelope( p_instrument->get_volume_envelope() ); + load_envelope( p_instrument->get_pan_envelope() ); + bool use_as_filter; + load_envelope( p_instrument->get_pitch_filter_envelope(), &use_as_filter ); + p_instrument->set_pitch_use_as_filter( use_as_filter ); + + return FILE_OK; + +} + + +CPLoader::Error CPLoader_IT::load_instruments() { + + + for (int i=0;iseek(0xC0+header.ordnum+i*4); + uint32_t final_location=file->get_dword(); + file->seek( final_location ); + + Error err=load_instrument( song->get_instrument( i ) ); + if (err) + return err; + + } + + return FILE_OK; + + if (file->eof_reached() || file->get_error()) + return FILE_CORRUPTED; +} + + diff --git a/modules/chibi/cp_loader_it_patterns.cpp b/modules/chibi/cp_loader_it_patterns.cpp new file mode 100644 index 0000000000..d951a91620 --- /dev/null +++ b/modules/chibi/cp_loader_it_patterns.cpp @@ -0,0 +1,166 @@ +/*************************************************************************/ +/* cp_loader_it_patterns.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_loader_it.h" + + +CPLoader::Error CPLoader_IT::load_patterns() { + + + for (int i=0;i=CPSong::MAX_PATTERNS) + break; + + /* Position where pattern offsets are stored */ + file->seek(0xC0+header.ordnum+header.insnum*4+header.smpnum*4+i*4); + uint32_t pattern_offset=file->get_dword(); + + if (pattern_offset==0) { + + continue; + } + + uint16_t pat_size; + uint16_t pat_length; + + int row=0,flag,channel,j; + uint8_t aux_byte; + uint32_t reserved; + uint8_t chan_mask[64]; //mask cache for each + CPNote last_value[64]; //last value of each + + for (j=0;j<64;j++) { + + chan_mask[j]=0; + last_value[j].clear(); + } + + file->seek(pattern_offset); + + pat_size=file->get_word(); + pat_length=file->get_word(); + reserved=file->get_dword(); + + song->get_pattern(i)->set_length( pat_length ); + + do { + + aux_byte=file->get_byte(); + flag=aux_byte; + + if ( flag==0 ) { + + row++; + } else { + + channel=(flag-1) & 63; + + if ( flag & 128 ) { + + aux_byte=file->get_byte(); + chan_mask[channel]=aux_byte; + } + + CPNote note; //note used for reading + + if ( chan_mask[channel]&1 ) { // read note + + aux_byte=file->get_byte(); + + if ( aux_byte<120 ) + note.note=aux_byte; + else if ( aux_byte==255 ) + note.note=CPNote::OFF; + else if ( aux_byte==254 ) + note.note=CPNote::CUT; + + last_value[channel].note=note.note; + } + + + if ( chan_mask[channel]&2 ) { + + aux_byte=file->get_byte(); + if ( aux_byte<100 ) + note.instrument=aux_byte-1; + + last_value[channel].instrument=note.instrument; + } + if ( chan_mask[channel]&4 ) { + + aux_byte=file->get_byte(); + if ( aux_byte<213 ) + note.volume=aux_byte; + + last_value[channel].volume=note.volume; + } + if ( chan_mask[channel]&8 ) { + + aux_byte=file->get_byte(); + if ( aux_byte>0 ) + note.command=aux_byte-1; + + + last_value[channel].command=note.command; + + note.parameter=file->get_byte(); + + last_value[channel].parameter=note.parameter; + } + + if ( chan_mask[channel]&16 ) { + + note.note=last_value[channel].note; + } + + if ( chan_mask[channel]&32 ) { + + note.instrument=last_value[channel].instrument; + } + if ( chan_mask[channel]&64 ) { + + note.volume=last_value[channel].volume; + } + if ( chan_mask[channel]&128 ) { + + note.command=last_value[channel].command; + note.parameter=last_value[channel].parameter; + } + + song->get_pattern(i)->set_note(channel,row,note); + } + + + } while(rowget_byte_array((uint8_t*)aux_header,4); + + if ( aux_header[0]!='I' || + aux_header[1]!='M' || + aux_header[2]!='P' || + aux_header[3]!='S') { + + //CP_PRINTERR("IT CPLoader CPSample: Failed Identifier"); + return FILE_UNRECOGNIZED; + } + + + // Ignore deprecated 8.3 filename + for (int i=0;i<12;i++) file->get_byte(); + + file->get_byte(); //ignore zerobyte + + p_sample->set_global_volume( file->get_byte() ); + + /* SAMPLE FLAGS */ + uint8_t flags=file->get_byte(); + aux_sample_data.loop_enabled=flags&IT_SAMPLE_LOOPED; + aux_sample_data.pingpong_enabled=flags&IT_SAMPLE_LOOP_IS_PINGPONG; + aux_sample_data.is16bit=flags&IT_SAMPLE_16BITS; + aux_sample_data.exists=flags&IT_SAMPLE_EXISTS; + aux_sample_data.stereo=flags&IT_SAMPLE_STEREO; + aux_sample_data.compressed=flags&IT_SAMPLE_COMPRESSED; + + p_sample->set_default_volume(file->get_byte()); + /* SAMPLE NAME */ + char aux_name[26]; + file->get_byte_array((uint8_t*)aux_name,26); + p_sample->set_name(aux_name); + + // ?? + uint8_t convert_flag=file->get_byte(); + // PAN + uint8_t pan=file->get_byte(); + p_sample->set_pan( pan&0x7F ); + p_sample->set_pan_enabled( pan & 0x80 ); + + aux_sample_data.length=file->get_dword(); + + + aux_sample_data.loop_begin= file->get_dword(); + aux_sample_data.loop_end= file->get_dword(); + aux_sample_data.c5spd=file->get_dword(); + /*p_sample->data.set_sustain_loop_begin=*/file->get_dword(); + /*p_sample->data.sustain_loop_end=*/file->get_dword(); + aux_sample_data.fileofs=file->get_dword(); + p_sample->set_vibrato_speed( file->get_byte() ); + p_sample->set_vibrato_depth( file->get_byte() ); + p_sample->set_vibrato_rate( file->get_byte() ); + switch( file->get_byte() ) { + /* Vibrato Wave: 0=sine, 1=rampdown, 2=square, 3=random */ + case 0: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break; + case 1: p_sample->set_vibrato_type( CPSample::VIBRATO_SAW ); break; + case 2: p_sample->set_vibrato_type( CPSample::VIBRATO_SQUARE ); break; + case 3: p_sample->set_vibrato_type( CPSample::VIBRATO_RANDOM ); break; + default: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break; + } + + //printf("Name %s - Flags: fileofs :%i - c5spd %i - len %i 16b %i - data?: %i\n",p_sample->get_name(),aux_sample_data.fileofs,aux_sample_data.c5spd, aux_sample_data.length, aux_sample_data.is16bit,aux_sample_data.exists); + CPSample_ID samp_id; + + if (aux_sample_data.exists) { + samp_id=load_sample_data(aux_sample_data); + CPSampleManager::get_singleton()->set_c5_freq(samp_id,aux_sample_data.c5spd); + CPSampleManager::get_singleton()->set_loop_begin( samp_id,aux_sample_data.loop_begin ); + CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end ); + CPSample_Loop_Type loop_type=aux_sample_data.loop_enabled?( aux_sample_data.pingpong_enabled? CP_LOOP_BIDI: CP_LOOP_FORWARD):CP_LOOP_NONE; + CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end ); + CPSampleManager::get_singleton()->set_loop_type( samp_id, loop_type); + + } + + //printf("Loaded id is null?: %i\n",samp_id.is_null()); + p_sample->set_sample_data(samp_id); + if (!samp_id.is_null()) { + + // printf("Loaded ID: stereo: %i len %i 16bit %i\n",CPSampleManager::get_singleton()->is_stereo(samp_id), CPSampleManager::get_singleton()->get_size( samp_id), CPSampleManager::get_singleton()->is_16bits( samp_id) ); + } + + CP_ERR_COND_V( file->eof_reached(),FILE_CORRUPTED ); + CP_ERR_COND_V( file->get_error(),FILE_CORRUPTED ); + + return FILE_OK; + +} + +CPSample_ID CPLoader_IT::load_sample_data(AuxSampleData& p_sample_data) { + + + int aux_sample_properties = (p_sample_data.is16bit?IT_SAMPLE_16BITS:0)|(p_sample_data.compressed?IT_SAMPLE_COMPRESSED:0)|(p_sample_data.stereo?IT_SAMPLE_STEREO:0); + + file->seek(p_sample_data.fileofs); + + CPSampleManager *sm=CPSampleManager::get_singleton(); + + CPSample_ID id; + + switch (aux_sample_properties) { + + case (0): // 8 bits, mono + case (IT_SAMPLE_16BITS): // 16 bits mono + case (IT_SAMPLE_STEREO): // 8 bits stereo + case (IT_SAMPLE_16BITS|IT_SAMPLE_STEREO): { // 16 bits mono + + id=sm->create(p_sample_data.is16bit,p_sample_data.stereo,p_sample_data.length); + if (id.is_null()) + break; + + sm->lock_data(id); + + int16_t *ptr16 = (int16_t*)sm->get_data(id); + int8_t *ptr8=(int8_t*)ptr16; + + int chans=p_sample_data.stereo?2:1; + + if (p_sample_data.is16bit) { + + for (int c=0;cget_word(); + } + } + } else { + + for (int c=0;cget_byte(); + } + } + + } + + sm->unlock_data(id); + + } break; + case (IT_SAMPLE_COMPRESSED): { // 8 bits compressed + + + id=sm->create(false,false,p_sample_data.length); + if (id.is_null()) + break; + sm->lock_data(id); + + if ( load_sample_8bits_IT_compressed((void*)sm->get_data( id),p_sample_data.length) ) { + + sm->unlock_data(id); + sm->destroy(id); + + break; + } + + sm->unlock_data(id); + + + } break; + case (IT_SAMPLE_16BITS|IT_SAMPLE_COMPRESSED): { // 16 bits compressed + + + id=sm->create(true,false,p_sample_data.length); + if (id.is_null()) + break; + sm->lock_data(id); + + if ( load_sample_16bits_IT_compressed((void*)sm->get_data(id),p_sample_data.length) ) { + + sm->unlock_data(id); + sm->destroy(id); + break; + } + + sm->unlock_data(id); + + } break; + default: { + + // I dont know how to handle stereo compressed, does that exist? + } break; + + } + + + return id; +} + + +CPLoader::Error CPLoader_IT::load_samples() { + + for (int i=0;iseek(0xC0+header.ordnum+header.insnum*4+i*4); + + uint32_t final_location=file->get_dword(); + file->seek( final_location ); + + + Error err=load_sample(song->get_sample(i)); + CP_ERR_COND_V(err,err); + + } + + if (file->eof_reached() || file->get_error()) + return FILE_CORRUPTED; + + return FILE_OK; +} +/* * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE + + -The following sample decompression code is based on xmp's code.(http://xmp.helllabs.org) which is based in openCP code. + +* NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE */ + +uint32_t CPLoader_IT::read_n_bits_from_IT_compressed_block (uint8_t p_bits_to_read) { + + uint32_t aux_return_value; + uint32_t val; + + uint8_t *buffer=(uint8_t*)source_position; + if ( p_bits_to_read <= source_remaining_bits ) { + + val=buffer[3]; + val<<=8; + val|=buffer[2]; + val<<=8; + val|=buffer[1]; + val<<=8; + val|=buffer[0]; + + aux_return_value = val & ((1 << p_bits_to_read) - 1); + val >>= p_bits_to_read; + source_remaining_bits -= p_bits_to_read; + + buffer[3]=val>>24; + buffer[2]=(val>>16)&0xFF; + buffer[1]=(val>>8)&0xFF; + buffer[0]=(val)&0xFF; + + } else { + aux_return_value=buffer[3]; + aux_return_value<<=8; + aux_return_value|=buffer[2]; + aux_return_value<<=8; + aux_return_value|=buffer[1]; + aux_return_value<<=8; + aux_return_value|=buffer[0]; + + uint32_t nbits = p_bits_to_read - source_remaining_bits; + source_position++; + + buffer+=4; + val=buffer[3]; + val<<=8; + val|=buffer[2]; + val<<=8; + val|=buffer[1]; + val<<=8; + val|=buffer[0]; + aux_return_value |= ((val & ((1 << nbits) - 1)) << source_remaining_bits); + val >>= nbits; + source_remaining_bits = 32 - nbits; + buffer[3]=val>>24; + buffer[2]=(val>>16)&0xFF; + buffer[1]=(val>>8)&0xFF; + buffer[0]=(val)&0xFF; + + } + + return aux_return_value; +} + +bool CPLoader_IT::read_IT_compressed_block (bool p_16bits) { + + uint16_t size; + + size=file->get_word(); + + if (file->eof_reached() || file->get_error()) return true; + + pat_data = (uint8_t*)CP_ALLOC( 4* ((size >> 2) + 2) ); + if (!pat_data) + return true; + + + source_buffer=(uint32_t*)pat_data; + file->get_byte_array((uint8_t*)source_buffer,size); + + if (file->eof_reached() || file->get_error()) { + + free_IT_compressed_block(); + return true; + } + + source_position = source_buffer; + source_remaining_bits = 32; + + return false; +} + +void CPLoader_IT::free_IT_compressed_block () { + + + if (pat_data) { + CP_FREE(pat_data); + pat_data=NULL; + } + +} + +bool CPLoader_IT::load_sample_8bits_IT_compressed(void *p_dest_buffer,int p_buffsize) { + + int8_t *dest_buffer; /* destination buffer which will be returned */ + uint16_t block_length; /* length of compressed data block in samples */ + uint16_t block_position; /* position in block */ + uint8_t bit_width; /* actual "bit width" */ + uint16_t aux_value; /* value read from file to be processed */ + int8_t d1, d2; /* integrator buffers (d2 for it2.15) */ + int8_t *dest_position; /* position in output buffer */ + int8_t v; /* sample value */ + bool it215; // is this an it215 module? + + dest_buffer = (int8_t *) p_dest_buffer; + + if (dest_buffer==NULL) + return true; + + for (int i=0;i read new width; */ + bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; + /* and expand it */ + continue; /* ... next value */ + } + + } else if ( bit_width < 9 ) { /* method 2 (7-8 bits) */ + + uint8_t border = (0xFF >> (9 - bit_width)) - 4; + /* lower border for width chg */ + + if ( aux_value > border && aux_value <= (border + 8) ) { + + aux_value -= border; /* convert width to 1-8 */ + bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; + /* and expand it */ + continue; /* ... next value */ + } + + + } else if ( bit_width == 9 ) { /* method 3 (9 bits) */ + + if ( aux_value & 0x100 ) { /* bit 8 set? */ + + bit_width = (aux_value + 1) & 0xff; /* new width... */ + continue; /* ... and next value */ + } + + } else { /* illegal width, abort */ + + + free_IT_compressed_block(); + CP_PRINTERR("CPSample has illegal BitWidth "); + return true; + } + + /* now expand value to signed byte */ + if ( bit_width < 8 ) { + + uint8_t tmp_shift = 8 - bit_width; + + v=(aux_value << tmp_shift); + v>>=tmp_shift; + + } else v = (int8_t) aux_value; + + /* integrate upon the sample values */ + d1 += v; + d2 += d1; + + /* ... and store it into the buffer */ + *(dest_position++) = it215 ? d2 : d1; + block_position++; + + } + + /* now subtract block lenght from total length and go on */ + free_IT_compressed_block(); + p_buffsize -= block_length; + } + + + return false; +} + +bool CPLoader_IT::load_sample_16bits_IT_compressed(void *p_dest_buffer,int p_buffsize) { + + int16_t *dest_buffer; /* destination buffer which will be returned */ + uint16_t block_length; /* length of compressed data block in samples */ + uint16_t block_position; /* position in block */ + uint8_t bit_width; /* actual "bit width" */ + uint32_t aux_value; /* value read from file to be processed */ + int16_t d1, d2; /* integrator buffers (d2 for it2.15) */ + int16_t *dest_position; /* position in output buffer */ + int16_t v; /* sample value */ + + bool it215; // is this an it215 module? + + dest_buffer = (int16_t *) p_dest_buffer; + + if (dest_buffer==NULL) + return true; + + for (int i=0;i read new width; */ + bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; + /* and expand it */ + continue; /* ... next value */ + } + + } else if ( bit_width < 17 ) { + + uint16_t border = (0xFFFF >> (17 - bit_width)) - 8; + + if ( (int)aux_value > (int)border && (int)aux_value <= ((int)border + 16) ) { + + aux_value -= border; /* convert width to 1-8 */ + bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; + /* and expand it */ + continue; /* ... next value */ + } + + + } else if ( bit_width == 17 ) { + + if ( aux_value & 0x10000 ) { /* bit 8 set? */ + + bit_width = (aux_value + 1) & 0xff; /* new width... */ + continue; /* ... and next value */ + } + + } else { /* illegal width, abort */ + + CP_PRINTERR("CPSample has illegal BitWidth "); + + free_IT_compressed_block(); + + return true; + } + + /* now expand value to signed byte */ + if ( bit_width < 16 ) { + + uint8_t tmp_shift = 16 - bit_width; + + v=(aux_value << tmp_shift); + v>>=tmp_shift; + + } else v = (int16_t) aux_value; + + /* integrate upon the sample values */ + d1 += v; + d2 += d1; + + /* ... and store it into the buffer */ + *(dest_position++) = it215 ? d2 : d1; + block_position++; + + } + + /* now subtract block lenght from total length and go on */ + free_IT_compressed_block(); + p_buffsize -= block_length; + } + + + return false; + +} + + + diff --git a/modules/chibi/cp_loader_mod.cpp b/modules/chibi/cp_loader_mod.cpp new file mode 100644 index 0000000000..f867b77914 --- /dev/null +++ b/modules/chibi/cp_loader_mod.cpp @@ -0,0 +1,482 @@ +/*************************************************************************/ +/* cp_loader_mod.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_loader_mod.h" + + +static bool tag_equal_to(const char *p_tag, const char *p_string) { + + return( p_tag[0]==p_string[0] && + p_tag[1]==p_string[1] && + p_tag[2]==p_string[2] && + p_tag[3]==p_string[3]); +} +/* ProTracker period table */ +uint16_t period_table[6*12] = { + 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907, + 856,808,762,720,678,640,604,570,538,508,480,453, + 428,404,381,360,339,320,302,285,269,254,240,226, + 214,202,190,180,170,160,151,143,135,127,120,113, + 107,101,95,90,85,80,75,71,67,63,60,56, + 53,50,47,45,42,40,37,35,33,31,30,28 +}; + + +CPLoader::Error CPLoader_MOD::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) { + + if (file->open(p_file,CPFileAccessWrapper::READ)) { + //printf("Can't open file! %s\n",p_file); + return FILE_CANNOT_OPEN; + }; + + /* FIRST OF ALL, one needs to read the .mod file format tag */ + file->seek( 1080 ); //located at 1080 + + char format_tag[4]; + + file->get_byte_array( (uint8_t*)format_tag, 4 ); + + int channels=-1; + + /** THE PAIN!! - COMPARE TAGS */ + + /* Classic 4-chan */ + if (tag_equal_to(format_tag,"M.K.") ) + channels=4; + if (tag_equal_to(format_tag,"FLT4") ) + channels=4; + if (tag_equal_to(format_tag,"M!K!") ) + channels=4; + + /* 8 Channel MODS */ + + if (tag_equal_to(format_tag,"FLT8") ) + channels=2; + + if (tag_equal_to(format_tag,"CD81") ) + channels=2; + + /* Custom channel MODS */ + + for (int i=1;i<=32;i++) { + + if (i<10) { // up to 9 channels mods + + /* Old Take Tracker */ + char old_take_tracker[4]={'T','D','Z',char('0'+i)}; + + if (tag_equal_to(format_tag,old_take_tracker)) { + + channels=i; + break; + } + + /* Contemplates many XCHN Formats */ + char xchn[4]={char('0'+i),'C','H','N'}; + + if (tag_equal_to(format_tag,xchn)) { + + channels=i; + break; + } + } + + /* Fast Tracker */ + char fast_tracker[4]={char('0'+(i/10)),char('0'+(i%10)),'C','H'}; + + if (tag_equal_to(format_tag,fast_tracker)) { + + channels=i; + break; + } + + } + + + if (channels==-1) { + + file->close(); + return FILE_UNRECOGNIZED; + } + + + + /** Load CPSong INFO */ + + file->seek( 0 ); //go to begining of file + + file->set_endian_conversion( true ); + p_song->reset(); + p_song->set_instruments( false ); + + char name[21]; + + file->get_byte_array( (uint8_t*)name,20); + name[20]=0; + + p_song->set_name(name); + p_song->set_old_effects( true ); + p_song->set_linear_slides( false ); + p_song->set_compatible_gxx( true ); + + + + CPSampleManager *sm=CPSampleManager::get_singleton(); + + int instruments=31; + + for (int i=0;iget_byte_array( (uint8_t*)sample_name,22); + sample_name[22]=0; + + uint32_t sample_len=file->get_word(); + sample_len<<=1; + + uint8_t fine_nibble=file->get_byte()&0xF; + + + //(int8_t)(fine_nibble & 7) - (int8_t)(fine_nibble & 8); //yesso's genius trick + // boo, I can't use it :( but i leave it here because of how cool it is + uint8_t linear_volume=file->get_byte(); //0 .. ? + + uint32_t loop_begin=file->get_word(); //0 .. ? + loop_begin<<=1; + uint32_t loop_end=file->get_word(); //0 .. ? + loop_end<<=1; + + if (sample_len>0) { + + CPSample_ID sid=sm->create( false, false, sample_len ); + + if (sid.is_null()) { + + file->close(); + return FILE_OUT_OF_MEMORY; + } + + if (loop_end>2) { + sm->set_loop_begin( sid, loop_begin ); + sm->set_loop_end( sid, loop_end+loop_begin ); + sm->set_loop_type( sid,CP_LOOP_FORWARD ); + } + static const uint16_t fine_to_freq[16]={ + 8363,8413,8463,8529,8581,8651,8723,8757, + 7895,7941,7985,8046,8107,8169,8232,8280 + }; + + sm->set_c5_freq( sid, fine_to_freq[fine_nibble] ); + p_song->get_sample(i)->set_sample_data(sid); + } + + p_song->get_sample(i)->set_name(sample_name); + p_song->get_sample(i)->set_default_volume( linear_volume ); + + + + } + + /* pan for MODs */ + for (int i=0;iset_channel_pan( i, (((i&3)==1) || ((i&3)==2)) ? 0: 64); + + + uint8_t order_count=file->get_byte(); +// uint8_t loop_to=file->get_byte(); + + + int pattern_count=0; + + for (int i=0;i<128;i++) { + + uint8_t order=file->get_byte(); + + + if (iset_order(i,order); + + /* Determine the amount of patterns */ + if ((order+1)>pattern_count) + pattern_count=order+1; + } else + p_song->set_order( i, CP_ORDER_NONE ); + } + + if (instruments==31) + file->get_dword(); // identiefier, now skip it + + for (int i=0;iget_dword(); + + CPNote note; + + note.instrument=(note_w>>12)&0xF; + note.instrument|=(note_w>>24)&0xF0; + + if (note.instrument==0) + note.instrument=CPNote::EMPTY; + else + note.instrument--; + + note.parameter=note_w&0xFF; + + int cmd=(note_w>>8)&0xF; + + uint32_t period=(note_w>>16)&0xFFF; + + if (period>0 && period<0xFFF) { + + //period>>=2; + //period<<=1; + for (int n=0; n<6*12; n++) { + + if (period >= period_table[n]) { + + if ((period!=period_table[n]) && (n)) + { + uint32_t p1 = period_table[n-1]; + uint32_t p2 = period_table[n]; + if (p1 - period < (period - p2)) { + + note.note=n+36; + break; + } + } + note.note=n+1+36; + break; + } + } + if (note.note==CPNote::EMPTY) + note.note=6*12+36; + + note.note--; + } + + + switch(cmd) { + + case 0x0: { + + if (note.parameter>0) + note.command='J'-'A'; + } break; + case 0x1: { + note.command='F'-'A'; + } break; + case 0x2: { + + note.command='E'-'A'; + } break; + case 0x3: { + + note.command='G'-'A'; + } break; + case 0x4: { + + note.command='H'-'A'; + } break; + case 0x5: { + note.command='L'-'A'; + } break; + case 0x6: { + + note.command='K'-'A'; + } break; + case 0x7: { + note.command='R'-'A'; + } break; + case 0x8: { + + note.command='X'-'A'; + } break; + case 0x9: { + + note.command='O'-'A'; + + } break; + case 0xA: { + + note.command='D'-'A'; + + } break; + case 0xB: { + + note.command='B'-'A'; + + } break; + case 0xC: { + + note.volume=note.parameter; + if (note.volume>64) + note.volume=64; + note.parameter=0; + + } break; + case 0xD: { + + note.command='C'-'A'; + note.parameter=(note.parameter>>4)*10 + (note.parameter&0xF); + + } break; + case 0xE: { //SPECIAL EFFECT! + + note.command='S'-'A'; + + switch(note.parameter>>4) { + + case 0x1: { + + note.command='F'-'A'; + note.parameter=0xF0|(note.parameter&0xF); + } break; + case 0x2: { + + note.command='E'-'A'; + note.parameter=0xF0|(note.parameter&0xF); + } break; + case 0x4: { + + note.command='S'-'A'; + note.parameter=0x30|(note.parameter&0x3); + + } break; + case 0x6: { + + note.command='S'-'A'; + note.parameter=0xB0|(note.parameter&0xF); + + } break; + case 0x7: { + note.command='S'-'A'; + note.parameter=0x40|(note.parameter&0x3); + + } break; + case 0x8: { + + note.command='S'-'A'; // wow, it's the same! + + } break; + case 0x9: { + note.command='Q'-'A'; + note.parameter=(note.parameter&0xF); + + } break; + case 0xA: { + + note.command='D'-'A'; + note.parameter=0xF|((note.parameter&0xF)<<4); + + } break; + case 0xB: { + note.command='D'-'A'; + note.parameter=0xF0|(note.parameter&0xF); + + } break; + case 0xC: + case 0xD: { + + note.command='S'-'A'; //wow, they are the same! + + } break; + case 0xE: { + note.command='S'-'A'; + note.parameter=0x60|(note.parameter&0xF); + + } break; + + default: { + + note.command=CPNote::EMPTY; + note.parameter=0; + } break; + + } + } break; + case 0xF: { + + if (note.parameter<32) + note.command='A'-'A'; + else + note.command='T'-'A'; + + } break; + } + + p_song->get_pattern(i)->set_note( column,line, note ); + } + } + } + + + + for (int i=0;iget_sample(i)->get_sample_data(); + if (sid.is_null()) { + continue; //empty sample, not stored? + } + sm->lock_data(sid); + uint8_t *dataptr = (uint8_t*)sm->get_data(sid); + + int len=sm->get_size(sid); + for (int s=0;sget_byte(); + //d-=128; //convert to signed + int8_t*ds=(int8_t*)&d; + dataptr[s]=*ds; + + } + sm->unlock_data(sid); + } + + file->close(); + + return FILE_OK; + + +} + + +CPLoader_MOD::CPLoader_MOD(CPFileAccessWrapper *p_file) { + + file=p_file; +} + + +CPLoader_MOD::~CPLoader_MOD() +{ +} + + diff --git a/modules/chibi/cp_loader_mod.h b/modules/chibi/cp_loader_mod.h new file mode 100644 index 0000000000..636f4f00f2 --- /dev/null +++ b/modules/chibi/cp_loader_mod.h @@ -0,0 +1,52 @@ +/*************************************************************************/ +/* cp_loader_mod.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_LOADER_MOD_H +#define CP_LOADER_MOD_H +#include "cp_loader.h" +/** + @author Juan Linietsky +*/ +class CPLoader_MOD : public CPLoader { + + CPFileAccessWrapper *file; +public: + + bool can_load_song() { return true; } + bool can_load_sample() { return false; } + bool can_load_instrument() { return false; } + + Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset); + Error load_sample(const char *p_file,CPSample *p_sample) { return FILE_UNRECOGNIZED; } + Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { return FILE_UNRECOGNIZED; } + + CPLoader_MOD(CPFileAccessWrapper *p_file); + ~CPLoader_MOD(); +}; + +#endif diff --git a/modules/chibi/cp_loader_s3m.cpp b/modules/chibi/cp_loader_s3m.cpp new file mode 100644 index 0000000000..0fc15c1e2f --- /dev/null +++ b/modules/chibi/cp_loader_s3m.cpp @@ -0,0 +1,413 @@ +/*************************************************************************/ +/* cp_loader_s3m.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_loader_s3m.h" + +#define BITBOOL(m_exp) ((m_exp)?1:0) + + +CPLoader::Error CPLoader_S3M::load_header() { + + int i; + + + file->get_byte_array((uint8_t*)header.songname,28); + header.t1a=file->get_byte(); + header.type=file->get_byte(); + file->get_byte_array((uint8_t*)header.unused1,2); + header.ordnum=file->get_word(); + header.insnum=file->get_word(); + header.patnum=file->get_word(); + header.flags=file->get_word(); + header.tracker=file->get_word(); + header.fileformat=file->get_word(); + file->get_byte_array((uint8_t*)header.scrm,4); + header.scrm[4]=0; + + if (header.scrm[0]!='S' || header.scrm[1]!='C' || header.scrm[2]!='R' || header.scrm[3]!='M') + return FILE_UNRECOGNIZED; + + header.mastervol=file->get_byte(); + header.initspeed=file->get_byte(); + header.inittempo=file->get_byte(); + header.mastermult=file->get_byte(); + header.ultraclick=file->get_byte(); + header.pantable=file->get_byte(); + file->get_byte_array((uint8_t*)header.unused2,8); + header.special=file->get_word(); + file->get_byte_array((uint8_t*)header.channels,32); + + file->get_byte_array((uint8_t*)header.orderlist,header.ordnum); + + header.scrm[4]=0; + if (header.scrm[0]!='S' || header.scrm[1]!='C' || header.scrm[2]!='R' || header.scrm[3]!='M') //again? + return FILE_UNRECOGNIZED; + //sample parapointers + for (i=0;iget_word(); + parapointer=(parapointer*16); + sample_parapointers[i]=parapointer; + } + //pattern + for (i=0;iget_word(); + parapointer=(parapointer*16); + pattern_parapointers[i]=parapointer; + } + + if (header.pantable==252) { + + file->get_byte_array((uint8_t*)header.pannings,32); + } + + return FILE_OK; + + +} + + +void CPLoader_S3M::set_header() { + + + + + song->set_name( header.songname ); +// song->variables.filename= + + song->set_row_highlight_minor( 4 ); + song->set_row_highlight_major( 16 ); + song->set_mixing_volume( header.mastervol ); + song->set_linear_slides( false ); + song->set_old_effects( !(header.flags&64) ); + song->set_compatible_gxx( true ); + + song->set_global_volume( header.mastermult ); + song->set_speed( header.initspeed ); + song->set_tempo( header.inittempo ); + + //[TODO] Set Panning Positions.. ? + + for (int i=0;iset_order(i,header.orderlist[i]); + +} + +CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) { + + + + int type=file->get_byte(); + + char filename[13]; + file->get_byte_array((uint8_t*)filename,12); + filename[12]=0; + + + uint32_t samplepos=(uint32_t)file->get_byte() << 16; + samplepos|=file->get_word(); + samplepos*=16; +// printf("sample at %i\n",samplepos); + /**/ + int sample_size=file->get_dword(); + + + int loop_begin=file->get_dword(); + int loop_end=file->get_dword(); + + int def_volume=file->get_byte();; + int dsk=file->get_byte(); + int pack=file->get_byte(); + + int flags=file->get_byte(); + int c2speed=file->get_dword(); + + file->get_dword(); //useless crap + file->get_dword(); + file->get_dword(); + + + char name[29]; + file->get_byte_array((uint8_t*)name,28); + name[28]=0; + + p_sample->set_default_volume(def_volume); + p_sample->set_name(name); + + char scrs[5]; + file->get_byte_array((uint8_t*)scrs,4); + scrs[4]=0; + + + + bool data_is_16bits=flags&4; + bool data_is_stereo=flags&2; + + if (type==0) { + //empty sample + return FILE_OK; + } + + + if ((type!=1) || scrs[0]!='S' || scrs[1]!='C' || scrs[2]!='R' || scrs[3]!='S' ) { +// printf("type: %i, %c%c%c%c\n",type,scrs[0],scrs[1],scrs[2],scrs[3]); + CP_PRINTERR("Not an S3M CPSample!"); + return FILE_CORRUPTED; + } + + //p_sample->data.set_c5_freq(p_sample->c2spd<<1); + + file->seek(samplepos); + + int real_sample_size=sample_size<create( data_is_16bits, data_is_stereo, sample_size ); + + if (id.is_null()) + return FILE_OUT_OF_MEMORY; + + sm->lock_data(id); + void *dataptr = sm->get_data(id); + + int chans = (data_is_stereo?2:1); + for (int c=0;cget_word(); + s-=32768; //toggle sign + + int16_t *v=(int16_t*)&s; + ((int16_t*)dataptr)[i*chans+c]=*v; + } else { + + + int8_t *v; + uint8_t s=file->get_byte(); + s-=128; //toggle sign + v=(int8_t*)&s; + ((int8_t*)dataptr)[i*chans+c]=*v; + + } + + } + + } + + sm->unlock_data(id); + + + sm->set_loop_begin( id, loop_begin ); + sm->set_loop_end( id, loop_end ); + sm->set_loop_type( id, (flags&1) ? CP_LOOP_FORWARD : CP_LOOP_NONE ); + sm->set_c5_freq( id, c2speed << 1 ); + p_sample->set_sample_data(id); + + /* Scream tracker previous to 3.10 seems to be buggy, as in, wont save what is after the sample loop, including the loop end point. Because of this I must fix it by habd */ + if (flags&1) { + + for (int c=0;c<(data_is_stereo?2:1);c++) { + sm->set_data( id, loop_end, sm->get_data( id, loop_begin,c ),c ); + + } + } + + + return FILE_OK; + +} + + +CPLoader::Error CPLoader_S3M::load_pattern(CPPattern *p_pattern) { + + int row=0,flag,ch; + CPNote n; + int length,accum=0; + + length=file->get_word(); + p_pattern->set_length(64); + + /* clear pattern data */ + while((row<64) && (accum<=length) ) { + flag=file->get_byte(); + accum++; + + n.clear(); + if(flag) { + // ch=remap[flag&31]; +// ch=remap[flag&31]; +// if(ch!=-1) +// n=s3mbuf[(64U*ch)+row]; +// else +// n=&dummy; + + ch=flag&31; + + if(flag&32) { + n.note=file->get_byte(); + if (n.note==255) { + + n.note=CPNote::EMPTY; + } else if (n.note==254) { + + n.note=CPNote::CUT; + } else { + + n.note=((n.note>>4)*12)+(n.note&0xF); + } + + n.instrument=file->get_byte()-1; + accum+=2; + + } + if(flag&64) { + n.volume=file->get_byte(); + if (n.volume>64) n.volume=64; + accum++; + + } + if(flag&128) { + n.command=file->get_byte()-1; + n.parameter=file->get_byte(); + accum+=2; + } + + p_pattern->set_note(ch,row,n); + } else row++; + } + return FILE_OK; + + +} + +CPLoader::Error CPLoader_S3M::load_sample(const char *p_file,CPSample *p_sample) { + + return FILE_UNRECOGNIZED; +} +CPLoader::Error CPLoader_S3M::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { + + return FILE_UNRECOGNIZED; + +} + + +CPLoader::Error CPLoader_S3M::load_samples() { + + int i; + + for(i=0;iseek(sample_parapointers[i]); + load_sample(song->get_sample(i)); + sample_count++; + } + + return FILE_OK; +} + +CPLoader::Error CPLoader_S3M::load_patterns() { + + int i; + + Error err; + for(i=0;iseek(pattern_parapointers[i]); + + err=load_pattern(song->get_pattern(i) ); + CP_ERR_COND_V(err,err); + + + pattern_count++; + } + return FILE_OK; + +} + +CPLoader::Error CPLoader_S3M::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) { + + song=p_song; + + if (file->open(p_file,CPFileAccessWrapper::READ)) { + //printf("Can't open file! %s\n",p_file); + return FILE_CANNOT_OPEN; + }; + + sample_count=0; + pattern_count=0; + + //printf("LOADING HEADER\n"); + CPLoader::Error err; + if ((err=load_header())) { + file->close(); + CP_ERR_COND_V(err,err); + + } + + song->reset(); //file type recognized, reset song! + + set_header(); + + //printf("LOADING SAMPLES\n"); + + if ((err=load_samples())) { + file->close(); + + CP_ERR_COND_V(err,err); + } + + //printf("LOADING PATTERNS\n"); + + if ((err=load_patterns())) { + + file->close(); + return err; + } + + file->close(); + + return FILE_OK; +} + + + +CPLoader_S3M::CPLoader_S3M(CPFileAccessWrapper *p_file){ + + file=p_file; + +} +CPLoader_S3M::~CPLoader_S3M(){ +} + diff --git a/modules/chibi/cp_loader_s3m.h b/modules/chibi/cp_loader_s3m.h new file mode 100644 index 0000000000..175e5e80fe --- /dev/null +++ b/modules/chibi/cp_loader_s3m.h @@ -0,0 +1,111 @@ +/*************************************************************************/ +/* cp_loader_s3m.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_LOADER_S3M_H +#define CP_LOADER_S3M_H + +#include "cp_loader.h" + +/** + *@author Juan Linietsky + */ +/****************************** + loader_s3m.h + ---------- +Scream Tracker Module CPLoader! +It lacks support for +individual sample loading +and reorganizing the columns. +********************************/ + + + + +class CPLoader_S3M : public CPLoader { + + struct S3M_Header { + char songname[28]; + uint8_t t1a; + uint8_t type; + uint8_t unused1[2]; + uint16_t ordnum; + uint16_t insnum; + uint16_t patnum; + uint16_t flags; + uint16_t tracker; + uint16_t fileformat; + char scrm[5]; + uint8_t mastervol; + uint8_t initspeed; + uint8_t inittempo; + uint8_t mastermult; + uint8_t ultraclick; + uint8_t pantable; + uint8_t unused2[8]; + uint16_t special; + uint8_t channels[32]; + uint8_t pannings[32]; + uint8_t orderlist[300]; + }; + + + int sample_parapointers[CPSong::MAX_SAMPLES]; + int pattern_parapointers[CPSong::MAX_PATTERNS]; + + Error load_header(); + void set_header(); + Error load_sample(CPSample *p_sample); + Error load_pattern(CPPattern *p_pattern); + Error load_patterns(); + + Error load_samples(); + + S3M_Header header; + int sample_count; + int pattern_count; + + CPFileAccessWrapper *file; + CPSong *song; +public: + + bool can_load_song() { return true; } + bool can_load_sample() { return false; } + bool can_load_instrument() { return false; } + + Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset); + Error load_sample(const char *p_file,CPSample *p_sample); + Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx); + + CPLoader_S3M(CPFileAccessWrapper *p_file); + ~CPLoader_S3M(); +}; + + + +#endif diff --git a/modules/chibi/cp_loader_xm.cpp b/modules/chibi/cp_loader_xm.cpp new file mode 100644 index 0000000000..bff8615a32 --- /dev/null +++ b/modules/chibi/cp_loader_xm.cpp @@ -0,0 +1,752 @@ +/*************************************************************************/ +/* cp_loader_xm.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_loader_xm.h" +#include "cp_tables.h" + +#define ABORT_LOAD { file->close(); return FILE_CORRUPTED; } + + + + +CPLoader::Error CPLoader_XM::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) { + + song=p_song; + + if (file->open(p_file,CPFileAccessWrapper::READ)) { + + return FILE_CANNOT_OPEN; + }; + + + /************************************** + LOAD HEADER + ***************************************/ + + file->get_byte_array(header.idtext,17); + header.idtext[17]=0; + + file->get_byte_array(header.songname,20); + + + + header.songname[20]=0; + header.hex1a=file->get_byte(); + if (header.hex1a!=0x1A) { //XM "magic" byte.. this sucks :) + + file->close(); + return FILE_UNRECOGNIZED; + + } + + + //magic byte sucks, but can't do much about it.. + + song->reset(); //must reset the song + + song->set_name( (const char*)header.songname ); + + file->get_byte_array(header.trackername,20); + header.trackername[20]=0; + + + header.version=file->get_word(); + + header.headersize=file->get_dword(); + + header.songlength=file->get_word(); + + header.restart_pos=file->get_word(); + + header.channels_used=file->get_word(); + + header.patterns_used=file->get_word(); + + header.instruments_used=file->get_word(); + + song->set_linear_slides( file->get_word() ); + + song->set_speed( file->get_word() ); + + song->set_tempo( file->get_word() ); + song->set_instruments( true ); + + file->get_byte_array(header.orderlist,256); + + for (int i=0;i199) + break; + song->set_order(i,header.orderlist[i]); + } + + /************************************** + LOAD PATTERNS + ***************************************/ + + for (int i=0;iget_dword(); //length + aux=file->get_byte(); //packing type + rows=aux=file->get_word(); //rows! + + song->get_pattern(i)->set_length( aux ); + + aux=file->get_word(); //packed size + if (aux==0) + continue; + //unpaaack! + for(int j=0;j<(int)rows;j++) + for(int k=0;kget_byte(); //packing type + if (!(aux_byte&0x80)) { + + aux_note.note=aux_byte; + aux_byte=0xFE; //if bit 7 not set, read all of them except the note + } + + if (aux_byte&1) aux_note.note=file->get_byte(); + if (aux_byte&2) aux_note.instrument=file->get_byte(); + if (aux_byte&4) aux_note.volume=file->get_byte(); + if (aux_byte&8) aux_note.command=file->get_byte(); + if (aux_byte&16) aux_note.parameter=file->get_byte(); + + if (aux_note.note!=CPNote::EMPTY) { + + if (aux_note.note==97) aux_note.note=CPNote::OFF; + else { + aux_note.note+=11; //octave minus one (XM C-0 is 1, not zero ) + } + } + if (aux_note.instrument!=CPNote::EMPTY) { + + if ((aux_note.instrument>0) && (aux_note.instrument<100)) + aux_note.instrument--; + else + aux_note.instrument=CPNote::EMPTY; + } + if (aux_note.volume!=CPNote::EMPTY) { + + if (aux_note.volume<0x10) {} + else if (aux_note.volume<0x50) { + + aux_note.volume-=0x10; + + } else if (aux_note.volume<0x60) { + // + aux_note.volume=CPNote::EMPTY; + + } else if (aux_note.volume<0x70) { + //60 -- volume slide down + aux_note.volume-=0x60; + if (aux_note.volume>9) aux_note.volume=9; + aux_note.volume+=95; + + } else if (aux_note.volume<0x80) { + //70 -- volume slide up + aux_note.volume-=0x70; + if (aux_note.volume>9) aux_note.volume=9; + aux_note.volume+=85; + + + } else if (aux_note.volume<0x90) { + //80 -- fine volume slide down + aux_note.volume-=0x80; + if (aux_note.volume>9) aux_note.volume=9; + aux_note.volume+=75; + + + } else if (aux_note.volume<0xA0) { + //9 -- fine volume slide up + + aux_note.volume-=0x90; + if (aux_note.volume>9) aux_note.volume=9; + + aux_note.volume+=65; + + + + } else if (aux_note.volume<0xB0) { + //A -- set vibrato speed + aux_note.volume=CPNote::EMPTY; + + } else if (aux_note.volume<0xC0) { + //B -- vibrato + aux_note.volume-=0xB0; + if (aux_note.volume>9) aux_note.volume=9; + aux_note.volume+=203; + + + } else if (aux_note.volume<0xD0) { + //C -- set panning + int aux=aux_note.volume-=0xC0; + aux=aux*65/0xF; + aux_note.volume=128+aux; + + } else if (aux_note.volume<0xE0) { + aux_note.volume=CPNote::EMPTY; + + + } else if (aux_note.volume<0xF0) { + aux_note.volume=CPNote::EMPTY; + + + } else { + //F -- tone porta + aux_note.volume-=0xF0; + aux_note.volume*=9; + aux_note.volume/=0xF; + aux_note.volume+=193; + } + } + if (aux_note.command!=CPNote::EMPTY) { + + switch(aux_note.command) { + + case 0x0: + aux_note.command='J'-'A'; + break; + case 0x1: + aux_note.command='F'-'A'; + break; + case 0x2: + aux_note.command='E'-'A'; + break; + case 0x3: + aux_note.command='G'-'A'; + break; + case 0x4: + aux_note.command='H'-'A'; + break; + case 0x5: + aux_note.command='L'-'A'; + break; + case 0x6: + aux_note.command='K'-'A'; + break; + case 0x7: + aux_note.command='R'-'A'; + break; + case 0x8: + aux_note.command='X'-'A'; + break; + case 0x9: + aux_note.command='O'-'A'; + break; + case 0xa: + aux_note.command='D'-'A'; + break; + case 0xb: + aux_note.command='B'-'A'; + break; + case 0xc: + //printf("XM Import: Warning! effect C (set volume) not implemented!\n"); + break; + case 0xd: + aux_note.command='C'-'A'; + break; + + case 0xe: /* Extended effects */ + + aux_note.command='S'-'A'; + switch(aux_note.parameter>>4) { + case 0x1: /* XM fine porta up */ + if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } + aux_note.command='F'-'A'; + aux_note.parameter=0xF0|(aux_note.parameter&0xF); + break; + case 0x2: /* XM fine porta down */ + if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } + aux_note.command='E'-'A'; + aux_note.parameter=0xF0|(aux_note.parameter&0xF); + break; + case 0xa: /* XM fine volume up */ + if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } + aux_note.command='D'-'A'; + aux_note.parameter=0x0F|((aux_note.parameter&0xF)<<4); + + break; + case 0xb: /* XM fine volume down */ + if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } + aux_note.command='D'-'A'; + aux_note.parameter=0xF0|(aux_note.parameter&0xF); + + break; + case 0x9: /* XM fine volume down */ + if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; } + aux_note.command='Q'-'A'; + aux_note.parameter=0x00|(aux_note.parameter&0xF); + break; + + case 0xc: //notecut + + aux_note.parameter=0xC0|(aux_note.parameter&0xF); + break; + + case 0xd: //notedelay + + aux_note.parameter=0xD0|(aux_note.parameter&0xF); + break; + + case 0xe: //patterndelay + + aux_note.parameter=0xE0|(aux_note.parameter&0xF); + break; + } + + break; + case 0xf: + if (aux_note.parameter<32) { + aux_note.command='A'-'A'; + } else { + aux_note.command='T'-'A'; + } + break; + case 'G'-55: + aux_note.command='V'-'A'; + break; + case 'H'-55: + aux_note.command='W'-'A'; + break; + case 'K'-55: + if (aux_note.note!=CPNote::EMPTY) break; + aux_note.note=CPNote::OFF; + break; + case 'P'-55: + aux_note.command='P'-'A'; + break; + case 'R'-55: + aux_note.command='Q'-'A'; + break; + case 'T'-55: + aux_note.command='I'-'A'; + break; + default: { + + aux_note.command=CPNote::EMPTY; + } + } + + + } + + song->get_pattern( i)->set_note( k,j,aux_note ); + } + } + + /************************************** + LOAD INSTRUMENTS! + ***************************************/ + + for (int i=0;iget_instrument(i); + uint32_t cpos=file->get_pos(); + //printf("pos is %i\n",cpos); + + + +/* +4 */ uint32_t hsize=file->get_dword(); //header length + + char instrname[23]; + instrname[22]=0; + + file->get_byte_array((uint8_t*)instrname,22); +//XM_LOAD_DEBUG printf("name is %s\n",instrname); + +/* +27 */ aux=file->get_byte(); //byte that must be ignored +//XM_LOAD_DEBUG printf("header size is %i\n",hsize); + +/* +29 */ sampnum=file->get_word(); + +//XM_LOAD_DEBUG printf("samples %i\n",sampnum); + + + instrument.set_name( instrname ); +// printf("Header Len: %i, CPInstrument %i, %i samples , name: s,\n",hsize,i,sampnum,instrname); + + if (sampnum==0) { + //aux=file->get_dword(); //Why is this for? -- for nothing, skipped + if (hsize) { + + file->seek( cpos+hsize ); //skip header if size has been specified + } + continue; + } + +/* +33 */ file->get_dword(); + + if (Error result=load_instrument_internal(&instrument,false,cpos,hsize,sampnum)) { + + CP_PRINTERR("Error loading instrument"); + file->close(); + return result; + } + + } +// + file->close(); + return FILE_OK; +} + +CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr,bool p_xi,int p_cpos, int p_hsize, int p_sampnum) { + + int sampnum; + uint32_t aux; + uint8_t notenumb[96]; + uint16_t panenv[24],volenv[24]; + int volpoints,panpoints; + int vol_loop_begin,vol_loop_end,vol_sustain_loop; + int pan_loop_begin,pan_loop_end,pan_sustain_loop; + char instrname[23]; + int sample_index[16]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; //-1 means no index! + + instrname[22]=0; + + +/* +129 */ file->get_byte_array((uint8_t*)notenumb,96); + for (int j=0;j<24;j++) { + volenv[j]=file->get_word(); + } + for (int j=0;j<24;j++) { + panenv[j]=file->get_word(); + } + +/* +177 */ +/* +225 */ +/* +226 */ volpoints=file->get_byte(); +/* +227 */ panpoints=file->get_byte(); +/* +230 */ vol_sustain_loop=file->get_byte(); +/* +228 */ vol_loop_begin=file->get_byte(); +/* +229 */ vol_loop_end=file->get_byte(); + +//XM_LOAD_DEBUG printf("1- volpoints: %i, panpoints: %i, susloop: %i, loop begin: %i, loop end %i\n",volpoints,panpoints,vol_sustain_loop,vol_loop_begin,vol_loop_end); + pan_sustain_loop=file->get_byte(); +/* +231 */ pan_loop_begin=file->get_byte(); +/* +232 */ pan_loop_end=file->get_byte(); + + + +/* +234 */ aux=file->get_byte(); + p_instr->get_volume_envelope()->reset(); + p_instr->get_volume_envelope()->set_enabled(aux&1); + p_instr->get_volume_envelope()->set_sustain_loop_enabled((aux&2)?true:false); + p_instr->get_volume_envelope()->set_loop_enabled((aux&4)?true:false); +/* +235 */ aux=file->get_byte(); + p_instr->get_pan_envelope()->reset(); + p_instr->get_pan_envelope()->set_enabled(aux&1); + p_instr->get_pan_envelope()->set_sustain_loop_enabled((aux&2)?true:false); + p_instr->get_pan_envelope()->set_loop_enabled((aux&4)?true:false); + +/* +239 */ aux=file->get_dword(); // sadly, cant use those +/* +241 */ p_instr->set_volume_fadeout( file->get_word() >> 4 ); +/* +243 */ aux=file->get_word(); // reserved! + + + + for (int j=0;jget_volume_envelope()->add_position(ofs,val); + + } + + //make sure minimum is 2 + while (p_instr->get_volume_envelope()->get_node_count()<2) { + + p_instr->get_volume_envelope()->add_position( p_instr->get_volume_envelope()->get_node_count()*20,64 ); + } + + for (int j=0;jget_pan_envelope()->add_position(ofs,val-32); + } + + //make sure minimum is 2 + while (p_instr->get_pan_envelope()->get_node_count()<2) { + + p_instr->get_pan_envelope()->add_position( p_instr->get_pan_envelope()->get_node_count()*20,0 ); + } + + + p_instr->get_volume_envelope()->set_loop_begin(vol_loop_begin); + p_instr->get_volume_envelope()->set_loop_end(vol_loop_end); + p_instr->get_volume_envelope()->set_sustain_loop_end(vol_sustain_loop); + p_instr->get_volume_envelope()->set_sustain_loop_begin(vol_sustain_loop); + p_instr->get_pan_envelope()->set_loop_begin(pan_loop_begin); + p_instr->get_pan_envelope()->set_loop_end(pan_loop_end); + p_instr->get_pan_envelope()->set_sustain_loop_end(pan_sustain_loop); + p_instr->get_pan_envelope()->set_sustain_loop_begin(pan_sustain_loop); + + + if (!p_xi) { + + if ((file->get_pos()-p_cpos)get_pos()-p_cpos)); + //printf("extra: %i\n",p_hsize-(file->get_pos()-p_cpos)); + file->get_byte_array((uint8_t*)junkbuster,p_hsize-(file->get_pos()-p_cpos)); + } + + sampnum=p_sampnum; + } else { + + uint8_t junkbuster[500]; + file->get_byte_array((uint8_t*)junkbuster,20); //14 bytes? + + sampnum=file->get_word(); + + } + + + CPSampleManager *sm=CPSampleManager::get_singleton(); + + /*SAMPLE!!*/ + + for (int j=0;j16) ABORT_LOAD; + + + int s_idx=-1; + for (int s=0;sget_sample(s)->get_sample_data().is_null()) { + //empty sample! + s_idx=s; + break; + } + } + + if (s_idx==-1) ABORT_LOAD; + //printf("free sample: %i\n",s_idx); + + + CPSample& sample=*song->get_sample(s_idx); + + int sample_size=file->get_dword(); + int tmp_loop_begin=file->get_dword(); + + int tmp_loop_end=file->get_dword(); + + sample.set_default_volume(file->get_byte()); + + uint8_t ftb=file->get_byte(); + int8_t *fts=(int8_t*)&ftb; + int finetune=*fts; + uint32_t flags=file->get_byte(); + + if (flags&16) { // is 16 bits.. at flag 16.. fun :) + + tmp_loop_end/=2; + tmp_loop_begin/=2; + sample_size/=2; + } + + + CPSample_ID sample_data=sm->create( flags&16, false, sample_size ); + + sample.set_sample_data(sample_data); + sm->set_loop_begin(sample_data,tmp_loop_begin); + sm->set_loop_end(sample_data,tmp_loop_end+tmp_loop_begin); + + sm->set_loop_type( sample_data, (flags&3)?( (flags&2) ? CP_LOOP_BIDI : CP_LOOP_FORWARD ):CP_LOOP_NONE ); + + + + sample.set_pan_enabled(true); + sample.set_pan(file->get_byte()*64/255); + uint8_t noteb=file->get_byte(); + int8_t *notes=(int8_t*)¬eb; + int note_offset=*notes; + note_offset+=48; + //note_offset+=60; + + + + //int linear_period=10*12*16*4 - (note_offset)*16*4 - finetune/2; + //int freq=(int)(8363*pow(2.0,(double)(6*12*16*4 - linear_period) / (double)(12*16*4))); + + //sm->set_c5_freq( sample_data, freq); + sm->set_c5_freq( sample_data, CPTables::get_linear_frequency(CPTables::get_linear_period(note_offset<<1,finetune)) ); + //printf("NOTE %i,fine %i\n",note_offset,finetune); + + char auxb; + auxb=file->get_byte(); //reserved? + file->get_byte_array((uint8_t*)instrname,22); + sample.set_name(instrname); + + sample_index[j]=s_idx; + } + + /*SAMPLE __DATA__!!*/ + + for (int j=0;jget_sample(sample_index[j]); + CPSample_ID sid=sample->get_sample_data(); + + sm->lock_data(sid); + + void*dataptr=sm->get_data(sid); + + if (sm->is_16bits( sid)) { + + int16_t old=0; + + + for (int k=0;kget_size(sid);k++) { + + int16_t newsample; + int16_t sampleval=file->get_word(); + newsample=sampleval+old; + old=newsample; + + ((int16_t*)dataptr)[k]=newsample; + //sm->set_data( sid, k, newsample ); + } + } else { + + int8_t old=0; + + + for (int k=0;kget_size(sid);k++) { + + int8_t newsample; + int8_t sampleval=file->get_byte(); + newsample=sampleval+old; + old=newsample; + + ((int8_t*)dataptr)[k]=newsample; + + //sm->set_data( sid, k, (int16_t)newsample << 8 ); + + } + } + + sm->unlock_data(sid); + + } + + for (int j=0;j<96;j++) { + + int val=notenumb[j]; + if ((val<0) || (val>15)) continue; + else val=sample_index[val]; + if (val==-1) continue; + p_instr->set_sample_number( 12+j,val ); + } + + + return FILE_OK; +} + + + +CPLoader::Error CPLoader_XM::load_sample(const char *p_file,CPSample *p_sample) { + + return FILE_UNRECOGNIZED; +} + + +/* Compute CPInstrument Info */ +CPLoader::Error CPLoader_XM::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) { + + if ( file->open(p_file,CPFileAccessWrapper::READ) ) return FILE_CANNOT_OPEN; + //int i; + song=p_song; + CPInstrument& instr=*p_song->get_instrument( p_instr_idx ); + int aux; + + + char buffer[500]; + file->get_byte_array((uint8_t*)buffer,0x15); + buffer[8]=0; + if ( buffer[0]!='E' || + buffer[1]!='x' || + buffer[2]!='t' || + buffer[3]!='e' || + buffer[4]!='n' || + buffer[5]!='d' || + buffer[6]!='e' || + buffer[7]!='d') { + file->close(); + return FILE_UNRECOGNIZED; + } + + file->get_byte_array((uint8_t*)buffer,0x16); + buffer[0x16]=0; + instr.set_name(buffer); + aux=file->get_byte(); //says ignore ti + /*if(aux!=0x1a) { I'm not sure. this is supposed to be ignored... + + file->close(); + return FILE_UNRECOGNIZED; + } */ + + file->get_byte_array((uint8_t*)buffer,0x14); //somethingaboutthename + aux=file->get_word(); //version or blahblah + + if (load_instrument_internal(&instr,true,0,0)) { + + file->close(); + return FILE_CORRUPTED; + } + + file->close(); //ook, we got it.. + + + return FILE_OK; + +} + + + +CPLoader_XM::CPLoader_XM(CPFileAccessWrapper *p_file){ + + file=p_file; +} +CPLoader_XM::~CPLoader_XM(){ +} + diff --git a/modules/chibi/cp_loader_xm.h b/modules/chibi/cp_loader_xm.h new file mode 100644 index 0000000000..9ae480cc8f --- /dev/null +++ b/modules/chibi/cp_loader_xm.h @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* cp_loader_xm.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_LOADER_XM_H +#define CP_LOADER_XM_H + +#include "cp_loader.h" + + +/** + *@author red + */ + + + + +class CPLoader_XM : public CPLoader { + + + struct XM_Header { + + uint8_t idtext[18]; + uint8_t songname[21]; + uint8_t hex1a; // ? + uint8_t trackername[21]; + uint16_t version; + uint32_t headersize; //from here + + uint16_t songlength; //pattern ordertable + uint16_t restart_pos; + uint16_t channels_used; + uint16_t patterns_used; + uint16_t instruments_used; + uint16_t use_linear_freq; + uint16_t tempo; + uint16_t speed; + uint8_t orderlist[256]; + + } header; + + CPFileAccessWrapper *file; + + Error load_instrument_internal(CPInstrument *pint,bool p_xi,int p_cpos, int p_hsize, int p_sampnumb=-1); + CPSong *song; + +public: + + bool can_load_song() { return true; } + bool can_load_sample() { return false; } + bool can_load_instrument() { return true; } + + Error load_song(const char *p_file,CPSong *p_song,bool p_sampleset); + Error load_sample(const char *p_file,CPSample *p_sample); + Error load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx); + + + CPLoader_XM(CPFileAccessWrapper *p_file); + ~CPLoader_XM(); +}; + + + +#endif diff --git a/modules/chibi/cp_mixer.h b/modules/chibi/cp_mixer.h new file mode 100644 index 0000000000..7ad22ac146 --- /dev/null +++ b/modules/chibi/cp_mixer.h @@ -0,0 +1,115 @@ +/*************************************************************************/ +/* cp_mixer.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_MIXER_H +#define CP_MIXER_H + +#include "cp_sample_defs.h" + +/**Abstract base class representing a mixer + *@author Juan Linietsky + */ + + +/****************************** + mixer.h + ---------- + +Abstract base class for the mixer. +This is what the player uses to setup +voices and stuff.. this way +it can be abstracted to hardware +devices or other stuff.. +********************************/ + +class CPSample_ID; /* need this */ + +class CPMixer { +public: + + enum { + + FREQUENCY_BITS=8 + + }; + + enum ReverbMode { + REVERB_MODE_ROOM, + REVERB_MODE_STUDIO_SMALL, + REVERB_MODE_STUDIO_MEDIUM, + REVERB_MODE_STUDIO_LARGE, + REVERB_MODE_HALL, + REVERB_MODE_SPACE_ECHO, + REVERB_MODE_ECHO, + REVERB_MODE_DELAY, + REVERB_MODE_HALF_ECHO + }; + + /* Callback */ + + virtual void set_callback_interval(int p_interval_us)=0; //in usecs, for tracker it's 2500000/tempo + virtual void set_callback(void (*p_callback)(void*),void *p_userdata)=0; + + /* Voice Control */ + + virtual void setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) =0; + virtual void stop_voice(int p_voice_index) =0; + virtual void set_voice_frequency(int p_voice_index,int32_t p_freq) =0; //in freq*FREQUENCY_BITS + virtual void set_voice_panning(int p_voice_index,int p_pan) =0; + virtual void set_voice_volume(int p_voice_index,int p_vol) =0; + virtual void set_voice_filter(int p_filter,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance )=0; + virtual void set_voice_reverb_send(int p_voice_index,int p_reverb)=0; + virtual void set_voice_chorus_send(int p_voice_index,int p_chorus)=0; /* 0 - 255 */ + + virtual void set_reverb_mode(ReverbMode p_mode)=0; + virtual void set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10)=0; + + + /* Info retrieving */ + + virtual int32_t get_voice_sample_pos_index(int p_voice_index) =0; + virtual int get_voice_panning(int p_voice_index) =0; + virtual int get_voice_volume(int p_voice_index) =0; + virtual CPSample_ID get_voice_sample_id(int p_voice_index) =0; + virtual bool is_voice_active(int p_voice_index) =0; + virtual int get_active_voice_count()=0; + virtual int get_total_voice_count()=0; + + + virtual uint32_t get_mix_frequency()=0; //if mixer is not software, return 0 + + /* Methods below only work with software mixers, meant for software-based sound drivers, hardware mixers ignore them */ + virtual int32_t process(int32_t p_frames)=0; /* Call this to process N frames, returns how much it was processed */ + virtual int32_t *get_mixdown_buffer_ptr()=0; /* retrieve what was mixed */ + virtual void set_mix_frequency(int32_t p_mix_frequency)=0; + + virtual ~CPMixer() {} +}; + +#endif diff --git a/modules/chibi/cp_note.h b/modules/chibi/cp_note.h new file mode 100644 index 0000000000..5cfa3f11ec --- /dev/null +++ b/modules/chibi/cp_note.h @@ -0,0 +1,102 @@ +/*************************************************************************/ +/* cp_note.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_NOTE_H +#define CP_NOTE_H + +#include "cp_config.h" + +struct CPNote { + + enum { + + NOTES=120, + OFF=254, + CUT=253, + EMPTY=255, + SCRIPT=252, + }; + + + uint8_t note; + uint8_t instrument; + uint8_t volume; + uint8_t command; + uint8_t parameter; + unsigned int script_source_sign; + bool cloned; + + void clear() { + + note=EMPTY; + instrument=EMPTY; + volume=EMPTY; + command=EMPTY; + parameter=0; + script_source_sign='\0'; + cloned=false; + } + + void raise() { + + if (note<(NOTES-1)) + note++; + else if (note==SCRIPT && parameter<0xFF) + parameter++; + } + + void lower() { + + if ((note>0) && (note0) + parameter--; + + } + + bool operator== (const CPNote &rvalue) { + + return ( + (note==rvalue.note) && + (instrument==rvalue.instrument) && + (volume==rvalue.volume) && + (command==rvalue.command) && + (parameter==rvalue.parameter) + ); + } + + bool is_empty() const { return (note==EMPTY && instrument==EMPTY && volume==EMPTY && command==EMPTY && parameter==0 && !cloned); } + CPNote() { + + clear(); + } +}; + + +#endif + diff --git a/modules/chibi/cp_order.h b/modules/chibi/cp_order.h new file mode 100644 index 0000000000..03ecc00bba --- /dev/null +++ b/modules/chibi/cp_order.h @@ -0,0 +1,43 @@ +/*************************************************************************/ +/* cp_order.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_ORDER_H +#define CP_ORDER_H + + +#include "cp_config.h" + +enum CPOrderType { + CP_ORDER_NONE=255, + CP_ORDER_BREAK=254 +}; + +typedef uint8_t CPOrder; + +#endif + diff --git a/modules/chibi/cp_pattern.cpp b/modules/chibi/cp_pattern.cpp new file mode 100644 index 0000000000..83e165bf87 --- /dev/null +++ b/modules/chibi/cp_pattern.cpp @@ -0,0 +1,574 @@ +/*************************************************************************/ +/* cp_pattern.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_pattern.h" + +void CPPattern::clear() { + + if (event_count>0) { + + + CP_FREE(events); + events=NULL; + event_count=0; + } + + length=DEFAULT_LEN; + +} + + +bool CPPattern::resize_event_list_to(uint32_t p_events) { + + + //Module is slow in some cpus, so this should be fast enough + uint32_t new_size=((p_events-1)&(~((1<=p_target_pos) + break; + + } */ + + //return pos_idx; +} + +bool CPPattern::erase_event_at_pos(uint16_t p_pos) { + + if (event_count==0) + return false; + + + + Event *event_list=events; + + int32_t pos_idx = get_event_pos(p_pos); + if (pos_idx==-1) { + CP_ERR_COND_V(pos_idx==-1,true); + } + + if (pos_idx==event_count || event_list[pos_idx].pos!=p_pos) { + /* Nothing to Erase */ + return false; + } + + for (int32_t i=pos_idx;i<(event_count-1);i++) { + + event_list[i]=event_list[i+1]; + } + + + resize_event_list_to(event_count-1); + + return false; +} + +bool CPPattern::set_note(uint8_t p_column, uint16_t p_row,const CPNote& p_note) { + + CP_ERR_COND_V(p_column>=WIDTH,true); + CP_ERR_COND_V(p_row>=length,true); + + int32_t new_pos; + uint16_t target_pos=p_row*WIDTH+p_column; + + + + if (p_note.is_empty()) { + bool res=erase_event_at_pos(target_pos); + + return res;; + } + + Event *event_list=0; + + if (event_count==0) { + /* If no events, create the first */ + + if (resize_event_list_to(1)) { + + CP_PRINTERR("Can't resize event list to 1"); + return true; + } + + event_list=events; + if (event_list==0) { + + + CP_PRINTERR("Can't get event list"); + return true; + } + + new_pos=0; + + } else { + /* Prepare to add */ + + event_list=events; + if (event_list==0) { + + + CP_PRINTERR("Can't get event list"); + return true; + } + + int32_t pos_idx = get_event_pos(target_pos); + + if (pos_idx==-1) { + + + CP_PRINTERR("Can't find add position"); + return true; + } + + + if (pos_idx==event_count || event_list[pos_idx].pos!=target_pos) { + /* If the note being modified didnt exist, then we add it */ + + //resize, and return if out of mem + if (resize_event_list_to( event_count+1)) { + + + CP_PRINTERR("Can't resize event list"); + return true; + } + event_list=events; + if (event_list==0) { + + + CP_PRINTERR("Can't get event list"); + return true; + } + + //make room for new pos, this wont do a thing if pos_idx was ==event_count + for(int32_t i=(event_count-1);i>pos_idx;i--) { + event_list[i]=event_list[i-1]; + + } + + } /* Else it means that position is taken, so we just modify it! */ + + + new_pos=pos_idx; + } + + event_list[new_pos].pos=target_pos; + event_list[new_pos].note=p_note.note; + event_list[new_pos].instrument=p_note.instrument; + event_list[new_pos].volume=p_note.volume; + event_list[new_pos].command=p_note.command; + event_list[new_pos].parameter=p_note.parameter; + event_list[new_pos].script_source_sign=p_note.script_source_sign; + event_list[new_pos].cloned=p_note.cloned; + + + + + return false; + +} +CPNote CPPattern::get_note(uint8_t p_column,uint16_t p_row) { + + if (p_column==CPNote::EMPTY) return CPNote(); + + CP_ERR_COND_V(p_column>=WIDTH,CPNote()); + CP_ERR_COND_V(p_row>=length,CPNote()); + + if (event_count==0) + return CPNote(); + + + Event *event_list=events; + + CP_ERR_COND_V(event_list==0,CPNote()); + + uint16_t target_pos=p_row*WIDTH+p_column; + int32_t pos_idx = get_event_pos(target_pos); + if (pos_idx==-1) { + + CP_PRINTERR("Can't find event pos"); + return CPNote(); + } + + if (pos_idx>=event_count || event_list[pos_idx].pos!=target_pos) { + /* no note found */ + + return CPNote(); + } + + CPNote n; + n.note=event_list[pos_idx].note; + n.instrument=event_list[pos_idx].instrument; + n.volume=event_list[pos_idx].volume; + n.command=event_list[pos_idx].command; + n.parameter=event_list[pos_idx].parameter; + n.script_source_sign=event_list[pos_idx].script_source_sign; + n.cloned=event_list[pos_idx].cloned; + + + return n; + +} + +CPNote CPPattern::get_transformed_script_note(uint8_t p_column,uint16_t p_row ) { + + CPNote n = get_note( p_column, p_row ); + + // get source channel and note + + int channel = get_scripted_note_target_channel( p_column, p_row ); + CPNote src_n = get_note( channel, 0 ); + + if ( src_n.note == CPNote::SCRIPT ) return CPNote(); + + script_transform_note( src_n, n ); + + return src_n; + +} + +int CPPattern::get_scripted_note_target_channel(uint8_t p_column, uint16_t p_row) { + + CPNote n = get_note( p_column, p_row ); + + if ( n.note != CPNote::SCRIPT ) return CPNote::EMPTY; + + int channel = n.instrument; + + if ( n.script_source_sign == '\0' ) { + + if ( channel < 0 || channel >= CPPattern::WIDTH ) return CPNote::EMPTY; + + } else { + + channel = p_column + ( ( n.script_source_sign=='+') ? 1 : -1 ) * (channel+1); + if ( channel < 0 || channel >= CPPattern::WIDTH ) return CPNote::EMPTY; + + } + + return channel; +} + +void CPPattern::scripted_clone(uint8_t p_column, uint16_t p_row) { + + int channel = get_scripted_note_target_channel( p_column, p_row ); + int src_row = 1; + CPNote script_n = get_note( p_column, p_row ); + + for ( int row = p_row+1; row < length; ++row ) { + + CPNote src_n = get_note( channel, src_row ); + CPNote target_n = get_note( p_column, row ); + + if ( target_n.note != CPNote::SCRIPT ) { + if ( src_n.note == CPNote::SCRIPT ) { + src_n = CPNote(); + channel = CPNote::EMPTY; + } + + script_transform_note( src_n, script_n ); + + src_n.cloned = true; + set_note( p_column, row, src_n ); + + } else { + + return; + + } + + src_row++; + } + +} + +void CPPattern::scripted_clone_remove(uint8_t p_column, uint16_t p_row) { + + if ( get_note( p_column, p_row ).cloned ) + set_note( p_column, p_row, CPNote() ); + + for ( int row = p_row+1; row < length; ++row ) { + + CPNote target_n = get_note( p_column, row ); + + if ( target_n.note != CPNote::SCRIPT ) { + + set_note( p_column, row, CPNote() ); + + } else { + + return; + + } + + } + +} + +void CPPattern::script_transform_note(CPNote& n, const CPNote& p_note) { + + // set instrument + + if ( n.note < CPNote::NOTES && p_note.volume != CPNote::EMPTY ) { + + n.instrument = p_note.volume; + + } + + // transpose + + if ( n.note < CPNote::NOTES && p_note.command != CPNote::EMPTY ) { + + int transpose = ( p_note.parameter & 0xF ) + ( p_note.parameter / 0x10 ) * 12; + + if ( p_note.command == '^' ) { + + if ( n.note >= CPNote::NOTES-transpose ) + n.note = CPNote::NOTES-1; + else + n.note += transpose; + + } else if ( p_note.command == 'v' ) { + + if ( n.note <= transpose ) + n.note = 0; + else + n.note -= transpose; + + } + } + +} + +bool CPPattern::update_scripted_clones_sourcing_channel( int channel ) { + + bool updated = false; + + for ( int x = 0; x < WIDTH; ++x ) { + + for (int y = 0; y < length; ++y ) { + + if ( channel == get_scripted_note_target_channel( x, y ) ) { + + scripted_clone( x, y ); + updated = true; + } + + } + + } + + return updated; +} + +void CPPattern::set_length(uint16_t p_rows) { + + + + if (event_count==0) { + + if (p_rows>=MIN_ROWS) + length=p_rows; + + + return; + + } + + if (p_rowsclear(); + p_pattern->length=length; + + + if (!event_count) + return; + + + + int bufsiz=MemPool_Wrapper::get_singleton()->get_mem_size( mem_handle ); + MemPool_Handle aux_mem_handle=MemPool_Wrapper::get_singleton()->alloc_mem( bufsiz ); + + if (aux_mem_handle.is_null()) { + + CP_PRINTERR("own handle is null"); + + return; + } + + + if (MemPool_Wrapper::get_singleton()->lock_mem(aux_mem_handle)) { + CP_PRINTERR("Unable to lock aux new handle"); + + return; + + } + + if (MemPool_Wrapper::get_singleton()->lock_mem(mem_handle)) { + + CP_PRINTERR("Unable to lock own handle"); + + return; + } + + uint8_t* srcuint8_tt8_t*)MemPool_Wrapper::get_singleton()->get_mem(mem_handle); + uint8_t* dstuint8_tt8_t*)MemPool_Wrapper::get_singleton()->get_mem(aux_mem_handle); + + for (int i=0;iunlock_mem(mem_handle); + MemPool_Wrapper::get_singleton()->unlock_mem(aux_mem_handle); + + p_pattern->mem_handle=aux_mem_handle; + p_pattern->event_count=event_count; + + +} +#endif +uint16_t CPPattern::get_length() { + + + return length; +} +CPPattern::CPPattern() { + + + length=DEFAULT_LEN; + event_count=0; + clear(); + +} +bool CPPattern::is_empty() { + + return events==NULL; +} + +CPPattern::~CPPattern() { + + clear(); +} diff --git a/modules/chibi/cp_pattern.h b/modules/chibi/cp_pattern.h new file mode 100644 index 0000000000..4065caa5e5 --- /dev/null +++ b/modules/chibi/cp_pattern.h @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* cp_pattern.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_PATTERN_H +#define CP_PATTERN_H + +#include "cp_note.h" + +class CPPattern { +public: + + + enum { + WIDTH=64, + DEFAULT_LEN=64, + RESIZE_EVERY_BITS=4, + MIN_ROWS=1, //otherwise clipboard wont work + MAX_LEN=256 + + }; + +private: + struct Event { + + uint16_t pos; //column*WIDTH+row + uint8_t note; + uint8_t instrument; + uint8_t volume; + uint8_t command; + uint8_t parameter; + unsigned int script_source_sign; + bool cloned; + }; + + uint16_t length; + uint32_t event_count; + Event* events; + + int32_t get_event_pos(uint16_t p_target_pos); + bool erase_event_at_pos(uint16_t p_pos); + + bool resize_event_list_to(uint32_t p_events); + + void operator=(const CPPattern& p_pattern); //no operator= +public: + + bool is_empty(); + void clear(); + + bool set_note(uint8_t p_column, uint16_t p_row,const CPNote& p_note); //true if no more memory + CPNote get_note(uint8_t p_column,uint16_t p_row); + + CPNote get_transformed_script_note(uint8_t p_column, uint16_t p_row); + int get_scripted_note_target_channel(uint8_t p_column, uint16_t p_row); + void scripted_clone(uint8_t p_column, uint16_t p_row); + void scripted_clone_remove(uint8_t p_column, uint16_t p_row); + void script_transform_note(CPNote& n, const CPNote& p_note); + bool update_scripted_clones_sourcing_channel(int channel); + + //void copy_to(CPPattern *p_pattern) const; + void set_length(uint16_t p_rows); + uint16_t get_length(); + CPPattern(); + ~CPPattern(); + + +}; + +#endif diff --git a/modules/chibi/cp_player_data.cpp b/modules/chibi/cp_player_data.cpp new file mode 100644 index 0000000000..3f3e9a5202 --- /dev/null +++ b/modules/chibi/cp_player_data.cpp @@ -0,0 +1,151 @@ +/*************************************************************************/ +/* cp_player_data.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" +#include + + +CPPlayer::CPPlayer(CPMixer *p_mixer,CPSong *p_song){ + + song=p_song; + mixer=p_mixer; + control.max_voices=p_mixer->get_total_voice_count()-1; //leave one for the sample + control.force_no_nna=false; + control.external_vibrato=false; + control.filters=true; + control.random_seed=128364; //anything + control.play_mode=0; + set_virtual_channels(p_mixer->get_total_voice_count()); + mixer->set_callback( &CPPlayer::callback_function, this ); + + reset(); +} +CPPlayer::~CPPlayer(){ +} + +void CPPlayer::set_virtual_channels(int p_amount) { + + if (p_amount<1) return; + if (p_amount>mixer->get_total_voice_count()) + return; + + control.max_voices=p_amount; + +} + + +void CPPlayer::callback_function(void *p_userdata) { + + CPPlayer*pd=(CPPlayer*)p_userdata; + pd->process_tick(); + +} + +void CPPlayer::process_tick() { + + handle_tick(); + mixer->set_callback_interval( 2500000/control.tempo ); + song_usecs+=2500000/control.tempo; +} + +void CPPlayer::reset() { + + if ( mixer==NULL ) return ; + if ( song==NULL ) return ; + + int i; + + for (i=0;istop_voice(i); + } + + for (i=0;iget_channel_volume(i); + control.channel[i].channel_panning=((int)song->get_channel_pan( i)*PAN_RIGHT/64); + if (song->is_channel_surround(i)) + control.channel[i].channel_panning=PAN_SURROUND; + control.channel[i].mute=song->is_channel_mute( i ); + control.channel[i].chorus_send=song->get_channel_chorus(i)*0xFF/64; + control.channel[i].reverb_send=song->get_channel_reverb(i)*0xFF/64; + } + + + control.speed=song->get_speed(); + control.tempo=song->get_tempo(); + control.global_volume=song->get_global_volume(); + + control.position.current_pattern=0; + control.position.current_row=0; + control.position.current_order=0; + control.position.force_next_order=-1; + control.ticks_counter=control.speed; + control.position.forbid_jump=false; + + song_usecs=0; + +} + +int64_t CPPlayer::get_channel_last_note_time_usec(int p_channel) const { + + CP_FAIL_INDEX_V(p_channel,64,-1); + return control.channel[p_channel].last_event_usecs; + +} + +void CPPlayer::set_channel_global_volume(int p_channel,int p_volume) { + + CP_FAIL_INDEX(p_channel,64); + control.channel[p_channel].channel_global_volume=CLAMP(p_volume,0,255); + +} + +int CPPlayer::get_channel_global_volume(int p_channel) const{ + + CP_FAIL_INDEX_V(p_channel,64,-1); + return control.channel[p_channel].channel_global_volume; + +} + +bool CPPlayer::reached_end_of_song() { + + return control.reached_end; + +} +void CPPlayer::set_force_external_vibratos(bool p_force) { + + control.external_vibrato=p_force; +} +void CPPlayer::set_force_no_nna(bool p_force) { + + control.force_no_nna=p_force; +} diff --git a/modules/chibi/cp_player_data.h b/modules/chibi/cp_player_data.h new file mode 100644 index 0000000000..282592b8f4 --- /dev/null +++ b/modules/chibi/cp_player_data.h @@ -0,0 +1,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 diff --git a/modules/chibi/cp_player_data_control.cpp b/modules/chibi/cp_player_data_control.cpp new file mode 100644 index 0000000000..d9aaed904f --- /dev/null +++ b/modules/chibi/cp_player_data_control.cpp @@ -0,0 +1,324 @@ +/*************************************************************************/ +/* cp_player_data_control.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" + +void CPPlayer::play_start_pattern(int p_pattern) { + + play_start(p_pattern,-1,-1); +} + +void CPPlayer::play_start_song() { + + play_start(-1,-1,-1); +} + +void CPPlayer::play_start_song_from_order(int p_order) { + + play_start(-1,p_order,-1); +} + +void CPPlayer::play_start_song_from_order_and_row(int p_order,int p_row) { + + play_start(-1,p_order,p_row); +} + +void CPPlayer::play_start(int p_pattern, int p_order, int p_row,bool p_lock) { + + + if (control.play_mode!=PLAY_NOTHING) play_stop(); + + + reset(); + + if (p_pattern!=-1) { + + control.play_mode=PLAY_PATTERN; + control.position.current_pattern=p_pattern; + control.position.current_row=(p_row!=-1)?p_row:0; + + } else { + + control.position.current_order=get_song_next_order_idx(song,(p_order==-1)?p_order:p_order-1); + if (control.position.current_order!=-1) { + + control.play_mode=PLAY_SONG; + control.position.current_pattern=song->get_order(control.position.current_order); + control.position.current_row=(p_row!=-1)?p_row:0; + } + } + + + control.reached_end=(control.play_mode==PLAY_NOTHING); + + +} + +void CPPlayer::play_stop() { + + int i; + + + control.play_mode=PLAY_NOTHING; + + for (i=0;istop_voice(i); + } + + for (i=0;iget_channel_volume(p_channel); + control.channel[p_channel].channel_panning=((int)song->get_channel_pan( p_channel)*255/64);*/ + if (p_reserve) { + control.channel[p_channel].mute=false; + control.channel[p_channel].reserved=true; + } else { + + control.channel[p_channel].reserved=false; + + } + process_note(p_channel,note); + + + +} + + +int CPPlayer::get_voice_volume(int p_voice) { + + return voice[p_voice].display_volume; +} + + +int CPPlayer::get_voice_envelope_pos(int p_voice,CPEnvelope *p_envelope) { + + int i,tmp_index=-1; + + i=p_voice; + + + + + if ((song->has_instruments()) && (voice[i].instrument_ptr!=NULL) && (voice[i].fadeout_volume>0)) { + + if ((p_envelope==voice[i].instrument_ptr->get_volume_envelope()) && (voice[i].instrument_ptr->get_volume_envelope()->is_enabled())) { + + tmp_index=voice[i].volume_envelope_ctrl.pos_index; + } + + if ((p_envelope==voice[i].instrument_ptr->get_pan_envelope()) && (voice[i].instrument_ptr->get_pan_envelope()->is_enabled())) { + + tmp_index=voice[i].panning_envelope_ctrl.pos_index; + } + + if ((p_envelope==voice[i].instrument_ptr->get_pitch_filter_envelope()) && (voice[i].instrument_ptr->get_pitch_filter_envelope()->is_enabled())) { + + + tmp_index=voice[i].pitch_envelope_ctrl.pos_index; + } + + } + + + + return tmp_index; +} + +void CPPlayer::goto_next_order() { + + + if (control.play_mode!=PLAY_SONG) return; + + + + control.position.current_row=0; + + + control.position.current_order=get_song_next_order_idx(song, control.position.current_order); + + + + if (control.position.current_order==-1) { + + reset(); + } + + control.position.current_pattern=song->get_order(control.position.current_order); + + +} +void CPPlayer::goto_previous_order() { + + if (control.play_mode!=PLAY_SONG) return; + + + int next_order,current_order; + + control.position.current_row=0; + + current_order=control.position.current_order; + + next_order=get_song_next_order_idx(song, current_order); + + while ((next_order!=control.position.current_order) && (next_order!=-1)) { + + current_order=next_order; + next_order=get_song_next_order_idx(song, current_order); + } + + if (next_order==-1) { + + reset(); + } else { + + control.position.current_order=current_order; + control.position.current_pattern=song->get_order(control.position.current_order); + + } + + + +} + +int CPPlayer::get_channel_voice(int p_channel) { + + if (control.channel[p_channel].slave_voice==NULL) return -1; + else return control.channel[p_channel].slave_voice_index; +} + +const char* CPPlayer::get_voice_sample_name(int p_voice) { + + const char *name = NULL; + + + + if (!voice[p_voice].sample_ptr) name=voice[p_voice].sample_ptr->get_name(); + + + + return name; + +} + + +bool CPPlayer::is_voice_active(int p_voice) { + + return !( ((voice[p_voice].kick==KICK_NOTHING)||(voice[p_voice].kick==KICK_ENVELOPE))&&!mixer->is_voice_active(p_voice) ); + +} + + + +int CPPlayer::get_voice_envelope_pos(int p_voice,CPInstrument::EnvelopeType p_env_type) { + + if (!is_voice_active(p_voice)) + return -1; + + Voice_Control::Envelope_Control *env=0; + + switch (p_env_type) { + + case CPInstrument::VOLUME_ENVELOPE: env=&voice[p_voice].volume_envelope_ctrl; break; + case CPInstrument::PAN_ENVELOPE: env=&voice[p_voice].panning_envelope_ctrl; break; + case CPInstrument::PITCH_ENVELOPE: env=&voice[p_voice].pitch_envelope_ctrl; break; + + } + + if (!env) + return -1; + + if (!env->active || env->terminated) + return -1; + + return env->pos_index; +} + + +CPEnvelope* CPPlayer::get_voice_envelope(int p_voice,CPInstrument::EnvelopeType p_env_type) { + + CPInstrument *ins=voice[p_voice].instrument_ptr; + + if (!ins) + return 0; + + switch( p_env_type ) { + + + case CPInstrument::VOLUME_ENVELOPE: return ins->get_volume_envelope(); + case CPInstrument::PAN_ENVELOPE: return ins->get_pan_envelope(); + case CPInstrument::PITCH_ENVELOPE: return ins->get_pitch_filter_envelope(); + }; + + return 0; + +} + +const char * CPPlayer::get_voice_instrument_name(int p_voice) { + + + + const char *name = NULL; + + + + if (voice[p_voice].instrument_ptr!=NULL) name=voice[p_voice].instrument_ptr->get_name(); + + + + return name; + +} +void CPPlayer::set_filters_enabled(bool p_enable){ + + control.filters=p_enable; +} + +int CPPlayer::get_voice_sample_index(int p_voice) { + + return voice[p_voice].sample_index; +} diff --git a/modules/chibi/cp_player_data_effects.cpp b/modules/chibi/cp_player_data_effects.cpp new file mode 100644 index 0000000000..3a52a3b91b --- /dev/null +++ b/modules/chibi/cp_player_data_effects.cpp @@ -0,0 +1,1232 @@ +/*************************************************************************/ +/* cp_player_data_effects.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" + + + +/********************** + complex effects +***********************/ +#define RANDOM_MAX 2147483647 + +static inline int32_t cp_random_generate(int32_t *seed) { + int32_t k; + int32_t s = (int32_t)(*seed); + if (s == 0) + s = 0x12345987; + k = s / 127773; + s = 16807 * (s - k * 127773) - 2836 * k; + if (s < 0) + s += 2147483647; + (*seed) = (int32_t)s; + return (int32_t)(s & RANDOM_MAX); +} + + + +void CPPlayer::do_vibrato(int p_track,bool fine) { + + uint8_t q; + uint16_t temp=0; + + if ((control.ticks_counter==0) && control.channel[p_track].row_has_note) control.channel[p_track].vibrato_position=0; + + q=(control.channel[p_track].vibrato_position>>2)&0x1f; + + switch (control.channel[p_track].vibrato_type) { + case 0: /* sine */ + temp=vibrato_table[q]; + break; + case 1: /* square wave */ + temp=255; + break; + case 2: /* ramp down */ + q<<=3; + if (control.channel[p_track].vibrato_position<0) q=255-q; + temp=q; + break; + case 3: /* random */ + temp=cp_random_generate(&control.random_seed) %256;//getrandom(256); + break; + } + + temp*=control.channel[p_track].vibrato_depth; + + if (song->has_old_effects()) { + + temp>>=7; + } else { + + temp>>=8; + } + + if (!fine) temp<<=2; + + if (control.channel[p_track].vibrato_position>=0) { + + control.channel[p_track].period=control.channel[p_track].aux_period+temp; + } else { + + control.channel[p_track].period=control.channel[p_track].aux_period-temp; + } + + if (!song->has_old_effects() || control.ticks_counter) control.channel[p_track].vibrato_position+=control.channel[p_track].vibrato_speed; +} + + +void CPPlayer::do_pitch_slide_down(int p_track,uint8_t inf) { + + uint8_t hi,lo; + + if (inf) control.channel[p_track].pitch_slide_info=inf; + else inf=control.channel[p_track].pitch_slide_info; + + hi=inf>>4; + lo=inf&0xf; + + if (hi==0xf) { + + if (!control.ticks_counter) control.channel[p_track].aux_period+=(uint16_t)lo<<2; + } else if (hi==0xe) { + + if (!control.ticks_counter) control.channel[p_track].aux_period+=lo; + } else { + + if (control.ticks_counter) control.channel[p_track].aux_period+=(uint16_t)inf<<2; + } +} + +void CPPlayer::do_pitch_slide_up(int p_track,uint8_t inf) { + + uint8_t hi,lo; + + if (inf) control.channel[p_track].pitch_slide_info=inf; + else inf=control.channel[p_track].pitch_slide_info; + + hi=inf>>4; + lo=inf&0xf; + + if (hi==0xf) { + + if (!control.ticks_counter) control.channel[p_track].aux_period-=(uint16_t)lo<<2; + } else if (hi==0xe) { + + if (!control.ticks_counter) control.channel[p_track].aux_period-=lo; + } else { + + if (control.ticks_counter) control.channel[p_track].aux_period-=(uint16_t)inf<<2; + } +} + +void CPPlayer::do_pitch_slide_to_note(int p_track) { + + if (control.ticks_counter) { + int dist; + + /* We have to slide a->period towards a->wantedperiod, compute the + difference between those two values */ + dist=control.channel[p_track].period-control.channel[p_track].slide_to_period; + + /* if they are equal or if portamentospeed is too big... */ + if ((!dist)||((control.channel[p_track].portamento_speed<<2)>cp_intabs(dist))) { + /* ... make tmpperiod equal tperiod */ + control.channel[p_track].aux_period=control.channel[p_track].period=control.channel[p_track].slide_to_period; + } else { + + if (dist>0) { + + control.channel[p_track].aux_period-=control.channel[p_track].portamento_speed<<2; + control.channel[p_track].period-=control.channel[p_track].portamento_speed<<2; /* dist>0 slide up */ + } else { + control.channel[p_track].aux_period+=control.channel[p_track].portamento_speed<<2; + control.channel[p_track].period+=control.channel[p_track].portamento_speed<<2; /* dist<0 slide down */ + } + } + + } else { + + control.channel[p_track].aux_period=control.channel[p_track].period; + } +} + +void CPPlayer::do_tremor(int p_track) { + + uint8_t on,off,inf; + + inf=control.channel[p_track].current_parameter; + + if (inf) { + control.channel[p_track].tremor_info=inf; + } else { + inf= control.channel[p_track].tremor_info; + if (!inf) return; + } + + //if (!control.ticks_counter) return; + + on=(inf>>4); + off=(inf&0xf); + + control.channel[p_track].tremor_position%=(on+off); + control.channel[p_track].volume=(control.channel[p_track].tremor_position>4; + + pan=(control.channel[p_track].panning==PAN_SURROUND)?PAN_CENTER:control.channel[p_track].panning; + + if (!hi) + pan+=lo<<2; + else + if (!lo) { + pan-=hi<<2; + } else + if (hi==0xf) { + if (!control.ticks_counter) pan+=lo<<2; + } else + if (lo==0xf) { + if (!control.ticks_counter) pan-=hi<<2; + } + //this sets both chan & voice paning + control.channel[p_track].panning=(panPAN_RIGHT?PAN_RIGHT:pan); + control.channel[p_track].channel_panning=control.channel[p_track].panning; +} + +void CPPlayer::do_volume_slide(int p_track,int inf) { + + uint8_t hi,lo; + + lo=inf&0xf; + hi=inf>>4; + + if (!lo) { + + if ((control.ticks_counter)) control.channel[p_track].aux_volume+=hi; + + } else if (!hi) { + + if ((control.ticks_counter)) control.channel[p_track].aux_volume-=lo; + + } else if (lo==0xf) { + + if (!control.ticks_counter) control.channel[p_track].aux_volume+=(hi?hi:0xf); + } else if (hi==0xf) { + + if (!control.ticks_counter) control.channel[p_track].aux_volume-=(lo?lo:0xf); + } else return; + + if (control.channel[p_track].aux_volume<0) { + + control.channel[p_track].aux_volume=0; + } else if (control.channel[p_track].aux_volume>64) { + + control.channel[p_track].aux_volume=64; + } +} + +void CPPlayer::do_channel_volume_slide(int p_track) { + + uint8_t lo, hi,inf; + + inf=control.channel[p_track].current_parameter; + + if (inf) control.channel[p_track].channel_volume_slide_info=inf; + inf=control.channel[p_track].channel_volume_slide_info; + + lo=inf&0xf; + hi=inf>>4; + + if (!hi) + control.channel[p_track].channel_volume-=lo; + else + if (!lo) { + control.channel[p_track].channel_volume+=hi; + } else + if (hi==0xf) { + if (!control.ticks_counter) control.channel[p_track].channel_volume-=lo; + } else + if (lo==0xf) { + if (!control.ticks_counter) control.channel[p_track].channel_volume+=hi; + } + + if (control.channel[p_track].channel_volume<0) control.channel[p_track].channel_volume=0; + if (control.channel[p_track].channel_volume>64) control.channel[p_track].channel_volume=64; +} + +void CPPlayer::do_tremolo(int p_track) { + + uint8_t q; + int16_t temp=0; + + if ((control.ticks_counter==0) && control.channel[p_track].row_has_note) control.channel[p_track].tremolo_position=0; + + q=(control.channel[p_track].tremolo_position>>2)&0x1f; + + switch (control.channel[p_track].tremolo_type) { + case 0: /* sine */ + temp=vibrato_table[q]; + break; + case 1: /* ramp down */ + q<<=3; + if (control.channel[p_track].tremolo_position<0) q=255-q; + temp=q; + break; + case 2: /* square wave */ + temp=255; + break; + case 3: /* random */ + temp=cp_random_generate(&control.random_seed) % 256;//getrandom(256); + break; + } + + temp*=control.channel[p_track].tremolo_depth; + temp>>=7; + + + + if (control.channel[p_track].tremolo_position>=0) { + + + control.channel[p_track].volume=control.channel[p_track].aux_volume+temp; + if (control.channel[p_track].volume>64) control.channel[p_track].volume=64; + } else { + + control.channel[p_track].volume=control.channel[p_track].aux_volume-temp; + if (control.channel[p_track].volume<0) control.channel[p_track].volume=0; + } + + /*if (control.ticks_counter)*/ control.channel[p_track].tremolo_position+=control.channel[p_track].tremolo_speed; + +} + +void CPPlayer::do_arpegio(int p_track) { + + uint8_t note,dat; + //note=control.channel[p_track].note; + note=0; + + if (control.channel[p_track].current_parameter) { + + control.channel[p_track].arpegio_info=control.channel[p_track].current_parameter; + } + + dat=control.channel[p_track].arpegio_info; + + if (dat) { + + switch (control.ticks_counter%3) { + + case 1: { + + note+=(dat>>4); + + } break; + case 2: { + + note+=(dat&0xf); + } break; + } + + if (song->has_linear_slides()) { + + control.channel[p_track].period=control.channel[p_track].aux_period-cp_intabs(get_period((uint16_t)46,0)-get_period((uint16_t)44,0))*note; + } else if (control.channel[p_track].sample_ptr) { + + control.channel[p_track].period=get_period( (((uint16_t)control.channel[p_track].note)+note)<<1,CPSampleManager::get_singleton()->get_c5_freq( (control.channel[p_track].sample_ptr->get_sample_data()))); + } + + control.channel[p_track].has_own_period=true; + } + + +} + + +void CPPlayer::do_retrig(int p_track) { + + uint8_t inf; + + inf=control.channel[p_track].current_parameter; + + if (inf) { + + control.channel[p_track].retrig_volslide=inf>>4; + control.channel[p_track].retrig_speed=inf&0xf; + } + + /* only retrigger if low nibble > 0 */ + if ( control.channel[p_track].retrig_speed>0) { + + if ( !control.channel[p_track].retrig_counter ) { + /* when retrig counter reaches 0, reset counter and restart the + sample */ + if (control.channel[p_track].kick!=KICK_NOTE) control.channel[p_track].kick=KICK_NOTEOFF; + control.channel[p_track].retrig_counter=control.channel[p_track].retrig_speed; + + + if ((control.ticks_counter)/*||(pf->flags&UF_S3MSLIDES)*/) { + switch (control.channel[p_track].retrig_volslide) { + case 1: + case 2: + case 3: + case 4: + case 5: + control.channel[p_track].aux_volume-=(1<<(control.channel[p_track].retrig_volslide-1)); + break; + case 6: + control.channel[p_track].aux_volume=(2*control.channel[p_track].aux_volume)/3; + break; + case 7: + control.channel[p_track].aux_volume>>=1; + break; + case 9: + case 0xa: + case 0xb: + case 0xc: + case 0xd: + control.channel[p_track].aux_volume+=(1<<(control.channel[p_track].retrig_volslide-9)); + break; + case 0xe: + control.channel[p_track].aux_volume=(3*control.channel[p_track].aux_volume)>>1; + break; + case 0xf: + control.channel[p_track].aux_volume=control.channel[p_track].aux_volume<<1; + break; + } + if (control.channel[p_track].aux_volume<0) control.channel[p_track].aux_volume=0; + else if (control.channel[p_track].aux_volume>64) control.channel[p_track].aux_volume=64; + } + } + control.channel[p_track].retrig_counter--; /* countdown */ + } +} + +void CPPlayer::do_global_volume_slide(int p_track) { + + uint8_t lo,hi,inf; + + inf=control.channel[p_track].current_parameter; + + if (inf) control.channel[p_track].global_volume_slide_info=inf; + inf=control.channel[p_track].global_volume_slide_info; + + lo=inf&0xf; + hi=inf>>4; + + if (!lo) { + if (control.ticks_counter) control.global_volume+=hi; + } else + if (!hi) { + if (control.ticks_counter) control.global_volume-=lo; + } else + if (lo==0xf) { + if (!control.ticks_counter) control.global_volume+=hi; + } else + if (hi==0xf) { + if (!control.ticks_counter) control.global_volume-=lo; + } + + if (control.global_volume<0) control.global_volume=0; + if (control.global_volume>128) control.global_volume=128; +} + +void CPPlayer::do_panbrello(int p_track) { + + uint8_t q; + int32_t temp=0; + + q=control.channel[p_track].panbrello_position; + + switch (control.channel[p_track].panbrello_type) { + case 0: {/* sine */ + temp=panbrello_table[q]; + } break; + case 1: {/* square wave */ + temp=(q<0x80)?64:0; + } break; + case 2: {/* ramp down */ + q<<=3; + temp=q; + } break; + case 3: {/* random */ + if (control.channel[p_track].panbrello_position>=control.channel[p_track].panbrello_speed) { + control.channel[p_track].panbrello_position=0; + temp=cp_random_generate(&control.random_seed)%256;//getrandom(256); + } + } break; + } + + + + temp=temp*(int)control.channel[p_track].panbrello_depth/0xF; + temp<<=1; + if (control.channel[p_track].channel_panning!=PAN_SURROUND) + temp+=control.channel[p_track].channel_panning; + + control.channel[p_track].panning=(tempPAN_RIGHT?PAN_RIGHT:temp); + control.channel[p_track].panbrello_position+=control.channel[p_track].panbrello_speed; +} + +/****************** + S effect +*******************/ + + +void CPPlayer::do_effect_S(int p_track) { + + uint8_t inf,c,dat; + + dat=control.channel[p_track].current_parameter; + + inf=dat&0xf; + c=dat>>4; + + if (!dat) { + c=control.channel[p_track].current_S_effect; + inf=control.channel[p_track].current_S_data; + } else { + control.channel[p_track].current_S_effect=c; + control.channel[p_track].current_S_data=inf; + } + + switch (c) { + case 1: {/* S1x set glissando voice */ + // this is unsupported in IT! + + control.channel[p_track].chorus_send=inf*0xFF/0xF; + + }break; + case 2: /* S2x set finetune */ + //Also not supported! + break; + case 3: /* S3x set vibrato waveform */ + if (inf<4) control.channel[p_track].vibrato_type=inf; + break; + case 4: /* S4x set tremolo waveform */ + if (inf<4) control.channel[p_track].tremolo_type=inf; + break; + case 5: /* S5x panbrello */ + if (inf<4) control.channel[p_track].panbrello_type=inf; + break; + case 6: {/* S6x delay x number of frames (patdly) */ + + if (control.ticks_counter) break; + if (!control.pattern_delay_2) control.pattern_delay_1=inf+1; /* only once, when vbtick=0 */ + + } break; + case 7: /* S7x instrument / NNA commands */ + + if (!song->has_instruments()) + break; + switch(inf) { + + case 0x3: { + + control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_CUT; + } break; + case 0x4: { + + control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_CONTINUE; + } break; + case 0x5: { + + control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_OFF; + } break; + case 0x6: { + + control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_FADE; + } break; + case 0x7: { + + if (control.channel[p_track].slave_voice) + control.channel[p_track].slave_voice->volume_envelope_ctrl.active=false; + } break; + case 0x8: { + + if (control.channel[p_track].slave_voice) + control.channel[p_track].slave_voice->volume_envelope_ctrl.active=true; + + } break; + case 0x9: { + + if (control.channel[p_track].slave_voice) + control.channel[p_track].slave_voice->panning_envelope_ctrl.active=false; + + } break; + case 0xA: { + + if (control.channel[p_track].slave_voice) + control.channel[p_track].slave_voice->panning_envelope_ctrl.active=true; + + } break; + case 0xB: { + if (control.channel[p_track].slave_voice) + control.channel[p_track].slave_voice->pitch_envelope_ctrl.active=false; + + } break; + case 0xC: { + + if (control.channel[p_track].slave_voice) + control.channel[p_track].slave_voice->pitch_envelope_ctrl.active=true; + + } break; + + } break; + + break; + case 8: {/* S8x set panning position */ + +// if (pf->panflag) { + if (inf<=8) inf<<=4; + else inf*=17; + control.channel[p_track].panning=control.channel[p_track].channel_panning=inf; +// } + } break; + + case 9: { /* S9x set surround sound */ + //if (pf->panflag) + control.channel[p_track].panning=control.channel[p_track].channel_panning=PAN_SURROUND; + } break; + case 0xA:{ /* SAy set high order sample offset yxx00h */ + + if (control.channel[p_track].current_parameter) control.channel[p_track].hi_offset=(int32_t)inf<<16; + control.channel[p_track].sample_start_index=control.channel[p_track].hi_offset|control.channel[p_track].lo_offset; + } break; + case 0xB: { /* SBx pattern loop */ + if (control.ticks_counter) break; + + if (inf) { /* set reppos or repcnt ? */ + /* set repcnt, so check if repcnt already is set, which means we + are already looping */ + if (control.channel[p_track].pattern_loop_count>0) + control.channel[p_track].pattern_loop_count--; /* already looping, decrease counter */ + else { + control.channel[p_track].pattern_loop_count=inf; /* not yet looping, so set repcnt */ + } + + if (control.channel[p_track].pattern_loop_count>0) { /* jump to reppos if repcnt>0 */ + + control.position=control.previous_position; // This will also anulate any Cxx or break.. + + control.position.current_row=control.channel[p_track].pattern_loop_position; + control.position.forbid_jump=true; + } + + } else { + + + control.channel[p_track].pattern_loop_position=control.position.current_row-1; + } + + } break; + case 0xC: { /* SCx notecut */ + + if (control.ticks_counter>=inf) { + + control.channel[p_track].aux_volume=0; + control.channel[p_track].note_end_flags|=END_NOTE_OFF; + control.channel[p_track].note_end_flags|=END_NOTE_KILL; + } + } break; + case 0xD: {/* SDx notedelay */ + + if (!control.ticks_counter) { + + control.channel[p_track].note_delay=inf; + + } else if (control.channel[p_track].note_delay) { + + control.channel[p_track].note_delay--; + } + + } break; + case 0xF: {/* SEx patterndelay */ + + if (control.ticks_counter) break; + if (!control.pattern_delay_2) control.pattern_delay_1=inf+1; /* only once, when vbtick=0 */ + + } break; + } +} + + + + + + + + +/********************* + volume effects +**********************/ + +void CPPlayer::run_volume_column_effects(int p_track) { + + uint8_t param=control.channel[p_track].current_volume_parameter; + + + switch ('A'+control.channel[p_track].current_volume_command) { + + case 'A': { + + if (param>0) control.channel[p_track].volcol_volume_slide=param; + else param=control.channel[p_track].volcol_volume_slide; + + do_volume_slide(p_track,param*0x10+0xF); + + } break; + case 'B': { + + if (param>0) control.channel[p_track].volcol_volume_slide=param; + else param=control.channel[p_track].volcol_volume_slide; + + do_volume_slide(p_track,0xF0+param); + + } break; + case 'C': { + + if (param>0) control.channel[p_track].volcol_volume_slide=param; + else param=control.channel[p_track].volcol_volume_slide; + + do_volume_slide(p_track,param*0x10); + } break; + case 'D': { + + if (param>0) control.channel[p_track].volcol_volume_slide=param; + else param=control.channel[p_track].volcol_volume_slide; + do_volume_slide(p_track,param); + + } break; + case 'E': { + + do_pitch_slide_down(p_track,param<<2); + } break; + case 'F': { + + do_pitch_slide_up(p_track,param<<2); + } break; + case 'G': { + + const uint8_t slide_table[]={0,1,4,8,16,32,64,96,128,255}; + if (param) { + + control.channel[p_track].portamento_speed=slide_table[param]; + } + + if (control.channel[p_track].period && (control.channel[p_track].old_note<=120)) { + + if ( (!control.ticks_counter) && (control.channel[p_track].new_instrument) ){ + + //control.channel[p_track].kick=KICK_NOTE; + //control.channel[p_track].sample_start_index=0; // < am i stupid? + } else { + + control.channel[p_track].kick=(control.channel[p_track].kick==KICK_NOTE)?KICK_ENVELOPE:KICK_NOTHING; + do_pitch_slide_to_note(p_track); + control.channel[p_track].has_own_period=true; + } + + } + } break; + case 'H': { + + + if (!control.ticks_counter) { + if (param&0x0f) control.channel[p_track].vibrato_depth=param; + } + control.channel[p_track].doing_vibrato=true; + if (control.external_vibrato) break; + if (control.channel[p_track].period) { + + do_vibrato(p_track,false); + control.channel[p_track].has_own_period=true; + } + + } break; + } +} +/********************* + table +**********************/ + + +void CPPlayer::run_effects(int p_track) { + + switch ('A'+control.channel[p_track].current_command) { + + case 'A': { + + if ((control.ticks_counter>0) || (control.pattern_delay_2>0)) break; + + int new_speed; + + new_speed=control.channel[p_track].current_parameter % 128; + + if (new_speed>0) { + control.speed=new_speed; + control.ticks_counter=0; + } + } break; + case 'B': { + + int next_order; + + if (control.ticks_counter || control.position.forbid_jump) break; + + control.position.current_row=0; + + if (control.play_mode==PLAY_PATTERN) break; + + next_order=get_song_next_order_idx(song, (int)control.channel[p_track].current_parameter-1); + + if (next_order!=-1) { + // Do we have a "next order?" + control.position.current_pattern=song->get_order(next_order); + control.position.force_next_order=next_order; + + } else { + // no, probably the user deleted the orderlist. + control.play_mode=PLAY_NOTHING; + reset(); + } + } break; + case 'C': { + + int next_order; + + if (control.ticks_counter || control.position.forbid_jump) break; + + control.position.current_row=control.channel[p_track].current_parameter; + + if (control.play_mode==PLAY_PATTERN) { + + if (control.position.current_row>=song->get_pattern(control.position.current_pattern)->get_length()) { + + control.position.current_row=0; + } + + break; + } + + next_order=get_song_next_order_idx(song, (int)control.position.current_order); + + if (next_order!=-1) { + // Do we have a "next order?" + control.position.current_pattern=song->get_order(next_order); + + if (control.position.current_row>=song->get_pattern(song->get_order(next_order))->get_length()) { + + control.position.current_row=0; + } + + control.position.force_next_order=next_order; + + } else { + // no, probably the user deleted the orderlist. + control.play_mode=PLAY_NOTHING; + reset(); + } + + } break; + case 'D': { + + uint8_t inf ; + //explicitslides=1; + inf=control.channel[p_track].current_parameter; + + if (inf) control.channel[p_track].volume_slide_info=inf; + else inf=control.channel[p_track].volume_slide_info; + + do_volume_slide(p_track,inf); + + } break; + case 'E': { + + uint8_t inf; + + inf=control.channel[p_track].current_parameter; + do_pitch_slide_down(p_track,inf); + + } break; + case 'F': { + + uint8_t inf; + + inf=control.channel[p_track].current_parameter; + do_pitch_slide_up(p_track,inf); + + } break; + case 'G': { + + if (control.channel[p_track].current_parameter) { + + control.channel[p_track].portamento_speed=control.channel[p_track].current_parameter; + } + + if (control.channel[p_track].period && (control.channel[p_track].old_note<=120)) { + + if ( (!control.ticks_counter) && (control.channel[p_track].new_instrument) ){ + + + control.channel[p_track].kick=KICK_NOTE; + control.channel[p_track].sample_start_index=0; + + } else { + + control.channel[p_track].kick=(control.channel[p_track].kick==KICK_NOTE)?KICK_ENVELOPE:KICK_NOTHING; + } + + do_pitch_slide_to_note(p_track); + control.channel[p_track].has_own_period=true; + } + + } break; + case 'H': { + + uint8_t dat; + + control.channel[p_track].doing_vibrato=true; + + dat=control.channel[p_track].current_parameter; + + if (!control.ticks_counter) { + if (dat&0x0f) control.channel[p_track].vibrato_depth=dat&0xf; + if (dat&0xf0) control.channel[p_track].vibrato_speed=(dat&0xf0)>>2; + } + + if (control.external_vibrato) break; + + if (control.channel[p_track].period) { + + do_vibrato(p_track,false); + control.channel[p_track].has_own_period=true; + } + + } break; + case 'I': { + + do_tremor(p_track); + control.channel[p_track].has_own_volume=true; + } break; + case 'J': { + + do_arpegio(p_track); + } break; + case 'K': { + + uint8_t inf ; + //explicitslides=1; + inf=control.channel[p_track].current_parameter; + + control.channel[p_track].doing_vibrato=true; + + + if (inf) control.channel[p_track].volume_slide_info=inf; + else inf=control.channel[p_track].volume_slide_info; + + do_volume_slide(p_track,inf); + + if (control.external_vibrato) break; + + if (control.channel[p_track].period) { + + do_vibrato(p_track,false); + control.channel[p_track].has_own_period=true; + } + + } break; + case 'L': { + uint8_t inf ; + //explicitslides=1; + inf=control.channel[p_track].current_parameter; + + if (inf) control.channel[p_track].volume_slide_info=inf; + else inf=control.channel[p_track].volume_slide_info; + + do_volume_slide(p_track,inf); + + if (control.channel[p_track].period && (control.channel[p_track].old_note<=120)) { + if ( (!control.ticks_counter) && (control.channel[p_track].new_instrument) ){ + + control.channel[p_track].kick=KICK_NOTE; + control.channel[p_track].sample_start_index=0; + + } else { + + control.channel[p_track].kick=(control.channel[p_track].kick==KICK_NOTE)?KICK_ENVELOPE:KICK_NOTHING; + } + + do_pitch_slide_to_note(p_track); + control.channel[p_track].has_own_period=true; + } + } break; + case 'M': { + control.channel[p_track].channel_volume=control.channel[p_track].current_parameter; + if (control.channel[p_track].channel_volume>64) control.channel[p_track].channel_volume=64; + else if (control.channel[p_track].channel_volume<0) control.channel[p_track].channel_volume=0; + } break; + case 'N': { + + do_channel_volume_slide(p_track); + } + case 'O': { + + if (!control.ticks_counter) { + + if (control.channel[p_track].current_parameter) control.channel[p_track].lo_offset=(uint16_t)control.channel[p_track].current_parameter<<8; + control.channel[p_track].sample_start_index=control.channel[p_track].hi_offset|control.channel[p_track].lo_offset; + + //if ((control.channel[p_track].sample_ptr!=NULL)&&(control.channel[p_track].sample_start_index>control.channel[p_track].sample_ptr->data.size)) { + //TODO, O effect + //a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length; + //} + } + } break; + case 'P': { + + do_pan_slide(p_track); + } break; + case 'Q': { + do_retrig(p_track); + + } break; + case 'R': { + + + uint8_t dat; + + if (control.channel[p_track].current_parameter) { + + control.channel[p_track].tremolo_info=control.channel[p_track].current_parameter; + } + + dat=control.channel[p_track].tremolo_info; + + if (!control.ticks_counter && dat) { + + if (dat&0x0f) control.channel[p_track].tremolo_depth=dat&0xf; + if (dat&0xf0) control.channel[p_track].tremolo_speed=(dat&0xf0)>>2; + } + + do_tremolo(p_track); + control.channel[p_track].has_own_volume=true; + + } break; + case 'S': { + + do_effect_S(p_track); + } break; + case 'T': { + uint8_t dat; + int16_t temp=control.tempo; + + if (control.pattern_delay_2) return; + + if (control.channel[p_track].current_parameter) { + + control.channel[p_track].tempo_slide_info=control.channel[p_track].current_parameter; + } + + dat=control.channel[p_track].tempo_slide_info; + + if (dat>=0x20) { + + if (control.ticks_counter) break; + control.tempo=dat; + } else { + + if (!control.ticks_counter) break; + + if (dat&0x10) { + + temp+=(dat&0x0f); + } else { + + temp-=dat; + } + control.tempo=(temp>255)?255:(temp<0x20?0x20:temp); + } + + } break; + case 'U': { + + uint8_t dat; + + dat=control.channel[p_track].current_parameter; + control.channel[p_track].doing_vibrato=true; + if (!control.ticks_counter) { + if (dat&0x0f) control.channel[p_track].vibrato_depth=dat&0xf; + if (dat&0xf0) control.channel[p_track].vibrato_speed=(dat&0xf0)>>2; + } + + if (control.external_vibrato) break; + + if (control.channel[p_track].period) { + + do_vibrato(p_track,true); + control.channel[p_track].has_own_period=true; + } + } break; + case 'V': { + + control.global_volume=control.channel[p_track].current_parameter; + if (control.global_volume>128) control.global_volume=128; + } break; + case 'W': { + do_global_volume_slide(p_track); + } break; + case 'X': { + //sets both channel and current + control.channel[p_track].channel_panning=control.channel[p_track].current_parameter; + control.channel[p_track].panning=control.channel[p_track].current_parameter; + } break; + case 'Y': { + + uint8_t dat; + + if (control.channel[p_track].current_parameter) { + + control.channel[p_track].panbrello_info=control.channel[p_track].current_parameter; + } + + dat=control.channel[p_track].panbrello_info; + + if (!control.ticks_counter) { + + if (dat&0x0f) control.channel[p_track].panbrello_depth=(dat&0xf); + if (dat&0xf0) control.channel[p_track].panbrello_speed=(dat&0xf0)>>4; + } + + //if (pf->panflag) + if (control.channel[p_track].panning!=PAN_SURROUND)do_panbrello(p_track); + + } break; + case 'Z': { + //I DO! cuttoff! + uint16_t dat=control.channel[p_track].current_parameter; + + if (dat<0x80) { + + control.channel[p_track].filter.it_cutoff=dat*2; + if (control.channel[p_track].filter.it_cutoff>0x80) + control.channel[p_track].filter.it_cutoff++; + } else if (dat<0x90) { + + control.channel[p_track].filter.it_reso=(dat-0x80)*0x10; + } else { + + control.channel[p_track].reverb_send=(dat-0x90)*255/0x6F; + } + + } break; + + } + +} + +void CPPlayer::pre_process_effects() { + +// MP_VOICE *aout; + int i; + + for (i=0;icontrol[mp_channel]; + + // if ((aout=a->slave)) { + // a->fadevol=aout->fadevol; + // a->period=aout->period; + // if (a->kick==KICK_KEYOFF) a->keyoff=aout->keyoff; + //} + + //if (!a->row) continue; + //UniSetRow(a->row); + control.channel[i].has_own_period=false; + control.channel[i].has_own_volume=false; + control.channel[i].doing_vibrato=false; + //explicitslides=0; + //pt_playeffects(); + if (control.ticks_counterflags&UF_BGSLIDES) { + // if (!explicitslides && a->sliding) + // DoS3MVolSlide(0); + // else if (a->tmpvolume) a->sliding=explicitslides; + //} + + if (!control.channel[i].has_own_period) control.channel[i].period=control.channel[i].aux_period; + if (!control.channel[i].has_own_volume) control.channel[i].volume=control.channel[i].aux_volume; + + if ((control.channel[i].sample_ptr!=NULL) && !(song->has_instruments() && (control.channel[i].instrument_ptr==NULL))) { + + if (song->has_instruments()) { + + control.channel[i].output_volume= + (control.channel[i].volume*control.channel[i].sample_ptr->get_global_volume()*control.channel[i].instrument_ptr->get_volume_global_amount())/2048; + control.channel[i].output_volume=control.channel[i].output_volume*control.channel[i].random_volume_variation/100; + + } else { + + control.channel[i].output_volume= + (control.channel[i].volume*control.channel[i].sample_ptr->get_global_volume())>>4; + + } + + if (control.channel[i].output_volume>256) { + + control.channel[i].output_volume=256; + + } else if (control.channel[i].output_volume<0) { + + control.channel[i].output_volume=0; + } + + + } + } + +} diff --git a/modules/chibi/cp_player_data_envelopes.cpp b/modules/chibi/cp_player_data_envelopes.cpp new file mode 100644 index 0000000000..96af42d19f --- /dev/null +++ b/modules/chibi/cp_player_data_envelopes.cpp @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* cp_player_data_envelopes.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" + + +void CPPlayer::Voice_Control::start_envelope(CPEnvelope *p_envelope,Envelope_Control *p_envelope_ctrl,Envelope_Control *p_from_env) { + + + if (p_from_env && p_envelope->is_carry_enabled() && !p_from_env->terminated) { + + + *p_envelope_ctrl=*p_from_env; + } else { + p_envelope_ctrl->pos_index=0; + p_envelope_ctrl->status=1; + p_envelope_ctrl->sustain_looping=p_envelope->is_sustain_loop_enabled(); + p_envelope_ctrl->looping=p_envelope->is_loop_enabled(); + p_envelope_ctrl->terminated=false; + p_envelope_ctrl->kill=false; + p_envelope_ctrl->value=p_envelope->get_height_at_pos(p_envelope_ctrl->pos_index); + } +} + +bool CPPlayer::Voice_Control::process_envelope(CPEnvelope *p_envelope,Envelope_Control *p_envelope_ctrl) { + + if (!p_envelope_ctrl->active) + return false; + + if (note_end_flags&END_NOTE_OFF) p_envelope_ctrl->sustain_looping=false; + + p_envelope_ctrl->value=p_envelope->get_height_at_pos(p_envelope_ctrl->pos_index); + if (p_envelope_ctrl->value==CPEnvelope::NO_POINT) + return false; + + + p_envelope_ctrl->pos_index++; + + if (p_envelope_ctrl->sustain_looping) { + + if (p_envelope_ctrl->pos_index>p_envelope->get_node(p_envelope->get_sustain_loop_end()).tick_offset) { + + p_envelope_ctrl->pos_index=p_envelope->get_node(p_envelope->get_sustain_loop_begin()).tick_offset; + } + + } else if (p_envelope_ctrl->looping) { + + if (p_envelope_ctrl->pos_index>p_envelope->get_node(p_envelope->get_loop_end()).tick_offset) { + + p_envelope_ctrl->pos_index=p_envelope->get_node(p_envelope->get_loop_begin()).tick_offset; + } + + } + + if (p_envelope_ctrl->pos_index>p_envelope->get_node(p_envelope->get_node_count()-1).tick_offset) { + + p_envelope_ctrl->terminated=true; + p_envelope_ctrl->pos_index=p_envelope->get_node(p_envelope->get_node_count()-1).tick_offset; + if (p_envelope->get_node(p_envelope->get_node_count()-1).value==0) p_envelope_ctrl->kill=true; + } + + return true; +} diff --git a/modules/chibi/cp_player_data_events.cpp b/modules/chibi/cp_player_data_events.cpp new file mode 100644 index 0000000000..fb5090461b --- /dev/null +++ b/modules/chibi/cp_player_data_events.cpp @@ -0,0 +1,679 @@ +/*************************************************************************/ +/* cp_player_data_events.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" +#include "cp_sample_manager.h" +#include "stdio.h" +/* + setup_voices(): + +This will go throught all the REAL channels, if it finds a channel +that needs to be restarted or assigned a new VIRTUAL channel, then it +will just find one and do it. + +*/ + + +#define C5FREQ 261.6255653006 +static const int32_t C5FREQ_MIXER = ((int32_t)(C5FREQ*(float)(1<has_instruments() && !control.force_no_nna) { + + if (control.channel[i].slave_voice==NULL) { // no slave?? + + int newchn; + if ((newchn=find_empty_voice())!=-1) { + + control.channel[i].slave_voice_index=newchn; + control.channel[i].slave_voice=&voice[newchn]; + } + } + + } else { + if (islave_voice=NULL; + + } + //notify the voice that the current channel is the master + v.master_channel=&control.channel[i]; + //set the voice as slave of the current channel + control.channel[i].slave_voice=&v; + //master channel index of the voice + v.master_channel_index=i; + v.has_master_channel=true; + } + + } else { + // nope.. + // so if we DO have a slave voice then use it. + if ( control.channel[i].slave_voice!=NULL ) { + + voice_index=control.channel[i].slave_voice_index; + } + } + //assuming this channel has a slave voice.. + if (voice_index>=0) { + + // IMPROVE: Code a method for this: + voice[voice_index].update_info_from_master_channel(); + } + + control.channel[i].kick=KICK_NOTHING; + } +} +void CPPlayer::Voice_Control::reset() { + + cp_memzero(this,sizeof(*this)); + + instrument_ptr=NULL; + sample_ptr=NULL; + has_master_channel=false; + instrument_index=-1; + reverb_send=0; + chorus_send=0; + filter.it_cutoff=255; + filter.it_reso=0; + display_volume=0; + + +} + +void CPPlayer::Channel_Control::reset() { + + int prev_gv =channel_global_volume; + cp_memzero(this,sizeof(*this)); + + slave_voice=NULL; + slave_voice_index=255; + + mute=false; + old_note=255; + real_note=255; + instrument_index=255; + filter.it_cutoff=255; + filter.it_reso=0; + reverb_send=0; + chorus_send=0; + reserved=false; + carry.maybe=false; + last_event_usecs=-1; + channel_global_volume=prev_gv; +} + +void CPPlayer::Voice_Control::update_info_from_master_channel() { + + instrument_ptr=master_channel->instrument_ptr; + sample_ptr=master_channel->sample_ptr; + + instrument_index=master_channel->instrument_index; + sample_index=master_channel->sample_index; + + note=master_channel->note; + output_volume=master_channel->output_volume; + + channel_volume=master_channel->channel_volume; + + panning=master_channel->panning; + + kick=master_channel->kick; + note_end_flags=master_channel->note_end_flags; + period=master_channel->period; + + volume_envelope_ctrl.active=master_channel->volume_envelope_on; + panning_envelope_ctrl.active=master_channel->panning_envelope_on; + pitch_envelope_ctrl.active=master_channel->pitch_envelope_on; + + + NNA_type=master_channel->NNA_type; + reverb_send=master_channel->reverb_send; + chorus_send=master_channel->chorus_send; + +// last_note_type=master_channel->last_note_type; + + sample_start_index=master_channel->sample_start_index; + filter=master_channel->filter; + +} + + +void CPPlayer::update_mixer() { + + int tmp_mixer_period; + int32_t tmp_vibrato_value,tmp_vibrato_depth,tmp_volenv_value; + uint64_t tmpvol; // 64bits should be the only way to avoid getting notes raped out + int i; + + + control.voices_used=0; + + for (i=0;i50000) { + + v.period=50000; + } + + + if ((v.kick==KICK_NOTE)||(v.kick==KICK_NOTEOFF)) { + + int real_start_index; + + if (v.sample_start_index==-1) { + + real_start_index=0; + + } else { + + real_start_index=v.sample_start_index; + } + + mixer->setup_voice(i,v.sample_ptr->get_sample_data(),real_start_index); + v.fadeout_volume=1024; //IT Docs it is 1024 internally + v.auto_vibrato_sweep_pos=0; + + + + } + + + /* Start Envelopes */ + if ( song->has_instruments() && ((v.kick==KICK_NOTE)||(v.kick==KICK_ENVELOPE))) { + +// Voice_Control *carry=0; + + + if (v.has_master_channel && v.master_channel->carry.maybe) { + + v.start_envelope(v.instrument_ptr->get_volume_envelope(),&v.volume_envelope_ctrl,&v.master_channel->carry.vol); + v.start_envelope(v.instrument_ptr->get_pan_envelope(),&v.panning_envelope_ctrl,&v.master_channel->carry.pan); + v.start_envelope(v.instrument_ptr->get_pitch_filter_envelope(),&v.pitch_envelope_ctrl,&v.master_channel->carry.pitch); + + } else { + + v.start_envelope(v.instrument_ptr->get_volume_envelope(),&v.volume_envelope_ctrl,NULL); + v.start_envelope(v.instrument_ptr->get_pan_envelope(),&v.panning_envelope_ctrl,NULL); + v.start_envelope(v.instrument_ptr->get_pitch_filter_envelope(),&v.pitch_envelope_ctrl,NULL); + + } + + + } + + v.kick=KICK_NOTHING; + + if (song->has_instruments()) { + + if (!v.process_envelope(v.instrument_ptr->get_volume_envelope(),&v.volume_envelope_ctrl)) + v.volume_envelope_ctrl.value=64; + + if (!v.process_envelope(v.instrument_ptr->get_pan_envelope(),&v.panning_envelope_ctrl)) + v.panning_envelope_ctrl.value=0; + + if (!v.process_envelope(v.instrument_ptr->get_pitch_filter_envelope(),&v.pitch_envelope_ctrl)) + v.pitch_envelope_ctrl.value=0; + + + if (v.volume_envelope_ctrl.terminated) { + + if (v.volume_envelope_ctrl.kill) { + + v.fadeout_volume=0; + } else { + + v.note_end_flags|=END_NOTE_FADE; + } + } + + } + + if (song->has_instruments()) { + + tmp_volenv_value=v.volume_envelope_ctrl.value; + } else { + + tmp_volenv_value=64; + + } + + /*printf("fadeout %i\n",(int)v.fadeout_volume); + printf("channel %i\n",(int)v.channel_volume); + printf("output %i\n",(int)v.output_volume); + printf("env %i\n",(int)tmp_volenv_value); + printf("cgb %i\n",(int)v.master_channel->channel_global_volume); +*/ + + + tmpvol=(uint64_t)v.fadeout_volume; /* max 1024 - 10 bits */ + tmpvol*=(uint64_t)v.channel_volume; /* * max 64 - 6 bits */ + tmpvol*=(uint64_t)v.output_volume; /* * max 256 - 8 bits */ + tmpvol*=(uint64_t)tmp_volenv_value; /* max 64 - 6 bits*/ + tmpvol*=(uint64_t)v.master_channel->channel_global_volume; + v.display_volume=tmpvol>>22; //volume used for display purposes , 0 -- 256 + + tmpvol*=(uint64_t)song->get_mixing_volume(); /* max 128 - 7 bits */ + tmpvol*=(uint64_t)control.global_volume; /* max 128 - 7 bits*/ + /* total 10+6+8+6+7+7=44 bits */ + + tmpvol>>=43; /* Move back to 8 bits range , 44-19+8=43*/ + + if (tmpvol>CP_VOL_MAX) + tmpvol=CP_VOL_MAX; + + //printf("volume check - fade %i, channel %i, output %i, env %i, mix %i, global %i -- final %i\n",v.fadeout_volume, v.channel_volume,v.output_volume,tmp_volenv_value, song->get_mixing_volume(),control.global_volume,tmpvol); + + v.total_volume=tmpvol; + + + if ((v.master_channel!=NULL) && song->is_channel_mute( v.master_channel_index ) && !v.master_channel->reserved) { + + mixer->set_voice_volume(i,0); + } else { + mixer->set_voice_volume(i,tmpvol); + if (v.fadeout_volume>0) control.voices_used++; + } + + + if (!song->is_stereo()) { + + mixer->set_voice_panning(i,PAN_CENTER); + + } else if (v.panning==PAN_SURROUND) { + + mixer->set_voice_panning(i,PAN_SURROUND); + } else if (song->has_instruments()) { + + int newpan,real_modifier; + + + real_modifier=(v.panning_envelope_ctrl.value*(PAN_CENTER-cp_intabs(v.panning-PAN_CENTER)))/32; + + newpan=v.panning+real_modifier; + + newpan=(newpanPAN_RIGHT)?PAN_RIGHT:newpan; + //printf("panenv val: %i, finalpan val %i\n",v.panning_envelope_ctrl.value,newpan); + + mixer->set_voice_panning(i,newpan); + } else { + mixer->set_voice_panning(i,v.panning); + } + + + + /* VIBRATO */ + + if ( (v.period>0) && (v.sample_ptr->get_vibrato_depth()>0) ) { + + switch (v.sample_ptr->get_vibrato_type()) { + case CPSample::VIBRATO_SINE: + tmp_vibrato_value=auto_vibrato_table[v.auto_vibrato_pos&127]; + if (v.auto_vibrato_pos & 0x80) tmp_vibrato_value=-tmp_vibrato_value; + break; + case CPSample::VIBRATO_SQUARE: + tmp_vibrato_value=64; + if (v.auto_vibrato_pos & 0x80) tmp_vibrato_value=-tmp_vibrato_value; + break; + case CPSample::VIBRATO_SAW: + tmp_vibrato_value=63-(((v.auto_vibrato_pos+128)&255)>>1); + break; + default: + tmp_vibrato_value=(((v.auto_vibrato_pos+128)&255)>>1)-64; + break; + } + } else { + + tmp_vibrato_value=0; + } + + if ((v.auto_vibrato_sweep_pos>>8)get_vibrato_depth()) { + + v.auto_vibrato_sweep_pos+=v.sample_ptr->get_vibrato_speed(); //FIXME - speed? i think so + tmp_vibrato_depth=v.auto_vibrato_sweep_pos; + + } else { + + tmp_vibrato_depth=v.sample_ptr->get_vibrato_depth()<<8; + } + + tmp_vibrato_value=(tmp_vibrato_value*tmp_vibrato_depth)>>16; + if (song->has_linear_slides()) + tmp_vibrato_value>>=1; + v.period-=tmp_vibrato_value; + + + /* update vibrato position */ + v.auto_vibrato_pos=(v.auto_vibrato_pos+v.sample_ptr->get_vibrato_rate())&0xff; + + + /* process pitch envelope */ + tmp_mixer_period=v.period; + + if (v.pitch_envelope_ctrl.active) { + + long aux_pitch_diff; + int pe_value=v.pitch_envelope_ctrl.value; + + if (!v.instrument_ptr->is_pitch_use_as_filter()) { + + + if (((uint16_t)v.note<<1)+pe_value<=0) + pe_value=-(v.note<<1); + + int smp_c5=CPSampleManager::get_singleton()->get_c5_freq( v.sample_ptr->get_sample_data()); + + int base=get_period(((uint16_t)v.note<<1),smp_c5); + int env=get_period(((uint16_t)v.note<<1)+pe_value,smp_c5); + /* + int env_next=(pe_value<0)?get_period(((uint16_t)(v.note-1)<<1)+pe_value,smp_c5):get_period(((uint16_t)(v.note+1)<<1)+pe_value,smp_c5); + + env=env+(abs(v.pitch_envelope_ctrl.value)&((1<stop_voice(i); + + } else { + + + int32_t freq=get_frequency(tmp_mixer_period); + int32_t tracker_c5=get_frequency(get_period(60<<1,CPSampleManager::get_singleton()->get_c5_freq( v.sample_ptr->get_sample_data()))); + + freq=(int32_t)((uint64_t)freq*(uint64_t)C5FREQ_MIXER/(uint64_t)tracker_c5); //numbers may become very high + mixer->set_voice_frequency(i,freq); + + /* if keyfade, start substracting fadeoutspeed from fadevol: */ + if ((song->has_instruments())&&(v.note_end_flags & END_NOTE_FADE)) { + + if (v.fadeout_volume>=(v.instrument_ptr->get_volume_fadeout())) { + + v.fadeout_volume-=(v.instrument_ptr->get_volume_fadeout()); + } else { + + v.fadeout_volume=0; + } + } + + /*FILTARSSSSSSSS*/ + + + + v.filter.envelope_cutoff=filter_env; + v.filter.process(); + + if ((v.filter.final_cutoff<0xFF) && (control.filters)) { + + //int final_cutoff; + //uint8_t final_reso; + + //v.filter.set_filter_parameters( &final_cutoff, &final_reso ); + + mixer->set_voice_filter(i,true,v.filter.final_cutoff,v.filter.it_reso); + } else { + + + mixer->set_voice_filter(i,false,0,0); + } + + /* RAIVERV */ + + mixer->set_voice_reverb_send(i,v.reverb_send); + + /* CHAURUZ */ + + mixer->set_voice_chorus_send(i,v.chorus_send); + + } + } + + + switch(song->get_reverb_mode()) { + + case CPSong::REVERB_MODE_ROOM: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_ROOM ); + } break; + case CPSong::REVERB_MODE_STUDIO_SMALL: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_STUDIO_SMALL ); + + } break; + case CPSong::REVERB_MODE_STUDIO_MEDIUM: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_STUDIO_MEDIUM ); + + } break; + case CPSong::REVERB_MODE_STUDIO_LARGE: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_STUDIO_LARGE ); + + } break; + case CPSong::REVERB_MODE_HALL: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_HALL ); + + } break; + case CPSong::REVERB_MODE_SPACE_ECHO: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_SPACE_ECHO ); + + } break; + case CPSong::REVERB_MODE_ECHO: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_ECHO ); + + } break; + case CPSong::REVERB_MODE_DELAY: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_DELAY ); + + } break; + case CPSong::REVERB_MODE_HALF_ECHO: { + + mixer->set_reverb_mode( CPMixer::REVERB_MODE_HALF_ECHO ); + + } break; + + } + + mixer->set_chorus_params(song->get_chorus_delay_ms(),song->get_chorus_separation_ms(),song->get_chorus_depth_ms10(),song->get_chorus_speed_hz10() ); + + +} + + + + + + + + +void CPPlayer::handle_tick() { + + int i; + + + if ( mixer==NULL ) return; + if ( song==NULL ) return; + + + /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */ + + if (control.ticks_counter>=control.speed) { // time to process... ***THE ROW***! + + /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is + the command memory. */ + +// if (control.pattern_delay_1) { + +// control.pattern_delay_2=control.pattern_delay_1; +// control.pattern_delay_1=0; +// } +// if (control.pattern_delay_2) { +// patterndelay active +// if (--control.pattern_delay_2) +// so turn back pf->patpos by 1 +// if (pf->patpos) pf->patpos--; +// } + + if (control.play_mode!=PLAY_NOTHING) { + + control.ticks_counter=0; + + + if (control.position.force_next_order>=0) { + + control.position.current_order=control.position.force_next_order; + } + + control.position.force_next_order=-1; + + control.previous_position=control.position; // for those special cases... + control.position.forbid_jump=false; + + for (i=0;iget_pattern(control.position.current_pattern)->get_note(i,control.position.current_row)); + } + + control.position.current_row++; + + if ( control.position.current_row>=song->get_pattern(control.position.current_pattern)->get_length() ) { + + if (control.play_mode==PLAY_SONG) { + + int next_order; + + next_order=get_song_next_order_idx(song,control.position.current_order); + + if (next_order!=-1) { + // Do we have a "next order?" + control.position.current_pattern=song->get_order(next_order); + if (next_order<=control.position.current_order) + control.reached_end=true; + control.position.current_order=next_order; + + } else { + // no, probably the user deleted the orderlist. + control.play_mode=PLAY_NOTHING; + reset(); + control.reached_end=true; + } + } + control.position.current_row=0; + } + + } + + + } + + + + pre_process_effects(); + process_NNAs(); + setup_voices(); + + /* now set up the actual hardware channel playback information */ + update_mixer(); + + control.ticks_counter++; +} diff --git a/modules/chibi/cp_player_data_filter.cpp b/modules/chibi/cp_player_data_filter.cpp new file mode 100644 index 0000000000..30db807eed --- /dev/null +++ b/modules/chibi/cp_player_data_filter.cpp @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* cp_player_data_filter.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + + +#include "cp_player_data.h" + +static float filter_cutoff[256] = { + 130, 132, 134, 136, 138, 140, 142, 144, + 146, 148, 151, 153, 155, 157, 160, 162, + 164, 167, 169, 172, 174, 177, 179, 182, + 184, 187, 190, 193, 195, 198, 201, 204, + 207, 210, 213, 216, 220, 223, 226, 229, + 233, 236, 239, 243, 246, 250, 254, 257, + 261, 265, 269, 273, 277, 281, 285, 289, + 293, 297, 302, 306, 311, 315, 320, 324, + 329, 334, 339, 344, 349, 354, 359, 364, + 369, 375, 380, 386, 391, 397, 403, 409, + 415, 421, 427, 433, 440, 446, 452, 459, + 466, 472, 479, 486, 493, 501, 508, 515, + 523, 530, 538, 546, 554, 562, 570, 578, + 587, 595, 604, 613, 622, 631, 640, 649, + 659, 668, 678, 688, 698, 708, 718, 729, + 739, 750, 761, 772, 783, 795, 806, 818, + 830, 842, 854, 867, 880, 892, 905, 918, + 932, 945, 959, 973, 987, 1002, 1016, 1031, + 1046, 1061, 1077, 1092, 1108, 1124, 1141, 1157, + 1174, 1191, 1209, 1226, 1244, 1262, 1280, 1299, + 1318, 1337, 1357, 1376, 1396, 1417, 1437, 1458, + 1479, 1501, 1523, 1545, 1567, 1590, 1613, 1637, + 1661, 1685, 1709, 1734, 1760, 1785, 1811, 1837, + 1864, 1891, 1919, 1947, 1975, 2004, 2033, 2062, + 2093, 2123, 2154, 2185, 2217, 2249, 2282, 2315, + 2349, 2383, 2418, 2453, 2489, 2525, 2561, 2599, + 2637, 2675, 2714, 2753, 2793, 2834, 2875, 2917, + 2959, 3003, 3046, 3091, 3135, 3181, 3227, 3274, + 3322, 3370, 3419, 3469, 3520, 3571, 3623, 3675, + 3729, 3783, 3838, 3894, 3951, 4008, 4066, 4125, + 4186, 4246, 4308, 4371, 4434, 4499, 4564, 4631, + 4698, 4766, 4836, 4906, 4978, 5050, 5123, 5198 +}; + + +void CPPlayer::Filter_Control::process() { + + + final_cutoff=it_cutoff; + if (envelope_cutoff>=0) { + + envelope_cutoff=envelope_cutoff*255/64; + final_cutoff=final_cutoff*envelope_cutoff/255; + if (final_cutoff>=0xFF) final_cutoff=0xFE; + + } + +} + +void CPPlayer::Filter_Control::set_filter_parameters(int *p_cutoff,uint8_t *p_reso) { + + + + *p_cutoff=filter_cutoff[final_cutoff]; + *p_reso=it_reso; +} diff --git a/modules/chibi/cp_player_data_nna.cpp b/modules/chibi/cp_player_data_nna.cpp new file mode 100644 index 0000000000..844f043694 --- /dev/null +++ b/modules/chibi/cp_player_data_nna.cpp @@ -0,0 +1,144 @@ +/*************************************************************************/ +/* cp_player_data_nna.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" + +void CPPlayer::process_NNAs() { + + int i; + + if (!song->has_instruments()) return; + + for (i=0;ikick==KICK_NOTE) { + + bool k=false; + + if (aux_chn_ctrl->slave_voice!=NULL) { + + Voice_Control *aux_voc_ctrl; + + aux_voc_ctrl=aux_chn_ctrl->slave_voice; + + if (aux_chn_ctrl->instrument_index==aux_chn_ctrl->slave_voice->instrument_index) { //maybe carry + + aux_chn_ctrl->carry.pan=aux_chn_ctrl->slave_voice->panning_envelope_ctrl; + aux_chn_ctrl->carry.vol=aux_chn_ctrl->slave_voice->volume_envelope_ctrl; + aux_chn_ctrl->carry.pitch=aux_chn_ctrl->slave_voice->pitch_envelope_ctrl; + aux_chn_ctrl->carry.maybe=true; + } else + aux_chn_ctrl->carry.maybe=false; + + if (aux_voc_ctrl->NNA_type != CPInstrument::NNA_NOTE_CUT) { + /* Make sure the old MP_VOICE channel knows it has no + master now ! */ + + + + aux_chn_ctrl->slave_voice=NULL; + /* assume the channel is taken by NNA */ + aux_voc_ctrl->has_master_channel=false; + + switch (aux_voc_ctrl->NNA_type) { + case CPInstrument::NNA_NOTE_CONTINUE: { + + } break; + case CPInstrument::NNA_NOTE_OFF: { + + + aux_voc_ctrl->note_end_flags|=END_NOTE_OFF; + + if (!aux_voc_ctrl->volume_envelope_ctrl.active || aux_voc_ctrl->instrument_ptr->get_volume_envelope()->is_loop_enabled()) { + aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; + } + } break; + case CPInstrument::NNA_NOTE_FADE: { + + aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; + } break; + } + } + } + + if (aux_chn_ctrl->duplicate_check_type!=CPInstrument::DCT_DISABLED) { + int i; + + for (i=0;iis_voice_active(i)|| + (voice[i].master_channel!=aux_chn_ctrl) || + (aux_chn_ctrl->instrument_index!=voice[i].instrument_index)) + continue; + + Voice_Control *aux_voc_ctrl; + + aux_voc_ctrl=&voice[i]; + + k=false; + switch (aux_chn_ctrl->duplicate_check_type) { + case CPInstrument::DCT_NOTE: + if (aux_chn_ctrl->note==aux_voc_ctrl->note) + k=true; + break; + case CPInstrument::DCT_SAMPLE: + if (aux_chn_ctrl->sample_ptr==aux_voc_ctrl->sample_ptr) + k=true; + break; + case CPInstrument::DCT_INSTRUMENT: + k=true; + break; + } + if (k) { + switch (aux_chn_ctrl->duplicate_check_action) { + case CPInstrument::DCA_NOTE_CUT: { + aux_voc_ctrl->fadeout_volume=0; + } break; + case CPInstrument::DCA_NOTE_OFF: { + + aux_voc_ctrl->note_end_flags|=END_NOTE_OFF; + + if (!aux_voc_ctrl->volume_envelope_ctrl.active || aux_chn_ctrl->instrument_ptr->get_volume_envelope()->is_loop_enabled()) { + + aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; + } + + } break; + case CPInstrument::DCA_NOTE_FADE: { + aux_voc_ctrl->note_end_flags|=END_NOTE_FADE; + } break; + } + } + } + + } + } /* if (aux_chn_ctrl->kick==KICK_NOTE) */ + } +} diff --git a/modules/chibi/cp_player_data_notes.cpp b/modules/chibi/cp_player_data_notes.cpp new file mode 100644 index 0000000000..621be019e1 --- /dev/null +++ b/modules/chibi/cp_player_data_notes.cpp @@ -0,0 +1,345 @@ +/*************************************************************************/ +/* cp_player_data_notes.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" +#include "cp_sample_manager.h" + +#define RANDOM_MAX 2147483647 + +static inline int32_t cp_random_generate(int32_t *seed) { + int32_t k; + int32_t s = (int32_t)(*seed); + if (s == 0) + s = 0x12345987; + k = s / 127773; + s = 16807 * (s - k * 127773) - 2836 * k; + if (s < 0) + s += 2147483647; + (*seed) = (int32_t)s; + return (int32_t)(s & RANDOM_MAX); +} + + +void CPPlayer::process_new_note(int p_track,uint8_t p_note) { // if there's really a new note.... + + if (control.channel[p_track].real_note!=255) { + control.channel[p_track].old_note=control.channel[p_track].real_note; + + } + + control.channel[p_track].real_note=p_note; + + control.channel[p_track].kick=KICK_NOTE; + + control.channel[p_track].sample_start_index=-1; + control.channel[p_track].sliding=0; + control.channel[p_track].row_has_note=true; + control.channel[p_track].last_event_usecs=song_usecs; + + if (control.channel[p_track].panbrello_type) control.channel[p_track].panbrello_position=0; +} + +bool CPPlayer::process_new_instrument(int p_track,uint8_t p_instrument) { + +// bool different_instrument=false; + ERR_FAIL_INDEX_V(p_instrument,CPSong::MAX_INSTRUMENTS,false); + + if ( song->has_instruments() ) { + + + control.channel[p_track].instrument_ptr=song->get_instrument(p_instrument); + } else { + + control.channel[p_track].instrument_ptr=NULL; + } + + control.channel[p_track].retrig_counter=0; + control.channel[p_track].tremor_position=0; + control.channel[p_track].sample_offset_fine=0; + int old_instr_index=control.channel[p_track].instrument_index; + control.channel[p_track].instrument_index=p_instrument; + + return (old_instr_index!=p_instrument); + + +} + + + // returns if it was able to process +bool CPPlayer::process_note_and_instrument(int p_track,int p_note,int p_instrument) { + + bool aux_result; + aux_result=false; + CPSample *aux_sample=0; // current sample + int dest_sample_index; + bool new_instrument=false; + + control.channel[p_track].row_has_note=false; // wise man says.. "we dont have a note... until we really know we have a note". + control.channel[p_track].new_instrument=false; + + if ( (p_note<0) && (p_instrument<0) ) return aux_result; // nothing to do here + if ( (p_note==255) && (p_instrument==255) ) return aux_result; + + if ( (p_note>=0) && (p_note<120) ) { + + process_new_note(p_track,p_note); + + } else if (p_note==CPNote::CUT) { + + control.channel[p_track].aux_volume=0; + control.channel[p_track].note_end_flags|=END_NOTE_OFF; + control.channel[p_track].note_end_flags|=END_NOTE_KILL; + return aux_result; + + } else if ((p_note==CPNote::OFF) && (song->has_instruments())) { + + if (control.channel[p_track].instrument_ptr!=NULL) { + + control.channel[p_track].note_end_flags|=END_NOTE_OFF; + + if (!control.channel[p_track].instrument_ptr->get_volume_envelope()->is_enabled() || control.channel[p_track].instrument_ptr->get_volume_envelope()->is_loop_enabled()) { + + control.channel[p_track].note_end_flags|=END_NOTE_FADE; + } + } + + return aux_result; + } else return aux_result; // invalid note! + + + if ( (p_instrument>=0) && (p_instrumenthas_instruments() ) { + // If we're in instrument mode... + if ( control.channel[p_track].instrument_ptr->get_sample_number(control.channel[p_track].real_note) >= CPSong::MAX_SAMPLES) { + + control.channel[p_track].kick=KICK_NOTHING; + return aux_result; + + } else { + dest_sample_index=control.channel[p_track].instrument_ptr->get_sample_number(control.channel[p_track].real_note); + control.channel[p_track].note=control.channel[p_track].instrument_ptr->get_note_number(control.channel[p_track].real_note); + } + + } else { + // If we're in sample mode... + dest_sample_index=control.channel[p_track].instrument_index; + control.channel[p_track].note=control.channel[p_track].real_note; + } + + control.channel[p_track].sample_index=dest_sample_index; + aux_sample=song->get_sample(dest_sample_index); + + if (!CPSampleManager::get_singleton()->check( aux_sample->get_sample_data() )) { + /* INVALID SAMPLE */ + control.channel[p_track].kick=KICK_NOTHING; + return aux_result; + + } + + aux_sample=song->get_sample(dest_sample_index); + } else { + + + if (!control.channel[p_track].sample_ptr) + return aux_result; + + if (song->has_instruments()) { + + if (!control.channel[p_track].instrument_ptr) + return aux_result; + + control.channel[p_track].note=control.channel[p_track].instrument_ptr->get_note_number(control.channel[p_track].real_note); + + } else { + + control.channel[p_track].note=control.channel[p_track].real_note; + + } + + aux_sample=control.channel[p_track].sample_ptr; + + } + + + + if (p_instrument>=CPSong::MAX_INSTRUMENTS && control.channel[p_track].sample_ptr!=aux_sample) { + + control.channel[p_track].new_instrument=(control.channel[p_track].period>0); + } + + control.channel[p_track].sample_ptr=aux_sample; + + /* channel or instrument determined panning ? */ + + control.channel[p_track].panning=control.channel[p_track].channel_panning; + + /* set filter,if any ? */ + + + if (aux_sample->is_pan_enabled()) { + + control.channel[p_track].panning=(int)aux_sample->get_pan()*255/64; + + } else if ( song->has_instruments() && (control.channel[p_track].instrument_ptr->is_pan_default_enabled()) ) { + + control.channel[p_track].panning=(int)control.channel[p_track].instrument_ptr->get_pan_default_amount()*255/64; + } + + + if (song->has_instruments()) { + + + /* Pitch-Pan Separation */ + if ((control.channel[p_track].instrument_ptr->get_pan_pitch_separation()!=0) && (control.channel[p_track].channel_panning!=PAN_SURROUND)){ + + control.channel[p_track].panning+=((control.channel[p_track].real_note-control.channel[p_track].instrument_ptr->get_pan_pitch_center())*control.channel[p_track].instrument_ptr->get_pan_pitch_separation())/8; + + if (control.channel[p_track].panningPAN_RIGHT) control.channel[p_track].panning=PAN_RIGHT; + } + + /* Random Volume Variation */ + if (control.channel[p_track].instrument_ptr->get_volume_random_variation()>0) { + + control.channel[p_track].random_volume_variation=100-(cp_random_generate(&control.random_seed) % control.channel[p_track].instrument_ptr->get_volume_random_variation()); + + } else { + + control.channel[p_track].random_volume_variation=100; + } + + + /* Random Pan Variation */ + if ((control.channel[p_track].instrument_ptr->get_pan_random_variation()>0) && (control.channel[p_track].panning!=PAN_SURROUND)){ + + int aux_pan_modifier; + + aux_pan_modifier=(cp_random_generate(&control.random_seed) % (control.channel[p_track].instrument_ptr->get_pan_random_variation() << 2)); + if ((cp_random_generate(&control.random_seed) % 2)==1) aux_pan_modifier=0-aux_pan_modifier; /* it's 5am, let me sleep :) */ + + control.channel[p_track].panning+=aux_pan_modifier; + + if (control.channel[p_track].panningPAN_RIGHT) control.channel[p_track].panning=PAN_RIGHT; + + + } + + /*filter*/ + + if (control.channel[p_track].instrument_ptr->filter_use_default_cutoff()) { + + control.channel[p_track].filter.it_cutoff=control.channel[p_track].instrument_ptr->get_filter_default_cutoff()*2; + + } + + if (control.channel[p_track].instrument_ptr->filter_use_default_resonance()) { + + control.channel[p_track].filter.it_reso=control.channel[p_track].instrument_ptr->get_filter_default_resonance()*2; + + } + + /*envelopes*/ + + + control.channel[p_track].volume_envelope_on=control.channel[p_track].instrument_ptr->get_volume_envelope()->is_enabled(); + control.channel[p_track].panning_envelope_on=control.channel[p_track].instrument_ptr->get_pan_envelope()->is_enabled(); + control.channel[p_track].pitch_envelope_on=control.channel[p_track].instrument_ptr->get_pitch_filter_envelope()->is_enabled(); + control.channel[p_track].NNA_type=control.channel[p_track].instrument_ptr->get_NNA_type(); + control.channel[p_track].duplicate_check_type=control.channel[p_track].instrument_ptr->get_DC_type(); + control.channel[p_track].duplicate_check_action=control.channel[p_track].instrument_ptr->get_DC_action(); + + + } else { + + control.channel[p_track].NNA_type=CPInstrument::NNA_NOTE_CUT; + control.channel[p_track].duplicate_check_type=CPInstrument::DCT_DISABLED; + control.channel[p_track].duplicate_check_action=CPInstrument::DCA_NOTE_CUT; + } + + + if (p_instrumentget_default_volume(); + + } + + + control.channel[p_track].slide_to_period=control.channel[p_track].aux_period=get_period((uint16_t)(control.channel[p_track].note)<<1,CPSampleManager::get_singleton()->get_c5_freq( (aux_sample->get_sample_data()))); + + control.channel[p_track].note_end_flags=END_NOTE_NOTHING; /* clears flags */ + + return true; +} + +void CPPlayer::process_volume_column(int p_track,uint8_t p_volume) { + + control.channel[p_track].current_volume_command=CPNote::EMPTY; + control.channel[p_track].current_volume_parameter=CPNote::EMPTY; + + if (p_volume<65) { // VOLUME + + control.channel[p_track].aux_volume=p_volume; + } else if (p_volume<125) { // Volume Command + + + control.channel[p_track].current_volume_command=(p_volume-65) / 10; + control.channel[p_track].current_volume_parameter=(p_volume-65) % 10; + } else if (p_volume<193) { // PAN + + control.channel[p_track].channel_panning=(p_volume-128)*PAN_RIGHT/64; + control.channel[p_track].panning=control.channel[p_track].channel_panning; + + } else if (p_volume<213) { //More volume Commands + + control.channel[p_track].current_volume_command=((p_volume-193) / 10)+6; + control.channel[p_track].current_volume_parameter=(p_volume-193) % 10; + } +} + + +void CPPlayer::process_note(int p_track,CPNote p_note) { + + if ( p_note.note!=CPNote::SCRIPT ) { + + process_note_and_instrument(p_track,p_note.note,p_note.instrument); + process_volume_column(p_track,p_note.volume); + control.channel[p_track].current_command=p_note.command; + control.channel[p_track].current_parameter=p_note.parameter; + + } else { + + CPNote n = song->get_pattern( control.position.current_pattern )->get_transformed_script_note( p_track, control.position.current_row ); + process_note( p_track, n ); + + song->get_pattern( control.position.current_pattern )->scripted_clone( p_track, control.position.current_row ); + } +} diff --git a/modules/chibi/cp_player_data_utils.cpp b/modules/chibi/cp_player_data_utils.cpp new file mode 100644 index 0000000000..170a849863 --- /dev/null +++ b/modules/chibi/cp_player_data_utils.cpp @@ -0,0 +1,138 @@ +/*************************************************************************/ +/* cp_player_data_utils.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "cp_player_data.h" +uint8_t CPPlayer::vibrato_table[32]={ + 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253, + 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24 +}; + +uint8_t CPPlayer::auto_vibrato_table[128]={ + 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23, + 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, + 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, + 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63, + 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59, + 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46, + 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25, + 24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1 +}; + + +int8_t CPPlayer::panbrello_table[256]={ + 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, + 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, + 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, + 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, + 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26, + 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2, + 0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23, + -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44, + -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59, + -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64, + -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60, + -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46, + -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26, + -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2 +}; + + + + + + +int32_t CPPlayer::get_period(uint16_t p_note,int32_t p_c5speed) { + + if (song->has_linear_slides()) { + + return CPTables::get_linear_period(p_note,0); + } else { + + + return CPTables::get_log_period(p_note>>1,p_c5speed >>1); + } +} + + +int32_t CPPlayer::get_frequency(int32_t period) { + + if (song->has_linear_slides()) { + + return CPTables::get_linear_frequency(period); + } else { + + return CPTables::get_old_frequency(period); + } +} + +int CPPlayer::find_empty_voice() { + + int i; + int min_priority,min_priority_chan=0,priority; + + for (i=0;iis_voice_active(i) ) { + + return i; + + } + } + + // todo more + + for (i=0;iget_loop_type( voice[i].sample_ptr->get_sample_data())!=CP_LOOP_NONE)?1:0); + + if ((voice[i].has_master_channel)&&(&voice[i]==voice[i].master_channel->slave_voice)) { + + priority<<=2; + + } + + if ((i==0) || (priority8000*7) return -1; /* what the fuck is this? */ + + return min_priority_chan; +} + diff --git a/modules/chibi/cp_sample.cpp b/modules/chibi/cp_sample.cpp new file mode 100644 index 0000000000..55c2c910a5 --- /dev/null +++ b/modules/chibi/cp_sample.cpp @@ -0,0 +1,203 @@ +/*************************************************************************/ +/* cp_sample.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "cp_sample.h" + +const char * CPSample::get_name() const { + + return name; +} +void CPSample::set_name(const char *p_name) { + + if (p_name==NULL) { + name[0]=0; + return; + } + + + bool done=false; + for (int i=0;icopy_to( p_sample.id, id ); +} + + + + + +void CPSample::reset() { + + + name[0]=0; + + default_volume=64; + global_volume=64; + + pan_enabled=false; + pan=32; + + vibrato_type=VIBRATO_SINE; + vibrato_speed=0; + vibrato_depth=0; + vibrato_rate=0; + + if (!id.is_null() && CPSampleManager::get_singleton()) + CPSampleManager::get_singleton()->destroy( id ); + + id=CPSample_ID(); + +} + +CPSample::CPSample(const CPSample&p_from) { + + reset(); + copy_from(p_from); +} +CPSample::CPSample() { + + reset(); +} + +CPSample::~CPSample() { + + reset(); +} diff --git a/modules/chibi/cp_sample.h b/modules/chibi/cp_sample.h new file mode 100644 index 0000000000..4b3d218106 --- /dev/null +++ b/modules/chibi/cp_sample.h @@ -0,0 +1,112 @@ +/*************************************************************************/ +/* cp_sample.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 CPSAMPLE_H +#define CPSAMPLE_H + + +#include "cp_config.h" +#include "cp_sample_manager.h" +class CPSample { + +public: + enum VibratoType { + VIBRATO_SINE, + VIBRATO_SAW, + VIBRATO_SQUARE, + VIBRATO_RANDOM + + }; + +private: + + enum { NAME_MAX_LEN=26 }; + + char name[NAME_MAX_LEN]; + + uint8_t default_volume; /* 0.. 64 */ + uint8_t global_volume; /* 0.. 64 */ + + bool pan_enabled; + uint8_t pan; /* 0.. 64 */ + + VibratoType vibrato_type; + uint8_t vibrato_speed; /* 0.. 64 */ + uint8_t vibrato_depth; /* 0.. 64 */ + uint8_t vibrato_rate; /* 0.. 64 */ + + CPSample_ID id; + + void copy_from(const CPSample &p_sample); +public: + + + void operator=(const CPSample &p_sample); + + const char * get_name() const; + void set_name(const char *p_name); + + void set_default_volume(uint8_t p_vol); + uint8_t get_default_volume() const; + + void set_global_volume(uint8_t p_vol); + uint8_t get_global_volume() const; + + void set_pan_enabled(bool p_vol); + bool is_pan_enabled() const; + + void set_pan(uint8_t p_pan); + uint8_t get_pan() const; + + void set_vibrato_type(VibratoType p_vibrato_type); + VibratoType get_vibrato_type() const; + + void set_vibrato_speed(uint8_t p_vibrato_speed) ; + uint8_t get_vibrato_speed() const; + + void set_vibrato_depth(uint8_t p_vibrato_depth); + uint8_t get_vibrato_depth() const; + + void set_vibrato_rate(uint8_t p_vibrato_rate); + uint8_t get_vibrato_rate() const; + + void set_sample_data(CPSample_ID); + CPSample_ID get_sample_data() const; + + void reset(); + + CPSample(const CPSample&p_from); + CPSample(); + ~CPSample(); + +}; + + + + +#endif diff --git a/modules/chibi/cp_sample_defs.h b/modules/chibi/cp_sample_defs.h new file mode 100644 index 0000000000..169963c98e --- /dev/null +++ b/modules/chibi/cp_sample_defs.h @@ -0,0 +1,97 @@ +/*************************************************************************/ +/* cp_sample_defs.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_SAMPLE_DEFS_H +#define CP_SAMPLE_DEFS_H + +#include "cp_config.h" + +enum CPSample_Loop_Type { + + CP_LOOP_NONE, + CP_LOOP_FORWARD, + CP_LOOP_BIDI +}; + +//#define INVALID_SAMPLE_ID -1 + +#define CP_MIXING_FRAC_BITS_MACRO 13 +#define CP_MIXING_FRAC_BITS_TEXT "13" +// 1<<9 - 1 +#define CP_MIXING_FRAC_BITS_MASK_TEXT "8191" + +enum CPMixConstants { + CP_MIXING_FRAC_BITS=CP_MIXING_FRAC_BITS_MACRO, + CP_MIXING_FRAC_LENGTH=(1<MAX_SPEED); + + initial_variables.speed=p_speed; + +} /* 1 .. 255 */ +int CPSong::get_speed() { + + return initial_variables.speed; + +} /* 1 .. 255 */ + +void CPSong::set_tempo(int p_tempo) { + + CP_ERR_COND( p_tempoMAX_TEMPO ); + + initial_variables.tempo=p_tempo; + +} /* MIN_TEMPO .. MAX_TEMPO */ +int CPSong::get_tempo() { + + return initial_variables.tempo; + + +} /* MIN_TEMPO .. MAX_TEMPO */ + +void CPSong::set_channel_pan(int p_channel,int p_pan) { + + CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); + CP_FAIL_INDEX(p_pan,CHANNEL_MAX_PAN+1); + + initial_variables.channel[p_channel].pan=p_pan; + +} /* 0 .. CHANNEL_MAX_PAN */ +int CPSong::get_channel_pan(int p_channel) { + + CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); + + return initial_variables.channel[p_channel].pan; +} + +void CPSong::set_channel_volume(int p_channel,int p_volume) { + + CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); + CP_FAIL_INDEX(p_volume,CHANNEL_MAX_VOLUME+1); + + + initial_variables.channel[p_channel].volume=p_volume; + + +} /* 0 .. CHANNEL_MAX_VOLUME */ + + +int CPSong::get_channel_volume(int p_channel) { + + CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); + + return initial_variables.channel[p_channel].volume; + +} + +void CPSong::set_channel_chorus(int p_channel,int p_chorus) { + + CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); + CP_FAIL_INDEX(p_chorus,CHANNEL_MAX_CHORUS+1); + + + initial_variables.channel[p_channel].chorus=p_chorus; + + +} /* 0 .. CHANNEL_MAX_CHORUS */ + + +int CPSong::get_channel_chorus(int p_channel) { + + CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); + + return initial_variables.channel[p_channel].chorus; + +} + +void CPSong::set_channel_reverb(int p_channel,int p_reverb) { + + CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); + CP_FAIL_INDEX(p_reverb,CHANNEL_MAX_REVERB+1); + + + initial_variables.channel[p_channel].reverb=p_reverb; + + +} /* 0 .. CHANNEL_MAX_CHORUS */ + + +int CPSong::get_channel_reverb(int p_channel) { + + CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,-1); + + return initial_variables.channel[p_channel].reverb; + +} + +void CPSong::set_channel_surround(int p_channel,bool p_surround) { + + CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); + initial_variables.channel[p_channel].surround=p_surround; + +} +bool CPSong::is_channel_surround(int p_channel) { + + CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,false); + + return initial_variables.channel[p_channel].surround; + + +} + +void CPSong::set_channel_mute(int p_channel,bool p_mute) { + + CP_FAIL_INDEX(p_channel,CPPattern::WIDTH); + + initial_variables.channel[p_channel].mute=p_mute; + +} +bool CPSong::is_channel_mute(int p_channel) { + + CP_FAIL_INDEX_V(p_channel,CPPattern::WIDTH,false); + + return initial_variables.channel[p_channel].mute; + +} + +/* arrays of stuff */ + +CPPattern* CPSong::get_pattern(int p_pattern) { + + CP_FAIL_INDEX_V(p_pattern,MAX_PATTERNS, NULL); + + return &pattern[p_pattern]; + +} +CPSample* CPSong::get_sample(int p_sample) { + + CP_FAIL_INDEX_V(p_sample,MAX_SAMPLES,NULL); + + return &sample[p_sample]; + + +} +CPInstrument* CPSong::get_instrument(int p_instrument) { + + + CP_FAIL_INDEX_V(p_instrument,MAX_INSTRUMENTS,NULL); + + return &instrument[p_instrument]; + +} + +int CPSong::get_order(int p_order) { + + CP_FAIL_INDEX_V(p_order,MAX_ORDERS,CP_ORDER_NONE); + + + return order[p_order]; + +} +void CPSong::set_order(int p_order,int p_pattern) { + + CP_FAIL_INDEX(p_order,MAX_ORDERS); + + order[p_order]=p_pattern; + +} + + +void CPSong::clear_instrument_with_samples(int p_instrument) { + + CPInstrument *ins = get_instrument( p_instrument ); + if (!ins) + return; + + for (int i=0;iget_sample_number( i ) ); + + if (!s) + continue; + + if (s->get_sample_data().is_null()) + continue; + + s->reset(); + } + ins->reset(); +} + +void CPSong::make_instrument_from_sample(int p_sample) { + + if (!has_instruments()) + return; + CP_ERR_COND(!get_sample( p_sample )); + + for (int i=0;iget_sample_number(n)set_sample_number(n,p_sample); + ins->set_note_number(n,n); + } + + ins->set_name( get_sample( p_sample )->get_name() ); + break; + } + +} + +void CPSong::make_instruments_from_samples() { + + for (int i=0;ireset(); + + CPSample *s=get_sample( i ); + + if (!s) + continue; + + ins->set_name( s->get_name() ); + + if (s->get_sample_data().is_null()) + continue; + + + + + for(int j=0;jset_sample_number( j, i ); + + + + } +} + +void CPSong::reset(bool p_clear_patterns,bool p_clear_samples,bool p_clear_instruments,bool p_clear_variables) { + + if (p_clear_variables) { + variables.name[0]=0; + variables.message[0]=0; + variables.row_highlight_major=16; + variables.row_highlight_minor=4; + variables.mixing_volume=48; + variables.old_effects=false; + if (p_clear_instruments) //should not be cleared, if not clearing instruments!! + variables.use_instruments=false; + variables.stereo_separation=128; + variables.use_linear_slides=true; + variables.use_stereo=true; + + initial_variables.global_volume=128; + initial_variables.speed=6; + initial_variables.tempo=125; + + for (int i=0;ireset(); + } + + if (p_clear_instruments) { + for (int i=0;ireset(); + } + + if (p_clear_patterns) { + for (int i=0;iclear(); + + for (int i=0;iis_empty()) + continue; + + for (int j=0;jclear(); + } + +} +void CPSong::cleanup_unused_instruments(){ + + if (!has_instruments()) + return; + + bool instr_found[MAX_INSTRUMENTS]; + for (int i=0;iis_empty()) + continue; + + for (int row=0;rowget_length();row++) { + + + for (int col=0;colget_note( col,row ); + + if (n.instrumentreset(); + + +} +void CPSong::cleanup_unused_samples(){ + + if (!has_instruments()) + return; + + bool sample_found[MAX_SAMPLES]; + for (int i=0;iis_empty()) + continue; + + + for (int row=0;rowget_length();row++) { + + + for (int col=0;colget_note( col,row ); + + if (n.instrument>=MAX_SAMPLES) + continue; + + if (has_instruments()) { + + for (int nt=0;ntget_sample_number(nt); + if (smpreset(); + +} +void CPSong::cleanup_unused_orders(){ + + bool finito=false; + for (int j=0;jset_pan_default_enabled( false ); //die! + + for (int i=0;iset_pan_enabled( false ); //die! + +} + + +void CPSong::clear_all_default_vol(){ + + for (int i=0;iset_default_volume( 64 ); //die! + for (int i=0;iset_volume_global_amount( CPInstrument::MAX_VOLUME ); + +} + + +int CPSong::get_order_in_use_count() { + + + int order_count = 0; + + for (int i=(MAX_ORDERS-1);i>=0;i--) { + + + if (get_order(i)!=CP_ORDER_NONE) { + order_count=i+1; + break; + } + } + + return order_count; +} +int CPSong::get_pattern_in_use_count() { + + + int pattern_count=0; + + for (int i=(CPSong::MAX_PATTERNS-1);i>=0;i--) { + + + if (!get_pattern(i)->is_empty()) { + pattern_count=i+1; + break; + } + } + + return pattern_count; +} + +int CPSong::get_instrument_in_use_count() { + + int instrument_count=0; + + for (int i=(CPSong::MAX_INSTRUMENTS-1);i>=0;i--) { + + CPInstrument *ins = get_instrument(i); + bool in_use=false; + + for (int s = 0 ; s < CPNote::NOTES ; s++ ) { + + int smp_idx = ins->get_sample_number(s); + if (smp_idx<0 || smp_idx>=CPSong::MAX_SAMPLES) + continue; + + if (!get_sample(smp_idx)->get_sample_data().is_null()) { + in_use=true; + break; + } + + } + + if (in_use) { + instrument_count=i+1; + break; + } + } + + return instrument_count; +} +#include +int CPSong::get_channels_in_use() { + + int max=0; + + for (int p=0;pis_empty()) + continue; + + + for (int c=(CPPattern::WIDTH-1);c>=0;c--) { + + if (cget_length();r++) { + + CPNote n = pat->get_note( c, r ); + if (!n.is_empty()) { + has_note=true; + break; + } + } + + if (has_note) { + + max=c+1; + } + } + } + + return max; +} + + +void CPSong::separate_in_one_sample_instruments(int p_instrument) { + + CP_ERR_COND( !variables.use_instruments ); + CP_FAIL_INDEX( p_instrument, MAX_INSTRUMENTS ); + + int remapped_count=0; + + signed char remap[MAX_SAMPLES]; + + for (int i=0;iget_sample_number(i); + + // check for unusable sample + if (sn<0 || sn>=MAX_SAMPLES || get_sample(sn)->get_sample_data().is_null()) + continue; + printf("sample %i\n",sn); + if ( remap[sn] !=-1 ) { + printf("already mapped to %i\n",remap[sn]); + continue; + } + + printf("isn't remapped\n"); + + // find remap + + for (int j=0;jis_empty()) + continue; + + printf("map to %i\n",j); + + //copy + *get_instrument(j)=*ins; + + // assign samples + for (int k=0;kset_note_number(k,k); + get_instrument(j)->set_sample_number(k,sn); + } + remap[sn]=j; + remapped_count++; + break; + } + + CP_ERR_COND(remap[sn]==-1); // no more free instruments + } + + printf("remapped %i\n",remapped_count); + + if (remapped_count<2) { + //undo if only one is remapped + for (int i=0;ireset(); + } + } + return; + } + + /* remap all song */ + + for (int p=0;pis_empty()) + continue; + + + for (int c=0;cget_length();r++) { + + CPNote n = pat->get_note(c,r); + if (n.noteget_sample_number(n.note); + if (remap[sn]==-1) + pat->set_note(c,r,CPNote()); + else { + + n.instrument=remap[sn]; + pat->set_note(c,r,n); + } + } + } + } + } + + ins->reset(); + +} + + +CPSong::CPSong() { + + reset(); +} +CPSong::~CPSong() { + +} + + + + +int get_song_next_order_idx(CPSong *p_song, int p_order_idx) { + + int baseorder,order_counter; + + order_counter=-1; + + baseorder=p_order_idx; + + do { + + baseorder++; + if ( baseorder>(CPSong::MAX_ORDERS-1) ) baseorder=0; + order_counter++; + + } while ( (p_song->get_order(baseorder)>=(CPSong::MAX_PATTERNS) ) && (order_counter>1); + return t; +} + +static int s3m_period_table[12]={1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907}; + + +int32_t CPTables::get_log_period(uint16_t note,int32_t p_c5freq) { + + return (8363L * 16 * s3m_period_table[note%12] >> (note/12)) / p_c5freq; + +} + +/* +int32_t CPTables::get_log_period(uint16_t note,int32_t p_c5freq) +{ + uint16_t n,o; + uint16_t p1,p2; + int32_t i; + + n=note%(2*OCTAVE); + o=note/(2*OCTAVE); + i=(n<<2); // n*8 + fine/16 + + if (i<0) + i=0; + + if (i>102) + i=102; + + + p1=log_table[i]; + p2=log_table[i+1]; + + + return (Interpolate(fine>>4,0,15,p1,p2)>>o); + +} */ + +int32_t CPTables::get_old_period(uint16_t note,int32_t speed) { + + uint16_t n,o,res; + +// if (!speed) { + + // return 4242; /* <- prevent divide overflow */ + // } + + n=note%(2*OCTAVE); + o=note/(2*OCTAVE); + + res=((8363L*(int32_t)old_period_table[n])>>o)/((old_period_table[17]>>1)+(speed<<2)); /*/(128-speed)*/; + + return res; +} + +int32_t CPTables::get_linear_frequency(int32_t period) { + + int32_t shift_value=(((int32_t)period/768)-2); + if (shift_value>0) { + + return linear_period_to_freq_tab[period%768]>>shift_value; + } else { + shift_value=0-shift_value; + return linear_period_to_freq_tab[period%768]<rid = AudioServer::get_singleton()->sample_create(sf,p_stereo,p_len); + sd->stereo=p_stereo; + sd->len=p_len; + sd->is16=p_16bits; + sd->mixfreq=44100; + sd->loop_begin=0; + sd->loop_end=0; + sd->loop_type=CP_LOOP_NONE; + sd->locks=0; +#ifdef DEBUG_ENABLED + valid.insert(sd); +#endif + CPSample_ID sid; + sid._private=sd; + return sid; +} + +void CPSampleManagerImpl::recreate(CPSample_ID p_id,bool p_16bits,bool p_stereo,int32_t p_len){ + + AudioServer::SampleFormat sf=p_16bits?AudioServer::SAMPLE_FORMAT_PCM16:AudioServer::SAMPLE_FORMAT_PCM8; + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + AudioServer::get_singleton()->free(sd->rid); + sd->rid = AudioServer::get_singleton()->sample_create(sf,p_stereo,p_len); + sd->stereo=p_stereo; + sd->len=p_len; + sd->is16=p_16bits; + sd->mixfreq=44100; + sd->loop_begin=0; + sd->loop_end=0; + sd->loop_type=CP_LOOP_NONE; +} +void CPSampleManagerImpl::destroy(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); + valid.erase(sd); +#endif + AudioServer::get_singleton()->free(sd->rid); + + memdelete(sd); +} +bool CPSampleManagerImpl::check(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + return valid.has(sd); +#else + return _getsd(p_id)!=NULL; +#endif +} + +void CPSampleManagerImpl::set_c5_freq(CPSample_ID p_id,int32_t p_freq){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + sd->mixfreq=p_freq; + AudioServer::get_singleton()->sample_set_mix_rate(sd->rid,p_freq); + +} +void CPSampleManagerImpl::set_loop_begin(CPSample_ID p_id,int32_t p_begin){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + sd->loop_begin=p_begin; + AudioServer::get_singleton()->sample_set_loop_begin(sd->rid,p_begin); + +} +void CPSampleManagerImpl::set_loop_end(CPSample_ID p_id,int32_t p_end){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + sd->loop_end=p_end; + AudioServer::get_singleton()->sample_set_loop_end(sd->rid,p_end); + +} +void CPSampleManagerImpl::set_loop_type(CPSample_ID p_id,CPSample_Loop_Type p_type){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + + sd->loop_type=p_type; + AudioServer::get_singleton()->sample_set_loop_format(sd->rid,AudioServer::SampleLoopFormat(p_type)); + + +} +void CPSampleManagerImpl::set_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + + ERR_FAIL(); +} + + +int32_t CPSampleManagerImpl::get_loop_begin(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + return sd->loop_begin; + +} +int32_t CPSampleManagerImpl::get_loop_end(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + return sd->loop_end; +} +CPSample_Loop_Type CPSampleManagerImpl::get_loop_type(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),CP_LOOP_NONE); +#endif + + return sd->loop_type; +} +int32_t CPSampleManagerImpl::get_c5_freq(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + return sd->mixfreq; +} +int32_t CPSampleManagerImpl::get_size(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + return sd->len; + +} +bool CPSampleManagerImpl::is_16bits(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),false); +#endif + + return sd->is16; + +} +bool CPSampleManagerImpl::is_stereo(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),false); +#endif + return sd->stereo; + + +} +bool CPSampleManagerImpl::lock_data(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + sd->locks++; + if (sd->locks==1) { + sd->lock=AudioServer::get_singleton()->sample_get_data(sd->rid); + sd->w=sd->lock.write(); + } + + return true; +} +void *CPSampleManagerImpl::get_data(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + ERR_FAIL_COND_V(sd->locks==0,0); + return sd->w.ptr(); +} + +int16_t CPSampleManagerImpl::get_data(CPSample_ID p_id, int p_sample, int p_channel){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!valid.has(sd),0); +#endif + + ERR_FAIL_V(0); + lock_data(p_id); + + int sofs = sd->stereo ? 2:1; + uint16_t v=0; + if (sd->is16) { + int16_t *p=(int16_t*)sd->w.ptr(); + v=p[p_sample*sofs+p_channel]; + } else { + int8_t *p=(int8_t*)sd->w.ptr(); + v=p[p_sample*sofs+p_channel]; + } + + unlock_data(p_id); + + return v; +} +void CPSampleManagerImpl::set_data(CPSample_ID p_id, int p_sample, int16_t p_data,int p_channel){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + + ERR_FAIL(); + lock_data(p_id); + + int sofs = sd->stereo ? 2:1; + if (sd->is16) { + int16_t *p=(int16_t*)sd->w.ptr(); + p[p_sample*sofs+p_channel]=p_data; + } else { + int8_t *p=(int8_t*)sd->w.ptr(); + p[p_sample*sofs+p_channel]=p_data; + } + + unlock_data(p_id); + +} +void CPSampleManagerImpl::unlock_data(CPSample_ID p_id){ + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + + ERR_FAIL_COND(sd->locks==0); + + sd->locks--; + if (sd->locks==0) { + sd->w=DVector::Write(); + AudioServer::get_singleton()->sample_set_data(sd->rid,sd->lock); + sd->lock=DVector(); + } +} + +void CPSampleManagerImpl::get_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len) { + + SampleData *sd=_getsd(p_id); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(!valid.has(sd)); +#endif + + ERR_FAIL(); +} + + +/** MIXER **/ + +void CPMixerImpl::set_callback_interval(int p_interval_us) { + + callback_interval=p_interval_us; +} + +void CPMixerImpl::set_callback(void (*p_callback)(void*),void *p_userdata) { + + callback=p_callback; + userdata=p_userdata; +} + +void CPMixerImpl::setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) { + + Voice &v=voices[p_voice_index]; + if (v.channel!=AudioMixer::INVALID_CHANNEL) { + mixer->channel_free(v.channel); + } + v.channel=mixer->channel_alloc(sample_manager->get_rid(p_sample_id)); + v.freq_mult = sample_manager->get_c5_freq(p_sample_id)/261.6255653006; + v.sample = p_sample_id; +} + +void CPMixerImpl::stop_voice(int p_voice_index) { + + Voice &v=voices[p_voice_index]; + if (v.channel==AudioMixer::INVALID_CHANNEL) + return; + + mixer->channel_free(v.channel); + v.channel=AudioMixer::INVALID_CHANNEL; + +} + +void CPMixerImpl::set_voice_frequency(int p_voice_index,int32_t p_freq) { + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + float f = p_freq / 256.0; + f*=pitch_scale; + mixer->channel_set_mix_rate(v.channel,f * v.freq_mult ); +} + +void CPMixerImpl::set_voice_panning(int p_voice_index,int p_pan) { + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + if (p_pan==CP_PAN_SURROUND) + p_pan=CP_PAN_CENTER; + float p = p_pan / 256.0; + mixer->channel_set_pan(v.channel,p); + +} + +void CPMixerImpl::set_voice_volume(int p_voice_index,int p_vol) { + + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + float vol = p_vol/512.0; + vol*=voice_scale; + mixer->channel_set_volume(v.channel,vol); + mixer->channel_set_reverb(v.channel,reverb_type,vol*v.reverb); +} + +void CPMixerImpl::set_voice_filter(int p_voice_index,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance ){ + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + +} + +void CPMixerImpl::set_voice_reverb_send(int p_voice_index,int p_reverb){ + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + v.reverb=p_reverb/255.0; + //mixer->channel_set_reverb(v.channel,reverb_type,p_reverb/255.0); + +} + +void CPMixerImpl::set_voice_chorus_send(int p_voice_index,int p_chorus){ + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + mixer->channel_set_chorus(v.channel,p_chorus/255.0); + +} + + +void CPMixerImpl::set_reverb_mode(ReverbMode p_mode){ + +// Voice &v=voices[p_voice_index]; +// ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + switch(p_mode) { + case CPMixer::REVERB_MODE_STUDIO_SMALL: reverb_type=AudioMixer::REVERB_SMALL; break; + case CPMixer::REVERB_MODE_STUDIO_MEDIUM: reverb_type=AudioMixer::REVERB_MEDIUM; break; + case CPMixer::REVERB_MODE_STUDIO_LARGE: reverb_type=AudioMixer::REVERB_LARGE; break; + case CPMixer::REVERB_MODE_HALL: reverb_type=AudioMixer::REVERB_HALL; break; + default: reverb_type=AudioMixer::REVERB_SMALL; break; + } + +} + +void CPMixerImpl::set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10){ + +// Voice &v=voices[p_voice_index]; +// ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); + +} + + + +/* Info retrieving */ + +int32_t CPMixerImpl::get_voice_sample_pos_index(int p_voice_index) { + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND_V(v.channel==AudioMixer::INVALID_CHANNEL,0); + return 0; + +} + +int CPMixerImpl::get_voice_panning(int p_voice_index) { + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND_V(!is_voice_active(p_voice_index),0); + return mixer->channel_get_pan(v.channel)*CP_PAN_RIGHT; + +} + +int CPMixerImpl::get_voice_volume(int p_voice_index) { + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND_V(!is_voice_active(p_voice_index),0); + return mixer->channel_get_volume(v.channel); + + +} + +CPSample_ID CPMixerImpl::get_voice_sample_id(int p_voice_index) { + + Voice &v=voices[p_voice_index]; + ERR_FAIL_COND_V(v.channel==AudioMixer::INVALID_CHANNEL,CPSample_ID()); + return v.sample; + + +} + +bool CPMixerImpl::is_voice_active(int p_voice_index){ + + Voice &v=voices[p_voice_index]; + if (v.channel==AudioMixer::INVALID_CHANNEL) + return false; + if (!mixer->channel_is_valid(v.channel)) + v.channel=AudioMixer::INVALID_CHANNEL; + + return v.channel!=AudioMixer::INVALID_CHANNEL; +} + +void CPMixerImpl::process_usecs(int p_usec,float p_volume,float p_pitch_scale,float p_tempo_scale) { + + ERR_FAIL_COND(callback_interval==0); + //update this somewhere + pitch_scale=p_pitch_scale; + tempo_scale=p_tempo_scale; + voice_scale = AudioServer::get_singleton()->get_event_voice_global_volume_scale()*p_volume; + while(p_usec) { + + if (p_usec>=callback_timeout) { + + p_usec-=callback_timeout; + callback_timeout=0; + if (callback) { + callback(userdata); + } + callback_timeout=callback_interval*(1.0/p_tempo_scale); + + } else { + + callback_timeout-=p_usec; + p_usec=0; + } + } +} + + +CPMixerImpl::CPMixerImpl(AudioMixer *p_mixer) { + + callback_interval=1; + callback_timeout=0; + userdata=0; + callback=0; + tempo_scale=1.0; + pitch_scale=1.0; + mixer=p_mixer; + voice_scale = AudioServer::get_singleton()->get_event_voice_global_volume_scale(); + reverb_type = AudioMixer::REVERB_SMALL; + +} + +/** FILE ACCESS WRAPPER **/ + + +CPFileAccessWrapperImpl::Error CPFileAccessWrapperImpl::open(const char *p_filename, int p_mode_flags) { + + ERR_FAIL_COND_V(p_mode_flags&WRITE,ERROR_WRITING_FILE); + close(); + f = FileAccess::open(String::utf8(p_filename),p_mode_flags); + if (!f) + return ERROR_FILE_NOT_FOUND; + return OK; +} + +void CPFileAccessWrapperImpl::close(){ + + if (f) + memdelete(f); + f=NULL; + + +} + +void CPFileAccessWrapperImpl::seek(uint32_t p_position){ + + f->seek(p_position); +} +void CPFileAccessWrapperImpl::seek_end(){ + + f->seek_end(); +} +uint32_t CPFileAccessWrapperImpl::get_pos(){ + + return f->get_pos(); +} + +bool CPFileAccessWrapperImpl::eof_reached(){ + + return f->eof_reached(); +} + +uint8_t CPFileAccessWrapperImpl::get_byte(){ + + return f->get_8(); +} +void CPFileAccessWrapperImpl::get_byte_array(uint8_t *p_dest,int p_elements){ + + f->get_buffer(p_dest,p_elements); +} +void CPFileAccessWrapperImpl::get_word_array(uint16_t *p_dest,int p_elements){ + + for(int i=0;iget_16(); + } + +} + +uint16_t CPFileAccessWrapperImpl::get_word(){ + + return f->get_16(); +} +uint32_t CPFileAccessWrapperImpl::get_dword(){ + + return f->get_32(); +} + +void CPFileAccessWrapperImpl::set_endian_conversion(bool p_swap){ + + f->set_endian_swap(p_swap); +} +bool CPFileAccessWrapperImpl::is_open(){ + + return f!=NULL; +} + +CPFileAccessWrapperImpl::Error CPFileAccessWrapperImpl::get_error(){ + + return (f->get_error()!=::OK)?ERROR_READING_FILE:OK; +} + +void CPFileAccessWrapperImpl::store_byte(uint8_t p_dest){ + +} +void CPFileAccessWrapperImpl::store_byte_array(const uint8_t *p_dest,int p_elements){ + +} + +void CPFileAccessWrapperImpl::store_word(uint16_t p_dest){ + +} +void CPFileAccessWrapperImpl::store_dword(uint32_t p_dest){ + +} + +//////////////////////////////////////////////// + + +Error EventStreamPlaybackChibi::_play() { + + last_order=0; + loops=0; + player->play_start_song(); + total_usec=0; + + return OK; +} + +bool EventStreamPlaybackChibi::_update(AudioMixer* p_mixer, uint64_t p_usec){ + + total_usec+=p_usec; + mixer.process_usecs(p_usec,volume,pitch_scale,tempo_scale); + int order=player->get_current_order(); + if (orderplay_stop(); +} + +void EventStreamPlaybackChibi::set_paused(bool p_paused){ + +} +bool EventStreamPlaybackChibi::is_paused() const{ + + return false; +} +void EventStreamPlaybackChibi::set_loop(bool p_loop){ + + loop=p_loop; + +} +bool EventStreamPlaybackChibi::is_loop_enabled() const{ + + return loop; +} + +int EventStreamPlaybackChibi::get_loop_count() const{ + + //return player->is + return loops; +} + +float EventStreamPlaybackChibi::get_pos() const{ + + return double(total_usec)/1000000.0; +} +void EventStreamPlaybackChibi::seek_pos(float p_time){ + + WARN_PRINT("seek_pos unimplemented."); +} + +void EventStreamPlaybackChibi::set_volume(float p_volume) { + + volume=p_volume; +} + +float EventStreamPlaybackChibi::get_volume() const{ + + return volume; +} + +void EventStreamPlaybackChibi::set_pitch_scale(float p_pitch_scale) { + + pitch_scale=p_pitch_scale; +} + +float EventStreamPlaybackChibi::get_pitch_scale() const{ + + return pitch_scale; +} + +void EventStreamPlaybackChibi::set_tempo_scale(float p_tempo_scale) { + + tempo_scale=p_tempo_scale; +} + +float EventStreamPlaybackChibi::get_tempo_scale() const{ + + return tempo_scale; +} + + +void EventStreamPlaybackChibi::set_channel_volume(int p_channel,float p_volume) { + + + if (p_channel>=64) + return; + player->set_channel_global_volume(p_channel,p_volume*256); +} + + + +float EventStreamPlaybackChibi::get_channel_volume(int p_channel) const{ + + return player->get_channel_global_volume(p_channel)/256.0; + +} + +float EventStreamPlaybackChibi::get_last_note_time(int p_channel) const { + + + double v = (player->get_channel_last_note_time_usec(p_channel))/1000000.0; + if (v<0) + v=-1; + return v; +} + +EventStreamPlaybackChibi::EventStreamPlaybackChibi(Ref p_stream) : mixer(_get_mixer()) { + + stream=p_stream; + player = memnew( CPPlayer(&mixer,&p_stream->song) ); + loop=false; + last_order=0; + loops=0; + volume=1.0; + pitch_scale=1.0; + tempo_scale=1.0; +} +EventStreamPlaybackChibi::~EventStreamPlaybackChibi(){ + + player->play_stop(); + memdelete(player); +} + +//////////////////////////////////////////////////// + +Ref EventStreamChibi::instance_playback() { + + return Ref( memnew(EventStreamPlaybackChibi(Ref(this))) ); +} + +String EventStreamChibi::get_stream_name() const{ + + return song.get_name(); + +} + + + +float EventStreamChibi::get_length() const{ + + return 1; +} + + +EventStreamChibi::EventStreamChibi() { + + +} + + + +////////////////////////////////////////////////////////////////// + + + + +RES ResourceFormatLoaderChibi::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; + String el = p_path.extension().to_lower(); + + CPFileAccessWrapperImpl f; + + if (el=="it") { + + Ref esc( memnew( EventStreamChibi ) ); + CPLoader_IT loader(&f); + CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false); + ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; + + return esc; + + } else if (el=="xm") { + + Ref esc( memnew( EventStreamChibi ) ); + CPLoader_XM loader(&f); + CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); + ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; + return esc; + + } else if (el=="s3m") { + + Ref esc( memnew( EventStreamChibi ) ); + CPLoader_S3M loader(&f); + CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); + ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; + + return esc; + + } else if (el=="mod") { + + Ref esc( memnew( EventStreamChibi ) ); + CPLoader_MOD loader(&f); + CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); + ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); + if (r_error) + *r_error=OK; + return esc; + } + + return RES(); + +} + +void ResourceFormatLoaderChibi::get_recognized_extensions(List *p_extensions) const { + + p_extensions->push_back("it"); + p_extensions->push_back("xm"); + p_extensions->push_back("s3m"); + p_extensions->push_back("mod"); +} +bool ResourceFormatLoaderChibi::handles_type(const String& p_type) const { + + return (p_type=="EventStreamChibi" || p_type=="EventStream"); +} + +String ResourceFormatLoaderChibi::get_resource_type(const String &p_path) const { + String el = p_path.extension().to_lower(); + if (el=="it" || el=="s3m" || el=="xm" || el=="mod") + return "EventStreamChibi"; + return ""; +} + +///////////////////////////////////////////////////////////////// +void initialize_chibi() { + + sample_manager = memnew( CPSampleManagerImpl ); + resource_loader = memnew( ResourceFormatLoaderChibi ); + ObjectTypeDB::register_type(); + ResourceLoader::add_resource_format_loader( resource_loader ); +} + +void finalize_chibi() { + + memdelete( sample_manager ); + memdelete( resource_loader ); +} + diff --git a/modules/chibi/event_stream_chibi.h b/modules/chibi/event_stream_chibi.h new file mode 100644 index 0000000000..cc7b0ace86 --- /dev/null +++ b/modules/chibi/event_stream_chibi.h @@ -0,0 +1,314 @@ +/*************************************************************************/ +/* event_stream_chibi.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 EVENT_STREAM_CHIBI_H +#define EVENT_STREAM_CHIBI_H + +#include "scene/resources/event_stream.h" +#include "cp_sample_manager.h" +#include "cp_mixer.h" +#include "cp_song.h" +#include "cp_file_access_wrapper.h" +#include "cp_player_data.h" +#include "resource.h" +#include "servers/audio_server.h" +#include "os/file_access.h" +#include "io/resource_loader.h" + +/** SAMPLE MANAGER **/ + +class CPSampleManagerImpl : public CPSampleManager { + + struct SampleData { + + RID rid; + bool stereo; + bool is16; + int len; + int mixfreq; + int loop_begin; + int loop_end; + int locks; + DVector lock; + DVector::Write w; + CPSample_Loop_Type loop_type; + }; + + + _FORCE_INLINE_ SampleData* _getsd(CPSample_ID p_id) { + + return ((SampleData*)p_id._private); + } + Set valid; + +public: + + _FORCE_INLINE_ RID get_rid(CPSample_ID p_id) { return _getsd(p_id)->rid; } + virtual CPSample_ID create(bool p_16bits,bool p_stereo,int32_t p_len); + virtual void recreate(CPSample_ID p_id,bool p_16bits,bool p_stereo,int32_t p_len); + virtual void destroy(CPSample_ID p_id); + virtual bool check(CPSample_ID p_id); // return false if invalid + + virtual void set_c5_freq(CPSample_ID p_id,int32_t p_freq); + virtual void set_loop_begin(CPSample_ID p_id,int32_t p_begin); + virtual void set_loop_end(CPSample_ID p_id,int32_t p_end); + virtual void set_loop_type(CPSample_ID p_id,CPSample_Loop_Type p_type); + virtual void set_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len); + + + virtual int32_t get_loop_begin(CPSample_ID p_id); + virtual int32_t get_loop_end(CPSample_ID p_id); + virtual CPSample_Loop_Type get_loop_type(CPSample_ID p_id); + virtual int32_t get_c5_freq(CPSample_ID p_id); + virtual int32_t get_size(CPSample_ID p_id); + virtual bool is_16bits(CPSample_ID p_id); + virtual bool is_stereo(CPSample_ID p_id); + virtual bool lock_data(CPSample_ID p_id); + virtual void *get_data(CPSample_ID p_id); /* WARNING: Not all sample managers +may be able to implement this, it depends on the mixer in use! */ + virtual int16_t get_data(CPSample_ID p_id, int p_sample, int p_channel=0); /// Does not need locking + virtual void set_data(CPSample_ID p_id, int p_sample, int16_t p_data,int p_channel=0); /// Does not need locking + virtual void unlock_data(CPSample_ID p_id); + + virtual void get_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len); + +}; + + +/** MIXER **/ + +class CPMixerImpl : public CPMixer { + + enum { + MAX_VOICES=64 + }; + + struct Voice { + + AudioMixer::ChannelID channel; + CPSample_ID sample; + float freq_mult; + float reverb; + Voice() { reverb=0.0; } + }; + + Voice voices[MAX_VOICES]; + + + int callback_interval; + int callback_timeout; + void (*callback)(void*); + void *userdata; + float voice_scale; + float tempo_scale; + float pitch_scale; + AudioMixer::ReverbRoomType reverb_type; + AudioMixer *mixer; +public: + + void process_usecs(int p_usec,float p_volume,float p_pitch_scale,float p_tempo_scale); + + /* Callback */ + + virtual void set_callback_interval(int p_interval_us); //in usecs, for tracker it's 2500000/tempo + virtual void set_callback(void (*p_callback)(void*),void *p_userdata); + + /* Voice Control */ + + virtual void setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) ; + virtual void stop_voice(int p_voice_index) ; + virtual void set_voice_frequency(int p_voice_index,int32_t p_freq) ; //in freq*FREQUENCY_BITS + virtual void set_voice_panning(int p_voice_index,int p_pan) ; + virtual void set_voice_volume(int p_voice_index,int p_vol) ; + virtual void set_voice_filter(int p_filter,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance ); + virtual void set_voice_reverb_send(int p_voice_index,int p_reverb); + virtual void set_voice_chorus_send(int p_voice_index,int p_chorus); /* 0 - 255 */ + + virtual void set_reverb_mode(ReverbMode p_mode); + virtual void set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10); + + + /* Info retrieving */ + + virtual int32_t get_voice_sample_pos_index(int p_voice_index) ; + virtual int get_voice_panning(int p_voice_index) ; + virtual int get_voice_volume(int p_voice_index) ; + virtual CPSample_ID get_voice_sample_id(int p_voice_index) ; + virtual bool is_voice_active(int p_voice_index); + virtual int get_active_voice_count() { return 0; } + virtual int get_total_voice_count() { return MAX_VOICES; } + + + virtual uint32_t get_mix_frequency() { return 0; } + + /* Methods below only work with software mixers, meant for software-based sound drivers, hardware mixers ignore them */ + virtual int32_t process(int32_t p_frames) { return 0; } + virtual int32_t *get_mixdown_buffer_ptr() { return NULL; } + virtual void set_mix_frequency(int32_t p_mix_frequency) {}; + + CPMixerImpl(AudioMixer *p_mixer=NULL); + virtual ~CPMixerImpl() {} +}; + +/** FILE ACCESS **/ + +class CPFileAccessWrapperImpl : public CPFileAccessWrapper { + + FileAccess *f; +public: + + + virtual Error open(const char *p_filename, int p_mode_flags); + virtual void close(); + + virtual void seek(uint32_t p_position); + virtual void seek_end(); + virtual uint32_t get_pos(); + + virtual bool eof_reached(); + + virtual uint8_t get_byte(); + virtual void get_byte_array(uint8_t *p_dest,int p_elements); + virtual void get_word_array(uint16_t *p_dest,int p_elements); + + virtual uint16_t get_word(); + virtual uint32_t get_dword(); + + virtual void set_endian_conversion(bool p_swap); + virtual bool is_open(); + + virtual Error get_error(); + + virtual void store_byte(uint8_t p_dest); + virtual void store_byte_array(const uint8_t *p_dest,int p_elements); + + virtual void store_word(uint16_t p_dest); + virtual void store_dword(uint32_t p_dest); + + CPFileAccessWrapperImpl() { f=NULL; } + virtual ~CPFileAccessWrapperImpl(){ if (f) memdelete(f); } + +}; + + + +///////////////////// + +class EventStreamChibi; + +class EventStreamPlaybackChibi : public EventStreamPlayback { + + OBJ_TYPE(EventStreamPlaybackChibi,EventStreamPlayback); + + CPMixerImpl mixer; + uint64_t total_usec; + Ref stream; + mutable CPPlayer *player; + bool loop; + int last_order; + int loops; + virtual Error _play(); + virtual bool _update(AudioMixer* p_mixer, uint64_t p_usec); + virtual void _stop(); + float volume; + float tempo_scale; + float pitch_scale; + + +public: + + + virtual void set_paused(bool p_paused); + virtual bool is_paused() const; + + virtual void set_loop(bool p_loop); + virtual bool is_loop_enabled() const; + + virtual int get_loop_count() const; + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + virtual void set_volume(float p_vol); + virtual float get_volume() const; + + virtual void set_pitch_scale(float p_pitch_scale); + virtual float get_pitch_scale() const; + + virtual void set_tempo_scale(float p_tempo_scale); + virtual float get_tempo_scale() const; + + virtual void set_channel_volume(int p_channel,float p_volume); + virtual float get_channel_volume(int p_channel) const; + + virtual float get_last_note_time(int p_channel) const; + + EventStreamPlaybackChibi(Ref p_stream=Ref()); + ~EventStreamPlaybackChibi(); +}; + + +class EventStreamChibi : public EventStream { + + OBJ_TYPE(EventStreamChibi,EventStream); + +friend class ResourceFormatLoaderChibi; +friend class EventStreamPlaybackChibi; + //I think i didn't know what const was when i wrote this more than a decade ago + //so it goes mutable :( + mutable CPSong song; + + +public: + + virtual Ref instance_playback(); + + virtual String get_stream_name() const; + + virtual float get_length() const; + + virtual int get_channel_count() const { return 64; } //tracker limit + + EventStreamChibi(); +}; + + +class ResourceFormatLoaderChibi : public ResourceFormatLoader { + +public: + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + +}; + +void initialize_chibi(); +void finalize_chibi(); + +#endif // EVENT_STREAM_CHIBI_H diff --git a/modules/chibi/register_types.cpp b/modules/chibi/register_types.cpp new file mode 100644 index 0000000000..b2ba16fa03 --- /dev/null +++ b/modules/chibi/register_types.cpp @@ -0,0 +1,41 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "register_types.h" + +#include "event_stream_chibi.h" + +void register_chibi_types() { + + initialize_chibi(); +} + +void unregister_chibi_types() { + + finalize_chibi(); +} diff --git a/modules/chibi/register_types.h b/modules/chibi/register_types.h new file mode 100644 index 0000000000..159823b85d --- /dev/null +++ b/modules/chibi/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.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. */ +/*************************************************************************/ +void register_chibi_types(); +void unregister_chibi_types(); -- cgit v1.2.3