summaryrefslogtreecommitdiff
path: root/scene/audio
diff options
context:
space:
mode:
Diffstat (limited to 'scene/audio')
-rw-r--r--scene/audio/sample_player.cpp40
-rw-r--r--scene/audio/sample_player.h8
-rw-r--r--scene/audio/stream_player.cpp178
-rw-r--r--scene/audio/stream_player.h33
4 files changed, 201 insertions, 58 deletions
diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp
index b93f7e7ddd..7c0a926324 100644
--- a/scene/audio/sample_player.cpp
+++ b/scene/audio/sample_player.cpp
@@ -48,8 +48,8 @@ bool SamplePlayer::_set(const StringName& p_name, const Variant& p_value) {
}
} else if (name=="config/samples")
set_sample_library(p_value);
- else if (name=="config/voices")
- set_voice_count(p_value);
+ else if (name=="config/polyphony")
+ set_polyphony(p_value);
else if (name.begins_with("default/")) {
String what=name.right(8);
@@ -95,14 +95,14 @@ bool SamplePlayer::_get(const StringName& p_name,Variant &r_ret) const {
if (name=="play/play") {
r_ret=played_back;
- } else if (name=="config/voices") {
- r_ret= get_voice_count();
+ } 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.get_slicec('/',1);
+ String what=name.right(8);
if (what=="volume_db")
r_ret= get_default_volume_db();
@@ -153,7 +153,7 @@ void SamplePlayer::_get_property_list(List<PropertyInfo> *p_list) const {
}
p_list->push_back( PropertyInfo( Variant::STRING, "play/play", PROPERTY_HINT_ENUM, en,PROPERTY_USAGE_EDITOR));
- p_list->push_back( PropertyInfo( Variant::INT, "config/voices", PROPERTY_HINT_RANGE, "1,256,1"));
+ 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"));
@@ -164,7 +164,7 @@ void SamplePlayer::_get_property_list(List<PropertyInfo> *p_list) const {
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,Medimum,Large,Hall"));
+ 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"));
@@ -203,14 +203,14 @@ SamplePlayer::Voice::~Voice() {
}
-void SamplePlayer::set_voice_count(int p_voice_count) {
+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_voice_count() const {
+int SamplePlayer::get_polyphony() const {
return voices.size();
}
@@ -460,9 +460,9 @@ float SamplePlayer::get_chorus(VoiceID p_voice) const {
return v.chorus_send;
}
-float SamplePlayer::get_reverb_room(VoiceID p_voice) const {
+SamplePlayer::ReverbRoomType SamplePlayer::get_reverb_room(VoiceID p_voice) const {
- _GET_VOICE_V(0);
+ _GET_VOICE_V(REVERB_SMALL);
return v.reverb_room;
}
@@ -591,7 +591,7 @@ float SamplePlayer::get_default_chorus() const {
return _default.chorus_send;
}
-float SamplePlayer::get_default_reverb_room() const {
+SamplePlayer::ReverbRoomType SamplePlayer::get_default_reverb_room() const {
return _default.reverb_room;
}
@@ -606,8 +606,8 @@ void SamplePlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_sample_library","library:SampleLibrary"),&SamplePlayer::set_sample_library );
ObjectTypeDB::bind_method(_MD("get_sample_library:SampleLibrary"),&SamplePlayer::get_sample_library );
- ObjectTypeDB::bind_method(_MD("set_voice_count","max_voices"),&SamplePlayer::set_voice_count );
- ObjectTypeDB::bind_method(_MD("get_voice_count"),&SamplePlayer::get_voice_count );
+ ObjectTypeDB::bind_method(_MD("set_polyphony","max_voices"),&SamplePlayer::set_polyphony );
+ ObjectTypeDB::bind_method(_MD("get_polyphony"),&SamplePlayer::get_polyphony );
ObjectTypeDB::bind_method(_MD("play","name","unique"),&SamplePlayer::play, DEFVAL(false) );
ObjectTypeDB::bind_method(_MD("stop","voice"),&SamplePlayer::stop );
@@ -615,8 +615,8 @@ void SamplePlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_mix_rate","voice","hz"),&SamplePlayer::set_mix_rate );
ObjectTypeDB::bind_method(_MD("set_pitch_scale","voice","ratio"),&SamplePlayer::set_pitch_scale );
- ObjectTypeDB::bind_method(_MD("set_volume","voice","nrg"),&SamplePlayer::set_volume );
- ObjectTypeDB::bind_method(_MD("set_volume_db","voice","nrg"),&SamplePlayer::set_volume_db );
+ ObjectTypeDB::bind_method(_MD("set_volume","voice","volume"),&SamplePlayer::set_volume );
+ ObjectTypeDB::bind_method(_MD("set_volume_db","voice","db"),&SamplePlayer::set_volume_db );
ObjectTypeDB::bind_method(_MD("set_pan","voice","pan","depth","height"),&SamplePlayer::set_pan,DEFVAL(0),DEFVAL(0) );
ObjectTypeDB::bind_method(_MD("set_filter","voice","type","cutoff_hz","resonance","gain"),&SamplePlayer::set_filter,DEFVAL(0) );
ObjectTypeDB::bind_method(_MD("set_chorus","voice","send"),&SamplePlayer::set_chorus );
@@ -638,8 +638,8 @@ void SamplePlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_reverb","voice"),&SamplePlayer::get_reverb );
ObjectTypeDB::bind_method(_MD("set_default_pitch_scale","ratio"),&SamplePlayer::set_default_pitch_scale );
- ObjectTypeDB::bind_method(_MD("set_default_volume","nrg"),&SamplePlayer::set_default_volume );
- ObjectTypeDB::bind_method(_MD("set_default_volume_db","db"),&SamplePlayer::set_default_volume );
+ ObjectTypeDB::bind_method(_MD("set_default_volume","volume"),&SamplePlayer::set_default_volume );
+ ObjectTypeDB::bind_method(_MD("set_default_volume_db","db"),&SamplePlayer::set_default_volume_db );
ObjectTypeDB::bind_method(_MD("set_default_pan","pan","depth","height"),&SamplePlayer::set_default_pan,DEFVAL(0),DEFVAL(0) );
ObjectTypeDB::bind_method(_MD("set_default_filter","type","cutoff_hz","resonance","gain"),&SamplePlayer::set_default_filter,DEFVAL(0) );
ObjectTypeDB::bind_method(_MD("set_default_chorus","send"),&SamplePlayer::set_default_chorus );
@@ -647,7 +647,7 @@ void SamplePlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_default_pitch_scale"),&SamplePlayer::get_default_pitch_scale );
ObjectTypeDB::bind_method(_MD("get_default_volume"),&SamplePlayer::get_default_volume );
- ObjectTypeDB::bind_method(_MD("get_default_volume_db"),&SamplePlayer::get_default_volume );
+ ObjectTypeDB::bind_method(_MD("get_default_volume_db"),&SamplePlayer::get_default_volume_db );
ObjectTypeDB::bind_method(_MD("get_default_pan"),&SamplePlayer::get_default_pan );
ObjectTypeDB::bind_method(_MD("get_default_pan_depth"),&SamplePlayer::get_default_pan_depth );
ObjectTypeDB::bind_method(_MD("get_default_pan_height"),&SamplePlayer::get_default_pan_height );
@@ -677,6 +677,8 @@ void SamplePlayer::_bind_methods() {
BIND_CONSTANT( REVERB_LARGE );
BIND_CONSTANT( REVERB_HALL );
+ BIND_CONSTANT( INVALID_VOICE_ID );
+
}
diff --git a/scene/audio/sample_player.h b/scene/audio/sample_player.h
index 53e085b8d8..75a01aff86 100644
--- a/scene/audio/sample_player.h
+++ b/scene/audio/sample_player.h
@@ -130,8 +130,8 @@ public:
void set_sample_library(const Ref<SampleLibrary>& p_library);
Ref<SampleLibrary> get_sample_library() const;
- void set_voice_count(int p_voice_count);
- int get_voice_count() 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);
@@ -161,7 +161,7 @@ public:
float get_filter_resonance(VoiceID p_voice) const;
float get_filter_gain(VoiceID p_voice) const;
float get_chorus(VoiceID p_voice) const;
- float get_reverb_room(VoiceID p_voice) const;
+ ReverbRoomType get_reverb_room(VoiceID p_voice) const;
float get_reverb(VoiceID p_voice) const;
@@ -185,7 +185,7 @@ public:
float get_default_filter_resonance() const;
float get_default_filter_gain() const;
float get_default_chorus() const;
- float get_default_reverb_room() const;
+ ReverbRoomType get_default_reverb_room() const;
float get_default_reverb() const;
SamplePlayer();
diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp
index a097aacf19..4cfca0492a 100644
--- a/scene/audio/stream_player.cpp
+++ b/scene/audio/stream_player.cpp
@@ -28,6 +28,67 @@
/*************************************************************************/
#include "stream_player.h"
+int StreamPlayer::InternalStream::get_channel_count() const {
+
+ return player->sp_get_channel_count();
+}
+void StreamPlayer::InternalStream::set_mix_rate(int p_rate){
+
+ return player->sp_set_mix_rate(p_rate);
+}
+bool StreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){
+
+ return player->sp_mix(p_buffer,p_frames);
+}
+void StreamPlayer::InternalStream::update(){
+
+ player->sp_update();
+}
+
+
+int StreamPlayer::sp_get_channel_count() const {
+
+ return playback->get_channels();
+}
+
+void StreamPlayer::sp_set_mix_rate(int p_rate){
+
+ server_mix_rate=p_rate;
+}
+
+bool StreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) {
+
+ if (resampler.is_ready()) {
+ return resampler.mix(p_buffer,p_frames);
+ }
+
+ return false;
+}
+
+void StreamPlayer::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 StreamPlayer::_notification(int p_what) {
@@ -52,19 +113,21 @@ void StreamPlayer::set_stream(const Ref<AudioStream> &p_stream) {
stop();
- if (stream_rid.is_valid())
- AudioServer::get_singleton()->free(stream_rid);
- stream_rid=RID();
-
stream=p_stream;
- if (!stream.is_null()) {
- stream->set_loop(loops);
- stream->set_paused(paused);
- stream_rid=AudioServer::get_singleton()->audio_stream_create(stream->get_audio_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> StreamPlayer::get_stream() const {
@@ -73,15 +136,18 @@ Ref<AudioStream> StreamPlayer::get_stream() const {
}
-void StreamPlayer::play() {
+void StreamPlayer::play(float p_from_offset) {
ERR_FAIL_COND(!is_inside_tree());
- if (stream.is_null())
+ if (playback.is_null())
return;
- if (stream->is_playing())
- stop();
+ //if (is_playing())
+ stop();
- stream->play();
+ //_THREAD_SAFE_METHOD_
+ playback->play(p_from_offset);
+ //feed the ringbuffer as long as no update callback is going on
+ sp_update();
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)
@@ -93,28 +159,31 @@ void StreamPlayer::stop() {
if (!is_inside_tree())
return;
- if (stream.is_null())
+ if (playback.is_null())
return;
+ //_THREAD_SAFE_METHOD_
AudioServer::get_singleton()->stream_set_active(stream_rid,false);
- stream->stop();
+ playback->stop();
+ resampler.flush();
+
//set_idle_process(false);
}
bool StreamPlayer::is_playing() const {
- if (stream.is_null())
+ if (playback.is_null())
return false;
- return stream->is_playing();
+ return playback->is_playing() || resampler.has_data();
}
void StreamPlayer::set_loop(bool p_enable) {
loops=p_enable;
- if (stream.is_null())
+ if (playback.is_null())
return;
- stream->set_loop(loops);
+ playback->set_loop(loops);
}
bool StreamPlayer::has_loop() const {
@@ -134,6 +203,19 @@ float StreamPlayer::get_volume() const {
return volume;
}
+void StreamPlayer::set_loop_restart_time(float p_secs) {
+
+ loop_point=p_secs;
+ if (playback.is_valid())
+ playback->set_loop_restart_time(p_secs);
+}
+
+float StreamPlayer::get_loop_restart_time() const {
+
+ return loop_point;
+}
+
+
void StreamPlayer::set_volume_db(float p_db) {
if (p_db<-79)
@@ -161,31 +243,33 @@ String StreamPlayer::get_stream_name() const {
int StreamPlayer::get_loop_count() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_loop_count();
+ return playback->get_loop_count();
}
float StreamPlayer::get_pos() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_pos();
+ return playback->get_pos();
}
float StreamPlayer::get_length() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_length();
+ return playback->get_length();
}
void StreamPlayer::seek_pos(float p_time) {
- if (stream.is_null())
+ if (playback.is_null())
return;
- return stream->seek_pos(p_time);
+ //works better...
+ stop();
+ playback->play(p_time);
}
@@ -202,8 +286,8 @@ bool StreamPlayer::has_autoplay() const {
void StreamPlayer::set_paused(bool p_paused) {
paused=p_paused;
- if (stream.is_valid())
- stream->set_paused(p_paused);
+ //if (stream.is_valid())
+ // stream->set_paused(p_paused);
}
bool StreamPlayer::is_paused() const {
@@ -228,13 +312,24 @@ bool StreamPlayer::_get_play() const{
return _play;
}
+void StreamPlayer::set_buffering_msec(int p_msec) {
+
+ buffering_ms=p_msec;
+}
+
+int StreamPlayer::get_buffering_msec() const{
+
+ return buffering_ms;
+}
+
+
void StreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&StreamPlayer::set_stream);
ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&StreamPlayer::get_stream);
- ObjectTypeDB::bind_method(_MD("play"),&StreamPlayer::play);
+ ObjectTypeDB::bind_method(_MD("play"),&StreamPlayer::play,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("stop"),&StreamPlayer::stop);
ObjectTypeDB::bind_method(_MD("is_playing"),&StreamPlayer::is_playing);
@@ -251,6 +346,12 @@ void StreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&StreamPlayer::set_volume_db);
ObjectTypeDB::bind_method(_MD("get_volume_db"),&StreamPlayer::get_volume_db);
+ ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&StreamPlayer::set_buffering_msec);
+ ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&StreamPlayer::get_buffering_msec);
+
+ ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&StreamPlayer::set_loop_restart_time);
+ ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&StreamPlayer::get_loop_restart_time);
+
ObjectTypeDB::bind_method(_MD("get_stream_name"),&StreamPlayer::get_stream_name);
ObjectTypeDB::bind_method(_MD("get_loop_count"),&StreamPlayer::get_loop_count);
@@ -271,6 +372,8 @@ void StreamPlayer::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") );
}
@@ -281,10 +384,17 @@ StreamPlayer::StreamPlayer() {
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;
+
}
StreamPlayer::~StreamPlayer() {
- if (stream_rid.is_valid())
- AudioServer::get_singleton()->free(stream_rid);
+ AudioServer::get_singleton()->free(stream_rid);
+ resampler.clear();
+
}
diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h
index 21e2162188..be090f50e1 100644
--- a/scene/audio/stream_player.h
+++ b/scene/audio/stream_player.h
@@ -31,17 +31,43 @@
#include "scene/resources/audio_stream.h"
#include "scene/main/node.h"
+#include "servers/audio/audio_rb_resampler.h"
class StreamPlayer : public Node {
OBJ_TYPE(StreamPlayer,Node);
+ //_THREAD_SAFE_CLASS_
+
+ struct InternalStream : public AudioServer::AudioStream {
+ StreamPlayer *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);
@@ -55,7 +81,7 @@ public:
void set_stream(const Ref<AudioStream> &p_stream);
Ref<AudioStream> get_stream() const;
- void play();
+ void play(float p_from_offset=0);
void stop();
bool is_playing() const;
@@ -68,6 +94,9 @@ public:
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;
@@ -81,6 +110,8 @@ public:
void set_autoplay(bool p_vol);
bool has_autoplay() const;
+ void set_buffering_msec(int p_msec);
+ int get_buffering_msec() const;
StreamPlayer();
~StreamPlayer();