From 590dabc2c555837d4da0b8b10a2c07c302ddd9fe Mon Sep 17 00:00:00 2001
From: Markus Henschel <markus.henschel@yager.de>
Date: Mon, 28 Oct 2013 20:02:39 +0100
Subject: [PATCH] reset stream in al_set_audio_stream_playing when playing is
 set to false for voice and mixer case by making all fragments available for
 refill, resetting the fake sample position and filling the MAX_LAG samples
 with silence

---
 addons/audio/kcm_stream.c | 50 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 15 deletions(-)

diff --git a/addons/audio/kcm_stream.c b/addons/audio/kcm_stream.c
index f8c7dcf..a9aec61 100644
--- a/addons/audio/kcm_stream.c
+++ b/addons/audio/kcm_stream.c
@@ -465,31 +465,51 @@ bool al_set_audio_stream_playmode(ALLEGRO_AUDIO_STREAM *stream,
  */
 bool al_set_audio_stream_playing(ALLEGRO_AUDIO_STREAM *stream, bool val)
 {
+   bool rc=true;
    ASSERT(stream);
 
    if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
       ALLEGRO_VOICE *voice = stream->spl.parent.u.voice;
-      bool rc;
-
-      if (val == stream->spl.is_playing) {
-         return true;
-      }
-
-      rc = _al_kcm_set_voice_playing(voice, val);
-      if (rc) {
-         stream->spl.is_playing = val;
-      }
-      return rc;
+      if (val != stream->spl.is_playing) {
+         rc = _al_kcm_set_voice_playing(voice, val);
+	  }
    }
 
-   stream->spl.is_playing = val;
+   maybe_lock_mutex(stream->spl.mutex);
+   stream->spl.is_playing = rc && val;	//this will prevent the sample from being set to playing if the voice stuff didn't work
 
    if (!val) {
-      maybe_lock_mutex(stream->spl.mutex);
+      const int bytes_per_sample = al_get_channel_count(stream->spl.spl_data.chan_conf) *
+         al_get_audio_depth_size(stream->spl.spl_data.depth);
+  
+	  const int fragment_buffer_size = bytes_per_sample*(stream->spl.spl_data.len+MAX_LAG);
+
+      size_t i,used_buf_count;      
+
+	  //Write silence to the "invisible" part of all fragment bufferes to avoid interpolation artifacts.
+	  //It's tempting to zero the complete memory block in one go but some of the buffers might be getting refilled.
+	  //So they are currently "owned" by the library user and should not be overwritten. But zeroing the 
+	  //parts not visible to the 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);
+	  }
+
+	  //get the current number of entries in the used_bug list
+      for (used_buf_count = 0; used_buf_count < stream->buf_count && stream->used_bufs[used_buf_count] ; ++used_buf_count) {};      
+
+	  //move everything from pending_bufs to used_bufs
+      for (i = 0; i < stream->buf_count && used_buf_count < stream->buf_count && stream->pending_bufs[i] ; ++i, ++used_buf_count) {
+         stream->used_bufs[used_buf_count] = stream->pending_bufs[i]; 
+         stream->pending_bufs[i] = NULL;
+      }
+
+      stream->spl.spl_data.buffer.ptr = NULL;	//no fragment buffer is currently played
       stream->spl.pos = stream->spl.spl_data.len;
-      maybe_unlock_mutex(stream->spl.mutex);
+	  stream->spl.pos_bresenham_error=0;		//not sure about this      
    }
-   return true;
+   maybe_unlock_mutex(stream->spl.mutex);
+
+   return rc;
 }
 
 
-- 
1.8.3.msysgit.0

