X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession_click.cc;h=9c67ebef869c99d6d8b22101815d58f7e102b832;hb=cf52d6e4b40111eb04b244ec054055a4ec15dbe0;hp=426e6e28649997e1c728676f979184bdc4a711f6;hpb=ac1272c0d4d4632106f7ed636ff1a9182b671a05;p=ardour.git diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc index 426e6e2864..9c67ebef86 100644 --- a/libs/ardour/session_click.cc +++ b/libs/ardour/session_click.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 20002 Paul Davis + Copyright (C) 2002 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,72 +15,82 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #include #include -#include -#include -#include -#include +#include "ardour/amp.h" +#include "ardour/audio_buffer.h" +#include "ardour/buffer_set.h" +#include "ardour/click.h" +#include "ardour/io.h" +#include "ardour/session.h" +#include "ardour/tempo.h" +#include "ardour/types.h" #include -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; using namespace PBD; -Pool Session::Click::pool ("click", sizeof (Click), 128); +Pool Click::pool ("click", sizeof (Click), 1024); void -Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t offset) +Session::click (framepos_t start, framecnt_t nframes) { - TempoMap::BBTPointList *points; - jack_nframes_t end; + vector points; Sample *buf; - vector bufs; + framecnt_t click_distance; if (_click_io == 0) { return; } - Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK); - - if (!clickm.locked() || _transport_speed != 1.0 || !_clicking || click_data == 0) { - _click_io->silence (nframes, offset); - return; - } + Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK); - end = start + nframes; + /* how far have we moved since the last time the clicks got cleared + */ - buf = _passthru_buffers[0]; - points = _tempo_map->get_points (start, end); + click_distance = start - _clicks_cleared; - if (points == 0) { - goto run_clicks; + if (!clickm.locked() || !_clicking || click_data == 0 || ((click_distance + nframes) < _worst_track_latency)) { + _click_io->silence (nframes); + return; } - if (points->empty()) { - delete points; + start -= _worst_track_latency; + /* start could be negative at this point */ + const framepos_t end = start + nframes; + /* correct start, potentially */ + start = max (start, (framepos_t) 0); + + BufferSet& bufs = get_scratch_buffers(ChanCount(DataType::AUDIO, 1)); + buf = bufs.get_audio(0).data(); + + _tempo_map->get_grid (points, start, end); + + if (distance (points.begin(), points.end()) == 0) { goto run_clicks; } - for (TempoMap::BBTPointList::iterator i = points->begin(); i != points->end(); ++i) { - switch ((*i).type) { - case TempoMap::Beat: - if (click_emphasis_data == 0 || (click_emphasis_data && (*i).beat != 1)) { + for (vector::iterator i = points.begin(); i != points.end(); ++i) { + switch ((*i).beat) { + case 1: + if (click_emphasis_data && Config->get_use_click_emphasis () == true) { + clicks.push_back (new Click ((*i).frame, click_emphasis_length, click_emphasis_data)); + } else if (click_data && Config->get_use_click_emphasis () == false) { clicks.push_back (new Click ((*i).frame, click_length, click_data)); } break; - case TempoMap::Bar: - if (click_emphasis_data) { - clicks.push_back (new Click ((*i).frame, click_emphasis_length, click_emphasis_data)); - } + default: + if (click_emphasis_data == 0 || (Config->get_use_click_emphasis () == false) || (click_emphasis_data && (*i).beat != 1)) { + clicks.push_back (new Click ((*i).frame, click_length, click_data)); + } break; } } @@ -90,15 +100,12 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off for (list::iterator i = clicks.begin(); i != clicks.end(); ) { - jack_nframes_t copy; - jack_nframes_t internal_offset; + framecnt_t copy; + framecnt_t internal_offset; Click *clk; - list::iterator next; clk = *i; - next = i; - ++next; - + if (clk->start < start) { internal_offset = 0; } else { @@ -106,7 +113,7 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off } if (nframes < internal_offset) { - /* we've just located or something.. + /* we've just located or something.. effectively going backwards. lets get the flock out of here */ break; @@ -120,105 +127,111 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off if (clk->offset >= clk->duration) { delete clk; - clicks.erase (i); + i = clicks.erase (i); + } else { + ++i; } - - - i = next; } - _click_io->deliver_output (_passthru_buffers, 1, nframes, offset); + _click_gain->run (bufs, 0, 0, 1.0, nframes, false); + _click_io->copy_to_outputs (bufs, DataType::AUDIO, nframes, 0); } void -Session::setup_click_sounds (int which) +Session::setup_click_sounds (Sample** data, Sample const * default_data, framecnt_t* length, framecnt_t default_length, string const & path) { - SNDFILE *sndfile; - SF_INFO info; + if (*data != default_data) { + delete[] *data; + *data = 0; + } - clear_clicks(); + if (path.empty ()) { - if ((which == 0 || which == 1)) { - - if (click_data && click_data != default_click) { - delete [] click_data; - click_data = 0; - } + *data = const_cast (default_data); + *length = default_length; - string path = Config->get_click_emphasis_sound(); + } else { - if (path.empty()) { + SF_INFO info; + SNDFILE* sndfile; - click_data = const_cast (default_click); - click_length = default_click_length; + info.format = 0; + if ((sndfile = sf_open (path.c_str(), SFM_READ, &info)) == 0) { + char errbuf[256]; + sf_error_str (0, errbuf, sizeof (errbuf) - 1); + warning << string_compose (_("cannot open click soundfile %1 (%2)"), path, errbuf) << endmsg; + _clicking = false; + return; + } - } else { + /* read the (possibly multi-channel) click data into a temporary buffer */ - if ((sndfile = sf_open (path.c_str(), SFM_READ, &info)) == 0) { - char errbuf[256]; - sf_error_str (0, errbuf, sizeof (errbuf) - 1); - warning << string_compose (_("cannot open click soundfile %1 (%2)"), path, errbuf) << endmsg; - _clicking = false; - return; - } - - click_data = new Sample[info.frames]; - click_length = info.frames; - - if (sf_read_float (sndfile, click_data, info.frames) != info.frames) { - warning << _("cannot read data from click soundfile") << endmsg; - delete click_data; - click_data = 0; - _clicking = false; - } - - sf_close (sndfile); + sf_count_t const samples = info.frames * info.channels; - } - } - - if ((which == 0 || which == -1)) { + Sample* tmp = new Sample[samples]; - if (click_emphasis_data && click_emphasis_data != default_click_emphasis) { - delete [] click_emphasis_data; - click_emphasis_data = 0; - } + if (sf_readf_float (sndfile, tmp, info.frames) != info.frames) { - string path = Config->get_click_emphasis_sound(); + warning << _("cannot read data from click soundfile") << endmsg; + *data = 0; + _clicking = false; - if (path.empty()) { - click_emphasis_data = const_cast (default_click_emphasis); - click_emphasis_length = default_click_emphasis_length; } else { - if ((sndfile = sf_open (path.c_str(), SFM_READ, &info)) == 0) { - char errbuf[256]; - sf_error_str (0, errbuf, sizeof (errbuf) - 1); - warning << string_compose (_("cannot open click emphasis soundfile %1 (%2)"), path, errbuf) << endmsg; - return; - } - - click_emphasis_data = new Sample[info.frames]; - click_emphasis_length = info.frames; - - if (sf_read_float (sndfile, click_emphasis_data, info.frames) != info.frames) { - warning << _("cannot read data from click emphasis soundfile") << endmsg; - delete click_emphasis_data; - click_emphasis_data = 0; + + *data = new Sample[info.frames]; + *length = info.frames; + + /* mix down to mono */ + + for (int i = 0; i < info.frames; ++i) { + (*data)[i] = 0; + for (int j = 0; j < info.channels; ++j) { + (*data)[i] = tmp[i * info.channels + j]; + } + (*data)[i] /= info.channels; } - - sf_close (sndfile); } + + delete[] tmp; + sf_close (sndfile); } -} +} + +void +Session::setup_click_sounds (int which) +{ + clear_clicks (); + + if (which == 0 || which == 1) { + setup_click_sounds ( + &click_data, + default_click, + &click_length, + default_click_length, + Config->get_click_sound () + ); + } + + if (which == 0 || which == -1) { + setup_click_sounds ( + &click_emphasis_data, + default_click_emphasis, + &click_emphasis_length, + default_click_emphasis_length, + Config->get_click_emphasis_sound () + ); + } +} void Session::clear_clicks () { - Glib::RWLock::WriterLock lm (click_lock); + Glib::Threads::RWLock::WriterLock lm (click_lock); for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) { delete *i; } clicks.clear (); + _clicks_cleared = _transport_frame; }