summaryrefslogtreecommitdiff
path: root/drivers/speex
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2015-09-09 18:50:52 -0300
committerJuan Linietsky <reduzio@gmail.com>2015-09-09 18:50:52 -0300
commit97413746173b4f872e8c72eba0e58d7092a93269 (patch)
tree576708292cc3e39f8acc3047441aaeb23e952164 /drivers/speex
parentb0aa49accbd7e45dae38f1bd43b0fbdd11714211 (diff)
Rewrite of the AudioStream API
-Fixes long-standing issues regarding to playing a single stream multiple times simultanteously -Fixes wrong-looping, starting, caching, etc. Issues resulting from bad original design -Allows more interesting kinds of streams (stream graphs with streams inside streams!) in the future
Diffstat (limited to 'drivers/speex')
-rw-r--r--drivers/speex/audio_stream_speex.cpp174
-rw-r--r--drivers/speex/audio_stream_speex.h55
2 files changed, 128 insertions, 101 deletions
diff --git a/drivers/speex/audio_stream_speex.cpp b/drivers/speex/audio_stream_speex.cpp
index 2cffb17049..2440969345 100644
--- a/drivers/speex/audio_stream_speex.cpp
+++ b/drivers/speex/audio_stream_speex.cpp
@@ -15,14 +15,15 @@ static _FORCE_INLINE_ uint16_t le_short(uint16_t s)
}
-void AudioStreamSpeex::update() {
+int AudioStreamPlaybackSpeex::mix(int16_t* p_buffer,int p_frames) {
+
+
- _THREAD_SAFE_METHOD_;
//printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs);
//printf("playing %i, paused %i\n", (int)playing, (int)paused);
if (!active || !playing || paused || !data.size())
- return;
+ return 0;
/*
if (read_ofs >= data.size()) {
@@ -35,12 +36,13 @@ void AudioStreamSpeex::update() {
};
*/
- int todo = get_todo();
+ int todo = p_frames;
if (todo < page_size) {
- return;
+ return 0;
};
- int eos = 0;
+ int eos = 0;
+ bool reloaded=false;
while (todo > page_size) {
@@ -92,7 +94,7 @@ void AudioStreamSpeex::update() {
for (int j=0;j!=nframes;j++)
{
- int16_t* out = get_write_buffer();
+ int16_t* out = p_buffer;
int ret;
/*Decode frame*/
@@ -120,7 +122,7 @@ void AudioStreamSpeex::update() {
/*Convert to short and save to output file*/
- for (int i=0;i<frame_size*get_channel_count();i++) {
+ for (int i=0;i<frame_size*stream_channels;i++) {
out[i]=le_short(out[i]);
}
@@ -149,7 +151,7 @@ void AudioStreamSpeex::update() {
}
- write(new_frame_size);
+ p_buffer+=new_frame_size*stream_channels;
todo-=new_frame_size;
}
}
@@ -175,6 +177,7 @@ void AudioStreamSpeex::update() {
if (loops) {
reload();
++loop_count;
+ //break;
} else {
playing=false;
unload();
@@ -183,18 +186,22 @@ void AudioStreamSpeex::update() {
}
};
};
+
+ return p_frames-todo;
};
-void AudioStreamSpeex::unload() {
+void AudioStreamPlaybackSpeex::unload() {
+
- _THREAD_SAFE_METHOD_
if (!active) return;
speex_bits_destroy(&bits);
if (st)
speex_decoder_destroy(st);
+
+ ogg_sync_clear(&oy);
active = false;
//data.resize(0);
st = NULL;
@@ -204,7 +211,7 @@ void AudioStreamSpeex::unload() {
loop_count = 0;
}
-void *AudioStreamSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) {
+void *AudioStreamPlaybackSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) {
void *st;
SpeexHeader *header;
@@ -276,9 +283,9 @@ void *AudioStreamSpeex::process_header(ogg_packet *op, int *frame_size, int *rat
-void AudioStreamSpeex::reload() {
+void AudioStreamPlaybackSpeex::reload() {
+
- _THREAD_SAFE_METHOD_
if (active)
unload();
@@ -359,8 +366,10 @@ void AudioStreamSpeex::reload() {
};
page_size = nframes * frame_size;
+ stream_srate=rate;
+ stream_channels=channels;
+ stream_minbuff_size=page_size;
- _setup(channels, rate,page_size);
} else if (packet_count==1)
{
@@ -374,23 +383,23 @@ void AudioStreamSpeex::reload() {
} while (packet_count <= extra_headers);
- active = true;
+ active=true;
}
-void AudioStreamSpeex::_bind_methods() {
+void AudioStreamPlaybackSpeex::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_file","file"),&AudioStreamSpeex::set_file);
- ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamSpeex::get_file);
+ //ObjectTypeDB::bind_method(_MD("set_file","file"),&AudioStreamPlaybackSpeex::set_file);
+// ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamPlaybackSpeex::get_file);
- ObjectTypeDB::bind_method(_MD("_set_bundled"),&AudioStreamSpeex::_set_bundled);
- ObjectTypeDB::bind_method(_MD("_get_bundled"),&AudioStreamSpeex::_get_bundled);
+ ObjectTypeDB::bind_method(_MD("_set_bundled"),&AudioStreamPlaybackSpeex::_set_bundled);
+ ObjectTypeDB::bind_method(_MD("_get_bundled"),&AudioStreamPlaybackSpeex::_get_bundled);
ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled"),_SCS("_get_bundled"));
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"*.spx"),_SCS("set_file"),_SCS("get_file"));
+ //ADD_PROPERTY( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"*.spx"),_SCS("set_file"),_SCS("get_file"));
};
-void AudioStreamSpeex::_set_bundled(const Dictionary& dict) {
+void AudioStreamPlaybackSpeex::_set_bundled(const Dictionary& dict) {
ERR_FAIL_COND( !dict.has("filename"));
ERR_FAIL_COND( !dict.has("data"));
@@ -399,7 +408,7 @@ void AudioStreamSpeex::_set_bundled(const Dictionary& dict) {
data = dict["data"];
};
-Dictionary AudioStreamSpeex::_get_bundled() const {
+Dictionary AudioStreamPlaybackSpeex::_get_bundled() const {
Dictionary d;
d["filename"] = filename;
@@ -408,43 +417,17 @@ Dictionary AudioStreamSpeex::_get_bundled() const {
};
-String AudioStreamSpeex::get_file() const {
-
- return filename;
-};
-
-void AudioStreamSpeex::set_file(const String& p_file){
-
- if (filename == p_file)
- return;
-
- if (active) {
- unload();
- }
-
- if (p_file == "") {
- data.resize(0);
- return;
- };
-
- Error err;
- FileAccess* file = FileAccess::open(p_file, FileAccess::READ,&err);
- if (err != OK) {
- data.resize(0);
- };
- ERR_FAIL_COND(err != OK);
- filename = p_file;
- data.resize(file->get_len());
- int read = file->get_buffer(&data[0], data.size());
- memdelete(file);
+void AudioStreamPlaybackSpeex::set_data(const Vector<uint8_t>& p_data) {
+ data=p_data;
reload();
}
-void AudioStreamSpeex::play() {
- _THREAD_SAFE_METHOD_
+void AudioStreamPlaybackSpeex::play(float p_from_pos) {
+
+
reload();
if (!active)
@@ -452,82 +435,101 @@ void AudioStreamSpeex::play() {
playing = true;
}
-void AudioStreamSpeex::stop(){
+void AudioStreamPlaybackSpeex::stop(){
+
- _THREAD_SAFE_METHOD_
unload();
playing = false;
- _clear();
-}
-bool AudioStreamSpeex::is_playing() const{
- return _is_ready() && (playing || (get_total() - get_todo() -1 > 0));
}
+bool AudioStreamPlaybackSpeex::is_playing() const{
-void AudioStreamSpeex::set_paused(bool p_paused){
-
- playing = !p_paused;
- paused = p_paused;
+ return playing;
}
-bool AudioStreamSpeex::is_paused(bool p_paused) const{
- return paused;
-}
-void AudioStreamSpeex::set_loop(bool p_enable){
+void AudioStreamPlaybackSpeex::set_loop(bool p_enable){
loops = p_enable;
}
-bool AudioStreamSpeex::has_loop() const{
+bool AudioStreamPlaybackSpeex::has_loop() const{
return loops;
}
-float AudioStreamSpeex::get_length() const{
+float AudioStreamPlaybackSpeex::get_length() const{
return 0;
}
-String AudioStreamSpeex::get_stream_name() const{
+String AudioStreamPlaybackSpeex::get_stream_name() const{
return "";
}
-int AudioStreamSpeex::get_loop_count() const{
+int AudioStreamPlaybackSpeex::get_loop_count() const{
return 0;
}
-float AudioStreamSpeex::get_pos() const{
+float AudioStreamPlaybackSpeex::get_pos() const{
return 0;
}
-void AudioStreamSpeex::seek_pos(float p_time){
+void AudioStreamPlaybackSpeex::seek_pos(float p_time){
};
-bool AudioStreamSpeex::_can_mix() const {
- //return playing;
- return data.size() != 0;
-};
+AudioStreamPlaybackSpeex::AudioStreamPlaybackSpeex() {
-AudioStream::UpdateMode AudioStreamSpeex::get_update_mode() const {
+ active=false;
+ st = NULL;
+ stream_channels=1;
+ stream_srate=1;
+ stream_minbuff_size=1;
- return UPDATE_THREAD;
}
-AudioStreamSpeex::AudioStreamSpeex() {
+AudioStreamPlaybackSpeex::~AudioStreamPlaybackSpeex() {
- active=false;
- st = NULL;
+ unload();
}
-AudioStreamSpeex::~AudioStreamSpeex() {
- unload();
+
+
+
+////////////////////////////////////////
+
+
+
+void AudioStreamSpeex::set_file(const String& p_file) {
+
+ if (this->file == p_file)
+ return;
+
+ this->file=p_file;
+
+ if (p_file == "") {
+ data.resize(0);
+ return;
+ };
+
+ Error err;
+ FileAccess* file = FileAccess::open(p_file, FileAccess::READ,&err);
+ if (err != OK) {
+ data.resize(0);
+ };
+ ERR_FAIL_COND(err != OK);
+
+ this->file = p_file;
+ data.resize(file->get_len());
+ int read = file->get_buffer(&data[0], data.size());
+ memdelete(file);
+
}
RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path, const String& p_original_path, Error *r_error) {
diff --git a/drivers/speex/audio_stream_speex.h b/drivers/speex/audio_stream_speex.h
index f9e0fce666..570e846734 100644
--- a/drivers/speex/audio_stream_speex.h
+++ b/drivers/speex/audio_stream_speex.h
@@ -1,7 +1,7 @@
#ifndef AUDIO_STREAM_SPEEX_H
#define AUDIO_STREAM_SPEEX_H
-#include "scene/resources/audio_stream_resampled.h"
+#include "scene/resources/audio_stream.h"
#include "speex/speex.h"
#include "os/file_access.h"
#include "io/resource_loader.h"
@@ -14,10 +14,10 @@
#include <ogg/ogg.h>
-class AudioStreamSpeex : public AudioStreamResampled {
+class AudioStreamPlaybackSpeex : public AudioStreamPlayback {
+
+ OBJ_TYPE(AudioStreamPlaybackSpeex, AudioStreamPlayback);
- OBJ_TYPE(AudioStreamSpeex, AudioStreamResampled);
- _THREAD_SAFE_CLASS_
void *st;
SpeexBits bits;
@@ -45,6 +45,9 @@ class AudioStreamSpeex : public AudioStreamResampled {
ogg_int64_t page_granule, last_granule;
int skip_samples, page_nb_packets;
+ int stream_channels;
+ int stream_srate;
+ int stream_minbuff_size;
void* process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers);
@@ -52,7 +55,7 @@ class AudioStreamSpeex : public AudioStreamResampled {
protected:
- virtual bool _can_mix() const;
+ //virtual bool _can_mix() const;
Dictionary _get_bundled() const;
void _set_bundled(const Dictionary& dict);
@@ -60,16 +63,12 @@ protected:
public:
- void set_file(const String& p_file);
- String get_file() const;
+ void set_data(const Vector<uint8_t>& p_data);
- virtual void play();
+ virtual void play(float p_from_pos=0);
virtual void stop();
virtual bool is_playing() const;
- virtual void set_paused(bool p_paused);
- virtual bool is_paused(bool p_paused) const;
-
virtual void set_loop(bool p_enable);
virtual bool has_loop() const;
@@ -82,13 +81,39 @@ public:
virtual float get_pos() const;
virtual void seek_pos(float p_time);
- virtual UpdateMode get_update_mode() const;
- virtual void update();
+ virtual int get_channels() const { return stream_channels; }
+ virtual int get_mix_rate() const { return stream_srate; }
+
+ virtual int get_minimum_buffer_size() const { return stream_minbuff_size; }
+ virtual int mix(int16_t* p_bufer,int p_frames);
+
+ virtual void set_loop_restart_time(float p_time) { } //no loop restart, ignore
+
+ AudioStreamPlaybackSpeex();
+ ~AudioStreamPlaybackSpeex();
+};
+
+
+
+class AudioStreamSpeex : public AudioStream {
+
+ OBJ_TYPE(AudioStreamSpeex,AudioStream);
+
+ Vector<uint8_t> data;
+ String file;
+public:
+
+ Ref<AudioStreamPlayback> instance_playback() {
+ Ref<AudioStreamPlaybackSpeex> pb = memnew( AudioStreamPlaybackSpeex );
+ pb->set_data(data);
+ return pb;
+ }
+
+ void set_file(const String& p_file);
- AudioStreamSpeex();
- ~AudioStreamSpeex();
};
+
class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader {
public:
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);