mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
Merge with 2.0-ongoing R2988
git-svn-id: svn://localhost/ardour2/branches/3.0@2991 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
9f63ab9931
commit
80c3677c83
70 changed files with 1442 additions and 398 deletions
|
|
@ -534,6 +534,7 @@ if env['LV2']:
|
||||||
if conf.CheckPKGExists ('\"slv2 >= 0.6.0\"'):
|
if conf.CheckPKGExists ('\"slv2 >= 0.6.0\"'):
|
||||||
libraries['slv2'] = LibraryInfo()
|
libraries['slv2'] = LibraryInfo()
|
||||||
libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
|
libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
|
||||||
|
env.Append (CCFLAGS="-DHAVE_LV2")
|
||||||
else:
|
else:
|
||||||
print 'Building Ardour with LV2 support requires SLV2 >= 0.6.0'
|
print 'Building Ardour with LV2 support requires SLV2 >= 0.6.0'
|
||||||
print 'WARNING: SLV2 not found, or too old. Ardour will be built without LV2 support.'
|
print 'WARNING: SLV2 not found, or too old. Ardour will be built without LV2 support.'
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,12 @@
|
||||||
(gtk_accel_path "<Actions>/Editor/cycle-snap-choice" "3")
|
(gtk_accel_path "<Actions>/Editor/cycle-snap-choice" "3")
|
||||||
(gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "4")
|
(gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "4")
|
||||||
(gtk_accel_path "<Actions>/Transport/ToggleClick" "5")
|
(gtk_accel_path "<Actions>/Transport/ToggleClick" "5")
|
||||||
|
(gtk_accel_path "<Actions>/Editor/tab-to-transient-forwards" "7")
|
||||||
|
(gtk_accel_path "<Actions>/Editor/tab-to-transient-backwards" "8")
|
||||||
(gtk_accel_path "<Actions>/Editor/set-tempo-from-region" "9")
|
(gtk_accel_path "<Actions>/Editor/set-tempo-from-region" "9")
|
||||||
(gtk_accel_path "<Actions>/Editor/set-tempo-from-edit-range" "0")
|
(gtk_accel_path "<Actions>/Editor/set-tempo-from-edit-range" "0")
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; unbound actions
|
;; unbound actions
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@
|
||||||
<Option name="ui-rc-file" value="ardour3_ui_dark.rc"/>
|
<Option name="ui-rc-file" value="ardour3_ui_dark.rc"/>
|
||||||
</UI>
|
</UI>
|
||||||
<Canvas>
|
<Canvas>
|
||||||
<Option name="waveform outline" value="0f0f0fcc"/>
|
<Option name="waveform outline" value="0f0f0fc8"/>
|
||||||
<Option name="waveform fill" value="3d475378"/>
|
<Option name="waveform fill" value="3d4753dc"/>
|
||||||
|
<Option name="selected waveform outline" value="0f0f0fcc"/>
|
||||||
|
<Option name="selected waveform fill" value="51518ac8"/>
|
||||||
<Option name="clipped waveform" value="ff0000e5"/>
|
<Option name="clipped waveform" value="ff0000e5"/>
|
||||||
<Option name="region base" value="99a7b5aa"/>
|
<Option name="region base" value="99a7b5a0"/>
|
||||||
<Option name="selected region base" value="b591a8ff"/>
|
<Option name="selected region base" value="51518aa0"/>
|
||||||
<Option name="midi frame base" value="698f9d6d"/>
|
<Option name="midi frame base" value="698f9d6d"/>
|
||||||
<Option name="audio track base" value="c6d3d868"/>
|
<Option name="audio track base" value="c6d3d868"/>
|
||||||
<Option name="audio bus base" value="dbd1ea68"/>
|
<Option name="audio bus base" value="dbd1ea68"/>
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
#include "ardour_dialog.h"
|
#include "ardour_dialog.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
|
#include "splash.h"
|
||||||
|
|
||||||
ArdourDialog::ArdourDialog (string title, bool modal, bool use_seperator)
|
ArdourDialog::ArdourDialog (string title, bool modal, bool use_seperator)
|
||||||
: Dialog (title, modal, use_seperator)
|
: Dialog (title, modal, use_seperator)
|
||||||
|
|
@ -66,3 +66,17 @@ ArdourDialog::on_unmap ()
|
||||||
{
|
{
|
||||||
Dialog::on_unmap ();
|
Dialog::on_unmap ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ArdourDialog::on_show ()
|
||||||
|
{
|
||||||
|
// never allow the splash screen to obscure any dialog
|
||||||
|
|
||||||
|
Splash* spl = Splash::instance();
|
||||||
|
|
||||||
|
if (spl) {
|
||||||
|
spl->pop_back ();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog::on_show ();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ class ArdourDialog : public Gtk::Dialog
|
||||||
bool on_enter_notify_event (GdkEventCrossing*);
|
bool on_enter_notify_event (GdkEventCrossing*);
|
||||||
bool on_leave_notify_event (GdkEventCrossing*);
|
bool on_leave_notify_event (GdkEventCrossing*);
|
||||||
void on_unmap ();
|
void on_unmap ();
|
||||||
|
void on_show ();
|
||||||
|
|
||||||
ARDOUR::Session *session;
|
ARDOUR::Session *session;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
|
||||||
|
|
||||||
ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
|
ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
|
||||||
|
|
||||||
|
/* handle sr mismatch with a dialog */
|
||||||
|
|
||||||
|
ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
|
||||||
|
|
||||||
/* lets get this party started */
|
/* lets get this party started */
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -403,6 +407,15 @@ ARDOUR_UI::~ARDOUR_UI ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ARDOUR_UI::pop_back_splash ()
|
||||||
|
{
|
||||||
|
if (Splash::instance()) {
|
||||||
|
// Splash::instance()->pop_back();
|
||||||
|
Splash::instance()->hide ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
ARDOUR_UI::configure_timeout ()
|
ARDOUR_UI::configure_timeout ()
|
||||||
{
|
{
|
||||||
|
|
@ -609,6 +622,7 @@ Please consider the possibilities, and perhaps (re)start JACK."));
|
||||||
|
|
||||||
win.show_all ();
|
win.show_all ();
|
||||||
win.set_position (Gtk::WIN_POS_CENTER);
|
win.set_position (Gtk::WIN_POS_CENTER);
|
||||||
|
pop_back_splash ();
|
||||||
|
|
||||||
/* we just don't care about the result, but we want to block */
|
/* we just don't care about the result, but we want to block */
|
||||||
|
|
||||||
|
|
@ -692,6 +706,8 @@ ARDOUR_UI::check_memory_locking ()
|
||||||
vbox->show();
|
vbox->show();
|
||||||
hbox.show ();
|
hbox.show ();
|
||||||
|
|
||||||
|
pop_back_splash ();
|
||||||
|
|
||||||
editor->ensure_float (msg);
|
editor->ensure_float (msg);
|
||||||
msg.run ();
|
msg.run ();
|
||||||
}
|
}
|
||||||
|
|
@ -725,6 +741,7 @@ ARDOUR_UI::finish()
|
||||||
Ardour was unable to save your session.\n\n\
|
Ardour was unable to save your session.\n\n\
|
||||||
If you still wish to quit, please use the\n\n\
|
If you still wish to quit, please use the\n\n\
|
||||||
\"Just quit\" option."));
|
\"Just quit\" option."));
|
||||||
|
pop_back_splash();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -997,8 +1014,27 @@ ARDOUR_UI::redisplay_recent_sessions ()
|
||||||
|
|
||||||
get_state_files_in_directory (*i, state_file_paths);
|
get_state_files_in_directory (*i, state_file_paths);
|
||||||
|
|
||||||
if (state_file_paths.empty()) {
|
vector<string*>* states;
|
||||||
// no state file?
|
vector<const gchar*> item;
|
||||||
|
string fullpath = (*i).to_string();
|
||||||
|
|
||||||
|
/* remove any trailing / */
|
||||||
|
|
||||||
|
if (fullpath[fullpath.length()-1] == '/') {
|
||||||
|
fullpath = fullpath.substr (0, fullpath.length()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check whether session still exists */
|
||||||
|
if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||||
|
/* session doesn't exist */
|
||||||
|
cerr << "skipping non-existent session " << fullpath << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now get available states for this session */
|
||||||
|
|
||||||
|
if ((states = Session::possible_states (fullpath)) == 0) {
|
||||||
|
/* no state file? */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1006,8 +1042,6 @@ ARDOUR_UI::redisplay_recent_sessions ()
|
||||||
|
|
||||||
Gtk::TreeModel::Row row = *(recent_session_model->append());
|
Gtk::TreeModel::Row row = *(recent_session_model->append());
|
||||||
|
|
||||||
const string fullpath = (*i).to_string();
|
|
||||||
|
|
||||||
row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
|
row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
|
||||||
row[recent_session_columns.fullpath] = fullpath;
|
row[recent_session_columns.fullpath] = fullpath;
|
||||||
|
|
||||||
|
|
@ -1153,6 +1187,7 @@ ARDOUR_UI::check_audioengine ()
|
||||||
if (!engine->connected()) {
|
if (!engine->connected()) {
|
||||||
MessageDialog msg (_("Ardour is not connected to JACK\n"
|
MessageDialog msg (_("Ardour is not connected to JACK\n"
|
||||||
"You cannot open or close sessions in this condition"));
|
"You cannot open or close sessions in this condition"));
|
||||||
|
pop_back_splash ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1309,6 +1344,7 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t
|
||||||
to create a new track or bus.\n\
|
to create a new track or bus.\n\
|
||||||
You should save Ardour, exit and\n\
|
You should save Ardour, exit and\n\
|
||||||
restart JACK with more ports."));
|
restart JACK with more ports."));
|
||||||
|
pop_back_splash ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1685,6 +1721,7 @@ JACK has either been shutdown or it\n\
|
||||||
disconnected Ardour because Ardour\n\
|
disconnected Ardour because Ardour\n\
|
||||||
was not fast enough. You can save the\n\
|
was not fast enough. You can save the\n\
|
||||||
session and/or try to reconnect to JACK ."));
|
session and/or try to reconnect to JACK ."));
|
||||||
|
pop_back_splash ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2026,6 +2063,7 @@ ARDOUR_UI::fontconfig_dialog ()
|
||||||
true,
|
true,
|
||||||
Gtk::MESSAGE_INFO,
|
Gtk::MESSAGE_INFO,
|
||||||
Gtk::BUTTONS_OK);
|
Gtk::BUTTONS_OK);
|
||||||
|
pop_back_splash ();
|
||||||
msg.show_all ();
|
msg.show_all ();
|
||||||
msg.present ();
|
msg.present ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
|
|
@ -2116,6 +2154,7 @@ ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path
|
||||||
msg.set_name (X_("CleanupDialog"));
|
msg.set_name (X_("CleanupDialog"));
|
||||||
msg.set_wmclass (X_("existing_session"), "Ardour");
|
msg.set_wmclass (X_("existing_session"), "Ardour");
|
||||||
msg.set_position (Gtk::WIN_POS_MOUSE);
|
msg.set_position (Gtk::WIN_POS_MOUSE);
|
||||||
|
pop_back_splash ();
|
||||||
|
|
||||||
switch (msg.run()) {
|
switch (msg.run()) {
|
||||||
case RESPONSE_YES:
|
case RESPONSE_YES:
|
||||||
|
|
@ -2325,6 +2364,7 @@ ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be
|
||||||
session_path = new_session_dialog->session_folder();
|
session_path = new_session_dialog->session_folder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template_name = Glib::ustring();
|
||||||
switch (new_session_dialog->which_page()) {
|
switch (new_session_dialog->which_page()) {
|
||||||
|
|
||||||
case NewSessionDialog::OpenPage:
|
case NewSessionDialog::OpenPage:
|
||||||
|
|
@ -2374,7 +2414,7 @@ ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be
|
||||||
loadit:
|
loadit:
|
||||||
new_session_dialog->hide ();
|
new_session_dialog->hide ();
|
||||||
|
|
||||||
if (load_session (session_path, session_name)) {
|
if (load_session (session_path, session_name, template_name)) {
|
||||||
/* force a retry */
|
/* force a retry */
|
||||||
response = Gtk::RESPONSE_NONE;
|
response = Gtk::RESPONSE_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -2435,6 +2475,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na
|
||||||
if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
|
if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
|
||||||
MessageDialog msg (*editor, _("You do not have write access to this session.\n"
|
MessageDialog msg (*editor, _("You do not have write access to this session.\n"
|
||||||
"This prevents the session from being loaded."));
|
"This prevents the session from being loaded."));
|
||||||
|
pop_back_splash ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -2458,6 +2499,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na
|
||||||
msg.set_title (_("Loading Error"));
|
msg.set_title (_("Loading Error"));
|
||||||
msg.set_secondary_text (_("Click the OK button to try again."));
|
msg.set_secondary_text (_("Click the OK button to try again."));
|
||||||
msg.set_position (Gtk::WIN_POS_CENTER);
|
msg.set_position (Gtk::WIN_POS_CENTER);
|
||||||
|
pop_back_splash ();
|
||||||
msg.present ();
|
msg.present ();
|
||||||
|
|
||||||
int response = msg.run ();
|
int response = msg.run ();
|
||||||
|
|
@ -2483,6 +2525,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na
|
||||||
msg.set_title (_("Loading Error"));
|
msg.set_title (_("Loading Error"));
|
||||||
msg.set_secondary_text (_("Click the OK button to try again."));
|
msg.set_secondary_text (_("Click the OK button to try again."));
|
||||||
msg.set_position (Gtk::WIN_POS_CENTER);
|
msg.set_position (Gtk::WIN_POS_CENTER);
|
||||||
|
pop_back_splash ();
|
||||||
msg.present ();
|
msg.present ();
|
||||||
|
|
||||||
int response = msg.run ();
|
int response = msg.run ();
|
||||||
|
|
@ -2555,6 +2598,7 @@ ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_n
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
|
||||||
MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
|
MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
|
||||||
|
pop_back_splash ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -3031,6 +3075,38 @@ what you would like to do.\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
|
||||||
|
{
|
||||||
|
HBox* hbox = new HBox();
|
||||||
|
Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
|
||||||
|
ArdourDialog dialog (_("Sample Rate Mismatch"), true);
|
||||||
|
Label message (string_compose (_("\
|
||||||
|
This session was created with a sample rate of %1 Hz\n\
|
||||||
|
\n\
|
||||||
|
The audioengine is currently running at %2 Hz\n"), desired, actual));
|
||||||
|
|
||||||
|
image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
|
||||||
|
hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
|
||||||
|
hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
|
||||||
|
dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
|
||||||
|
dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
|
||||||
|
dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
|
||||||
|
dialog.set_default_response (RESPONSE_ACCEPT);
|
||||||
|
dialog.set_position (WIN_POS_CENTER);
|
||||||
|
message.show();
|
||||||
|
image->show();
|
||||||
|
hbox->show();
|
||||||
|
|
||||||
|
switch (dialog.run ()) {
|
||||||
|
case RESPONSE_ACCEPT:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR_UI::disconnect_from_jack ()
|
ARDOUR_UI::disconnect_from_jack ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -660,7 +660,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI
|
||||||
|
|
||||||
About* about;
|
About* about;
|
||||||
Splash* splash;
|
Splash* splash;
|
||||||
|
void pop_back_splash ();
|
||||||
bool shown_flag;
|
bool shown_flag;
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
|
|
||||||
Gtk::MenuItem *cleanup_item;
|
Gtk::MenuItem *cleanup_item;
|
||||||
|
|
@ -682,6 +684,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
|
||||||
void disk_underrun_handler ();
|
void disk_underrun_handler ();
|
||||||
|
|
||||||
int pending_state_dialog ();
|
int pending_state_dialog ();
|
||||||
|
int sr_mismatch_dialog (nframes_t, nframes_t);
|
||||||
|
|
||||||
void disconnect_from_jack ();
|
void disconnect_from_jack ();
|
||||||
void reconnect_to_jack ();
|
void reconnect_to_jack ();
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ ARDOUR_UI::shutdown ()
|
||||||
session->remove_pending_capture_state ();
|
session->remove_pending_capture_state ();
|
||||||
session = 0;
|
session = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_config->save_state();
|
ui_config->save_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1220,14 +1220,15 @@ AudioRegionView::set_frame_color ()
|
||||||
uint32_t r,g,b,a;
|
uint32_t r,g,b,a;
|
||||||
|
|
||||||
if (_selected && should_show_selection) {
|
if (_selected && should_show_selection) {
|
||||||
frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_WaveForm.get();
|
UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get(), &r, &g, &b, &a);
|
||||||
|
frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);
|
||||||
|
|
||||||
UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a);
|
|
||||||
for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
|
for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
|
||||||
if (_region->muted()) {
|
if (_region->muted()) {
|
||||||
(*w)->property_wave_color() = RGBA_TO_UINT(r, g, b, MUTED_ALPHA);
|
(*w)->property_wave_color() = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_SelectedWaveForm.get(), MUTED_ALPHA);
|
||||||
} else {
|
} else {
|
||||||
(*w)->property_wave_color() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);// Lets still use the theme's opacity value if Opaque is not set
|
(*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedWaveForm.get();
|
||||||
|
(*w)->property_fill_color() = ARDOUR_UI::config()->canvasvar_SelectedWaveFormFill.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
CANVAS_VARIABLE(canvasvar_WaveForm, "waveform outline")
|
CANVAS_VARIABLE(canvasvar_WaveForm, "waveform outline")
|
||||||
CANVAS_VARIABLE(canvasvar_WaveFormFill, "waveform fill")
|
CANVAS_VARIABLE(canvasvar_WaveFormFill, "waveform fill")
|
||||||
|
CANVAS_VARIABLE(canvasvar_SelectedWaveForm, "selected waveform outline")
|
||||||
|
CANVAS_VARIABLE(canvasvar_SelectedWaveFormFill, "selected waveform fill")
|
||||||
CANVAS_VARIABLE(canvasvar_WaveFormClip, "clipped waveform")
|
CANVAS_VARIABLE(canvasvar_WaveFormClip, "clipped waveform")
|
||||||
CANVAS_VARIABLE(canvasvar_FrameBase, "region base")
|
CANVAS_VARIABLE(canvasvar_FrameBase, "region base")
|
||||||
CANVAS_VARIABLE(canvasvar_SelectedFrameBase, "selected region base")
|
CANVAS_VARIABLE(canvasvar_SelectedFrameBase, "selected region base")
|
||||||
|
|
|
||||||
|
|
@ -1803,12 +1803,25 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
|
||||||
|
|
||||||
items.push_back (CheckMenuElem (_("Lock")));
|
items.push_back (CheckMenuElem (_("Lock")));
|
||||||
CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
|
CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
|
||||||
fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
|
|
||||||
if (region->locked()) {
|
if (region->locked()) {
|
||||||
fooc.block (true);
|
|
||||||
region_lock_item->set_active();
|
region_lock_item->set_active();
|
||||||
fooc.block (false);
|
|
||||||
}
|
}
|
||||||
|
region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
|
||||||
|
|
||||||
|
items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
|
||||||
|
CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
|
||||||
|
|
||||||
|
switch (region->positional_lock_style()) {
|
||||||
|
case Region::MusicTime:
|
||||||
|
bbt_glue_item->set_active (true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bbt_glue_item->set_active (true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
|
||||||
|
|
||||||
items.push_back (CheckMenuElem (_("Mute")));
|
items.push_back (CheckMenuElem (_("Mute")));
|
||||||
CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
|
CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
|
||||||
fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
|
fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
|
||||||
|
|
@ -3366,15 +3379,25 @@ Editor::hide_verbose_canvas_cursor ()
|
||||||
verbose_cursor_visible = false;
|
verbose_cursor_visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
Editor::clamp_verbose_cursor_x (double x)
|
||||||
|
{
|
||||||
|
return min (horizontal_adjustment.get_value() + canvas_width - 75.0, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
Editor::clamp_verbose_cursor_y (double y)
|
||||||
|
{
|
||||||
|
return min (vertical_adjustment.get_value() + canvas_height - 50.0, y);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::set_verbose_canvas_cursor (const string & txt, double x, double y)
|
Editor::set_verbose_canvas_cursor (const string & txt, double x, double y)
|
||||||
{
|
{
|
||||||
/* XXX get origin of canvas relative to root window,
|
|
||||||
add x and y and check compared to gdk_screen_{width,height}
|
|
||||||
*/
|
|
||||||
verbose_canvas_cursor->property_text() = txt.c_str();
|
verbose_canvas_cursor->property_text() = txt.c_str();
|
||||||
verbose_canvas_cursor->property_x() = x;
|
/* don't get too close to the edge */
|
||||||
verbose_canvas_cursor->property_y() = y;
|
verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (x);
|
||||||
|
verbose_canvas_cursor->property_y() = clamp_verbose_cursor_x (y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -1019,7 +1019,7 @@ class Editor : public PublicEditor
|
||||||
void toggle_region_mute ();
|
void toggle_region_mute ();
|
||||||
void toggle_region_lock ();
|
void toggle_region_lock ();
|
||||||
void toggle_region_opaque ();
|
void toggle_region_opaque ();
|
||||||
void toggle_region_position_lock ();
|
void set_region_lock_style (ARDOUR::Region::PositionLockStyle);
|
||||||
void raise_region ();
|
void raise_region ();
|
||||||
void raise_region_to_top ();
|
void raise_region_to_top ();
|
||||||
void lower_region ();
|
void lower_region ();
|
||||||
|
|
@ -1028,7 +1028,7 @@ class Editor : public PublicEditor
|
||||||
void split_region_at (nframes_t);
|
void split_region_at (nframes_t);
|
||||||
void split_regions_at (nframes_t, RegionSelection&);
|
void split_regions_at (nframes_t, RegionSelection&);
|
||||||
void split_region_at_transients ();
|
void split_region_at_transients ();
|
||||||
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, std::vector<nframes64_t>&);
|
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&);
|
||||||
void crop_region_to_selection ();
|
void crop_region_to_selection ();
|
||||||
void crop_region_to (nframes_t start, nframes_t end);
|
void crop_region_to (nframes_t start, nframes_t end);
|
||||||
void set_sync_point (nframes64_t, const RegionSelection&);
|
void set_sync_point (nframes64_t, const RegionSelection&);
|
||||||
|
|
@ -1334,6 +1334,8 @@ class Editor : public PublicEditor
|
||||||
|
|
||||||
void show_verbose_time_cursor (nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1);
|
void show_verbose_time_cursor (nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1);
|
||||||
void show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset = 0, double xpos=-1, double ypos=-1);
|
void show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset = 0, double xpos=-1, double ypos=-1);
|
||||||
|
double clamp_verbose_cursor_x (double);
|
||||||
|
double clamp_verbose_cursor_y (double);
|
||||||
|
|
||||||
/* Canvas event handlers */
|
/* Canvas event handlers */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ Editor::register_actions ()
|
||||||
|
|
||||||
act = ActionManager::register_action (editor_actions, "tab-to-transient-forwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), true));
|
act = ActionManager::register_action (editor_actions, "tab-to-transient-forwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), true));
|
||||||
ActionManager::session_sensitive_actions.push_back (act);
|
ActionManager::session_sensitive_actions.push_back (act);
|
||||||
act = ActionManager::register_action (editor_actions, "tab-to-transient-backwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), false));
|
act = ActionManager::register_action (editor_actions, "tab-to-transient-backwards", _("Move Backwards to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), false));
|
||||||
ActionManager::session_sensitive_actions.push_back (act);
|
ActionManager::session_sensitive_actions.push_back (act);
|
||||||
|
|
||||||
act = ActionManager::register_action (editor_actions, "crop", _("Crop"), mem_fun(*this, &Editor::crop_region_to_selection));
|
act = ActionManager::register_action (editor_actions, "crop", _("Crop"), mem_fun(*this, &Editor::crop_region_to_selection));
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <pbd/stacktrace.h>
|
#include <pbd/stacktrace.h>
|
||||||
|
|
||||||
|
|
@ -43,6 +44,7 @@
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace sigc;
|
using namespace sigc;
|
||||||
|
using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
using namespace Gtk;
|
using namespace Gtk;
|
||||||
|
|
@ -245,8 +247,8 @@ bool
|
||||||
Editor::track_canvas_motion (GdkEvent *ev)
|
Editor::track_canvas_motion (GdkEvent *ev)
|
||||||
{
|
{
|
||||||
if (verbose_cursor_visible) {
|
if (verbose_cursor_visible) {
|
||||||
verbose_canvas_cursor->property_x() = ev->motion.x + 20;
|
verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 20);
|
||||||
verbose_canvas_cursor->property_y() = ev->motion.y + 20;
|
verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GTKOSX
|
#ifdef GTKOSX
|
||||||
|
|
|
||||||
|
|
@ -3382,7 +3382,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sync_frame - sync_offset <= sync_frame) {
|
if (sync_frame - sync_offset <= sync_frame) {
|
||||||
pending_region_position = sync_frame + (sync_dir*sync_offset);
|
pending_region_position = sync_frame - (sync_dir*sync_offset);
|
||||||
} else {
|
} else {
|
||||||
pending_region_position = 0;
|
pending_region_position = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "time_axis_view.h"
|
#include "time_axis_view.h"
|
||||||
|
#include "route_time_axis.h"
|
||||||
#include "audio_time_axis.h"
|
#include "audio_time_axis.h"
|
||||||
#include "automation_time_axis.h"
|
#include "automation_time_axis.h"
|
||||||
#include "streamview.h"
|
#include "streamview.h"
|
||||||
|
|
@ -1659,7 +1660,6 @@ Editor::temporal_zoom_region ()
|
||||||
ensure_entered_region_selected (true);
|
ensure_entered_region_selected (true);
|
||||||
|
|
||||||
if (selection->regions.empty()) {
|
if (selection->regions.empty()) {
|
||||||
info << _("cannot set loop: no region selected") << endmsg;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3540,13 +3540,11 @@ Editor::cut_copy (CutCopyOp op)
|
||||||
|
|
||||||
switch (current_mouse_mode()) {
|
switch (current_mouse_mode()) {
|
||||||
case MouseObject:
|
case MouseObject:
|
||||||
cerr << "cutting in object mode\n";
|
|
||||||
if (!selection->regions.empty() || !selection->points.empty()) {
|
if (!selection->regions.empty() || !selection->points.empty()) {
|
||||||
|
|
||||||
begin_reversible_command (opname + _(" objects"));
|
begin_reversible_command (opname + _(" objects"));
|
||||||
|
|
||||||
if (!selection->regions.empty()) {
|
if (!selection->regions.empty()) {
|
||||||
cerr << "have regions to cut" << endl;
|
|
||||||
cut_copy_regions (op);
|
cut_copy_regions (op);
|
||||||
|
|
||||||
if (op == Cut) {
|
if (op == Cut) {
|
||||||
|
|
@ -3565,7 +3563,6 @@ Editor::cut_copy (CutCopyOp op)
|
||||||
commit_reversible_command ();
|
commit_reversible_command ();
|
||||||
break; // terminate case statement here
|
break; // terminate case statement here
|
||||||
}
|
}
|
||||||
cerr << "nope, now cutting time range" << endl;
|
|
||||||
if (!selection->time.empty()) {
|
if (!selection->time.empty()) {
|
||||||
/* don't cause suprises */
|
/* don't cause suprises */
|
||||||
break;
|
break;
|
||||||
|
|
@ -3575,9 +3572,7 @@ Editor::cut_copy (CutCopyOp op)
|
||||||
case MouseRange:
|
case MouseRange:
|
||||||
if (selection->time.empty()) {
|
if (selection->time.empty()) {
|
||||||
nframes64_t start, end;
|
nframes64_t start, end;
|
||||||
cerr << "no time selection, get edit op range" << endl;
|
|
||||||
if (!get_edit_op_range (start, end)) {
|
if (!get_edit_op_range (start, end)) {
|
||||||
cerr << "no edit op range" << endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selection->set ((TimeAxisView*) 0, start, end);
|
selection->set ((TimeAxisView*) 0, start, end);
|
||||||
|
|
@ -4375,6 +4370,15 @@ Editor::toggle_region_lock ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Editor::set_region_lock_style (Region::PositionLockStyle ps)
|
||||||
|
{
|
||||||
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
||||||
|
(*i)->region()->set_position_lock_style (ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::toggle_region_mute ()
|
Editor::toggle_region_mute ()
|
||||||
{
|
{
|
||||||
|
|
@ -5016,28 +5020,67 @@ Editor::define_one_bar (nframes64_t start, nframes64_t end)
|
||||||
|
|
||||||
const Meter& m (session->tempo_map().meter_at (start));
|
const Meter& m (session->tempo_map().meter_at (start));
|
||||||
|
|
||||||
/* region length = 1 bar */
|
/* length = 1 bar */
|
||||||
|
|
||||||
/* 1 bar = how many beats per bar */
|
|
||||||
|
|
||||||
double beats_per_bar = m.beats_per_bar();
|
|
||||||
|
|
||||||
/* now we want frames per beat.
|
/* now we want frames per beat.
|
||||||
we have frames per bar, and beats per bar, so ...
|
we have frames per bar, and beats per bar, so ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double frames_per_beat = length / beats_per_bar;
|
double frames_per_beat = length / m.beats_per_bar();
|
||||||
|
|
||||||
/* beats per minute = */
|
/* beats per minute = */
|
||||||
|
|
||||||
double beats_per_minute = (session->frame_rate() * 60.0) / frames_per_beat;
|
double beats_per_minute = (session->frame_rate() * 60.0) / frames_per_beat;
|
||||||
|
|
||||||
|
/* now decide whether to:
|
||||||
|
|
||||||
|
(a) set global tempo
|
||||||
|
(b) add a new tempo marker
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
const TempoSection& t (session->tempo_map().tempo_section_at (start));
|
const TempoSection& t (session->tempo_map().tempo_section_at (start));
|
||||||
|
|
||||||
|
bool do_global = false;
|
||||||
|
|
||||||
|
if ((session->tempo_map().n_tempos() == 1) && (session->tempo_map().n_meters() == 1)) {
|
||||||
|
|
||||||
|
/* only 1 tempo & 1 meter: ask if the user wants to set the tempo
|
||||||
|
at the start, or create a new marker
|
||||||
|
*/
|
||||||
|
|
||||||
|
vector<string> options;
|
||||||
|
options.push_back (_("Set global tempo"));
|
||||||
|
options.push_back (_("Add new marker"));
|
||||||
|
options.push_back (_("Cancel"));
|
||||||
|
Choice c (_("Do you want to set the global tempo or add new tempo marker?"),
|
||||||
|
options);
|
||||||
|
|
||||||
|
switch (c.run()) {
|
||||||
|
case 0:
|
||||||
|
do_global = true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
do_global = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* more than 1 tempo and/or meter section already, go ahead do the "usual":
|
||||||
|
if the marker is at the region starter, change it, otherwise add
|
||||||
|
a new tempo marker
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
begin_reversible_command (_("set tempo from region"));
|
begin_reversible_command (_("set tempo from region"));
|
||||||
XMLNode& before (session->tempo_map().get_state());
|
XMLNode& before (session->tempo_map().get_state());
|
||||||
|
|
||||||
if (t.frame() == start) {
|
if (do_global) {
|
||||||
|
session->tempo_map().change_initial_tempo (beats_per_minute, t.note_type());
|
||||||
|
} else if (t.frame() == start) {
|
||||||
session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type());
|
session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type());
|
||||||
} else {
|
} else {
|
||||||
session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), start);
|
session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), start);
|
||||||
|
|
@ -5052,7 +5095,7 @@ Editor::define_one_bar (nframes64_t start, nframes64_t end)
|
||||||
void
|
void
|
||||||
Editor::split_region_at_transients ()
|
Editor::split_region_at_transients ()
|
||||||
{
|
{
|
||||||
vector<nframes64_t> positions;
|
AnalysisFeatureList positions;
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -5088,7 +5131,7 @@ Editor::split_region_at_transients ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t>& positions)
|
Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList& positions)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
|
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
|
||||||
|
|
||||||
|
|
@ -5106,7 +5149,7 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<nframes64_t>::const_iterator x;
|
AnalysisFeatureList::const_iterator x;
|
||||||
|
|
||||||
nframes64_t pos = ar->position();
|
nframes64_t pos = ar->position();
|
||||||
|
|
||||||
|
|
@ -5163,30 +5206,52 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t>
|
||||||
void
|
void
|
||||||
Editor::tab_to_transient (bool forward)
|
Editor::tab_to_transient (bool forward)
|
||||||
{
|
{
|
||||||
|
AnalysisFeatureList positions;
|
||||||
vector<nframes64_t> positions;
|
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusiveRegionSelection esr (*this, entered_regionview);
|
|
||||||
|
|
||||||
if (selection->regions.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (selection->regions.front()->region());
|
|
||||||
|
|
||||||
if (!ar) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ar->get_transients (positions);
|
|
||||||
nframes64_t pos = session->audible_frame ();
|
nframes64_t pos = session->audible_frame ();
|
||||||
|
|
||||||
|
if (!selection->tracks.empty()) {
|
||||||
|
|
||||||
|
for (TrackSelection::iterator t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
|
||||||
|
|
||||||
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*t);
|
||||||
|
|
||||||
|
if (rtv) {
|
||||||
|
boost::shared_ptr<Diskstream> ds = rtv->get_diskstream();
|
||||||
|
if (ds) {
|
||||||
|
boost::shared_ptr<Playlist> pl = rtv->get_diskstream()->playlist ();
|
||||||
|
if (pl) {
|
||||||
|
nframes64_t result = pl->find_next_transient (pos, forward ? 1 : -1);
|
||||||
|
|
||||||
|
if (result >= 0) {
|
||||||
|
positions.push_back (result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ExclusiveRegionSelection esr (*this, entered_regionview);
|
||||||
|
|
||||||
|
if (selection->regions.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
|
||||||
|
(*r)->region()->get_transients (positions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TransientDetector::cleanup_transients (positions, session->frame_rate(), 3.0);
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
vector<nframes64_t>::iterator x;
|
AnalysisFeatureList::iterator x;
|
||||||
|
|
||||||
for (x = positions.begin(); x != positions.end(); ++x) {
|
for (x = positions.begin(); x != positions.end(); ++x) {
|
||||||
if ((*x) > pos) {
|
if ((*x) > pos) {
|
||||||
|
|
@ -5199,7 +5264,7 @@ Editor::tab_to_transient (bool forward)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
vector<nframes64_t>::reverse_iterator x;
|
AnalysisFeatureList::reverse_iterator x;
|
||||||
|
|
||||||
for (x = positions.rbegin(); x != positions.rend(); ++x) {
|
for (x = positions.rbegin(); x != positions.rend(); ++x) {
|
||||||
if ((*x) < pos) {
|
if ((*x) < pos) {
|
||||||
|
|
|
||||||
|
|
@ -365,10 +365,14 @@ Editor::edit_tempo_section (TempoSection* section)
|
||||||
tempo_dialog.get_bbt_time(when);
|
tempo_dialog.get_bbt_time(when);
|
||||||
bpm = max (0.01, bpm);
|
bpm = max (0.01, bpm);
|
||||||
|
|
||||||
|
cerr << "Editing tempo section to be at " << when << endl;
|
||||||
|
session->tempo_map().dump (cerr);
|
||||||
begin_reversible_command (_("replace tempo mark"));
|
begin_reversible_command (_("replace tempo mark"));
|
||||||
XMLNode &before = session->tempo_map().get_state();
|
XMLNode &before = session->tempo_map().get_state();
|
||||||
session->tempo_map().replace_tempo (*section, Tempo (bpm,nt));
|
session->tempo_map().replace_tempo (*section, Tempo (bpm,nt));
|
||||||
|
session->tempo_map().dump (cerr);
|
||||||
session->tempo_map().move_tempo (*section, when);
|
session->tempo_map().move_tempo (*section, when);
|
||||||
|
session->tempo_map().dump (cerr);
|
||||||
XMLNode &after = session->tempo_map().get_state();
|
XMLNode &after = session->tempo_map().get_state();
|
||||||
session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
|
session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
|
||||||
commit_reversible_command ();
|
commit_reversible_command ();
|
||||||
|
|
|
||||||
|
|
@ -553,10 +553,12 @@ EngineControl::setup_engine ()
|
||||||
error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg;
|
error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
cerr << "JACK COMMAND: ";
|
||||||
for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) {
|
for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) {
|
||||||
|
cerr << (*i) << ' ';
|
||||||
jackdrc << (*i) << ' ';
|
jackdrc << (*i) << ' ';
|
||||||
}
|
}
|
||||||
|
cerr << endl;
|
||||||
jackdrc << endl;
|
jackdrc << endl;
|
||||||
jackdrc.close ();
|
jackdrc.close ();
|
||||||
|
|
||||||
|
|
@ -915,7 +917,7 @@ EngineControl::find_jack_servers (vector<string>& strings)
|
||||||
|
|
||||||
_NSGetExecutablePath (execpath, &pathsz);
|
_NSGetExecutablePath (execpath, &pathsz);
|
||||||
|
|
||||||
Glib::ustring path (Glib::path_get_dirname (execpath));
|
string path (Glib::path_get_dirname (execpath));
|
||||||
path += "/jackd";
|
path += "/jackd";
|
||||||
|
|
||||||
if (Glib::file_test (path, FILE_TEST_EXISTS)) {
|
if (Glib::file_test (path, FILE_TEST_EXISTS)) {
|
||||||
|
|
@ -937,8 +939,36 @@ EngineControl::find_jack_servers (vector<string>& strings)
|
||||||
PathScanner scanner;
|
PathScanner scanner;
|
||||||
vector<string *> *jack_servers;
|
vector<string *> *jack_servers;
|
||||||
std::map<string,int> un;
|
std::map<string,int> un;
|
||||||
|
char *p;
|
||||||
|
bool need_minimal_path = false;
|
||||||
|
|
||||||
path = getenv ("PATH");
|
p = getenv ("PATH");
|
||||||
|
|
||||||
|
if (p && *p) {
|
||||||
|
path = p;
|
||||||
|
} else {
|
||||||
|
need_minimal_path = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// many mac users don't have PATH set up to include
|
||||||
|
// likely installed locations of JACK
|
||||||
|
need_minimal_path = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (need_minimal_path) {
|
||||||
|
if (path.empty()) {
|
||||||
|
path = "/usr/bin:/bin:/usr/local/bin:/opt/local/bin";
|
||||||
|
} else {
|
||||||
|
path += ":/usr/local/bin:/opt/local/bin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// push it back into the environment so that auto-started JACK can find it.
|
||||||
|
// XXX why can't we just expect OS X users to have PATH set correctly? we can't ...
|
||||||
|
setenv ("PATH", path.c_str(), 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
jack_servers = scanner (path, jack_server_filter, 0, false, true);
|
jack_servers = scanner (path, jack_server_filter, 0, false, true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,9 @@
|
||||||
#include <ardour/plugin.h>
|
#include <ardour/plugin.h>
|
||||||
#include <ardour/plugin_insert.h>
|
#include <ardour/plugin_insert.h>
|
||||||
#include <ardour/ladspa_plugin.h>
|
#include <ardour/ladspa_plugin.h>
|
||||||
|
#ifdef HAVE_LV2
|
||||||
#include <ardour/lv2_plugin.h>
|
#include <ardour/lv2_plugin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <lrdf.h>
|
#include <lrdf.h>
|
||||||
|
|
||||||
|
|
@ -385,8 +387,9 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
|
||||||
if (plugin->parameter_is_input (port_index)) {
|
if (plugin->parameter_is_input (port_index)) {
|
||||||
|
|
||||||
boost::shared_ptr<LadspaPlugin> lp;
|
boost::shared_ptr<LadspaPlugin> lp;
|
||||||
|
#ifdef HAVE_LV2
|
||||||
boost::shared_ptr<LV2Plugin> lv2p;
|
boost::shared_ptr<LV2Plugin> lv2p;
|
||||||
|
#endif
|
||||||
if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
|
if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
|
||||||
|
|
||||||
// FIXME: not all plugins have a numeric unique ID
|
// FIXME: not all plugins have a numeric unique ID
|
||||||
|
|
@ -409,6 +412,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
|
||||||
return control_ui;
|
return control_ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LV2
|
||||||
} else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin>(plugin)) != 0) {
|
} else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin>(plugin)) != 0) {
|
||||||
|
|
||||||
SLV2Port port = lv2p->slv2_port(port_index);
|
SLV2Port port = lv2p->slv2_port(port_index);
|
||||||
|
|
@ -428,6 +432,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
|
||||||
slv2_scale_points_free(points);
|
slv2_scale_points_free(points);
|
||||||
return control_ui;
|
return control_ui;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.toggled) {
|
if (desc.toggled) {
|
||||||
|
|
@ -757,7 +762,9 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
|
||||||
{
|
{
|
||||||
vector<string> enums;
|
vector<string> enums;
|
||||||
boost::shared_ptr<LadspaPlugin> lp;
|
boost::shared_ptr<LadspaPlugin> lp;
|
||||||
|
#ifdef HAVE_LV2
|
||||||
boost::shared_ptr<LV2Plugin> lv2p;
|
boost::shared_ptr<LV2Plugin> lv2p;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
|
if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
|
||||||
// all LADPSA plugins have a numeric unique ID
|
// all LADPSA plugins have a numeric unique ID
|
||||||
|
|
@ -777,6 +784,7 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
|
||||||
lrdf_free_setting_values(defaults);
|
lrdf_free_setting_values(defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LV2
|
||||||
} else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin>(plugin)) != 0) {
|
} else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin>(plugin)) != 0) {
|
||||||
|
|
||||||
SLV2Port port = lv2p->slv2_port(port_index);
|
SLV2Port port = lv2p->slv2_port(port_index);
|
||||||
|
|
@ -797,6 +805,7 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
|
||||||
}
|
}
|
||||||
|
|
||||||
slv2_scale_points_free(points);
|
slv2_scale_points_free(points);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
BIN
gtk2_ardour/icons/ferret_02.png
Normal file
BIN
gtk2_ardour/icons/ferret_02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
|
|
@ -971,6 +971,8 @@ NewSessionDialog::reset_recent()
|
||||||
i != session_directories.end(); ++i)
|
i != session_directories.end(); ++i)
|
||||||
{
|
{
|
||||||
std::vector<sys::path> state_file_paths;
|
std::vector<sys::path> state_file_paths;
|
||||||
|
std::vector<std::string*>* states;
|
||||||
|
const string fullpath = (*i).to_string();
|
||||||
|
|
||||||
// now get available states for this session
|
// now get available states for this session
|
||||||
|
|
||||||
|
|
@ -981,27 +983,36 @@ NewSessionDialog::reset_recent()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
|
/* check whether session still exists */
|
||||||
|
if (!Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS)) {
|
||||||
|
/* session doesn't exist */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now get available states for this session */
|
||||||
|
|
||||||
|
if ((states = ARDOUR::Session::possible_states (fullpath)) == 0) {
|
||||||
|
/* no state file? */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Gtk::TreeModel::Row row = *(recent_model->append());
|
Gtk::TreeModel::Row row = *(recent_model->append());
|
||||||
|
|
||||||
const string fullpath = (*i).to_string();
|
|
||||||
|
|
||||||
row[recent_columns.visible_name] = Glib::path_get_basename (fullpath);
|
row[recent_columns.visible_name] = Glib::path_get_basename (fullpath);
|
||||||
row[recent_columns.fullpath] = fullpath;
|
row[recent_columns.fullpath] = fullpath;
|
||||||
|
|
||||||
if (state_file_names.size() > 1) {
|
if (states->size()) {
|
||||||
|
|
||||||
// add the children
|
/* add the children */
|
||||||
|
|
||||||
for (std::vector<std::string>::iterator i2 = state_file_names.begin();
|
for (std::vector<std::string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
|
||||||
i2 != state_file_names.end(); ++i2)
|
|
||||||
{
|
|
||||||
|
|
||||||
Gtk::TreeModel::Row child_row = *(recent_model->append (row.children()));
|
Gtk::TreeModel::Row child_row = *(recent_model->append (row.children()));
|
||||||
|
|
||||||
child_row[recent_columns.visible_name] = *i2;
|
child_row[recent_columns.visible_name] = **i2;
|
||||||
child_row[recent_columns.fullpath] = fullpath;
|
child_row[recent_columns.fullpath] = fullpath;
|
||||||
|
|
||||||
|
delete *i2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
|
||||||
virtual void restore_editing_space () = 0;
|
virtual void restore_editing_space () = 0;
|
||||||
virtual nframes64_t get_preferred_edit_position (bool ignore_playhead = false) = 0;
|
virtual nframes64_t get_preferred_edit_position (bool ignore_playhead = false) = 0;
|
||||||
virtual void toggle_meter_updating() = 0;
|
virtual void toggle_meter_updating() = 0;
|
||||||
virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, std::vector<nframes64_t>&) = 0;
|
virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&) = 0;
|
||||||
|
|
||||||
#ifdef WITH_CMT
|
#ifdef WITH_CMT
|
||||||
virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0;
|
virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "rhythm_ferret.h"
|
#include "rhythm_ferret.h"
|
||||||
#include "audio_region_view.h"
|
#include "audio_region_view.h"
|
||||||
#include "public_editor.h"
|
#include "public_editor.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -57,9 +58,9 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
{
|
{
|
||||||
upper_hpacker.set_spacing (6);
|
upper_hpacker.set_spacing (6);
|
||||||
|
|
||||||
upper_hpacker.pack_start (operation_frame, true, true);
|
|
||||||
upper_hpacker.pack_start (selection_frame, true, true);
|
|
||||||
upper_hpacker.pack_start (ferret_frame, true, true);
|
upper_hpacker.pack_start (ferret_frame, true, true);
|
||||||
|
upper_hpacker.pack_start (selection_frame, true, true);
|
||||||
|
upper_hpacker.pack_start (operation_frame, true, true);
|
||||||
|
|
||||||
op_packer.pack_start (region_split_button, false, false);
|
op_packer.pack_start (region_split_button, false, false);
|
||||||
op_packer.pack_start (tempo_button, false, false);
|
op_packer.pack_start (tempo_button, false, false);
|
||||||
|
|
@ -108,14 +109,16 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
|
|
||||||
ferret_frame.add (ferret_packer);
|
ferret_frame.add (ferret_packer);
|
||||||
|
|
||||||
// Glib::RefPtr<Pixbuf> logo_pixbuf ("somefile");
|
logo = manage (new Gtk::Image (::get_icon (X_("ferret_02"))));
|
||||||
|
|
||||||
if (logo) {
|
if (logo) {
|
||||||
lower_hpacker.pack_start (*logo, false, false);
|
lower_hpacker.pack_start (*logo, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
lower_hpacker.pack_start (operation_clarification_label, false, false);
|
lower_hpacker.pack_start (operation_clarification_label, true, true);
|
||||||
lower_hpacker.pack_start (action_button, false, false);
|
lower_hpacker.pack_start (action_button, false, false);
|
||||||
|
lower_hpacker.set_border_width (6);
|
||||||
|
lower_hpacker.set_spacing (6);
|
||||||
|
|
||||||
action_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::do_action));
|
action_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::do_action));
|
||||||
|
|
||||||
|
|
@ -194,13 +197,13 @@ RhythmFerret::run_analysis ()
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readable, nframes64_t offset, vector<nframes64_t>& results)
|
RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readable, nframes64_t offset, AnalysisFeatureList& results)
|
||||||
{
|
{
|
||||||
TransientDetector t (session->frame_rate());
|
TransientDetector t (session->frame_rate());
|
||||||
|
|
||||||
for (uint32_t i = 0; i < readable->n_channels(); ++i) {
|
for (uint32_t i = 0; i < readable->n_channels(); ++i) {
|
||||||
|
|
||||||
vector<nframes64_t> these_results;
|
AnalysisFeatureList these_results;
|
||||||
|
|
||||||
t.reset ();
|
t.reset ();
|
||||||
t.set_threshold (detection_threshold_adjustment.get_value());
|
t.set_threshold (detection_threshold_adjustment.get_value());
|
||||||
|
|
@ -212,38 +215,18 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readabl
|
||||||
|
|
||||||
/* translate all transients to give absolute position */
|
/* translate all transients to give absolute position */
|
||||||
|
|
||||||
for (vector<nframes64_t>::iterator i = these_results.begin(); i != these_results.end(); ++i) {
|
for (AnalysisFeatureList::iterator x = these_results.begin(); x != these_results.end(); ++x) {
|
||||||
(*i) += offset;
|
(*x) += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* merge */
|
/* merge */
|
||||||
|
|
||||||
results.insert (results.end(), these_results.begin(), these_results.end());
|
results.insert (results.end(), these_results.begin(), these_results.end());
|
||||||
|
these_results.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!results.empty()) {
|
if (!results.empty()) {
|
||||||
|
TransientDetector::cleanup_transients (results, session->frame_rate(), trigger_gap_adjustment.get_value());
|
||||||
/* now resort to bring transients from different channels together */
|
|
||||||
|
|
||||||
sort (results.begin(), results.end());
|
|
||||||
|
|
||||||
/* remove duplicates or other things that are too close */
|
|
||||||
|
|
||||||
vector<nframes64_t>::iterator i = results.begin();
|
|
||||||
nframes64_t curr = (*i);
|
|
||||||
nframes64_t gap_frames = (nframes64_t) floor (trigger_gap_adjustment.get_value() * (session->frame_rate() / 1000.0));
|
|
||||||
|
|
||||||
++i;
|
|
||||||
|
|
||||||
while (i != results.end()) {
|
|
||||||
if (((*i) == curr) || (((*i) - curr) < gap_frames)) {
|
|
||||||
i = results.erase (i);
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
curr = *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -84,17 +84,17 @@ class RhythmFerret : public ArdourDialog {
|
||||||
|
|
||||||
std::vector<std::string> analysis_mode_strings;
|
std::vector<std::string> analysis_mode_strings;
|
||||||
|
|
||||||
std::vector<nframes64_t> current_results;
|
ARDOUR::AnalysisFeatureList current_results;
|
||||||
|
|
||||||
AnalysisMode get_analysis_mode () const;
|
AnalysisMode get_analysis_mode () const;
|
||||||
Action get_action() const;
|
Action get_action() const;
|
||||||
|
|
||||||
void run_analysis ();
|
void run_analysis ();
|
||||||
int run_percussion_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, std::vector<nframes64_t>& results);
|
int run_percussion_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results);
|
||||||
|
|
||||||
void do_action ();
|
void do_action ();
|
||||||
void do_split_action ();
|
void do_split_action ();
|
||||||
void do_region_split (RegionView* rv, const std::vector<nframes64_t>&);
|
void do_region_split (RegionView* rv, const ARDOUR::AnalysisFeatureList&);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __gtk2_ardour_rhythm_ferret_h__ */
|
#endif /* __gtk2_ardour_rhythm_ferret_h__ */
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ using namespace Glib;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
Splash* Splash::the_splash = 0;
|
||||||
|
|
||||||
Splash::Splash ()
|
Splash::Splash ()
|
||||||
{
|
{
|
||||||
sys::path splash_file;
|
sys::path splash_file;
|
||||||
|
|
@ -47,6 +49,14 @@ Splash::Splash ()
|
||||||
darea.signal_expose_event().connect (mem_fun (*this, &Splash::expose));
|
darea.signal_expose_event().connect (mem_fun (*this, &Splash::expose));
|
||||||
|
|
||||||
add (darea);
|
add (darea);
|
||||||
|
|
||||||
|
the_splash = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Splash::pop_back ()
|
||||||
|
{
|
||||||
|
set_keep_above (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,10 @@ class Splash : public Gtk::Window
|
||||||
Splash ();
|
Splash ();
|
||||||
~Splash () {}
|
~Splash () {}
|
||||||
|
|
||||||
|
static Splash* instance() { return the_splash; }
|
||||||
|
|
||||||
|
void pop_back ();
|
||||||
|
|
||||||
bool expose (GdkEventExpose*);
|
bool expose (GdkEventExpose*);
|
||||||
bool on_button_release_event (GdkEventButton*);
|
bool on_button_release_event (GdkEventButton*);
|
||||||
void on_realize ();
|
void on_realize ();
|
||||||
|
|
@ -41,6 +45,8 @@ class Splash : public Gtk::Window
|
||||||
void message (const std::string& msg);
|
void message (const std::string& msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static Splash* the_splash;
|
||||||
|
|
||||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||||
Gtk::DrawingArea darea;
|
Gtk::DrawingArea darea;
|
||||||
Glib::RefPtr<Pango::Layout> layout;
|
Glib::RefPtr<Pango::Layout> layout;
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,6 @@ TempoDialog::get_note_type ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "returning " << note_type << " based on " << text << endl;
|
|
||||||
return note_type;
|
return note_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1104,7 +1104,7 @@ TimeAxisView::covers_y_position (double y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimeAxisView::show_temporary_lines (const vector<nframes64_t>& pos)
|
TimeAxisView::show_temporary_lines (const AnalysisFeatureList& pos)
|
||||||
{
|
{
|
||||||
while (temp_lines.size()< pos.size()) {
|
while (temp_lines.size()< pos.size()) {
|
||||||
ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*canvas_display);
|
ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*canvas_display);
|
||||||
|
|
@ -1120,7 +1120,7 @@ TimeAxisView::show_temporary_lines (const vector<nframes64_t>& pos)
|
||||||
delete line;
|
delete line;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<nframes64_t>::const_iterator i;
|
AnalysisFeatureList::const_iterator i;
|
||||||
list<ArdourCanvas::SimpleLine*>::iterator l;
|
list<ArdourCanvas::SimpleLine*>::iterator l;
|
||||||
|
|
||||||
for (i = pos.begin(), l = temp_lines.begin(); i != pos.end() && l != temp_lines.end(); ++i, ++l) {
|
for (i = pos.begin(), l = temp_lines.begin(); i != pos.end() && l != temp_lines.end(); ++i, ++l) {
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ class TimeAxisView : public virtual AxisView
|
||||||
virtual ARDOUR::RouteGroup* edit_group() const { return 0; }
|
virtual ARDOUR::RouteGroup* edit_group() const { return 0; }
|
||||||
virtual boost::shared_ptr<ARDOUR::Playlist> playlist() const { return boost::shared_ptr<ARDOUR::Playlist> (); }
|
virtual boost::shared_ptr<ARDOUR::Playlist> playlist() const { return boost::shared_ptr<ARDOUR::Playlist> (); }
|
||||||
|
|
||||||
virtual void show_temporary_lines (const std::vector<nframes64_t>&);
|
virtual void show_temporary_lines (const ARDOUR::AnalysisFeatureList&);
|
||||||
virtual void hide_temporary_lines ();
|
virtual void hide_temporary_lines ();
|
||||||
|
|
||||||
virtual void set_samples_per_unit (double);
|
virtual void set_samples_per_unit (double);
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,16 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
|
||||||
int ret = false;
|
int ret = false;
|
||||||
|
|
||||||
switch (ev->keyval) {
|
switch (ev->keyval) {
|
||||||
|
case GDK_Tab:
|
||||||
|
ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_nabla, GdkModifierType(ev->state));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// some X and/or GDK implementations do Shift-Tab -> GDK_ISO_Left_Tab
|
||||||
|
|
||||||
|
case GDK_ISO_Left_Tab:
|
||||||
|
ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_nabla, GdkModifierType(ev->state));
|
||||||
|
break;
|
||||||
|
|
||||||
case GDK_Up:
|
case GDK_Up:
|
||||||
ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_uparrow, GdkModifierType(ev->state));
|
ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_uparrow, GdkModifierType(ev->state));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ amp.cc
|
||||||
audio_buffer.cc
|
audio_buffer.cc
|
||||||
auto_bundle.cc
|
auto_bundle.cc
|
||||||
user_bundle.cc
|
user_bundle.cc
|
||||||
|
analyser.cc
|
||||||
audioanalyser.cc
|
audioanalyser.cc
|
||||||
audio_diskstream.cc
|
audio_diskstream.cc
|
||||||
audio_library.cc
|
audio_library.cc
|
||||||
|
|
|
||||||
119
libs/ardour/analyser.cc
Normal file
119
libs/ardour/analyser.cc
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 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
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ardour/analyser.h>
|
||||||
|
#include <ardour/audiofilesource.h>
|
||||||
|
#include <ardour/transient_detector.h>
|
||||||
|
|
||||||
|
#include <pbd/pthread_utils.h>
|
||||||
|
#include <pbd/convert.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace sigc;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
using namespace PBD;
|
||||||
|
|
||||||
|
Analyser* Analyser::the_analyser = 0;
|
||||||
|
Glib::StaticMutex Analyser::analysis_queue_lock = GLIBMM_STATIC_MUTEX_INIT;
|
||||||
|
Glib::Cond* Analyser::SourcesToAnalyse = 0;
|
||||||
|
list<boost::weak_ptr<Source> > Analyser::analysis_queue;
|
||||||
|
|
||||||
|
Analyser::Analyser ()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Analyser::~Analyser ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
analyser_work ()
|
||||||
|
{
|
||||||
|
Analyser::work ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Analyser::init ()
|
||||||
|
{
|
||||||
|
SourcesToAnalyse = new Glib::Cond();
|
||||||
|
Glib::Thread::create (sigc::ptr_fun (analyser_work), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Analyser::queue_source_for_analysis (boost::shared_ptr<Source> src, bool force)
|
||||||
|
{
|
||||||
|
if (!src->can_be_analysed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force && src->has_been_analysed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Glib::Mutex::Lock lm (analysis_queue_lock);
|
||||||
|
analysis_queue.push_back (boost::weak_ptr<Source>(src));
|
||||||
|
SourcesToAnalyse->broadcast ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Analyser::work ()
|
||||||
|
{
|
||||||
|
PBD::ThreadCreated (pthread_self(), string ("analyser-") + to_string (pthread_self(), std::dec));
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
analysis_queue_lock.lock ();
|
||||||
|
|
||||||
|
wait:
|
||||||
|
if (analysis_queue.empty()) {
|
||||||
|
SourcesToAnalyse->wait (analysis_queue_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (analysis_queue.empty()) {
|
||||||
|
goto wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<Source> src (analysis_queue.front().lock());
|
||||||
|
analysis_queue.pop_front();
|
||||||
|
analysis_queue_lock.unlock ();
|
||||||
|
|
||||||
|
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
|
||||||
|
|
||||||
|
if (afs) {
|
||||||
|
analyse_audio_file_source (afs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Analyser::analyse_audio_file_source (boost::shared_ptr<AudioFileSource> src)
|
||||||
|
{
|
||||||
|
AnalysisFeatureList results;
|
||||||
|
|
||||||
|
TransientDetector td (src->sample_rate());
|
||||||
|
|
||||||
|
if (td.run (src->get_transients_path(), src.get(), 0, results) == 0) {
|
||||||
|
src->set_been_analysed (true);
|
||||||
|
} else {
|
||||||
|
src->set_been_analysed (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
35
libs/ardour/ardour/analyser.h
Normal file
35
libs/ardour/ardour/analyser.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef __ardour_analyser_h__
|
||||||
|
#define __ardour_analyser_h__
|
||||||
|
|
||||||
|
#include <glibmm/thread.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class AudioFileSource;
|
||||||
|
class Source;
|
||||||
|
class TransientDetector;
|
||||||
|
|
||||||
|
class Analyser {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Analyser();
|
||||||
|
~Analyser ();
|
||||||
|
|
||||||
|
static void init ();
|
||||||
|
static void queue_source_for_analysis (boost::shared_ptr<Source>, bool force);
|
||||||
|
static void work ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Analyser* the_analyser;
|
||||||
|
static Glib::StaticMutex analysis_queue_lock;
|
||||||
|
static Glib::Cond* SourcesToAnalyse;
|
||||||
|
static std::list<boost::weak_ptr<Source> > analysis_queue;
|
||||||
|
|
||||||
|
static void analyse_audio_file_source (boost::shared_ptr<AudioFileSource>);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ardour_analyser_h__ */
|
||||||
|
|
@ -125,6 +125,8 @@ class AudioFileSource : public AudioSource {
|
||||||
|
|
||||||
virtual void handle_header_position_change () {}
|
virtual void handle_header_position_change () {}
|
||||||
|
|
||||||
|
bool can_be_analysed() const { return _length > 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/* constructor to be called for existing external-to-session files */
|
/* constructor to be called for existing external-to-session files */
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ class AudioRegion : public Region
|
||||||
void resume_fade_in ();
|
void resume_fade_in ();
|
||||||
void resume_fade_out ();
|
void resume_fade_out ();
|
||||||
|
|
||||||
int get_transients (std::vector<nframes64_t>&, bool force_new = false);
|
int get_transients (AnalysisFeatureList&, bool force_new = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RegionFactory;
|
friend class RegionFactory;
|
||||||
|
|
@ -170,6 +170,7 @@ class AudioRegion : public Region
|
||||||
void fade_out_changed ();
|
void fade_out_changed ();
|
||||||
void source_offset_changed ();
|
void source_offset_changed ();
|
||||||
void listen_to_my_curves ();
|
void listen_to_my_curves ();
|
||||||
|
void listen_to_my_sources ();
|
||||||
|
|
||||||
boost::shared_ptr<AutomationList> _fade_in;
|
boost::shared_ptr<AutomationList> _fade_in;
|
||||||
FadeShape _fade_in_shape;
|
FadeShape _fade_in_shape;
|
||||||
|
|
@ -187,11 +188,6 @@ class AudioRegion : public Region
|
||||||
AudioRegion (boost::shared_ptr<const AudioRegion>);
|
AudioRegion (boost::shared_ptr<const AudioRegion>);
|
||||||
|
|
||||||
int set_live_state (const XMLNode&, Change&, bool send);
|
int set_live_state (const XMLNode&, Change&, bool send);
|
||||||
|
|
||||||
std::vector<nframes64_t> _transients;
|
|
||||||
bool valid_transients;
|
|
||||||
void invalidate_transients ();
|
|
||||||
void cleanup_transients (std::vector<nframes64_t>&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ARDOUR */
|
} /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -111,14 +111,12 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR:
|
||||||
int prepare_for_peakfile_writes ();
|
int prepare_for_peakfile_writes ();
|
||||||
void done_with_peakfile_writes (bool done = true);
|
void done_with_peakfile_writes (bool done = true);
|
||||||
|
|
||||||
std::vector<nframes64_t> transients;
|
|
||||||
std::string get_transients_path() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool _build_missing_peakfiles;
|
static bool _build_missing_peakfiles;
|
||||||
static bool _build_peakfiles;
|
static bool _build_peakfiles;
|
||||||
|
|
||||||
bool _peaks_built;
|
bool _peaks_built;
|
||||||
|
bool _analysed;
|
||||||
mutable Glib::Mutex _lock;
|
mutable Glib::Mutex _lock;
|
||||||
mutable Glib::Mutex _peaks_ready_lock;
|
mutable Glib::Mutex _peaks_ready_lock;
|
||||||
Glib::ustring peakpath;
|
Glib::ustring peakpath;
|
||||||
|
|
@ -147,8 +145,6 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR:
|
||||||
int compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force,
|
int compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force,
|
||||||
bool intermediate_peaks_ready_signal, nframes_t frames_per_peak);
|
bool intermediate_peaks_ready_signal, nframes_t frames_per_peak);
|
||||||
|
|
||||||
int load_transients (const std::string&);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int peakfile;
|
int peakfile;
|
||||||
nframes_t peak_leftover_cnt;
|
nframes_t peak_leftover_cnt;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ CONFIG_VARIABLE (float, track_buffer_seconds, "track-buffer-seconds", 5.0)
|
||||||
CONFIG_VARIABLE (uint32_t, disk_choice_space_threshold, "disk-choice-space-threshold", 57600000)
|
CONFIG_VARIABLE (uint32_t, disk_choice_space_threshold, "disk-choice-space-threshold", 57600000)
|
||||||
CONFIG_VARIABLE (SampleFormat, native_file_data_format, "native-file-data-format", ARDOUR::FormatFloat)
|
CONFIG_VARIABLE (SampleFormat, native_file_data_format, "native-file-data-format", ARDOUR::FormatFloat)
|
||||||
CONFIG_VARIABLE (HeaderFormat, native_file_header_format, "native-file-header-format", ARDOUR::WAVE)
|
CONFIG_VARIABLE (HeaderFormat, native_file_header_format, "native-file-header-format", ARDOUR::WAVE)
|
||||||
|
CONFIG_VARIABLE (bool, auto_analyse_audio, "auto-analyse-audio", true)
|
||||||
|
|
||||||
/* OSC */
|
/* OSC */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
|
||||||
void duplicate (boost::shared_ptr<Region>, nframes_t position, float times);
|
void duplicate (boost::shared_ptr<Region>, nframes_t position, float times);
|
||||||
void nudge_after (nframes_t start, nframes_t distance, bool forwards);
|
void nudge_after (nframes_t start, nframes_t distance, bool forwards);
|
||||||
void shuffle (boost::shared_ptr<Region>, int dir);
|
void shuffle (boost::shared_ptr<Region>, int dir);
|
||||||
|
void update_after_tempo_map_change ();
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> cut (list<AudioRange>&, bool result_is_hidden = true);
|
boost::shared_ptr<Playlist> cut (list<AudioRange>&, bool result_is_hidden = true);
|
||||||
boost::shared_ptr<Playlist> copy (list<AudioRange>&, bool result_is_hidden = true);
|
boost::shared_ptr<Playlist> copy (list<AudioRange>&, bool result_is_hidden = true);
|
||||||
|
|
@ -110,6 +111,8 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
|
||||||
nframes64_t find_next_region_boundary (nframes64_t frame, int dir);
|
nframes64_t find_next_region_boundary (nframes64_t frame, int dir);
|
||||||
bool region_is_shuffle_constrained (boost::shared_ptr<Region>);
|
bool region_is_shuffle_constrained (boost::shared_ptr<Region>);
|
||||||
|
|
||||||
|
nframes64_t find_next_transient (nframes64_t position, int dir);
|
||||||
|
|
||||||
template<class T> void foreach_region (T *t, void (T::*func)(boost::shared_ptr<Region>, void *), void *arg);
|
template<class T> void foreach_region (T *t, void (T::*func)(boost::shared_ptr<Region>, void *), void *arg);
|
||||||
template<class T> void foreach_region (T *t, void (T::*func)(boost::shared_ptr<Region>));
|
template<class T> void foreach_region (T *t, void (T::*func)(boost::shared_ptr<Region>));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,11 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
range_guarantoor = USHRT_MAX
|
range_guarantoor = USHRT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum PositionLockStyle {
|
||||||
|
AudioTime,
|
||||||
|
MusicTime
|
||||||
|
};
|
||||||
|
|
||||||
static const Flag DefaultFlags = Flag (Opaque|DefaultFadeIn|DefaultFadeOut|FadeIn|FadeOut);
|
static const Flag DefaultFlags = Flag (Opaque|DefaultFadeIn|DefaultFadeOut|FadeIn|FadeOut);
|
||||||
|
|
||||||
static Change FadeChanged;
|
static Change FadeChanged;
|
||||||
|
|
@ -130,6 +135,9 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); }
|
bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); }
|
||||||
bool can_move() const { return !(_flags & (Locked|PositionLocked)); }
|
bool can_move() const { return !(_flags & (Locked|PositionLocked)); }
|
||||||
|
|
||||||
|
PositionLockStyle positional_lock_style() const { return _positional_lock_style; }
|
||||||
|
void set_position_lock_style (PositionLockStyle ps);
|
||||||
|
|
||||||
virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
|
virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
|
||||||
|
|
||||||
void freeze ();
|
void freeze ();
|
||||||
|
|
@ -156,6 +164,7 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
void set_position (nframes_t, void *src);
|
void set_position (nframes_t, void *src);
|
||||||
void set_position_on_top (nframes_t, void *src);
|
void set_position_on_top (nframes_t, void *src);
|
||||||
void special_set_position (nframes_t);
|
void special_set_position (nframes_t);
|
||||||
|
void update_position_after_tempo_map_change ();
|
||||||
void nudge_position (nframes64_t, void *src);
|
void nudge_position (nframes64_t, void *src);
|
||||||
|
|
||||||
bool at_natural_position () const;
|
bool at_natural_position () const;
|
||||||
|
|
@ -213,6 +222,13 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
virtual bool is_dependent() const { return false; }
|
virtual bool is_dependent() const { return false; }
|
||||||
virtual bool depends_on (boost::shared_ptr<Region> other) const { return false; }
|
virtual bool depends_on (boost::shared_ptr<Region> other) const { return false; }
|
||||||
|
|
||||||
|
virtual int get_transients (AnalysisFeatureList&, bool force_new = false) {
|
||||||
|
// no transients, but its OK
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate_transients ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class RegionFactory;
|
friend class RegionFactory;
|
||||||
|
|
||||||
|
|
@ -226,8 +242,6 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
Region (boost::shared_ptr<Source> src, const XMLNode&);
|
Region (boost::shared_ptr<Source> src, const XMLNode&);
|
||||||
Region (const SourceList& srcs, const XMLNode&);
|
Region (const SourceList& srcs, const XMLNode&);
|
||||||
|
|
||||||
/* this one is for derived types of derived types */
|
|
||||||
|
|
||||||
Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType, layer_t = 0, Flag flags = DefaultFlags);
|
Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType, layer_t = 0, Flag flags = DefaultFlags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -236,6 +250,7 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
void send_change (Change);
|
void send_change (Change);
|
||||||
|
|
||||||
void trim_to_internal (nframes_t position, nframes_t length, void *src);
|
void trim_to_internal (nframes_t position, nframes_t length, void *src);
|
||||||
|
void set_position_internal (nframes_t pos, bool allow_bbt_recompute);
|
||||||
|
|
||||||
bool copied() const { return _flags & Copied; }
|
bool copied() const { return _flags & Copied; }
|
||||||
void maybe_uncopy ();
|
void maybe_uncopy ();
|
||||||
|
|
@ -256,6 +271,7 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
nframes_t _last_length;
|
nframes_t _last_length;
|
||||||
nframes_t _position;
|
nframes_t _position;
|
||||||
nframes_t _last_position;
|
nframes_t _last_position;
|
||||||
|
PositionLockStyle _positional_lock_style;
|
||||||
nframes_t _sync_position;
|
nframes_t _sync_position;
|
||||||
layer_t _layer;
|
layer_t _layer;
|
||||||
mutable RegionEditState _first_edit;
|
mutable RegionEditState _first_edit;
|
||||||
|
|
@ -264,6 +280,9 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
|
||||||
nframes64_t _ancestral_length;
|
nframes64_t _ancestral_length;
|
||||||
float _stretch;
|
float _stretch;
|
||||||
float _shift;
|
float _shift;
|
||||||
|
BBT_Time _bbt_time;
|
||||||
|
AnalysisFeatureList _transients;
|
||||||
|
bool _valid_transients;
|
||||||
mutable uint32_t _read_data_count; ///< modified in read()
|
mutable uint32_t _read_data_count; ///< modified in read()
|
||||||
Change _pending_changed;
|
Change _pending_changed;
|
||||||
uint64_t _last_layer_op; ///< timestamp
|
uint64_t _last_layer_op; ///< timestamp
|
||||||
|
|
|
||||||
|
|
@ -389,7 +389,10 @@ class Session : public PBD::StatefulDestructible
|
||||||
nframes_t get_maximum_extent () const;
|
nframes_t get_maximum_extent () const;
|
||||||
nframes_t current_end_frame() const { return end_location->start(); }
|
nframes_t current_end_frame() const { return end_location->start(); }
|
||||||
nframes_t current_start_frame() const { return start_location->start(); }
|
nframes_t current_start_frame() const { return start_location->start(); }
|
||||||
|
// "actual" sample rate of session, set by current audioengine rate, pullup/down etc.
|
||||||
nframes_t frame_rate() const { return _current_frame_rate; }
|
nframes_t frame_rate() const { return _current_frame_rate; }
|
||||||
|
// "native" sample rate of session, regardless of current audioengine rate, pullup/down etc
|
||||||
|
nframes_t nominal_frame_rate() const { return _nominal_frame_rate; }
|
||||||
nframes_t frames_per_hour() const { return _frames_per_hour; }
|
nframes_t frames_per_hour() const { return _frames_per_hour; }
|
||||||
|
|
||||||
double frames_per_smpte_frame() const { return _frames_per_smpte_frame; }
|
double frames_per_smpte_frame() const { return _frames_per_smpte_frame; }
|
||||||
|
|
@ -433,6 +436,9 @@ class Session : public PBD::StatefulDestructible
|
||||||
sigc::signal<void,string> StateSaved;
|
sigc::signal<void,string> StateSaved;
|
||||||
sigc::signal<void> StateReady;
|
sigc::signal<void> StateReady;
|
||||||
|
|
||||||
|
vector<string*>* possible_states() const;
|
||||||
|
static vector<string*>* possible_states(string path);
|
||||||
|
|
||||||
XMLNode& get_state();
|
XMLNode& get_state();
|
||||||
int set_state(const XMLNode& node); // not idempotent
|
int set_state(const XMLNode& node); // not idempotent
|
||||||
XMLNode& get_template();
|
XMLNode& get_template();
|
||||||
|
|
@ -624,6 +630,12 @@ class Session : public PBD::StatefulDestructible
|
||||||
|
|
||||||
sigc::signal<int,boost::shared_ptr<ARDOUR::Playlist> > AskAboutPlaylistDeletion;
|
sigc::signal<int,boost::shared_ptr<ARDOUR::Playlist> > AskAboutPlaylistDeletion;
|
||||||
|
|
||||||
|
/* handlers should return 0 for "ignore the rate mismatch"
|
||||||
|
and !0 for "do not use this session"
|
||||||
|
*/
|
||||||
|
|
||||||
|
static sigc::signal<int,nframes_t, nframes_t> AskAboutSampleRateMismatch;
|
||||||
|
|
||||||
/* handlers should return !0 for use pending state, 0 for
|
/* handlers should return !0 for use pending state, 0 for
|
||||||
ignore it.
|
ignore it.
|
||||||
*/
|
*/
|
||||||
|
|
@ -981,6 +993,7 @@ class Session : public PBD::StatefulDestructible
|
||||||
bool waiting_for_sync_offset;
|
bool waiting_for_sync_offset;
|
||||||
nframes_t _base_frame_rate;
|
nframes_t _base_frame_rate;
|
||||||
nframes_t _current_frame_rate; //this includes video pullup offset
|
nframes_t _current_frame_rate; //this includes video pullup offset
|
||||||
|
nframes_t _nominal_frame_rate; //ignores audioengine setting, "native" SR
|
||||||
int transport_sub_state;
|
int transport_sub_state;
|
||||||
mutable gint _record_status;
|
mutable gint _record_status;
|
||||||
volatile nframes_t _transport_frame;
|
volatile nframes_t _transport_frame;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class SilentFileSource : public AudioFileSource {
|
||||||
void set_length (nframes_t len);
|
void set_length (nframes_t len);
|
||||||
|
|
||||||
bool destructive() const { return false; }
|
bool destructive() const { return false; }
|
||||||
|
bool can_be_analysed() const { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,27 @@ class Source : public SessionObject, public ARDOUR::Readable
|
||||||
static sigc::signal<void,Source*> SourceCreated;
|
static sigc::signal<void,Source*> SourceCreated;
|
||||||
sigc::signal<void,boost::shared_ptr<Source> > Switched;
|
sigc::signal<void,boost::shared_ptr<Source> > Switched;
|
||||||
|
|
||||||
|
bool has_been_analysed() const;
|
||||||
|
virtual bool can_be_analysed() const { return false; }
|
||||||
|
virtual void set_been_analysed (bool yn);
|
||||||
|
virtual bool check_for_analysis_data_on_disk();
|
||||||
|
|
||||||
|
sigc::signal<void> AnalysisChanged;
|
||||||
|
|
||||||
|
AnalysisFeatureList transients;
|
||||||
|
std::string get_transients_path() const;
|
||||||
|
int load_transients (const std::string&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void update_length (nframes_t pos, nframes_t cnt);
|
void update_length (nframes_t pos, nframes_t cnt);
|
||||||
|
|
||||||
DataType _type;
|
DataType _type;
|
||||||
time_t _timestamp;
|
time_t _timestamp;
|
||||||
nframes_t _length;
|
nframes_t _length;
|
||||||
|
bool _analysed;
|
||||||
|
mutable Glib::Mutex _analysis_lock;
|
||||||
|
Glib::Mutex _playlist_lock;
|
||||||
|
|
||||||
Glib::Mutex playlist_lock;
|
|
||||||
typedef std::map<boost::shared_ptr<ARDOUR::Playlist>, uint32_t > PlaylistMap;
|
typedef std::map<boost::shared_ptr<ARDOUR::Playlist>, uint32_t > PlaylistMap;
|
||||||
PlaylistMap _playlists;
|
PlaylistMap _playlists;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,10 @@ class TempoMap : public PBD::StatefulDestructible
|
||||||
void bbt_time_with_metric (nframes_t, BBT_Time&, const Metric&) const;
|
void bbt_time_with_metric (nframes_t, BBT_Time&, const Metric&) const;
|
||||||
|
|
||||||
void change_existing_tempo_at (nframes_t, double bpm, double note_type);
|
void change_existing_tempo_at (nframes_t, double bpm, double note_type);
|
||||||
|
void change_initial_tempo (double bpm, double note_type);
|
||||||
|
|
||||||
|
int n_tempos () const;
|
||||||
|
int n_meters () const;
|
||||||
|
|
||||||
sigc::signal<void,ARDOUR::Change> StateChanged;
|
sigc::signal<void,ARDOUR::Change> StateChanged;
|
||||||
|
|
||||||
|
|
@ -286,12 +290,12 @@ class TempoMap : public PBD::StatefulDestructible
|
||||||
static Tempo _default_tempo;
|
static Tempo _default_tempo;
|
||||||
static Meter _default_meter;
|
static Meter _default_meter;
|
||||||
|
|
||||||
Metrics *metrics;
|
Metrics* metrics;
|
||||||
nframes_t _frame_rate;
|
nframes_t _frame_rate;
|
||||||
nframes_t last_bbt_when;
|
nframes_t last_bbt_when;
|
||||||
bool last_bbt_valid;
|
bool last_bbt_valid;
|
||||||
BBT_Time last_bbt;
|
BBT_Time last_bbt;
|
||||||
mutable Glib::RWLock lock;
|
mutable Glib::RWLock lock;
|
||||||
|
|
||||||
void timestamp_metrics (bool use_bbt);
|
void timestamp_metrics (bool use_bbt);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,17 +34,23 @@ class TransientDetector : public AudioAnalyser
|
||||||
TransientDetector (float sample_rate);
|
TransientDetector (float sample_rate);
|
||||||
~TransientDetector();
|
~TransientDetector();
|
||||||
|
|
||||||
|
static std::string operational_identifier();
|
||||||
|
|
||||||
void set_threshold (float);
|
void set_threshold (float);
|
||||||
void set_sensitivity (float);
|
void set_sensitivity (float);
|
||||||
|
|
||||||
float get_threshold () const;
|
float get_threshold () const;
|
||||||
float get_sensitivity () const;
|
float get_sensitivity () const;
|
||||||
|
|
||||||
int run (const std::string& path, Readable*, uint32_t channel, std::vector<nframes64_t>& results);
|
int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results);
|
||||||
|
|
||||||
protected:
|
static void cleanup_transients (AnalysisFeatureList&, float sr, float gap_msecs);
|
||||||
std::vector<nframes64_t>* current_results;
|
|
||||||
|
protected:
|
||||||
|
AnalysisFeatureList* current_results;
|
||||||
int use_features (Vamp::Plugin::FeatureSet&, std::ostream*);
|
int use_features (Vamp::Plugin::FeatureSet&, std::ostream*);
|
||||||
|
|
||||||
|
static std::string _op_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace */
|
} /* namespace */
|
||||||
|
|
|
||||||
|
|
@ -392,6 +392,8 @@ namespace ARDOUR {
|
||||||
int opts; // really RubberBandStretcher::Options
|
int opts; // really RubberBandStretcher::Options
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::list<nframes64_t> AnalysisFeatureList;
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
||||||
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ardour/audio_buffer.h>
|
#include <ardour/audio_buffer.h>
|
||||||
|
#include <pbd/error.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
static const int CPU_CACHE_ALIGN = 64;
|
static const int CPU_CACHE_ALIGN = 64;
|
||||||
|
|
@ -24,6 +28,8 @@ static const int CPU_CACHE_ALIGN = 64;
|
||||||
static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
|
static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -63,7 +69,10 @@ AudioBuffer::resize (size_t size)
|
||||||
#ifdef NO_POSIX_MEMALIGN
|
#ifdef NO_POSIX_MEMALIGN
|
||||||
_data = (Sample *) malloc(sizeof(Sample) * _capacity);
|
_data = (Sample *) malloc(sizeof(Sample) * _capacity);
|
||||||
#else
|
#else
|
||||||
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Sample) * _capacity);
|
if (posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Sample) * _capacity)) {
|
||||||
|
fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
|
||||||
|
CPU_CACHE_ALIGN, sizeof (Sample) * _capacity, strerror (errno)) << endmsg;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_owns_data = true;
|
_owns_data = true;
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
#include <ardour/audioengine.h>
|
#include <ardour/audioengine.h>
|
||||||
|
#include <ardour/analyser.h>
|
||||||
#include <ardour/audio_diskstream.h>
|
#include <ardour/audio_diskstream.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/configuration.h>
|
#include <ardour/configuration.h>
|
||||||
|
|
@ -1569,6 +1570,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
|
||||||
s->update_header (capture_info.front()->start, when, twhen);
|
s->update_header (capture_info.front()->start, when, twhen);
|
||||||
s->set_captured_for (_name);
|
s->set_captured_for (_name);
|
||||||
s->mark_immutable ();
|
s->mark_immutable ();
|
||||||
|
Analyser::queue_source_for_analysis (s, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,19 @@ using namespace ARDOUR;
|
||||||
|
|
||||||
AudioAnalyser::AudioAnalyser (float sr, AnalysisPluginKey key)
|
AudioAnalyser::AudioAnalyser (float sr, AnalysisPluginKey key)
|
||||||
: sample_rate (sr)
|
: sample_rate (sr)
|
||||||
, plugin (0)
|
|
||||||
, plugin_key (key)
|
, plugin_key (key)
|
||||||
{
|
{
|
||||||
|
/* create VAMP plugin and initialize */
|
||||||
|
|
||||||
|
if (initialize_plugin (plugin_key, sample_rate)) {
|
||||||
|
error << string_compose (_("cannot load VAMP plugin \"%1\""), key) << endmsg;
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioAnalyser::~AudioAnalyser ()
|
AudioAnalyser::~AudioAnalyser ()
|
||||||
{
|
{
|
||||||
|
delete plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -73,29 +79,28 @@ int
|
||||||
AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
|
AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
|
||||||
{
|
{
|
||||||
ofstream ofile;
|
ofstream ofile;
|
||||||
Plugin::FeatureSet onsets;
|
Plugin::FeatureSet features;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
Sample* data = 0;
|
Sample* data = 0;
|
||||||
nframes64_t len = src->readable_length();
|
nframes64_t len = src->readable_length();
|
||||||
nframes64_t pos = 0;
|
nframes64_t pos = 0;
|
||||||
float* bufs[1] = { 0 };
|
float* bufs[1] = { 0 };
|
||||||
|
string tmp_path;
|
||||||
|
|
||||||
if (!path.empty()) {
|
if (!path.empty()) {
|
||||||
ofile.open (path.c_str());
|
|
||||||
|
/* store data in tmp file, not the real one */
|
||||||
|
|
||||||
|
tmp_path = path;
|
||||||
|
tmp_path += ".tmp";
|
||||||
|
|
||||||
|
ofile.open (tmp_path.c_str());
|
||||||
if (!ofile) {
|
if (!ofile) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create VAMP percussion onset plugin and initialize */
|
|
||||||
|
|
||||||
if (plugin == 0) {
|
|
||||||
if (initialize_plugin (plugin_key, sample_rate)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data = new Sample[bufsize];
|
data = new Sample[bufsize];
|
||||||
bufs[0] = data;
|
bufs[0] = data;
|
||||||
|
|
||||||
|
|
@ -108,7 +113,6 @@ AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
|
||||||
to_read = min ((len - pos), bufsize);
|
to_read = min ((len - pos), bufsize);
|
||||||
|
|
||||||
if (src->read (data, pos, to_read, channel) != to_read) {
|
if (src->read (data, pos, to_read, channel) != to_read) {
|
||||||
cerr << "bad read\n";
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,9 +122,9 @@ AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
|
||||||
memset (data + to_read, 0, (bufsize - to_read));
|
memset (data + to_read, 0, (bufsize - to_read));
|
||||||
}
|
}
|
||||||
|
|
||||||
onsets = plugin->process (bufs, RealTime::fromSeconds ((double) pos / sample_rate));
|
features = plugin->process (bufs, RealTime::fromSeconds ((double) pos / sample_rate));
|
||||||
|
|
||||||
if (use_features (onsets, (path.empty() ? &ofile : 0))) {
|
if (use_features (features, (path.empty() ? 0 : &ofile))) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,9 +137,9 @@ AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
|
||||||
|
|
||||||
/* finish up VAMP plugin */
|
/* finish up VAMP plugin */
|
||||||
|
|
||||||
onsets = plugin->getRemainingFeatures ();
|
features = plugin->getRemainingFeatures ();
|
||||||
|
|
||||||
if (use_features (onsets, (path.empty() ? &ofile : 0))) {
|
if (use_features (features, (path.empty() ? &ofile : 0))) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,10 +150,14 @@ AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
|
||||||
ofile.close ();
|
ofile.close ();
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
g_remove (path.c_str());
|
g_remove (tmp_path.c_str());
|
||||||
|
} else if (!path.empty()) {
|
||||||
|
/* move the data file to the requested path */
|
||||||
|
g_rename (tmp_path.c_str(), path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
delete data;
|
delete [] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -857,13 +857,16 @@ void
|
||||||
AudioEngine::halted (void *arg)
|
AudioEngine::halted (void *arg)
|
||||||
{
|
{
|
||||||
AudioEngine* ae = static_cast<AudioEngine *> (arg);
|
AudioEngine* ae = static_cast<AudioEngine *> (arg);
|
||||||
|
bool was_running = ae->_running;
|
||||||
|
|
||||||
ae->_running = false;
|
ae->_running = false;
|
||||||
ae->_buffer_size = 0;
|
ae->_buffer_size = 0;
|
||||||
ae->_frame_rate = 0;
|
ae->_frame_rate = 0;
|
||||||
ae->_jack = 0;
|
ae->_jack = 0;
|
||||||
|
|
||||||
ae->Halted(); /* EMIT SIGNAL */
|
if (was_running) {
|
||||||
|
ae->Halted(); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
|
|
||||||
|
|
@ -66,12 +66,12 @@ void
|
||||||
AudioRegion::init ()
|
AudioRegion::init ()
|
||||||
{
|
{
|
||||||
_scale_amplitude = 1.0;
|
_scale_amplitude = 1.0;
|
||||||
valid_transients = false;
|
|
||||||
|
|
||||||
set_default_fades ();
|
set_default_fades ();
|
||||||
set_default_envelope ();
|
set_default_envelope ();
|
||||||
|
|
||||||
listen_to_my_curves ();
|
listen_to_my_curves ();
|
||||||
|
listen_to_my_sources ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* constructor for use by derived types only */
|
/* constructor for use by derived types only */
|
||||||
|
|
@ -122,6 +122,7 @@ AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t len
|
||||||
, _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
|
, _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
|
||||||
{
|
{
|
||||||
init ();
|
init ();
|
||||||
|
listen_to_my_sources ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a new AudioRegion, that is part of an existing one */
|
/** Create a new AudioRegion, that is part of an existing one */
|
||||||
|
|
@ -172,9 +173,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
|
||||||
}
|
}
|
||||||
|
|
||||||
_scale_amplitude = other->_scale_amplitude;
|
_scale_amplitude = other->_scale_amplitude;
|
||||||
valid_transients = false;
|
|
||||||
|
|
||||||
assert(_type == DataType::AUDIO);
|
assert(_type == DataType::AUDIO);
|
||||||
|
listen_to_my_sources ();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
|
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
|
||||||
|
|
@ -183,15 +184,14 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
|
||||||
, _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
|
, _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
|
||||||
, _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
|
, _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
|
||||||
{
|
{
|
||||||
|
assert(_type == DataType::AUDIO);
|
||||||
_scale_amplitude = other->_scale_amplitude;
|
_scale_amplitude = other->_scale_amplitude;
|
||||||
valid_transients = false;
|
|
||||||
_envelope = other->_envelope;
|
_envelope = other->_envelope;
|
||||||
|
|
||||||
set_default_fades ();
|
set_default_fades ();
|
||||||
|
|
||||||
listen_to_my_curves ();
|
listen_to_my_curves ();
|
||||||
|
listen_to_my_sources ();
|
||||||
assert(_type == DataType::AUDIO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
|
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
|
||||||
|
|
@ -206,13 +206,13 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
|
||||||
}
|
}
|
||||||
|
|
||||||
init ();
|
init ();
|
||||||
valid_transients = false;
|
|
||||||
|
|
||||||
if (set_state (node)) {
|
if (set_state (node)) {
|
||||||
throw failed_constructor();
|
throw failed_constructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_type == DataType::AUDIO);
|
assert(_type == DataType::AUDIO);
|
||||||
|
listen_to_my_sources ();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
|
AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
|
||||||
|
|
@ -228,6 +228,7 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_type == DataType::AUDIO);
|
assert(_type == DataType::AUDIO);
|
||||||
|
listen_to_my_sources ();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegion::~AudioRegion ()
|
AudioRegion::~AudioRegion ()
|
||||||
|
|
@ -235,10 +236,11 @@ AudioRegion::~AudioRegion ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegion::invalidate_transients ()
|
AudioRegion::listen_to_my_sources ()
|
||||||
{
|
{
|
||||||
valid_transients = false;
|
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||||
_transients.clear ();
|
(*i)->AnalysisChanged.connect (mem_fun (*this, &AudioRegion::invalidate_transients));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1256,53 +1258,73 @@ AudioRegion::audio_source (uint32_t n) const
|
||||||
return boost::dynamic_pointer_cast<AudioSource>(source(n));
|
return boost::dynamic_pointer_cast<AudioSource>(source(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AudioRegion::cleanup_transients (vector<nframes64_t>& t)
|
|
||||||
{
|
|
||||||
sort (t.begin(), t.end());
|
|
||||||
|
|
||||||
/* remove duplicates or other things that are too close */
|
|
||||||
|
|
||||||
vector<nframes64_t>::iterator i = t.begin();
|
|
||||||
nframes64_t curr = (*i);
|
|
||||||
|
|
||||||
/* XXX force a 3msec gap - use a config variable */
|
|
||||||
|
|
||||||
nframes64_t gap_frames = (nframes64_t) floor (3.0 * (playlist()->session().frame_rate() / 1000.0));
|
|
||||||
|
|
||||||
++i;
|
|
||||||
|
|
||||||
while (i != t.end()) {
|
|
||||||
if (((*i) == curr) || (((*i) - curr) < gap_frames)) {
|
|
||||||
i = t.erase (i);
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
curr = *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new)
|
AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
|
||||||
{
|
{
|
||||||
if (!playlist()) {
|
boost::shared_ptr<Playlist> pl = playlist();
|
||||||
|
|
||||||
|
if (!pl) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_transients && !force_new) {
|
if (_valid_transients && !force_new) {
|
||||||
results = _transients;
|
results = _transients;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransientDetector t (playlist()->session().frame_rate());
|
SourceList::iterator s;
|
||||||
|
|
||||||
|
for (s = _sources.begin() ; s != _sources.end(); ++s) {
|
||||||
|
if (!(*s)->has_been_analysed()) {
|
||||||
|
cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == _sources.end()) {
|
||||||
|
/* all sources are analyzed, merge data from each one */
|
||||||
|
|
||||||
|
for (s = _sources.begin() ; s != _sources.end(); ++s) {
|
||||||
|
|
||||||
|
/* find the set of transients within the bounds of this region */
|
||||||
|
|
||||||
|
AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
|
||||||
|
(*s)->transients.end(),
|
||||||
|
_start);
|
||||||
|
|
||||||
|
AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
|
||||||
|
(*s)->transients.end(),
|
||||||
|
_start + _length);
|
||||||
|
|
||||||
|
/* and add them */
|
||||||
|
|
||||||
|
results.insert (results.end(), low, high);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
|
||||||
|
|
||||||
|
/* translate all transients to current position */
|
||||||
|
|
||||||
|
for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
|
||||||
|
(*x) -= _start;
|
||||||
|
(*x) += _position;
|
||||||
|
}
|
||||||
|
|
||||||
|
_transients = results;
|
||||||
|
_valid_transients = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransientDetector t (pl->session().frame_rate());
|
||||||
bool existing_results = !results.empty();
|
bool existing_results = !results.empty();
|
||||||
|
|
||||||
_transients.clear ();
|
_transients.clear ();
|
||||||
valid_transients = false;
|
_valid_transients = false;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < n_channels(); ++i) {
|
for (uint32_t i = 0; i < n_channels(); ++i) {
|
||||||
|
|
||||||
vector<nframes64_t> these_results;
|
AnalysisFeatureList these_results;
|
||||||
|
|
||||||
t.reset ();
|
t.reset ();
|
||||||
|
|
||||||
|
|
@ -1312,7 +1334,7 @@ AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new)
|
||||||
|
|
||||||
/* translate all transients to give absolute position */
|
/* translate all transients to give absolute position */
|
||||||
|
|
||||||
for (vector<nframes64_t>::iterator i = these_results.begin(); i != these_results.end(); ++i) {
|
for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
|
||||||
(*i) += _position;
|
(*i) += _position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1329,20 +1351,19 @@ AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
results.insert (results.end(), _transients.begin(), _transients.end());
|
results.insert (results.end(), _transients.begin(), _transients.end());
|
||||||
cleanup_transients (results);
|
TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure ours are clean too */
|
/* make sure ours are clean too */
|
||||||
|
|
||||||
cleanup_transients (_transients);
|
TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
valid_transients = true;
|
_valid_transients = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)
|
int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)
|
||||||
|
|
|
||||||
|
|
@ -919,50 +919,3 @@ AudioSource::update_length (nframes_t pos, nframes_t cnt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
AudioSource::load_transients (const string& path)
|
|
||||||
{
|
|
||||||
ifstream file (path.c_str());
|
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
transients.clear ();
|
|
||||||
|
|
||||||
stringstream strstr;
|
|
||||||
double val;
|
|
||||||
|
|
||||||
while (file.good()) {
|
|
||||||
file >> val;
|
|
||||||
|
|
||||||
if (!file.fail()) {
|
|
||||||
nframes64_t frame = (nframes64_t) floor (val * _session.frame_rate());
|
|
||||||
transients.push_back (frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
string
|
|
||||||
AudioSource::get_transients_path () const
|
|
||||||
{
|
|
||||||
vector<string> parts;
|
|
||||||
string s;
|
|
||||||
|
|
||||||
/* old sessions may not have the analysis directory */
|
|
||||||
|
|
||||||
_session.ensure_subdirs ();
|
|
||||||
|
|
||||||
s = _session.analysis_dir ();
|
|
||||||
parts.push_back (s);
|
|
||||||
|
|
||||||
s = _id.to_s();
|
|
||||||
s += '.';
|
|
||||||
s += X_("transients");
|
|
||||||
parts.push_back (s);
|
|
||||||
|
|
||||||
return Glib::build_filename (parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ setup_enum_writer ()
|
||||||
Location::Flags _Location_Flags;
|
Location::Flags _Location_Flags;
|
||||||
RouteGroup::Flag _RouteGroup_Flag;
|
RouteGroup::Flag _RouteGroup_Flag;
|
||||||
Region::Flag _Region_Flag;
|
Region::Flag _Region_Flag;
|
||||||
|
Region::PositionLockStyle _Region_PositionLockStyle;
|
||||||
Track::FreezeState _Track_FreezeState;
|
Track::FreezeState _Track_FreezeState;
|
||||||
AutomationList::InterpolationStyle _AutomationList_InterpolationStyle;
|
AutomationList::InterpolationStyle _AutomationList_InterpolationStyle;
|
||||||
|
|
||||||
|
|
@ -364,6 +365,10 @@ setup_enum_writer ()
|
||||||
REGISTER_CLASS_ENUM (Region, DoNotSaveState);
|
REGISTER_CLASS_ENUM (Region, DoNotSaveState);
|
||||||
REGISTER_BITS (_Region_Flag);
|
REGISTER_BITS (_Region_Flag);
|
||||||
|
|
||||||
|
REGISTER_CLASS_ENUM (Region, AudioTime);
|
||||||
|
REGISTER_CLASS_ENUM (Region, MusicTime);
|
||||||
|
REGISTER_BITS (_Region_PositionLockStyle);
|
||||||
|
|
||||||
REGISTER_CLASS_ENUM (Track, NoFreeze);
|
REGISTER_CLASS_ENUM (Track, NoFreeze);
|
||||||
REGISTER_CLASS_ENUM (Track, Frozen);
|
REGISTER_CLASS_ENUM (Track, Frozen);
|
||||||
REGISTER_CLASS_ENUM (Track, UnFrozen);
|
REGISTER_CLASS_ENUM (Track, UnFrozen);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
#include <midi++/mmc.h>
|
#include <midi++/mmc.h>
|
||||||
|
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
|
#include <ardour/analyser.h>
|
||||||
#include <ardour/audio_library.h>
|
#include <ardour/audio_library.h>
|
||||||
#include <ardour/configuration.h>
|
#include <ardour/configuration.h>
|
||||||
#include <ardour/profile.h>
|
#include <ardour/profile.h>
|
||||||
|
|
@ -300,6 +301,7 @@ ARDOUR::init (bool use_vst, bool try_optimization)
|
||||||
setup_hardware_optimization (try_optimization);
|
setup_hardware_optimization (try_optimization);
|
||||||
|
|
||||||
SourceFactory::init ();
|
SourceFactory::init ();
|
||||||
|
Analyser::init ();
|
||||||
|
|
||||||
/* singleton - first object is "it" */
|
/* singleton - first object is "it" */
|
||||||
new PluginManager ();
|
new PluginManager ();
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include <ardour/region.h>
|
#include <ardour/region.h>
|
||||||
#include <ardour/region_factory.h>
|
#include <ardour/region_factory.h>
|
||||||
#include <ardour/playlist_factory.h>
|
#include <ardour/playlist_factory.h>
|
||||||
|
#include <ardour/transient_detector.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -1428,6 +1429,65 @@ Playlist::regions_touched (nframes_t start, nframes_t end)
|
||||||
return rlist;
|
return rlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nframes64_t
|
||||||
|
Playlist::find_next_transient (nframes64_t from, int dir)
|
||||||
|
{
|
||||||
|
RegionLock rlock (this);
|
||||||
|
AnalysisFeatureList points;
|
||||||
|
AnalysisFeatureList these_points;
|
||||||
|
|
||||||
|
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||||
|
if (dir > 0) {
|
||||||
|
if ((*i)->last_frame() < from) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((*i)->first_frame() > from) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*i)->get_transients (these_points);
|
||||||
|
|
||||||
|
/* add first frame, just, err, because */
|
||||||
|
|
||||||
|
these_points.push_back ((*i)->first_frame());
|
||||||
|
|
||||||
|
points.insert (points.end(), these_points.begin(), these_points.end());
|
||||||
|
these_points.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points.empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
|
||||||
|
bool reached = false;
|
||||||
|
|
||||||
|
if (dir > 0) {
|
||||||
|
for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
|
||||||
|
if ((*x) >= from) {
|
||||||
|
reached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reached && (*x) > from) {
|
||||||
|
return *x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
|
||||||
|
if ((*x) <= from) {
|
||||||
|
reached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reached && (*x) < from) {
|
||||||
|
return *x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Region>
|
boost::shared_ptr<Region>
|
||||||
Playlist::find_next_region (nframes_t frame, RegionPoint point, int dir)
|
Playlist::find_next_region (nframes_t frame, RegionPoint point, int dir)
|
||||||
|
|
@ -2259,3 +2319,18 @@ Playlist::region_is_shuffle_constrained (boost::shared_ptr<Region>)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::update_after_tempo_map_change ()
|
||||||
|
{
|
||||||
|
RegionLock rlock (const_cast<Playlist*> (this));
|
||||||
|
RegionList copy (regions);
|
||||||
|
|
||||||
|
freeze ();
|
||||||
|
|
||||||
|
for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||||
|
(*i)->update_position_after_tempo_map_change ();
|
||||||
|
}
|
||||||
|
|
||||||
|
thaw ();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,9 @@ ARDOUR::read_recent_sessions (RecentSessions& rs)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!access(newpair.second.c_str(), R_OK)) {
|
rs.push_back (newpair);
|
||||||
rs.push_back (newpair);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This deletes any missing sessions
|
|
||||||
ARDOUR::write_recent_sessions (rs);
|
|
||||||
|
|
||||||
/* display sorting should be done in the GUI, otherwise the
|
/* display sorting should be done in the GUI, otherwise the
|
||||||
* natural order will be broken
|
* natural order will be broken
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <sigc++/bind.h>
|
#include <sigc++/bind.h>
|
||||||
#include <sigc++/class_slot.h>
|
#include <sigc++/class_slot.h>
|
||||||
|
|
@ -28,11 +29,13 @@
|
||||||
#include <glibmm/thread.h>
|
#include <glibmm/thread.h>
|
||||||
#include <pbd/xml++.h>
|
#include <pbd/xml++.h>
|
||||||
#include <pbd/stacktrace.h>
|
#include <pbd/stacktrace.h>
|
||||||
|
#include <pbd/enumwriter.h>
|
||||||
|
|
||||||
#include <ardour/region.h>
|
#include <ardour/region.h>
|
||||||
#include <ardour/playlist.h>
|
#include <ardour/playlist.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/source.h>
|
#include <ardour/source.h>
|
||||||
|
#include <ardour/tempo.h>
|
||||||
#include <ardour/region_factory.h>
|
#include <ardour/region_factory.h>
|
||||||
#include <ardour/filter.h>
|
#include <ardour/filter.h>
|
||||||
|
|
||||||
|
|
@ -59,6 +62,8 @@ Region::Region (Session& s, nframes_t start, nframes_t length, const string& nam
|
||||||
, _start(start)
|
, _start(start)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
, _last_position(0)
|
||||||
|
, _positional_lock_style(AudioTime)
|
||||||
, _sync_position(_start)
|
, _sync_position(_start)
|
||||||
, _layer(layer)
|
, _layer(layer)
|
||||||
, _first_edit(EditChangesNothing)
|
, _first_edit(EditChangesNothing)
|
||||||
|
|
@ -70,7 +75,6 @@ Region::Region (Session& s, nframes_t start, nframes_t length, const string& nam
|
||||||
/* no sources at this point */
|
/* no sources at this point */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Basic Region constructor (single source) */
|
/** Basic Region constructor (single source) */
|
||||||
Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
|
Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
|
||||||
: Automatable(src->session(), name)
|
: Automatable(src->session(), name)
|
||||||
|
|
@ -79,6 +83,8 @@ Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length
|
||||||
, _start(start)
|
, _start(start)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
, _last_position(0)
|
||||||
|
, _positional_lock_style(AudioTime)
|
||||||
, _sync_position(_start)
|
, _sync_position(_start)
|
||||||
, _layer(layer)
|
, _layer(layer)
|
||||||
, _first_edit(EditChangesNothing)
|
, _first_edit(EditChangesNothing)
|
||||||
|
|
@ -86,6 +92,8 @@ Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length
|
||||||
, _ancestral_start (start)
|
, _ancestral_start (start)
|
||||||
, _ancestral_length (length)
|
, _ancestral_length (length)
|
||||||
, _stretch (1.0)
|
, _stretch (1.0)
|
||||||
|
, _shift (0.0)
|
||||||
|
, _valid_transients(false)
|
||||||
, _read_data_count(0)
|
, _read_data_count(0)
|
||||||
, _pending_changed(Change (0))
|
, _pending_changed(Change (0))
|
||||||
, _last_layer_op(0)
|
, _last_layer_op(0)
|
||||||
|
|
@ -96,6 +104,7 @@ Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length
|
||||||
src->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), src));
|
src->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), src));
|
||||||
|
|
||||||
assert(_sources.size() > 0);
|
assert(_sources.size() > 0);
|
||||||
|
_positional_lock_style = AudioTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Basic Region constructor (many sources) */
|
/** Basic Region constructor (many sources) */
|
||||||
|
|
@ -106,6 +115,8 @@ Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const
|
||||||
, _start(start)
|
, _start(start)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
, _last_position(0)
|
||||||
|
, _positional_lock_style(AudioTime)
|
||||||
, _sync_position(_start)
|
, _sync_position(_start)
|
||||||
, _layer(layer)
|
, _layer(layer)
|
||||||
, _first_edit(EditChangesNothing)
|
, _first_edit(EditChangesNothing)
|
||||||
|
|
@ -141,6 +152,8 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
|
||||||
, _start(other->_start + offset)
|
, _start(other->_start + offset)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
, _last_position(0)
|
||||||
|
, _positional_lock_style(other->_positional_lock_style)
|
||||||
, _sync_position(_start)
|
, _sync_position(_start)
|
||||||
, _layer(layer)
|
, _layer(layer)
|
||||||
, _first_edit(EditChangesNothing)
|
, _first_edit(EditChangesNothing)
|
||||||
|
|
@ -148,6 +161,8 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
|
||||||
, _ancestral_start (other->_ancestral_start + offset)
|
, _ancestral_start (other->_ancestral_start + offset)
|
||||||
, _ancestral_length (length)
|
, _ancestral_length (length)
|
||||||
, _stretch (1.0)
|
, _stretch (1.0)
|
||||||
|
, _shift (0.0)
|
||||||
|
, _valid_transients(false)
|
||||||
, _read_data_count(0)
|
, _read_data_count(0)
|
||||||
, _pending_changed(Change (0))
|
, _pending_changed(Change (0))
|
||||||
, _last_layer_op(0)
|
, _last_layer_op(0)
|
||||||
|
|
@ -185,6 +200,8 @@ Region::Region (boost::shared_ptr<const Region> other)
|
||||||
, _start(other->_start)
|
, _start(other->_start)
|
||||||
, _length(other->_length)
|
, _length(other->_length)
|
||||||
, _position(other->_position)
|
, _position(other->_position)
|
||||||
|
, _last_position(other->_last_position)
|
||||||
|
, _positional_lock_style(other->_positional_lock_style)
|
||||||
, _sync_position(other->_sync_position)
|
, _sync_position(other->_sync_position)
|
||||||
, _layer(other->_layer)
|
, _layer(other->_layer)
|
||||||
, _first_edit(EditChangesID)
|
, _first_edit(EditChangesID)
|
||||||
|
|
@ -192,6 +209,8 @@ Region::Region (boost::shared_ptr<const Region> other)
|
||||||
, _ancestral_start (_start)
|
, _ancestral_start (_start)
|
||||||
, _ancestral_length (_length)
|
, _ancestral_length (_length)
|
||||||
, _stretch (1.0)
|
, _stretch (1.0)
|
||||||
|
, _shift (0.0)
|
||||||
|
, _valid_transients(false)
|
||||||
, _read_data_count(0)
|
, _read_data_count(0)
|
||||||
, _pending_changed(Change(0))
|
, _pending_changed(Change(0))
|
||||||
, _last_layer_op(other->_last_layer_op)
|
, _last_layer_op(other->_last_layer_op)
|
||||||
|
|
@ -229,6 +248,8 @@ Region::Region (const SourceList& srcs, const XMLNode& node)
|
||||||
, _start(0)
|
, _start(0)
|
||||||
, _length(0)
|
, _length(0)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
, _last_position(0)
|
||||||
|
, _positional_lock_style(AudioTime)
|
||||||
, _sync_position(_start)
|
, _sync_position(_start)
|
||||||
, _layer(0)
|
, _layer(0)
|
||||||
, _first_edit(EditChangesNothing)
|
, _first_edit(EditChangesNothing)
|
||||||
|
|
@ -267,6 +288,8 @@ Region::Region (boost::shared_ptr<Source> src, const XMLNode& node)
|
||||||
, _start(0)
|
, _start(0)
|
||||||
, _length(0)
|
, _length(0)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
, _last_position(0)
|
||||||
|
, _positional_lock_style(AudioTime)
|
||||||
, _sync_position(_start)
|
, _sync_position(_start)
|
||||||
, _layer(0)
|
, _layer(0)
|
||||||
, _first_edit(EditChangesNothing)
|
, _first_edit(EditChangesNothing)
|
||||||
|
|
@ -373,6 +396,7 @@ Region::set_length (nframes_t len, void *src)
|
||||||
|
|
||||||
first_edit ();
|
first_edit ();
|
||||||
maybe_uncopy ();
|
maybe_uncopy ();
|
||||||
|
invalidate_transients ();
|
||||||
|
|
||||||
if (!_frozen) {
|
if (!_frozen) {
|
||||||
recompute_at_end ();
|
recompute_at_end ();
|
||||||
|
|
@ -449,6 +473,37 @@ Region::special_set_position (nframes_t pos)
|
||||||
_position = pos;
|
_position = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Region::set_position_lock_style (PositionLockStyle ps)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<Playlist> pl (playlist());
|
||||||
|
|
||||||
|
if (!pl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_positional_lock_style = ps;
|
||||||
|
|
||||||
|
if (_positional_lock_style == MusicTime) {
|
||||||
|
pl->session().tempo_map().bbt_time (_position, _bbt_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Region::update_position_after_tempo_map_change ()
|
||||||
|
{
|
||||||
|
boost::shared_ptr<Playlist> pl (playlist());
|
||||||
|
|
||||||
|
if (!pl || _positional_lock_style != MusicTime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempoMap& map (pl->session().tempo_map());
|
||||||
|
nframes_t pos = map.frame_time (_bbt_time);
|
||||||
|
set_position_internal (pos, false);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Region::set_position (nframes_t pos, void *src)
|
Region::set_position (nframes_t pos, void *src)
|
||||||
{
|
{
|
||||||
|
|
@ -456,6 +511,12 @@ Region::set_position (nframes_t pos, void *src)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_position_internal (pos, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Region::set_position_internal (nframes_t pos, bool allow_bbt_recompute)
|
||||||
|
{
|
||||||
if (_position != pos) {
|
if (_position != pos) {
|
||||||
_last_position = _position;
|
_last_position = _position;
|
||||||
_position = pos;
|
_position = pos;
|
||||||
|
|
@ -470,6 +531,15 @@ Region::set_position (nframes_t pos, void *src)
|
||||||
_last_length = _length;
|
_last_length = _length;
|
||||||
_length = max_frames - _position;
|
_length = max_frames - _position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allow_bbt_recompute && _positional_lock_style == MusicTime) {
|
||||||
|
boost::shared_ptr<Playlist> pl (playlist());
|
||||||
|
if (pl) {
|
||||||
|
pl->session().tempo_map().bbt_time (_position, _bbt_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate_transients ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do this even if the position is the same. this helps out
|
/* do this even if the position is the same. this helps out
|
||||||
|
|
@ -563,6 +633,7 @@ Region::set_start (nframes_t pos, void *src)
|
||||||
_start = pos;
|
_start = pos;
|
||||||
_flags = Region::Flag (_flags & ~WholeFile);
|
_flags = Region::Flag (_flags & ~WholeFile);
|
||||||
first_edit ();
|
first_edit ();
|
||||||
|
invalidate_transients ();
|
||||||
|
|
||||||
send_change (StartChanged);
|
send_change (StartChanged);
|
||||||
}
|
}
|
||||||
|
|
@ -974,9 +1045,9 @@ Region::state (bool full_state)
|
||||||
node->add_property ("length", buf);
|
node->add_property ("length", buf);
|
||||||
snprintf (buf, sizeof (buf), "%u", _position);
|
snprintf (buf, sizeof (buf), "%u", _position);
|
||||||
node->add_property ("position", buf);
|
node->add_property ("position", buf);
|
||||||
snprintf (buf, sizeof (buf), "%Ld", _ancestral_start);
|
snprintf (buf, sizeof (buf), "%" PRIi64, _ancestral_start);
|
||||||
node->add_property ("ancestral-start", buf);
|
node->add_property ("ancestral-start", buf);
|
||||||
snprintf (buf, sizeof (buf), "%Ld", _ancestral_length);
|
snprintf (buf, sizeof (buf), "%" PRIi64, _ancestral_length);
|
||||||
node->add_property ("ancestral-length", buf);
|
node->add_property ("ancestral-length", buf);
|
||||||
snprintf (buf, sizeof (buf), "%.12g", _stretch);
|
snprintf (buf, sizeof (buf), "%.12g", _stretch);
|
||||||
node->add_property ("stretch", buf);
|
node->add_property ("stretch", buf);
|
||||||
|
|
@ -1007,6 +1078,13 @@ Region::state (bool full_state)
|
||||||
snprintf (buf, sizeof (buf), "%" PRIu32, _sync_position);
|
snprintf (buf, sizeof (buf), "%" PRIu32, _sync_position);
|
||||||
node->add_property ("sync-position", buf);
|
node->add_property ("sync-position", buf);
|
||||||
|
|
||||||
|
if (_positional_lock_style != AudioTime) {
|
||||||
|
node->add_property ("positional-lock-style", enum_2_string (_positional_lock_style));
|
||||||
|
stringstream str;
|
||||||
|
str << _bbt_time;
|
||||||
|
node->add_property ("bbt-position", str.str());
|
||||||
|
}
|
||||||
|
|
||||||
return *node;
|
return *node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1095,6 +1173,27 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send)
|
||||||
_sync_position = _start;
|
_sync_position = _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((prop = node.property ("positional-lock-style")) != 0) {
|
||||||
|
_positional_lock_style = PositionLockStyle (string_2_enum (prop->value(), _positional_lock_style));
|
||||||
|
|
||||||
|
if (_positional_lock_style == MusicTime) {
|
||||||
|
if ((prop = node.property ("bbt-position")) == 0) {
|
||||||
|
/* missing BBT info, revert to audio time locking */
|
||||||
|
_positional_lock_style = AudioTime;
|
||||||
|
} else {
|
||||||
|
if (sscanf (prop->value().c_str(), "%d|%d|%d",
|
||||||
|
&_bbt_time.bars,
|
||||||
|
&_bbt_time.beats,
|
||||||
|
&_bbt_time.ticks) != 3) {
|
||||||
|
_positional_lock_style = AudioTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_positional_lock_style = AudioTime;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX FIRST EDIT !!! */
|
/* XXX FIRST EDIT !!! */
|
||||||
|
|
||||||
/* these 3 properties never change as a result of any editing */
|
/* these 3 properties never change as a result of any editing */
|
||||||
|
|
@ -1261,7 +1360,8 @@ Region::region_list_equivalent (boost::shared_ptr<const Region> other) const
|
||||||
void
|
void
|
||||||
Region::source_deleted (boost::shared_ptr<Source>)
|
Region::source_deleted (boost::shared_ptr<Source>)
|
||||||
{
|
{
|
||||||
delete this;
|
_sources.clear ();
|
||||||
|
drop_references ();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string>
|
vector<string>
|
||||||
|
|
@ -1397,3 +1497,10 @@ Region::apply (Filter& filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Region::invalidate_transients ()
|
||||||
|
{
|
||||||
|
_valid_transients = false;
|
||||||
|
_transients.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@
|
||||||
#include <ardour/filename_extensions.h>
|
#include <ardour/filename_extensions.h>
|
||||||
#include <ardour/session_directory.h>
|
#include <ardour/session_directory.h>
|
||||||
#include <ardour/tape_file_matcher.h>
|
#include <ardour/tape_file_matcher.h>
|
||||||
|
#include <ardour/analyser.h>
|
||||||
|
|
||||||
#ifdef HAVE_LIBLO
|
#ifdef HAVE_LIBLO
|
||||||
#include <ardour/osc.h>
|
#include <ardour/osc.h>
|
||||||
|
|
@ -107,6 +108,7 @@ Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
|
||||||
Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
|
Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
|
||||||
|
|
||||||
sigc::signal<int> Session::AskAboutPendingState;
|
sigc::signal<int> Session::AskAboutPendingState;
|
||||||
|
sigc::signal<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
|
||||||
sigc::signal<void> Session::SendFeedback;
|
sigc::signal<void> Session::SendFeedback;
|
||||||
|
|
||||||
sigc::signal<void> Session::SMPTEOffsetChanged;
|
sigc::signal<void> Session::SMPTEOffsetChanged;
|
||||||
|
|
@ -2771,6 +2773,14 @@ Session::add_source (boost::shared_ptr<Source> source)
|
||||||
source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
|
source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
|
||||||
set_dirty();
|
set_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<AudioFileSource> afs;
|
||||||
|
|
||||||
|
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
|
||||||
|
if (Config->get_auto_analyse_audio()) {
|
||||||
|
Analyser::queue_source_for_analysis (source, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3726,6 +3736,15 @@ void
|
||||||
Session::tempo_map_changed (Change ignored)
|
Session::tempo_map_changed (Change ignored)
|
||||||
{
|
{
|
||||||
clear_clicks ();
|
clear_clicks ();
|
||||||
|
|
||||||
|
for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
|
||||||
|
(*i)->update_after_tempo_map_change ();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
|
||||||
|
(*i)->update_after_tempo_map_change ();
|
||||||
|
}
|
||||||
|
|
||||||
set_dirty ();
|
set_dirty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,9 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
set_history_depth (Config->get_history_depth());
|
set_history_depth (Config->get_history_depth());
|
||||||
|
|
||||||
_current_frame_rate = _engine.frame_rate ();
|
_current_frame_rate = _engine.frame_rate ();
|
||||||
|
_nominal_frame_rate = _current_frame_rate;
|
||||||
|
_base_frame_rate = _current_frame_rate;
|
||||||
|
|
||||||
_tempo_map = new TempoMap (_current_frame_rate);
|
_tempo_map = new TempoMap (_current_frame_rate);
|
||||||
_tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
|
_tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
|
||||||
|
|
||||||
|
|
@ -236,9 +239,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
waiting_for_sync_offset = false;
|
waiting_for_sync_offset = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_current_frame_rate = 48000;
|
|
||||||
_base_frame_rate = 48000;
|
|
||||||
|
|
||||||
last_smpte_when = 0;
|
last_smpte_when = 0;
|
||||||
_smpte_offset = 0;
|
_smpte_offset = 0;
|
||||||
_smpte_offset_negative = true;
|
_smpte_offset_negative = true;
|
||||||
|
|
@ -920,16 +920,16 @@ Session::state(bool full_state)
|
||||||
|
|
||||||
// store libardour version, just in case
|
// store libardour version, just in case
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
|
snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
|
||||||
libardour_major_version, libardour_minor_version, libardour_micro_version);
|
|
||||||
node->add_property("version", string(buf));
|
node->add_property("version", string(buf));
|
||||||
|
|
||||||
/* store configuration settings */
|
/* store configuration settings */
|
||||||
|
|
||||||
if (full_state) {
|
if (full_state) {
|
||||||
|
|
||||||
/* store the name */
|
|
||||||
node->add_property ("name", _name);
|
node->add_property ("name", _name);
|
||||||
|
snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
|
||||||
|
node->add_property ("sample-rate", buf);
|
||||||
|
|
||||||
if (session_dirs.size() > 1) {
|
if (session_dirs.size() > 1) {
|
||||||
|
|
||||||
|
|
@ -1149,7 +1149,6 @@ Session::set_state (const XMLNode& node)
|
||||||
|
|
||||||
_state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
|
_state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
|
||||||
|
|
||||||
|
|
||||||
if (node.name() != X_("Session")){
|
if (node.name() != X_("Session")){
|
||||||
fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
|
fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1159,6 +1158,17 @@ Session::set_state (const XMLNode& node)
|
||||||
_name = prop->value ();
|
_name = prop->value ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((prop = node.property (X_("sample-rate"))) != 0) {
|
||||||
|
|
||||||
|
_nominal_frame_rate = atoi (prop->value());
|
||||||
|
|
||||||
|
if (_nominal_frame_rate != _current_frame_rate) {
|
||||||
|
if (AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setup_raid_path(_session_dir->root_path().to_string());
|
setup_raid_path(_session_dir->root_path().to_string());
|
||||||
|
|
||||||
if ((prop = node.property (X_("id-counter"))) != 0) {
|
if ((prop = node.property (X_("id-counter"))) != 0) {
|
||||||
|
|
@ -2067,6 +2077,56 @@ Session::auto_save()
|
||||||
save_state (_current_snapshot_name);
|
save_state (_current_snapshot_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
state_file_filter (const string &str, void *arg)
|
||||||
|
{
|
||||||
|
return (str.length() > strlen(statefile_suffix) &&
|
||||||
|
str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string_cmp {
|
||||||
|
bool operator()(const string* a, const string* b) {
|
||||||
|
return *a < *b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static string*
|
||||||
|
remove_end(string* state)
|
||||||
|
{
|
||||||
|
string statename(*state);
|
||||||
|
|
||||||
|
string::size_type start,end;
|
||||||
|
if ((start = statename.find_last_of ('/')) != string::npos) {
|
||||||
|
statename = statename.substr (start+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((end = statename.rfind(".ardour")) == string::npos) {
|
||||||
|
end = statename.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(statename.substr (0, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string *> *
|
||||||
|
Session::possible_states (string path)
|
||||||
|
{
|
||||||
|
PathScanner scanner;
|
||||||
|
vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
|
||||||
|
|
||||||
|
transform(states->begin(), states->end(), states->begin(), remove_end);
|
||||||
|
|
||||||
|
string_cmp cmp;
|
||||||
|
sort (states->begin(), states->end(), cmp);
|
||||||
|
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string *> *
|
||||||
|
Session::possible_states () const
|
||||||
|
{
|
||||||
|
return possible_states(_path);
|
||||||
|
}
|
||||||
|
|
||||||
RouteGroup *
|
RouteGroup *
|
||||||
Session::add_edit_group (string name)
|
Session::add_edit_group (string name)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,19 +27,22 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include <glibmm/thread.h>
|
#include <glibmm/thread.h>
|
||||||
|
#include <glibmm/miscutils.h>
|
||||||
|
#include <glibmm/fileutils.h>
|
||||||
#include <pbd/xml++.h>
|
#include <pbd/xml++.h>
|
||||||
#include <pbd/pthread_utils.h>
|
#include <pbd/pthread_utils.h>
|
||||||
|
|
||||||
#include <ardour/source.h>
|
#include <ardour/source.h>
|
||||||
#include <ardour/playlist.h>
|
#include <ardour/playlist.h>
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <ardour/transient_detector.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using std::min;
|
using namespace std;
|
||||||
using std::max;
|
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
Source::Source (Session& s, const string& name, DataType type)
|
Source::Source (Session& s, const string& name, DataType type)
|
||||||
|
|
@ -49,6 +52,7 @@ Source::Source (Session& s, const string& name, DataType type)
|
||||||
// not true.. is this supposed to be an assertion?
|
// not true.. is this supposed to be an assertion?
|
||||||
//assert(_name.find("/") == string::npos);
|
//assert(_name.find("/") == string::npos);
|
||||||
|
|
||||||
|
_analysed = false;
|
||||||
_timestamp = 0;
|
_timestamp = 0;
|
||||||
_length = 0;
|
_length = 0;
|
||||||
_in_use = 0;
|
_in_use = 0;
|
||||||
|
|
@ -60,6 +64,7 @@ Source::Source (Session& s, const XMLNode& node)
|
||||||
{
|
{
|
||||||
_timestamp = 0;
|
_timestamp = 0;
|
||||||
_length = 0;
|
_length = 0;
|
||||||
|
_analysed = false;
|
||||||
_in_use = 0;
|
_in_use = 0;
|
||||||
|
|
||||||
if (set_state (node) || _type == DataType::NIL) {
|
if (set_state (node) || _type == DataType::NIL) {
|
||||||
|
|
@ -135,7 +140,7 @@ Source::add_playlist (boost::shared_ptr<Playlist> pl)
|
||||||
{
|
{
|
||||||
std::pair<PlaylistMap::iterator,bool> res;
|
std::pair<PlaylistMap::iterator,bool> res;
|
||||||
std::pair<boost::shared_ptr<Playlist>, uint32_t> newpair (pl, 1);
|
std::pair<boost::shared_ptr<Playlist>, uint32_t> newpair (pl, 1);
|
||||||
Glib::Mutex::Lock lm (playlist_lock);
|
Glib::Mutex::Lock lm (_playlist_lock);
|
||||||
|
|
||||||
res = _playlists.insert (newpair);
|
res = _playlists.insert (newpair);
|
||||||
|
|
||||||
|
|
@ -157,7 +162,7 @@ Source::remove_playlist (boost::weak_ptr<Playlist> wpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistMap::iterator x;
|
PlaylistMap::iterator x;
|
||||||
Glib::Mutex::Lock lm (playlist_lock);
|
Glib::Mutex::Lock lm (_playlist_lock);
|
||||||
|
|
||||||
if ((x = _playlists.find (pl)) != _playlists.end()) {
|
if ((x = _playlists.find (pl)) != _playlists.end()) {
|
||||||
if (x->second > 1) {
|
if (x->second > 1) {
|
||||||
|
|
@ -173,3 +178,90 @@ Source::used () const
|
||||||
{
|
{
|
||||||
return _playlists.size();
|
return _playlists.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Source::has_been_analysed() const
|
||||||
|
{
|
||||||
|
Glib::Mutex::Lock lm (_analysis_lock);
|
||||||
|
return _analysed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Source::set_been_analysed (bool yn)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Glib::Mutex::Lock lm (_analysis_lock);
|
||||||
|
_analysed = yn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yn) {
|
||||||
|
AnalysisChanged(); // EMIT SIGNAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Source::load_transients (const string& path)
|
||||||
|
{
|
||||||
|
ifstream file (path.c_str());
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
transients.clear ();
|
||||||
|
|
||||||
|
stringstream strstr;
|
||||||
|
double val;
|
||||||
|
|
||||||
|
while (file.good()) {
|
||||||
|
file >> val;
|
||||||
|
|
||||||
|
if (!file.fail()) {
|
||||||
|
nframes64_t frame = (nframes64_t) floor (val * _session.frame_rate());
|
||||||
|
transients.push_back (frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Source::get_transients_path () const
|
||||||
|
{
|
||||||
|
vector<string> parts;
|
||||||
|
string s;
|
||||||
|
|
||||||
|
/* old sessions may not have the analysis directory */
|
||||||
|
|
||||||
|
_session.ensure_subdirs ();
|
||||||
|
|
||||||
|
s = _session.analysis_dir ();
|
||||||
|
parts.push_back (s);
|
||||||
|
|
||||||
|
s = _id.to_s();
|
||||||
|
s += '.';
|
||||||
|
s += TransientDetector::operational_identifier();
|
||||||
|
parts.push_back (s);
|
||||||
|
|
||||||
|
return Glib::build_filename (parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Source::check_for_analysis_data_on_disk ()
|
||||||
|
{
|
||||||
|
/* looks to see if the analysis files for this source are on disk.
|
||||||
|
if so, mark us already analysed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
string path = get_transients_path ();
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX add other tests here as appropriate
|
||||||
|
|
||||||
|
set_been_analysed (ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ boost::shared_ptr<Source>
|
||||||
SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes, float sr)
|
SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes, float sr)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Source> ret (new SilentFileSource (s, node, nframes, sr));
|
boost::shared_ptr<Source> ret (new SilentFileSource (s, node, nframes, sr));
|
||||||
|
// no analysis data - the file is non-existent
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -118,61 +119,64 @@ SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes,
|
||||||
boost::shared_ptr<Source>
|
boost::shared_ptr<Source>
|
||||||
SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
|
SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
|
||||||
{
|
{
|
||||||
DataType type = DataType::AUDIO;
|
DataType type = DataType::AUDIO;
|
||||||
const XMLProperty* prop = node.property("type");
|
const XMLProperty* prop = node.property("type");
|
||||||
|
|
||||||
if (prop) {
|
if (prop) {
|
||||||
type = DataType(prop->value());
|
type = DataType(prop->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == DataType::AUDIO) {
|
if (type == DataType::AUDIO) {
|
||||||
|
|
||||||
#ifdef HAVE_COREAUDIO
|
#ifdef HAVE_COREAUDIO
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
|
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
|
||||||
|
|
||||||
if (setup_peakfile (ret, defer_peaks)) {
|
if (setup_peakfile (ret, defer_peaks)) {
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceCreated (ret);
|
ret->check_for_analysis_data_on_disk ();
|
||||||
return ret;
|
SourceCreated (ret);
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
catch (failed_constructor& err) {
|
catch (failed_constructor& err) {
|
||||||
|
|
||||||
/* this is allowed to throw */
|
/* this is allowed to throw */
|
||||||
|
|
||||||
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
||||||
|
|
||||||
if (setup_peakfile (ret, defer_peaks)) {
|
if (setup_peakfile (ret, defer_peaks)) {
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceCreated (ret);
|
ret->check_for_analysis_data_on_disk ();
|
||||||
return ret;
|
SourceCreated (ret);
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* this is allowed to throw */
|
/* this is allowed to throw */
|
||||||
|
|
||||||
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
||||||
|
|
||||||
if (setup_peakfile (ret, defer_peaks)) {
|
if (setup_peakfile (ret, defer_peaks)) {
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceCreated (ret);
|
ret->check_for_analysis_data_on_disk ();
|
||||||
return ret;
|
SourceCreated (ret);
|
||||||
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else if (type == DataType::MIDI) {
|
} else if (type == DataType::MIDI) {
|
||||||
boost::shared_ptr<Source> ret (new SMFSource (s, node));
|
boost::shared_ptr<Source> ret (new SMFSource (s, node));
|
||||||
|
ret->check_for_analysis_data_on_disk ();
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +194,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret->check_for_analysis_data_on_disk ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +206,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
|
||||||
if (setup_peakfile (ret, defer_peaks)) {
|
if (setup_peakfile (ret, defer_peaks)) {
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
ret->check_for_analysis_data_on_disk ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +219,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret->check_for_analysis_data_on_disk ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -225,6 +232,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
|
||||||
// FIXME: flags?
|
// FIXME: flags?
|
||||||
boost::shared_ptr<Source> ret (new SMFSource (s, path, SMFSource::Flag(0)));
|
boost::shared_ptr<Source> ret (new SMFSource (s, path, SMFSource::Flag(0)));
|
||||||
|
|
||||||
|
ret->check_for_analysis_data_on_disk ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -253,6 +261,8 @@ SourceFactory::createWritable (DataType type, Session& s, std::string path, bool
|
||||||
return boost::shared_ptr<Source>();
|
return boost::shared_ptr<Source>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no analysis data - this is a new file
|
||||||
|
|
||||||
if (announce) {
|
if (announce) {
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -262,6 +272,8 @@ SourceFactory::createWritable (DataType type, Session& s, std::string path, bool
|
||||||
|
|
||||||
boost::shared_ptr<Source> ret (new SMFSource (s, path));
|
boost::shared_ptr<Source> ret (new SMFSource (s, path));
|
||||||
|
|
||||||
|
// no analysis data - this is a new file
|
||||||
|
|
||||||
if (announce) {
|
if (announce) {
|
||||||
SourceCreated (ret);
|
SourceCreated (ret);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -246,29 +246,49 @@ TempoMap::~TempoMap ()
|
||||||
int
|
int
|
||||||
TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
|
TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
|
||||||
{
|
{
|
||||||
if (when == section.start()) {
|
if (when == section.start() || !section.movable()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!section.movable()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Glib::RWLock::WriterLock lm (lock);
|
Glib::RWLock::WriterLock lm (lock);
|
||||||
MetricSectionSorter cmp;
|
MetricSectionSorter cmp;
|
||||||
BBT_Time corrected (when);
|
|
||||||
|
|
||||||
if (dynamic_cast<MeterSection*>(§ion) != 0) {
|
if (when.beats != 1) {
|
||||||
if (corrected.beats > 1) {
|
|
||||||
corrected.beats = 1;
|
/* position by audio frame, then recompute BBT timestamps from the audio ones */
|
||||||
corrected.bars++;
|
|
||||||
|
nframes_t frame = frame_time (when);
|
||||||
|
// cerr << "nominal frame time = " << frame << endl;
|
||||||
|
|
||||||
|
nframes_t prev_frame = round_to_type (frame, -1, Beat);
|
||||||
|
nframes_t next_frame = round_to_type (frame, 1, Beat);
|
||||||
|
|
||||||
|
// cerr << "previous beat at " << prev_frame << " next at " << next_frame << endl;
|
||||||
|
|
||||||
|
/* use the closest beat */
|
||||||
|
|
||||||
|
if ((frame - prev_frame) < (next_frame - frame)) {
|
||||||
|
frame = prev_frame;
|
||||||
|
} else {
|
||||||
|
frame = next_frame;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
corrected.ticks = 0;
|
|
||||||
|
|
||||||
section.set_start (corrected);
|
// cerr << "actual frame time = " << frame << endl;
|
||||||
metrics->sort (cmp);
|
section.set_frame (frame);
|
||||||
timestamp_metrics (true);
|
// cerr << "frame time = " << section.frame() << endl;
|
||||||
|
timestamp_metrics (false);
|
||||||
|
// cerr << "new BBT time = " << section.start() << endl;
|
||||||
|
metrics->sort (cmp);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* positioned at bar start already, so just put it there */
|
||||||
|
|
||||||
|
section.set_start (when);
|
||||||
|
metrics->sort (cmp);
|
||||||
|
timestamp_metrics (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +309,6 @@ TempoMap::move_meter (MeterSection& meter, const BBT_Time& when)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TempoMap::remove_tempo (const TempoSection& tempo)
|
TempoMap::remove_tempo (const TempoSection& tempo)
|
||||||
{
|
{
|
||||||
|
|
@ -413,10 +432,11 @@ TempoMap::replace_tempo (TempoSection& existing, const Tempo& replacement)
|
||||||
|
|
||||||
if ((ts = dynamic_cast<TempoSection*>(*i)) != 0 && ts == &existing) {
|
if ((ts = dynamic_cast<TempoSection*>(*i)) != 0 && ts == &existing) {
|
||||||
|
|
||||||
*((Tempo *) ts) = replacement;
|
*((Tempo *) ts) = replacement;
|
||||||
|
|
||||||
replaced = true;
|
replaced = true;
|
||||||
timestamp_metrics (true);
|
timestamp_metrics (true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -493,6 +513,21 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TempoMap::change_initial_tempo (double beats_per_minute, double note_type)
|
||||||
|
{
|
||||||
|
Tempo newtempo (beats_per_minute, note_type);
|
||||||
|
TempoSection* t;
|
||||||
|
|
||||||
|
for (Metrics::iterator i = metrics->begin(); i != metrics->end(); ++i) {
|
||||||
|
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||||
|
*((Tempo*) t) = newtempo;
|
||||||
|
StateChanged (Change (0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TempoMap::change_existing_tempo_at (nframes_t where, double beats_per_minute, double note_type)
|
TempoMap::change_existing_tempo_at (nframes_t where, double beats_per_minute, double note_type)
|
||||||
{
|
{
|
||||||
|
|
@ -582,6 +617,8 @@ TempoMap::timestamp_metrics (bool use_bbt)
|
||||||
|
|
||||||
if (use_bbt) {
|
if (use_bbt) {
|
||||||
|
|
||||||
|
// cerr << "\n\n\n ######################\nTIMESTAMP via BBT ##############\n" << endl;
|
||||||
|
|
||||||
nframes_t current = 0;
|
nframes_t current = 0;
|
||||||
nframes_t section_frames;
|
nframes_t section_frames;
|
||||||
BBT_Time start;
|
BBT_Time start;
|
||||||
|
|
@ -611,42 +648,68 @@ TempoMap::timestamp_metrics (bool use_bbt)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// cerr << "\n\n\n ######################\nTIMESTAMP via AUDIO ##############\n" << endl;
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
MetricSection* prev = 0;
|
||||||
|
|
||||||
for (i = metrics->begin(); i != metrics->end(); ++i) {
|
for (i = metrics->begin(); i != metrics->end(); ++i) {
|
||||||
|
|
||||||
BBT_Time bbt;
|
BBT_Time bbt;
|
||||||
|
Metric metric (*meter, *tempo);
|
||||||
|
|
||||||
bbt_time_with_metric ((*i)->frame(), bbt, Metric (*meter, *tempo));
|
if (prev) {
|
||||||
|
metric.set_start (prev->start());
|
||||||
|
} else {
|
||||||
|
// metric will be at frames=0 bbt=1|1|0 by default
|
||||||
|
// which is correct for our purpose
|
||||||
|
}
|
||||||
|
|
||||||
|
bbt_time_with_metric ((*i)->frame(), bbt, metric);
|
||||||
|
|
||||||
// cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => ";
|
// cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => ";
|
||||||
|
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
if (bbt.beats != 1 || bbt.ticks != 0) {
|
|
||||||
|
if (bbt.ticks > Meter::ticks_per_beat/2) {
|
||||||
|
/* round up to next beat */
|
||||||
|
bbt.beats += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bbt.ticks = 0;
|
||||||
|
|
||||||
|
if (bbt.beats != 1) {
|
||||||
|
/* round up to next bar */
|
||||||
bbt.bars += 1;
|
bbt.bars += 1;
|
||||||
bbt.beats = 1;
|
bbt.beats = 1;
|
||||||
bbt.ticks = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cerr << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << endl;
|
//s cerr << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << endl;
|
||||||
|
|
||||||
(*i)->set_start (bbt);
|
(*i)->set_start (bbt);
|
||||||
|
|
||||||
if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
|
if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
|
||||||
tempo = t;
|
tempo = t;
|
||||||
|
// cerr << "NEW TEMPO, frame = " << (*i)->frame() << " start = " << (*i)->start() <<endl;
|
||||||
} else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
|
} else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
|
||||||
meter = m;
|
meter = m;
|
||||||
|
// cerr << "NEW METER, frame = " << (*i)->frame() << " start = " << (*i)->start() <<endl;
|
||||||
} else {
|
} else {
|
||||||
fatal << _("programming error: unhandled MetricSection type") << endmsg;
|
fatal << _("programming error: unhandled MetricSection type") << endmsg;
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev = (*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dump (cerr);
|
// dump (cerr);
|
||||||
|
// cerr << "###############################################\n\n\n" << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TempoMap::Metric
|
TempoMap::Metric
|
||||||
|
|
@ -741,6 +804,8 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
|
||||||
double xtra_beats = 0;
|
double xtra_beats = 0;
|
||||||
double beats = 0;
|
double beats = 0;
|
||||||
|
|
||||||
|
// cerr << "---- BBT time for " << frame << " using metric @ " << metric.frame() << " BBT " << metric.start() << endl;
|
||||||
|
|
||||||
const double beats_per_bar = metric.meter().beats_per_bar();
|
const double beats_per_bar = metric.meter().beats_per_bar();
|
||||||
const double frames_per_bar = metric.meter().frames_per_bar (metric.tempo(), _frame_rate);
|
const double frames_per_bar = metric.meter().frames_per_bar (metric.tempo(), _frame_rate);
|
||||||
const double beat_frames = metric.tempo().frames_per_beat (_frame_rate, metric.meter());
|
const double beat_frames = metric.tempo().frames_per_beat (_frame_rate, metric.meter());
|
||||||
|
|
@ -749,10 +814,13 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
|
||||||
|
|
||||||
frame_diff = frame - metric.frame();
|
frame_diff = frame - metric.frame();
|
||||||
|
|
||||||
|
// cerr << "----\tdelta = " << frame_diff << endl;
|
||||||
|
|
||||||
xtra_bars = (uint32_t) floor (frame_diff / frames_per_bar);
|
xtra_bars = (uint32_t) floor (frame_diff / frames_per_bar);
|
||||||
frame_diff -= (uint32_t) floor (xtra_bars * frames_per_bar);
|
frame_diff -= (uint32_t) floor (xtra_bars * frames_per_bar);
|
||||||
xtra_beats = (double) frame_diff / beat_frames;
|
xtra_beats = (double) frame_diff / beat_frames;
|
||||||
|
|
||||||
|
// cerr << "---\tmeaning " << xtra_bars << " xtra bars and " << xtra_beats << " xtra beats\n";
|
||||||
|
|
||||||
/* and set the returned value */
|
/* and set the returned value */
|
||||||
|
|
||||||
|
|
@ -772,14 +840,14 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
|
||||||
bbt.ticks = (uint32_t)( round((beats - floor(beats)) *(double) Meter::ticks_per_beat));
|
bbt.ticks = (uint32_t)( round((beats - floor(beats)) *(double) Meter::ticks_per_beat));
|
||||||
bbt.beats = (uint32_t) floor(beats);
|
bbt.beats = (uint32_t) floor(beats);
|
||||||
|
|
||||||
|
// cerr << "-----\t RETURN " << bbt << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) const
|
TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) const
|
||||||
{
|
{
|
||||||
/* for this to work with fractional measure types, start and end have to be "legal" BBT types,
|
/* for this to work with fractional measure types, start and end have to be "legal" BBT types,
|
||||||
that means that the beats and ticks should be inside a bar
|
that means that the beats and ticks should be inside a bar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nframes_t frames = 0;
|
nframes_t frames = 0;
|
||||||
|
|
@ -814,7 +882,7 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
|
||||||
nframes_t
|
nframes_t
|
||||||
TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo, const BBT_Time& start, const BBT_Time& end) const
|
TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo, const BBT_Time& start, const BBT_Time& end) const
|
||||||
{
|
{
|
||||||
/*this is used in timestamping the metrics by actually counting the beats */
|
/* this is used in timestamping the metrics by actually counting the beats */
|
||||||
|
|
||||||
nframes_t frames = 0;
|
nframes_t frames = 0;
|
||||||
uint32_t bar = start.bars;
|
uint32_t bar = start.bars;
|
||||||
|
|
@ -834,17 +902,27 @@ TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo,
|
||||||
beat = 1;
|
beat = 1;
|
||||||
++bar;
|
++bar;
|
||||||
++beats_counted;
|
++beats_counted;
|
||||||
|
|
||||||
|
if (beat > beats_per_bar) {
|
||||||
|
|
||||||
|
/* this is a fractional beat at the end of a fractional bar
|
||||||
|
so it should only count for the fraction
|
||||||
|
*/
|
||||||
|
|
||||||
|
beats_counted -= (ceil(beats_per_bar) - beats_per_bar);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
++beat;
|
++beat;
|
||||||
++beats_counted;
|
++beats_counted;
|
||||||
if (beat > beats_per_bar) {
|
|
||||||
/* this is a fractional beat at the end of a fractional bar
|
|
||||||
so it should only count for the fraction */
|
|
||||||
beats_counted -= (ceil(beats_per_bar) - beats_per_bar);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cerr << "Counted " << beats_counted << " from " << start << " to " << end
|
||||||
|
// << " bpb were " << beats_per_bar
|
||||||
|
// << " fpb was " << beat_frames
|
||||||
|
// << endl;
|
||||||
|
|
||||||
frames = (nframes_t) floor (beats_counted * beat_frames);
|
frames = (nframes_t) floor (beats_counted * beat_frames);
|
||||||
|
|
||||||
return frames;
|
return frames;
|
||||||
|
|
@ -1052,7 +1130,6 @@ TempoMap::round_to_beat_subdivision (nframes_t fr, int sub_num)
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
|
|
||||||
TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
|
TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
|
||||||
{
|
{
|
||||||
Metric metric = metric_at (frame);
|
Metric metric = metric_at (frame);
|
||||||
|
|
@ -1191,7 +1268,9 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
|
||||||
|
|
||||||
if (i == metrics->end()) {
|
if (i == metrics->end()) {
|
||||||
limit = upper;
|
limit = upper;
|
||||||
|
// cerr << "== limit set to end of request @ " << limit << endl;
|
||||||
} else {
|
} else {
|
||||||
|
// cerr << "== limit set to next metric @ " << (*i)->frame() << endl;
|
||||||
limit = (*i)->frame();
|
limit = (*i)->frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1224,6 +1303,10 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
|
||||||
beat++;
|
beat++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cerr << "out of beats, @ end ? " << (i == metrics->end()) << " out of bpb ? "
|
||||||
|
// << (beat > ceil(beats_per_bar))
|
||||||
|
// << endl;
|
||||||
|
|
||||||
if (beat > ceil(beats_per_bar) || i != metrics->end()) {
|
if (beat > ceil(beats_per_bar) || i != metrics->end()) {
|
||||||
|
|
||||||
/* we walked an entire bar. its
|
/* we walked an entire bar. its
|
||||||
|
|
@ -1245,9 +1328,11 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
|
||||||
if (beat > ceil (beats_per_bar)) {
|
if (beat > ceil (beats_per_bar)) {
|
||||||
/* next bar goes where the numbers suggest */
|
/* next bar goes where the numbers suggest */
|
||||||
current -= beat_frames * (ceil(beats_per_bar)-beats_per_bar);
|
current -= beat_frames * (ceil(beats_per_bar)-beats_per_bar);
|
||||||
|
// cerr << "++ next bar from numbers\n";
|
||||||
} else {
|
} else {
|
||||||
/* next bar goes where the next metric is */
|
/* next bar goes where the next metric is */
|
||||||
current = limit;
|
current = limit;
|
||||||
|
// cerr << "++ next bar at next metric\n";
|
||||||
}
|
}
|
||||||
bar++;
|
bar++;
|
||||||
beat = 1;
|
beat = 1;
|
||||||
|
|
@ -1275,6 +1360,9 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
|
||||||
beat = 1;
|
beat = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current = (*i)->frame ();
|
||||||
|
// cerr << "loop around with current @ " << current << endl;
|
||||||
|
|
||||||
beats_per_bar = meter->beats_per_bar ();
|
beats_per_bar = meter->beats_per_bar ();
|
||||||
frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
|
frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
|
||||||
beat_frames = tempo->frames_per_beat (_frame_rate, *meter);
|
beat_frames = tempo->frames_per_beat (_frame_rate, *meter);
|
||||||
|
|
@ -1419,3 +1507,32 @@ TempoMap::dump (std::ostream& o) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
TempoMap::n_tempos() const
|
||||||
|
{
|
||||||
|
Glib::RWLock::ReaderLock lm (lock);
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
for (Metrics::const_iterator i = metrics->begin(); i != metrics->end(); ++i) {
|
||||||
|
if (dynamic_cast<const TempoSection*>(*i) != 0) {
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
TempoMap::n_meters() const
|
||||||
|
{
|
||||||
|
Glib::RWLock::ReaderLock lm (lock);
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
for (Metrics::const_iterator i = metrics->begin(); i != metrics->end(); ++i) {
|
||||||
|
if (dynamic_cast<const MeterSection*>(*i) != 0) {
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,36 @@ using namespace Vamp;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
string TransientDetector::_op_id;
|
||||||
|
|
||||||
TransientDetector::TransientDetector (float sr)
|
TransientDetector::TransientDetector (float sr)
|
||||||
: AudioAnalyser (sr, X_("libardourvampplugins:percussiononsets"))
|
: AudioAnalyser (sr, X_("libardourvampplugins:percussiononsets"))
|
||||||
{
|
{
|
||||||
|
if (_op_id.empty()) {
|
||||||
|
_op_id = X_("libardourvampplugins:percussiononsets");
|
||||||
|
|
||||||
|
// XXX this should load the above-named plugin and get the current version
|
||||||
|
|
||||||
|
_op_id += ":2";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TransientDetector::~TransientDetector()
|
TransientDetector::~TransientDetector()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
TransientDetector::operational_identifier()
|
||||||
|
{
|
||||||
|
return _op_id;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
TransientDetector::run (const std::string& path, Readable* src, uint32_t channel, vector<nframes64_t>& results)
|
TransientDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results)
|
||||||
{
|
{
|
||||||
current_results = &results;
|
current_results = &results;
|
||||||
int ret = analyse (path, src, channel);
|
int ret = analyse (path, src, channel);
|
||||||
|
|
||||||
current_results = 0;
|
current_results = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -59,3 +75,42 @@ TransientDetector::set_sensitivity (float val)
|
||||||
plugin->setParameter ("sensitivity", val);
|
plugin->setParameter ("sensitivity", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TransientDetector::cleanup_transients (AnalysisFeatureList& t, float sr, float gap_msecs)
|
||||||
|
{
|
||||||
|
if (t.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.sort ();
|
||||||
|
|
||||||
|
/* remove duplicates or other things that are too close */
|
||||||
|
|
||||||
|
AnalysisFeatureList::iterator i = t.begin();
|
||||||
|
AnalysisFeatureList::iterator f, b;
|
||||||
|
const nframes64_t gap_frames = (nframes64_t) floor (gap_msecs * (sr / 1000.0));
|
||||||
|
|
||||||
|
while (i != t.end()) {
|
||||||
|
|
||||||
|
// move front iterator to just past i, and back iterator the same place
|
||||||
|
|
||||||
|
f = i;
|
||||||
|
++f;
|
||||||
|
b = f;
|
||||||
|
|
||||||
|
// move f until we find a new value that is far enough away
|
||||||
|
|
||||||
|
while ((f != t.end()) && (((*f) - (*i)) < gap_frames)) {
|
||||||
|
++f;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = f;
|
||||||
|
|
||||||
|
// if f moved forward from b, we had duplicates/too-close points: get rid of them
|
||||||
|
|
||||||
|
if (b != f) {
|
||||||
|
t.erase (b, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ gnomecanvasmm.Merge([libraries['glibmm2'],
|
||||||
libraries['libgnomecanvas2'],
|
libraries['libgnomecanvas2'],
|
||||||
libraries['cairomm']])
|
libraries['cairomm']])
|
||||||
|
|
||||||
gnomecanvasmm.Append(CXXFLAGS = ["-DGLIBMM_PROPERTIES_ENABLED", "-DGLIBMM_EXCEPTIONS_ENABLED"])
|
if gnomecanvasmm['IS_OSX']:
|
||||||
|
gnomecanvasmm.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
|
||||||
|
|
||||||
libgnomecanvasmm = gnomecanvasmm.SharedLibrary('libgnomecanvasmm', gnomecanvasmm_files)
|
libgnomecanvasmm = gnomecanvasmm.SharedLibrary('libgnomecanvasmm', gnomecanvasmm_files)
|
||||||
Default(libgnomecanvasmm)
|
Default(libgnomecanvasmm)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ Import('env libraries install_prefix')
|
||||||
midi2 = env.Copy()
|
midi2 = env.Copy()
|
||||||
midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], libraries['glib2'], libraries['pbd'], libraries['jack'] ])
|
midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], libraries['glib2'], libraries['pbd'], libraries['jack'] ])
|
||||||
|
|
||||||
|
if midi2['IS_OSX']:
|
||||||
|
midi2.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
|
||||||
|
|
||||||
domain = 'midipp'
|
domain = 'midipp'
|
||||||
|
|
||||||
midi2.Append(DOMAIN=domain,MAJOR=2,MINOR=1,MICRO=1)
|
midi2.Append(DOMAIN=domain,MAJOR=2,MINOR=1,MICRO=1)
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ public:
|
||||||
|
|
||||||
OutputList getOutputDescriptors() const;
|
OutputList getOutputDescriptors() const;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||||
|
|
||||||
FeatureSet getRemainingFeatures();
|
FeatureSet getRemainingFeatures();
|
||||||
|
|
@ -226,6 +228,7 @@ protected:
|
||||||
float **m_buffers;
|
float **m_buffers;
|
||||||
float m_inputSampleRate;
|
float m_inputSampleRate;
|
||||||
RealTime m_timestamp;
|
RealTime m_timestamp;
|
||||||
|
bool m_unrun;
|
||||||
OutputList m_outputs;
|
OutputList m_outputs;
|
||||||
|
|
||||||
void processBlock(FeatureSet& allFeatureSets, RealTime timestamp);
|
void processBlock(FeatureSet& allFeatureSets, RealTime timestamp);
|
||||||
|
|
@ -254,6 +257,12 @@ PluginBufferingAdapter::getOutputDescriptors() const
|
||||||
return m_impl->getOutputDescriptors();
|
return m_impl->getOutputDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginBufferingAdapter::reset()
|
||||||
|
{
|
||||||
|
m_impl->reset();
|
||||||
|
}
|
||||||
|
|
||||||
PluginBufferingAdapter::FeatureSet
|
PluginBufferingAdapter::FeatureSet
|
||||||
PluginBufferingAdapter::process(const float *const *inputBuffers,
|
PluginBufferingAdapter::process(const float *const *inputBuffers,
|
||||||
RealTime timestamp)
|
RealTime timestamp)
|
||||||
|
|
@ -277,7 +286,8 @@ PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
||||||
m_queue(0),
|
m_queue(0),
|
||||||
m_buffers(0),
|
m_buffers(0),
|
||||||
m_inputSampleRate(inputSampleRate),
|
m_inputSampleRate(inputSampleRate),
|
||||||
m_timestamp()
|
m_timestamp(RealTime::zeroTime),
|
||||||
|
m_unrun(true)
|
||||||
{
|
{
|
||||||
m_outputs = plugin->getOutputDescriptors();
|
m_outputs = plugin->getOutputDescriptors();
|
||||||
}
|
}
|
||||||
|
|
@ -333,8 +343,8 @@ PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize
|
// std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize
|
||||||
<< ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
|
// << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
|
||||||
|
|
||||||
// current implementation breaks if step is greater than block
|
// current implementation breaks if step is greater than block
|
||||||
if (m_stepSize > m_blockSize) {
|
if (m_stepSize > m_blockSize) {
|
||||||
|
|
@ -365,12 +375,28 @@ PluginBufferingAdapter::Impl::getOutputDescriptors() const
|
||||||
return outs;
|
return outs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginBufferingAdapter::Impl::reset()
|
||||||
|
{
|
||||||
|
m_timestamp = RealTime::zeroTime;
|
||||||
|
m_unrun = true;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_queue.size(); ++i) {
|
||||||
|
m_queue[i]->reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PluginBufferingAdapter::FeatureSet
|
PluginBufferingAdapter::FeatureSet
|
||||||
PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
|
PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
|
||||||
RealTime timestamp)
|
RealTime timestamp)
|
||||||
{
|
{
|
||||||
FeatureSet allFeatureSets;
|
FeatureSet allFeatureSets;
|
||||||
|
|
||||||
|
if (m_unrun) {
|
||||||
|
m_timestamp = timestamp;
|
||||||
|
m_unrun = false;
|
||||||
|
}
|
||||||
|
|
||||||
// queue the new input
|
// queue the new input
|
||||||
|
|
||||||
for (size_t i = 0; i < m_channels; ++i) {
|
for (size_t i = 0; i < m_channels; ++i) {
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ public:
|
||||||
|
|
||||||
OutputList getOutputDescriptors() const;
|
OutputList getOutputDescriptors() const;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||||
|
|
||||||
FeatureSet getRemainingFeatures();
|
FeatureSet getRemainingFeatures();
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
|
||||||
|
|
||||||
m_pluginChannels = minch;
|
m_pluginChannels = minch;
|
||||||
|
|
||||||
std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
// std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
||||||
|
|
||||||
} else if (m_inputChannels > maxch) {
|
} else if (m_inputChannels > maxch) {
|
||||||
|
|
||||||
|
|
@ -155,18 +155,18 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
|
||||||
m_buffer = new float *[1];
|
m_buffer = new float *[1];
|
||||||
m_buffer[0] = new float[blockSize];
|
m_buffer[0] = new float[blockSize];
|
||||||
|
|
||||||
std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
|
// std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
// std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pluginChannels = maxch;
|
m_pluginChannels = maxch;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
|
// std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
|
||||||
m_pluginChannels = m_inputChannels;
|
m_pluginChannels = m_inputChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@
|
||||||
Centre for Digital Music, Queen Mary, University of London.
|
Centre for Digital Music, Queen Mary, University of London.
|
||||||
Copyright 2006-2007 Chris Cannam and QMUL.
|
Copyright 2006-2007 Chris Cannam and QMUL.
|
||||||
|
|
||||||
|
This file is based in part on Don Cross's public domain FFT
|
||||||
|
implementation.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
files (the "Software"), to deal in the Software without
|
files (the "Software"), to deal in the Software without
|
||||||
|
|
@ -38,28 +41,33 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If you want to compile using FFTW instead of the built-in FFT
|
* If you want to compile using FFTW instead of the built-in FFT
|
||||||
* implementation for the PluginInputDomainAdapter, define HAVE_FFTW3
|
* implementation for the PluginInputDomainAdapter, define HAVE_FFTW3
|
||||||
* in the Makefile.
|
* in the Makefile.
|
||||||
*
|
*
|
||||||
* Remember that FFTW is licensed under the GPL (unlike this SDK, which
|
* Be aware that FFTW is licensed under the GPL -- unlike this SDK,
|
||||||
* is licensed liberally in order to permit closed-source usage), so
|
* which is provided under a more liberal BSD license in order to
|
||||||
* you should not define this symbol unless your code is also under the
|
* permit use in closed source applications. The use of FFTW would
|
||||||
* GPL. Also, parties redistributing this SDK for use in other
|
* mean that your code would need to be licensed under the GPL as
|
||||||
* programs should be careful _not_ to define this symbol in order not
|
* well. Do not define this symbol unless you understand and accept
|
||||||
* to affect the stated license of this SDK.
|
* the implications of this.
|
||||||
*
|
*
|
||||||
* Note: This code uses FFTW_MEASURE, and will perform badly on its
|
* Parties such as Linux distribution packagers who redistribute this
|
||||||
* first invocation unless the host has saved and restored FFTW wisdom
|
* SDK for use in other programs should _not_ define this symbol, as
|
||||||
* (see the FFTW documentation).
|
* it would change the effective licensing terms under which the SDK
|
||||||
|
* was available to third party developers.
|
||||||
|
*
|
||||||
|
* The default is not to use FFTW, and to use the built-in FFT instead.
|
||||||
|
*
|
||||||
|
* Note: The FFTW code uses FFTW_MEASURE, and so will perform badly on
|
||||||
|
* its first invocation unless the host has saved and restored FFTW
|
||||||
|
* wisdom (see the FFTW documentation).
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_FFTW3
|
#ifdef HAVE_FFTW3
|
||||||
#include <fftw3.h>
|
#include <fftw3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Vamp {
|
namespace Vamp {
|
||||||
|
|
||||||
namespace HostExt {
|
namespace HostExt {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __ardour_svn_revision_h__
|
#ifndef __ardour_svn_revision_h__
|
||||||
#define __ardour_svn_revision_h__
|
#define __ardour_svn_revision_h__
|
||||||
static const char* ardour_svn_revision = "2918";
|
static const char* ardour_svn_revision = "2985";
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue