From 2308160bc2d9991ced86e8fb7320645a377df549 Mon Sep 17 00:00:00 2001
From: Markus Henschel <markus.henschel@yager.de>
Date: Thu, 7 Nov 2013 18:24:19 +0100
Subject: [PATCH] add al_fill_silence

---
 addons/acodec/ogg.c                            |  5 +--
 addons/audio/allegro5/allegro_audio.h          |  4 +++
 addons/audio/allegro5/internal/aintern_audio.h |  3 +-
 addons/audio/alsa.c                            |  9 +++--
 addons/audio/audio.c                           | 46 ++++++++++++++++++++------
 addons/audio/dsound.cpp                        |  5 ++-
 addons/audio/kcm_stream.c                      | 26 +++++++++++----
 addons/audio/oss.c                             |  5 +--
 8 files changed, 73 insertions(+), 30 deletions(-)

diff --git a/addons/acodec/ogg.c b/addons/acodec/ogg.c
index 0db1545..0e4a05c 100644
--- a/addons/acodec/ogg.c
+++ b/addons/acodec/ogg.c
@@ -419,8 +419,9 @@ static size_t ogg_stream_update(ALLEGRO_AUDIO_STREAM *stream, void *data,
 	   
       /* If nothing read then now to silence from here to the end. */
       if (read == 0) {
-         int silence = _al_kcm_get_silence(stream->spl.spl_data.depth);
-         memset((char *)data + pos, silence, buf_size - pos);
+         unsigned long silence_samples=(buf_size - pos)/
+            (al_get_audio_depth_size(stream->spl.spl_data.depth)*al_get_channel_count(stream->spl.spl_data.chan_conf));
+         al_fill_silence(stream->spl.spl_data.depth, stream->spl.spl_data.chan_conf, silence_samples, (char *)data + pos);
          /* return the number of usefull byes written */
          return pos;
       }
diff --git a/addons/audio/allegro5/allegro_audio.h b/addons/audio/allegro5/allegro_audio.h
index 2fd9a82..8cee4ad 100644
--- a/addons/audio/allegro5/allegro_audio.h
+++ b/addons/audio/allegro5/allegro_audio.h
@@ -263,6 +263,8 @@ ALLEGRO_KCM_AUDIO_FUNC(bool, al_get_audio_stream_attached, (const ALLEGRO_AUDIO_
 
 ALLEGRO_KCM_AUDIO_FUNC(void *, al_get_audio_stream_fragment, (const ALLEGRO_AUDIO_STREAM *stream));
 
+ALLEGRO_KCM_AUDIO_FUNC(uint64_t, al_get_audio_stream_played_samples, (const ALLEGRO_AUDIO_STREAM *stream));
+
 ALLEGRO_KCM_AUDIO_FUNC(bool, al_set_audio_stream_speed, (ALLEGRO_AUDIO_STREAM *stream, float val));
 ALLEGRO_KCM_AUDIO_FUNC(bool, al_set_audio_stream_gain, (ALLEGRO_AUDIO_STREAM *stream, float val));
 ALLEGRO_KCM_AUDIO_FUNC(bool, al_set_audio_stream_pan, (ALLEGRO_AUDIO_STREAM *stream, float val));
@@ -339,6 +341,8 @@ ALLEGRO_KCM_AUDIO_FUNC(uint32_t, al_get_allegro_audio_version, (void));
 ALLEGRO_KCM_AUDIO_FUNC(size_t, al_get_channel_count, (ALLEGRO_CHANNEL_CONF conf));
 ALLEGRO_KCM_AUDIO_FUNC(size_t, al_get_audio_depth_size, (ALLEGRO_AUDIO_DEPTH conf));
 
+ALLEGRO_KCM_AUDIO_FUNC(void, al_fill_silence, (ALLEGRO_AUDIO_DEPTH depth, ALLEGRO_CHANNEL_CONF chan_conf, unsigned int samples, void * buf));
+
 /* Simple audio layer */
 ALLEGRO_KCM_AUDIO_FUNC(bool, al_reserve_samples, (int reserve_samples));
 ALLEGRO_KCM_AUDIO_FUNC(ALLEGRO_MIXER *, al_get_default_mixer, (void));
diff --git a/addons/audio/allegro5/internal/aintern_audio.h b/addons/audio/allegro5/internal/aintern_audio.h
index cf6f899..b75ee26 100644
--- a/addons/audio/allegro5/internal/aintern_audio.h
+++ b/addons/audio/allegro5/internal/aintern_audio.h
@@ -263,6 +263,8 @@ struct ALLEGRO_AUDIO_STREAM {
 
    void                  *extra;
                          /* Extra data for use by the flac/vorbis addons. */
+   
+   uint64_t				played_fragments; //number of complete fragment buffers played since the stream has been started the last time
 };
 
 bool _al_kcm_refill_stream(ALLEGRO_AUDIO_STREAM *stream);
@@ -308,7 +310,6 @@ typedef enum {
 extern void _al_set_error(int error, char* string);
 
 /* Supposedly internal */
-ALLEGRO_KCM_AUDIO_FUNC(int, _al_kcm_get_silence, (ALLEGRO_AUDIO_DEPTH depth));
 ALLEGRO_KCM_AUDIO_FUNC(void*, _al_kcm_feed_stream, (ALLEGRO_THREAD *self, void *vstream));
 
 /* Helper to emit an event that the stream has got a buffer ready to be refilled. */
diff --git a/addons/audio/alsa.c b/addons/audio/alsa.c
index 08615cf..050cf73 100644
--- a/addons/audio/alsa.c
+++ b/addons/audio/alsa.c
@@ -349,8 +349,7 @@ static void *alsa_update_mmap(ALLEGRO_THREAD *self, void *arg)
          int silence;
 silence:
          /* If stopped just fill with silence. */
-         silence = _al_kcm_get_silence(voice->depth);
-         memset(mmap, silence, frames * alsa_voice->frame_size);
+		 al_fill_silence(voice->depth, voice->chan_conf, frames, mmap);
       }
 
       snd_pcm_sframes_t commitres = snd_pcm_mmap_commit(alsa_voice->pcm_handle, offset, frames);
@@ -449,16 +448,16 @@ static void *alsa_update_rw(ALLEGRO_THREAD *self, void *arg)
          /* This should fit. */
          unsigned int iframes = frames;
          buf = (void *)_al_voice_update(voice, &iframes);
-         frames = iframes;
          if (buf == NULL)
             goto silence;
+         
+         frames = iframes;
       }
       else {
          int silence;
 silence:
          /* If stopped just fill with silence. */
-         silence = _al_kcm_get_silence(voice->depth);
-         memset(data, silence, bytes);
+         al_fill_silence(voice->depth, voice->chan_conf, frames, data);
          buf = data;
       }
       err = snd_pcm_writei(alsa_voice->pcm_handle, buf, frames);
diff --git a/addons/audio/audio.c b/addons/audio/audio.c
index 6f593f9..e1f58de 100644
--- a/addons/audio/audio.c
+++ b/addons/audio/audio.c
@@ -119,18 +119,42 @@ ALLEGRO_AUDIO_DEPTH _al_word_size_to_depth_conf(int word_size)
    }
 }
 
