summaryrefslogtreecommitdiff
path: root/libs/ardour/audioengine.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-06-21 20:31:14 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-06-21 20:31:14 +0000
commit39becbeb70aa4ab82b963669d87995a32141981c (patch)
tree4124b69dbc082561e601377fb41109ee96216735 /libs/ardour/audioengine.cc
parent33d17f176b20e2ebc96e7bb05af5ff3984e71f1d (diff)
smooth 0.5 second fade out during quit, plus MIDI panic to turn everything off (someone will want an opton for that, no doubt)
git-svn-id: svn://localhost/ardour2/branches/3.0@12814 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/audioengine.cc')
-rw-r--r--libs/ardour/audioengine.cc107
1 files changed, 74 insertions, 33 deletions
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 5642db8932..004ba33a6e 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -62,26 +62,26 @@ AudioEngine* AudioEngine::_instance = 0;
#define GET_PRIVATE_JACK_POINTER_RET(j,r) jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return r; }
AudioEngine::AudioEngine (string client_name, string session_uuid)
- : ports (new Ports)
+ : _jack (0)
+ , session_remove_pending (false)
+ , session_removal_countdown (-1)
+ , _running (false)
+ , _has_run (false)
+ , _buffer_size (0)
+ , _frame_rate (0)
+ , monitor_check_interval (INT32_MAX)
+ , last_monitor_check (0)
+ , _processed_frames (0)
+ , _freewheeling (false)
+ , _pre_freewheel_mmc_enabled (false)
+ , _usecs_per_cycle (0)
+ , port_remove_in_progress (false)
+ , m_meter_thread (0)
+ , _main_thread (0)
+ , ports (new Ports)
{
_instance = this; /* singleton */
- session_remove_pending = false;
- _running = false;
- _has_run = false;
- last_monitor_check = 0;
- monitor_check_interval = INT32_MAX;
- _processed_frames = 0;
- _usecs_per_cycle = 0;
- _jack = 0;
- _frame_rate = 0;
- _buffer_size = 0;
- _freewheeling = false;
- _pre_freewheel_mmc_enabled = false;
- _main_thread = 0;
- port_remove_in_progress = false;
-
- m_meter_thread = 0;
g_atomic_int_set (&m_meter_exit, 0);
if (connect_to_jack (client_name, session_uuid)) {
@@ -476,28 +476,43 @@ AudioEngine::process_callback (pframes_t nframes)
}
if (session_remove_pending) {
+
/* perform the actual session removal */
- _session = 0;
- session_remove_pending = false;
- /* pump one cycle of silence into the ports
- before the session tears them all down
- (asynchronously).
- */
+ if (session_removal_countdown < 0) {
- boost::shared_ptr<Ports> p = ports.reader();
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-
- if (i->second->sends_output()) {
- i->second->get_buffer (nframes).silence (nframes);
+ /* fade out over 1 second */
+ session_removal_countdown = _frame_rate/2;
+ session_removal_gain = 1.0;
+ session_removal_gain_step = 1.0/session_removal_countdown;
+
+ } else if (session_removal_countdown > 0) {
+
+ /* we'll be fading audio out.
+
+ if this is the last time we do this as part
+ of session removal, do a MIDI panic now
+ to get MIDI stopped. This relies on the fact
+ that "immediate data" (aka "out of band data") from
+ MIDI tracks is *appended* after any other data,
+ so that it emerges after any outbound note ons, etc.
+ */
+
+ if (session_removal_countdown <= nframes) {
+ _session->midi_panic ();
}
- }
- session_removed.signal();
+ } else {
+ /* fade out done */
+ _session = 0;
+ session_removal_countdown = -1; // reset to "not in progress"
+ session_remove_pending = false;
+ session_removed.signal(); // wakes up thread that initiated session removal
+ }
}
if (_session == 0) {
+
if (!_freewheeling) {
MIDI::Manager::instance()->cycle_start(nframes);
MIDI::Manager::instance()->cycle_end();
@@ -574,8 +589,6 @@ AudioEngine::process_callback (pframes_t nframes)
if (_session->silent()) {
- boost::shared_ptr<Ports> p = ports.reader();
-
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
if (i->second->sends_output()) {
@@ -584,6 +597,34 @@ AudioEngine::process_callback (pframes_t nframes)
}
}
+ if (session_remove_pending && session_removal_countdown) {
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+
+ if (i->second->sends_output()) {
+
+ boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
+ if (ap) {
+ Sample* s = ap->engine_get_whole_audio_buffer ();
+ gain_t g = session_removal_gain;
+
+ for (pframes_t n = 0; n < nframes; ++n) {
+ *s++ *= g;
+ g -= session_removal_gain_step;
+ }
+ }
+ }
+ }
+
+ if (session_removal_countdown > nframes) {
+ session_removal_countdown -= nframes;
+ } else {
+ session_removal_countdown = 0;
+ }
+
+ session_removal_gain -= (nframes * session_removal_gain_step);
+ }
+
// Finalize ports
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {