diff options
Diffstat (limited to 'drivers/vorbis/audio_stream_ogg_vorbis.cpp')
-rw-r--r-- | drivers/vorbis/audio_stream_ogg_vorbis.cpp | 206 |
1 files changed, 113 insertions, 93 deletions
diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index ee9ba8da4d..ca055c8b62 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -30,7 +30,7 @@ -size_t AudioStreamOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) { +size_t AudioStreamPlaybackOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) { //printf("read to %p, %i bytes, %i nmemb, %p\n",p_dst,p_data,p_count,_f); FileAccess *fa=(FileAccess*)_f; @@ -46,7 +46,7 @@ size_t AudioStreamOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_c return read; } -int AudioStreamOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { +int AudioStreamPlaybackOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { //printf("seek to %p, offs %i, whence %i\n",_f,(int)offs,whence); @@ -76,7 +76,7 @@ int AudioStreamOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { #endif } -int AudioStreamOGGVorbis::_ov_close_func(void *_f) { +int AudioStreamPlaybackOGGVorbis::_ov_close_func(void *_f) { // printf("close %p\n",_f); if (!_f) @@ -86,7 +86,7 @@ int AudioStreamOGGVorbis::_ov_close_func(void *_f) { fa->close(); return 0; } -long AudioStreamOGGVorbis::_ov_tell_func(void *_f) { +long AudioStreamPlaybackOGGVorbis::_ov_tell_func(void *_f) { //printf("close %p\n",_f); @@ -95,38 +95,32 @@ long AudioStreamOGGVorbis::_ov_tell_func(void *_f) { } -bool AudioStreamOGGVorbis::_can_mix() const { - return /*playing &&*/ !paused; -} - - -void AudioStreamOGGVorbis::update() { +int AudioStreamPlaybackOGGVorbis::mix(int16_t* p_bufer,int p_frames) { - _THREAD_SAFE_METHOD_ - - if (!playing && !setting_up) - return; + if (!playing) + return 0; + int total=p_frames; while (true) { - int todo = get_todo(); + int todo = p_frames; - if (todo==0 || todo<MIN_MIX) + if (todo==0 || todo<MIN_MIX) { break; + } //printf("to mix %i - mix me %i bytes\n",to_mix,to_mix*stream_channels*sizeof(int16_t)); #ifdef BIG_ENDIAN_ENABLED - long ret=ov_read(&vf,(char*)get_write_buffer(),todo*stream_channels*sizeof(int16_t), 1, 2, 1, ¤t_section); + long ret=ov_read(&vf,(char*)p_bufer,todo*stream_channels*sizeof(int16_t), 1, 2, 1, ¤t_section); #else - long ret=ov_read(&vf,(char*)get_write_buffer(),todo*stream_channels*sizeof(int16_t), 0, 2, 1, ¤t_section); + long ret=ov_read(&vf,(char*)p_bufer,todo*stream_channels*sizeof(int16_t), 0, 2, 1, ¤t_section); #endif + if (ret<0) { playing = false; - setting_up=false; - ERR_EXPLAIN("Error reading OGG Vorbis File: "+file); ERR_BREAK(ret<0); } else if (ret==0) { // end of song, reload? @@ -138,9 +132,8 @@ void AudioStreamOGGVorbis::update() { if (!has_loop()) { playing=false; - setting_up=false; repeats=1; - return; + break; } f=FileAccess::open(file,FileAccess::READ); @@ -148,11 +141,22 @@ void AudioStreamOGGVorbis::update() { int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); if (errv!=0) { playing=false; - setting_up=false; - return; // :( + break;; // :( } - frames_mixed=0; + if (loop_restart_time) { + bool ok = ov_time_seek(&vf,loop_restart_time)==0; + if (!ok) { + playing=false; + //ERR_EXPLAIN("loop restart time rejected"); + ERR_PRINT("loop restart time rejected") + } + + frames_mixed=stream_srate*loop_restart_time; + } else { + + frames_mixed=0; + } repeats++; continue; @@ -162,16 +166,19 @@ void AudioStreamOGGVorbis::update() { ret/=sizeof(int16_t); frames_mixed+=ret; - write(ret); + + p_bufer+=ret*stream_channels; + p_frames-=ret; + } -} + return total-p_frames; +} -void AudioStreamOGGVorbis::play() { - _THREAD_SAFE_METHOD_ +void AudioStreamPlaybackOGGVorbis::play(float p_from) { if (playing) stop(); @@ -179,56 +186,46 @@ void AudioStreamOGGVorbis::play() { if (_load_stream()!=OK) return; + frames_mixed=0; - playing=false; - setting_up=true; - update(); - if (!setting_up) - return; - setting_up=false; playing=true; + if (p_from>0) { + seek_pos(p_from); + } } -void AudioStreamOGGVorbis::_close_file() { +void AudioStreamPlaybackOGGVorbis::_close_file() { if (f) { + memdelete(f); f=NULL; } } -void AudioStreamOGGVorbis::stop() { - - _THREAD_SAFE_METHOD_ +bool AudioStreamPlaybackOGGVorbis::is_playing() const { + return playing; +} +void AudioStreamPlaybackOGGVorbis::stop() { _clear_stream(); playing=false; - _clear(); -} - -AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const { - - return UPDATE_THREAD; + //_clear(); } -bool AudioStreamOGGVorbis::is_playing() const { +float AudioStreamPlaybackOGGVorbis::get_pos() const { - return playing || (get_total() - get_todo() -1 > 0); -} - -float AudioStreamOGGVorbis::get_pos() const { - - int32_t frames = int32_t(frames_mixed) - (int32_t(get_total()) - get_todo()); + int32_t frames = int32_t(frames_mixed); if (frames < 0) frames=0; return double(frames) / stream_srate; } -void AudioStreamOGGVorbis::seek_pos(float p_time) { +void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) { + - _THREAD_SAFE_METHOD_ if (!playing) return; @@ -237,85 +234,107 @@ void AudioStreamOGGVorbis::seek_pos(float p_time) { frames_mixed=stream_srate*p_time; } -String AudioStreamOGGVorbis::get_stream_name() const { +String AudioStreamPlaybackOGGVorbis::get_stream_name() const { return ""; } -void AudioStreamOGGVorbis::set_loop(bool p_enable) { +void AudioStreamPlaybackOGGVorbis::set_loop(bool p_enable) { loops=p_enable; } -bool AudioStreamOGGVorbis::has_loop() const { +bool AudioStreamPlaybackOGGVorbis::has_loop() const { return loops; } -int AudioStreamOGGVorbis::get_loop_count() const { +int AudioStreamPlaybackOGGVorbis::get_loop_count() const { return repeats; } -void AudioStreamOGGVorbis::set_file(const String& p_file) { +Error AudioStreamPlaybackOGGVorbis::set_file(const String& p_file) { file=p_file; -} - -Error AudioStreamOGGVorbis::_load_stream() { - - _clear_stream(); - if (file=="") - return ERR_INVALID_DATA; - + stream_valid=false; Error err; f=FileAccess::open(file,FileAccess::READ,&err); - if (err) { ERR_FAIL_COND_V( err, err ); } int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); + switch(errv) { - + case OV_EREAD: { // - A read from media returned an error. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CANT_READ ); + } break; + case OV_EVERSION: // - Vorbis version mismatch. + case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_UNRECOGNIZED ); + } break; + case OV_EBADHEADER: { // - Invalid Vorbis bitstream header. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CORRUPT ); + } break; + case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_BUG ); + } break; + } const vorbis_info *vinfo=ov_info(&vf,-1); stream_channels=vinfo->channels; stream_srate=vinfo->rate; - Error serr = _setup(stream_channels,stream_srate); + ogg_int64_t len = ov_time_total(&vf,-1); + length=len/1000.0; + ov_clear(&vf); + memdelete(f); + f=NULL; + stream_valid=true; + + + return OK; +} + +Error AudioStreamPlaybackOGGVorbis::_load_stream() { + + ERR_FAIL_COND_V(!stream_valid,ERR_UNCONFIGURED); - if (serr) { - _close_file(); - ERR_FAIL_V( ERR_INVALID_DATA ); + _clear_stream(); + if (file=="") + return ERR_INVALID_DATA; + + Error err; + f=FileAccess::open(file,FileAccess::READ,&err); + if (err) { + ERR_FAIL_COND_V( err, err ); } + int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); switch(errv) { case OV_EREAD: { // - A read from media returned an error. - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_FILE_CANT_READ ); } break; case OV_EVERSION: // - Vorbis version mismatch. case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data. - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_FILE_UNRECOGNIZED ); } break; case OV_EBADHEADER: { // - Invalid Vorbis bitstream header. - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_FILE_CORRUPT ); } break; case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption. - - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_BUG ); } break; } - - - ogg_int64_t len = ov_time_total(&vf,-1); - - length=len/1000.0; - repeats=0; stream_loaded=true; @@ -324,16 +343,16 @@ Error AudioStreamOGGVorbis::_load_stream() { } -float AudioStreamOGGVorbis::get_length() const { +float AudioStreamPlaybackOGGVorbis::get_length() const { if (!stream_loaded) { - if (const_cast<AudioStreamOGGVorbis*>(this)->_load_stream()!=OK) + if (const_cast<AudioStreamPlaybackOGGVorbis*>(this)->_load_stream()!=OK) return 0; } return length; } -void AudioStreamOGGVorbis::_clear_stream() { +void AudioStreamPlaybackOGGVorbis::_clear_stream() { if (!stream_loaded) return; @@ -346,18 +365,18 @@ void AudioStreamOGGVorbis::_clear_stream() { playing=false; } -void AudioStreamOGGVorbis::set_paused(bool p_paused) { +void AudioStreamPlaybackOGGVorbis::set_paused(bool p_paused) { paused=p_paused; } -bool AudioStreamOGGVorbis::is_paused(bool p_paused) const { +bool AudioStreamPlaybackOGGVorbis::is_paused(bool p_paused) const { return paused; } -AudioStreamOGGVorbis::AudioStreamOGGVorbis() { +AudioStreamPlaybackOGGVorbis::AudioStreamPlaybackOGGVorbis() { loops=false; playing=false; @@ -367,17 +386,18 @@ AudioStreamOGGVorbis::AudioStreamOGGVorbis() { _ov_callbacks.tell_func=_ov_tell_func; f = NULL; stream_loaded=false; - repeats=0; - setting_up=false; + stream_valid=false; + repeats=0; paused=true; stream_channels=0; stream_srate=0; current_section=0; length=0; + loop_restart_time=0; } -AudioStreamOGGVorbis::~AudioStreamOGGVorbis() { +AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { _clear_stream(); |