denemo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Denemo-devel] Real time playback in Denemo


From: Jeremiah Benham
Subject: Re: [Denemo-devel] Real time playback in Denemo
Date: Sun, 01 Jan 2012 14:41:07 -0600

Are we going to have a release before we start this?

Jeremiah

Sent from my Samsung smartphone on AT&T

Richard Shann <address@hidden> wrote:

>I think the next big step for Denemo will be to get the playback working
>in its own thread.
>
>Below are some ideas for how to do this, first there are some notes
>which you can cut out if you already know how the soc code is working.
>
>8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 
>I have studied the soc branch code and made the following notes:
>
>The playback works by using two threads, one is the
>process_thread_func() of the backend chosen (I see alsabackend.c and
>dummybackend.c so far) and the other is the queue_thread_func() in
>audiointerface.c
>
>The process_thread_func() creates a mutex and then runs a loop:
>the loop gets the system time g_get_current_time() and to it adds 5ms (a
>compiler constant called PLAYBACK_INTERVAL). This time is then used for
>a timed wait on a condition with the mutex, that is a call to
>g_cond_timed_wait(). This means that the thread waits for the condition
>process_cond to be signalled or until the 5ms have elapsed.
>The g_cond_timed_wait() unlocks the mutex before the thread sleeps and
>locks it when it continues. 
>***Question*** is it ok that the mutex has not been locked for the first
>time (and correspondingly, at the end g_mutex_free() is called without
>unlocking the mutex, is that ok?).
>
>Next a check is made for quitting the loop - this is done by making an
>atomic access to an int which is set by the alsa_seq_destroy() call.
>***Question*** does that need to be an atomic access? The int in
>question is just a boolean, so in C it just means that if any of the
>bits are set it is true. So it really doesn't matter if another thread
>is halfway through setting it.
>
>Next is code which I think is for MIDI input - I ignore this here.
>
>Now the playback code continues by getting the current time and
>subtracting a value called playback_start_time. This latter value is set
>up when starting the playing by getting the system time and subtracting
>a value "playback_time" which is kept in audiointerface.c and controlled
>by calls to the function update_playback_time() and initialized by
>midi_play() to Denemo.gui->si->start_time. This last is the time in
>seconds from the start of the piece which the user has set as the time
>to start from (e.g. via d-SetPlaybackInterval etc).
>So for the case of playing an entire movement, this is zero, and the
>playback_start_time is the system time when the play was initiated.
>
>Back to the loop which the process_thread_func() runs...
>
>The difference between the current time and the playback_start_time is
>called the playback_time and is time in seconds along the midi track
>where the next event should be taken from.
>
>After a check for reset (I ignore that here) an event is read from the
>queue. This is the call read_event_from_queue() in audiointerface.c.
>This is called with a parameter called until_time which is set to the
>playback_time plus 5ms (the PLAYBACK_INTERVAL value again). After
>checking for stop play conditions (discuss later) this calls into
>eventqueue.c for the function event_queue_read_output(). This checks the
>midi event time is < the until_time and returns TRUE and the event if so
>otherwise FALSE.
>Further events are read until this call to get an event from the queue
>fails.
>Finally before the loop begins again the playback_time that the backend
>has, is "sent back" to audiointerface.c via update_playback_time().
>
>8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 8>< 
>
>This code lacks the flexibility to speed up, slow down or pause the
>playback - once the playback_start_time has been fixed the midi events
>following that time will be sent out by referencing the current system
>time.
>This could be changed so that instead of executing g_get_current_time()
>the time is obtained from a thread which manages the requests from the
>user to pause, change tempo etc.
>
>Currently, I think there are two examples of how to do this in Denemo.
>The first was the one I wrote to allow live change of tempo - very
>useful for getting the right tempo by adjusting the slider while the
>music is playing. The second I wrote to allow the playback to follow a
>user playing along with it.
>Only the first of these is easy enough to understand that I still have
>it in my head: when the tempo slider is moved all the elapsed times that
>are obtained are scaled. To make this work, the playback_start_time has
>to be re-calculated - so it is as if we had been playing since then at
>the new tempo and had just reached the current playback time. In this
>way we do not have to keep a history of all the tempo changes.
>The second method of controlling the playback was for following the
>player (or conductor). In this case the user is setting a time at which
>the playback should pause (unless the user has updated it meanwhile).
>I am not sure if these could be unified.
>
>What would the new time-control thread look like? Well, for all the
>paused time it could add up the total of pauses so far and subtract
>these from the time value it returns. While actually in a pause, I guess
>it would just keep returning the same time - only when the pause is
>ended would it increment the total amount of pause time and subtract
>that from the time value it would otherwise return. I guess it could
>also manage the tempo change signal, adjusting the playback_start_time
>and scaling the times it returns. Perhaps though, it should be returning
>not absolute times but times since start? So it would be returning 0
>during a pause and a scaled difference of (g_get_current_time() -
>playback_start_time) and the total_pause_time. (?)
>
>I would welcome comments.
>
>Richard Shann
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>_______________________________________________
>Denemo-devel mailing list
>address@hidden
>https://lists.gnu.org/mailman/listinfo/denemo-devel

reply via email to

[Prev in Thread] Current Thread [Next in Thread]