Oops! Audio engine has vanished :D
This commit is contained in:
parent
b24b52d56b
commit
b400c69cd4
160 changed files with 618 additions and 24650 deletions
2
core/math/audio_frame.cpp
Normal file
2
core/math/audio_frame.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "audio_frame.h"
|
||||
|
28
core/math/audio_frame.h
Normal file
28
core/math/audio_frame.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef AUDIOFRAME_H
|
||||
#define AUDIOFRAME_H
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
struct AudioFrame {
|
||||
|
||||
float l,r;
|
||||
|
||||
_ALWAYS_INLINE_ const float& operator[](int idx) const { return idx==0?l:r; }
|
||||
_ALWAYS_INLINE_ float& operator[](int idx) { return idx==0?l:r; }
|
||||
|
||||
_ALWAYS_INLINE_ AudioFrame operator+(const AudioFrame& p_frame) const { return AudioFrame(l+p_frame.l,r+p_frame.r); }
|
||||
_ALWAYS_INLINE_ AudioFrame operator-(const AudioFrame& p_frame) const { return AudioFrame(l-p_frame.l,r-p_frame.r); }
|
||||
_ALWAYS_INLINE_ AudioFrame operator*(const AudioFrame& p_frame) const { return AudioFrame(l*p_frame.l,r*p_frame.r); }
|
||||
_ALWAYS_INLINE_ AudioFrame operator/(const AudioFrame& p_frame) const { return AudioFrame(l/p_frame.l,r/p_frame.r); }
|
||||
|
||||
_ALWAYS_INLINE_ void operator+=(const AudioFrame& p_frame) { l+=p_frame.l; r+=p_frame.r; }
|
||||
_ALWAYS_INLINE_ void operator-=(const AudioFrame& p_frame) { l-=p_frame.l; r-=p_frame.r; }
|
||||
_ALWAYS_INLINE_ void operator*=(const AudioFrame& p_frame) { l*=p_frame.l; r*=p_frame.r; }
|
||||
_ALWAYS_INLINE_ void operator/=(const AudioFrame& p_frame) { l/=p_frame.l; r/=p_frame.r; }
|
||||
|
||||
_ALWAYS_INLINE_ AudioFrame(float p_l, float p_r) {l=p_l; r=p_r;}
|
||||
_ALWAYS_INLINE_ AudioFrame(const AudioFrame& p_frame) {l=p_frame.l; r=p_frame.r;}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -46,7 +46,7 @@ Error AudioDriverALSA::init() {
|
|||
samples_out = NULL;
|
||||
|
||||
mix_rate = GLOBAL_DEF("audio/mix_rate",44100);
|
||||
output_format = OUTPUT_STEREO;
|
||||
output_format = SPEAKER_MODE_STEREO;
|
||||
channels = 2;
|
||||
|
||||
|
||||
|
@ -205,7 +205,7 @@ int AudioDriverALSA::get_mix_rate() const {
|
|||
return mix_rate;
|
||||
};
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverALSA::get_output_format() const {
|
||||
AudioDriver::SpeakerMode AudioDriverALSA::get_speaker_mode() const {
|
||||
|
||||
return output_format;
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "servers/audio/audio_server_sw.h"
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
#ifdef ALSA_ENABLED
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
class AudioDriverALSA : public AudioDriverSW {
|
||||
class AudioDriverALSA : public AudioDriver {
|
||||
|
||||
Thread* thread;
|
||||
Mutex* mutex;
|
||||
|
@ -48,7 +48,7 @@ class AudioDriverALSA : public AudioDriverSW {
|
|||
static void thread_func(void* p_udata);
|
||||
|
||||
unsigned int mix_rate;
|
||||
OutputFormat output_format;
|
||||
SpeakerMode output_format;
|
||||
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
snd_pcm_uframes_t period_size;
|
||||
|
@ -68,7 +68,7 @@ public:
|
|||
virtual Error init();
|
||||
virtual void start();
|
||||
virtual int get_mix_rate() const;
|
||||
virtual OutputFormat get_output_format() const;
|
||||
virtual SpeakerMode get_speaker_mode() const;
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual void finish();
|
||||
|
|
|
@ -44,7 +44,7 @@ Error AudioDriverPulseAudio::init() {
|
|||
samples_out = NULL;
|
||||
|
||||
mix_rate = GLOBAL_DEF("audio/mix_rate",44100);
|
||||
output_format = OUTPUT_STEREO;
|
||||
output_format = SPEAKER_MODE_STEREO;
|
||||
channels = 2;
|
||||
|
||||
pa_sample_spec spec;
|
||||
|
@ -149,7 +149,7 @@ int AudioDriverPulseAudio::get_mix_rate() const {
|
|||
return mix_rate;
|
||||
}
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverPulseAudio::get_output_format() const {
|
||||
AudioDriver::SpeakerMode AudioDriverPulseAudio::get_speaker_mode() const {
|
||||
|
||||
return output_format;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "servers/audio/audio_server_sw.h"
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
#ifdef PULSEAUDIO_ENABLED
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include <pulse/simple.h>
|
||||
|
||||
class AudioDriverPulseAudio : public AudioDriverSW {
|
||||
class AudioDriverPulseAudio : public AudioDriver{
|
||||
|
||||
Thread* thread;
|
||||
Mutex* mutex;
|
||||
|
@ -48,7 +48,7 @@ class AudioDriverPulseAudio : public AudioDriverSW {
|
|||
static void thread_func(void* p_udata);
|
||||
|
||||
unsigned int mix_rate;
|
||||
OutputFormat output_format;
|
||||
SpeakerMode output_format;
|
||||
|
||||
unsigned int buffer_size;
|
||||
int channels;
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
virtual Error init();
|
||||
virtual void start();
|
||||
virtual int get_mix_rate() const;
|
||||
virtual OutputFormat get_output_format() const;
|
||||
virtual SpeakerMode get_speaker_mode() const;
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual void finish();
|
||||
|
|
|
@ -156,7 +156,7 @@ int AudioDriverXAudio2::get_mix_rate() const {
|
|||
return mix_rate;
|
||||
};
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverXAudio2::get_output_format() const {
|
||||
AudioDriver::OutputFormat AudioDriverXAudio2::get_output_format() const {
|
||||
|
||||
return output_format;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <xaudio2.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class AudioDriverXAudio2 : public AudioDriverSW {
|
||||
class AudioDriverXAudio2 : public AudioDriver {
|
||||
|
||||
enum {
|
||||
AUDIO_BUFFERS = 2
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "input_map.h"
|
||||
#include "io/resource_loader.h"
|
||||
#include "scene/main/scene_main_loop.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
#include "script_language.h"
|
||||
#include "io/resource_loader.h"
|
||||
|
@ -63,8 +63,6 @@
|
|||
#include "tools/doc/doc_data.h"
|
||||
|
||||
|
||||
#include "servers/spatial_sound_server.h"
|
||||
#include "servers/spatial_sound_2d_server.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
|
||||
|
||||
|
@ -83,6 +81,7 @@ static Engine *engine=NULL;
|
|||
static InputMap *input_map=NULL;
|
||||
static bool _start_success=false;
|
||||
static ScriptDebugger *script_debugger=NULL;
|
||||
AudioServer *audio_server=NULL;
|
||||
|
||||
static MessageQueue *message_queue=NULL;
|
||||
static Performance *performance = NULL;
|
||||
|
@ -908,6 +907,11 @@ Error Main::setup2() {
|
|||
OS::get_singleton()->set_window_position(init_custom_pos);
|
||||
}
|
||||
|
||||
//right moment to create and initialize the audio server
|
||||
|
||||
audio_server = memnew( AudioServer );
|
||||
audio_server->init();
|
||||
|
||||
OS::get_singleton()->set_use_vsync(use_vsync);
|
||||
|
||||
register_core_singletons();
|
||||
|
@ -1657,11 +1661,6 @@ bool Main::iteration() {
|
|||
OS::get_singleton()->get_main_loop()->idle( step*time_scale );
|
||||
message_queue->flush();
|
||||
|
||||
if (SpatialSoundServer::get_singleton())
|
||||
SpatialSoundServer::get_singleton()->update( step*time_scale );
|
||||
if (SpatialSound2DServer::get_singleton())
|
||||
SpatialSound2DServer::get_singleton()->update( step*time_scale );
|
||||
|
||||
|
||||
VisualServer::get_singleton()->sync(); //sync if still drawing from previous frames.
|
||||
|
||||
|
@ -1764,6 +1763,11 @@ void Main::cleanup() {
|
|||
OS::get_singleton()->_execpath="";
|
||||
OS::get_singleton()->_local_clipboard="";
|
||||
|
||||
if (audio_server) {
|
||||
memdelete(audio_server);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
EditorNode::unregister_editor_types();
|
||||
#endif
|
||||
|
@ -1775,6 +1779,7 @@ void Main::cleanup() {
|
|||
|
||||
OS::get_singleton()->finalize();
|
||||
|
||||
|
||||
if (packed_data)
|
||||
memdelete(packed_data);
|
||||
if (file_access_network_client)
|
||||
|
|
|
@ -104,10 +104,10 @@ MainLoop* test_main(String p_test,const List<String>& p_args) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (p_test=="sound") {
|
||||
//if (p_test=="sound") {
|
||||
|
||||
return TestSound::test();
|
||||
}
|
||||
// return TestSound::test();
|
||||
//}
|
||||
|
||||
if (p_test=="io") {
|
||||
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
#include "servers/visual_server.h"
|
||||
#include "os/main_loop.h"
|
||||
#include "math_funcs.h"
|
||||
#include "scene/resources/sample.h"
|
||||
|
||||
#include "io/resource_loader.h"
|
||||
#include "print_string.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "os/os.h"
|
||||
|
||||
#if 0
|
||||
namespace TestSound {
|
||||
|
||||
|
||||
|
@ -93,3 +95,4 @@ MainLoop* test() {
|
|||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
Import('env_modules')
|
||||
|
||||
env_chibi = env_modules.Clone()
|
||||
|
||||
# Godot source files
|
||||
env_chibi.add_source_files(env.modules_sources, "*.cpp")
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
def can_build(platform):
|
||||
return True
|
||||
|
||||
|
||||
def configure(env):
|
||||
pass
|
|
@ -1,52 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_config.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,369 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_envelope.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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<node_count) && (limit==-1)) {
|
||||
|
||||
if (node[count].tick_offset>=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<<FX_HEIGHT_BITS;
|
||||
|
||||
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<node_count) && (limit==-1)) {
|
||||
|
||||
if (node[count].tick_offset>=pos) limit=count;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (pos==0) return node[0].value<<FX_HEIGHT_BITS;
|
||||
|
||||
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<<FX_HEIGHT_BITS)+((pos-begin_x)*(end_y-begin_y)*(int)(1<<FX_HEIGHT_BITS))/(xdif?xdif:1);
|
||||
}
|
||||
*/
|
||||
|
||||
float CPEnvelope::get_interp_height_at_pos(float 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<node_count) && (limit==-1)) {
|
||||
|
||||
if (node[count].tick_offset>=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<min_value) p_y=min_value;
|
||||
|
||||
|
||||
node[p_node].tick_offset=p_x;
|
||||
node[p_node].value=p_y;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int CPEnvelope::add_position(int p_x,int p_y,bool p_move_loops) {
|
||||
|
||||
if (node_count==MAX_POINTS) return -1;
|
||||
|
||||
|
||||
int i,new_node;
|
||||
|
||||
// if this is assigning an existing node, let's quit.
|
||||
for (i=0;i<node_count;i++) if (p_x==node[i].tick_offset) return -1;
|
||||
|
||||
|
||||
i=0;
|
||||
while ((i<node_count) && (p_x>=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<loop_begin_node) loop_end_node=loop_begin_node;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CPEnvelope::set_loop_end(int pos) {
|
||||
|
||||
if ((pos<0) || (pos>=node_count)) return;
|
||||
|
||||
|
||||
|
||||
loop_end_node=pos;
|
||||
|
||||
if (loop_end_node<loop_begin_node) loop_begin_node=loop_end_node;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CPEnvelope::set_sustain_loop_begin(int pos) {
|
||||
|
||||
if ((pos<0) || (pos>=node_count)) return;
|
||||
|
||||
|
||||
|
||||
sustain_loop_begin_node=pos;
|
||||
|
||||
if (sustain_loop_end_node<sustain_loop_begin_node) sustain_loop_end_node=sustain_loop_begin_node;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CPEnvelope::set_sustain_loop_end(int pos) {
|
||||
|
||||
if ((pos<0) || (pos>=node_count)) return;
|
||||
|
||||
|
||||
|
||||
sustain_loop_end_node=pos;
|
||||
|
||||
if (sustain_loop_end_node<sustain_loop_begin_node) sustain_loop_begin_node=sustain_loop_end_node;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CPEnvelope::set_loop_enabled(bool p_enabled) {
|
||||
|
||||
loop_on=p_enabled;
|
||||
}
|
||||
bool CPEnvelope::is_loop_enabled() {
|
||||
|
||||
return loop_on;
|
||||
}
|
||||
|
||||
|
||||
void CPEnvelope::set_sustain_loop_enabled(bool p_enabled) {
|
||||
|
||||
sustain_loop_on=p_enabled;
|
||||
}
|
||||
bool CPEnvelope::is_sustain_loop_enabled() {
|
||||
|
||||
return sustain_loop_on;
|
||||
}
|
||||
|
||||
void CPEnvelope::del_position(int p_node) {
|
||||
|
||||
if ((node_count<3) || (p_node<=0) || (p_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-1;i++) node[i]=node[i+1];
|
||||
|
||||
node_count--;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint8_t CPEnvelope::get_loop_begin() {
|
||||
|
||||
|
||||
return loop_begin_node;
|
||||
}
|
||||
uint8_t CPEnvelope::get_loop_end() {
|
||||
|
||||
return loop_end_node;
|
||||
}
|
||||
|
||||
uint8_t CPEnvelope::get_sustain_loop_begin() {
|
||||
|
||||
|
||||
return sustain_loop_begin_node;
|
||||
}
|
||||
uint8_t CPEnvelope::get_sustain_loop_end() {
|
||||
|
||||
return sustain_loop_end_node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CPEnvelope::set_enabled(bool p_enabled) {
|
||||
|
||||
on=p_enabled;
|
||||
}
|
||||
|
||||
bool CPEnvelope::is_enabled() {
|
||||
|
||||
return on;
|
||||
}
|
||||
|
||||
void CPEnvelope::set_carry_enabled(bool p_enabled) {
|
||||
|
||||
carry=p_enabled;
|
||||
}
|
||||
bool CPEnvelope::is_carry_enabled() {
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
uint8_t CPEnvelope::get_node_count() {
|
||||
|
||||
return node_count;
|
||||
}
|
||||
|
||||
const CPEnvelope::Point& CPEnvelope::get_node(int p_idx) {
|
||||
|
||||
if (p_idx<0 || p_idx>=node_count)
|
||||
return node[node_count-1];
|
||||
|
||||
return node[p_idx];
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_envelope.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,96 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_file_access_wrapper.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,344 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_instrument.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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<MAX_NAME_LEN;i++) {
|
||||
|
||||
|
||||
name[i]=done?0:p_name[i];
|
||||
if (!done && p_name[i]==0)
|
||||
done=true;
|
||||
}
|
||||
|
||||
name[MAX_NAME_LEN-1]=0; /* just in case */
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CPInstrument::set_sample_number(uint8_t p_note,uint8_t p_sample_id) {
|
||||
|
||||
CP_ERR_COND(p_note>=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<CPNote::NOTES;i++) {
|
||||
|
||||
data.sample_number[i]=CPNote::EMPTY;
|
||||
data.note_number[i]=i;
|
||||
}
|
||||
|
||||
data.volume.envelope.reset();
|
||||
data.volume.envelope.set_max(64);
|
||||
data.volume.envelope.set_min(0);
|
||||
data.volume.envelope.add_position(0,64,false);
|
||||
data.volume.envelope.add_position(30,64,false);
|
||||
|
||||
data.volume.global_amount=MAX_VOLUME;
|
||||
data.volume.fadeout=0;
|
||||
data.volume.random_variation=0;
|
||||
|
||||
data.pan.envelope.reset();
|
||||
data.pan.envelope.set_max(32);
|
||||
data.pan.envelope.set_min(-32);
|
||||
data.pan.envelope.add_position(0,0,false);
|
||||
data.pan.envelope.add_position(30,0,false);
|
||||
|
||||
data.pan.default_amount=32;
|
||||
data.pan.pitch_center=48;
|
||||
data.pan.pitch_separation=0;
|
||||
data.pan.use_default=false;
|
||||
data.pan.random_variation=0;
|
||||
|
||||
|
||||
data.pitch.envelope.reset();
|
||||
data.pitch.envelope.set_max(32);
|
||||
data.pitch.envelope.set_min(-32);
|
||||
data.pitch.envelope.add_position(0,0,false);
|
||||
data.pitch.envelope.add_position(30,0,false);
|
||||
data.pitch.use_as_filter=false;
|
||||
data.pitch.use_default_cutoff=false;
|
||||
data.pitch.use_default_resonance=false;
|
||||
data.pitch.default_cutoff=0;
|
||||
data.pitch.default_resonance=0;
|
||||
|
||||
}
|
||||
|
||||
bool CPInstrument::is_empty() {
|
||||
|
||||
bool has_sample=false;
|
||||
|
||||
for (int i=0;i<CPNote::NOTES;i++) {
|
||||
|
||||
if (data.sample_number[i]!=CPNote::EMPTY) {
|
||||
|
||||
has_sample=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !has_sample;
|
||||
}
|
||||
|
||||
CPInstrument::CPInstrument() {
|
||||
|
||||
reset();
|
||||
|
||||
}
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_instrument.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_INSTRUMENT_H
|
||||
#define CP_INSTRUMENT_H
|
||||
|
||||
|
||||
#include "cp_config.h"
|
||||
#include "cp_note.h"
|
||||
#include "cp_envelope.h"
|
||||
|
||||
class CPInstrument {
|
||||
public:
|
||||
|
||||
|
||||
enum NNA_Type {
|
||||
|
||||
NNA_NOTE_CUT,
|
||||
NNA_NOTE_CONTINUE,
|
||||
NNA_NOTE_OFF,
|
||||
NNA_NOTE_FADE
|
||||
};
|
||||
|
||||
enum DC_Type {
|
||||
|
||||
DCT_DISABLED,
|
||||
DCT_NOTE,
|
||||
DCT_SAMPLE,
|
||||
DCT_INSTRUMENT
|
||||
};
|
||||
|
||||
enum DC_Action
|
||||
{
|
||||
|
||||
DCA_NOTE_CUT,
|
||||
DCA_NOTE_OFF,
|
||||
DCA_NOTE_FADE,
|
||||
};
|
||||
|
||||
enum EnvelopeType {
|
||||
VOLUME_ENVELOPE,
|
||||
PAN_ENVELOPE,
|
||||
PITCH_ENVELOPE
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
MAX_NAME_LEN=26,
|
||||
MAX_ENVELOPE_NODES=25,
|
||||
ENVELOPE_FRAC_BITS=8,
|
||||
MAX_VOLUME=128,
|
||||
MAX_FADEOUT=256,
|
||||
MAX_PAN=128,
|
||||
MAX_VOLUME_RANDOM=100,
|
||||
MAX_PAN_RANDOM=64, //what did this guy have inside his head?
|
||||
|
||||
MAX_FILTER_CUTOFF=127,
|
||||
MAX_FILTER_RESONANCE=127
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct Data {
|
||||
|
||||
|
||||
uint8_t sample_number[CPNote::NOTES];
|
||||
uint8_t note_number[CPNote::NOTES];
|
||||
|
||||
NNA_Type NNA_type;
|
||||
DC_Type DC_type;
|
||||
DC_Action DC_action;
|
||||
|
||||
struct Volume {
|
||||
|
||||
CPEnvelope envelope;
|
||||
uint8_t global_amount;
|
||||
uint16_t fadeout;
|
||||
uint8_t random_variation;
|
||||
|
||||
} volume;
|
||||
|
||||
struct Pan {
|
||||
|
||||
CPEnvelope envelope;
|
||||
bool use_default;
|
||||
uint8_t default_amount;
|
||||
int8_t pitch_separation;
|
||||
uint8_t pitch_center;
|
||||
uint8_t random_variation;
|
||||
|
||||
} pan;
|
||||
|
||||
struct Pitch {
|
||||
|
||||
CPEnvelope envelope;
|
||||
bool use_as_filter;
|
||||
bool use_default_cutoff;
|
||||
uint8_t default_cutoff;
|
||||
bool use_default_resonance;
|
||||
uint8_t default_resonance;
|
||||
} pitch;
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
Data data;
|
||||
char name[MAX_NAME_LEN];
|
||||
|
||||
public:
|
||||
|
||||
/* CPInstrument General */
|
||||
|
||||
const char *get_name();
|
||||
void set_name(const char *p_name);
|
||||
|
||||
void set_sample_number(uint8_t p_note,uint8_t p_sample_id);
|
||||
uint8_t get_sample_number(uint8_t p_note);
|
||||
|
||||
void set_note_number(uint8_t p_note,uint8_t p_note_id);
|
||||
uint8_t get_note_number(uint8_t p_note);
|
||||
|
||||
void set_NNA_type(NNA_Type p_NNA_type);
|
||||
NNA_Type get_NNA_type();
|
||||
|
||||
void set_DC_type(DC_Type p_DC_type);
|
||||
DC_Type get_DC_type();
|
||||
|
||||
void set_DC_action(DC_Action p_DC_action);
|
||||
DC_Action get_DC_action();
|
||||
|
||||
/* Volume */
|
||||
|
||||
void set_volume_global_amount(uint8_t p_amount);
|
||||
uint8_t get_volume_global_amount();
|
||||
|
||||
void set_volume_fadeout(uint16_t p_amount);
|
||||
uint16_t get_volume_fadeout();
|
||||
|
||||
void set_volume_random_variation(uint8_t p_amount);
|
||||
uint8_t get_volume_random_variation();
|
||||
|
||||
/* Panning */
|
||||
|
||||
void set_pan_default_amount(uint8_t p_amount);
|
||||
uint8_t get_pan_default_amount();
|
||||
|
||||
void set_pan_default_enabled(bool p_enabled);
|
||||
bool is_pan_default_enabled();
|
||||
|
||||
void set_pan_pitch_separation(int8_t p_amount);
|
||||
int8_t get_pan_pitch_separation();
|
||||
|
||||
void set_pan_pitch_center(uint8_t p_amount);
|
||||
uint8_t get_pan_pitch_center();
|
||||
|
||||
void set_pan_random_variation(uint8_t p_amount);
|
||||
uint8_t get_pan_random_variation();
|
||||
|
||||
/* Pitch / Filter */
|
||||
|
||||
void set_pitch_use_as_filter(bool p_enabled);
|
||||
bool is_pitch_use_as_filter();
|
||||
|
||||
void set_filter_use_default_cutoff(bool p_enabled);
|
||||
bool filter_use_default_cutoff();
|
||||
|
||||
void set_filter_default_cutoff(uint8_t p_amount);
|
||||
uint8_t get_filter_default_cutoff();
|
||||
|
||||
void set_filter_use_default_resonance(bool p_enabled);
|
||||
bool filter_use_default_resonance();
|
||||
|
||||
void set_filter_default_resonance(uint8_t p_amount);
|
||||
uint8_t get_filter_default_resonance();
|
||||
|
||||
CPEnvelope* get_volume_envelope();
|
||||
CPEnvelope* get_pan_envelope();
|
||||
CPEnvelope* get_pitch_filter_envelope();
|
||||
|
||||
bool is_empty();
|
||||
|
||||
void reset();
|
||||
CPInstrument();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_H
|
||||
#define CP_LOADER_H
|
||||
|
||||
|
||||
#include "cp_song.h"
|
||||
#include "cp_file_access_wrapper.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
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
|
|
@ -1,216 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_it.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<CPSong::MAX_SAMPLES;i++)
|
||||
exchange[i]=0;
|
||||
|
||||
for (int i=0;i<samples;i++) {
|
||||
|
||||
file->seek( 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;s<CPSong::MAX_SAMPLES;s++) {
|
||||
|
||||
if (p_song->get_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;i<CPNote::NOTES;i++) {
|
||||
|
||||
int smp=song->get_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;
|
||||
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_it.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,268 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_it_info.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<CPPattern::WIDTH;i++) {
|
||||
song->set_channel_reverb(i,file->get_byte());
|
||||
}
|
||||
for (int i=0;i<CPPattern::WIDTH;i++) {
|
||||
song->set_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;i<header.msglength;i++) if (tmpmsg[i]=='\r') tmpmsg[i]='\n';
|
||||
|
||||
song->set_message(tmpmsg);
|
||||
|
||||
return FILE_OK;
|
||||
}
|
||||
|
||||
CPLoader::Error CPLoader_IT::load_orders() {
|
||||
|
||||
file->seek(0xC0);
|
||||
|
||||
|
||||
for (int i=0;i<header.ordnum;i++) {
|
||||
|
||||
uint8_t aux_order=file->get_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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_it_instruments.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<CPNote::NOTES;i++) {
|
||||
|
||||
|
||||
uint8_t note=file->get_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;i<header.insnum;i++) {
|
||||
|
||||
|
||||
file->seek(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;
|
||||
}
|
||||
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_it_patterns.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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<header.patnum;i++) {
|
||||
|
||||
if (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(row<pat_length);
|
||||
|
||||
}
|
||||
|
||||
return FILE_OK;
|
||||
}
|
||||
|
|
@ -1,620 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_it_samples.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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"
|
||||
#include "cp_sample.h"
|
||||
|
||||
struct AuxSampleData {
|
||||
|
||||
|
||||
uint32_t fileofs;
|
||||
uint32_t c5spd;
|
||||
uint32_t length;
|
||||
uint32_t loop_begin;
|
||||
uint32_t loop_end;
|
||||
bool loop_enabled;
|
||||
bool pingpong_enabled;
|
||||
bool is16bit;
|
||||
bool stereo;
|
||||
bool exists;
|
||||
bool compressed;
|
||||
|
||||
};
|
||||
|
||||
|
||||
enum IT_Sample_Flags {
|
||||
|
||||
IT_SAMPLE_EXISTS=1,
|
||||
IT_SAMPLE_16BITS=2,
|
||||
IT_SAMPLE_STEREO=4,
|
||||
IT_SAMPLE_COMPRESSED=8,
|
||||
IT_SAMPLE_LOOPED=16,
|
||||
IT_SAMPLE_SUSTAIN_LOOPED=32,
|
||||
IT_SAMPLE_LOOP_IS_PINGPONG=64,
|
||||
IT_SAMPLE_SUSTAIN_LOOP_IS_PINGPONG=128
|
||||
};
|
||||
|
||||
|
||||
CPLoader::Error CPLoader_IT::load_sample(CPSample *p_sample) {
|
||||
|
||||
|
||||
AuxSampleData aux_sample_data;
|
||||
|
||||
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]!='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;c<chans;c++) {
|
||||
|
||||
for (int i=0;i<p_sample_data.length;i++) {
|
||||
|
||||
ptr16[i*chans+c]=file->get_word();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (int c=0;c<chans;c++) {
|
||||
|
||||
for (int i=0;i<p_sample_data.length;i++) {
|
||||
|
||||
ptr8[i*chans+c]=file->get_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;i<header.smpnum;i++) {
|
||||
|
||||
//seek to sample
|
||||
file->seek(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<p_buffsize;i++)
|
||||
dest_buffer[i]=0;
|
||||
|
||||
|
||||
dest_position = dest_buffer;
|
||||
|
||||
it215=(header.cmwt==0x215);
|
||||
|
||||
/* now unpack data till the dest buffer is full */
|
||||
|
||||
while (p_buffsize) {
|
||||
/* read a new block of compressed data and reset variables */
|
||||
if ( read_IT_compressed_block(false) ) {
|
||||
CP_PRINTERR("Out of memory decompressing IT CPSample");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
block_length = (p_buffsize < 0x8000) ? p_buffsize : 0x8000;
|
||||
|
||||
block_position = 0;
|
||||
|
||||
bit_width = 9; /* start with width of 9 bits */
|
||||
|
||||
d1 = d2 = 0; /* reset integrator buffers */
|
||||
|
||||
/* now uncompress the data block */
|
||||
while ( block_position < block_length ) {
|
||||
|
||||
aux_value = read_n_bits_from_IT_compressed_block(bit_width); /* read bits */
|
||||
|
||||
if ( bit_width < 7 ) { /* method 1 (1-6 bits) */
|
||||
|
||||
if ( aux_value == (1 << (bit_width - 1)) ) { /* check for "100..." */
|
||||
|
||||
aux_value = read_n_bits_from_IT_compressed_block(3) + 1; /* yes -> 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<p_buffsize;i++)
|
||||
dest_buffer[i]=0;
|
||||
|
||||
dest_position = dest_buffer;
|
||||
|
||||
it215=(header.cmwt==0x215);
|
||||
|
||||
|
||||
while (p_buffsize) {
|
||||
/* read a new block of compressed data and reset variables */
|
||||
if ( read_IT_compressed_block(true) ) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
block_length = (p_buffsize < 0x4000) ? p_buffsize : 0x4000;
|
||||
|
||||
block_position = 0;
|
||||
|
||||
bit_width = 17; /* start with width of 9 bits */
|
||||
|
||||
d1 = d2 = 0; /* reset integrator buffers */
|
||||
|
||||
while ( block_position < block_length ) {
|
||||
|
||||
aux_value = read_n_bits_from_IT_compressed_block(bit_width); /* read bits */
|
||||
|
||||
if ( bit_width < 7 ) { /* method 1 (1-6 bits) */
|
||||
|
||||
if ( (signed)aux_value == (1 << (bit_width - 1)) ) { /* check for "100..." */
|
||||
|
||||
aux_value = read_n_bits_from_IT_compressed_block(4) + 1; /* yes -> 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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,482 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_mod.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<instruments;i++) {
|
||||
|
||||
char sample_name[23];
|
||||
file->get_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;i<channels;i++)
|
||||
p_song->set_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 (i<order_count) {
|
||||
p_song->set_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;i<pattern_count;i++) {
|
||||
|
||||
for(int line=0;line<64;line++) {
|
||||
|
||||
for(int column=0;column<channels;column++) {
|
||||
|
||||
uint32_t note_w=file->get_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;i<instruments;i++) {
|
||||
|
||||
CPSample_ID sid=p_song->get_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;s<len;s++) {
|
||||
|
||||
uint8_t d=file->get_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()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_mod.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 <reduz@gmail.com>
|
||||
*/
|
||||
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
|
|
@ -1,413 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_s3m.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<header.insnum;i++) {
|
||||
|
||||
int parapointer;
|
||||
parapointer=file->get_word();
|
||||
parapointer=(parapointer*16);
|
||||
sample_parapointers[i]=parapointer;
|
||||
}
|
||||
//pattern
|
||||
for (i=0;i<header.patnum;i++) {
|
||||
|
||||
int parapointer;
|
||||
parapointer=file->get_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;i<header.ordnum;i++) song->set_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<<BITBOOL(data_is_16bits);
|
||||
real_sample_size<<=BITBOOL(data_is_stereo);
|
||||
|
||||
CPSampleManager *sm=CPSampleManager::get_singleton();
|
||||
|
||||
CPSample_ID id =sm->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;c<chans;c++) {
|
||||
for (int i=0;i<sample_size;i++) {
|
||||
|
||||
if (data_is_16bits) {
|
||||
|
||||
uint16_t s=file->get_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;i<header.insnum;i++) {
|
||||
|
||||
file->seek(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;i<header.patnum;i++) {
|
||||
|
||||
file->seek(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(){
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_s3m.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,766 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_xm.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<header.songlength;i++) {
|
||||
|
||||
if (i>199)
|
||||
break;
|
||||
song->set_order(i,header.orderlist[i]);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
LOAD PATTERNS
|
||||
***************************************/
|
||||
|
||||
for (int i=0;i<header.patterns_used;i++) {
|
||||
|
||||
uint32_t aux,rows;
|
||||
|
||||
aux=file->get_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;k<header.channels_used;k++) {
|
||||
|
||||
CPNote aux_note;
|
||||
uint8_t aux_byte;
|
||||
//uint8_t field;
|
||||
aux_byte=file->get_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;i<header.instruments_used;i++) {
|
||||
|
||||
|
||||
uint32_t aux;
|
||||
int sampnum;
|
||||
|
||||
CPInstrument &instrument=*song->get_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;j<volpoints;j++) {
|
||||
int ofs=volenv[j*2];
|
||||
int val=volenv[j*2+1];
|
||||
p_instr->get_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;j<panpoints;j++) {
|
||||
int ofs=panenv[j*2];
|
||||
int val=panenv[j*2+1];
|
||||
p_instr->get_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)<p_hsize) {
|
||||
|
||||
uint8_t junkbuster[500];
|
||||
|
||||
//printf("extra junk XM instrument in header! hsize is %i, extra junk: %i\n",p_hsize,(file->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;j<sampnum;j++) {
|
||||
|
||||
if (j>16) ABORT_LOAD;
|
||||
|
||||
|
||||
int s_idx=-1;
|
||||
for (int s=0;s<CPSong::MAX_SAMPLES;s++) {
|
||||
|
||||
if (song->get_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;j<sampnum;j++) {
|
||||
|
||||
if (sample_index[j]==-1) continue;
|
||||
|
||||
CPSample *sample=song->get_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;k<sm->get_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;k<sm->get_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(){
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_loader_xm.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,115 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_mixer.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,102 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_note.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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) && (note<NOTES))
|
||||
note--;
|
||||
else if (note==SCRIPT && parameter>0)
|
||||
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
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_order.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
||||
|
|
@ -1,574 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_pattern.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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<<RESIZE_EVERY_BITS)-1)))+(1<<RESIZE_EVERY_BITS);
|
||||
|
||||
CP_ERR_COND_V(new_size<p_events,true); //bugARM_INFO
|
||||
|
||||
if (event_count==0 && new_size==0)
|
||||
return false; //nothing to do
|
||||
|
||||
if (event_count==0) {
|
||||
|
||||
events=(Event*)CP_ALLOC( new_size*sizeof(Event) );
|
||||
|
||||
} else if (new_size==0) {
|
||||
|
||||
CP_FREE(events);
|
||||
events=NULL;
|
||||
} else {
|
||||
|
||||
CP_ERR_COND_V(events==NULL,true);
|
||||
events=(Event*)CP_REALLOC(events, new_size*sizeof(Event));
|
||||
|
||||
}
|
||||
|
||||
event_count=p_events;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int32_t CPPattern::get_event_pos(uint16_t p_target_pos) {
|
||||
|
||||
|
||||
if (event_count==0)
|
||||
return -1;
|
||||
|
||||
int low = 0;
|
||||
int high = event_count -1;
|
||||
int middle;
|
||||
|
||||
while( low <= high )
|
||||
{
|
||||
middle = ( low + high ) / 2;
|
||||
|
||||
if( p_target_pos == events[middle].pos ) { //match
|
||||
break;
|
||||
} else if( p_target_pos < events[middle].pos )
|
||||
high = middle - 1; //search low end of array
|
||||
else
|
||||
low = middle + 1; //search high end of array
|
||||
}
|
||||
|
||||
/* adapt so we are behind 2 */
|
||||
|
||||
if (events[middle].pos<p_target_pos)
|
||||
middle++;
|
||||
return middle;
|
||||
|
||||
/* Linear search for now */
|
||||
|
||||
/*
|
||||
int32_t pos_idx=0;
|
||||
|
||||
for (;pos_idx<event_count;pos_idx++) {
|
||||
|
||||
if (event_list[pos_idx].pos>=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_rows<MIN_ROWS) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_rows<length) {
|
||||
|
||||
Event* event_list=events;
|
||||
if (event_list==0) {
|
||||
|
||||
CP_PRINTERR("get_event_list() Failed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint16_t target_pos=p_rows*WIDTH;
|
||||
int32_t pos_idx = get_event_pos(target_pos);
|
||||
|
||||
|
||||
if (pos_idx==-1) {
|
||||
|
||||
CP_ERR_COND(pos_idx==-1);
|
||||
}
|
||||
|
||||
if (resize_event_list_to(pos_idx)) {
|
||||
|
||||
CP_PRINTERR("resize_event_list_to(pos_idx) Failed");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
length=p_rows;
|
||||
|
||||
|
||||
}
|
||||
#if 0
|
||||
void CPPattern::copy_to(CPPattern *p_pattern) const {
|
||||
|
||||
|
||||
|
||||
|
||||
p_pattern->clear();
|
||||
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;i<bufsiz;i++)
|
||||
dst[i]=src[i];
|
||||
|
||||
MemPool_Wrapper::get_singleton()->unlock_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();
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_pattern.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,151 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 <stdio.h>
|
||||
|
||||
|
||||
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;i<control.max_voices;i++) {
|
||||
|
||||
voice[i].reset();
|
||||
mixer->stop_voice(i);
|
||||
}
|
||||
|
||||
for (i=0;i<CPPattern::WIDTH;i++) {
|
||||
|
||||
control.channel[i].reset();
|
||||
control.channel[i].channel_volume=song->get_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;
|
||||
}
|
|
@ -1,582 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,324 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_control.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<control.max_voices;i++) {
|
||||
|
||||
voice[i].reset();
|
||||
mixer->stop_voice(i);
|
||||
}
|
||||
|
||||
for (i=0;i<CPPattern::WIDTH;i++) {
|
||||
|
||||
control.channel[i].reset();
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
}
|
||||
|
||||
void CPPlayer::play_note(int p_channel,CPNote note,bool p_reserve) {
|
||||
|
||||
|
||||
|
||||
if (control.play_mode==PLAY_NOTHING) {
|
||||
|
||||
control.ticks_counter=0;
|
||||
}
|
||||
|
||||
/*control.channel[p_channel].reset();
|
||||
control.channel[p_channel].channel_volume=song->get_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;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,89 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_envelopes.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;
|
||||
}
|
|
@ -1,681 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_events.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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<<CPMixer::FREQUENCY_BITS)));
|
||||
|
||||
|
||||
void CPPlayer::setup_voices() {
|
||||
|
||||
int i,voice_index;
|
||||
|
||||
|
||||
|
||||
|
||||
for (i=0;i<CPPattern::WIDTH;i++) {
|
||||
|
||||
voice_index=-1;
|
||||
|
||||
if (control.channel[i].note_delay) continue;
|
||||
|
||||
|
||||
// check if we need a new empty voice
|
||||
if (control.channel[i].kick==KICK_NOTE) {
|
||||
|
||||
/* if no channel was cut above, find an empty or quiet channel
|
||||
here */
|
||||
if ( song->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 (i<control.max_voices) {
|
||||
|
||||
control.channel[i].slave_voice_index=i;
|
||||
control.channel[i].slave_voice=&voice[i];
|
||||
} else {
|
||||
//This is a _DIRTY_ hack, but i cant think a better way.
|
||||
control.channel[i].slave_voice_index=control.max_voices-1;
|
||||
control.channel[i].slave_voice=&voice[control.max_voices-1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* assign parts of MP_VOICE only done for a KICK_NOTE */
|
||||
if ( ( control.channel[i].slave_voice!=NULL ) ) {
|
||||
|
||||
voice_index=control.channel[i].slave_voice_index;
|
||||
Voice_Control &v=voice[voice_index];
|
||||
|
||||
if (v.has_master_channel && (v.master_channel!=NULL) ) {
|
||||
// If this voice already has a master channel, make sure to remove the reference to it.
|
||||
v.master_channel->slave_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;i<control.max_voices;i++) {
|
||||
|
||||
|
||||
int filter_env=-1;
|
||||
Voice_Control &v=voice[i];
|
||||
|
||||
if ( !((v.kick==KICK_NOTE)||(v.kick==KICK_NOTEOFF)) && !is_voice_active(i))
|
||||
continue;
|
||||
|
||||
//if voice doesnt have a sample set or size is 0.. forget it
|
||||
if ( v.sample_ptr==NULL) continue;
|
||||
|
||||
|
||||
//TODO set limits somewhere else
|
||||
|
||||
if (v.period<40) {
|
||||
|
||||
v.period=40;
|
||||
|
||||
} else if (v.period>50000) {
|
||||
|
||||
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=(newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_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)<v.sample_ptr->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<<CPEnvelope::FX_HEIGHT_BITS)-1))*(env_next-env)/(1<<CPEnvelope::FX_HEIGHT_BITS);
|
||||
|
||||
printf("env %i\n",env);
|
||||
*/
|
||||
aux_pitch_diff=env-base;
|
||||
|
||||
|
||||
if ( ((int)tmp_mixer_period-aux_pitch_diff)<0 ) aux_pitch_diff=0;
|
||||
|
||||
tmp_mixer_period+=aux_pitch_diff;
|
||||
|
||||
} else {
|
||||
|
||||
filter_env=pe_value+32; //max 64
|
||||
//printf("pitch envelope at %i",filter_env);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (v.fadeout_volume==0 || (v.note_end_flags & END_NOTE_KILL)) { /* check for a dead note (fadevol=0) */
|
||||
|
||||
mixer->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;i<CPPattern::WIDTH;i++) {
|
||||
|
||||
process_note(i,song->get_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++;
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_filter.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_nna.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<CPPattern::WIDTH;i++) {
|
||||
|
||||
Channel_Control *aux_chn_ctrl = &control.channel[i];
|
||||
|
||||
if (aux_chn_ctrl->kick==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;i<control.max_voices;i++) {
|
||||
if (!mixer->is_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) */
|
||||
}
|
||||
}
|
|
@ -1,345 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_notes.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_instrument<CPSong::MAX_INSTRUMENTS)) {
|
||||
new_instrument=process_new_instrument(p_track,p_instrument);
|
||||
|
||||
if ( song->has_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].panning<PAN_LEFT) control.channel[p_track].panning=PAN_LEFT;
|
||||
if (control.channel[p_track].panning>PAN_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].panning<PAN_LEFT) control.channel[p_track].panning=PAN_LEFT;
|
||||
if (control.channel[p_track].panning>PAN_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_instrument<CPSong::MAX_INSTRUMENTS) { // instrument change
|
||||
|
||||
control.channel[p_track].volume=control.channel[p_track].aux_volume=aux_sample->get_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 );
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_player_data_utils.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<control.max_voices;i++) {
|
||||
|
||||
if ( ((voice[i].kick==KICK_NOTHING)||(voice[i].kick==KICK_ENVELOPE))&&!mixer->is_voice_active(i) ) {
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// todo more
|
||||
|
||||
for (i=0;i<control.max_voices;i++) {
|
||||
/* allow us to take over a nonexisting sample */
|
||||
/*
|
||||
if ((voice[i].s==NULL)
|
||||
return k;
|
||||
*/
|
||||
|
||||
if ((voice[i].kick==KICK_NOTHING)||(voice[i].kick==KICK_ENVELOPE)) {
|
||||
|
||||
priority=voice[i].total_volume<<((CPSampleManager::get_singleton()->get_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) || (priority<min_priority)) {
|
||||
min_priority=priority;
|
||||
min_priority_chan=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (min_priority>8000*7) return -1; /* what the fuck is this? */
|
||||
|
||||
return min_priority_chan;
|
||||
}
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_sample.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<NAME_MAX_LEN;i++) {
|
||||
|
||||
|
||||
name[i]=done?0:p_name[i];
|
||||
if (!done && p_name[i]==0)
|
||||
done=true;
|
||||
}
|
||||
|
||||
name[NAME_MAX_LEN-1]=0; /* just in case */
|
||||
|
||||
}
|
||||
|
||||
void CPSample::set_default_volume(uint8_t p_vol) {
|
||||
|
||||
default_volume=p_vol;
|
||||
}
|
||||
uint8_t CPSample::get_default_volume() const{
|
||||
|
||||
return default_volume;
|
||||
}
|
||||
|
||||
void CPSample::set_global_volume(uint8_t p_vol) {
|
||||
|
||||
global_volume=p_vol;
|
||||
}
|
||||
uint8_t CPSample::get_global_volume() const{
|
||||
|
||||
return global_volume;
|
||||
}
|
||||
|
||||
void CPSample::set_pan_enabled(bool p_vol) {
|
||||
|
||||
pan_enabled=p_vol;
|
||||
}
|
||||
bool CPSample::is_pan_enabled() const{
|
||||
|
||||
return pan_enabled;
|
||||
}
|
||||
|
||||
void CPSample::set_pan(uint8_t p_pan) {
|
||||
|
||||
pan=p_pan;
|
||||
|
||||
}
|
||||
uint8_t CPSample::get_pan() const{
|
||||
|
||||
return pan;
|
||||
}
|
||||
|
||||
|
||||
void CPSample::set_vibrato_type(VibratoType p_vibrato_type) {
|
||||
|
||||
vibrato_type=p_vibrato_type;
|
||||
}
|
||||
CPSample::VibratoType CPSample::get_vibrato_type() const{
|
||||
|
||||
return vibrato_type;
|
||||
}
|
||||
|
||||
void CPSample::set_vibrato_speed(uint8_t p_vibrato_speed) {
|
||||
|
||||
vibrato_speed=p_vibrato_speed;
|
||||
}
|
||||
uint8_t CPSample::get_vibrato_speed() const {
|
||||
|
||||
return vibrato_speed;
|
||||
}
|
||||
|
||||
void CPSample::set_vibrato_depth(uint8_t p_vibrato_depth) {
|
||||
|
||||
vibrato_depth=p_vibrato_depth;
|
||||
}
|
||||
uint8_t CPSample::get_vibrato_depth() const{
|
||||
|
||||
return vibrato_depth;
|
||||
}
|
||||
|
||||
void CPSample::set_vibrato_rate(uint8_t p_vibrato_rate) {
|
||||
|
||||
vibrato_rate=p_vibrato_rate;
|
||||
}
|
||||
uint8_t CPSample::get_vibrato_rate() const{
|
||||
|
||||
return vibrato_rate;
|
||||
}
|
||||
|
||||
void CPSample::set_sample_data(CPSample_ID p_ID) {
|
||||
|
||||
id=p_ID;
|
||||
}
|
||||
CPSample_ID CPSample::get_sample_data() const{
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void CPSample::operator=(const CPSample &p_sample) {
|
||||
|
||||
copy_from(p_sample);
|
||||
}
|
||||
void CPSample::copy_from(const CPSample &p_sample) {
|
||||
|
||||
reset();
|
||||
set_name(p_sample.get_name());
|
||||
|
||||
default_volume=p_sample.default_volume;
|
||||
global_volume=p_sample.global_volume;
|
||||
|
||||
pan_enabled=p_sample.pan_enabled;
|
||||
pan=p_sample.pan;
|
||||
|
||||
vibrato_type=p_sample.vibrato_type;
|
||||
vibrato_speed=p_sample.vibrato_speed;
|
||||
vibrato_depth=p_sample.vibrato_depth;
|
||||
vibrato_rate=p_sample.vibrato_rate;
|
||||
|
||||
if (CPSampleManager::get_singleton() && !p_sample.id.is_null())
|
||||
CPSampleManager::get_singleton()->copy_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();
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_sample.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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
|
|
@ -1,97 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_sample_defs.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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<<CP_MIXING_FRAC_BITS),
|
||||
CP_MIXING_FRAC_MASK=CP_MIXING_FRAC_LENGTH-1,
|
||||
CP_MIXING_VOL_FRAC_BITS=8,
|
||||
CP_MIXING_FREQ_FRAC_BITS=8
|
||||
};
|
||||
|
||||
enum CPFilterConstants {
|
||||
CP_FILTER_SHIFT=16,
|
||||
CP_FILTER_LENGTH=(1<<CP_FILTER_SHIFT)
|
||||
};
|
||||
|
||||
|
||||
enum CPInterpolationType {
|
||||
CP_INTERPOLATION_RAW,
|
||||
CP_INTERPOLATION_LINEAR,
|
||||
CP_INTERPOLATION_CUBIC
|
||||
};
|
||||
|
||||
enum CPPanConstants {
|
||||
|
||||
CP_PAN_BITS=8, // 0 .. 256
|
||||
CP_PAN_LEFT=0,
|
||||
CP_PAN_RIGHT=((1<<CP_PAN_BITS)-1), // 255
|
||||
CP_PAN_CENTER=CP_PAN_RIGHT/2, // 128
|
||||
CP_PAN_SURROUND=512
|
||||
};
|
||||
|
||||
enum CPMixerVolConstants {
|
||||
CP_VOL_MAX=512,
|
||||
CP_VOL_RAMP_BITS=9,
|
||||
CP_VOL_SHIFT=2
|
||||
|
||||
|
||||
};
|
||||
|
||||
enum CPStereoCannels {
|
||||
CP_CHAN_LEFT,
|
||||
CP_CHAN_RIGHT
|
||||
};
|
||||
|
||||
#define CP_FIRST_SAMPLE_DECLICK_THRESHOLD 1000
|
||||
#define CP_FIRST_SAMPLE_RAMP_LEN 32
|
||||
|
||||
typedef signed char CPFrame8;
|
||||
typedef signed short CPFrame16;
|
||||
|
||||
|
||||
#endif
|
|
@ -1,78 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_sample_manager.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_manager.h"
|
||||
|
||||
|
||||
CPSampleManager * CPSampleManager::singleton=NULL;
|
||||
|
||||
|
||||
void CPSampleManager::copy_to(CPSample_ID p_from,CPSample_ID &p_to) {
|
||||
|
||||
ERR_FAIL_COND(!check( p_from ));
|
||||
|
||||
|
||||
if (p_to.is_null()) {
|
||||
|
||||
p_to=create( is_16bits( p_from), is_stereo( p_from), get_size(p_from));
|
||||
} else {
|
||||
|
||||
recreate( p_to, is_16bits( p_from), is_stereo( p_from), get_size(p_from));
|
||||
|
||||
}
|
||||
|
||||
int len=get_size( p_from );
|
||||
int ch=is_stereo( p_from ) ? 2 : 1;
|
||||
|
||||
for (int c=0;c<ch;c++) {
|
||||
|
||||
for (int i=0;i<len;i++) {
|
||||
|
||||
int16_t s=get_data( p_from, i, c );
|
||||
set_data( p_to, i, s, c );
|
||||
}
|
||||
}
|
||||
|
||||
set_loop_type( p_to, get_loop_type( p_from ) );
|
||||
set_loop_begin( p_to, get_loop_begin( p_from ) );
|
||||
set_loop_end( p_to, get_loop_end( p_from ) );
|
||||
set_c5_freq( p_to, get_c5_freq( p_from ) );
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
CPSampleManager::CPSampleManager() {
|
||||
|
||||
singleton=this;
|
||||
}
|
||||
|
||||
CPSampleManager *CPSampleManager::get_singleton() {
|
||||
|
||||
return singleton;
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_sample_manager.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_MANAGER_H
|
||||
#define CP_SAMPLE_MANAGER_H
|
||||
|
||||
#include "cp_config.h"
|
||||
#include "cp_sample_defs.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@author Juan Linietsky
|
||||
*/
|
||||
|
||||
|
||||
/* abstract base CPSample_ID class */
|
||||
|
||||
struct CPSample_ID {
|
||||
|
||||
void *_private;
|
||||
|
||||
bool operator==(const CPSample_ID&p_other) const { return _private==p_other._private; }
|
||||
bool operator!=(const CPSample_ID&p_other) const { return _private!=p_other._private; }
|
||||
bool is_null() const { return _private==0; }
|
||||
CPSample_ID(void *p_private=0) { _private=p_private; };
|
||||
};
|
||||
|
||||
|
||||
class CPSampleManager {
|
||||
|
||||
static CPSampleManager * singleton;
|
||||
|
||||
public:
|
||||
|
||||
/* get the singleton instance */
|
||||
static CPSampleManager *get_singleton();
|
||||
|
||||
virtual void copy_to(CPSample_ID p_from,CPSample_ID &p_to); ///< if p_to is null, it gets created
|
||||
|
||||
virtual CPSample_ID create(bool p_16bits,bool p_stereo,int32_t p_len)=0;
|
||||
virtual void recreate(CPSample_ID p_id,bool p_16bits,bool p_stereo,int32_t p_len)=0;
|
||||
virtual void destroy(CPSample_ID p_id)=0;
|
||||
virtual bool check(CPSample_ID p_id)=0; // return false if invalid
|
||||
|
||||
virtual void set_c5_freq(CPSample_ID p_id,int32_t p_freq)=0;
|
||||
virtual void set_loop_begin(CPSample_ID p_id,int32_t p_begin)=0;
|
||||
virtual void set_loop_end(CPSample_ID p_id,int32_t p_end)=0;
|
||||
virtual void set_loop_type(CPSample_ID p_id,CPSample_Loop_Type p_type)=0;
|
||||
virtual void set_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len)=0;
|
||||
|
||||
|
||||
virtual int32_t get_loop_begin(CPSample_ID p_id)=0;
|
||||
virtual int32_t get_loop_end(CPSample_ID p_id)=0;
|
||||
virtual CPSample_Loop_Type get_loop_type(CPSample_ID p_id)=0;
|
||||
virtual int32_t get_c5_freq(CPSample_ID p_id)=0;
|
||||
virtual int32_t get_size(CPSample_ID p_id)=0;
|
||||
virtual bool is_16bits(CPSample_ID p_id)=0;
|
||||
virtual bool is_stereo(CPSample_ID p_id)=0;
|
||||
virtual bool lock_data(CPSample_ID p_id)=0;
|
||||
virtual void *get_data(CPSample_ID p_id)=0; /* 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)=0; /// Does not need locking
|
||||
virtual void set_data(CPSample_ID p_id, int p_sample, int16_t p_data,int p_channel=0)=0; /// Does not need locking
|
||||
virtual void unlock_data(CPSample_ID p_id)=0;
|
||||
|
||||
virtual void get_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len)=0;
|
||||
|
||||
CPSampleManager();
|
||||
virtual ~CPSampleManager(){}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,957 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_song.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;i<MAX_SONG_NAME;i++) {
|
||||
|
||||
|
||||
variables.name[i]=done?0:p_name[i];
|
||||
if (!done && p_name[i]==0)
|
||||
done=true;
|
||||
}
|
||||
|
||||
variables.name[MAX_SONG_NAME-1]=0; /* just in case */
|
||||
}
|
||||
|
||||
const char * CPSong::get_name() {
|
||||
|
||||
return variables.name;
|
||||
|
||||
}
|
||||
|
||||
void CPSong::set_message(const char *p_message) {
|
||||
|
||||
if (p_message==NULL) {
|
||||
variables.message[0]=0;
|
||||
return;
|
||||
}
|
||||
|
||||
bool done=false;
|
||||
for (int i=0;i<MAX_MESSAGE_LEN;i++) {
|
||||
|
||||
|
||||
variables.message[i]=done?0:p_message[i];
|
||||
if (!done && p_message[i]==0)
|
||||
done=true;
|
||||
}
|
||||
|
||||
variables.message[MAX_MESSAGE_LEN-1]=0; /* just in case */
|
||||
}
|
||||
|
||||
const char * CPSong::get_message() {
|
||||
|
||||
return variables.message;
|
||||
|
||||
}
|
||||
|
||||
void CPSong::set_row_highlight_minor(int p_hl_minor) {
|
||||
|
||||
variables.row_highlight_minor=p_hl_minor;
|
||||
}
|
||||
int CPSong::get_row_highlight_minor() {
|
||||
|
||||
return variables.row_highlight_minor;
|
||||
}
|
||||
|
||||
void CPSong::set_row_highlight_major(int p_hl_major) {
|
||||
|
||||
variables.row_highlight_major=p_hl_major;
|
||||
|
||||
|
||||
} /* 0 .. 256 */
|
||||
int CPSong::get_row_highlight_major() {
|
||||
|
||||
return variables.row_highlight_major;
|
||||
|
||||
|
||||
} /* 0 .. 256 */
|
||||
|
||||
void CPSong::set_mixing_volume(int p_mix_volume) {
|
||||
|
||||
|
||||
variables.mixing_volume=p_mix_volume;
|
||||
} /* 0 .. 128 */
|
||||
int CPSong::get_mixing_volume() {
|
||||
|
||||
return variables.mixing_volume;
|
||||
|
||||
} /* 0 .. 128 */
|
||||
|
||||
void CPSong::set_global_volume(int p_global_volume) {
|
||||
|
||||
|
||||
initial_variables.global_volume=p_global_volume;
|
||||
|
||||
} /* 0 .. 128 */
|
||||
int CPSong::get_global_volume() {
|
||||
|
||||
return initial_variables.global_volume;
|
||||
|
||||
} /* 0 .. 128 */
|
||||
|
||||
void CPSong::set_stereo_separation(int p_separation) {
|
||||
|
||||
variables.stereo_separation=p_separation;
|
||||
|
||||
} /* 0 .. 128 */
|
||||
int CPSong::get_stereo_separation() {
|
||||
|
||||
return variables.stereo_separation;
|
||||
} /* 0 .. 128 */
|
||||
|
||||
void CPSong::set_stereo(bool p_stereo) {
|
||||
|
||||
variables.use_stereo=p_stereo;
|
||||
|
||||
}
|
||||
bool CPSong::is_stereo() {
|
||||
|
||||
return variables.use_stereo;
|
||||
}
|
||||
|
||||
void CPSong::set_instruments(bool p_instruments) {
|
||||
|
||||
variables.use_instruments=p_instruments;
|
||||
|
||||
|
||||
}
|
||||
bool CPSong::has_instruments() {
|
||||
|
||||
|
||||
return variables.use_instruments;
|
||||
|
||||
}
|
||||
|
||||
void CPSong::set_linear_slides(bool p_linear_slides) {
|
||||
|
||||
variables.use_linear_slides=p_linear_slides;
|
||||
|
||||
|
||||
}
|
||||
bool CPSong::has_linear_slides() {
|
||||
|
||||
return variables.use_linear_slides;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CPSong::set_old_effects(bool p_old_effects) {
|
||||
|
||||
variables.old_effects=p_old_effects;
|
||||
|
||||
|
||||
}
|
||||
bool CPSong::has_old_effects() {
|
||||
|
||||
return variables.old_effects;
|
||||
}
|
||||
|
||||
void CPSong::set_compatible_gxx(bool p_compatible_gxx) {
|
||||
|
||||
|
||||
variables.compatible_gxx=p_compatible_gxx;
|
||||
}
|
||||
bool CPSong::has_compatible_gxx() {
|
||||
|
||||
return variables.compatible_gxx;
|
||||
|
||||
}
|
||||
|
||||
void CPSong::set_speed(int p_speed) {
|
||||
|
||||
CP_ERR_COND(p_speed<MIN_SPEED);
|
||||
CP_ERR_COND(p_speed>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_tempo<MIN_TEMPO );
|
||||
CP_ERR_COND( p_tempo>MAX_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;i<CPNote::NOTES;i++) {
|
||||
|
||||
CPSample *s=get_sample( ins->get_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;i<MAX_INSTRUMENTS;i++) {
|
||||
|
||||
|
||||
CPInstrument *ins=get_instrument(i);
|
||||
|
||||
bool empty_slot=true;
|
||||
for (int n=0;n<CPNote::NOTES;n++) {
|
||||
|
||||
if (ins->get_sample_number(n)<MAX_SAMPLES) {
|
||||
|
||||
empty_slot=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty_slot)
|
||||
continue;
|
||||
|
||||
for (int n=0;n<CPNote::NOTES;n++) {
|
||||
|
||||
ins->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;i<MAX_SAMPLES;i++) {
|
||||
|
||||
CPInstrument *ins=get_instrument( i );
|
||||
|
||||
if (!ins)
|
||||
continue;
|
||||
|
||||
ins->reset();
|
||||
|
||||
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;j<CPNote::NOTES;j++)
|
||||
ins->set_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;i<CPPattern::WIDTH;i++) {
|
||||
|
||||
initial_variables.channel[i].pan=32;
|
||||
initial_variables.channel[i].volume=CHANNEL_MAX_VOLUME;
|
||||
initial_variables.channel[i].mute=false;
|
||||
initial_variables.channel[i].surround=false;
|
||||
initial_variables.channel[i].chorus=0;
|
||||
initial_variables.channel[i].reverb=0;
|
||||
|
||||
}
|
||||
|
||||
effects.chorus.delay_ms=6;
|
||||
effects.chorus.separation_ms=3;
|
||||
effects.chorus.depth_ms10=6,
|
||||
effects.chorus.speed_hz10=5;
|
||||
effects.reverb_mode=REVERB_MODE_ROOM;
|
||||
}
|
||||
|
||||
if (p_clear_samples) {
|
||||
for (int i=0;i<MAX_SAMPLES;i++)
|
||||
get_sample(i)->reset();
|
||||
}
|
||||
|
||||
if (p_clear_instruments) {
|
||||
for (int i=0;i<MAX_INSTRUMENTS;i++)
|
||||
get_instrument(i)->reset();
|
||||
}
|
||||
|
||||
if (p_clear_patterns) {
|
||||
for (int i=0;i<MAX_PATTERNS;i++)
|
||||
get_pattern(i)->clear();
|
||||
|
||||
for (int i=0;i<MAX_ORDERS;i++)
|
||||
set_order( i, CP_ORDER_NONE );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
CPSong::ReverbMode CPSong::get_reverb_mode() {
|
||||
|
||||
return effects.reverb_mode;
|
||||
}
|
||||
void CPSong::set_reverb_mode(ReverbMode p_mode) {
|
||||
|
||||
effects.reverb_mode=p_mode;
|
||||
}
|
||||
|
||||
void CPSong::set_chorus_delay_ms(int p_amount) {
|
||||
|
||||
effects.chorus.delay_ms=p_amount;
|
||||
}
|
||||
void CPSong::set_chorus_separation_ms(int p_amount) {
|
||||
|
||||
effects.chorus.separation_ms=p_amount;
|
||||
|
||||
}
|
||||
void CPSong::set_chorus_depth_ms10(int p_amount) {
|
||||
|
||||
effects.chorus.depth_ms10=p_amount;
|
||||
|
||||
}
|
||||
void CPSong::set_chorus_speed_hz10(int p_amount) {
|
||||
|
||||
effects.chorus.speed_hz10=p_amount;
|
||||
|
||||
}
|
||||
|
||||
int CPSong::get_chorus_delay_ms() {
|
||||
|
||||
return effects.chorus.delay_ms;
|
||||
|
||||
}
|
||||
int CPSong::get_chorus_separation_ms() {
|
||||
|
||||
return effects.chorus.separation_ms;
|
||||
}
|
||||
int CPSong::get_chorus_depth_ms10() {
|
||||
|
||||
return effects.chorus.depth_ms10;
|
||||
|
||||
}
|
||||
int CPSong::get_chorus_speed_hz10() {
|
||||
|
||||
return effects.chorus.speed_hz10;
|
||||
|
||||
}
|
||||
|
||||
void CPSong::cleanup_unused_patterns() {
|
||||
|
||||
for (int i=0;i<MAX_PATTERNS;i++) {
|
||||
|
||||
bool used=false;
|
||||
if (get_pattern(i)->is_empty())
|
||||
continue;
|
||||
|
||||
for (int j=0;j<MAX_ORDERS;j++) {
|
||||
|
||||
if (get_order(j)==i) {
|
||||
used=true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!used)
|
||||
get_pattern(i)->clear();
|
||||
}
|
||||
|
||||
}
|
||||
void CPSong::cleanup_unused_instruments(){
|
||||
|
||||
if (!has_instruments())
|
||||
return;
|
||||
|
||||
bool instr_found[MAX_INSTRUMENTS];
|
||||
for (int i=0;i<MAX_INSTRUMENTS;i++)
|
||||
instr_found[i]=false;
|
||||
|
||||
for (int i=0;i<MAX_PATTERNS;i++) {
|
||||
|
||||
if (get_pattern(i)->is_empty())
|
||||
continue;
|
||||
|
||||
for (int row=0;row<get_pattern(i)->get_length();row++) {
|
||||
|
||||
|
||||
for (int col=0;col<CPPattern::WIDTH;col++) {
|
||||
|
||||
CPNote n;
|
||||
n=get_pattern(i)->get_note( col,row );
|
||||
|
||||
if (n.instrument<MAX_INSTRUMENTS)
|
||||
instr_found[n.instrument]=true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i=0;i<MAX_INSTRUMENTS;i++)
|
||||
if (!instr_found[i])
|
||||
get_instrument(i)->reset();
|
||||
|
||||
|
||||
}
|
||||
void CPSong::cleanup_unused_samples(){
|
||||
|
||||
if (!has_instruments())
|
||||
return;
|
||||
|
||||
bool sample_found[MAX_SAMPLES];
|
||||
for (int i=0;i<MAX_INSTRUMENTS;i++)
|
||||
sample_found[i]=false;
|
||||
|
||||
for (int i=0;i<MAX_PATTERNS;i++) {
|
||||
|
||||
if (get_pattern(i)->is_empty())
|
||||
continue;
|
||||
|
||||
|
||||
for (int row=0;row<get_pattern(i)->get_length();row++) {
|
||||
|
||||
|
||||
for (int col=0;col<CPPattern::WIDTH;col++) {
|
||||
|
||||
CPNote n;
|
||||
n=get_pattern(i)->get_note( col,row );
|
||||
|
||||
if (n.instrument>=MAX_SAMPLES)
|
||||
continue;
|
||||
|
||||
if (has_instruments()) {
|
||||
|
||||
for (int nt=0;nt<CPNote::NOTES;nt++) {
|
||||
|
||||
int smp=get_instrument(n.instrument)->get_sample_number(nt);
|
||||
if (smp<MAX_SAMPLES)
|
||||
sample_found[smp]=true;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (n.instrument<MAX_SAMPLES)
|
||||
sample_found[n.instrument]=true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i=0;i<MAX_SAMPLES;i++)
|
||||
if (!sample_found[i])
|
||||
get_sample(i)->reset();
|
||||
|
||||
}
|
||||
void CPSong::cleanup_unused_orders(){
|
||||
|
||||
bool finito=false;
|
||||
for (int j=0;j<MAX_ORDERS;j++) {
|
||||
|
||||
|
||||
if (get_order(j)==CP_ORDER_NONE)
|
||||
finito=true;
|
||||
if (finito)
|
||||
set_order(j,CP_ORDER_NONE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CPSong::clear_all_default_pan() {
|
||||
|
||||
for (int i=0;i<MAX_INSTRUMENTS;i++)
|
||||
get_instrument(i)->set_pan_default_enabled( false ); //die!
|
||||
|
||||
for (int i=0;i<MAX_SAMPLES;i++)
|
||||
get_sample(i)->set_pan_enabled( false ); //die!
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CPSong::clear_all_default_vol(){
|
||||
|
||||
for (int i=0;i<MAX_SAMPLES;i++)
|
||||
get_sample(i)->set_default_volume( 64 ); //die!
|
||||
for (int i=0;i<MAX_INSTRUMENTS;i++)
|
||||
get_instrument(i)->set_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 <stdio.h>
|
||||
int CPSong::get_channels_in_use() {
|
||||
|
||||
int max=0;
|
||||
|
||||
for (int p=0;p<CPSong::MAX_PATTERNS;p++) {
|
||||
|
||||
CPPattern *pat = get_pattern(p);
|
||||
if (pat->is_empty())
|
||||
continue;
|
||||
|
||||
|
||||
for (int c=(CPPattern::WIDTH-1);c>=0;c--) {
|
||||
|
||||
if (c<max)
|
||||
break;
|
||||
|
||||
bool has_note=false;
|
||||
for (int r=0;r<pat->get_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;i<MAX_SAMPLES;i++) {
|
||||
|
||||
remap[i]=-1;
|
||||
}
|
||||
|
||||
/* Find remaps */
|
||||
CPInstrument *ins=get_instrument(p_instrument);
|
||||
for (int i=0;i<CPNote::NOTES;i++) {
|
||||
|
||||
int sn = ins->get_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;j<MAX_INSTRUMENTS;j++) {
|
||||
|
||||
if (!get_instrument(j)->is_empty())
|
||||
continue;
|
||||
|
||||
printf("map to %i\n",j);
|
||||
|
||||
//copy
|
||||
*get_instrument(j)=*ins;
|
||||
|
||||
// assign samples
|
||||
for (int k=0;k<CPNote::NOTES;k++) {
|
||||
|
||||
get_instrument(j)->set_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;i<MAX_SAMPLES;i++) {
|
||||
|
||||
if (remap[i]!=-1) {
|
||||
|
||||
get_instrument(remap[i])->reset();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* remap all song */
|
||||
|
||||
for (int p=0;p<CPSong::MAX_PATTERNS;p++) {
|
||||
|
||||
CPPattern *pat = get_pattern(p);
|
||||
if (pat->is_empty())
|
||||
continue;
|
||||
|
||||
|
||||
for (int c=0;c<CPPattern::WIDTH;c++) {
|
||||
|
||||
for (int r=0;r<pat->get_length();r++) {
|
||||
|
||||
CPNote n = pat->get_note(c,r);
|
||||
if (n.note<CPNote::NOTES && n.instrument==p_instrument) {
|
||||
|
||||
int sn = ins->get_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<CPSong::MAX_ORDERS) );
|
||||
|
||||
|
||||
if (order_counter==CPSong::MAX_ORDERS) {
|
||||
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
|
||||
return baseorder;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,261 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_song.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 CPSONG_H
|
||||
#define CPSONG_H
|
||||
|
||||
|
||||
/**CPSong Class
|
||||
*@author Juan Linietsky
|
||||
*/
|
||||
|
||||
#include "cp_order.h"
|
||||
#include "cp_pattern.h"
|
||||
#include "cp_sample.h"
|
||||
#include "cp_instrument.h"
|
||||
|
||||
class CPSong {
|
||||
public:
|
||||
enum {
|
||||
MAX_SONG_NAME=26,
|
||||
MAX_ORDERS=200,
|
||||
MAX_PATTERNS=200,
|
||||
MAX_SAMPLES=99,
|
||||
MAX_INSTRUMENTS=99,
|
||||
|
||||
CHANNEL_MAX_PAN=64,
|
||||
CHANNEL_MAX_VOLUME=64,
|
||||
CHANNEL_MAX_CHORUS=64,
|
||||
CHANNEL_MAX_REVERB=64,
|
||||
|
||||
MIN_TEMPO=31,
|
||||
MAX_TEMPO=255,
|
||||
MIN_SPEED=1,
|
||||
MAX_SPEED=255,
|
||||
MAX_MESSAGE_LEN=8000,
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
private:
|
||||
CPOrder order[MAX_ORDERS];
|
||||
CPPattern pattern[MAX_PATTERNS];
|
||||
CPSample sample[MAX_SAMPLES];
|
||||
CPInstrument instrument[MAX_INSTRUMENTS];
|
||||
|
||||
|
||||
|
||||
struct Song_Variables { // variables that wont change in playback
|
||||
|
||||
char name[MAX_SONG_NAME];
|
||||
char message[MAX_MESSAGE_LEN];
|
||||
/* string message; */
|
||||
|
||||
int row_highlight_minor;
|
||||
int row_highlight_major;
|
||||
|
||||
int mixing_volume;
|
||||
int stereo_separation;
|
||||
|
||||
bool use_stereo;
|
||||
bool use_instruments;
|
||||
bool use_linear_slides;
|
||||
|
||||
bool old_effects;
|
||||
bool compatible_gxx;
|
||||
|
||||
} variables;
|
||||
|
||||
struct Initial_Variables { // Initial values used for playback
|
||||
|
||||
struct Channel_State {
|
||||
|
||||
int pan,volume; // 0-- CHANNEL_MAX_PAN, CHANNEL_MAX_VOLUME
|
||||
bool surround;
|
||||
bool mute;
|
||||
int chorus; //0 - 64
|
||||
int reverb; //0 - 64
|
||||
};
|
||||
|
||||
int global_volume;
|
||||
int speed;
|
||||
int tempo;
|
||||
|
||||
Channel_State channel[CPPattern::WIDTH];
|
||||
} initial_variables;
|
||||
|
||||
struct Effects {
|
||||
|
||||
ReverbMode reverb_mode;
|
||||
|
||||
struct Chorus {
|
||||
|
||||
int delay_ms;
|
||||
int separation_ms;
|
||||
int depth_ms10;
|
||||
int speed_hz10;
|
||||
} chorus;
|
||||
|
||||
} effects;
|
||||
|
||||
public:
|
||||
|
||||
/* Properties */
|
||||
|
||||
const char *get_name();
|
||||
void set_name(const char *p_name);
|
||||
|
||||
const char *get_message();
|
||||
void set_message(const char *p_message);
|
||||
|
||||
void set_row_highlight_minor(int p_hl_minor); /* 0 .. 256 */
|
||||
int get_row_highlight_minor(); /* 0 .. 256 */
|
||||
|
||||
void set_row_highlight_major(int p_hl_major); /* 0 .. 256 */
|
||||
int get_row_highlight_major(); /* 0 .. 256 */
|
||||
|
||||
void set_mixing_volume(int p_mix_volume); /* 0 .. 128 */
|
||||
int get_mixing_volume(); /* 0 .. 128 */
|
||||
|
||||
void set_global_volume(int p_global_volume); /* 0 .. 128 */
|
||||
int get_global_volume(); /* 0 .. 128 */
|
||||
|
||||
void set_stereo_separation(int p_separation); /* 0 .. 128 */
|
||||
int get_stereo_separation(); /* 0 .. 128 */
|
||||
|
||||
void set_stereo(bool p_stereo);
|
||||
bool is_stereo();
|
||||
|
||||
void set_instruments(bool p_instruments);
|
||||
bool has_instruments();
|
||||
|
||||
void set_linear_slides(bool p_linear_slides);
|
||||
bool has_linear_slides();
|
||||
|
||||
void set_old_effects(bool p_old_effects);
|
||||
bool has_old_effects();
|
||||
|
||||
void set_compatible_gxx(bool p_compatible_gxx);
|
||||
bool has_compatible_gxx();
|
||||
|
||||
void set_speed(int p_speed); /* 1 .. 255 */
|
||||
int get_speed(); /* 1 .. 255 */
|
||||
|
||||
void set_tempo(int p_tempo); /* 31 .. 255 */
|
||||
int get_tempo(); /* 31 .. 255 */
|
||||
|
||||
void set_channel_pan(int p_channel,int p_pan); /* 0 .. 64 */
|
||||
int get_channel_pan(int p_channel);
|
||||
|
||||
void set_channel_volume(int p_channel,int p_volume); /* 0 .. 64 */
|
||||
int get_channel_volume(int p_channel);
|
||||
|
||||
void set_channel_surround(int p_channel,bool p_surround);
|
||||
bool is_channel_surround(int p_channel);
|
||||
|
||||
void set_channel_mute(int p_channel,bool p_mute);
|
||||
bool is_channel_mute(int p_channel);
|
||||
|
||||
void set_channel_chorus(int p_channel,int p_chorus); /* 0 .. 64 */
|
||||
int get_channel_chorus(int p_channel);
|
||||
|
||||
void set_channel_reverb(int p_channel,int p_reverb); /* 0 .. 64 */
|
||||
int get_channel_reverb(int p_channel);
|
||||
|
||||
/* arrays of stuff */
|
||||
|
||||
CPPattern* get_pattern(int p_pattern);
|
||||
CPSample* get_sample(int p_sample);
|
||||
CPInstrument* get_instrument(int p_instrument);
|
||||
|
||||
int get_order(int p_position);
|
||||
void set_order(int p_position,int p_order);
|
||||
|
||||
|
||||
/* Effects */
|
||||
|
||||
ReverbMode get_reverb_mode();
|
||||
void set_reverb_mode(ReverbMode p_mode);
|
||||
|
||||
void set_chorus_delay_ms(int p_amount);
|
||||
void set_chorus_separation_ms(int p_amount);
|
||||
void set_chorus_depth_ms10(int p_amount);
|
||||
void set_chorus_speed_hz10(int p_amount);
|
||||
|
||||
int get_chorus_delay_ms();
|
||||
int get_chorus_separation_ms();
|
||||
int get_chorus_depth_ms10();
|
||||
int get_chorus_speed_hz10();
|
||||
|
||||
/* utils */
|
||||
|
||||
void reset(bool p_clear_patterns=true,bool p_clear_samples=true,bool p_clear_instruments=true,bool p_clear_variables=true);
|
||||
|
||||
void cleanup_unused_patterns();
|
||||
void cleanup_unused_instruments();
|
||||
void cleanup_unused_samples();
|
||||
void cleanup_unused_orders();
|
||||
void clear_all_default_pan();
|
||||
void clear_all_default_vol();
|
||||
|
||||
void clear_instrument_with_samples(int p_instrument);
|
||||
|
||||
void make_instruments_from_samples();
|
||||
void make_instrument_from_sample(int p_sample);
|
||||
|
||||
void separate_in_one_sample_instruments(int p_instrument);
|
||||
|
||||
int get_order_in_use_count();
|
||||
int get_pattern_in_use_count();
|
||||
int get_instrument_in_use_count();
|
||||
int get_channels_in_use();
|
||||
|
||||
CPSong();
|
||||
~CPSong();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* Some helper for something used a lot */
|
||||
|
||||
int get_song_next_order_idx(CPSong *p_song, int p_order_idx);
|
||||
|
||||
#endif
|
|
@ -1,254 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_tables.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_tables.h"
|
||||
|
||||
int32_t CPTables::linear_period_to_freq_tab[768]={
|
||||
|
||||
535232,534749,534266,533784,533303,532822,532341,531861,
|
||||
531381,530902,530423,529944,529466,528988,528511,528034,
|
||||
527558,527082,526607,526131,525657,525183,524709,524236,
|
||||
523763,523290,522818,522346,521875,521404,520934,520464,
|
||||
519994,519525,519057,518588,518121,517653,517186,516720,
|
||||
516253,515788,515322,514858,514393,513929,513465,513002,
|
||||
512539,512077,511615,511154,510692,510232,509771,509312,
|
||||
508852,508393,507934,507476,507018,506561,506104,505647,
|
||||
505191,504735,504280,503825,503371,502917,502463,502010,
|
||||
501557,501104,500652,500201,499749,499298,498848,498398,
|
||||
497948,497499,497050,496602,496154,495706,495259,494812,
|
||||
494366,493920,493474,493029,492585,492140,491696,491253,
|
||||
490809,490367,489924,489482,489041,488600,488159,487718,
|
||||
487278,486839,486400,485961,485522,485084,484647,484210,
|
||||
483773,483336,482900,482465,482029,481595,481160,480726,
|
||||
480292,479859,479426,478994,478562,478130,477699,477268,
|
||||
476837,476407,475977,475548,475119,474690,474262,473834,
|
||||
473407,472979,472553,472126,471701,471275,470850,470425,
|
||||
470001,469577,469153,468730,468307,467884,467462,467041,
|
||||
466619,466198,465778,465358,464938,464518,464099,463681,
|
||||
463262,462844,462427,462010,461593,461177,460760,460345,
|
||||
459930,459515,459100,458686,458272,457859,457446,457033,
|
||||
456621,456209,455797,455386,454975,454565,454155,453745,
|
||||
453336,452927,452518,452110,451702,451294,450887,450481,
|
||||
450074,449668,449262,448857,448452,448048,447644,447240,
|
||||
446836,446433,446030,445628,445226,444824,444423,444022,
|
||||
443622,443221,442821,442422,442023,441624,441226,440828,
|
||||
440430,440033,439636,439239,438843,438447,438051,437656,
|
||||
437261,436867,436473,436079,435686,435293,434900,434508,
|
||||
434116,433724,433333,432942,432551,432161,431771,431382,
|
||||
430992,430604,430215,429827,429439,429052,428665,428278,
|
||||
427892,427506,427120,426735,426350,425965,425581,425197,
|
||||
424813,424430,424047,423665,423283,422901,422519,422138,
|
||||
421757,421377,420997,420617,420237,419858,419479,419101,
|
||||
418723,418345,417968,417591,417214,416838,416462,416086,
|
||||
415711,415336,414961,414586,414212,413839,413465,413092,
|
||||
412720,412347,411975,411604,411232,410862,410491,410121,
|
||||
409751,409381,409012,408643,408274,407906,407538,407170,
|
||||
406803,406436,406069,405703,405337,404971,404606,404241,
|
||||
403876,403512,403148,402784,402421,402058,401695,401333,
|
||||
400970,400609,400247,399886,399525,399165,398805,398445,
|
||||
398086,397727,397368,397009,396651,396293,395936,395579,
|
||||
395222,394865,394509,394153,393798,393442,393087,392733,
|
||||
392378,392024,391671,391317,390964,390612,390259,389907,
|
||||
389556,389204,388853,388502,388152,387802,387452,387102,
|
||||
386753,386404,386056,385707,385359,385012,384664,384317,
|
||||
383971,383624,383278,382932,382587,382242,381897,381552,
|
||||
381208,380864,380521,380177,379834,379492,379149,378807,
|
||||
378466,378124,377783,377442,377102,376762,376422,376082,
|
||||
375743,375404,375065,374727,374389,374051,373714,373377,
|
||||
373040,372703,372367,372031,371695,371360,371025,370690,
|
||||
370356,370022,369688,369355,369021,368688,368356,368023,
|
||||
367691,367360,367028,366697,366366,366036,365706,365376,
|
||||
365046,364717,364388,364059,363731,363403,363075,362747,
|
||||
362420,362093,361766,361440,361114,360788,360463,360137,
|
||||
359813,359488,359164,358840,358516,358193,357869,357547,
|
||||
357224,356902,356580,356258,355937,355616,355295,354974,
|
||||
354654,354334,354014,353695,353376,353057,352739,352420,
|
||||
352103,351785,351468,351150,350834,350517,350201,349885,
|
||||
349569,349254,348939,348624,348310,347995,347682,347368,
|
||||
347055,346741,346429,346116,345804,345492,345180,344869,
|
||||
344558,344247,343936,343626,343316,343006,342697,342388,
|
||||
342079,341770,341462,341154,340846,340539,340231,339924,
|
||||
339618,339311,339005,338700,338394,338089,337784,337479,
|
||||
337175,336870,336566,336263,335959,335656,335354,335051,
|
||||
334749,334447,334145,333844,333542,333242,332941,332641,
|
||||
332341,332041,331741,331442,331143,330844,330546,330247,
|
||||
329950,329652,329355,329057,328761,328464,328168,327872,
|
||||
327576,327280,326985,326690,326395,326101,325807,325513,
|
||||
325219,324926,324633,324340,324047,323755,323463,323171,
|
||||
322879,322588,322297,322006,321716,321426,321136,320846,
|
||||
320557,320267,319978,319690,319401,319113,318825,318538,
|
||||
318250,317963,317676,317390,317103,316817,316532,316246,
|
||||
315961,315676,315391,315106,314822,314538,314254,313971,
|
||||
313688,313405,313122,312839,312557,312275,311994,311712,
|
||||
311431,311150,310869,310589,310309,310029,309749,309470,
|
||||
309190,308911,308633,308354,308076,307798,307521,307243,
|
||||
306966,306689,306412,306136,305860,305584,305308,305033,
|
||||
304758,304483,304208,303934,303659,303385,303112,302838,
|
||||
302565,302292,302019,301747,301475,301203,300931,300660,
|
||||
300388,300117,299847,299576,299306,299036,298766,298497,
|
||||
298227,297958,297689,297421,297153,296884,296617,296349,
|
||||
296082,295815,295548,295281,295015,294749,294483,294217,
|
||||
293952,293686,293421,293157,292892,292628,292364,292100,
|
||||
291837,291574,291311,291048,290785,290523,290261,289999,
|
||||
289737,289476,289215,288954,288693,288433,288173,287913,
|
||||
287653,287393,287134,286875,286616,286358,286099,285841,
|
||||
285583,285326,285068,284811,284554,284298,284041,283785,
|
||||
283529,283273,283017,282762,282507,282252,281998,281743,
|
||||
281489,281235,280981,280728,280475,280222,279969,279716,
|
||||
279464,279212,278960,278708,278457,278206,277955,277704,
|
||||
277453,277203,276953,276703,276453,276204,275955,275706,
|
||||
275457,275209,274960,274712,274465,274217,273970,273722,
|
||||
273476,273229,272982,272736,272490,272244,271999,271753,
|
||||
271508,271263,271018,270774,270530,270286,270042,269798,
|
||||
269555,269312,269069,268826,268583,268341,268099,267857
|
||||
};
|
||||
|
||||
uint16_t CPTables::old_period_table[OCTAVE*2]={
|
||||
|
||||
0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
|
||||
0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
|
||||
0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
|
||||
0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
|
||||
};
|
||||
|
||||
#define LOGFAC 2*16
|
||||
|
||||
uint16_t CPTables::log_table[104]= {
|
||||
LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,
|
||||
LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
|
||||
LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,
|
||||
LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814,
|
||||
LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,
|
||||
LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768,
|
||||
LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,
|
||||
LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725,
|
||||
LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,
|
||||
LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684,
|
||||
LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,
|
||||
LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646,
|
||||
LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,
|
||||
LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610,
|
||||
LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,
|
||||
LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575,
|
||||
LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,
|
||||
LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543,
|
||||
LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,
|
||||
LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513,
|
||||
LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,
|
||||
LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484,
|
||||
LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,
|
||||
LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457,
|
||||
LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,
|
||||
LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
|
||||
};
|
||||
|
||||
|
||||
|
||||
int32_t CPTables::get_linear_period(uint16_t note,int32_t fine) {
|
||||
|
||||
int32_t t;
|
||||
|
||||
t=(24L*OCTAVE-(int32_t)note)*32L-(fine>>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]<<shift_value;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CPTables::get_old_frequency(int32_t period) {
|
||||
|
||||
return (8363L*1712L)/(period?period:1);
|
||||
|
||||
}
|
||||
|
||||
CPTables::CPTables(){
|
||||
}
|
||||
CPTables::~CPTables(){
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* cp_tables.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 CPTABLES_H
|
||||
#define CPTABLES_H
|
||||
|
||||
#include "cp_config.h"
|
||||
|
||||
/**conversion CPTables/functions
|
||||
*@author Juan Linietsky
|
||||
*/
|
||||
|
||||
/******************************
|
||||
CPTables.h
|
||||
--------
|
||||
|
||||
CPTables methods for miscelaneous
|
||||
conversion utilities
|
||||
********************************/
|
||||
|
||||
class CPTables {
|
||||
public:
|
||||
|
||||
enum { OCTAVE=12 };
|
||||
|
||||
static uint16_t old_period_table[OCTAVE*2];
|
||||
static uint16_t log_table[104];
|
||||
static int32_t linear_period_to_freq_tab[768];
|
||||
|
||||
static int32_t get_old_period(uint16_t note,int32_t speed);
|
||||
static int32_t get_amiga_period(uint16_t note,int32_t fine);
|
||||
static int32_t get_linear_period(uint16_t note,int32_t fine);
|
||||
static int32_t get_linear_frequency(int32_t period);
|
||||
static int32_t get_old_frequency(int32_t period);
|
||||
static int32_t get_log_period(uint16_t note,int32_t p_c5freq);
|
||||
|
||||
CPTables();
|
||||
~CPTables();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,872 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* event_stream_chibi.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "event_stream_chibi.h"
|
||||
#include "cp_loader_it.h"
|
||||
#include "cp_loader_xm.h"
|
||||
#include "cp_loader_s3m.h"
|
||||
#include "cp_loader_mod.h"
|
||||
|
||||
static CPSampleManagerImpl *sample_manager;
|
||||
static ResourceFormatLoaderChibi *resource_loader;
|
||||
|
||||
CPSample_ID CPSampleManagerImpl::create(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 = memnew( SampleData );
|
||||
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;
|
||||
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=PoolVector<uint8_t>::Write();
|
||||
AudioServer::get_singleton()->sample_set_data(sd->rid,sd->lock);
|
||||
sd->lock=PoolVector<uint8_t>();
|
||||
}
|
||||
}
|
||||
|
||||
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;i<p_elements;i++) {
|
||||
p_dest[i]=f->get_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 (order<last_order) {
|
||||
if (!loop) {
|
||||
stop();
|
||||
} else {
|
||||
loops++;
|
||||
}
|
||||
}
|
||||
last_order=order;
|
||||
return false;
|
||||
}
|
||||
void EventStreamPlaybackChibi::_stop(){
|
||||
|
||||
player->play_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<EventStreamChibi> 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<EventStreamPlayback> EventStreamChibi::instance_playback() {
|
||||
|
||||
return Ref<EventStreamPlayback>( memnew(EventStreamPlaybackChibi(Ref<EventStreamChibi>(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.get_extension().to_lower();
|
||||
|
||||
CPFileAccessWrapperImpl f;
|
||||
|
||||
if (el=="it") {
|
||||
|
||||
Ref<EventStreamChibi> 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<EventStreamChibi> 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<EventStreamChibi> 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<EventStreamChibi> 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<String> *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.get_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 );
|
||||
ClassDB::register_class<EventStreamChibi>();
|
||||
ResourceLoader::add_resource_format_loader( resource_loader );
|
||||
}
|
||||
|
||||
void finalize_chibi() {
|
||||
|
||||
memdelete( sample_manager );
|
||||
memdelete( resource_loader );
|
||||
}
|
||||
|
|
@ -1,314 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* event_stream_chibi.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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;
|
||||
PoolVector<uint8_t> lock;
|
||||
PoolVector<uint8_t>::Write w;
|
||||
CPSample_Loop_Type loop_type;
|
||||
};
|
||||
|
||||
|
||||
_FORCE_INLINE_ SampleData* _getsd(CPSample_ID p_id) {
|
||||
|
||||
return ((SampleData*)p_id._private);
|
||||
}
|
||||
Set<SampleData*> 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 {
|
||||
|
||||
GDCLASS(EventStreamPlaybackChibi,EventStreamPlayback);
|
||||
|
||||
CPMixerImpl mixer;
|
||||
uint64_t total_usec;
|
||||
Ref<EventStreamChibi> 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<EventStreamChibi> p_stream=Ref<EventStreamChibi>());
|
||||
~EventStreamPlaybackChibi();
|
||||
};
|
||||
|
||||
|
||||
class EventStreamChibi : public EventStream {
|
||||
|
||||
GDCLASS(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<EventStreamPlayback> 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<String> *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
|
|
@ -1,41 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* register_types.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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();
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* register_types.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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();
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
def can_build(platform):
|
||||
return True
|
||||
# return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
def can_build(platform):
|
||||
return True
|
||||
# return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
def can_build(platform):
|
||||
return True
|
||||
# return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
def can_build(platform):
|
||||
return True
|
||||
# return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
def can_build(platform):
|
||||
return True
|
||||
# return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -199,7 +199,7 @@ int AudioDriverAndroid::get_mix_rate() const {
|
|||
return mix_rate;
|
||||
}
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverAndroid::get_output_format() const{
|
||||
AudioDriver::OutputFormat AudioDriverAndroid::get_output_format() const{
|
||||
|
||||
return OUTPUT_STEREO;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "java_glue.h"
|
||||
|
||||
class AudioDriverAndroid : public AudioDriverSW {
|
||||
class AudioDriverAndroid : public AudioDriver {
|
||||
|
||||
|
||||
static Mutex *mutex;
|
||||
|
|
|
@ -373,7 +373,7 @@ int AudioDriverOpenSL::get_mix_rate() const {
|
|||
return 44100;
|
||||
}
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverOpenSL::get_output_format() const{
|
||||
AudioDriver::OutputFormat AudioDriverOpenSL::get_output_format() const{
|
||||
|
||||
return OUTPUT_STEREO;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "SLES/OpenSLES_Android.h"
|
||||
|
||||
|
||||
class AudioDriverOpenSL : public AudioDriverSW {
|
||||
class AudioDriverOpenSL : public AudioDriver {
|
||||
|
||||
bool active;
|
||||
Mutex *mutex;
|
||||
|
|
|
@ -129,7 +129,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
|||
if (gfx_init_func)
|
||||
gfx_init_func(gfx_init_ud,use_gl2);
|
||||
|
||||
AudioDriverManagerSW::add_driver(&audio_driver_android);
|
||||
AudioDriverManager::add_driver(&audio_driver_android);
|
||||
|
||||
|
||||
RasterizerGLES2 *rasterizer_gles22=memnew( RasterizerGLES2(false,use_reload_hooks,false,use_reload_hooks ) );
|
||||
|
@ -147,9 +147,9 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
|||
visual_server->init();
|
||||
visual_server->cursor_set_visible(false, 0);
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
|
||||
|
||||
ERR_PRINT("Initializing audio failed.");
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ int AudioDriverBB10::get_mix_rate() const {
|
|||
return mix_rate;
|
||||
};
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverBB10::get_output_format() const {
|
||||
AudioDriver::OutputFormat AudioDriverBB10::get_output_format() const {
|
||||
|
||||
return output_format;
|
||||
};
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include <sys/asoundlib.h>
|
||||
|
||||
class AudioDriverBB10 : public AudioDriverSW {
|
||||
class AudioDriverBB10 : public AudioDriver {
|
||||
|
||||
Thread* thread;
|
||||
Mutex* mutex;
|
||||
|
|
|
@ -138,9 +138,9 @@ void OS_Haiku::initialize(const VideoMode& p_desired, int p_video_driver, int p_
|
|||
//physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
|
||||
physics_2d_server->init();
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init() != OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
|
||||
ERR_PRINT("Initializing audio failed.");
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ int AudioDriverIphone::get_mix_rate() const {
|
|||
return 44100;
|
||||
};
|
||||
|
||||
AudioDriverSW::OutputFormat AudioDriverIphone::get_output_format() const {
|
||||
AudioDriver::OutputFormat AudioDriverIphone::get_output_format() const {
|
||||
return OUTPUT_STEREO;
|
||||
};
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
class AudioDriverIphone : public AudioDriverSW {
|
||||
class AudioDriverIphone : public AudioDriver {
|
||||
|
||||
AudioComponentInstance audio_unit;
|
||||
bool active;
|
||||
|
|
|
@ -62,7 +62,7 @@ int AudioDriverJavaScript::get_mix_rate() const {
|
|||
|
||||
return 44100;
|
||||
}
|
||||
AudioDriverSW::OutputFormat AudioDriverJavaScript::get_output_format() const{
|
||||
AudioDriver::OutputFormat AudioDriverJavaScript::get_output_format() const{
|
||||
|
||||
return OUTPUT_STEREO;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "servers/audio/audio_server_sw.h"
|
||||
#include "os/mutex.h"
|
||||
|
||||
class AudioDriverJavaScript : public AudioDriverSW {
|
||||
class AudioDriverJavaScript : public AudioDriver {
|
||||
public:
|
||||
|
||||
void set_singleton();
|
||||
|
|
|
@ -234,7 +234,7 @@ void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int
|
|||
|
||||
print_line("Init Audio");
|
||||
|
||||
AudioDriverManagerSW::add_driver(&audio_driver_javascript);
|
||||
AudioDriverManager::add_driver(&audio_driver_javascript);
|
||||
|
||||
if (true) {
|
||||
RasterizerGLES2 *rasterizer_gles22=memnew( RasterizerGLES2(false,false,false,false) );;
|
||||
|
|
|
@ -1083,7 +1083,7 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
|
|||
|
||||
|
||||
|
||||
AudioDriverManagerSW::add_driver(&audio_driver_osx);
|
||||
AudioDriverManager::add_driver(&audio_driver_osx);
|
||||
|
||||
// only opengl support here...
|
||||
RasterizerGLES3::register_config();
|
||||
|
@ -1102,9 +1102,9 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
|
|||
visual_server->init();
|
||||
visual_server->cursor_set_visible(false, 0);
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
|
||||
|
||||
ERR_PRINT("Initializing audio failed.");
|
||||
}
|
||||
|
|
|
@ -61,9 +61,9 @@ void OS_Server::initialize(const VideoMode& p_desired,int p_video_driver,int p_a
|
|||
|
||||
//visual_server = memnew( VisualServerRaster(rasterizer) );
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
|
||||
|
||||
ERR_PRINT("Initializing audio failed.");
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ void OS_Server::run() {
|
|||
|
||||
OS_Server::OS_Server() {
|
||||
|
||||
AudioDriverManagerSW::add_driver(&driver_dummy);
|
||||
AudioDriverManager::add_driver(&driver_dummy);
|
||||
//adriver here
|
||||
grab=false;
|
||||
|
||||
|
|
|
@ -145,13 +145,13 @@ void OSUWP::set_keep_screen_on(bool p_enabled) {
|
|||
|
||||
int OSUWP::get_audio_driver_count() const {
|
||||
|
||||
return AudioDriverManagerSW::get_driver_count();
|
||||
return AudioDriverManager::get_driver_count();
|
||||
}
|
||||
const char * OSUWP::get_audio_driver_name(int p_driver) const {
|
||||
|
||||
AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver);
|
||||
AudioDriver* driver = AudioDriverManager::get_driver(p_driver);
|
||||
ERR_FAIL_COND_V( !driver, "" );
|
||||
return AudioDriverManagerSW::get_driver(p_driver)->get_name();
|
||||
return AudioDriverManager::get_driver(p_driver)->get_name();
|
||||
}
|
||||
|
||||
static MemoryPoolStatic *mempool_static=NULL;
|
||||
|
@ -288,9 +288,9 @@ void OSUWP::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio
|
|||
joypad = ref new JoypadUWP(input);
|
||||
joypad->register_events();
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
|
||||
|
||||
ERR_PRINT("Initializing audio failed.");
|
||||
}
|
||||
|
@ -971,7 +971,7 @@ OSUWP::OSUWP() {
|
|||
|
||||
mouse_mode_changed = CreateEvent(NULL, TRUE, FALSE, L"os_mouse_mode_changed");
|
||||
|
||||
AudioDriverManagerSW::add_driver(&audio_driver);
|
||||
AudioDriverManager::add_driver(&audio_driver);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -158,13 +158,13 @@ OS::VideoMode OS_Windows::get_default_video_mode() const {
|
|||
|
||||
int OS_Windows::get_audio_driver_count() const {
|
||||
|
||||
return AudioDriverManagerSW::get_driver_count();
|
||||
return AudioDriverManager::get_driver_count();
|
||||
}
|
||||
const char * OS_Windows::get_audio_driver_name(int p_driver) const {
|
||||
|
||||
AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver);
|
||||
AudioDriver* driver = AudioDriverManager::get_driver(p_driver);
|
||||
ERR_FAIL_COND_V( !driver, "" );
|
||||
return AudioDriverManagerSW::get_driver(p_driver)->get_name();
|
||||
return AudioDriverManager::get_driver(p_driver)->get_name();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1124,9 +1124,9 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
|||
input = memnew( InputDefault );
|
||||
joypad = memnew (JoypadWindows(input, &hWnd));
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
|
||||
|
||||
ERR_PRINT("Initializing audio failed.");
|
||||
}
|
||||
|
|
|
@ -82,14 +82,14 @@ OS::VideoMode OS_X11::get_default_video_mode() const {
|
|||
}
|
||||
|
||||
int OS_X11::get_audio_driver_count() const {
|
||||
return AudioDriverManagerSW::get_driver_count();
|
||||
return AudioDriverManager::get_driver_count();
|
||||
}
|
||||
|
||||
const char *OS_X11::get_audio_driver_name(int p_driver) const {
|
||||
|
||||
AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver);
|
||||
AudioDriver* driver = AudioDriverManager::get_driver(p_driver);
|
||||
ERR_FAIL_COND_V( !driver, "" );
|
||||
return AudioDriverManagerSW::get_driver(p_driver)->get_name();
|
||||
return AudioDriverManager::get_driver(p_driver)->get_name();
|
||||
}
|
||||
|
||||
void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
|
||||
|
@ -269,21 +269,21 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
|
|||
XFree(xsh);
|
||||
}
|
||||
|
||||
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
|
||||
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
|
||||
|
||||
audio_driver_index=p_audio_driver;
|
||||
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
|
||||
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
|
||||
|
||||
bool success=false;
|
||||
audio_driver_index=-1;
|
||||
for(int i=0;i<AudioDriverManagerSW::get_driver_count();i++) {
|
||||
for(int i=0;i<AudioDriverManager::get_driver_count();i++) {
|
||||
if (i==p_audio_driver)
|
||||
continue;
|
||||
AudioDriverManagerSW::get_driver(i)->set_singleton();
|
||||
if (AudioDriverManagerSW::get_driver(i)->init()==OK) {
|
||||
AudioDriverManager::get_driver(i)->set_singleton();
|
||||
if (AudioDriverManager::get_driver(i)->init()==OK) {
|
||||
success=true;
|
||||
print_line("Audio Driver Failed: "+String(AudioDriverManagerSW::get_driver(p_audio_driver)->get_name()));
|
||||
print_line("Using alternate audio driver: "+String(AudioDriverManagerSW::get_driver(i)->get_name()));
|
||||
print_line("Audio Driver Failed: "+String(AudioDriverManager::get_driver(p_audio_driver)->get_name()));
|
||||
print_line("Using alternate audio driver: "+String(AudioDriverManager::get_driver(i)->get_name()));
|
||||
audio_driver_index=i;
|
||||
break;
|
||||
}
|
||||
|
@ -294,14 +294,6 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
|
|||
|
||||
}
|
||||
|
||||
sample_manager = memnew( SampleManagerMallocSW );
|
||||
audio_server = memnew( AudioServerSW(sample_manager) );
|
||||
audio_server->init();
|
||||
spatial_sound_server = memnew( SpatialSoundServerSW );
|
||||
spatial_sound_server->init();
|
||||
spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
|
||||
spatial_sound_2d_server->init();
|
||||
|
||||
|
||||
ERR_FAIL_COND(!visual_server);
|
||||
ERR_FAIL_COND(x11_window==0);
|
||||
|
@ -469,10 +461,6 @@ void OS_X11::finalize() {
|
|||
memdelete(main_loop);
|
||||
main_loop=NULL;
|
||||
|
||||
spatial_sound_server->finish();
|
||||
memdelete(spatial_sound_server);
|
||||
spatial_sound_2d_server->finish();
|
||||
memdelete(spatial_sound_2d_server);
|
||||
|
||||
/*
|
||||
if (debugger_connection_console) {
|
||||
|
@ -485,10 +473,6 @@ void OS_X11::finalize() {
|
|||
#endif
|
||||
memdelete(input);
|
||||
|
||||
memdelete(sample_manager);
|
||||
|
||||
audio_server->finish();
|
||||
memdelete(audio_server);
|
||||
|
||||
visual_server->finish();
|
||||
memdelete(visual_server);
|
||||
|
@ -1984,20 +1968,20 @@ void OS_X11::set_context(int p_context) {
|
|||
OS_X11::OS_X11() {
|
||||
|
||||
#ifdef RTAUDIO_ENABLED
|
||||
AudioDriverManagerSW::add_driver(&driver_rtaudio);
|
||||
AudioDriverManager::add_driver(&driver_rtaudio);
|
||||
#endif
|
||||
|
||||
#ifdef PULSEAUDIO_ENABLED
|
||||
AudioDriverManagerSW::add_driver(&driver_pulseaudio);
|
||||
AudioDriverManager::add_driver(&driver_pulseaudio);
|
||||
#endif
|
||||
|
||||
#ifdef ALSA_ENABLED
|
||||
AudioDriverManagerSW::add_driver(&driver_alsa);
|
||||
AudioDriverManager::add_driver(&driver_alsa);
|
||||
#endif
|
||||
|
||||
if(AudioDriverManagerSW::get_driver_count() == 0){
|
||||
if(AudioDriverManager::get_driver_count() == 0){
|
||||
WARN_PRINT("No sound driver found... Defaulting to dummy driver");
|
||||
AudioDriverManagerSW::add_driver(&driver_dummy);
|
||||
AudioDriverManager::add_driver(&driver_dummy);
|
||||
}
|
||||
|
||||
minimized = false;
|
||||
|
|
|
@ -37,10 +37,7 @@
|
|||
//#include "servers/visual/visual_server_wrap_mt.h"
|
||||
#include "servers/visual/rasterizer.h"
|
||||
#include "servers/physics_server.h"
|
||||
#include "servers/audio/audio_server_sw.h"
|
||||
#include "servers/audio/sample_manager_sw.h"
|
||||
#include "servers/spatial_sound/spatial_sound_server_sw.h"
|
||||
#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "drivers/rtaudio/audio_driver_rtaudio.h"
|
||||
#include "drivers/alsa/audio_driver_alsa.h"
|
||||
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
|
||||
|
@ -135,11 +132,6 @@ class OS_X11 : public OS_Unix {
|
|||
virtual void delete_main_loop();
|
||||
IP_Unix *ip_unix;
|
||||
|
||||
AudioServerSW *audio_server;
|
||||
SampleManagerMallocSW *sample_manager;
|
||||
SpatialSoundServerSW *spatial_sound_server;
|
||||
SpatialSound2DServerSW *spatial_sound_2d_server;
|
||||
|
||||
bool force_quit;
|
||||
bool minimized;
|
||||
|
||||
|
|
|
@ -1,263 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* sample_player_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "sample_player_2d.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
|
||||
|
||||
bool SamplePlayer2D::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="play/play") {
|
||||
if (library.is_valid()) {
|
||||
|
||||
String what=p_value;
|
||||
if (what=="")
|
||||
stop_all();
|
||||
else
|
||||
play(what);
|
||||
|
||||
played_back=what;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SamplePlayer2D::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="play/play") {
|
||||
r_ret=played_back;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SamplePlayer2D::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
String en="";
|
||||
if (library.is_valid()) {
|
||||
List<StringName> samples;
|
||||
Ref<SampleLibrary> ncl=library;
|
||||
ncl->get_sample_list(&samples);
|
||||
for (List<StringName>::Element *E=samples.front();E;E=E->next()) {
|
||||
|
||||
en+=",";
|
||||
en+=E->get();
|
||||
}
|
||||
}
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::STRING, "play/play", PROPERTY_HINT_ENUM, en,PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_ANIMATE_AS_TRIGGER));
|
||||
}
|
||||
|
||||
void SamplePlayer2D::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony);
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::set_sample_library(const Ref<SampleLibrary>& p_library) {
|
||||
|
||||
library=p_library;
|
||||
_change_notify();
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
Ref<SampleLibrary> SamplePlayer2D::get_sample_library() const {
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
void SamplePlayer2D::set_polyphony(int p_voice_count) {
|
||||
|
||||
ERR_FAIL_COND(p_voice_count<0 || p_voice_count>64);
|
||||
polyphony=p_voice_count;
|
||||
if (get_source_rid().is_valid())
|
||||
SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony);
|
||||
|
||||
}
|
||||
|
||||
int SamplePlayer2D::get_polyphony() const {
|
||||
|
||||
return polyphony;
|
||||
}
|
||||
|
||||
SamplePlayer2D::VoiceID SamplePlayer2D::play(const String& p_sample,int p_voice) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return INVALID_VOICE;
|
||||
if (library.is_null())
|
||||
return INVALID_VOICE;
|
||||
if (!library->has_sample(p_sample))
|
||||
return INVALID_VOICE;
|
||||
Ref<Sample> sample = library->get_sample(p_sample);
|
||||
float vol_change = library->sample_get_volume_db(p_sample);
|
||||
float pitch_change = library->sample_get_pitch_scale(p_sample);
|
||||
|
||||
VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(),sample->get_rid(),sample->get_mix_rate()*pitch_change,p_voice);
|
||||
if (vol_change)
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(),vid,vol_change);
|
||||
|
||||
|
||||
if (random_pitch_scale) {
|
||||
float ps = Math::random(-random_pitch_scale,random_pitch_scale);
|
||||
if (ps>0)
|
||||
ps=1.0+ps;
|
||||
else
|
||||
ps=1.0/(1.0-ps);
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(),vid,ps*pitch_change);
|
||||
|
||||
}
|
||||
|
||||
return vid;
|
||||
}
|
||||
//voices
|
||||
void SamplePlayer2D::voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(),p_voice,p_pitch_scale);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(),p_voice,p_volume_db);
|
||||
|
||||
}
|
||||
|
||||
bool SamplePlayer2D::is_voice_active(VoiceID p_voice) const {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return false;
|
||||
return SpatialSound2DServer::get_singleton()->source_is_voice_active(get_source_rid(),p_voice);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::stop_voice(VoiceID p_voice) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
SpatialSound2DServer::get_singleton()->source_stop_voice(get_source_rid(),p_voice);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::stop_all() {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
|
||||
for(int i=0;i<polyphony;i++) {
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_stop_voice(get_source_rid(),i);
|
||||
}
|
||||
}
|
||||
|
||||
void SamplePlayer2D::set_random_pitch_scale(float p_scale) {
|
||||
random_pitch_scale=p_scale;
|
||||
}
|
||||
|
||||
float SamplePlayer2D::get_random_pitch_scale() const {
|
||||
|
||||
return random_pitch_scale;
|
||||
}
|
||||
|
||||
String SamplePlayer2D::get_configuration_warning() const {
|
||||
|
||||
if (library.is_null()) {
|
||||
return TTR("A SampleLibrary resource must be created or set in the 'samples' property in order for SamplePlayer to play sound.");
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
void SamplePlayer2D::_bind_methods() {
|
||||
|
||||
|
||||
ClassDB::bind_method(_MD("set_sample_library","library:SampleLibrary"),&SamplePlayer2D::set_sample_library);
|
||||
ClassDB::bind_method(_MD("get_sample_library:SampleLibrary"),&SamplePlayer2D::get_sample_library);
|
||||
|
||||
ClassDB::bind_method(_MD("set_polyphony","max_voices"),&SamplePlayer2D::set_polyphony);
|
||||
ClassDB::bind_method(_MD("get_polyphony"),&SamplePlayer2D::get_polyphony);
|
||||
|
||||
ClassDB::bind_method(_MD("play","sample","voice"),&SamplePlayer2D::play,DEFVAL(NEXT_VOICE));
|
||||
//voices,DEV
|
||||
ClassDB::bind_method(_MD("voice_set_pitch_scale","voice","ratio"),&SamplePlayer2D::voice_set_pitch_scale);
|
||||
ClassDB::bind_method(_MD("voice_set_volume_scale_db","voice","db"),&SamplePlayer2D::voice_set_volume_scale_db);
|
||||
|
||||
ClassDB::bind_method(_MD("is_voice_active","voice"),&SamplePlayer2D::is_voice_active);
|
||||
ClassDB::bind_method(_MD("stop_voice","voice"),&SamplePlayer2D::stop_voice);
|
||||
ClassDB::bind_method(_MD("stop_all"),&SamplePlayer2D::stop_all);
|
||||
|
||||
ClassDB::bind_method(_MD("set_random_pitch_scale","val"),&SamplePlayer2D::set_random_pitch_scale);
|
||||
ClassDB::bind_method(_MD("get_random_pitch_scale"),&SamplePlayer2D::get_random_pitch_scale);
|
||||
|
||||
BIND_CONSTANT( INVALID_VOICE );
|
||||
BIND_CONSTANT( NEXT_VOICE );
|
||||
|
||||
ADD_GROUP("Config","");
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "polyphony", PROPERTY_HINT_RANGE, "1,64,1"),_SCS("set_polyphony"),_SCS("get_polyphony"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "samples", PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_sample_library"),_SCS("get_sample_library"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "pitch_random", PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_random_pitch_scale"),_SCS("get_random_pitch_scale"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
SamplePlayer2D::SamplePlayer2D() {
|
||||
|
||||
polyphony=1;
|
||||
random_pitch_scale=0;
|
||||
|
||||
}
|
||||
|
||||
SamplePlayer2D::~SamplePlayer2D() {
|
||||
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* sample_player_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 SAMPLE_PLAYER_2D_H
|
||||
#define SAMPLE_PLAYER_2D_H
|
||||
|
||||
#include "scene/2d/sound_player_2d.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
|
||||
class SamplePlayer2D : public SoundPlayer2D {
|
||||
|
||||
GDCLASS(SamplePlayer2D,SoundPlayer2D);
|
||||
public:
|
||||
|
||||
enum {
|
||||
|
||||
INVALID_VOICE=SpatialSoundServer::SOURCE_INVALID_VOICE,
|
||||
NEXT_VOICE=SpatialSoundServer::SOURCE_NEXT_VOICE
|
||||
};
|
||||
|
||||
typedef int VoiceID;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Ref<SampleLibrary> library;
|
||||
int polyphony;
|
||||
String played_back;
|
||||
float random_pitch_scale;
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_sample_library(const Ref<SampleLibrary>& p_library);
|
||||
Ref<SampleLibrary> get_sample_library() const;
|
||||
|
||||
void set_polyphony(int p_voice_count);
|
||||
int get_polyphony() const;
|
||||
|
||||
VoiceID play(const String& p_sample,int p_voice=NEXT_VOICE);
|
||||
//voices
|
||||
void voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale);
|
||||
void voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db);
|
||||
|
||||
bool is_voice_active(VoiceID p_voice) const;
|
||||
void stop_voice(VoiceID p_voice);
|
||||
void stop_all();
|
||||
|
||||
void set_random_pitch_scale(float p_scale);
|
||||
float get_random_pitch_scale() const;
|
||||
|
||||
String get_configuration_warning() const;
|
||||
|
||||
SamplePlayer2D();
|
||||
~SamplePlayer2D();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // SAMPLE_PLAYER_2D_H
|
|
@ -1,125 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* sound_player_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "sound_player_2d.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
#include "servers/spatial_sound_2d_server.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
|
||||
void SoundPlayer2D::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
//find the sound space
|
||||
|
||||
source_rid = SpatialSound2DServer::get_singleton()->source_create(get_world_2d()->get_sound_space());
|
||||
|
||||
for(int i=0;i<PARAM_MAX;i++)
|
||||
set_param(Param(i),params[i]);
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_set_transform(source_rid,get_global_transform());
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_set_transform(source_rid,get_global_transform());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
|
||||
if (source_rid.is_valid())
|
||||
SpatialSound2DServer::get_singleton()->free(source_rid);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SoundPlayer2D::set_param( Param p_param, float p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_param,PARAM_MAX);
|
||||
params[p_param]=p_value;
|
||||
if (source_rid.is_valid())
|
||||
SpatialSound2DServer::get_singleton()->source_set_param(source_rid,(SpatialSound2DServer::SourceParam)p_param,p_value);
|
||||
|
||||
}
|
||||
|
||||
float SoundPlayer2D::get_param( Param p_param) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0);
|
||||
return params[p_param];
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SoundPlayer2D::_bind_methods() {
|
||||
|
||||
|
||||
ClassDB::bind_method(_MD("set_param","param","value"),&SoundPlayer2D::set_param);
|
||||
ClassDB::bind_method(_MD("get_param","param"),&SoundPlayer2D::get_param);
|
||||
|
||||
BIND_CONSTANT( PARAM_VOLUME_DB );
|
||||
BIND_CONSTANT( PARAM_PITCH_SCALE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_MIN_DISTANCE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_MAX_DISTANCE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_DISTANCE_EXP );
|
||||
BIND_CONSTANT( PARAM_MAX );
|
||||
|
||||
ADD_GROUP("Parameters","");
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "volume_db",PROPERTY_HINT_RANGE, "-80,24,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_VOLUME_DB);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "pitch_scale",PROPERTY_HINT_RANGE, "0.001,32,0.001"),_SCS("set_param"),_SCS("get_param"),PARAM_PITCH_SCALE);
|
||||
ADD_GROUP("Attenuation","attenuation_");
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "attenuation_min_distance",PROPERTY_HINT_EXP_RANGE, "16,16384,1"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_MIN_DISTANCE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "attenuation_max_distance",PROPERTY_HINT_EXP_RANGE, "16,16384,1"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_MAX_DISTANCE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "attenuation_distance_exp",PROPERTY_HINT_EXP_EASING, "attenuation"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_DISTANCE_EXP);
|
||||
|
||||
}
|
||||
|
||||
|
||||
SoundPlayer2D::SoundPlayer2D() {
|
||||
|
||||
params[PARAM_VOLUME_DB]=0.0;
|
||||
params[PARAM_PITCH_SCALE]=1.0;
|
||||
params[PARAM_ATTENUATION_MIN_DISTANCE]=1;
|
||||
params[PARAM_ATTENUATION_MAX_DISTANCE]=2048;
|
||||
params[PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good)
|
||||
|
||||
set_notify_transform(true);
|
||||
}
|
||||
|
||||
SoundPlayer2D::~SoundPlayer2D() {
|
||||
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* sound_player_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 SOUND_PLAYER_2D_H
|
||||
#define SOUND_PLAYER_2D_H
|
||||
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
#include "servers/spatial_sound_2d_server.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
class SoundPlayer2D : public Node2D {
|
||||
|
||||
GDCLASS(SoundPlayer2D,Node2D);
|
||||
public:
|
||||
|
||||
|
||||
enum Param {
|
||||
|
||||
PARAM_VOLUME_DB=SpatialSound2DServer::SOURCE_PARAM_VOLUME_DB,
|
||||
PARAM_PITCH_SCALE=SpatialSound2DServer::SOURCE_PARAM_PITCH_SCALE,
|
||||
PARAM_ATTENUATION_MIN_DISTANCE=SpatialSound2DServer::SOURCE_PARAM_ATTENUATION_MIN_DISTANCE,
|
||||
PARAM_ATTENUATION_MAX_DISTANCE=SpatialSound2DServer::SOURCE_PARAM_ATTENUATION_MAX_DISTANCE,
|
||||
PARAM_ATTENUATION_DISTANCE_EXP=SpatialSound2DServer::SOURCE_PARAM_ATTENUATION_DISTANCE_EXP,
|
||||
PARAM_MAX=SpatialSound2DServer::SOURCE_PARAM_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
float params[PARAM_MAX];
|
||||
RID source_rid;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
_FORCE_INLINE_ RID get_source_rid() const { return source_rid; }
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_param( Param p_param, float p_value);
|
||||
float get_param( Param p_param) const;
|
||||
|
||||
|
||||
SoundPlayer2D();
|
||||
~SoundPlayer2D();
|
||||
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SoundPlayer2D::Param );
|
||||
|
||||
#endif // SOUND_PLAYER_2D_H
|
|
@ -56,17 +56,11 @@ void Room::_notification(int p_what) {
|
|||
}
|
||||
|
||||
|
||||
if (sound_enabled)
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,get_world()->get_sound_space());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
SpatialSoundServer::get_singleton()->room_set_transform(sound_room,get_global_transform());
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
|
||||
if (sound_enabled)
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,RID());
|
||||
|
||||
|
||||
} break;
|
||||
|
@ -158,39 +152,12 @@ void Room::_parse_node_faces(PoolVector<Face3> &all_faces,const Node *p_node) co
|
|||
|
||||
|
||||
|
||||
void Room::set_simulate_acoustics(bool p_enable) {
|
||||
|
||||
if (sound_enabled==p_enable)
|
||||
return;
|
||||
|
||||
sound_enabled=p_enable;
|
||||
if (!is_inside_world())
|
||||
return; //nothing to do
|
||||
|
||||
if (sound_enabled)
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,get_world()->get_sound_space());
|
||||
else
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,RID());
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Room::_bounds_changed() {
|
||||
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
bool Room::is_simulating_acoustics() const {
|
||||
|
||||
return sound_enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RID Room::get_sound_room() const {
|
||||
|
||||
return RID();
|
||||
}
|
||||
|
||||
void Room::_bind_methods() {
|
||||
|
||||
|
@ -198,21 +165,14 @@ void Room::_bind_methods() {
|
|||
ClassDB::bind_method(_MD("get_room:Room"),&Room::get_room );
|
||||
|
||||
|
||||
|
||||
ClassDB::bind_method(_MD("set_simulate_acoustics","enable"),&Room::set_simulate_acoustics );
|
||||
ClassDB::bind_method(_MD("is_simulating_acoustics"),&Room::is_simulating_acoustics );
|
||||
|
||||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "room/room", PROPERTY_HINT_RESOURCE_TYPE, "Area" ), _SCS("set_room"), _SCS("get_room") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "room/simulate_acoustics"), _SCS("set_simulate_acoustics"), _SCS("is_simulating_acoustics") );
|
||||
|
||||
}
|
||||
|
||||
|
||||
Room::Room() {
|
||||
|
||||
sound_enabled=false;
|
||||
sound_room=SpatialSoundServer::get_singleton()->room_create();
|
||||
// sound_enabled=false;
|
||||
|
||||
level=0;
|
||||
|
||||
|
@ -222,6 +182,6 @@ Room::Room() {
|
|||
|
||||
Room::~Room() {
|
||||
|
||||
SpatialSoundServer::get_singleton()->free(sound_room);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/room.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
@ -58,9 +58,6 @@ public:
|
|||
private:
|
||||
Ref<RoomBounds> room;
|
||||
|
||||
RID sound_room;
|
||||
|
||||
bool sound_enabled;
|
||||
|
||||
int level;
|
||||
void _parse_node_faces(PoolVector<Face3> &all_faces,const Node *p_node) const;
|
||||
|
@ -88,11 +85,6 @@ public:
|
|||
void set_room( const Ref<RoomBounds>& p_room );
|
||||
Ref<RoomBounds> get_room() const;
|
||||
|
||||
void set_simulate_acoustics(bool p_enable);
|
||||
bool is_simulating_acoustics() const;
|
||||
|
||||
|
||||
RID get_sound_room() const;
|
||||
|
||||
Room();
|
||||
~Room();
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* spatial_player.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "spatial_player.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
#include "camera.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
|
||||
void SpatialPlayer::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
//find the sound space
|
||||
|
||||
source_rid = SpatialSoundServer::get_singleton()->source_create(get_world()->get_sound_space());
|
||||
for(int i=0;i<PARAM_MAX;i++)
|
||||
set_param(Param(i),params[i]);
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
SpatialSoundServer::get_singleton()->source_set_transform(source_rid,get_global_transform());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
|
||||
if (source_rid.is_valid())
|
||||
SpatialSoundServer::get_singleton()->free(source_rid);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SpatialPlayer::set_param( Param p_param, float p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_param,PARAM_MAX);
|
||||
params[p_param]=p_value;
|
||||
if (p_param==PARAM_EMISSION_CONE_DEGREES) {
|
||||
update_gizmo();
|
||||
}
|
||||
if (source_rid.is_valid())
|
||||
SpatialSoundServer::get_singleton()->source_set_param(source_rid,(SpatialSoundServer::SourceParam)p_param,p_value);
|
||||
|
||||
}
|
||||
|
||||
float SpatialPlayer::get_param( Param p_param) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0);
|
||||
return params[p_param];
|
||||
|
||||
}
|
||||
|
||||
bool SpatialPlayer::_can_gizmo_scale() const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpatialPlayer::_bind_methods() {
|
||||
|
||||
|
||||
ClassDB::bind_method(_MD("set_param","param","value"),&SpatialPlayer::set_param);
|
||||
ClassDB::bind_method(_MD("get_param","param"),&SpatialPlayer::get_param);
|
||||
|
||||
BIND_CONSTANT( PARAM_VOLUME_DB );
|
||||
BIND_CONSTANT( PARAM_PITCH_SCALE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_MIN_DISTANCE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_MAX_DISTANCE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_DISTANCE_EXP );
|
||||
BIND_CONSTANT( PARAM_EMISSION_CONE_DEGREES );
|
||||
BIND_CONSTANT( PARAM_EMISSION_CONE_ATTENUATION_DB );
|
||||
BIND_CONSTANT( PARAM_MAX );
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "volume_db",PROPERTY_HINT_RANGE, "-80,24,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_VOLUME_DB);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "pitch_scale",PROPERTY_HINT_RANGE, "0.001,32,0.001"),_SCS("set_param"),_SCS("get_param"),PARAM_PITCH_SCALE);
|
||||
ADD_GROUP("Attenuation","attenuation_");
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "attenuation_min_distance",PROPERTY_HINT_RANGE, "0.01,4096,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_MIN_DISTANCE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "attenuation_max_distance",PROPERTY_HINT_RANGE, "0.01,4096,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_MAX_DISTANCE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "attenuation_distance_exp",PROPERTY_HINT_EXP_EASING, "attenuation"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_DISTANCE_EXP);
|
||||
ADD_GROUP("Emission Cone","emission_cone_");
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "emission_cone_degrees",PROPERTY_HINT_RANGE, "0,180,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_EMISSION_CONE_DEGREES);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "emission_cone_attenuation_db",PROPERTY_HINT_RANGE, "-80,24,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_EMISSION_CONE_ATTENUATION_DB);
|
||||
|
||||
}
|
||||
|
||||
|
||||
SpatialPlayer::SpatialPlayer() {
|
||||
|
||||
params[PARAM_VOLUME_DB]=0.0;
|
||||
params[PARAM_PITCH_SCALE]=1.0;
|
||||
params[PARAM_ATTENUATION_MIN_DISTANCE]=1;
|
||||
params[PARAM_ATTENUATION_MAX_DISTANCE]=100;
|
||||
params[PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good)
|
||||
params[PARAM_EMISSION_CONE_DEGREES]=180.0; //cone disabled
|
||||
params[PARAM_EMISSION_CONE_ATTENUATION_DB]=-6.0; //minus 6 db attenuation
|
||||
set_notify_transform(true);
|
||||
|
||||
}
|
||||
|
||||
SpatialPlayer::~SpatialPlayer() {
|
||||
|
||||
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* spatial_player.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 SPATIAL_PLAYER_H
|
||||
#define SPATIAL_PLAYER_H
|
||||
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
class SpatialPlayer : public Spatial {
|
||||
|
||||
GDCLASS(SpatialPlayer,Spatial);
|
||||
public:
|
||||
|
||||
|
||||
enum Param {
|
||||
|
||||
PARAM_VOLUME_DB=SpatialSoundServer::SOURCE_PARAM_VOLUME_DB,
|
||||
PARAM_PITCH_SCALE=SpatialSoundServer::SOURCE_PARAM_PITCH_SCALE,
|
||||
PARAM_ATTENUATION_MIN_DISTANCE=SpatialSoundServer::SOURCE_PARAM_ATTENUATION_MIN_DISTANCE,
|
||||
PARAM_ATTENUATION_MAX_DISTANCE=SpatialSoundServer::SOURCE_PARAM_ATTENUATION_MAX_DISTANCE,
|
||||
PARAM_ATTENUATION_DISTANCE_EXP=SpatialSoundServer::SOURCE_PARAM_ATTENUATION_DISTANCE_EXP,
|
||||
PARAM_EMISSION_CONE_DEGREES=SpatialSoundServer::SOURCE_PARAM_EMISSION_CONE_DEGREES,
|
||||
PARAM_EMISSION_CONE_ATTENUATION_DB=SpatialSoundServer::SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB,
|
||||
PARAM_MAX=SpatialSoundServer::SOURCE_PARAM_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
float params[PARAM_MAX];
|
||||
RID source_rid;
|
||||
|
||||
virtual bool _can_gizmo_scale() const;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
_FORCE_INLINE_ RID get_source_rid() const { return source_rid; }
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_param( Param p_param, float p_value);
|
||||
float get_param( Param p_param) const;
|
||||
|
||||
|
||||
SpatialPlayer();
|
||||
~SpatialPlayer();
|
||||
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( SpatialPlayer::Param );
|
||||
#endif // SPATIAL_PLAYER_H
|
|
@ -1,241 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* spatial_sample_player.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "spatial_sample_player.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
#include "camera.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
bool SpatialSamplePlayer::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name==SceneStringNames::get_singleton()->play_play) {
|
||||
if (library.is_valid()) {
|
||||
|
||||
String what=p_value;
|
||||
if (what=="")
|
||||
stop_all();
|
||||
else
|
||||
play(what);
|
||||
|
||||
played_back=what;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpatialSamplePlayer::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name==SceneStringNames::get_singleton()->play_play) {
|
||||
r_ret=played_back;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpatialSamplePlayer::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
String en="";
|
||||
if (library.is_valid()) {
|
||||
List<StringName> samples;
|
||||
Ref<SampleLibrary> ncl=library;
|
||||
ncl->get_sample_list(&samples);
|
||||
for (List<StringName>::Element *E=samples.front();E;E=E->next()) {
|
||||
|
||||
en+=",";
|
||||
en+=E->get();
|
||||
}
|
||||
}
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::STRING, "play/play", PROPERTY_HINT_ENUM, en,PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_ANIMATE_AS_TRIGGER));
|
||||
|
||||
}
|
||||
void SpatialSamplePlayer::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
|
||||
SpatialSoundServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony);
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SpatialSamplePlayer::set_sample_library(const Ref<SampleLibrary>& p_library) {
|
||||
|
||||
library=p_library;
|
||||
_change_notify();
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
Ref<SampleLibrary> SpatialSamplePlayer::get_sample_library() const {
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
void SpatialSamplePlayer::set_polyphony(int p_voice_count) {
|
||||
|
||||
ERR_FAIL_COND(p_voice_count<0 || p_voice_count>64);
|
||||
polyphony=p_voice_count;
|
||||
if (get_source_rid().is_valid())
|
||||
SpatialSoundServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony);
|
||||
|
||||
}
|
||||
|
||||
int SpatialSamplePlayer::get_polyphony() const {
|
||||
|
||||
return polyphony;
|
||||
}
|
||||
|
||||
SpatialSamplePlayer::VoiceID SpatialSamplePlayer::play(const String& p_sample,int p_voice) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return INVALID_VOICE;
|
||||
if (library.is_null())
|
||||
return INVALID_VOICE;
|
||||
if (!library->has_sample(p_sample))
|
||||
return INVALID_VOICE;
|
||||
Ref<Sample> sample = library->get_sample(p_sample);
|
||||
float vol_change = library->sample_get_volume_db(p_sample);
|
||||
float pitch_change = library->sample_get_pitch_scale(p_sample);
|
||||
|
||||
VoiceID vid = SpatialSoundServer::get_singleton()->source_play_sample(get_source_rid(),sample->get_rid(),sample->get_mix_rate()*pitch_change,p_voice);
|
||||
if (vol_change)
|
||||
SpatialSoundServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(),vid,vol_change);
|
||||
|
||||
return vid;
|
||||
|
||||
|
||||
}
|
||||
//voices
|
||||
void SpatialSamplePlayer::voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
|
||||
SpatialSoundServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(),p_voice,p_pitch_scale);
|
||||
|
||||
}
|
||||
|
||||
void SpatialSamplePlayer::voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
SpatialSoundServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(),p_voice,p_volume_db);
|
||||
|
||||
}
|
||||
|
||||
bool SpatialSamplePlayer::is_voice_active(VoiceID p_voice) const {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return false;
|
||||
return SpatialSoundServer::get_singleton()->source_is_voice_active(get_source_rid(),p_voice);
|
||||
|
||||
}
|
||||
|
||||
void SpatialSamplePlayer::stop_voice(VoiceID p_voice) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
SpatialSoundServer::get_singleton()->source_stop_voice(get_source_rid(),p_voice);
|
||||
|
||||
}
|
||||
|
||||
void SpatialSamplePlayer::stop_all() {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
|
||||
for(int i=0;i<polyphony;i++) {
|
||||
|
||||
SpatialSoundServer::get_singleton()->source_stop_voice(get_source_rid(),i);
|
||||
}
|
||||
}
|
||||
|
||||
String SpatialSamplePlayer::get_configuration_warning() const {
|
||||
|
||||
if (library.is_null()) {
|
||||
return TTR("A SampleLibrary resource must be created or set in the 'samples' property in order for SpatialSamplePlayer to play sound.");
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
|
||||
void SpatialSamplePlayer::_bind_methods() {
|
||||
|
||||
|
||||
ClassDB::bind_method(_MD("set_sample_library","library:SampleLibrary"),&SpatialSamplePlayer::set_sample_library);
|
||||
ClassDB::bind_method(_MD("get_sample_library:SampleLibrary"),&SpatialSamplePlayer::get_sample_library);
|
||||
|
||||
ClassDB::bind_method(_MD("set_polyphony","voices"),&SpatialSamplePlayer::set_polyphony);
|
||||
ClassDB::bind_method(_MD("get_polyphony"),&SpatialSamplePlayer::get_polyphony);
|
||||
|
||||
ClassDB::bind_method(_MD("play","sample","voice"),&SpatialSamplePlayer::play,DEFVAL(NEXT_VOICE));
|
||||
//voices,DEV
|
||||
ClassDB::bind_method(_MD("voice_set_pitch_scale","voice","ratio"),&SpatialSamplePlayer::voice_set_pitch_scale);
|
||||
ClassDB::bind_method(_MD("voice_set_volume_scale_db","voice","db"),&SpatialSamplePlayer::voice_set_volume_scale_db);
|
||||
|
||||
ClassDB::bind_method(_MD("is_voice_active","voice"),&SpatialSamplePlayer::is_voice_active);
|
||||
ClassDB::bind_method(_MD("stop_voice","voice"),&SpatialSamplePlayer::stop_voice);
|
||||
ClassDB::bind_method(_MD("stop_all"),&SpatialSamplePlayer::stop_all);
|
||||
|
||||
BIND_CONSTANT( INVALID_VOICE );
|
||||
BIND_CONSTANT( NEXT_VOICE );
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "polyphony", PROPERTY_HINT_RANGE, "1,64,1"),_SCS("set_polyphony"),_SCS("get_polyphony"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "samples", PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_sample_library"),_SCS("get_sample_library"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
SpatialSamplePlayer::SpatialSamplePlayer() {
|
||||
|
||||
polyphony=1;
|
||||
|
||||
}
|
||||
|
||||
SpatialSamplePlayer::~SpatialSamplePlayer() {
|
||||
|
||||
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* spatial_sample_player.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 SPATIAL_SAMPLE_PLAYER_H
|
||||
#define SPATIAL_SAMPLE_PLAYER_H
|
||||
|
||||
#include "scene/3d/spatial_player.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
|
||||
class SpatialSamplePlayer : public SpatialPlayer {
|
||||
|
||||
GDCLASS(SpatialSamplePlayer,SpatialPlayer);
|
||||
public:
|
||||
|
||||
enum {
|
||||
|
||||
INVALID_VOICE=SpatialSoundServer::SOURCE_INVALID_VOICE,
|
||||
NEXT_VOICE=SpatialSoundServer::SOURCE_NEXT_VOICE
|
||||
};
|
||||
|
||||
typedef int VoiceID;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Ref<SampleLibrary> library;
|
||||
int polyphony;
|
||||
String played_back;
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_sample_library(const Ref<SampleLibrary>& p_library);
|
||||
Ref<SampleLibrary> get_sample_library() const;
|
||||
|
||||
void set_polyphony(int p_voice_count);
|
||||
int get_polyphony() const;
|
||||
|
||||
VoiceID play(const String& p_sample,int p_voice=NEXT_VOICE);
|
||||
//voices
|
||||
void voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale);
|
||||
void voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db);
|
||||
|
||||
bool is_voice_active(VoiceID p_voice) const;
|
||||
void stop_voice(VoiceID p_voice);
|
||||
void stop_all();
|
||||
|
||||
String get_configuration_warning() const;
|
||||
|
||||
SpatialSamplePlayer();
|
||||
~SpatialSamplePlayer();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // SPATIAL_SAMPLE_PLAYER_H
|
|
@ -1,407 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* spatial_stream_player.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "spatial_stream_player.h"
|
||||
|
||||
|
||||
|
||||
int SpatialStreamPlayer::InternalStream::get_channel_count() const {
|
||||
|
||||
return player->sp_get_channel_count();
|
||||
}
|
||||
void SpatialStreamPlayer::InternalStream::set_mix_rate(int p_rate){
|
||||
|
||||
return player->sp_set_mix_rate(p_rate);
|
||||
}
|
||||
bool SpatialStreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){
|
||||
|
||||
return player->sp_mix(p_buffer,p_frames);
|
||||
}
|
||||
void SpatialStreamPlayer::InternalStream::update(){
|
||||
|
||||
player->sp_update();
|
||||
}
|
||||
|
||||
|
||||
int SpatialStreamPlayer::sp_get_channel_count() const {
|
||||
|
||||
return playback->get_channels();
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::sp_set_mix_rate(int p_rate){
|
||||
|
||||
server_mix_rate=p_rate;
|
||||
}
|
||||
|
||||
bool SpatialStreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) {
|
||||
|
||||
if (resampler.is_ready() && !paused) {
|
||||
return resampler.mix(p_buffer,p_frames);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::sp_update() {
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
if (!paused && resampler.is_ready() && playback.is_valid()) {
|
||||
|
||||
if (!playback->is_playing()) {
|
||||
//stream depleted data, but there's still audio in the ringbuffer
|
||||
//check that all this audio has been flushed before stopping the stream
|
||||
int to_mix = resampler.get_total() - resampler.get_todo();
|
||||
if (to_mix==0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int todo =resampler.get_todo();
|
||||
int wrote = playback->mix(resampler.get_write_buffer(),todo);
|
||||
resampler.write(wrote);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SpatialStreamPlayer::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
||||
//set_idle_process(false); //don't annoy
|
||||
if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint())
|
||||
play();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
|
||||
stop(); //wathever it may be doing, stop
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SpatialStreamPlayer::set_stream(const Ref<AudioStream> &p_stream) {
|
||||
|
||||
stop();
|
||||
|
||||
stream=p_stream;
|
||||
|
||||
if (!stream.is_null()) {
|
||||
playback=stream->instance_playback();
|
||||
playback->set_loop(loops);
|
||||
playback->set_loop_restart_time(loop_point);
|
||||
AudioServer::get_singleton()->lock();
|
||||
resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size());
|
||||
AudioServer::get_singleton()->unlock();
|
||||
} else {
|
||||
AudioServer::get_singleton()->lock();
|
||||
resampler.clear();
|
||||
playback.unref();
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<AudioStream> SpatialStreamPlayer::get_stream() const {
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
void SpatialStreamPlayer::play(float p_from_offset) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
if (playback.is_null())
|
||||
return;
|
||||
if (playback->is_playing())
|
||||
stop();
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
playback->play(p_from_offset);
|
||||
//feed the ringbuffer as long as no update callback is going on
|
||||
sp_update();
|
||||
|
||||
SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),&internal_stream);
|
||||
|
||||
/*
|
||||
AudioServer::get_singleton()->stream_set_active(stream_rid,true);
|
||||
AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume);
|
||||
if (stream->get_update_mode()!=AudioStream::UPDATE_NONE)
|
||||
set_idle_process(true);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::stop() {
|
||||
|
||||
if (!is_inside_tree())
|
||||
return;
|
||||
if (playback.is_null())
|
||||
return;
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
//AudioServer::get_singleton()->stream_set_active(stream_rid,false);
|
||||
SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),NULL);
|
||||
playback->stop();
|
||||
resampler.flush();
|
||||
//set_idle_process(false);
|
||||
}
|
||||
|
||||
bool SpatialStreamPlayer::is_playing() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return false;
|
||||
|
||||
return playback->is_playing();
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::set_loop(bool p_enable) {
|
||||
|
||||
loops=p_enable;
|
||||
if (playback.is_null())
|
||||
return;
|
||||
playback->set_loop(loops);
|
||||
|
||||
}
|
||||
bool SpatialStreamPlayer::has_loop() const {
|
||||
|
||||
return loops;
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::set_volume(float p_vol) {
|
||||
|
||||
volume=p_vol;
|
||||
if (stream_rid.is_valid())
|
||||
AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume);
|
||||
}
|
||||
|
||||
float SpatialStreamPlayer::get_volume() const {
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::set_loop_restart_time(float p_secs) {
|
||||
|
||||
loop_point=p_secs;
|
||||
if (playback.is_valid())
|
||||
playback->set_loop_restart_time(p_secs);
|
||||
}
|
||||
|
||||
float SpatialStreamPlayer::get_loop_restart_time() const {
|
||||
|
||||
return loop_point;
|
||||
}
|
||||
|
||||
|
||||
void SpatialStreamPlayer::set_volume_db(float p_db) {
|
||||
|
||||
if (p_db<-79)
|
||||
set_volume(0);
|
||||
else
|
||||
set_volume(Math::db2linear(p_db));
|
||||
}
|
||||
|
||||
float SpatialStreamPlayer::get_volume_db() const {
|
||||
|
||||
if (volume==0)
|
||||
return -80;
|
||||
else
|
||||
return Math::linear2db(volume);
|
||||
}
|
||||
|
||||
|
||||
String SpatialStreamPlayer::get_stream_name() const {
|
||||
|
||||
if (stream.is_null())
|
||||
return "<No Stream>";
|
||||
return stream->get_name();
|
||||
|
||||
}
|
||||
|
||||
int SpatialStreamPlayer::get_loop_count() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return 0;
|
||||
return playback->get_loop_count();
|
||||
|
||||
}
|
||||
|
||||
float SpatialStreamPlayer::get_pos() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return 0;
|
||||
return playback->get_pos();
|
||||
|
||||
}
|
||||
|
||||
float SpatialStreamPlayer::get_length() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return 0;
|
||||
return playback->get_length();
|
||||
}
|
||||
void SpatialStreamPlayer::seek_pos(float p_time) {
|
||||
|
||||
if (playback.is_null())
|
||||
return;
|
||||
return playback->seek_pos(p_time);
|
||||
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::set_autoplay(bool p_enable) {
|
||||
|
||||
autoplay=p_enable;
|
||||
}
|
||||
|
||||
bool SpatialStreamPlayer::has_autoplay() const {
|
||||
|
||||
return autoplay;
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::set_paused(bool p_paused) {
|
||||
|
||||
paused=p_paused;
|
||||
/*
|
||||
if (stream.is_valid())
|
||||
stream->set_paused(p_paused);
|
||||
*/
|
||||
}
|
||||
|
||||
bool SpatialStreamPlayer::is_paused() const {
|
||||
|
||||
return paused;
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::_set_play(bool p_play) {
|
||||
|
||||
_play=p_play;
|
||||
if (is_inside_tree()) {
|
||||
if(_play)
|
||||
play();
|
||||
else
|
||||
stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool SpatialStreamPlayer::_get_play() const{
|
||||
|
||||
return _play;
|
||||
}
|
||||
|
||||
void SpatialStreamPlayer::set_buffering_msec(int p_msec) {
|
||||
|
||||
buffering_ms=p_msec;
|
||||
}
|
||||
|
||||
int SpatialStreamPlayer::get_buffering_msec() const{
|
||||
|
||||
return buffering_ms;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SpatialStreamPlayer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(_MD("set_stream","stream:AudioStream"),&SpatialStreamPlayer::set_stream);
|
||||
ClassDB::bind_method(_MD("get_stream:AudioStream"),&SpatialStreamPlayer::get_stream);
|
||||
|
||||
ClassDB::bind_method(_MD("play","offset"),&SpatialStreamPlayer::play,DEFVAL(0));
|
||||
ClassDB::bind_method(_MD("stop"),&SpatialStreamPlayer::stop);
|
||||
|
||||
ClassDB::bind_method(_MD("is_playing"),&SpatialStreamPlayer::is_playing);
|
||||
|
||||
ClassDB::bind_method(_MD("set_paused","paused"),&SpatialStreamPlayer::set_paused);
|
||||
ClassDB::bind_method(_MD("is_paused"),&SpatialStreamPlayer::is_paused);
|
||||
|
||||
ClassDB::bind_method(_MD("set_loop","enabled"),&SpatialStreamPlayer::set_loop);
|
||||
ClassDB::bind_method(_MD("has_loop"),&SpatialStreamPlayer::has_loop);
|
||||
|
||||
ClassDB::bind_method(_MD("set_volume","volume"),&SpatialStreamPlayer::set_volume);
|
||||
ClassDB::bind_method(_MD("get_volume"),&SpatialStreamPlayer::get_volume);
|
||||
|
||||
ClassDB::bind_method(_MD("set_volume_db","db"),&SpatialStreamPlayer::set_volume_db);
|
||||
ClassDB::bind_method(_MD("get_volume_db"),&SpatialStreamPlayer::get_volume_db);
|
||||
|
||||
ClassDB::bind_method(_MD("set_buffering_msec","msec"),&SpatialStreamPlayer::set_buffering_msec);
|
||||
ClassDB::bind_method(_MD("get_buffering_msec"),&SpatialStreamPlayer::get_buffering_msec);
|
||||
|
||||
ClassDB::bind_method(_MD("set_loop_restart_time","secs"),&SpatialStreamPlayer::set_loop_restart_time);
|
||||
ClassDB::bind_method(_MD("get_loop_restart_time"),&SpatialStreamPlayer::get_loop_restart_time);
|
||||
|
||||
ClassDB::bind_method(_MD("get_stream_name"),&SpatialStreamPlayer::get_stream_name);
|
||||
ClassDB::bind_method(_MD("get_loop_count"),&SpatialStreamPlayer::get_loop_count);
|
||||
|
||||
ClassDB::bind_method(_MD("get_pos"),&SpatialStreamPlayer::get_pos);
|
||||
ClassDB::bind_method(_MD("seek_pos","time"),&SpatialStreamPlayer::seek_pos);
|
||||
|
||||
ClassDB::bind_method(_MD("set_autoplay","enabled"),&SpatialStreamPlayer::set_autoplay);
|
||||
ClassDB::bind_method(_MD("has_autoplay"),&SpatialStreamPlayer::has_autoplay);
|
||||
|
||||
ClassDB::bind_method(_MD("get_length"),&SpatialStreamPlayer::get_length);
|
||||
|
||||
ClassDB::bind_method(_MD("_set_play","play"),&SpatialStreamPlayer::_set_play);
|
||||
ClassDB::bind_method(_MD("_get_play"),&SpatialStreamPlayer::_get_play);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"), _SCS("get_stream") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "play"), _SCS("_set_play"), _SCS("_get_play") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "loop"), _SCS("set_loop"), _SCS("has_loop") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "paused"), _SCS("set_paused"), _SCS("is_paused") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT, "loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT, "buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") );
|
||||
}
|
||||
|
||||
|
||||
SpatialStreamPlayer::SpatialStreamPlayer() {
|
||||
|
||||
volume=1;
|
||||
loops=false;
|
||||
paused=false;
|
||||
autoplay=false;
|
||||
_play=false;
|
||||
server_mix_rate=1;
|
||||
internal_stream.player=this;
|
||||
stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream);
|
||||
buffering_ms=500;
|
||||
loop_point=0;
|
||||
|
||||
}
|
||||
|
||||
SpatialStreamPlayer::~SpatialStreamPlayer() {
|
||||
AudioServer::get_singleton()->free(stream_rid);
|
||||
resampler.clear();
|
||||
|
||||
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* spatial_stream_player.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 SPATIAL_STREAM_PLAYER_H
|
||||
#define SPATIAL_STREAM_PLAYER_H
|
||||
|
||||
#include "scene/resources/audio_stream.h"
|
||||
#include "scene/3d/spatial_player.h"
|
||||
#include "servers/audio/audio_rb_resampler.h"
|
||||
|
||||
class SpatialStreamPlayer : public SpatialPlayer {
|
||||
|
||||
GDCLASS(SpatialStreamPlayer,SpatialPlayer);
|
||||
|
||||
_THREAD_SAFE_CLASS_
|
||||
|
||||
struct InternalStream : public AudioServer::AudioStream {
|
||||
SpatialStreamPlayer *player;
|
||||
virtual int get_channel_count() const;
|
||||
virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
|
||||
virtual bool mix(int32_t *p_buffer,int p_frames);
|
||||
virtual void update();
|
||||
};
|
||||
|
||||
|
||||
InternalStream internal_stream;
|
||||
Ref<AudioStreamPlayback> playback;
|
||||
Ref<AudioStream> stream;
|
||||
|
||||
int sp_get_channel_count() const;
|
||||
void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate
|
||||
bool sp_mix(int32_t *p_buffer,int p_frames);
|
||||
void sp_update();
|
||||
|
||||
int server_mix_rate;
|
||||
|
||||
RID stream_rid;
|
||||
bool paused;
|
||||
bool autoplay;
|
||||
bool loops;
|
||||
float volume;
|
||||
float loop_point;
|
||||
int buffering_ms;
|
||||
|
||||
AudioRBResampler resampler;
|
||||
|
||||
bool _play;
|
||||
void _set_play(bool p_play);
|
||||
bool _get_play() const;
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_stream(const Ref<AudioStream> &p_stream);
|
||||
Ref<AudioStream> get_stream() const;
|
||||
|
||||
void play(float p_from_offset=0);
|
||||
void stop();
|
||||
bool is_playing() const;
|
||||
|
||||
void set_paused(bool p_paused);
|
||||
bool is_paused() const;
|
||||
|
||||
void set_loop(bool p_enable);
|
||||
bool has_loop() const;
|
||||
|
||||
void set_volume(float p_vol);
|
||||
float get_volume() const;
|
||||
|
||||
void set_loop_restart_time(float p_secs);
|
||||
float get_loop_restart_time() const;
|
||||
|
||||
void set_volume_db(float p_db);
|
||||
float get_volume_db() const;
|
||||
|
||||
String get_stream_name() const;
|
||||
|
||||
int get_loop_count() const;
|
||||
|
||||
float get_pos() const;
|
||||
void seek_pos(float p_time);
|
||||
float get_length() const;
|
||||
void set_autoplay(bool p_vol);
|
||||
bool has_autoplay() const;
|
||||
|
||||
void set_buffering_msec(int p_msec);
|
||||
int get_buffering_msec() const;
|
||||
|
||||
SpatialStreamPlayer();
|
||||
~SpatialStreamPlayer();
|
||||
};
|
||||
|
||||
#endif // SPATIAL_STREAM_PLAYER_H
|
|
@ -1,357 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* event_player.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "event_player.h"
|
||||
|
||||
|
||||
void EventPlayer::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
||||
//set_idle_process(false); //don't annoy
|
||||
if (playback.is_valid() && autoplay && !get_tree()->is_editor_hint())
|
||||
play();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
|
||||
stop(); //wathever it may be doing, stop
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EventPlayer::set_stream(const Ref<EventStream> &p_stream) {
|
||||
|
||||
stop();
|
||||
stream=p_stream;
|
||||
if (stream.is_valid())
|
||||
playback=stream->instance_playback();
|
||||
else
|
||||
playback.unref();
|
||||
|
||||
if (playback.is_valid()) {
|
||||
|
||||
playback->set_loop(loops);
|
||||
playback->set_paused(paused);
|
||||
playback->set_volume(volume);
|
||||
for(int i=0;i<(MIN(MAX_CHANNELS,stream->get_channel_count()));i++)
|
||||
playback->set_channel_volume(i,channel_volume[i]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Ref<EventStream> EventPlayer::get_stream() const {
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
void EventPlayer::play() {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
if (playback.is_null()) {
|
||||
return;
|
||||
}
|
||||
if (playback->is_playing()) {
|
||||
AudioServer::get_singleton()->lock();
|
||||
stop();
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
|
||||
AudioServer::get_singleton()->lock();
|
||||
playback->play();
|
||||
AudioServer::get_singleton()->unlock();
|
||||
|
||||
}
|
||||
|
||||
void EventPlayer::stop() {
|
||||
|
||||
if (!is_inside_tree())
|
||||
return;
|
||||
if (playback.is_null())
|
||||
return;
|
||||
|
||||
AudioServer::get_singleton()->lock();
|
||||
playback->stop();
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
|
||||
bool EventPlayer::is_playing() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return false;
|
||||
|
||||
return playback->is_playing();
|
||||
}
|
||||
|
||||
void EventPlayer::set_loop(bool p_enable) {
|
||||
|
||||
loops=p_enable;
|
||||
if (playback.is_null())
|
||||
return;
|
||||
playback->set_loop(loops);
|
||||
|
||||
}
|
||||
bool EventPlayer::has_loop() const {
|
||||
|
||||
return loops;
|
||||
}
|
||||
|
||||
void EventPlayer::set_volume(float p_volume) {
|
||||
|
||||
volume=p_volume;
|
||||
if (playback.is_valid())
|
||||
playback->set_volume(volume);
|
||||
}
|
||||
|
||||
float EventPlayer::get_volume() const {
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
|
||||
void EventPlayer::set_volume_db(float p_db) {
|
||||
|
||||
if (p_db<-79)
|
||||
set_volume(0);
|
||||
else
|
||||
set_volume(Math::db2linear(p_db));
|
||||
}
|
||||
|
||||
float EventPlayer::get_volume_db() const {
|
||||
|
||||
if (volume==0)
|
||||
return -80;
|
||||
else
|
||||
return Math::linear2db(volume);
|
||||
}
|
||||
|
||||
void EventPlayer::set_pitch_scale(float p_pitch_scale) {
|
||||
|
||||
pitch_scale=p_pitch_scale;
|
||||
if (playback.is_valid())
|
||||
playback->set_pitch_scale(pitch_scale);
|
||||
}
|
||||
|
||||
float EventPlayer::get_pitch_scale() const {
|
||||
|
||||
return pitch_scale;
|
||||
}
|
||||
|
||||
void EventPlayer::set_tempo_scale(float p_tempo_scale) {
|
||||
|
||||
tempo_scale=p_tempo_scale;
|
||||
if (playback.is_valid())
|
||||
playback->set_tempo_scale(tempo_scale);
|
||||
}
|
||||
|
||||
float EventPlayer::get_tempo_scale() const {
|
||||
|
||||
return tempo_scale;
|
||||
}
|
||||
|
||||
|
||||
String EventPlayer::get_stream_name() const {
|
||||
|
||||
if (stream.is_null())
|
||||
return "<No Stream>";
|
||||
return stream->get_name();
|
||||
|
||||
}
|
||||
|
||||
int EventPlayer::get_loop_count() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return 0;
|
||||
return playback->get_loop_count();
|
||||
|
||||
}
|
||||
|
||||
float EventPlayer::get_pos() const {
|
||||
|
||||
if (playback.is_null())
|
||||
return 0;
|
||||
return playback->get_pos();
|
||||
|
||||
}
|
||||
|
||||
float EventPlayer::get_length() const {
|
||||
|
||||
if (stream.is_null())
|
||||
return 0;
|
||||
return stream->get_length();
|
||||
}
|
||||
void EventPlayer::seek_pos(float p_time) {
|
||||
|
||||
if (playback.is_null())
|
||||
return;
|
||||
return playback->seek_pos(p_time);
|
||||
|
||||
}
|
||||
|
||||
void EventPlayer::set_autoplay(bool p_enable) {
|
||||
|
||||
autoplay=p_enable;
|
||||
}
|
||||
|
||||
bool EventPlayer::has_autoplay() const {
|
||||
|
||||
return autoplay;
|
||||
}
|
||||
|
||||
void EventPlayer::set_paused(bool p_paused) {
|
||||
|
||||
paused=p_paused;
|
||||
if (playback.is_valid())
|
||||
playback->set_paused(p_paused);
|
||||
}
|
||||
|
||||
bool EventPlayer::is_paused() const {
|
||||
|
||||
return paused;
|
||||
}
|
||||
|
||||
void EventPlayer::_set_play(bool p_play) {
|
||||
|
||||
_play=p_play;
|
||||
if (is_inside_tree()) {
|
||||
if(_play)
|
||||
play();
|
||||
else
|
||||
stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool EventPlayer::_get_play() const{
|
||||
|
||||
return _play;
|
||||
}
|
||||
|
||||
void EventPlayer::set_channel_volume(int p_channel,float p_volume) {
|
||||
|
||||
ERR_FAIL_INDEX(p_channel,MAX_CHANNELS);
|
||||
channel_volume[p_channel]=p_volume;
|
||||
if (playback.is_valid())
|
||||
playback->set_channel_volume(p_channel,p_volume);
|
||||
}
|
||||
|
||||
float EventPlayer::get_channel_volume(int p_channel) const{
|
||||
|
||||
ERR_FAIL_INDEX_V(p_channel,MAX_CHANNELS,0);
|
||||
return channel_volume[p_channel];
|
||||
|
||||
}
|
||||
|
||||
float EventPlayer::get_channel_last_note_time(int p_channel) const {
|
||||
|
||||
if (playback.is_valid())
|
||||
return playback->get_last_note_time(p_channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EventPlayer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(_MD("set_stream","stream:EventStream"),&EventPlayer::set_stream);
|
||||
ClassDB::bind_method(_MD("get_stream:EventStream"),&EventPlayer::get_stream);
|
||||
|
||||
ClassDB::bind_method(_MD("play"),&EventPlayer::play);
|
||||
ClassDB::bind_method(_MD("stop"),&EventPlayer::stop);
|
||||
|
||||
ClassDB::bind_method(_MD("is_playing"),&EventPlayer::is_playing);
|
||||
|
||||
ClassDB::bind_method(_MD("set_paused","paused"),&EventPlayer::set_paused);
|
||||
ClassDB::bind_method(_MD("is_paused"),&EventPlayer::is_paused);
|
||||
|
||||
ClassDB::bind_method(_MD("set_loop","enabled"),&EventPlayer::set_loop);
|
||||
ClassDB::bind_method(_MD("has_loop"),&EventPlayer::has_loop);
|
||||
|
||||
ClassDB::bind_method(_MD("set_volume","volume"),&EventPlayer::set_volume);
|
||||
ClassDB::bind_method(_MD("get_volume"),&EventPlayer::get_volume);
|
||||
|
||||
ClassDB::bind_method(_MD("set_pitch_scale","pitch_scale"),&EventPlayer::set_pitch_scale);
|
||||
ClassDB::bind_method(_MD("get_pitch_scale"),&EventPlayer::get_pitch_scale);
|
||||
|
||||
ClassDB::bind_method(_MD("set_tempo_scale","tempo_scale"),&EventPlayer::set_tempo_scale);
|
||||
ClassDB::bind_method(_MD("get_tempo_scale"),&EventPlayer::get_tempo_scale);
|
||||
|
||||
ClassDB::bind_method(_MD("set_volume_db","db"),&EventPlayer::set_volume_db);
|
||||
ClassDB::bind_method(_MD("get_volume_db"),&EventPlayer::get_volume_db);
|
||||
|
||||
ClassDB::bind_method(_MD("get_stream_name"),&EventPlayer::get_stream_name);
|
||||
ClassDB::bind_method(_MD("get_loop_count"),&EventPlayer::get_loop_count);
|
||||
|
||||
ClassDB::bind_method(_MD("get_pos"),&EventPlayer::get_pos);
|
||||
ClassDB::bind_method(_MD("seek_pos","time"),&EventPlayer::seek_pos);
|
||||
|
||||
ClassDB::bind_method(_MD("get_length"),&EventPlayer::get_length);
|
||||
|
||||
ClassDB::bind_method(_MD("set_autoplay","enabled"),&EventPlayer::set_autoplay);
|
||||
ClassDB::bind_method(_MD("has_autoplay"),&EventPlayer::has_autoplay);
|
||||
|
||||
ClassDB::bind_method(_MD("set_channel_volume","channel","channel_volume"),&EventPlayer::set_channel_volume);
|
||||
ClassDB::bind_method(_MD("get_channel_volume","channel"),&EventPlayer::get_channel_volume);
|
||||
ClassDB::bind_method(_MD("get_channel_last_note_time","channel"),&EventPlayer::get_channel_last_note_time);
|
||||
|
||||
ClassDB::bind_method(_MD("_set_play","play"),&EventPlayer::_set_play);
|
||||
ClassDB::bind_method(_MD("_get_play"),&EventPlayer::_get_play);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE,"EventStream"), _SCS("set_stream"), _SCS("get_stream") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "play"), _SCS("_set_play"), _SCS("_get_play") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "loop"), _SCS("set_loop"), _SCS("has_loop") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE,"0.001,16,0.001"), _SCS("set_pitch_scale"), _SCS("get_pitch_scale") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL, "tempo_scale", PROPERTY_HINT_RANGE,"0.001,16,0.001"), _SCS("set_tempo_scale"), _SCS("get_tempo_scale") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "paused"), _SCS("set_paused"), _SCS("is_paused") );
|
||||
}
|
||||
|
||||
|
||||
EventPlayer::EventPlayer() {
|
||||
|
||||
volume=1;
|
||||
loops=false;
|
||||
paused=false;
|
||||
autoplay=false;
|
||||
_play=false;
|
||||
pitch_scale=1.0;
|
||||
tempo_scale=1.0;
|
||||
for(int i=0;i<MAX_CHANNELS;i++)
|
||||
channel_volume[i]=1.0;
|
||||
|
||||
}
|
||||
|
||||
EventPlayer::~EventPlayer() {
|
||||
|
||||
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* event_player.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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_PLAYER_H
|
||||
#define EVENT_PLAYER_H
|
||||
|
||||
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/event_stream.h"
|
||||
class EventPlayer : public Node {
|
||||
|
||||
GDCLASS(EventPlayer,Node);
|
||||
|
||||
|
||||
enum {
|
||||
MAX_CHANNELS=256
|
||||
};
|
||||
|
||||
Ref<EventStreamPlayback> playback;
|
||||
Ref<EventStream> stream;
|
||||
bool paused;
|
||||
bool autoplay;
|
||||
bool loops;
|
||||
float volume;
|
||||
|
||||
float tempo_scale;
|
||||
float pitch_scale;
|
||||
|
||||
float channel_volume[MAX_CHANNELS];
|
||||
bool _play;
|
||||
void _set_play(bool p_play);
|
||||
bool _get_play() const;
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_stream(const Ref<EventStream> &p_stream);
|
||||
Ref<EventStream> get_stream() const;
|
||||
|
||||
void play();
|
||||
void stop();
|
||||
bool is_playing() const;
|
||||
|
||||
void set_paused(bool p_paused);
|
||||
bool is_paused() const;
|
||||
|
||||
void set_loop(bool p_enable);
|
||||
bool has_loop() const;
|
||||
|
||||
void set_volume(float p_vol);
|
||||
float get_volume() const;
|
||||
|
||||
void set_volume_db(float p_db);
|
||||
float get_volume_db() const;
|
||||
|
||||
void set_pitch_scale(float p_scale);
|
||||
float get_pitch_scale() const;
|
||||
|
||||
void set_tempo_scale(float p_scale);
|
||||
float get_tempo_scale() const;
|
||||
|
||||
String get_stream_name() const;
|
||||
|
||||
int get_loop_count() const;
|
||||
|
||||
float get_pos() const;
|
||||
void seek_pos(float p_time);
|
||||
float get_length() const;
|
||||
void set_autoplay(bool p_vol);
|
||||
bool has_autoplay() const;
|
||||
|
||||
void set_channel_volume(int p_channel,float p_volume);
|
||||
float get_channel_volume(int p_channel) const;
|
||||
|
||||
float get_channel_last_note_time(int p_channel) const;
|
||||
|
||||
EventPlayer();
|
||||
~EventPlayer();
|
||||
};
|
||||
|
||||
#endif // EVENT_PLAYER_H
|
|
@ -1,718 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* sample_player.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 "sample_player.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
|
||||
bool SamplePlayer::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="play/play") {
|
||||
if (library.is_valid()) {
|
||||
|
||||
String what=p_value;
|
||||
if (what=="")
|
||||
stop_all();
|
||||
else
|
||||
play(what);
|
||||
|
||||
played_back=what;
|
||||
}
|
||||
} else if (name=="config/samples")
|
||||
set_sample_library(p_value);
|
||||
else if (name=="config/polyphony")
|
||||
set_polyphony(p_value);
|
||||
else if (name.begins_with("default/")) {
|
||||
|
||||
String what=name.right(8);
|
||||
|
||||
if (what=="volume_db")
|
||||
set_default_volume_db(p_value);
|
||||
else if (what=="pitch_scale")
|
||||
set_default_pitch_scale(p_value);
|
||||
else if (what=="pan")
|
||||
_default.pan=p_value;
|
||||
else if (what=="depth")
|
||||
_default.depth=p_value;
|
||||
else if (what=="height")
|
||||
_default.height=p_value;
|
||||
else if (what=="filter/type")
|
||||
_default.filter_type=FilterType(p_value.operator int());
|
||||
else if (what=="filter/cutoff")
|
||||
_default.filter_cutoff=p_value;
|
||||
else if (what=="filter/resonance")
|
||||
_default.filter_resonance=p_value;
|
||||
else if (what=="filter/gain")
|
||||
_default.filter_gain=p_value;
|
||||
else if (what=="reverb_room")
|
||||
_default.reverb_room=ReverbRoomType(p_value.operator int());
|
||||
else if (what=="reverb_send")
|
||||
_default.reverb_send=p_value;
|
||||
else if (what=="chorus_send")
|
||||
_default.chorus_send=p_value;
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SamplePlayer::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="play/play") {
|
||||
r_ret=played_back;
|
||||
} else if (name=="config/polyphony") {
|
||||
r_ret= get_polyphony();
|
||||
} else if (name=="config/samples") {
|
||||
|
||||
r_ret= get_sample_library();
|
||||
} else if (name.begins_with("default/")) {
|
||||
|
||||
String what=name.right(8);
|
||||
|
||||
if (what=="volume_db")
|
||||
r_ret= get_default_volume_db();
|
||||
else if (what=="pitch_scale")
|
||||
r_ret= get_default_pitch_scale();
|
||||
else if (what=="pan")
|
||||
r_ret= _default.pan;
|
||||
else if (what=="depth")
|
||||
r_ret= _default.depth;
|
||||
else if (what=="height")
|
||||
r_ret= _default.height;
|
||||
else if (what=="filter/type")
|
||||
r_ret= _default.filter_type;
|
||||
else if (what=="filter/cutoff")
|
||||
r_ret= _default.filter_cutoff;
|
||||
else if (what=="filter/resonance")
|
||||
r_ret= _default.filter_resonance;
|
||||
else if (what=="filter/gain")
|
||||
r_ret= _default.filter_gain;
|
||||
else if (what=="reverb_room")
|
||||
r_ret= _default.reverb_room;
|
||||
else if (what=="reverb_send")
|
||||
r_ret= _default.reverb_send;
|
||||
else if (what=="chorus_send")
|
||||
r_ret= _default.chorus_send;
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SamplePlayer::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
String en="";
|
||||
if (library.is_valid()) {
|
||||
List<StringName> samples;
|
||||
Ref<SampleLibrary> ncl=library;
|
||||
ncl->get_sample_list(&samples);
|
||||
for (List<StringName>::Element *E=samples.front();E;E=E->next()) {
|
||||
|
||||
en+=",";
|
||||
en+=E->get();
|
||||
}
|
||||
}
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::STRING, "play/play", PROPERTY_HINT_ENUM, en,PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_ANIMATE_AS_TRIGGER));
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "config/polyphony", PROPERTY_HINT_RANGE, "1,256,1"));
|
||||
p_list->push_back( PropertyInfo( Variant::OBJECT, "config/samples", PROPERTY_HINT_RESOURCE_TYPE, "SampleLibrary"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/volume_db", PROPERTY_HINT_RANGE, "-80,24,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/pitch_scale", PROPERTY_HINT_RANGE, "0.01,48,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/depth", PROPERTY_HINT_RANGE, "-1,1,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/height", PROPERTY_HINT_RANGE, "-1,1,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "default/filter/type", PROPERTY_HINT_ENUM, "Disabled,Lowpass,Bandpass,Highpass,Notch,Peak,BandLimit,LowShelf,HighShelf"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/filter/cutoff", PROPERTY_HINT_RANGE, "20,16384.0,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/filter/resonance", PROPERTY_HINT_RANGE, "0,4,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/filter/gain", PROPERTY_HINT_RANGE, "0,2,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "default/reverb_room", PROPERTY_HINT_ENUM, "Small,Medium,Large,Hall"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/reverb_send", PROPERTY_HINT_RANGE, "0,1,0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "default/chorus_send", PROPERTY_HINT_RANGE, "0,1,0.01"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
SamplePlayer::Voice::Voice() {
|
||||
|
||||
voice=AudioServer::get_singleton()->voice_create();
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void SamplePlayer::Voice::clear() {
|
||||
|
||||
check=0;
|
||||
|
||||
mix_rate=44100;
|
||||
volume=1;
|
||||
pan=0;
|
||||
pan_depth=0;
|
||||
pan_height=0;
|
||||
filter_type=FILTER_NONE;
|
||||
filter_cutoff=0;
|
||||
filter_resonance=0;
|
||||
chorus_send=0;
|
||||
reverb_room=REVERB_HALL;
|
||||
reverb_send=0;
|
||||
active=false;
|
||||
|
||||
}
|
||||
SamplePlayer::Voice::~Voice() {
|
||||
|
||||
AudioServer::get_singleton()->free(voice);
|
||||
}
|
||||
|
||||
|
||||
void SamplePlayer::set_polyphony(int p_voice_count) {
|
||||
|
||||
ERR_FAIL_COND( p_voice_count <1 || p_voice_count >0xFFFE );
|
||||
|
||||
voices.resize(p_voice_count);
|
||||
}
|
||||
|
||||
int SamplePlayer::get_polyphony() const {
|
||||
|
||||
return voices.size();
|
||||
}
|
||||
|
||||
SamplePlayer::VoiceID SamplePlayer::play(const String& p_name,bool unique) {
|
||||
|
||||
if (library.is_null())
|
||||
return INVALID_VOICE_ID;
|
||||
ERR_FAIL_COND_V( !library->has_sample(p_name), INVALID_VOICE_ID );
|
||||
|
||||
Ref<Sample> sample = library->get_sample(p_name);
|
||||
float vol_change = library->sample_get_volume_db(p_name);
|
||||
float pitch_change = library->sample_get_pitch_scale(p_name);
|
||||
|
||||
last_check++;
|
||||
last_id = (last_id + 1) % voices.size();
|
||||
|
||||
Voice&v = voices[last_id];
|
||||
v.clear();
|
||||
|
||||
|
||||
v.mix_rate=sample->get_mix_rate()*(_default.pitch_scale*pitch_change);
|
||||
v.sample_mix_rate=sample->get_mix_rate();
|
||||
v.check=last_check;
|
||||
v.volume=Math::db2linear(_default.volume_db+vol_change);
|
||||
v.pan=_default.pan;
|
||||
v.pan_depth=_default.depth;
|
||||
v.pan_height=_default.height;
|
||||
v.filter_type=_default.filter_type;
|
||||
v.filter_cutoff=_default.filter_cutoff;
|
||||
v.filter_resonance=_default.filter_resonance;
|
||||
v.filter_gain=_default.filter_gain;
|
||||
v.chorus_send=_default.chorus_send;
|
||||
v.reverb_room=_default.reverb_room;
|
||||
v.reverb_send=_default.reverb_send;
|
||||
|
||||
AudioServer::get_singleton()->voice_play(v.voice,sample->get_rid());
|
||||
AudioServer::get_singleton()->voice_set_mix_rate(v.voice,v.mix_rate);
|
||||
AudioServer::get_singleton()->voice_set_volume(v.voice,v.volume);
|
||||
AudioServer::get_singleton()->voice_set_pan(v.voice,v.pan,v.pan_depth,v.pan_height);
|
||||
AudioServer::get_singleton()->voice_set_filter(v.voice,(AudioServer::FilterType)v.filter_type,v.filter_cutoff,v.filter_resonance,v.filter_gain);
|
||||
AudioServer::get_singleton()->voice_set_chorus(v.voice,v.chorus_send);
|
||||
AudioServer::get_singleton()->voice_set_reverb(v.voice,(AudioServer::ReverbRoomType)v.reverb_room,v.reverb_send);
|
||||
|
||||
v.active=true;
|
||||
|
||||
if (unique) {
|
||||
|
||||
for(int i=0;i<voices.size();i++) {
|
||||
|
||||
if (!voices[i].active || uint32_t(i)==last_id)
|
||||
continue;
|
||||
|
||||
AudioServer::get_singleton()->voice_stop(voices[i].voice);
|
||||
|
||||
voices[i].clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return last_id | (last_check<<16);
|
||||
}
|
||||
|
||||
void SamplePlayer::stop_all() {
|
||||
|
||||
|
||||
for(int i=0;i<voices.size();i++) {
|
||||
|
||||
if (!voices[i].active)
|
||||
continue;
|
||||
|
||||
AudioServer::get_singleton()->voice_stop(voices[i].voice);
|
||||
voices[i].clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define _GET_VOICE\
|
||||
uint32_t voice=p_voice&0xFFFF;\
|
||||
ERR_FAIL_COND(voice >= (uint32_t)voices.size());\
|
||||
Voice &v=voices[voice];\
|
||||
if (v.check!=uint32_t(p_voice>>16))\
|
||||
return;\
|
||||
ERR_FAIL_COND(!v.active);
|
||||
|
||||
void SamplePlayer::stop(VoiceID p_voice) {
|
||||
|
||||
_GET_VOICE
|
||||
|
||||
AudioServer::get_singleton()->voice_stop(v.voice);
|
||||
v.active=false;
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer::set_mix_rate(VoiceID p_voice, int p_mix_rate) {
|
||||
|
||||
_GET_VOICE
|
||||
|
||||
v.mix_rate=p_mix_rate;
|
||||
AudioServer::get_singleton()->voice_set_mix_rate(v.voice,v.mix_rate);
|
||||
|
||||
}
|
||||
void SamplePlayer::set_pitch_scale(VoiceID p_voice, float p_pitch_scale) {
|
||||
|
||||
_GET_VOICE
|
||||
|
||||
v.mix_rate=v.sample_mix_rate*p_pitch_scale;
|
||||
AudioServer::get_singleton()->voice_set_mix_rate(v.voice,v.mix_rate);
|
||||
|
||||
}
|
||||
void SamplePlayer::set_volume(VoiceID p_voice, float p_volume) {
|
||||
|
||||
|
||||
_GET_VOICE
|
||||
v.volume=p_volume;
|
||||
AudioServer::get_singleton()->voice_set_volume(v.voice,v.volume);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer::set_volume_db(VoiceID p_voice, float p_db) {
|
||||
|
||||
//@TODO handle 0 volume as -80db or something
|
||||
_GET_VOICE
|
||||
v.volume=Math::db2linear(p_db);
|
||||
AudioServer::get_singleton()->voice_set_volume(v.voice,v.volume);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer::set_pan(VoiceID p_voice, float p_pan,float p_pan_depth,float p_pan_height) {
|
||||
|
||||
_GET_VOICE
|
||||
v.pan=p_pan;
|
||||
v.pan_depth=p_pan_depth;
|
||||
v.pan_height=p_pan_height;
|
||||
|
||||
AudioServer::get_singleton()->voice_set_pan(v.voice,v.pan,v.pan_depth,v.pan_height);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer::set_filter(VoiceID p_voice,FilterType p_filter,float p_cutoff,float p_resonance,float p_gain) {
|
||||
|
||||
_GET_VOICE
|
||||
v.filter_type=p_filter;
|
||||
v.filter_cutoff=p_cutoff;
|
||||
v.filter_resonance=p_resonance;
|
||||
v.filter_gain=p_gain;
|
||||
|
||||
AudioServer::get_singleton()->voice_set_filter(v.voice,(AudioServer::FilterType)p_filter,p_cutoff,p_resonance);
|
||||
|
||||
}
|
||||
void SamplePlayer::set_chorus(VoiceID p_voice,float p_send) {
|
||||
|
||||
_GET_VOICE
|
||||
v.chorus_send=p_send;
|
||||
|
||||
AudioServer::get_singleton()->voice_set_chorus(v.voice,p_send);
|
||||
|
||||
}
|
||||
void SamplePlayer::set_reverb(VoiceID p_voice,ReverbRoomType p_room,float p_send) {
|
||||
|
||||
_GET_VOICE
|
||||
v.reverb_room=p_room;
|
||||
v.reverb_send=p_send;
|
||||
|
||||
AudioServer::get_singleton()->voice_set_reverb(v.voice,(AudioServer::ReverbRoomType)p_room,p_send);
|
||||
|
||||
}
|
||||
|
||||
#define _GET_VOICE_V(m_ret)\
|
||||
uint32_t voice=p_voice&0xFFFF;\
|
||||
ERR_FAIL_COND_V(voice >= (uint32_t)voices.size(),m_ret);\
|
||||
const Voice &v=voices[voice];\
|
||||
if (v.check!=(p_voice>>16))\
|
||||
return m_ret;\
|
||||
ERR_FAIL_COND_V(!v.active,m_ret);
|
||||
|
||||
|
||||
int SamplePlayer::get_mix_rate(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.mix_rate;
|
||||
}
|
||||
float SamplePlayer::get_pitch_scale(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
return v.sample_mix_rate/(float)v.mix_rate;
|
||||
}
|
||||
float SamplePlayer::get_volume(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
return v.volume;
|
||||
}
|
||||
|
||||
|
||||
float SamplePlayer::get_volume_db(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
return Math::linear2db(v.volume);
|
||||
}
|
||||
|
||||
float SamplePlayer::get_pan(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
return v.pan;
|
||||
}
|
||||
float SamplePlayer::get_pan_depth(VoiceID p_voice) const {
|
||||
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
return v.pan_depth;
|
||||
}
|
||||
float SamplePlayer::get_pan_height(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.pan_height;
|
||||
}
|
||||
SamplePlayer::FilterType SamplePlayer::get_filter_type(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(FILTER_NONE);
|
||||
|
||||
return v.filter_type;
|
||||
}
|
||||
float SamplePlayer::get_filter_cutoff(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.filter_cutoff;
|
||||
}
|
||||
float SamplePlayer::get_filter_resonance(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.filter_resonance;
|
||||
}
|
||||
|
||||
float SamplePlayer::get_filter_gain(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.filter_gain;
|
||||
}
|
||||
float SamplePlayer::get_chorus(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.chorus_send;
|
||||
}
|
||||
SamplePlayer::ReverbRoomType SamplePlayer::get_reverb_room(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(REVERB_SMALL);
|
||||
|
||||
return v.reverb_room;
|
||||
}
|
||||
|
||||
float SamplePlayer::get_reverb(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(0);
|
||||
|
||||
return v.reverb_send;
|
||||
}
|
||||
|
||||
bool SamplePlayer::is_voice_active(VoiceID p_voice) const {
|
||||
|
||||
_GET_VOICE_V(false);
|
||||
return v.active && AudioServer::get_singleton()->voice_is_active(v.voice);
|
||||
|
||||
}
|
||||
bool SamplePlayer::is_active() const {
|
||||
|
||||
for(int i=0;i<voices.size();i++) {
|
||||
|
||||
if (voices[i].active && AudioServer::get_singleton()->voice_is_active(voices[i].voice))
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SamplePlayer::set_sample_library(const Ref<SampleLibrary>& p_library) {
|
||||
|
||||
library=p_library;
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
Ref<SampleLibrary> SamplePlayer::get_sample_library() const {
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SamplePlayer::set_default_pitch_scale(float p_pitch_scale) {
|
||||
|
||||
_default.pitch_scale=p_pitch_scale;
|
||||
}
|
||||
void SamplePlayer::set_default_volume(float p_volume) {
|
||||
|
||||
_default.volume_db=Math::linear2db(p_volume);
|
||||
}
|
||||
void SamplePlayer::set_default_volume_db(float p_db) {
|
||||
|
||||
_default.volume_db=p_db;
|
||||
}
|
||||
void SamplePlayer::set_default_pan(float p_pan,float p_pan_depth,float p_pan_height) {
|
||||
|
||||
_default.pan=p_pan;
|
||||
_default.depth=p_pan_depth;
|
||||
_default.height=p_pan_height;
|
||||
|
||||
}
|
||||
void SamplePlayer::set_default_filter(FilterType p_filter,float p_cutoff,float p_resonance,float p_gain) {
|
||||
|
||||
_default.filter_type=p_filter;
|
||||
_default.filter_cutoff=p_cutoff;
|
||||
_default.filter_resonance=p_resonance;
|
||||
_default.filter_gain=p_gain;
|
||||
}
|
||||
void SamplePlayer::set_default_chorus(float p_send) {
|
||||
|
||||
_default.chorus_send=p_send;
|
||||
|
||||
}
|
||||
void SamplePlayer::set_default_reverb(ReverbRoomType p_room,float p_send) {
|
||||
|
||||
_default.reverb_room=p_room;
|
||||
_default.reverb_send=p_send;
|
||||
}
|
||||
|
||||
float SamplePlayer::get_default_volume() const {
|
||||
|
||||
return Math::db2linear(_default.volume_db);
|
||||
}
|
||||
float SamplePlayer::get_default_volume_db() const {
|
||||
|
||||
return _default.volume_db;
|
||||
}
|
||||
float SamplePlayer::get_default_pitch_scale() const {
|
||||
|
||||
return _default.pitch_scale;
|
||||
}
|
||||
|
||||
|
||||
float SamplePlayer::get_default_pan() const {
|
||||
|
||||
return _default.pan;
|
||||
}
|
||||
float SamplePlayer::get_default_pan_depth() const {
|
||||
|
||||
return _default.depth;
|
||||
}
|
||||
float SamplePlayer::get_default_pan_height() const {
|
||||
|
||||
return _default.height;
|
||||
}
|
||||
SamplePlayer::FilterType SamplePlayer::get_default_filter_type() const {
|
||||
|
||||
return _default.filter_type;
|
||||
}
|
||||
float SamplePlayer::get_default_filter_cutoff() const {
|
||||
|
||||
return _default.filter_cutoff;
|
||||
}
|
||||
float SamplePlayer::get_default_filter_resonance() const {
|
||||
|
||||
return _default.filter_resonance;
|
||||
}
|
||||
float SamplePlayer::get_default_filter_gain() const {
|
||||
|
||||
return _default.filter_gain;
|
||||
}
|
||||
float SamplePlayer::get_default_chorus() const {
|
||||
|
||||
return _default.chorus_send;
|
||||
}
|
||||
SamplePlayer::ReverbRoomType SamplePlayer::get_default_reverb_room() const {
|
||||
|
||||
return _default.reverb_room;
|
||||
}
|
||||
float SamplePlayer::get_default_reverb() const {
|
||||
|
||||
return _default.reverb_send;
|
||||
}
|
||||
|
||||
String SamplePlayer::get_configuration_warning() const {
|
||||
|
||||
if (library.is_null()) {
|
||||
return TTR("A SampleLibrary resource must be created or set in the 'samples' property in order for SamplePlayer to play sound.");
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
void SamplePlayer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(_MD("set_sample_library","library:SampleLibrary"),&SamplePlayer::set_sample_library );
|
||||
ClassDB::bind_method(_MD("get_sample_library:SampleLibrary"),&SamplePlayer::get_sample_library );
|
||||
|
||||
ClassDB::bind_method(_MD("set_polyphony","max_voices"),&SamplePlayer::set_polyphony );
|
||||
ClassDB::bind_method(_MD("get_polyphony"),&SamplePlayer::get_polyphony );
|
||||
|
||||
ClassDB::bind_method(_MD("play","name","unique"),&SamplePlayer::play, DEFVAL(false) );
|
||||
ClassDB::bind_method(_MD("stop","voice"),&SamplePlayer::stop );
|
||||
ClassDB::bind_method(_MD("stop_all"),&SamplePlayer::stop_all );
|
||||
|
||||
ClassDB::bind_method(_MD("set_mix_rate","voice","hz"),&SamplePlayer::set_mix_rate );
|
||||
ClassDB::bind_method(_MD("set_pitch_scale","voice","ratio"),&SamplePlayer::set_pitch_scale );
|
||||
ClassDB::bind_method(_MD("set_volume","voice","volume"),&SamplePlayer::set_volume );
|
||||
ClassDB::bind_method(_MD("set_volume_db","voice","db"),&SamplePlayer::set_volume_db );
|
||||
ClassDB::bind_method(_MD("set_pan","voice","pan","depth","height"),&SamplePlayer::set_pan,DEFVAL(0),DEFVAL(0) );
|
||||
ClassDB::bind_method(_MD("set_filter","voice","type","cutoff_hz","resonance","gain"),&SamplePlayer::set_filter,DEFVAL(0) );
|
||||
ClassDB::bind_method(_MD("set_chorus","voice","send"),&SamplePlayer::set_chorus );
|
||||
ClassDB::bind_method(_MD("set_reverb","voice","room_type","send"),&SamplePlayer::set_reverb );
|
||||
|
||||
ClassDB::bind_method(_MD("get_mix_rate","voice"),&SamplePlayer::get_mix_rate );
|
||||
ClassDB::bind_method(_MD("get_pitch_scale","voice"),&SamplePlayer::get_pitch_scale );
|
||||
ClassDB::bind_method(_MD("get_volume","voice"),&SamplePlayer::get_volume );
|
||||
ClassDB::bind_method(_MD("get_volume_db","voice"),&SamplePlayer::get_volume_db );
|
||||
ClassDB::bind_method(_MD("get_pan","voice"),&SamplePlayer::get_pan );
|
||||
ClassDB::bind_method(_MD("get_pan_depth","voice"),&SamplePlayer::get_pan_depth );
|
||||
ClassDB::bind_method(_MD("get_pan_height","voice"),&SamplePlayer::get_pan_height );
|
||||
ClassDB::bind_method(_MD("get_filter_type","voice"),&SamplePlayer::get_filter_type );
|
||||
ClassDB::bind_method(_MD("get_filter_cutoff","voice"),&SamplePlayer::get_filter_cutoff );
|
||||
ClassDB::bind_method(_MD("get_filter_resonance","voice"),&SamplePlayer::get_filter_resonance );
|
||||
ClassDB::bind_method(_MD("get_filter_gain","voice"),&SamplePlayer::get_filter_gain );
|
||||
ClassDB::bind_method(_MD("get_chorus","voice"),&SamplePlayer::get_chorus );
|
||||
ClassDB::bind_method(_MD("get_reverb_room","voice"),&SamplePlayer::get_reverb_room );
|
||||
ClassDB::bind_method(_MD("get_reverb","voice"),&SamplePlayer::get_reverb );
|
||||
|
||||
ClassDB::bind_method(_MD("set_default_pitch_scale","ratio"),&SamplePlayer::set_default_pitch_scale );
|
||||
ClassDB::bind_method(_MD("set_default_volume","volume"),&SamplePlayer::set_default_volume );
|
||||
ClassDB::bind_method(_MD("set_default_volume_db","db"),&SamplePlayer::set_default_volume_db );
|
||||
ClassDB::bind_method(_MD("set_default_pan","pan","depth","height"),&SamplePlayer::set_default_pan,DEFVAL(0),DEFVAL(0) );
|
||||
ClassDB::bind_method(_MD("set_default_filter","type","cutoff_hz","resonance","gain"),&SamplePlayer::set_default_filter,DEFVAL(0) );
|
||||
ClassDB::bind_method(_MD("set_default_chorus","send"),&SamplePlayer::set_default_chorus );
|
||||
ClassDB::bind_method(_MD("set_default_reverb","room_type","send"),&SamplePlayer::set_default_reverb );
|
||||
|
||||
ClassDB::bind_method(_MD("get_default_pitch_scale"),&SamplePlayer::get_default_pitch_scale );
|
||||
ClassDB::bind_method(_MD("get_default_volume"),&SamplePlayer::get_default_volume );
|
||||
ClassDB::bind_method(_MD("get_default_volume_db"),&SamplePlayer::get_default_volume_db );
|
||||
ClassDB::bind_method(_MD("get_default_pan"),&SamplePlayer::get_default_pan );
|
||||
ClassDB::bind_method(_MD("get_default_pan_depth"),&SamplePlayer::get_default_pan_depth );
|
||||
ClassDB::bind_method(_MD("get_default_pan_height"),&SamplePlayer::get_default_pan_height );
|
||||
ClassDB::bind_method(_MD("get_default_filter_type"),&SamplePlayer::get_default_filter_type );
|
||||
ClassDB::bind_method(_MD("get_default_filter_cutoff"),&SamplePlayer::get_default_filter_cutoff );
|
||||
ClassDB::bind_method(_MD("get_default_filter_resonance"),&SamplePlayer::get_default_filter_resonance );
|
||||
ClassDB::bind_method(_MD("get_default_filter_gain"),&SamplePlayer::get_default_filter_gain );
|
||||
ClassDB::bind_method(_MD("get_default_chorus"),&SamplePlayer::get_default_chorus );
|
||||
ClassDB::bind_method(_MD("get_default_reverb_room"),&SamplePlayer::get_default_reverb_room );
|
||||
ClassDB::bind_method(_MD("get_default_reverb"),&SamplePlayer::get_default_reverb );
|
||||
|
||||
ClassDB::bind_method(_MD("is_active"),&SamplePlayer::is_active );
|
||||
ClassDB::bind_method(_MD("is_voice_active","voice"),&SamplePlayer::is_voice_active );
|
||||
|
||||
BIND_CONSTANT( FILTER_NONE);
|
||||
BIND_CONSTANT( FILTER_LOWPASS);
|
||||
BIND_CONSTANT( FILTER_BANDPASS);
|
||||
BIND_CONSTANT( FILTER_HIPASS);
|
||||
BIND_CONSTANT( FILTER_NOTCH);
|
||||
BIND_CONSTANT( FILTER_PEAK);
|
||||
BIND_CONSTANT( FILTER_BANDLIMIT); ///< cutoff is LP resonace is HP
|
||||
BIND_CONSTANT( FILTER_LOW_SHELF);
|
||||
BIND_CONSTANT( FILTER_HIGH_SHELF);
|
||||
|
||||
BIND_CONSTANT( REVERB_SMALL );
|
||||
BIND_CONSTANT( REVERB_MEDIUM );
|
||||
BIND_CONSTANT( REVERB_LARGE );
|
||||
BIND_CONSTANT( REVERB_HALL );
|
||||
|
||||
BIND_CONSTANT( INVALID_VOICE_ID );
|
||||
|
||||
}
|
||||
|
||||
|
||||
SamplePlayer::SamplePlayer() {
|
||||
|
||||
voices.resize(1);
|
||||
|
||||
_default.pitch_scale=1;
|
||||
_default.volume_db=0;
|
||||
_default.pan=0;
|
||||
_default.depth=0;
|
||||
_default.height=0;
|
||||
_default.filter_type=FILTER_NONE;
|
||||
_default.filter_cutoff=5000;
|
||||
_default.filter_resonance=1;
|
||||
_default.filter_gain=1;
|
||||
_default.chorus_send=0;
|
||||
_default.reverb_room=REVERB_LARGE;
|
||||
_default.reverb_send=0;
|
||||
last_id=0;
|
||||
last_check=0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
SamplePlayer::~SamplePlayer() {
|
||||
|
||||
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* sample_player.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 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 SAMPLE_PLAYER_H
|
||||
#define SAMPLE_PLAYER_H
|
||||
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
|
||||
class SamplePlayer : public Node {
|
||||
|
||||
GDCLASS( SamplePlayer, Node );
|
||||
OBJ_CATEGORY("Audio Nodes");
|
||||
public:
|
||||
|
||||
|
||||
enum FilterType {
|
||||
FILTER_NONE,
|
||||
FILTER_LOWPASS,
|
||||
FILTER_BANDPASS,
|
||||
FILTER_HIPASS,
|
||||
FILTER_NOTCH,
|
||||
FILTER_PEAK,
|
||||
FILTER_BANDLIMIT, ///< cutoff is LP resonace is HP
|
||||
FILTER_LOW_SHELF,
|
||||
FILTER_HIGH_SHELF,
|
||||
};
|
||||
|
||||
enum ReverbRoomType {
|
||||
|
||||
REVERB_SMALL,
|
||||
REVERB_MEDIUM,
|
||||
REVERB_LARGE,
|
||||
REVERB_HALL
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
INVALID_VOICE_ID=0xFFFFFFFF
|
||||
};
|
||||
|
||||
typedef uint32_t VoiceID;
|
||||
|
||||
private:
|
||||
|
||||
Ref<SampleLibrary> library;
|
||||
|
||||
struct Voice {
|
||||
|
||||
RID voice;
|
||||
uint32_t check;
|
||||
bool active;
|
||||
|
||||
int sample_mix_rate;
|
||||
int mix_rate;
|
||||
float volume;
|
||||
float pan;
|
||||
float pan_depth;
|
||||
float pan_height;
|
||||
FilterType filter_type;
|
||||
float filter_cutoff;
|
||||
float filter_resonance;
|
||||
float filter_gain;
|
||||
float chorus_send;
|
||||
ReverbRoomType reverb_room;
|
||||
float reverb_send;
|
||||
|
||||
void clear();
|
||||
Voice();
|
||||
~Voice();
|
||||
};
|
||||
|
||||
Vector<Voice> voices;
|
||||
|
||||
struct Default {
|
||||
|
||||
float reverb_send;
|
||||
float pitch_scale;
|
||||
float volume_db;
|
||||
float pan;
|
||||
float depth;
|
||||
float height;
|
||||
FilterType filter_type;
|
||||
float filter_cutoff;
|
||||
float filter_resonance;
|
||||
float filter_gain;
|
||||
float chorus_send;
|
||||
ReverbRoomType reverb_room;
|
||||
|
||||
} _default;
|
||||
|
||||
uint32_t last_id;
|
||||
uint16_t last_check;
|
||||
String played_back;
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_sample_library(const Ref<SampleLibrary>& p_library);
|
||||
Ref<SampleLibrary> get_sample_library() const;
|
||||
|
||||
void set_polyphony(int p_voice_count);
|
||||
int get_polyphony() const;
|
||||
|
||||
VoiceID play(const String& p_name,bool unique=false);
|
||||
void stop(VoiceID p_voice);
|
||||
void stop_all();
|
||||
bool is_voice_active(VoiceID) const;
|
||||
bool is_active() const;
|
||||
|
||||
void set_mix_rate(VoiceID p_voice, int p_mix_rate);
|
||||
void set_pitch_scale(VoiceID p_voice, float p_pitch_scale);
|
||||
void set_volume(VoiceID p_voice, float p_volume);
|
||||
void set_volume_db(VoiceID p_voice, float p_db);
|
||||
void set_pan(VoiceID p_voice, float p_pan,float p_pan_depth=0,float p_pan_height=0);
|
||||
void set_filter(VoiceID p_voice,FilterType p_filter,float p_cutoff,float p_resonance,float p_gain);
|
||||
void set_chorus(VoiceID p_voice,float p_send);
|
||||
void set_reverb(VoiceID p_voice,ReverbRoomType p_room,float p_send);
|
||||
|
||||
int get_mix_rate(VoiceID p_voice) const;
|
||||
float get_pitch_scale(VoiceID p_voice) const;
|
||||
float get_volume(VoiceID p_voice) const;
|
||||
float get_volume_db(VoiceID p_voice) const;
|
||||
|
||||
float get_pan(VoiceID p_voice) const;
|
||||
float get_pan_depth(VoiceID p_voice) const;
|
||||
float get_pan_height(VoiceID p_voice) const;
|
||||
FilterType get_filter_type(VoiceID p_voice) const;
|
||||
float get_filter_cutoff(VoiceID p_voice) const;
|
||||
float get_filter_resonance(VoiceID p_voice) const;
|
||||
float get_filter_gain(VoiceID p_voice) const;
|
||||
float get_chorus(VoiceID p_voice) const;
|
||||
ReverbRoomType get_reverb_room(VoiceID p_voice) const;
|
||||
float get_reverb(VoiceID p_voice) const;
|
||||
|
||||
|
||||
|
||||
void set_default_pitch_scale(float p_pitch_scale);
|
||||
void set_default_volume(float p_volume);
|
||||
void set_default_volume_db(float p_db);
|
||||
void set_default_pan(float p_pan,float p_pan_depth=0,float p_pan_height=0);
|
||||
void set_default_filter(FilterType p_filter,float p_cutoff,float p_resonance,float p_gain);
|
||||
void set_default_chorus(float p_send);
|
||||
void set_default_reverb(ReverbRoomType p_room,float p_send);
|
||||
|
||||
float get_default_volume() const;
|
||||
float get_default_volume_db() const;
|
||||
float get_default_pitch_scale() const;
|
||||
float get_default_pan() const;
|
||||
float get_default_pan_depth() const;
|
||||
float get_default_pan_height() const;
|
||||
FilterType get_default_filter_type() const;
|
||||
float get_default_filter_cutoff() const;
|
||||
float get_default_filter_resonance() const;
|
||||
float get_default_filter_gain() const;
|
||||
float get_default_chorus() const;
|
||||
ReverbRoomType get_default_reverb_room() const;
|
||||
float get_default_reverb() const;
|
||||
|
||||
String get_configuration_warning() const;
|
||||
|
||||
SamplePlayer();
|
||||
~SamplePlayer();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( SamplePlayer::FilterType );
|
||||
VARIANT_ENUM_CAST( SamplePlayer::ReverbRoomType );
|
||||
|
||||
#endif // SAMPLE_PLAYER_H
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue