[beast: 1/8] BSE: synchronize PcmWriter output with song start
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 1/8] BSE: synchronize PcmWriter output with song start
- Date: Thu, 23 Mar 2017 17:13:50 +0000 (UTC)
commit 61696c4642f855390b877dc890762dd81a1b3c59
Author: Tim Janik <timj gnu org>
Date: Wed Mar 15 01:34:22 2017 +0100
BSE: synchronize PcmWriter output with song start
Currently, PcmWriterImpl::trigger_tick() only works correctly for a scenario
where one project with one song is played back. A comment outlines the short
commings.
Signed-off-by: Tim Janik <timj gnu org>
bse/bsepcmmodule.cc | 3 ++-
bse/bsepcmwriter.cc | 48 ++++++++++++++++++++++++++++++++++++++----------
bse/bsepcmwriter.hh | 20 +++++++++-----------
bse/bseproject.cc | 5 ++++-
bse/bsesequencer.cc | 4 ++++
5 files changed, 57 insertions(+), 23 deletions(-)
---
diff --git a/bse/bsepcmmodule.cc b/bse/bsepcmmodule.cc
index a319ba6..0af927b 100644
--- a/bse/bsepcmmodule.cc
+++ b/bse/bsepcmmodule.cc
@@ -93,7 +93,8 @@ bse_pcm_omodule_process (BseModule *module,
bse_pcm_handle_write (mdata->handle, mdata->n_values, mdata->buffer);
if (mdata->pcm_writer)
- bse_pcm_writer_write (mdata->pcm_writer, mdata->n_values, mdata->buffer);
+ bse_pcm_writer_write (mdata->pcm_writer, mdata->n_values, mdata->buffer,
+ bse_module_tick_stamp (module));
}
static void
diff --git a/bse/bsepcmwriter.cc b/bse/bsepcmwriter.cc
index 58b57c2..e95f902 100644
--- a/bse/bsepcmwriter.cc
+++ b/bse/bsepcmwriter.cc
@@ -7,13 +7,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-/* --- prototypes --- */
+
+// == prototypes ==
static void bse_pcm_writer_init (BsePcmWriter *pdev);
static void bse_pcm_writer_class_init (BsePcmWriterClass *klass);
static void bse_pcm_writer_finalize (GObject *object);
-/* --- variables --- */
+
+// == variables ==
+static std::atomic<uint64> atomic_trigger_tick {-uint64 (1)};
static gpointer parent_class = NULL;
-/* --- functions --- */
+
+// == functions ==
BSE_BUILTIN_TYPE (BsePcmWriter)
{
static const GTypeInfo pcm_writer_info = {
@@ -77,6 +81,7 @@ bse_pcm_writer_open (BsePcmWriter *self,
self->mutex.lock();
self->n_bytes = 0;
self->recorded_maximum = recorded_maximum;
+ self->start_tick = atomic_trigger_tick;
fd = open (file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
{
@@ -119,16 +124,27 @@ bsethread_halt_recording (gpointer data)
}
void
-bse_pcm_writer_write (BsePcmWriter *self,
- gsize n_values,
- const gfloat *values)
+bse_pcm_writer_write (BsePcmWriter *self, size_t n_values, const float *values, uint64 start_stamp)
{
assert_return (BSE_IS_PCM_WRITER (self));
assert_return (self->open);
- if (n_values)
- assert_return (values != NULL);
- else
- return;
+ return_unless (n_values);
+ assert_return (values != NULL);
+ if (UNLIKELY (start_stamp + n_values <= self->start_tick))
+ {
+ self->mutex.lock();
+ self->start_tick = atomic_trigger_tick;
+ self->mutex.unlock();
+ if (start_stamp + n_values <= self->start_tick)
+ return; // writer not yet activated
+ }
+ if (self->start_tick > start_stamp)
+ {
+ const uint64 delta = self->start_tick - start_stamp;
+ n_values -= delta;
+ values += delta;
+ start_stamp += delta;
+ }
self->mutex.lock();
const uint bw = 2; /* 16bit */
if (!self->broken && (!self->recorded_maximum || self->n_bytes < bw * self->recorded_maximum))
@@ -170,4 +186,16 @@ PcmWriterImpl::PcmWriterImpl (BseObject *bobj) :
PcmWriterImpl::~PcmWriterImpl ()
{}
+void
+PcmWriterImpl::trigger_tick (uint64 start_tick)
+{
+ /* FIXME: workaround for the lack of per-project engine instantiations.
+ * There really should be a single engine instance per-project, and a
+ * single pcm-writer instance per engine (if any). Then trigger_tick()
+ * becomes a method on the per-project pcm-writer instead of a static
+ * function that only works for WAV capturing of a single instance.
+ */
+ atomic_trigger_tick = start_tick;
+}
+
} // Bse
diff --git a/bse/bsepcmwriter.hh b/bse/bsepcmwriter.hh
index 0d66618..f723cf5 100644
--- a/bse/bsepcmwriter.hh
+++ b/bse/bsepcmwriter.hh
@@ -21,28 +21,26 @@ struct BsePcmWriter : BseItem {
gint fd;
uint64 n_bytes;
uint64 recorded_maximum;
+ uint64 start_tick;
};
struct BsePcmWriterClass : BseItemClass
{};
-Bse::Error bse_pcm_writer_open (BsePcmWriter *pdev,
- const gchar *file,
- guint n_channels,
- guint sample_freq,
- uint64 recorded_maximum);
-void bse_pcm_writer_close (BsePcmWriter *pdev);
+Bse::Error bse_pcm_writer_open (BsePcmWriter *pdev, const gchar *file, guint n_channels,
+ guint sample_freq, uint64 recorded_maximum);
+void bse_pcm_writer_close (BsePcmWriter *pdev);
/* writing is lock protected */
-void bse_pcm_writer_write (BsePcmWriter *pdev,
- gsize n_values,
- const gfloat *values);
+void bse_pcm_writer_write (BsePcmWriter *pdev, size_t n_values,
+ const float *values, uint64 start_stamp);
namespace Bse {
class PcmWriterImpl : public ItemImpl, public virtual PcmWriterIface {
protected:
- virtual ~PcmWriterImpl ();
+ virtual ~PcmWriterImpl ();
public:
- explicit PcmWriterImpl (BseObject*);
+ explicit PcmWriterImpl (BseObject*);
+ static void trigger_tick (uint64 start_tick);
};
} // Bse
diff --git a/bse/bseproject.cc b/bse/bseproject.cc
index 52c1b43..ba56f7d 100644
--- a/bse/bseproject.cc
+++ b/bse/bseproject.cc
@@ -16,6 +16,7 @@
#include "bsemidinotifier.hh"
#include "gslcommon.hh"
#include "bseengine.hh"
+#include "bsepcmwriter.hh"
#include "bsemidifile.hh"
#include <string.h>
#include <stdlib.h>
@@ -817,6 +818,8 @@ bse_project_start_playback (BseProject *self)
if (BSE_IS_SONG (super))
songs = sfi_ring_append (songs, super);
}
+ if (!songs) // start pcm-writer ASAP if no songs are present
+ Bse::PcmWriterImpl::trigger_tick (Bse::TickStamp::current());
/* enfore MasterThread roundtrip */
bse_trans_add (trans, bse_job_nop());
bse_trans_commit (trans);
@@ -826,7 +829,7 @@ bse_project_start_playback (BseProject *self)
if (seen_synth || songs)
bse_project_state_changed (self, Bse::ProjectState::PLAYING);
/* then, start the sequencer */
- while (songs)
+ while (songs) // start_song will synchronize PcmWriterImpl::trigger_tick
Bse::Sequencer::instance().start_song ((BseSong*) sfi_ring_pop_head (&songs), 0);
}
diff --git a/bse/bsesequencer.cc b/bse/bsesequencer.cc
index 02ade33..7d416b4 100644
--- a/bse/bsesequencer.cc
+++ b/bse/bsesequencer.cc
@@ -8,6 +8,7 @@
#include "bseproject.hh"
#include "bsemidireceiver.hh"
#include "bsemain.hh"
+#include "bsepcmwriter.hh"
#include "bseieee754.hh"
#include "bsestartup.hh" // for TaskRegistry
#include <sys/poll.h>
@@ -242,6 +243,9 @@ Sequencer::start_song (BseSong *song, uint64 start_stamp)
assert (song->sequencer_owns_refcount_SL == false);
start_stamp = MAX (start_stamp, 1);
+ // synchornize pcm-writer output with song start
+ PcmWriterImpl::trigger_tick (start_stamp);
+
g_object_ref (song);
BSE_SEQUENCER_LOCK();
song->sequencer_owns_refcount_SL = true;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]