try to make peak building from scratch more efficient

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2445 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-09-10 21:53:13 +00:00
parent afcbba17f0
commit a0eca60f7a
4 changed files with 67 additions and 18 deletions

View file

@ -20,10 +20,14 @@
#ifndef __ardour_source_factory_h__
#define __ardour_source_factory_h__
#include <list>
#include <glibmm/thread.h>
#include <string>
#include <stdint.h>
#include <sigc++/sigc++.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <ardour/source.h>
#include <ardour/audiofilesource.h>
@ -36,6 +40,8 @@ class Session;
class SourceFactory {
public:
static void init ();
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
static boost::shared_ptr<Source> create (Session&, const XMLNode& node, bool async = false);
@ -45,7 +51,12 @@ class SourceFactory {
static boost::shared_ptr<Source> createReadable (Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true, bool async = false);
static boost::shared_ptr<Source> createWritable (Session&, std::string name, bool destructive, nframes_t rate, bool announce = true, bool async = false);
static Glib::Cond* PeaksToBuild;
static Glib::StaticMutex peak_building_lock;
static std::list<boost::weak_ptr<AudioSource> > files_with_peaks;
private:
static int setup_peakfile (boost::shared_ptr<Source>, bool async);
};

View file

@ -582,9 +582,10 @@ AudioSource::build_peaks_from_scratch ()
{
nframes_t current_frame;
nframes_t cnt;
Sample buf[frames_per_peak];
Sample* buf = 0;
nframes_t frames_read;
nframes_t frames_to_read;
nframes_t frames_to_read = 65536; // 256kB reads from disk, roughly ideal
int ret = -1;
{
@ -599,6 +600,7 @@ AudioSource::build_peaks_from_scratch ()
current_frame = 0;
cnt = _length;
_peaks_built = false;
buf = new Sample[frames_to_read];
while (cnt) {
@ -609,7 +611,7 @@ AudioSource::build_peaks_from_scratch ()
done_with_peakfile_writes (false);
goto out;
}
if (compute_and_write_peaks (buf, current_frame, frames_read, true, false)) {
break;
}
@ -617,7 +619,7 @@ AudioSource::build_peaks_from_scratch ()
current_frame += frames_read;
cnt -= frames_read;
}
if (cnt == 0) {
/* success */
truncate_peakfile();
@ -642,6 +644,10 @@ AudioSource::build_peaks_from_scratch ()
unlink (peakpath.c_str());
}
if (buf) {
delete [] buf;
}
return ret;
}
@ -719,9 +725,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
if (intermediate_peaks_ready) {
PeaksReady (); /* EMIT SIGNAL */
} else {
cerr << "skipped PR @ A\n";
}
}
}
/* left overs are done */
@ -833,10 +837,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
if (intermediate_peaks_ready) {
PeaksReady (); /* EMIT SIGNAL */
} else {
cerr << "skipped PR @ B\n";
}
}
ret = 0;

View file

@ -52,6 +52,7 @@
#include <ardour/audiosource.h>
#include <ardour/utils.h>
#include <ardour/session.h>
#include <ardour/source_factory.h>
#include <ardour/control_protocol_manager.h>
#ifdef HAVE_LIBLO
@ -301,6 +302,8 @@ ARDOUR::init (bool use_vst, bool try_optimization)
setup_hardware_optimization (try_optimization);
SourceFactory::init ();
/* singleton - first object is "it" */
new PluginManager ();

View file

@ -41,28 +41,62 @@ using namespace PBD;
using namespace sigc;
sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
Glib::Cond* SourceFactory::PeaksToBuild;
Glib::StaticMutex SourceFactory::peak_building_lock;
std::list<boost::weak_ptr<AudioSource> > SourceFactory::files_with_peaks;
static void setup_peakfile (boost::weak_ptr<AudioSource> was)
static void
peak_thread_work ()
{
boost::shared_ptr<AudioSource> as (was.lock());
PBD::ThreadCreated (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec));
if (!as) {
return;
while (true) {
SourceFactory::peak_building_lock.lock ();
SourceFactory::PeaksToBuild->wait (SourceFactory::peak_building_lock);
if (SourceFactory::files_with_peaks.empty()) {
continue;
}
boost::shared_ptr<AudioSource> as (SourceFactory::files_with_peaks.front().lock());
SourceFactory::files_with_peaks.pop_front ();
SourceFactory::peak_building_lock.unlock ();
if (!as) {
continue;
}
as->setup_peakfile ();
}
}
PBD::ThreadCreatedWithRequestSize (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec), 1024);
as->setup_peakfile ();
// PBD::ThreadLeaving (pthread_self());
void
SourceFactory::init ()
{
PeaksToBuild = new Glib::Cond();
for (int n = 0; n < 2; ++n) {
Glib::Thread::create (sigc::ptr_fun (::peak_thread_work), false);
}
}
int
SourceFactory::setup_peakfile (boost::shared_ptr<Source> s, bool async)
{
boost::shared_ptr<AudioSource> as (boost::dynamic_pointer_cast<AudioSource> (s));
if (as) {
if (async) {
Glib::Thread::create (bind (sigc::ptr_fun (::setup_peakfile), boost::weak_ptr<AudioSource>(as)), false);
Glib::Mutex::Lock lm (peak_building_lock);
files_with_peaks.push_back (boost::weak_ptr<AudioSource> (as));
PeaksToBuild->signal ();
} else {
if (as->setup_peakfile ()) {
error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg;
return -1;