-/* Returns a silent sample frame. */
-int _al_kcm_get_silence(ALLEGRO_AUDIO_DEPTH depth)
+void al_fill_silence(ALLEGRO_AUDIO_DEPTH depth, ALLEGRO_CHANNEL_CONF chan_conf, unsigned int samples, void * buf)
 {
-   switch (depth) {
-      case ALLEGRO_AUDIO_DEPTH_UINT8:
-         return 0x80;
-      case ALLEGRO_AUDIO_DEPTH_INT16:
-         return 0x8000;
-      case ALLEGRO_AUDIO_DEPTH_INT24:
-         return 0x800000;
-      default:
-         return 0;
+   size_t buffersize=al_get_audio_depth_size(depth)*al_get_channel_count(chan_conf)*samples;
+   
+   switch(depth)
+   {
+   case ALLEGRO_AUDIO_DEPTH_INT8:
+   case ALLEGRO_AUDIO_DEPTH_INT16:
+   case ALLEGRO_AUDIO_DEPTH_INT24:
+   case ALLEGRO_AUDIO_DEPTH_FLOAT32:
+      memset(buf, 0, buffersize);
+      break;
+   case ALLEGRO_AUDIO_DEPTH_UINT8:
+      memset(buf, 128, buffersize);
+      break;
+   case ALLEGRO_AUDIO_DEPTH_UINT16:  
+      {
+         size_t i=0;
+         unsigned char * buffer=(unsigned char*)buf;
+         while(i<buffersize) {
+            buffer[i++]=0;
+            buffer[i++]=128;
+         }
+      }      
+      break;
+   case ALLEGRO_AUDIO_DEPTH_UINT24:
+      {
+         size_t i=0;
+         unsigned char * buffer=(unsigned char*)buf;
+         while(i<buffersize) {
+            buffer[i++]=0;
+			buffer[i++]=0;
+            buffer[i++]=128;
+         }
+      }      
+      break;
    }
 }
 
diff --git a/addons/audio/dsound.cpp b/addons/audio/dsound.cpp
index 52dfb4e..bf75fff 100644
--- a/addons/audio/dsound.cpp
+++ b/addons/audio/dsound.cpp
@@ -156,10 +156,9 @@ static void* _dsound_update(ALLEGRO_THREAD *self, void *arg)
    HRESULT hr;
 
    (void)self;
-
+   
    unsigned char *silence = (unsigned char *)al_malloc(buffer_size);
-   int silence_value = _al_kcm_get_silence(voice->depth);
-   memset(silence, silence_value, buffer_size);
+   al_fill_silence(voice->depth, voice->chan_conf, buffer_size_in_samples, silence);
 
    /* Fill buffer */
    hr = ex_data->ds8_buffer->Lock(0, buffer_size,
diff --git a/addons/audio/kcm_stream.c b/addons/audio/kcm_stream.c
index c2835fc..547a45e 100644
--- a/addons/audio/kcm_stream.c
+++ b/addons/audio/kcm_stream.c
@@ -121,10 +121,10 @@ ALLEGRO_AUDIO_STREAM *al_create_audio_stream(size_t fragment_count,
    }
 
    for (i = 0; i < fragment_count; i++) {
-      stream->used_bufs[i] =
-         (char *) stream->main_buffer
-         + i * (MAX_LAG*bytes_per_sample + bytes_per_frag_buf)
-         + MAX_LAG*bytes_per_sample;
+      char*buffer=(char *) stream->main_buffer
+         + i * (MAX_LAG*bytes_per_sample + bytes_per_frag_buf);
+	  al_fill_silence(depth, chan_conf, MAX_LAG, buffer);
+      stream->used_bufs[i] = buffer + MAX_LAG*bytes_per_sample;
    }
 
    al_init_user_event_source(&stream->spl.es);
@@ -330,6 +330,18 @@ void *al_get_audio_stream_fragment(const ALLEGRO_AUDIO_STREAM *stream)
    return fragment;
 }
 
+/* Function: al_get_audio_stream_played_samples
+*/
+uint64_t al_get_audio_stream_played_samples(const ALLEGRO_AUDIO_STREAM *stream)
+{
+   uint64_t result=0;
+   maybe_lock_mutex(stream->spl.mutex);
+   if (stream->spl.spl_data.buffer.ptr)
+      result=stream->played_fragments*stream->spl.spl_data.len+stream->spl.pos;
+   maybe_unlock_mutex(stream->spl.mutex);
+   return result;
+}
+
 
 /* Function: al_set_audio_stream_speed
  */
@@ -478,8 +490,7 @@ static void reset_stopped_stream(ALLEGRO_AUDIO_STREAM *stream)
     * user should be OK.
     */
    for (i = 0; i < stream->buf_count; ++i) {
-      memset((char *)stream->main_buffer + i * fragment_buffer_size, 0,
-         MAX_LAG * bytes_per_sample);
+      al_fill_silence(stream->spl.spl_data.depth, stream->spl.spl_data.chan_conf, MAX_LAG, (char *)stream->main_buffer + i * fragment_buffer_size);
    }
 
    /* Get the current number of entries in the used_buf list. */
@@ -502,6 +513,7 @@ static void reset_stopped_stream(ALLEGRO_AUDIO_STREAM *stream)
    stream->spl.spl_data.buffer.ptr = NULL;
    stream->spl.pos = stream->spl.spl_data.len;
    stream->spl.pos_bresenham_error = 0;
+   stream->played_fragments=0;
 }
 
 
