+MixersAlignMatchRevFarm::MixersAlignMatchRevFarm(int n, int cpus,
+ MixersAlign *dialog, double *ar, double *ai, int len)
+ : LoadServer(n, cpus)
+{
+ this->dialog = dialog;
+ this->ar = ar;
+ this->ai = ai;
+ this->len = len;
+ mixer_lock = new Mutex("MixersAlignMatchRevFarm::mixer_lock");
+ pos = -1;
+}
+MixersAlignMatchRevFarm::~MixersAlignMatchRevFarm()
+{
+ delete mixer_lock;
+}
+
+MixersAlignMatchRevPackage::MixersAlignMatchRevPackage()
+{
+ mix = 0;
+}
+MixersAlignMatchRevPackage::~MixersAlignMatchRevPackage()
+{
+}
+
+void MixersAlignMatchRevFarm::init_packages()
+{
+ for( int i=0,m=0,n=dialog->mixers.size(); m<n; ++m ) {
+ if( !dialog->mixers[m]->br ) continue;
+ MixersAlignMatchRevPackage *pkg = (MixersAlignMatchRevPackage *)get_package(i++);
+ pkg->mix = dialog->mixers[m];
+ }
+}
+
+LoadClient *MixersAlignMatchRevFarm::new_client()
+{
+ return new MixersAlignMatchRevClient(this);
+}
+LoadPackage *MixersAlignMatchRevFarm::new_package()
+{
+ return new MixersAlignMatchRevPackage();
+}
+
+void MixersAlignMatchRevClient::process_package(LoadPackage *package)
+{
+ MixersAlignMatchRevFarm *farm = (MixersAlignMatchRevFarm *)server;
+ MixersAlign *dialog = farm->dialog;
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
+ if( dialog->failed ) return;
+ pkg = (MixersAlignMatchRevPackage *)package;
+ MixersAlignMixer *mix = pkg->mix;
+ if( mix->aidx < 0 ) return;
+ int64_t ss = dialog->atracks[mix->aidx]->ss;
+
+ conj_product(farm->len, re, im, farm->ar, farm->ai, mix->br, mix->bi);
+ FFT fft;
+ fft.do_fft(farm->len, 1, re, im);
+ double mx = 0; int64_t mi = -1;
+ for( int i=0,n=farm->len/2; i<n; ++i ) {
+ double r = fabs(re[i]) / ss;
+ if( mx < r ) {
+ mx = r;
+ mi = i + farm->pos;
+ }
+ }
+ farm->mixer_lock->lock("MixersAlignMatchRevFarm::process_package");
+ if( mix->mx < mx ) {
+ mix->mx = mx;
+ mix->mi = mi;
+//printf("best %d: %f at %jd\n", get_package_number(), mx, mi);
+ }
+ farm->mixer_lock->unlock();
+}
+
+MixersAlignMatchRevClient::MixersAlignMatchRevClient(MixersAlignMatchRevFarm *farm)
+{
+ re = new double[farm->len];
+ im = new double[farm->len];
+}
+MixersAlignMatchRevClient::~MixersAlignMatchRevClient()
+{
+ delete [] re;
+ delete [] im;
+}
+
+void MixersAlign::start_progress(int64_t total_len)
+{
+ total_rendered = 0;
+ mwindow->gui->lock_window("MixersAlign::start_progress");
+ progress = mwindow->mainprogress->
+ start_progress(_("match mixer audio"), total_len);
+ mwindow->gui->unlock_window();
+}
+void MixersAlign::stop_progress(const char *msg)
+{
+ mwindow->gui->lock_window("MixersAlign::stop_progress");
+ progress->update(0);
+ mwindow->mainprogress->end_progress(progress);
+ progress = 0;
+ if( msg ) mwindow->gui->show_message(msg);
+ mwindow->gui->unlock_window();
+}
+
+void MixersAlign::reset_targets()
+{
+ for( int m=0,n=mixers.size(); m<n; ++m ) {
+ MixersAlignMixer *mix = mixers[m];
+ delete mix->br; mix->br = 0;
+ delete mix->bi; mix->bi = 0;
+ mix->mi = 0;
+ mix->aidx = -1;
+ }
+ for( int i=0,n=atracks.size(); i<n; ++i ) {
+ MixersAlignATrack *atrk = atracks[i];
+ atrk->nudge = 0; atrk->ss = 0;
+ atrk->mx = 0; atrk->mi = -1;
+ }
+}
+
+void MixersAlign::scan_targets()
+{
+ int idx = ma_gui->mtrack_list->get_selection_number(0, 0);
+ int midx = mmixer_of(idx);
+ int64_t total_len = mixer_tracks_total(midx);
+ start_progress(total_len);
+ int m = mixers.size();
+ if( midx >= 0 ) --m;
+ int cpus = bmin(mwindow->preferences->processors, m);
+ MixersAlignScanFarm scan(this, cpus, m);
+ scan.process_packages();
+ stop_progress(0);
+}
+