Optimize buffer zero-filling
authorRobin Gareus <robin@gareus.org>
Wed, 6 Feb 2019 15:59:41 +0000 (16:59 +0100)
committerRobin Gareus <robin@gareus.org>
Wed, 6 Feb 2019 16:02:20 +0000 (17:02 +0100)
libs/ardour/disk_reader.cc
libs/pbd/pbd/playback_buffer.h

index 5b7b5bde52d4298ed6d1a6359ceeffb99a4fbbf8..c87f04daf2d5ad68f630077aa91e19ca373748e6 100644 (file)
@@ -692,11 +692,7 @@ DiskReader::audio_read (PBD::PlaybackBuffer<Sample>*rb,
        Location *loc = 0;
 
        if (!_playlists[DataType::AUDIO]) {
-               // TODO optimize use zero-buffer
-               for (uint32_t z = 0; z < cnt; ++z) {
-                       Sample t = 0;
-                       rb->write (&t, 1);
-               }
+               rb->write_zero (cnt);
                return 0;
        }
 
@@ -908,12 +904,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai
                        /* at start: nothing to do but fill with silence */
                        for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
                                ChannelInfo* chan (*i);
-                               // TODO optimize use zero-buffer
-                               samplecnt_t ws = chan->rbuf->write_space ();
-                               for (uint32_t z = 0; z < ws; ++z) {
-                                       Sample t = 0;
-                                       chan->rbuf->write (&t, 1);
-                               }
+                               chan->rbuf->write_zero (chan->rbuf->write_space ());
                        }
                        return 0;
                }
@@ -932,12 +923,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai
                        /* at end: nothing to do but fill with silence */
                        for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
                                ChannelInfo* chan (*i);
-                               // TODO optimize use zero-buffer
-                               samplecnt_t ws = chan->rbuf->write_space ();
-                               for (uint32_t z = 0; z < ws; ++z) {
-                                       Sample t = 0;
-                                       chan->rbuf->write (&t, 1);
-                               }
+                               chan->rbuf->write_zero (chan->rbuf->write_space ());
                        }
                        return 0;
                }
@@ -990,7 +976,10 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai
                }
 
                if (zero_fill) {
-                       /* XXX: do something */
+                       /* not sure if action is needed,
+                        * we'll later hit the "to close to the end" case
+                        */
+                       //chan->rbuf->write_zero (zero_fill);
                }
        }
 
index fc9bd4d6e0dfc4217a08c4185f498c6a237081a4..d9f2232144a2a030d0d8f9d2980fcf6724af30f2 100644 (file)
@@ -106,7 +106,8 @@ public:
        }
 
        guint read  (T *dest, guint cnt, bool commit = true);
-       guint write (T const * src,  guint cnt);
+       guint write (T const * src, guint cnt);
+       guint write_zero (guint cnt);
 
        T *buffer () { return buf; }
        guint bufsize () const { return size; }
@@ -139,7 +140,6 @@ private:
        Glib::Threads::Mutex _reset_lock;
 };
 
-
 template<class T> /*LIBPBD_API*/ guint
 PlaybackBuffer<T>::write (T const *src, guint cnt)
 {
@@ -178,6 +178,44 @@ PlaybackBuffer<T>::write (T const *src, guint cnt)
        return to_write;
 }
 
+template<class T> /*LIBPBD_API*/ guint
+PlaybackBuffer<T>::write_zero (guint cnt)
+{
+       guint w = g_atomic_int_get (&write_idx);
+       const guint free_cnt = write_space ();
+
+       if (free_cnt == 0) {
+               return 0;
+       }
+
+       const guint to_write = cnt > free_cnt ? free_cnt : cnt;
+       const guint cnt2 = w + to_write;
+
+       guint n1, n2;
+       if (cnt2 > size) {
+               n1 = size - w;
+               n2 = cnt2 & size_mask;
+       } else {
+               n1 = to_write;
+               n2 = 0;
+       }
+
+       memset (&buf[w], 0, n1 * sizeof (T));
+       w = (w + n1) & size_mask;
+
+       if (n2) {
+               memset (buf, 0, n2 * sizeof (T));
+               w = n2;
+       }
+
+       {
+               SpinLock sl (_writepos_lock);
+               write_pos += to_write;
+               g_atomic_int_set (&write_idx, w);
+       }
+       return to_write;
+}
+
 template<class T> /*LIBPBD_API*/ guint
 PlaybackBuffer<T>::read (T *dest, guint cnt, bool commit)
 {