/*************************************************************************/ /* cp_song.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_song.h" void CPSong::set_name(const char *p_name) { if (p_name==NULL) { variables.name[0]=0; return; } bool done=false; for (int i=0;iMAX_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