@@ -627,6 +639,8 @@ bool _al_kcm_refill_stream(ALLEGRO_AUDIO_STREAM *stream)
          (char *) new_buf - bytes_per_sample * MAX_LAG,
          (char *) old_buf + bytes_per_sample * (spl->pos-MAX_LAG),
          bytes_per_sample * MAX_LAG);
+
+	  ++stream->played_fragments;
    }
 
    stream->spl.pos = 0;
diff --git a/addons/audio/oss.c b/addons/audio/oss.c
index 986429e..9bed702 100644
--- a/addons/audio/oss.c
+++ b/addons/audio/oss.c
@@ -76,7 +76,6 @@ static int oss_fragsize = (8 << 16) | (10);
 
 /* Auxiliary buffer used to store silence. */
 #define SIL_BUF_SIZE 1024
-static char sil_buf[SIL_BUF_SIZE];
 
 static bool using_ver_4;
 
@@ -465,7 +464,9 @@ static void* oss_update(ALLEGRO_THREAD *self, void *arg)
       else {
 silence:
          /* If stopped just fill with silence. */
-         memset(sil_buf, _al_kcm_get_silence(voice->depth), SIL_BUF_SIZE);
+         char sil_buf[SIL_BUF_SIZE];
+         const unsigned int silent_samples=SIL_BUF_SIZE/(al_get_audio_depth_size(voice->depth)*al_get_channel_count(voice->chan_conf));
+         al_fill_silence(voice->depth, voice->chan_conf, silent_samples, sil_buf);         
          if (write(oss_voice->fd, sil_buf, SIL_BUF_SIZE) == -1) {
             ALLEGRO_ERROR("errno: %i -- %s\n", errno, strerror(errno));
          }
-- 
1.8.3.msysgit.0

