lincoln's patch to use QM onset detection in RFerret, and other tweaks
git-svn-id: svn://localhost/ardour2/branches/3.0@9031 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
730cdb38bc
commit
5fb296cd6b
|
@ -56,7 +56,7 @@ static const gchar * _operation_strings[] = {
|
|||
RhythmFerret::RhythmFerret (Editor& e)
|
||||
: ArdourDialog (_("Rhythm Ferret"))
|
||||
, editor (e)
|
||||
, detection_threshold_adjustment (3, 0, 20, 1, 4)
|
||||
, detection_threshold_adjustment (0.015, 0.0, 0.1, 0.001, 0.1)
|
||||
, detection_threshold_scale (detection_threshold_adjustment)
|
||||
, sensitivity_adjustment (40, 0, 100, 1, 10)
|
||||
, sensitivity_scale (sensitivity_adjustment)
|
||||
|
@ -84,6 +84,7 @@ RhythmFerret::RhythmFerret (Editor& e)
|
|||
XXX there should be a non-hacky way to set this
|
||||
*/
|
||||
onset_detection_function_selector.set_active_text (onset_function_strings[3]);
|
||||
detection_threshold_scale.set_digits (3);
|
||||
|
||||
Table* t = manage (new Table (7, 3));
|
||||
t->set_spacings (12);
|
||||
|
@ -145,6 +146,7 @@ RhythmFerret::analysis_mode_changed ()
|
|||
{
|
||||
bool const perc = get_analysis_mode() == PercussionOnset;
|
||||
|
||||
trigger_gap_spinner.set_sensitive (!perc);
|
||||
detection_threshold_scale.set_sensitive (perc);
|
||||
sensitivity_scale.set_sensitive (perc);
|
||||
onset_detection_function_selector.set_sensitive (!perc);
|
||||
|
@ -230,20 +232,12 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readabl
|
|||
continue;
|
||||
}
|
||||
|
||||
/* translate all transients to give absolute position */
|
||||
|
||||
//for (AnalysisFeatureList::iterator x = these_results.begin(); x != these_results.end(); ++x) {
|
||||
// (*x) += offset;
|
||||
//}
|
||||
|
||||
/* merge */
|
||||
|
||||
results.insert (results.end(), these_results.begin(), these_results.end());
|
||||
these_results.clear ();
|
||||
}
|
||||
|
||||
if (!results.empty()) {
|
||||
TransientDetector::cleanup_transients (results, _session->frame_rate(), trigger_gap_adjustment.get_value());
|
||||
|
||||
t.update_positions (readable.get(), i, results);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -260,8 +254,10 @@ RhythmFerret::get_note_onset_function ()
|
|||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
fatal << string_compose (_("programming error: %1 (%2)"), X_("illegal note onset function string"), txt)
|
||||
<< endmsg;
|
||||
|
||||
/*NOTREACHED*/
|
||||
return -1;
|
||||
}
|
||||
|
@ -286,12 +282,6 @@ RhythmFerret::run_note_onset_analysis (boost::shared_ptr<Readable> readable, fra
|
|||
continue;
|
||||
}
|
||||
|
||||
/* translate all transients to give absolute position */
|
||||
|
||||
//for (AnalysisFeatureList::iterator x = these_results.begin(); x != these_results.end(); ++x) {
|
||||
// (*x) += offset;
|
||||
//}
|
||||
|
||||
/* merge */
|
||||
|
||||
results.insert (results.end(), these_results.begin(), these_results.end());
|
||||
|
@ -344,6 +334,8 @@ RhythmFerret::do_split_action ()
|
|||
if (regions.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.EditorFreeze(); /* Emit signal */
|
||||
|
||||
_session->begin_reversible_command (_("split regions (rhythm ferret)"));
|
||||
|
||||
|
@ -351,13 +343,13 @@ RhythmFerret::do_split_action ()
|
|||
AnalysisFeatureList merged_features;
|
||||
|
||||
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
|
||||
|
||||
AnalysisFeatureList features;
|
||||
features = (*i)->region()->transients();
|
||||
|
||||
|
||||
merged_features.insert (merged_features.end(), features.begin(), features.end());
|
||||
}
|
||||
|
||||
|
||||
merged_features.sort();
|
||||
merged_features.unique();
|
||||
|
||||
|
@ -368,16 +360,15 @@ RhythmFerret::do_split_action ()
|
|||
tmp = i;
|
||||
++tmp;
|
||||
|
||||
AnalysisFeatureList features;
|
||||
features = (*i)->region()->transients();
|
||||
editor.split_region_at_points ((*i)->region(), merged_features, false, true);
|
||||
editor.split_region_at_points ((*i)->region(), merged_features, false, false);
|
||||
|
||||
/* i is invalid at this point */
|
||||
|
||||
i = tmp;
|
||||
}
|
||||
|
||||
_session->commit_reversible_command ();
|
||||
|
||||
editor.EditorThaw(); /* Emit signal */
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -399,9 +390,11 @@ void
|
|||
RhythmFerret::clear_transients ()
|
||||
{
|
||||
current_results.clear ();
|
||||
|
||||
for (RegionSelection::iterator i = regions_with_transients.begin(); i != regions_with_transients.end(); ++i) {
|
||||
(*i)->region()->set_transients (current_results);
|
||||
}
|
||||
|
||||
regions_with_transients.clear ();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
namespace ARDOUR {
|
||||
|
||||
class AudioSource;
|
||||
class Readable;
|
||||
class Session;
|
||||
|
||||
class TransientDetector : public AudioAnalyser
|
||||
|
@ -43,14 +44,17 @@ class TransientDetector : public AudioAnalyser
|
|||
float get_sensitivity () const;
|
||||
|
||||
int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results);
|
||||
|
||||
void update_positions (Readable* src, uint32_t channel, AnalysisFeatureList& results);
|
||||
|
||||
static void cleanup_transients (AnalysisFeatureList&, float sr, float gap_msecs);
|
||||
|
||||
|
||||
protected:
|
||||
AnalysisFeatureList* current_results;
|
||||
int use_features (Vamp::Plugin::FeatureSet&, std::ostream*);
|
||||
|
||||
static std::string _op_id;
|
||||
float threshold;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "ardour/readable.h"
|
||||
#include "ardour/transient_detector.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
@ -9,18 +11,20 @@ using namespace std;
|
|||
|
||||
/* need a static initializer function for this */
|
||||
|
||||
string TransientDetector::_op_id = X_("libardourvampplugins:percussiononsets:2");
|
||||
string TransientDetector::_op_id = X_("libardourvampplugins:qm-onsetdetector:2");
|
||||
|
||||
TransientDetector::TransientDetector (float sr)
|
||||
: AudioAnalyser (sr, X_("libardourvampplugins:percussiononsets"))
|
||||
: AudioAnalyser (sr, X_("libardourvampplugins:qm-onsetdetector"))
|
||||
{
|
||||
/* update the op_id */
|
||||
|
||||
_op_id = X_("libardourvampplugins:percussiononsets");
|
||||
_op_id = X_("libardourvampplugins:qm-onsetdetector");
|
||||
|
||||
// XXX this should load the above-named plugin and get the current version
|
||||
|
||||
_op_id += ":2";
|
||||
|
||||
threshold = 0.00;
|
||||
}
|
||||
|
||||
TransientDetector::~TransientDetector()
|
||||
|
@ -40,6 +44,7 @@ TransientDetector::run (const std::string& path, Readable* src, uint32_t channel
|
|||
int ret = analyse (path, src, channel);
|
||||
|
||||
current_results = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -66,15 +71,14 @@ TransientDetector::use_features (Plugin::FeatureSet& features, ostream* out)
|
|||
void
|
||||
TransientDetector::set_threshold (float val)
|
||||
{
|
||||
if (plugin) {
|
||||
plugin->setParameter ("threshold", val);
|
||||
}
|
||||
threshold = val;
|
||||
}
|
||||
|
||||
void
|
||||
TransientDetector::set_sensitivity (float val)
|
||||
{
|
||||
if (plugin) {
|
||||
plugin->selectProgram ("Percussive onsets");
|
||||
plugin->setParameter ("sensitivity", val);
|
||||
}
|
||||
}
|
||||
|
@ -117,3 +121,52 @@ TransientDetector::cleanup_transients (AnalysisFeatureList& t, float sr, float g
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TransientDetector::update_positions (Readable* src, uint32_t channel, AnalysisFeatureList& positions)
|
||||
{
|
||||
Plugin::FeatureSet features;
|
||||
|
||||
Sample* data = 0;
|
||||
float* bufs[1] = { 0 };
|
||||
|
||||
int buff_size = 1024;
|
||||
int step_size = 64;
|
||||
|
||||
data = new Sample[buff_size];
|
||||
bufs[0] = data;
|
||||
|
||||
AnalysisFeatureList::iterator i = positions.begin();
|
||||
|
||||
while (i != positions.end()) {
|
||||
|
||||
framecnt_t to_read;
|
||||
|
||||
/* read from source */
|
||||
to_read = buff_size;
|
||||
|
||||
if (src->read (data, (*i) - buff_size, to_read, channel) != to_read) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Simple heuristic for locating approx correct cut position.
|
||||
|
||||
for (int j = 0; j < buff_size;){
|
||||
|
||||
Sample s = abs (data[j]);
|
||||
Sample s2 = abs (data[j + step_size]);
|
||||
|
||||
if ((s2 - s) > threshold){
|
||||
//cerr << "Thresh exceeded. Moving pos from: " << (*i) << " to: " << (*i) - buff_size + (j + 16) << endl;
|
||||
(*i) = (*i) - buff_size + (j + 24);
|
||||
break;
|
||||
}
|
||||
|
||||
j = j + step_size;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user