Merge with 2.0-ongoing R2885.

Fix loading of 2.0 sessions.


git-svn-id: svn://localhost/ardour2/trunk@2904 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2008-01-12 23:45:50 +00:00
parent bf256c1681
commit e92c1669c1
64 changed files with 7929 additions and 1269 deletions

View file

@ -231,6 +231,7 @@ def i18n (buildenv, sources, installenv):
buildenv.PoBuild(po_file, ['po/'+po_file, potfile]) buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
mo_file = po_file.replace (".po", ".mo") mo_file = po_file.replace (".po", ".mo")
installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file)) installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
installenv.Alias ('msgupdate', buildenv.MoBuild (mo_file, po_file))
for lang in languages: for lang in languages:
modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/')) modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
@ -363,7 +364,7 @@ def distcopy (target, source, env):
return p.close () return p.close ()
def tarballer (target, source, env): def tarballer (target, source, env):
cmd = 'tar -jcf ' + str (target[0]) + ' ' + str(source[0]) + " --exclude '*~'" cmd = 'tar -jcf ' + str (target[0]) + ' ' + str(source[0]) + " --exclude '*~'" + " --exclude .svn --exclude '.svn/*'"
print 'running ', cmd, ' ... ' print 'running ', cmd, ' ... '
p = os.popen (cmd) p = os.popen (cmd)
return p.close () return p.close ()
@ -766,34 +767,32 @@ def prep_libcheck(topenv, libinfo):
prep_libcheck(env, env) prep_libcheck(env, env)
#
# check for VAMP and rubberband (currently optional)
#
libraries['vamp'] = LibraryInfo() libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
LIBPATH='#libs/vamp-sdk',
CPPPATH='#libs/vamp-sdk/vamp')
env['RUBBERBAND'] = False env['RUBBERBAND'] = False
#conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } ) #conf = Configure (env)
# #
#if conf.CheckPKGExists('vamp-sdk'): #if conf.CheckHeader ('fftw3.h'):
# have_vamp = True # env['RUBBERBAND'] = True
# libraries['vamp'].ParseConfig('pkg-config --cflags --libs vamp-sdk') # libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
# LIBPATH='#libs/rubberband',
# CPPPATH='#libs/rubberband',
# CCFLAGS='-DUSE_RUBBERBAND')
#else: #else:
# have_vamp = False # print ""
# print "-------------------------------------------------------------------------"
# print "You do not have the FFTW single-precision development package installed."
# print "This prevents Ardour from using the Rubberband library for timestretching"
# print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
# print "pitchshifting will not be available."
# print "-------------------------------------------------------------------------"
# print ""
# #
#libraries['vamp'] = conf.Finish () #conf.Finish()
#
#if have_vamp:
# if os.path.exists ('libs/rubberband/src'):
# conf = Configure (libraries['vamp'])
# if conf.CheckHeader ('fftw3.h'):
# env['RUBBERBAND'] = True
# libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
# LIBPATH='#libs/rubberband',
# CPPPATH='#libs/rubberband',
# CCFLAGS='-DUSE_RUBBERBAND')
# libraries['vamp'] = conf.Finish ()
# #
# Check for libusb # Check for libusb
@ -995,6 +994,7 @@ if env['SYSLIBS']:
'libs/pbd', 'libs/pbd',
'libs/midi++2', 'libs/midi++2',
'libs/ardour', 'libs/ardour',
'libs/vamp-sdk',
# these are unconditionally included but have # these are unconditionally included but have
# tests internally to avoid compilation etc # tests internally to avoid compilation etc
# if VST is not set # if VST is not set
@ -1068,6 +1068,7 @@ else:
'libs/pbd', 'libs/pbd',
'libs/midi++2', 'libs/midi++2',
'libs/ardour', 'libs/ardour',
'libs/vamp-sdk',
# these are unconditionally included but have # these are unconditionally included but have
# tests internally to avoid compilation etc # tests internally to avoid compilation etc
# if VST is not set # if VST is not set
@ -1132,7 +1133,7 @@ else:
timefx_subdirs = ['libs/soundtouch'] timefx_subdirs = ['libs/soundtouch']
#if env['RUBBERBAND']: #if env['RUBBERBAND']:
# timefx_subdirs += ['libs/rubberband'] # timefx_subdirs += ['libs/rubberband']
opts.Save('scache.conf', env) opts.Save('scache.conf', env)
Help(opts.GenerateHelpText(env)) Help(opts.GenerateHelpText(env))

View file

@ -37,7 +37,9 @@
<Option name="destructive-xfade-msecs" value="20"/> <Option name="destructive-xfade-msecs" value="20"/>
<Option name="periodic-safety-backups" value="1"/> <Option name="periodic-safety-backups" value="1"/>
<Option name="periodic-safety-backup-interval" value="120"/> <Option name="periodic-safety-backup-interval" value="120"/>
<Option name="show-track-meters" value="1"/> <Option name="show-track-meters" value="1"/>
<Option name="default-narrow_ms" value="0"/>
<Option name="smpte-format" value="6"/>
</Config> </Config>
<extra> <extra>
<Keyboard edit-button="3" edit-modifier="4" delete-button="3" delete-modifier="1" snap-modifier="32"/> <Keyboard edit-button="3" edit-modifier="4" delete-button="3" delete-modifier="1" snap-modifier="32"/>

View file

@ -1341,7 +1341,6 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t
} }
catch (...) { catch (...) {
cerr << "About to complain about JACK\n";
MessageDialog msg (*editor, MessageDialog msg (*editor,
_("There are insufficient JACK ports available\n\ _("There are insufficient JACK ports available\n\
to create a new track or bus.\n\ to create a new track or bus.\n\
@ -2270,7 +2269,7 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
if (session_name[0] == '/' || if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') || (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) { (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
cerr << "here\n";
if (load_session (Glib::path_get_dirname (session_name), session_name)) { if (load_session (Glib::path_get_dirname (session_name), session_name)) {
response = Gtk::RESPONSE_NONE; response = Gtk::RESPONSE_NONE;
goto try_again; goto try_again;

View file

@ -900,19 +900,6 @@ Editor::show_window ()
present (); present ();
} }
void
Editor::tie_vertical_scrolling ()
{
double y1 = vertical_adjustment.get_value();
playhead_cursor->set_y_axis (y1);
if (logo_item) {
logo_item->property_y() = y1;
}
controls_layout.get_vadjustment()->set_value (y1);
}
void void
Editor::instant_save () Editor::instant_save ()
{ {
@ -1431,28 +1418,179 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
fade_context_menu.popup (button, time); fade_context_menu.popup (button, time);
} }
/* Pop up the general track context menu for when the user clicks pretty much anywhere in a track or bus */
void void
Editor::popup_track_context_menu (int button, int32_t time, nframes_t frame) Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes_t frame)
{ {
build_track_context_menu (frame)->popup (button, time); using namespace Menu_Helpers;
Menu* (Editor::*build_menu_function)(nframes_t);
Menu *menu;
switch (item_type) {
case RegionItem:
case RegionViewName:
case RegionViewNameHighlight:
if (with_selection) {
build_menu_function = &Editor::build_track_selection_context_menu;
} else {
build_menu_function = &Editor::build_track_region_context_menu;
}
break;
case SelectionItem:
if (with_selection) {
build_menu_function = &Editor::build_track_selection_context_menu;
} else {
build_menu_function = &Editor::build_track_context_menu;
}
break;
case CrossfadeViewItem:
build_menu_function = &Editor::build_track_crossfade_context_menu;
break;
case StreamItem:
if (clicked_routeview->get_diskstream()) {
build_menu_function = &Editor::build_track_context_menu;
} else {
build_menu_function = &Editor::build_track_bus_context_menu;
}
break;
default:
/* probably shouldn't happen but if it does, we don't care */
return;
}
menu = (this->*build_menu_function)(frame);
menu->set_name ("ArdourContextMenu");
/* now handle specific situations */
switch (item_type) {
case RegionItem:
case RegionViewName:
case RegionViewNameHighlight:
if (!with_selection) {
if (region_edit_menu_split_item) {
if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
} else {
ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
}
}
/*
if (region_edit_menu_split_multichannel_item) {
if (clicked_regionview && clicked_regionview->region().n_channels() > 1) {
// GTK2FIX find the action, change its sensitivity
// region_edit_menu_split_multichannel_item->set_sensitive (true);
} else {
// GTK2FIX see above
// region_edit_menu_split_multichannel_item->set_sensitive (false);
}
}*/
}
break;
case SelectionItem:
break;
case CrossfadeViewItem:
break;
case StreamItem:
break;
default:
/* probably shouldn't happen but if it does, we don't care */
return;
}
if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
/* Bounce to disk */
using namespace Menu_Helpers;
MenuList& edit_items = menu->items();
edit_items.push_back (SeparatorElem());
switch (clicked_routeview->audio_track()->freeze_state()) {
case AudioTrack::NoFreeze:
edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
break;
case AudioTrack::Frozen:
edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
break;
case AudioTrack::UnFrozen:
edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
break;
}
}
menu->popup (button, time);
} }
Menu* Menu*
Editor::build_track_context_menu (nframes_t frame) Editor::build_track_context_menu (nframes_t ignored)
{ {
using namespace Menu_Helpers; using namespace Menu_Helpers;
Menu* menu = manage (new Menu); MenuList& edit_items = track_context_menu.items();
MenuList& edit_items = menu->items();
edit_items.clear(); edit_items.clear();
/* Build the general `track' context menu, adding what is appropriate given add_dstream_context_items (edit_items);
the current selection */ return &track_context_menu;
}
Menu*
Editor::build_track_bus_context_menu (nframes_t ignored)
{
using namespace Menu_Helpers;
MenuList& edit_items = track_context_menu.items();
edit_items.clear();
add_bus_context_items (edit_items);
return &track_context_menu;
}
Menu*
Editor::build_track_region_context_menu (nframes_t frame)
{
using namespace Menu_Helpers;
MenuList& edit_items = track_region_context_menu.items();
edit_items.clear();
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
if (rtv) {
boost::shared_ptr<Diskstream> ds;
boost::shared_ptr<Playlist> pl;
if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed()));
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
add_region_context_items (rtv->view(), (*i), edit_items);
}
delete regions;
}
}
add_dstream_context_items (edit_items);
return &track_region_context_menu;
}
Menu*
Editor::build_track_crossfade_context_menu (nframes_t frame)
{
using namespace Menu_Helpers;
MenuList& edit_items = track_crossfade_context_menu.items();
edit_items.clear ();
/* XXX: currently crossfades can't be selected, so we can't use the selection
to decide which crossfades to mention in the menu. I believe this will
change at some point. For now we have to use clicked_trackview to decide. */
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview); AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview);
if (atv) { if (atv) {
@ -1462,7 +1600,9 @@ Editor::build_track_context_menu (nframes_t frame)
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) { if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) {
Playlist::RegionList* regions = pl->regions_at (frame);
AudioPlaylist::Crossfades xfades; AudioPlaylist::Crossfades xfades;
apl->crossfades_at (frame, xfades); apl->crossfades_at (frame, xfades);
bool many = xfades.size() > 1; bool many = xfades.size() > 1;
@ -1470,24 +1610,18 @@ Editor::build_track_context_menu (nframes_t frame)
for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) { for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many); add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
} }
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
add_region_context_items (atv->audio_view(), (*i), edit_items);
}
delete regions;
} }
}
if (!selection->time.empty()) {
add_selection_context_items (edit_items);
} }
if (!selection->regions.empty()) { add_dstream_context_items (edit_items);
add_region_context_items (edit_items);
}
if (!selection->tracks.empty()) { return &track_crossfade_context_menu;
add_bus_or_audio_track_context_items (edit_items);
}
menu->set_name ("ArdourContextMenu");
return menu;
} }
#ifdef FFT_ANALYSIS #ifdef FFT_ANALYSIS
@ -1528,6 +1662,19 @@ Editor::analyze_range_selection()
} }
#endif /* FFT_ANALYSIS */ #endif /* FFT_ANALYSIS */
Menu*
Editor::build_track_selection_context_menu (nframes_t ignored)
{
using namespace Menu_Helpers;
MenuList& edit_items = track_selection_context_menu.items();
edit_items.clear ();
add_selection_context_items (edit_items);
// edit_items.push_back (SeparatorElem());
// add_dstream_context_items (edit_items);
return &track_selection_context_menu;
}
/** Add context menu items relevant to crossfades. /** Add context menu items relevant to crossfades.
* @param edit_items List to add the items to. * @param edit_items List to add the items to.
@ -1603,34 +1750,27 @@ Editor::add_item_with_sensitivity (Menu_Helpers::MenuList& m, Menu_Helpers::Menu
} }
} }
/** Add context menu items relevant to regions.
* @param edit_items List to add the items to.
*/
void void
Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items) Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> region, Menu_Helpers::MenuList& edit_items)
{ {
using namespace Menu_Helpers; using namespace Menu_Helpers;
sigc::connection fooc; Menu *region_menu = manage (new Menu);
Menu *region_menu = manage (new Menu); MenuList& items = region_menu->items();
MenuList& items = region_menu->items();
region_menu->set_name ("ArdourContextMenu"); region_menu->set_name ("ArdourContextMenu");
items.push_back (MenuElem (_("Edit..."), mem_fun(*this, &Editor::edit_region))); boost::shared_ptr<AudioRegion> ar;
items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top))); boost::shared_ptr<MidiRegion> mr;
items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
Menu* sync_point_menu = manage (new Menu); if (region) {
MenuList& sync_point_items = sync_point_menu->items(); ar = boost::dynamic_pointer_cast<AudioRegion> (region);
sync_point_menu->set_name("ArdourContextMenu"); mr = boost::dynamic_pointer_cast<MidiRegion> (region);
}
sync_point_items.push_back (MenuElem (_("Define"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
sync_point_items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region_sync)));
items.push_back (MenuElem (_("Sync points"), *sync_point_menu)); /* when this particular menu pops up, make the relevant region
become selected.
*/
//add_item_with_sensitivity (items, MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)), selection->regions.size() == 1); region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
add_item_with_sensitivity (items, MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)), selection->regions.size() == 1);
items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region))); items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region))); items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
@ -1646,97 +1786,59 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection))); items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
#ifdef FFT_ANALYSIS #ifdef FFT_ANALYSIS
items.push_back (MenuElem (_("Analyze region"), mem_fun(*this, &Editor::analyze_region_selection))); if (ar)
items.push_back (MenuElem (_("Analyze region"), mem_fun(*this, &Editor::analyze_region_selection)));
#endif #endif
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
items.push_back (CheckMenuElem (_("Lock"))); sigc::connection fooc;
region_lock_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
#if FIXUP_REGION_MENU items.push_back (CheckMenuElem (_("Lock")));
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); fooc.block (true);
region_lock_item->set_active(); region_lock_item->set_active();
fooc.block (false); fooc.block (false);
} }
#endif
items.push_back (CheckMenuElem (_("Lock Position")));
region_lock_position_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_position_lock));
#if FIXUP_REGION_MENU
if (region->locked()) {
fooc.block (true);
region_lock_position_item->set_active();
fooc.block (false);
}
#endif
items.push_back (CheckMenuElem (_("Mute"))); items.push_back (CheckMenuElem (_("Mute")));
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));
#if FIXUP_REGION_MENU
if (region->muted()) { if (region->muted()) {
fooc.block (true); fooc.block (true);
region_mute_item->set_active(); region_mute_item->set_active();
fooc.block (false); fooc.block (false);
} }
#endif
if (!Profile->get_sae()) { if (!Profile->get_sae()) {
items.push_back (CheckMenuElem (_("Opaque"))); items.push_back (CheckMenuElem (_("Opaque")));
region_opaque_item = static_cast<CheckMenuItem*>(&items.back()); CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque)); fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
#if FIXUP_REGION_MENU
if (region->opaque()) { if (region->opaque()) {
fooc.block (true); fooc.block (true);
region_opaque_item->set_active(); region_opaque_item->set_active();
fooc.block (false); fooc.block (false);
} }
#endif
} }
/* We allow "Original position" if at least one region is not at its items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
natural position if (region->at_natural_position()) {
*/ items.back().set_sensitive (false);
RegionSelection::iterator i = selection->regions.begin();
while (i != selection->regions.end() && (*i)->region()->at_natural_position() == true) {
++i;
} }
add_item_with_sensitivity (items, MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)), i != selection->regions.end());
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
/* Find out if we have a selected audio region */ if (ar) {
i = selection->regions.begin();
while (i != selection->regions.end() && boost::dynamic_pointer_cast<AudioRegion>((*i)->region()) == 0) {
++i;
}
const bool have_selected_audio_region = (i != selection->regions.end());
if (have_selected_audio_region) {
Menu* envelopes_menu = manage (new Menu);
envelopes_menu->set_name ("ArdourContextMenu");
#if FIXUP_REGION_MENU
XXX NEED TO RESOLVE ONE v. MANY REGION ISSUE
MenuList& envelopes_items = envelopes_menu->items();
RegionView* rv = sv->find_view (ar); RegionView* rv = sv->find_view (ar);
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv); AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
if (!Profile->get_sae()) { if (!Profile->get_sae()) {
envelopes_items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes))); items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
envelopes_items.push_back (CheckMenuElem (_("Envelope Visible"))); items.push_back (CheckMenuElem (_("Envelope Visible")));
region_envelope_visible_item = static_cast<CheckMenuItem*> (&items.back()); CheckMenuItem* region_envelope_visible_item = static_cast<CheckMenuItem*> (&items.back());
fooc = region_envelope_visible_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_visibility)); fooc = region_envelope_visible_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_visibility));
if (arv->envelope_visible()) { if (arv->envelope_visible()) {
fooc.block (true); fooc.block (true);
@ -1744,8 +1846,8 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
fooc.block (false); fooc.block (false);
} }
envelopes_items.push_back (CheckMenuElem (_("Envelope Active"))); items.push_back (CheckMenuElem (_("Envelope Active")));
region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back()); CheckMenuItem* region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active)); fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
if (ar->envelope_active()) { if (ar->envelope_active()) {
@ -1756,39 +1858,25 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
} }
#endif
items.push_back (MenuElem (_("Envelopes"), *envelopes_menu));
#if FIXUP_REGION_MENU
if (ar->scale_amplitude() != 1.0f) { if (ar->scale_amplitude() != 1.0f) {
items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_regions))); items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
} else { } else {
items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_regions))); items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
} }
#endif
}
/* Find out if we have a selected MIDI region */
i = selection->regions.begin();
while (i != selection->regions.end() && boost::dynamic_pointer_cast<MidiRegion>((*i)->region()) == 0) {
++i;
}
const bool have_selected_midi_region = (i != selection->regions.end());
if (have_selected_midi_region) {
items.push_back (MenuElem (_("Quantize"), mem_fun(*this, &Editor::quantize_regions))); } else if (mr) {
items.push_back (MenuElem (_("Quantize"), mem_fun(*this, &Editor::quantize_region)));
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
} }
items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
items.push_back (SeparatorElem());
/* range related stuff */ /* range related stuff */
add_item_with_sensitivity (items, MenuElem (_("Add range markers"), mem_fun (*this, &Editor::add_location_from_audio_region)), selection->regions.size() == 1); items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region)));
items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_region)));
add_item_with_sensitivity (items, MenuElem (_("Set range selection"), mem_fun (*this, &Editor::set_selection_from_audio_region)), selection->regions.size() == 1);
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
/* Nudge region */ /* Nudge region */
@ -1797,12 +1885,13 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
MenuList& nudge_items = nudge_menu->items(); MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu"); nudge_menu->set_name ("ArdourContextMenu");
nudge_items.push_back (MenuElem (_("Nudge forward"), (bind (mem_fun(*this, &Editor::nudge_forward), false)))); nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
nudge_items.push_back (MenuElem (_("Nudge backward"), (bind (mem_fun(*this, &Editor::nudge_backward), false)))); nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
nudge_items.push_back (MenuElem (_("Nudge forward by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset)))); nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
nudge_items.push_back (MenuElem (_("Nudge backward by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset)))); nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
items.push_back (MenuElem (_("Nudge"), *nudge_menu)); items.push_back (MenuElem (_("Nudge"), *nudge_menu));
items.push_back (SeparatorElem());
Menu *trim_menu = manage (new Menu); Menu *trim_menu = manage (new Menu);
MenuList& trim_items = trim_menu->items(); MenuList& trim_items = trim_menu->items();
@ -1814,20 +1903,38 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch))); trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch)));
items.push_back (MenuElem (_("Trim"), *trim_menu)); items.push_back (MenuElem (_("Trim"), *trim_menu));
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region)))); items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
region_edit_menu_split_item = &items.back();
items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region)))); items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
region_edit_menu_split_multichannel_item = &items.back();
items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), false)))); items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), false))));
items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true)))); items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
items.push_back (MenuElem (_("Fill track"), (mem_fun(*this, &Editor::region_fill_track)))); items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_selected_regions))); items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
/* OK, stick the region submenu at the top of the list, and then add /* OK, stick the region submenu at the top of the list, and then add
the standard items. the standard items.
*/ */
string const menu_item_name = selection->regions.size() > 1 ? _("Regions") : _("Region"); /* we have to hack up the region name because "_" has a special
meaning for menu titles.
*/
string::size_type pos = 0;
string menu_item_name = region->name();
while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
menu_item_name.replace (pos, 1, "__");
pos += 2;
}
edit_items.push_back (MenuElem (menu_item_name, *region_menu)); edit_items.push_back (MenuElem (menu_item_name, *region_menu));
edit_items.push_back (SeparatorElem());
} }
/** Add context menu items relevant to selection ranges. /** Add context menu items relevant to selection ranges.
@ -1876,33 +1983,12 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection))); items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection)));
} }
/** Add context menu items relevant to busses or audio tracks.
* @param edit_items List to add the items to.
*/
void void
Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items) Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
{ {
using namespace Menu_Helpers; using namespace Menu_Helpers;
/* We add every possible action here, and de-sensitize things
that aren't allowed. The sensitivity logic is a bit spread out;
on the one hand I'm using things like can_cut_copy (), which is
reasonably complicated and so perhaps better near the function that
it expresses sensitivity for, and on the other hand checks
in this function as well. You can't really have can_* for everything
or the number of methods would get silly. */
bool const one_selected_region = selection->regions.size() == 1;
/* Count the number of selected audio tracks */
int n_audio_tracks = 0;
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
RouteTimeAxisView const * r = dynamic_cast<RouteTimeAxisView*>(*i);
if (r && r->is_audio_track()) {
n_audio_tracks++;
}
}
/* Playback */ /* Playback */
Menu *play_menu = manage (new Menu); Menu *play_menu = manage (new Menu);
@ -1911,9 +1997,9 @@ Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items
play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point))); play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start))); play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
add_item_with_sensitivity (play_items, MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)), one_selected_region); play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
play_items.push_back (SeparatorElem());
add_item_with_sensitivity (play_items, MenuElem (_("Loop region"), mem_fun(*this, &Editor::loop_selected_region)), one_selected_region); play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
edit_items.push_back (MenuElem (_("Play"), *play_menu)); edit_items.push_back (MenuElem (_("Play"), *play_menu));
@ -1922,25 +2008,15 @@ Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items
Menu *select_menu = manage (new Menu); Menu *select_menu = manage (new Menu);
MenuList& select_items = select_menu->items(); MenuList& select_items = select_menu->items();
select_menu->set_name ("ArdourContextMenu"); select_menu->set_name ("ArdourContextMenu");
string str = selection->tracks.size() == 1 ? _("Select all in track") : _("Select all in tracks");
select_items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::select_all_in_selected_tracks), Selection::Set)));
select_items.push_back (MenuElem (_("Select all"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
str = selection->tracks.size() == 1 ? _("Invert selection in track") : _("Invert selection in tracks");
select_items.push_back (MenuElem (str, mem_fun(*this, &Editor::invert_selection_in_selected_tracks)));
select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection))); select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
select_items.push_back (SeparatorElem()); select_items.push_back (SeparatorElem());
select_items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
if (n_audio_tracks) { select_items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
select_items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop))); select_items.push_back (SeparatorElem());
select_items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
}
select_items.push_back (MenuElem (_("Select All After Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true))); select_items.push_back (MenuElem (_("Select All After Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
select_items.push_back (MenuElem (_("Select All Before Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false))); select_items.push_back (MenuElem (_("Select All Before Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
select_items.push_back (MenuElem (_("Select All After Playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true))); select_items.push_back (MenuElem (_("Select All After Playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
@ -1958,69 +2034,97 @@ Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items
Menu *cutnpaste_menu = manage (new Menu); Menu *cutnpaste_menu = manage (new Menu);
MenuList& cutnpaste_items = cutnpaste_menu->items(); MenuList& cutnpaste_items = cutnpaste_menu->items();
cutnpaste_menu->set_name ("ArdourContextMenu"); cutnpaste_menu->set_name ("ArdourContextMenu");
cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut))); cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy))); cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f))); cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
add_item_with_sensitivity (cutnpaste_items, MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)), can_cut_copy ()); cutnpaste_items.push_back (SeparatorElem());
add_item_with_sensitivity (cutnpaste_items, MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)), can_cut_copy ()); cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
if (n_audio_tracks) {
cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f))); cutnpaste_items.push_back (SeparatorElem());
cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
cutnpaste_items.push_back (SeparatorElem());
cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
cutnpaste_items.push_back (MenuElem (_("Align relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
} else {
cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
}
edit_items.push_back (SeparatorElem());
edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu)); edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
if (n_audio_tracks) { /* Adding new material */
Menu *track_menu = manage (new Menu);
MenuList& track_items = track_menu->items();
track_menu->set_name ("ArdourContextMenu");
/* Adding new material */
add_item_with_sensitivity (track_items, MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)), n_audio_tracks == 1); edit_items.push_back (SeparatorElem());
add_item_with_sensitivity (track_items, MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)), n_audio_tracks == 1); edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
edit_items.push_back (MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
/* Nudge */
Menu *nudge_menu = manage (new Menu()); /* Nudge track */
MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu");
str = selection->tracks.size() == 1 ? _("Nudge track after edit cursor forward") : _("Nudge tracks after edit cursor forward"); Menu *nudge_menu = manage (new Menu());
MenuList& nudge_items = nudge_menu->items();
nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), true, true)))); nudge_menu->set_name ("ArdourContextMenu");
edit_items.push_back (SeparatorElem());
nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
str = selection->tracks.size() == 1 ? _("Nudge track backward") : _("Nudge tracks backward"); edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
}
nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), false, false))));
str = selection->tracks.size() == 1 ? _("Nudge track after edit cursor backward") : _("Nudge tracks after edit cursor backward"); void
Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), true, false)))); {
using namespace Menu_Helpers;
track_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
/* Freeze */ /* Playback */
track_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_routes)));
track_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_routes)));
str = selection->tracks.size() == 1 ? _("Track") : _("Tracks"); Menu *play_menu = manage (new Menu);
edit_items.push_back (MenuElem (str, *track_menu)); MenuList& play_items = play_menu->items();
} play_menu->set_name ("ArdourContextMenu");
play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
edit_items.push_back (MenuElem (_("Play"), *play_menu));
/* Selection */
Menu *select_menu = manage (new Menu);
MenuList& select_items = select_menu->items();
select_menu->set_name ("ArdourContextMenu");
select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
select_items.push_back (SeparatorElem());
select_items.push_back (MenuElem (_("Select all after edit point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
select_items.push_back (MenuElem (_("Select all before edit point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
select_items.push_back (MenuElem (_("Select all after playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
select_items.push_back (MenuElem (_("Select all before playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
edit_items.push_back (MenuElem (_("Select"), *select_menu));
/* Cut-n-Paste */
Menu *cutnpaste_menu = manage (new Menu);
MenuList& cutnpaste_items = cutnpaste_menu->items();
cutnpaste_menu->set_name ("ArdourContextMenu");
cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
Menu *nudge_menu = manage (new Menu());
MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu");
edit_items.push_back (SeparatorElem());
nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
} }
/* CURSOR SETTING AND MARKS AND STUFF */ /* CURSOR SETTING AND MARKS AND STUFF */

View file

@ -239,9 +239,9 @@ class Editor : public PublicEditor
bool extend_selection_to_track (TimeAxisView&); bool extend_selection_to_track (TimeAxisView&);
void play_selection (); void play_selection ();
void select_all_in_selected_tracks (Selection::Operation op); void select_all_in_track (Selection::Operation op);
void select_all (Selection::Operation op); void select_all (Selection::Operation op);
void invert_selection_in_selected_tracks (); void invert_selection_in_track ();
void invert_selection (); void invert_selection ();
void deselect_all (); void deselect_all ();
@ -511,16 +511,30 @@ class Editor : public PublicEditor
bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false); bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false);
void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set); void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, boost::weak_ptr<ARDOUR::Region>);
void collect_new_region_view (RegionView *); void collect_new_region_view (RegionView *);
void collect_and_select_new_region_view (RegionView *); void collect_and_select_new_region_view (RegionView *);
Gtk::Menu track_context_menu;
Gtk::Menu track_region_context_menu;
Gtk::Menu track_selection_context_menu;
Gtk::Menu track_crossfade_context_menu;
Gtk::MenuItem* region_edit_menu_split_item; Gtk::MenuItem* region_edit_menu_split_item;
Gtk::MenuItem* region_edit_menu_split_multichannel_item; Gtk::MenuItem* region_edit_menu_split_multichannel_item;
Gtk::Menu * track_region_edit_playlist_menu;
Gtk::Menu * track_edit_playlist_submenu;
Gtk::Menu * track_selection_edit_playlist_submenu;
void popup_track_context_menu (int, int, nframes_t); void popup_track_context_menu (int, int, ItemType, bool, nframes_t);
Gtk::Menu* build_track_context_menu (nframes_t); Gtk::Menu* build_track_context_menu (nframes_t);
void add_bus_or_audio_track_context_items (Gtk::Menu_Helpers::MenuList&); Gtk::Menu* build_track_bus_context_menu (nframes_t);
void add_region_context_items (Gtk::Menu_Helpers::MenuList&); Gtk::Menu* build_track_region_context_menu (nframes_t frame);
Gtk::Menu* build_track_crossfade_context_menu (nframes_t);
Gtk::Menu* build_track_selection_context_menu (nframes_t);
void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&);
void add_bus_context_items (Gtk::Menu_Helpers::MenuList&);
void add_region_context_items (StreamView*, boost::shared_ptr<ARDOUR::Region>, Gtk::Menu_Helpers::MenuList&);
void add_crossfade_context_items (AudioStreamView*, boost::shared_ptr<ARDOUR::Crossfade>, Gtk::Menu_Helpers::MenuList&, bool many); void add_crossfade_context_items (AudioStreamView*, boost::shared_ptr<ARDOUR::Crossfade>, Gtk::Menu_Helpers::MenuList&, bool many);
void add_selection_context_items (Gtk::Menu_Helpers::MenuList&); void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
@ -1031,10 +1045,10 @@ class Editor : public PublicEditor
void audition_playlist_region_standalone (boost::shared_ptr<ARDOUR::Region>); void audition_playlist_region_standalone (boost::shared_ptr<ARDOUR::Region>);
void audition_playlist_region_via_route (boost::shared_ptr<ARDOUR::Region>, ARDOUR::Route&); void audition_playlist_region_via_route (boost::shared_ptr<ARDOUR::Region>, ARDOUR::Route&);
void split_multichannel_region(); void split_multichannel_region();
void reverse_regions (); void reverse_region ();
void normalize_regions (); void normalize_region ();
void denormalize_regions (); void denormalize_region ();
void quantize_regions (); void quantize_region ();
void audition_region_from_region_list (); void audition_region_from_region_list ();
void hide_region_from_region_list (); void hide_region_from_region_list ();
@ -1176,7 +1190,7 @@ class Editor : public PublicEditor
void set_selection_from_range (ARDOUR::Location&); void set_selection_from_range (ARDOUR::Location&);
void set_selection_from_punch (); void set_selection_from_punch ();
void set_selection_from_loop (); void set_selection_from_loop ();
void set_selection_from_audio_region (); void set_selection_from_region ();
void add_location_mark (nframes64_t where); void add_location_mark (nframes64_t where);
void add_location_from_audio_region (); void add_location_from_audio_region ();
@ -1901,8 +1915,8 @@ class Editor : public PublicEditor
static void* _freeze_thread (void*); static void* _freeze_thread (void*);
void* freeze_thread (); void* freeze_thread ();
void freeze_routes (); void freeze_route ();
void unfreeze_routes (); void unfreeze_route ();
/* edit-group solo + mute */ /* edit-group solo + mute */
@ -1990,7 +2004,7 @@ class Editor : public PublicEditor
/* nudging tracks */ /* nudging tracks */
void nudge_selected_tracks (bool use_edit_cursor, bool forwards); void nudge_track (bool use_edit_point, bool forwards);
/* xfades */ /* xfades */
@ -2101,13 +2115,6 @@ class Editor : public PublicEditor
void toggle_gain_envelope_active (); void toggle_gain_envelope_active ();
void reset_region_gain_envelopes (); void reset_region_gain_envelopes ();
Gtk::CheckMenuItem* region_envelope_visible_item;
Gtk::CheckMenuItem* region_envelope_active_item;
Gtk::CheckMenuItem* region_mute_item;
Gtk::CheckMenuItem* region_lock_item;
Gtk::CheckMenuItem* region_lock_position_item;
Gtk::CheckMenuItem* region_opaque_item;
bool on_key_press_event (GdkEventKey*); bool on_key_press_event (GdkEventKey*);
bool on_key_release_event (GdkEventKey*); bool on_key_release_event (GdkEventKey*);

View file

@ -352,11 +352,11 @@ Editor::register_actions ()
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "insert-region", _("Insert Region"), mem_fun(*this, &Editor::keyboard_insert_region_list_selection)); act = ActionManager::register_action (editor_actions, "insert-region", _("Insert Region"), mem_fun(*this, &Editor::keyboard_insert_region_list_selection));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "reverse-region", _("Reverse Regions"), mem_fun(*this, &Editor::reverse_regions)); act = ActionManager::register_action (editor_actions, "reverse-region", _("Reverse Region"), mem_fun(*this, &Editor::reverse_region));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "normalize-region", _("Normalize Regions"), mem_fun(*this, &Editor::normalize_regions)); act = ActionManager::register_action (editor_actions, "normalize-region", _("Normalize Region"), mem_fun(*this, &Editor::normalize_region));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "quantize-region", _("Quantize Regions"), mem_fun(*this, &Editor::quantize_regions)); act = ActionManager::register_action (editor_actions, "quantize-region", _("Quantize Region"), mem_fun(*this, &Editor::quantize_region));
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));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);

View file

@ -335,51 +335,27 @@ Editor::track_canvas_size_allocated ()
reset_scrolling_region (); reset_scrolling_region ();
if (playhead_cursor) playhead_cursor->set_length (canvas_height); if (playhead_cursor) playhead_cursor->set_length (canvas_height);
double y1 = vertical_adjustment.get_value ();
for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) { for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
(*x)->set_line_length (full_canvas_height); (*x)->set_line_vpos (y1, canvas_height);
} }
if (range_marker_drag_rect) { range_marker_drag_rect->property_y1() = 0.0;
range_marker_drag_rect->property_y1() = 0.0; range_marker_drag_rect->property_y2() = canvas_height;
range_marker_drag_rect->property_y2() = canvas_height; transport_loop_range_rect->property_y1() = 0.0;
} transport_loop_range_rect->property_y2() = canvas_height;
transport_punch_range_rect->property_y1() = 0.0;
if (transport_loop_range_rect) { transport_punch_range_rect->property_y2() = canvas_height;
transport_loop_range_rect->property_y1() = 0.0; transport_punchin_line->property_y1() = 0.0;
transport_loop_range_rect->property_y2() = canvas_height; transport_punchin_line->property_y2() = canvas_height;
} transport_punchout_line->property_y1() = 0.0;
transport_punchout_line->property_y2() = canvas_height;
if (transport_punch_range_rect) {
transport_punch_range_rect->property_y1() = 0.0;
transport_punch_range_rect->property_y2() = canvas_height;
}
if (transport_punchin_line) {
transport_punchin_line->property_y1() = 0.0;
transport_punchin_line->property_y2() = canvas_height;
}
if (transport_punchout_line) {
transport_punchout_line->property_y1() = 0.0;
transport_punchout_line->property_y2() = canvas_height;
}
compute_fixed_ruler_scale ();
range_marker_drag_rect->property_y2() = full_canvas_height;
transport_loop_range_rect->property_y2() = full_canvas_height;
transport_punch_range_rect->property_y2() = full_canvas_height;
transport_punchin_line->property_y2() = full_canvas_height;
transport_punchout_line->property_y2() = full_canvas_height;
update_fixed_rulers(); update_fixed_rulers();
redisplay_tempo (true); redisplay_tempo (true);
if (logo_item) {
// logo_item->property_height() = full_canvas_height;
// logo_item->property_width() = canvas_width;
}
Resized (); /* EMIT_SIGNAL */ Resized (); /* EMIT_SIGNAL */
return false; return false;
@ -723,6 +699,38 @@ Editor::left_track_canvas (GdkEventCrossing *ev)
return FALSE; return FALSE;
} }
void
Editor::tie_vertical_scrolling ()
{
double y1 = vertical_adjustment.get_value();
playhead_cursor->set_y_axis (y1);
range_marker_drag_rect->property_y1() = y1;
range_marker_drag_rect->property_y2() = y1 + canvas_height;
transport_loop_range_rect->property_y1() = y1;
transport_loop_range_rect->property_y2() = y1 + canvas_height;
transport_punch_range_rect->property_y1() = y1;
transport_punch_range_rect->property_y2() = y1 + canvas_height;
transport_punchin_line->property_y1() = y1;
transport_punchin_line->property_y2() = y1 + canvas_height;
transport_punchout_line->property_y1() = y1;
transport_punchout_line->property_y2() = y1 + canvas_height;
if (!selection->markers.empty()) {
for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
(*x)->set_line_vpos (y1, canvas_height);
}
}
if (logo_item) {
logo_item->property_y() = y1;
}
/* this will do an immediate redraw */
controls_layout.get_vadjustment()->set_value (y1);
}
void void
Editor::canvas_horizontally_scrolled () Editor::canvas_horizontally_scrolled ()

View file

@ -1172,7 +1172,7 @@ Editor::marker_selection_changed ()
} }
for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) { for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
(*x)->add_line (cursor_group, full_canvas_height); (*x)->add_line (cursor_group, vertical_adjustment.get_value(), canvas_height);
(*x)->show_line (); (*x)->show_line ();
} }

View file

@ -967,24 +967,23 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case FadeOutHandleItem: case FadeOutHandleItem:
popup_fade_context_menu (1, event->button.time, item, item_type); popup_fade_context_menu (1, event->button.time, item, item_type);
break; break;
case StreamItem: case StreamItem:
popup_track_context_menu (1, event->button.time, where); popup_track_context_menu (1, event->button.time, item_type, false, where);
break; break;
case RegionItem: case RegionItem:
case RegionViewNameHighlight: case RegionViewNameHighlight:
case RegionViewName: case RegionViewName:
popup_track_context_menu (1, event->button.time, where); popup_track_context_menu (1, event->button.time, item_type, false, where);
break; break;
case SelectionItem: case SelectionItem:
popup_track_context_menu (1, event->button.time, where); popup_track_context_menu (1, event->button.time, item_type, true, where);
break; break;
case AutomationTrackItem: case AutomationTrackItem:
case CrossfadeViewItem: popup_track_context_menu (1, event->button.time, item_type, false, where);
popup_track_context_menu (1, event->button.time, where);
break; break;
case MarkerBarItem: case MarkerBarItem:
@ -1007,6 +1006,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MeterMarkerItem: case MeterMarkerItem:
tm_marker_context_menu (&event->button, item); tm_marker_context_menu (&event->button, item);
break; break;
case CrossfadeViewItem:
popup_track_context_menu (1, event->button.time, item_type, false, where);
break;
#ifdef WITH_CMT #ifdef WITH_CMT
case ImageFrameItem: case ImageFrameItem:
@ -3680,7 +3683,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
if (regionview_y_movement) { if (regionview_y_movement) {
/* moved to a different audio track. */ /* moved to a different track. */
vector<RegionView*> new_selection; vector<RegionView*> new_selection;
@ -3695,7 +3698,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(trackview_by_y_position (iy1)); RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(trackview_by_y_position (iy1));
boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
boost::shared_ptr<Playlist> to_playlist = rtv2->playlist(); boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
where = (nframes_t) (unit_to_frame (ix1) * speed);
boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
if (! to_playlist->frozen()) { if (! to_playlist->frozen()) {
/* /*
@ -3720,35 +3727,26 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
to_playlist->freeze(); to_playlist->freeze();
} }
where = (nframes_t) (unit_to_frame (ix1) * speed); /* undo the previous hide_dependent_views so that xfades don't
boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region())); disappear on copying regions
*/
rv->get_time_axis_view().reveal_dependent_views (*rv);
if (!drag_info.copy) { if (!drag_info.copy) {
/* the region that used to be in the old playlist is not /* the region that used to be in the old playlist is not
moved to the new one - we make a copy of it. as a result, moved to the new one - we make a copy of it. as a result,
any existing editor for the region should no longer be any existing editor for the region should no longer be
visible. visible.
*/ */
RouteTimeAxisView* from_playlist_rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_trackview());
boost::shared_ptr<Playlist> from_playlist = from_playlist_rtv->playlist();
if (! from_playlist->frozen()) {
from_playlist->freeze();
used_playlists.push_back(from_playlist);
sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
used_connections.push_back (c);
session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
}
rv->hide_region_editor(); rv->hide_region_editor();
rv->fake_set_opaque (false); rv->fake_set_opaque (false);
session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
from_playlist->remove_region ((rv->region())); from_playlist->remove_region ((rv->region()));
session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));
} else { } else {

View file

@ -2595,6 +2595,9 @@ Editor::separate_regions_between (const TimeSelection& ts)
sort_track_selection (&tmptracks); sort_track_selection (&tmptracks);
for (TrackSelection::iterator i = tmptracks.begin(); i != tmptracks.end(); ++i) { for (TrackSelection::iterator i = tmptracks.begin(); i != tmptracks.end(); ++i) {
RouteTimeAxisView* rtv; RouteTimeAxisView* rtv;
@ -3298,16 +3301,14 @@ Editor::trim_region_from_edit_point ()
commit_reversible_command (); commit_reversible_command ();
} }
/** Unfreeze selected routes */
void void
Editor::unfreeze_routes () Editor::unfreeze_route ()
{ {
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*i); return;
if (atv && atv->is_audio_track()) {
atv->audio_track()->unfreeze ();
}
} }
clicked_routeview->audio_track()->unfreeze ();
} }
void* void*
@ -3320,15 +3321,7 @@ Editor::_freeze_thread (void* arg)
void* void*
Editor::freeze_thread () Editor::freeze_thread ()
{ {
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { clicked_routeview->audio_track()->freeze (*current_interthread_info);
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*i);
if (atv && atv->is_audio_track()) {
atv->audio_track()->freeze (*current_interthread_info);
}
}
current_interthread_info->done = true;
return 0; return 0;
} }
@ -3339,10 +3332,13 @@ Editor::freeze_progress_timeout (void *arg)
return !(current_interthread_info->done || current_interthread_info->cancel); return !(current_interthread_info->done || current_interthread_info->cancel);
} }
/** Freeze selected routes */
void void
Editor::freeze_routes () Editor::freeze_route ()
{ {
if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
return;
}
InterThreadInfo itt; InterThreadInfo itt;
if (interthread_progress_window == 0) { if (interthread_progress_window == 0) {
@ -3991,7 +3987,7 @@ Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
} }
void void
Editor::nudge_selected_tracks (bool use_edit, bool forwards) Editor::nudge_track (bool use_edit, bool forwards)
{ {
boost::shared_ptr<Playlist> playlist; boost::shared_ptr<Playlist> playlist;
nframes_t distance; nframes_t distance;
@ -4058,7 +4054,7 @@ Editor::remove_last_capture ()
} }
void void
Editor::normalize_regions () Editor::normalize_region ()
{ {
if (!session) { if (!session) {
return; return;
@ -4088,7 +4084,7 @@ Editor::normalize_regions ()
void void
Editor::denormalize_regions () Editor::denormalize_region ()
{ {
if (!session) { if (!session) {
return; return;
@ -4114,7 +4110,7 @@ Editor::denormalize_regions ()
void void
Editor::reverse_regions () Editor::reverse_region ()
{ {
if (!session) { if (!session) {
return; return;
@ -4126,7 +4122,7 @@ Editor::reverse_regions ()
void void
Editor::quantize_regions () Editor::quantize_region ()
{ {
if (!session) { if (!session) {
return; return;
@ -4270,10 +4266,7 @@ Editor::toggle_gain_envelope_visibility ()
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) { if (arv) {
bool x = region_envelope_visible_item->get_active(); arv->set_envelope_visible (!arv->envelope_visible());
if (x != arv->envelope_visible()) {
arv->set_envelope_visible (x);
}
} }
} }
} }
@ -4284,28 +4277,7 @@ Editor::toggle_gain_envelope_active ()
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) { if (arv) {
bool x = region_envelope_active_item->get_active(); arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active());
if (x != arv->audio_region()->envelope_active()) {
arv->audio_region()->set_envelope_active (x);
}
}
}
}
/** Set the position-locked state of all selected regions to a particular value.
* @param yn true to make locked, false to make unlocked.
*/
void
Editor::toggle_region_position_lock ()
{
bool x = region_lock_position_item->get_active();
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
if (x != arv->audio_region()->locked()) {
arv->audio_region()->set_position_locked (x);
}
} }
} }
} }
@ -4313,45 +4285,24 @@ Editor::toggle_region_position_lock ()
void void
Editor::toggle_region_lock () Editor::toggle_region_lock ()
{ {
bool x = region_lock_item->get_active();
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); (*i)->region()->set_locked (!(*i)->region()->locked());
if (arv) {
if (x != arv->audio_region()->locked()) {
arv->audio_region()->set_locked (x);
}
}
} }
} }
void void
Editor::toggle_region_mute () Editor::toggle_region_mute ()
{ {
bool x = region_mute_item->get_active();
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); (*i)->region()->set_muted (!(*i)->region()->muted());
if (arv) {
if (x != arv->audio_region()->muted()) {
arv->audio_region()->set_muted (x);
}
}
} }
} }
void void
Editor::toggle_region_opaque () Editor::toggle_region_opaque ()
{ {
bool x = region_opaque_item->get_active();
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); (*i)->region()->set_opaque (!(*i)->region()->opaque());
if (arv) {
if (x != arv->audio_region()->opaque()) {
arv->audio_region()->set_opaque (x);
}
}
} }
} }

View file

@ -713,6 +713,37 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> regi
commit_reversible_command () ; commit_reversible_command () ;
} }
bool
Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
{
RegionView* rv;
boost::shared_ptr<Region> r (weak_r.lock());
if (!r) {
return true;
}
if ((rv = sv->find_view (r)) == 0) {
return true;
}
/* don't reset the selection if its something other than
a single other region.
*/
if (selection->regions.size() > 1) {
return true;
}
begin_reversible_command (_("set selected regions"));
selection->set (rv);
commit_reversible_command () ;
return true;
}
void void
Editor::track_selection_changed () Editor::track_selection_changed ()
{ {
@ -776,17 +807,16 @@ Editor::point_selection_changed ()
} }
} }
/** Select everything in the selected tracks
* @param Selection operation to apply.
*/
void void
Editor::select_all_in_selected_tracks (Selection::Operation op) Editor::select_all_in_track (Selection::Operation op)
{ {
list<Selectable *> touched; list<Selectable *> touched;
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { if (!clicked_routeview) {
(*i)->get_selectables (0, max_frames, 0, DBL_MAX, touched); return;
} }
clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
switch (op) { switch (op) {
case Selection::Toggle: case Selection::Toggle:
@ -832,17 +862,16 @@ Editor::select_all (Selection::Operation op)
} }
commit_reversible_command (); commit_reversible_command ();
} }
/** Invert the selection in the selected tracks */
void void
Editor::invert_selection_in_selected_tracks () Editor::invert_selection_in_track ()
{ {
list<Selectable *> touched; list<Selectable *> touched;
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { if (!clicked_routeview) {
(*i)->get_inverted_selectables (*selection, touched); return;
} }
clicked_routeview->get_inverted_selectables (*selection, touched);
selection->set (touched); selection->set (touched);
} }
@ -926,7 +955,7 @@ Editor::select_all_within (nframes_t start, nframes_t end, double top, double bo
} }
void void
Editor::set_selection_from_audio_region () Editor::set_selection_from_region ()
{ {
if (selection->regions.empty()) { if (selection->regions.empty()) {
return; return;

View file

@ -4,6 +4,7 @@
#include <map> #include <map>
#include <glibmm.h> #include <glibmm.h>
#include <gtkmm/messagedialog.h>
#include <pbd/xml++.h> #include <pbd/xml++.h>
#ifdef __APPLE__ #ifdef __APPLE__
@ -427,11 +428,11 @@ EngineControl::build_command_line (vector<string>& cmd)
cmd.push_back ("netjack"); cmd.push_back ("netjack");
} else if (driver == X_("FFADO")) { } else if (driver == X_("FFADO")) {
using_ffado = true; using_ffado = true;
cmd.push_back ("firewire"); cmd.push_back ("ffado");
} else if ( driver == X_("Dummy")) { } else if ( driver == X_("Dummy")) {
using_dummy = true; using_dummy = true;
cmd.push_back ("dummy"); cmd.push_back ("dummy");
} }
/* driver arguments */ /* driver arguments */
@ -621,10 +622,29 @@ EngineControl::enumerate_coreaudio_devices ()
// Look for the CoreAudio device name... // Look for the CoreAudio device name...
char coreDeviceName[256]; char coreDeviceName[256];
size_t nameSize; size_t nameSize;
for (int i = 0; i < numCoreDevices; i++) { for (int i = 0; i < numCoreDevices; i++) {
nameSize = sizeof (coreDeviceName); nameSize = sizeof (coreDeviceName);
/* enforce duplex devices only */
err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
0, true, kAudioDevicePropertyStreams,
&outSize, &isWritable);
if (err != noErr || outSize == 0) {
continue;
}
err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
0, false, kAudioDevicePropertyStreams,
&outSize, &isWritable);
if (err != noErr || outSize == 0) {
continue;
}
err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
0, true, kAudioDevicePropertyDeviceName, 0, true, kAudioDevicePropertyDeviceName,
&outSize, &isWritable); &outSize, &isWritable);
@ -649,6 +669,26 @@ EngineControl::enumerate_coreaudio_devices ()
delete [] coreDeviceIDs; delete [] coreDeviceIDs;
} }
if (devs.size() == 0) {
MessageDialog msg (_("\
You do not have any audio devices capable of\n\
simultaneous playback and recording.\n\n\
Please use Applications -> Utilities -> Audio MIDI Setup\n\
to create an \"aggregrate\" device, or install a suitable\n\
audio interface.\n\n\
Please send email to Apple and ask them why new Macs\n\
have no duplex audio device.\n\n\
Alternatively, if you really want just playback\n\
or recording but not both, start JACK before running\n\
Ardour and choose the relevant device then."
),
true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
msg.set_title (_("No suitable audio devices"));
msg.set_position (Gtk::WIN_POS_MOUSE);
msg.run ();
exit (1);
}
return devs; return devs;
} }
#else #else
@ -869,7 +909,7 @@ EngineControl::find_jack_servers (vector<string>& strings)
std::map<string,int> un; std::map<string,int> un;
path = getenv ("PATH"); path = getenv ("PATH");
jack_servers = scanner (path, jack_server_filter, 0, false, true); jack_servers = scanner (path, jack_server_filter, 0, false, true);
vector<string *>::iterator iter; vector<string *>::iterator iter;

View file

@ -25,6 +25,7 @@
#include "utils.h" #include "utils.h"
#include "canvas_impl.h" #include "canvas_impl.h"
#include "ardour_ui.h" #include "ardour_ui.h"
#include "simpleline.h"
#include "i18n.h" #include "i18n.h"
@ -269,7 +270,6 @@ Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, con
} }
line = 0; line = 0;
line_points = 0;
} }
@ -285,7 +285,6 @@ Marker::~Marker ()
if (line) { if (line) {
delete line; delete line;
delete line_points;
} }
} }
@ -295,35 +294,28 @@ void Marker::reparent(ArdourCanvas::Group & parent)
_parent = &parent; _parent = &parent;
} }
void void
Marker::set_line_length (double len) Marker::set_line_vpos (double pos, double height)
{ {
if (line) { if (line) {
line_points->back().set_y (len); line->property_y1() = pos;
line->property_points() = *line_points; line->property_y2() = pos + height;
} }
} }
void void
Marker::add_line (ArdourCanvas::Group* group, double initial_height) Marker::add_line (ArdourCanvas::Group* group, double y_origin, double initial_height)
{ {
if (!line) { if (!line) {
line_points = new ArdourCanvas::Points (); line = new ArdourCanvas::SimpleLine (*group);
line_points->push_back (Gnome::Art::Point (unit_position + shift, 0.0)); line->property_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
line_points->push_back (Gnome::Art::Point (unit_position + shift, initial_height)); line->property_x1() = unit_position + shift;
line->property_y1() = y_origin;
line = new ArdourCanvas::Line (*group); line->property_x2() = unit_position + shift;
line->property_width_pixels() = 1; line->property_y2() = y_origin + initial_height;
line->property_points() = *line_points;
line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
#if 0
line->property_first_arrowhead() = TRUE;
line->property_last_arrowhead() = TRUE;
line->property_arrow_shape_a() = 11.0;
line->property_arrow_shape_b() = 0.0;
line->property_arrow_shape_c() = 9.0;
#endif
line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this)); line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
} }
@ -372,9 +364,8 @@ Marker::set_position (nframes_t frame)
unit_position = new_unit_position; unit_position = new_unit_position;
if (line) { if (line) {
(*line_points)[0].set_x (unit_position + shift); line->property_x1() = unit_position + shift;
(*line_points)[1].set_x (unit_position + shift); line->property_x2() = unit_position + shift;
line->property_points() = *line_points;
} }
} }

View file

@ -57,10 +57,10 @@ class Marker : public PBD::Destructible
ArdourCanvas::Item& the_item() const; ArdourCanvas::Item& the_item() const;
void add_line (ArdourCanvas::Group*, double initial_height); void add_line (ArdourCanvas::Group*, double y_origin, double initial_height);
void show_line (); void show_line ();
void hide_line (); void hide_line ();
void set_line_length (double); void set_line_vpos (double y_origin, double height);
void set_position (nframes_t); void set_position (nframes_t);
void set_name (const string&); void set_name (const string&);
@ -84,7 +84,7 @@ class Marker : public PBD::Destructible
ArdourCanvas::Polygon *mark; ArdourCanvas::Polygon *mark;
ArdourCanvas::Text *text; ArdourCanvas::Text *text;
ArdourCanvas::Points *points; ArdourCanvas::Points *points;
ArdourCanvas::Line *line; ArdourCanvas::SimpleLine *line;
ArdourCanvas::Points *line_points; ArdourCanvas::Points *line_points;
double unit_position; double unit_position;

View file

@ -311,6 +311,8 @@ Mixer_UI::add_strip (Session::RouteList& routes)
Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide; Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide;
Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide;
if (strip->width_owner() != strip) { if (strip->width_owner() != strip) {
strip->set_width (_strip_width, this); strip->set_width (_strip_width, this);
} }

View file

@ -20,6 +20,8 @@
#include "i18n.h" #include "i18n.h"
#include "new_session_dialog.h" #include "new_session_dialog.h"
#include <pbd/error.h>
#include <ardour/recent_sessions.h> #include <ardour/recent_sessions.h>
#include <ardour/session_state_utils.h> #include <ardour/session_state_utils.h>
#include <ardour/template_utils.h> #include <ardour/template_utils.h>
@ -38,8 +40,8 @@
#include <gtkmm2ext/window_title.h> #include <gtkmm2ext/window_title.h>
using namespace Gtkmm2ext; using namespace Gtkmm2ext;
using namespace ARDOUR;
using namespace PBD; using namespace PBD;
using namespace ARDOUR;
#include "opts.h" #include "opts.h"
#include "utils.h" #include "utils.h"
@ -526,7 +528,49 @@ NewSessionDialog::set_session_name (const Glib::ustring& name)
void void
NewSessionDialog::set_session_folder(const Glib::ustring& dir) NewSessionDialog::set_session_folder(const Glib::ustring& dir)
{ {
m_folder->set_current_folder (dir); Glib::ustring realdir = dir;
char* res;
/* this little tangled mess is a result of 4 things:
1) GtkFileChooser vomits when given a non-absolute directory
argument to set_current_folder()
2) canonicalize_file_name() doesn't exist on OS X
3) linux man page for realpath() says "do not use this function"
4) canonicalize_file_name() & realpath() have entirely
different semantics on OS X and Linux when given
a non-existent path.
as result of all this, we take two distinct pathways through the code.
*/
#ifdef __APPLE__
char buf[PATH_MAX];
if((res = realpath (dir.c_str(), buf)) != 0) {
if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
realdir = Glib::path_get_dirname (realdir);
}
m_folder->set_current_folder (realdir);
}
#else
if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
realdir = Glib::path_get_dirname (realdir);
cerr << "didn't exist, use " << realdir << endl;
}
if ((res = canonicalize_file_name (realdir.c_str())) != 0) {
cerr << "canonical, use " << res << endl;
m_folder->set_current_folder (res);
free (res);
}
#endif
} }
std::string std::string
@ -547,40 +591,54 @@ NewSessionDialog::session_name() const
} }
*/ */
int page = m_notebook->get_current_page(); switch (which_page()) {
case NewPage:
if (page == 0 || page == 2) { case EnginePage:
/* new or audio setup pages */ /* new or audio setup pages */
return Glib::filename_from_utf8(m_name->get_text()); return Glib::filename_from_utf8(m_name->get_text());
} else { default:
if (m_treeview->get_selection()->count_selected_rows() == 0) { break;
return Glib::filename_from_utf8(str); }
}
Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected(); if (m_treeview->get_selection()->count_selected_rows() == 0) {
return (*i)[recent_columns.visible_name]; return Glib::filename_from_utf8(str);
} }
Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected();
return (*i)[recent_columns.visible_name];
} }
std::string std::string
NewSessionDialog::session_folder() const NewSessionDialog::session_folder() const
{ {
if (m_notebook->get_current_page() == 0) { switch (which_page()) {
case NewPage:
return Glib::filename_from_utf8(m_folder->get_filename()); return Glib::filename_from_utf8(m_folder->get_filename());
} else {
case EnginePage:
if (m_treeview->get_selection()->count_selected_rows() == 0) { if (page_set == EnginePage) {
const string filename(Glib::filename_from_utf8(m_open_filechooser->get_filename())); /* just engine page, nothing else : use m_folder since it should be set */
return Glib::path_get_dirname(filename); return Glib::filename_from_utf8(m_folder->get_filename());
} }
Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected(); break;
return (*i)[recent_columns.fullpath];
default:
break;
} }
if (m_treeview->get_selection()->count_selected_rows() == 0) {
const string filename(Glib::filename_from_utf8(m_open_filechooser->get_filename()));
return Glib::path_get_dirname(filename);
}
Gtk::TreeModel::iterator i = m_treeview->get_selection()->get_selected();
return (*i)[recent_columns.fullpath];
} }
bool bool
NewSessionDialog::use_session_template() const NewSessionDialog::use_session_template() const
{ {
if(m_template->get_filename().empty() && (m_notebook->get_current_page() == 0)) return false; if (m_template->get_filename().empty() && (which_page() == NewPage))
return false;
return true; return true;
} }
@ -663,13 +721,13 @@ NewSessionDialog::connect_outs_to_physical() const
} }
int int
NewSessionDialog::get_current_page() const NewSessionDialog::get_current_page()
{ {
return m_notebook->get_current_page(); return m_notebook->get_current_page();
} }
NewSessionDialog::Pages NewSessionDialog::Pages
NewSessionDialog::which_page () NewSessionDialog::which_page () const
{ {
int num = m_notebook->get_current_page(); int num = m_notebook->get_current_page();
@ -755,7 +813,6 @@ NewSessionDialog::notebook_page_changed (GtkNotebookPage* np, uint pagenum)
m_okbutton->set_label(_("Open")); m_okbutton->set_label(_("Open"));
m_okbutton->set_image (*(manage (new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON)))); m_okbutton->set_image (*(manage (new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON))));
set_response_sensitive (Gtk::RESPONSE_NONE, false); set_response_sensitive (Gtk::RESPONSE_NONE, false);
m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON)));
if (m_treeview->get_selection()->count_selected_rows() == 0) { if (m_treeview->get_selection()->count_selected_rows() == 0) {
set_response_sensitive (Gtk::RESPONSE_OK, false); set_response_sensitive (Gtk::RESPONSE_OK, false);
} else { } else {
@ -772,8 +829,7 @@ NewSessionDialog::notebook_page_changed (GtkNotebookPage* np, uint pagenum)
break; break;
default: default:
m_okbutton->set_label(_("New")); on_new_session_page = true;
m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
m_okbutton->set_label(_("New")); m_okbutton->set_label(_("New"));
m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON))); m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
if (m_name->get_text() == "") { if (m_name->get_text() == "") {
@ -893,7 +949,7 @@ NewSessionDialog::monitor_bus_button_clicked ()
void void
NewSessionDialog::reset_template() NewSessionDialog::reset_template()
{ {
m_template->set_filename(""); m_template->unselect_all ();
} }
void void

View file

@ -92,9 +92,9 @@ public:
bool connect_outs_to_master() const; bool connect_outs_to_master() const;
bool connect_outs_to_physical() const ; bool connect_outs_to_physical() const ;
Pages which_page (); Pages which_page () const;
int get_current_page() const; int get_current_page();
void set_current_page (int); void set_current_page (int);
void reset_recent(); void reset_recent();

View file

@ -6854,7 +6854,7 @@ msgstr "som nya bandspår"
#: gtk2_ardour/sfdb_ui.cc:109 #: gtk2_ardour/sfdb_ui.cc:109
msgid "Auto-play" msgid "Auto-play"
msgstr "Spela automatiskt" msgstr "Spela autom."
#: gtk2_ardour/sfdb_ui.cc:994 gtk2_ardour/sfdb_ui.cc:1129 #: gtk2_ardour/sfdb_ui.cc:994 gtk2_ardour/sfdb_ui.cc:1129
msgid "use file timestamp" msgid "use file timestamp"
@ -7062,3 +7062,39 @@ msgstr "Bra"
#: gtk2_ardour/sfdb_ui.cc:1069 gtk2_ardour/sfdb_ui.cc:1149 #: gtk2_ardour/sfdb_ui.cc:1069 gtk2_ardour/sfdb_ui.cc:1149
msgid "Quick" msgid "Quick"
msgstr "Snabb" msgstr "Snabb"
#: gtk2_ardour/editor_timefx.cc:74
msgid "Strict Linear"
msgstr "Strikt linjär"
#: gtk2_ardour/editor_timefx.cc:84
msgid "Time Stretch"
msgstr "Förläng/förkorta"
#: gtk2_ardour/editor.cc:156
msgid "Mushy"
msgstr "Mossig"
#: gtk2_ardour/editor.cc:157
msgid "Smooth"
msgstr "Mjuk"
#: gtk2_ardour/editor.cc:158
msgid "Balanced multitimbral mixture"
msgstr "Balanserad flerröstig mix"
#: gtk2_ardour/editor.cc:159
msgid "Unpitched percussion with stable notes"
msgstr "Ej tonhöjdsändrat slagverk med stabila noter"
#: gtk2_ardour/editor.cc:160
msgid "Crisp monophonic instrumental"
msgstr "Skarpt monofoniskt"
#: gtk2_ardour/editor.cc:161
msgid "Unpitched solo percussion"
msgstr "EJ tonhöjdsändrat soloslagverk"
#: gtk2_ardour/editor_timefx.cc:73
msgid "Contents:"
msgstr "Innehåll"

View file

@ -70,8 +70,6 @@ class AUPlugin : public ARDOUR::Plugin
int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset); int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
std::set<uint32_t> automatable() const; std::set<uint32_t> automatable() const;
void store_state (ARDOUR::PluginState&);
void restore_state (ARDOUR::PluginState&);
string describe_parameter (uint32_t); string describe_parameter (uint32_t);
string state_node_name () const { return "audiounit"; } string state_node_name () const { return "audiounit"; }
void print_parameter (uint32_t, char*, uint32_t len) const; void print_parameter (uint32_t, char*, uint32_t len) const;

View file

@ -32,7 +32,6 @@
#include <jack/types.h> #include <jack/types.h>
#include <ardour/ladspa.h> #include <ardour/ladspa.h>
#include <ardour/plugin_state.h>
#include <ardour/plugin.h> #include <ardour/plugin.h>
#include <ardour/ladspa_plugin.h> #include <ardour/ladspa_plugin.h>
@ -54,53 +53,47 @@ class LadspaPlugin : public ARDOUR::Plugin
/* Plugin interface */ /* Plugin interface */
std::string unique_id() const; std::string unique_id() const;
const char * label() const { return descriptor->Label; } const char* label() const { return _descriptor->Label; }
const char * name() const { return descriptor->Name; } const char* name() const { return _descriptor->Name; }
const char * maker() const { return descriptor->Maker; } const char* maker() const { return _descriptor->Maker; }
uint32_t parameter_count() const { return descriptor->PortCount; } uint32_t parameter_count() const { return _descriptor->PortCount; }
float default_value (uint32_t port); float default_value (uint32_t port);
nframes_t signal_latency() const; nframes_t signal_latency() const;
void set_parameter (uint32_t port, float val); void set_parameter (uint32_t port, float val);
float get_parameter (uint32_t port) const; float get_parameter (uint32_t port) const;
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const; int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;
std::set<Parameter> automatable() const; std::set<Parameter> automatable() const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;
void activate () { void activate () {
if (was_activated) if (!_was_activated && _descriptor->activate)
return; _descriptor->activate (_handle);
if (descriptor->activate) { _was_activated = true;
descriptor->activate (handle);
}
was_activated = true;
} }
void deactivate () { void deactivate () {
if (!was_activated) if (_was_activated && _descriptor->deactivate)
return; _descriptor->deactivate (_handle);
if (descriptor->deactivate) { _was_activated = false;
descriptor->deactivate (handle);
}
was_activated = false;
} }
void cleanup () { void cleanup () {
activate(); activate();
deactivate(); deactivate();
if (descriptor->cleanup) { if (_descriptor->cleanup)
descriptor->cleanup (handle); _descriptor->cleanup (_handle);
}
} }
void set_block_size (nframes_t nframes) {} void set_block_size (nframes_t nframes) {}
int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset); int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
void store_state (ARDOUR::PluginState&);
void restore_state (ARDOUR::PluginState&);
string describe_parameter (Parameter); string describe_parameter (Parameter);
string state_node_name() const { return "ladspa"; } string state_node_name() const { return "ladspa"; }
void print_parameter (uint32_t, char*, uint32_t len) const; void print_parameter (uint32_t, char*, uint32_t len) const;
bool parameter_is_audio(uint32_t) const; bool parameter_is_audio(uint32_t) const;
bool parameter_is_control(uint32_t) const; bool parameter_is_control(uint32_t) const;
@ -109,8 +102,8 @@ class LadspaPlugin : public ARDOUR::Plugin
bool parameter_is_toggled(uint32_t) const; bool parameter_is_toggled(uint32_t) const;
XMLNode& get_state(); XMLNode& get_state();
int set_state(const XMLNode& node); int set_state(const XMLNode& node);
bool save_preset(string name); bool save_preset(string name);
bool has_editor() const { return false; } bool has_editor() const { return false; }
@ -118,32 +111,27 @@ class LadspaPlugin : public ARDOUR::Plugin
/* LADSPA extras */ /* LADSPA extras */
LADSPA_Properties properties() const { return descriptor->Properties; } LADSPA_Properties properties() const { return _descriptor->Properties; }
uint32_t index() const { return _index; } uint32_t index() const { return _index; }
const char * copyright() const { return descriptor->Copyright; } const char * copyright() const { return _descriptor->Copyright; }
LADSPA_PortDescriptor port_descriptor(uint32_t i) const { return descriptor->PortDescriptors[i]; } LADSPA_PortDescriptor port_descriptor(uint32_t i) const { return _descriptor->PortDescriptors[i]; }
const LADSPA_PortRangeHint * port_range_hints() const { return descriptor->PortRangeHints; } const LADSPA_PortRangeHint* port_range_hints() const { return _descriptor->PortRangeHints; }
const char * const * port_names() const { return descriptor->PortNames; } const char * const * port_names() const { return _descriptor->PortNames; }
void set_gain (float gain) {
descriptor->set_run_adding_gain (handle, gain); void set_gain (float gain) { _descriptor->set_run_adding_gain (_handle, gain); }
} void run_adding (uint32_t nsamples) { _descriptor->run_adding (_handle, nsamples); }
void run_adding (uint32_t nsamples) { void connect_port (uint32_t port, float *ptr) { _descriptor->connect_port (_handle, port, ptr); }
descriptor->run_adding (handle, nsamples);
}
void connect_port (uint32_t port, float *ptr) {
descriptor->connect_port (handle, port, ptr);
}
private: private:
void *module; void* _module;
const LADSPA_Descriptor *descriptor; const LADSPA_Descriptor* _descriptor;
LADSPA_Handle handle; LADSPA_Handle _handle;
nframes_t sample_rate; nframes_t _sample_rate;
LADSPA_Data *control_data; LADSPA_Data* _control_data;
LADSPA_Data *shadow_data; LADSPA_Data* _shadow_data;
LADSPA_Data *latency_control_port; LADSPA_Data* _latency_control_port;
uint32_t _index; uint32_t _index;
bool was_activated; bool _was_activated;
void init (void *mod, uint32_t index, nframes_t rate); void init (void *mod, uint32_t index, nframes_t rate);
void run_in_place (nframes_t nsamples); void run_in_place (nframes_t nsamples);

View file

@ -30,7 +30,6 @@
#include <jack/types.h> #include <jack/types.h>
#include <ardour/types.h> #include <ardour/types.h>
#include <ardour/chan_count.h> #include <ardour/chan_count.h>
#include <ardour/plugin_state.h>
#include <ardour/cycles.h> #include <ardour/cycles.h>
#include <ardour/latent.h> #include <ardour/latent.h>
#include <ardour/parameter.h> #include <ardour/parameter.h>
@ -131,8 +130,6 @@ class Plugin : public PBD::StatefulDestructible, public Latent
virtual int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset) = 0; virtual int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset) = 0;
virtual std::set<Parameter> automatable() const = 0; virtual std::set<Parameter> automatable() const = 0;
virtual void store_state (ARDOUR::PluginState&) = 0;
virtual void restore_state (ARDOUR::PluginState&) = 0;
virtual string describe_parameter (Parameter) = 0; virtual string describe_parameter (Parameter) = 0;
virtual string state_node_name() const = 0; virtual string state_node_name() const = 0;
virtual void print_parameter (uint32_t, char*, uint32_t len) const = 0; virtual void print_parameter (uint32_t, char*, uint32_t len) const = 0;

View file

@ -25,7 +25,6 @@
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
#include <ardour/plugin_state.h>
#include <ardour/types.h> #include <ardour/types.h>
#include <ardour/processor.h> #include <ardour/processor.h>
#include <ardour/automation_event.h> #include <ardour/automation_event.h>

View file

@ -1,14 +0,0 @@
#ifndef __ardour_plugin_state_h__
#define __ardour_plugin_state_h__
#include <map>
namespace ARDOUR {
struct PluginState {
std::map<uint32_t,float> parameters;
};
}
#endif /* __ardour_plugin_state_h__ */

View file

@ -27,7 +27,6 @@
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
#include <ardour/io_processor.h> #include <ardour/io_processor.h>
#include <ardour/plugin_state.h>
#include <ardour/types.h> #include <ardour/types.h>
class XMLNode; class XMLNode;

View file

@ -30,7 +30,6 @@
#include <ardour/types.h> #include <ardour/types.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
#include <ardour/plugin_state.h>
#include <ardour/buffer_set.h> #include <ardour/buffer_set.h>
#include <ardour/automatable.h> #include <ardour/automatable.h>
#include <ardour/latent.h> #include <ardour/latent.h>

View file

@ -20,7 +20,7 @@
#ifndef __ardour_rbeffect_h__ #ifndef __ardour_rbeffect_h__
#define __ardour_rbeffect_h__ #define __ardour_rbeffect_h__
#include <ardour/audiofilter.h> #include <ardour/filter.h>
namespace ARDOUR { namespace ARDOUR {

View file

@ -72,8 +72,6 @@ class VSTPlugin : public ARDOUR::Plugin
void deactivate (); void deactivate ();
void set_block_size (nframes_t nframes); void set_block_size (nframes_t nframes);
int connect_and_run (BufferSet&, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset); int connect_and_run (BufferSet&, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
void store_state (ARDOUR::PluginState&);
void restore_state (ARDOUR::PluginState&);
string describe_parameter (uint32_t); string describe_parameter (uint32_t);
string state_node_name() const { return "vst"; } string state_node_name() const { return "vst"; }
void print_parameter (uint32_t, char*, uint32_t len) const; void print_parameter (uint32_t, char*, uint32_t len) const;

View file

@ -401,18 +401,6 @@ AUPlugin::automatable() const
return automates; return automates;
} }
void
AUPlugin::store_state (ARDOUR::PluginState&)
{
}
void
AUPlugin::restore_state (ARDOUR::PluginState&)
{
}
string string
AUPlugin::describe_parameter (uint32_t) AUPlugin::describe_parameter (uint32_t)
{ {

View file

@ -636,7 +636,7 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
set_fade_out_active (false); set_fade_out_active (false);
} }
} }
} }
} }

View file

@ -62,11 +62,11 @@ LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_
LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) LadspaPlugin::LadspaPlugin (const LadspaPlugin &other)
: Plugin (other) : Plugin (other)
{ {
init (other.module, other._index, other.sample_rate); init (other._module, other._index, other._sample_rate);
for (uint32_t i = 0; i < parameter_count(); ++i) { for (uint32_t i = 0; i < parameter_count(); ++i) {
control_data[i] = other.shadow_data[i]; _control_data[i] = other._shadow_data[i];
shadow_data[i] = other.shadow_data[i]; _shadow_data[i] = other._shadow_data[i];
} }
} }
@ -77,61 +77,61 @@ LadspaPlugin::init (void *mod, uint32_t index, nframes_t rate)
uint32_t i, port_cnt; uint32_t i, port_cnt;
const char *errstr; const char *errstr;
module = mod; _module = mod;
control_data = 0; _control_data = 0;
shadow_data = 0; _shadow_data = 0;
latency_control_port = 0; _latency_control_port = 0;
was_activated = false; _was_activated = false;
dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor"); dfunc = (LADSPA_Descriptor_Function) dlsym (_module, "ladspa_descriptor");
if ((errstr = dlerror()) != NULL) { if ((errstr = dlerror()) != NULL) {
error << _("LADSPA: module has no descriptor function.") << endmsg; error << _("LADSPA: module has no descriptor function.") << endmsg;
throw failed_constructor(); throw failed_constructor();
} }
if ((descriptor = dfunc (index)) == 0) { if ((_descriptor = dfunc (index)) == 0) {
error << _("LADSPA: plugin has gone away since discovery!") << endmsg; error << _("LADSPA: plugin has gone away since discovery!") << endmsg;
throw failed_constructor(); throw failed_constructor();
} }
_index = index; _index = index;
if (LADSPA_IS_INPLACE_BROKEN(descriptor->Properties)) { if (LADSPA_IS_INPLACE_BROKEN(_descriptor->Properties)) {
error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), descriptor->Name) << endmsg; error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), _descriptor->Name) << endmsg;
throw failed_constructor(); throw failed_constructor();
} }
sample_rate = rate; _sample_rate = rate;
if (descriptor->instantiate == 0) { if (_descriptor->instantiate == 0) {
throw failed_constructor(); throw failed_constructor();
} }
if ((handle = descriptor->instantiate (descriptor, rate)) == 0) { if ((_handle = _descriptor->instantiate (_descriptor, rate)) == 0) {
throw failed_constructor(); throw failed_constructor();
} }
port_cnt = parameter_count(); port_cnt = parameter_count();
control_data = new LADSPA_Data[port_cnt]; _control_data = new LADSPA_Data[port_cnt];
shadow_data = new LADSPA_Data[port_cnt]; _shadow_data = new LADSPA_Data[port_cnt];
for (i = 0; i < port_cnt; ++i) { for (i = 0; i < port_cnt; ++i) {
if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) { if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
connect_port (i, &control_data[i]); connect_port (i, &_control_data[i]);
if (LADSPA_IS_PORT_OUTPUT(port_descriptor (i)) && if (LADSPA_IS_PORT_OUTPUT(port_descriptor (i)) &&
strcmp (port_names()[i], X_("latency")) == 0) { strcmp (port_names()[i], X_("latency")) == 0) {
latency_control_port = &control_data[i]; _latency_control_port = &_control_data[i];
*latency_control_port = 0; *_latency_control_port = 0;
} }
if (!LADSPA_IS_PORT_INPUT(port_descriptor (i))) { if (!LADSPA_IS_PORT_INPUT(port_descriptor (i))) {
continue; continue;
} }
shadow_data[i] = default_value (i); _shadow_data[i] = default_value (i);
} }
} }
@ -149,39 +149,12 @@ LadspaPlugin::~LadspaPlugin ()
// dlclose (module); // dlclose (module);
if (control_data) { if (_control_data) {
delete [] control_data; delete [] _control_data;
} }
if (shadow_data) { if (_shadow_data) {
delete [] shadow_data; delete [] _shadow_data;
}
}
void
LadspaPlugin::store_state (PluginState& state)
{
state.parameters.clear ();
for (uint32_t i = 0; i < parameter_count(); ++i){
if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
pair<uint32_t,float> datum;
datum.first = i;
datum.second = shadow_data[i];
state.parameters.insert (datum);
}
}
}
void
LadspaPlugin::restore_state (PluginState& state)
{
for (map<uint32_t,float>::iterator i = state.parameters.begin(); i != state.parameters.end(); ++i) {
set_parameter (i->first, i->second);
} }
} }
@ -189,7 +162,7 @@ string
LadspaPlugin::unique_id() const LadspaPlugin::unique_id() const
{ {
char buf[32]; char buf[32];
snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID); snprintf (buf, sizeof (buf), "%lu", _descriptor->UniqueID);
return string (buf); return string (buf);
} }
@ -308,10 +281,10 @@ LadspaPlugin::default_value (uint32_t port)
if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) { if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) {
if (bounds_given) { if (bounds_given) {
if (sr_scaling) { if (sr_scaling) {
ret *= sample_rate; ret *= _sample_rate;
} }
} else { } else {
ret = sample_rate; ret = _sample_rate;
} }
} }
@ -321,8 +294,8 @@ LadspaPlugin::default_value (uint32_t port)
void void
LadspaPlugin::set_parameter (uint32_t which, float val) LadspaPlugin::set_parameter (uint32_t which, float val)
{ {
if (which < descriptor->PortCount) { if (which < _descriptor->PortCount) {
shadow_data[which] = (LADSPA_Data) val; _shadow_data[which] = (LADSPA_Data) val;
#if 0 #if 0
ParameterChanged (Parameter(PluginAutomation, which), val); /* EMIT SIGNAL */ ParameterChanged (Parameter(PluginAutomation, which), val); /* EMIT SIGNAL */
@ -343,9 +316,9 @@ float
LadspaPlugin::get_parameter (uint32_t which) const LadspaPlugin::get_parameter (uint32_t which) const
{ {
if (LADSPA_IS_PORT_INPUT(port_descriptor (which))) { if (LADSPA_IS_PORT_INPUT(port_descriptor (which))) {
return (float) shadow_data[which]; return (float) _shadow_data[which];
} else { } else {
return (float) control_data[which]; return (float) _control_data[which];
} }
} }
@ -356,7 +329,7 @@ LadspaPlugin::nth_parameter (uint32_t n, bool& ok) const
ok = false; ok = false;
for (c = 0, x = 0; x < descriptor->PortCount; ++x) { for (c = 0, x = 0; x < _descriptor->PortCount; ++x) {
if (LADSPA_IS_PORT_CONTROL (port_descriptor (x))) { if (LADSPA_IS_PORT_CONTROL (port_descriptor (x))) {
if (c++ == n) { if (c++ == n) {
ok = true; ok = true;
@ -383,7 +356,7 @@ LadspaPlugin::get_state()
child = new XMLNode("port"); child = new XMLNode("port");
snprintf(buf, sizeof(buf), "%u", i); snprintf(buf, sizeof(buf), "%u", i);
child->add_property("number", string(buf)); child->add_property("number", string(buf));
snprintf(buf, sizeof(buf), "%+f", shadow_data[i]); snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
child->add_property("value", string(buf)); child->add_property("value", string(buf));
root->add_child_nocopy (*child); root->add_child_nocopy (*child);
} }
@ -515,8 +488,8 @@ LadspaPlugin::signal_latency () const
return _user_latency; return _user_latency;
} }
if (latency_control_port) { if (_latency_control_port) {
return (nframes_t) floor (*latency_control_port); return (nframes_t) floor (*_latency_control_port);
} else { } else {
return 0; return 0;
} }
@ -617,16 +590,16 @@ LadspaPlugin::run_in_place (nframes_t nframes)
{ {
for (uint32_t i = 0; i < parameter_count(); ++i) { for (uint32_t i = 0; i < parameter_count(); ++i) {
if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) { if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
control_data[i] = shadow_data[i]; _control_data[i] = _shadow_data[i];
} }
} }
descriptor->run (handle, nframes); _descriptor->run (_handle, nframes);
} }
void void
LadspaPlugin::latency_compute_run () LadspaPlugin::latency_compute_run ()
{ {
if (!latency_control_port) { if (!_latency_control_port) {
return; return;
} }

View file

@ -328,7 +328,7 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
} }
pattern.subject = matches1->object; pattern.subject = matches1->object;
pattern.predicate = (char*)LADSPA_BASE "hasLabel"; pattern.predicate = (char*)(LADSPA_BASE "hasLabel");
pattern.object = 0; pattern.object = 0;
pattern.object_type = lrdf_literal; pattern.object_type = lrdf_literal;

View file

@ -273,7 +273,6 @@ Session::Session (AudioEngine &eng,
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed)); Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
} }
@ -711,7 +710,7 @@ Session::when_engine_running ()
osc->set_session (*this); osc->set_session (*this);
#endif #endif
} }
void void

View file

@ -716,7 +716,7 @@ Session::save_state (string snapshot_name, bool pending)
bool was_dirty = dirty(); bool was_dirty = dirty();
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
if (was_dirty) { if (was_dirty) {
DirtyChanged (); /* EMIT SIGNAL */ DirtyChanged (); /* EMIT SIGNAL */
} }
@ -1270,8 +1270,8 @@ Session::set_state (const XMLNode& node)
} }
if ((child = find_named_node (node, "Bundles")) == 0) { if ((child = find_named_node (node, "Bundles")) == 0) {
error << _("Session: XML state has no bundles section") << endmsg; warning << _("Session: XML state has no bundles section (2.0 session?)") << endmsg;
goto out; //goto out;
} else { } else {
/* We can't load Bundles yet as they need to be able /* We can't load Bundles yet as they need to be able
to convert from port names to Port objects, which can't happen until to convert from port names to Port objects, which can't happen until

View file

@ -510,15 +510,3 @@ VSTPluginInfo::load (Session& session)
return PluginPtr ((Plugin*) 0); return PluginPtr ((Plugin*) 0);
} }
} }
void
VSTPlugin::store_state (ARDOUR::PluginState& s)
{
}
void
VSTPlugin::restore_state (ARDOUR::PluginState& s)
{
}

View file

@ -97,6 +97,8 @@ Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_vertical_meter(int width, int heigh
height = min_v_pixbuf_size; height = min_v_pixbuf_size;
if (height > max_v_pixbuf_size) if (height > max_v_pixbuf_size)
height = max_v_pixbuf_size; height = max_v_pixbuf_size;
//int index = height - 1;
//if (v_pixbuf_cache == 0) { //if (v_pixbuf_cache == 0) {
// v_pixbuf_cache = (Glib::RefPtr<Gdk::Pixbuf>*) malloc(sizeof(Glib::RefPtr<Gdk::Pixbuf>) * max_v_pixbuf_size); // v_pixbuf_cache = (Glib::RefPtr<Gdk::Pixbuf>*) malloc(sizeof(Glib::RefPtr<Gdk::Pixbuf>) * max_v_pixbuf_size);
@ -363,7 +365,7 @@ FastMeter::vertical_expose (GdkEventExpose* ev)
background.width = pixrect.width; background.width = pixrect.width;
background.height = pixheight - top_of_meter; background.height = pixheight - top_of_meter;
if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) { if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
get_window()->draw_rectangle (get_style()->get_black_gc(), true, get_window()->draw_rectangle (get_style()->get_black_gc(), true,
intersection.x, intersection.y, intersection.x, intersection.y,
intersection.width, intersection.height); intersection.width, intersection.height);
@ -408,7 +410,7 @@ FastMeter::horizontal_expose (GdkEventExpose* ev)
background.width = pixwidth - right_of_meter; background.width = pixwidth - right_of_meter;
background.height = pixrect.height; background.height = pixrect.height;
if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) { if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
get_window()->draw_rectangle (get_style()->get_black_gc(), true, get_window()->draw_rectangle (get_style()->get_black_gc(), true,
intersection.x + right_of_meter, intersection.y, intersection.x + right_of_meter, intersection.y,
intersection.width, intersection.height); intersection.width, intersection.height);
@ -419,7 +421,7 @@ FastMeter::horizontal_expose (GdkEventExpose* ev)
get_window()->draw_pixbuf(get_style()->get_fg_gc(get_state()), pixbuf, get_window()->draw_pixbuf(get_style()->get_fg_gc(get_state()), pixbuf,
intersection.x, intersection.y, intersection.x, intersection.y,
intersection.x, intersection.y, intersection.x, intersection.y,
intersection.width, intersection.height, pixrect.width, intersection.height,
Gdk::RGB_DITHER_NONE, 0, 0); Gdk::RGB_DITHER_NONE, 0, 0);
} }

26
libs/vamp-sdk/COPYING Normal file
View file

@ -0,0 +1,26 @@
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.

240
libs/vamp-sdk/README Normal file
View file

@ -0,0 +1,240 @@
Vamp
====
An API for audio analysis and feature extraction plugins.
http://www.vamp-plugins.org/
Vamp is an API for C and C++ plugins that process sampled audio data
to produce descriptive output (measurements or semantic observations).
The principal differences between Vamp and a real-time audio
processing plugin system such as VST are:
* Vamp plugins may output complex multidimensional data with labels.
As a consequence, they are likely to work best when the output
data has a much lower sampling rate than the input. (This also
means it is usually desirable to implement them in C++ using the
high-level base class provided rather than use the raw C API.)
* While Vamp plugins receive data block-by-block, they are not
required to return output immediately on receiving the input.
A Vamp plugin may be non-causal, preferring to store up data
based on its input until the end of a processing run and then
return all results at once.
* Vamp plugins have more control over their inputs than a typical
real-time processing plugin. For example, they can indicate to
the host their preferred processing block and step sizes, and these
may differ.
* Vamp plugins may ask to receive data in the frequency domain
instead of the time domain. The host takes the responsibility
for converting the input data using an FFT of windowed frames.
This simplifies plugins that do straightforward frequency-domain
processing and permits the host to cache frequency-domain data
when possible.
* A Vamp plugin is configured once before each processing run, and
receives no further parameter changes during use -- unlike real-
time plugin APIs in which the input parameters may change at any
time. This also means that fundamental properties such as the
number of values per output or the preferred processing block
size may depend on the input parameters.
* Vamp plugins do not have to be able to run in real time.
About this SDK
==============
This is version 1.1b of the Vamp plugin Software Development Kit.
Plugins and hosts built with this SDK are binary compatible with those
built using version 1.0 of the SDK.
This SDK contains the following:
* vamp/vamp.h
The formal C language plugin API for Vamp plugins.
A Vamp plugin is a dynamic library (.so, .dll or .dylib depending on
platform) exposing one C-linkage entry point (vampGetPluginDescriptor)
which returns data defined in the rest of this C header.
Although the C API is the official API for Vamp, we don't recommend
that you program directly to it. The C++ abstraction found in the
vamp-sdk directory (below) is preferable for most purposes and is
more thoroughly documented.
* vamp-sdk
C++ classes for straightforwardly implementing Vamp plugins and hosts.
Plugins should subclass Vamp::Plugin and then use Vamp::PluginAdapter
to expose the correct C API for the plugin. Plugin authors should
read vamp-sdk/PluginBase.h and Plugin.h for code documentation, and
refer to the example plugin code in the examples directory. Plugins
should link with -lvampsdk. [*NOTE: this has changed from vamp-sdk in
previous versions, to avoid conflict with the use of hyphens for
library versioning schemes on some platforms.]
Hosts may use the Vamp::PluginHostAdapter to convert the loaded
plugin's C API back into a Vamp::Plugin object. Host authors should
refer to the example host code in the host directory. Hosts should
link with -lvamphostsdk. [*NOTE: this has changed from vamp-hostsdk
in previous versions, to avoid conflict with the use of hyphens for
library versioning schemes on some platforms.]
* vamp-sdk/hostext
Additional C++ classes to make a host's life easier (introduced in
version 1.1 of the Vamp SDK).
Vamp::HostExt::PluginLoader provides a very easy interface for a host
to discover, load, and find out category information about the
available plugins. Most "casual" Vamp hosts will probably want to use
this class.
Vamp::HostExt::PluginInputDomainAdapter provides a means for hosts to
handle plugins that expect frequency-domain input, without having to
convert the input themselves.
Vamp::HostExt::PluginChannelAdapter provides a means for hosts to use
plugins that do not necessarily support the same number of audio
channels as they have available, without having to worry about
applying a channel management / mixdown policy themselves.
The PluginLoader class can also use the input domain and channel
adapters automatically to make the entire conversion process
transparent to the host if required.
* examples
Example plugins implemented using the C++ classes. ZeroCrossing
calculates the positions and density of zero-crossing points in an
audio waveform. SpectralCentroid calculates the centre of gravity of
the frequency domain representation of each block of audio.
AmplitudeFollower tracks the amplitude of a signal based on a method
from the SuperCollider real-time audio system.
PercussionOnsetDetector estimates the locations of percussive onsets
using a simple method described in "Drum Source Separation using
Percussive Feature Detection and Spectral Modulation" by Dan Barry,
Derry Fitzgerald, Eugene Coyle and Bob Lawlor, ISSC 2005.
* host
A simple command-line Vamp host, capable of loading a plugin and using
it to process a complete audio file, with its default parameters.
Requires libsndfile (http://www.mega-nerd.com/libsndfile/).
If you don't have libsndfile, you may want to edit the Makefile to
change the default build target from "all" to "sdk", so as to compile
only the SDK and not the host.
Plugin Lookup and Categorisation
================================
The Vamp API does not officially specify how to load plugin libraries
or where to find them. However, the SDK does include a function
(Vamp::PluginHostAdapter::getPluginPath()) that returns a recommended
directory search path that hosts may use for plugin libraries, and a
class (Vamp::HostExt::PluginLoader) that implements a sensible
cross-platform lookup policy using this path. We recommend using this
class in your host unless you have a good reason not to want to. This
implementation also permits the user to set the environment variable
VAMP_PATH to override the default path if desired.
The policy used by Vamp::HostExt::PluginLoader -- and our
recommendation for any host -- is to search each directory in the path
returned by getPluginPath for .DLL (on Windows), .so (on Linux,
Solaris, BSD etc) or .dylib (on OS/X) files, then to load each one and
perform a dynamic name lookup on the vampGetPluginDescriptor function
to enumerate the plugins in the library. This operation will
necessarily be system-dependent.
Vamp also has an informal convention for sorting plugins into
functional categories. In addition to the library file itself, a
plugin library may install a category file with the same name as the
library but .cat extension. The existence and format of this file are
not specified by the Vamp API, but by convention the file may contain
lines of the format
vamp:pluginlibrary:pluginname::General Category > Specific Category
which a host may read and use to assign plugins a location within a
category tree for display to the user. The expectation is that
advanced users may also choose to set up their own preferred category
trees, which is why this information is not queried as part of the
Vamp plugin's API itself. The Vamp::HostExt::PluginLoader class also
provides support for plugin category lookup using this scheme.
Building and Installing the SDK and Examples
============================================
To build the SDK, the simple host, and the example plugins, edit the
Makefile to suit your platform according to the comments in it, then
run "make".
To use an IDE to build a plugin or host using the Vamp SDK, simply add
the .cpp files in the vamp-sdk directory to your project.
Installing the example plugins so that they can be found by other Vamp
hosts depends on your platform:
* Windows: copy the files
examples/vamp-example-plugins.dll
examples/vamp-example-plugins.cat
to
C:\Program Files\Vamp Plugins
* Linux: copy the files
examples/vamp-example-plugins.so
examples/vamp-example-plugins.cat
to
/usr/local/lib/vamp/
* OS/X: copy the files
examples/vamp-example-plugins.dylib
examples/vamp-example-plugins.cat
to
/Library/Audio/Plug-Ins/Vamp
Licensing
=========
This plugin SDK is freely redistributable under a "new-style BSD"
licence. See the file COPYING for more details. In short, you may
modify and redistribute the SDK and example plugins within any
commercial or non-commercial, proprietary or open-source plugin or
application under almost any conditions, with no obligation to provide
source code, provided you retain the original copyright note.
See Also
========
Sonic Visualiser, an interactive open-source graphical audio
inspection, analysis and visualisation tool supporting Vamp plugins.
http://www.sonicvisualiser.org/
Authors
=======
Vamp and the Vamp SDK were designed and made at the Centre for Digital
Music at Queen Mary, University of London.
The SDK was written by Chris Cannam, copyright (c) 2005-2007
Chris Cannam and QMUL.
Mark Sandler and Christian Landone provided ideas and direction, and
Mark Levy, Dan Stowell, Martin Gasser and Craig Sapp provided testing
and other input for the 1.0 API and SDK. The API also uses some ideas
from prior plugin systems, notably DSSI (http://dssi.sourceforge.net)
and FEAPI (http://feapi.sourceforge.net).

39
libs/vamp-sdk/SConscript Normal file
View file

@ -0,0 +1,39 @@
# -*- python -*-
import os
import os.path
import glob
vampsdk_files = Split ("""
vamp-sdk/PluginAdapter.cpp
vamp-sdk/RealTime.cpp
""")
vamphostsdk_files = Split ("""
vamp-sdk/PluginHostAdapter.cpp
vamp-sdk/hostext/PluginChannelAdapter.cpp
vamp-sdk/hostext/PluginInputDomainAdapter.cpp
vamp-sdk/hostext/PluginLoader.cpp
vamp-sdk/hostext/PluginWrapper.cpp
vamp-sdk/RealTime.cpp
""")
Import('env install_prefix libraries')
vampsdk = env.Copy()
vampsdk.Append (CPPATH='#libs/vamp-sdk/vamp', CXXFLAGS="-Ilibs/vamp-sdk")
libvampsdk = vampsdk.SharedLibrary('vampsdk', vampsdk_files)
libvamphostsdk = vampsdk.SharedLibrary('vamphostsdk', vamphostsdk_files)
Default(libvampsdk)
Default(libvamphostsdk)
env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2'), libvampsdk))
env.Alias('tarball', env.Distribute (env['DISTTREE'],
[ 'SConscript', 'COPYING', 'README' ] +
vampsdk_files +
vamphostsdk_files +
glob.glob('vamp/*.h') +
glob.glob('vamp-sdk/*.h') +
glob.glob('vamp-sdk/hostext/*.h')))

View file

@ -0,0 +1,405 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_H_
#define _VAMP_PLUGIN_H_
#include "PluginBase.h"
#include "RealTime.h"
#include <string>
#include <vector>
#include <map>
namespace Vamp {
/**
* \class Plugin Plugin.h <vamp-sdk/Plugin.h>
*
* Vamp::Plugin is a base class for plugin instance classes
* that provide feature extraction from audio or related data.
*
* In most cases, the input will be audio and the output will be a
* stream of derived data at a lower sampling resolution than the
* input.
*
* Note that this class inherits several abstract methods from
* PluginBase. These must be implemented by the subclass.
*
*
* PLUGIN LIFECYCLE
*
* Feature extraction plugins are managed differently from real-time
* plugins (such as VST effects). The main difference is that the
* parameters for a feature extraction plugin are configured before
* the plugin is used, and do not change during use.
*
* 1. Host constructs the plugin, passing it the input sample rate.
* The plugin may do basic initialisation, but should not do anything
* computationally expensive at this point. You must make sure your
* plugin is cheap to construct, otherwise you'll seriously affect the
* startup performance of almost all hosts. If you have serious
* initialisation to do, the proper place is in initialise() (step 5).
*
* 2. Host may query the plugin's available outputs.
*
* 3. Host queries programs and parameter descriptors, and may set
* some or all of them. Parameters that are not explicitly set should
* take their default values as specified in the parameter descriptor.
* When a program is set, the parameter values may change and the host
* will re-query them to check.
*
* 4. Host queries the preferred step size, block size and number of
* channels. These may all vary depending on the parameter values.
* (Note however that you cannot make the number of distinct outputs
* dependent on parameter values.)
*
* 5. Plugin is properly initialised with a call to initialise. This
* fixes the step size, block size, and number of channels, as well as
* all of the parameter and program settings. If the values passed in
* to initialise do not match the plugin's advertised preferred values
* from step 4, the plugin may refuse to initialise and return false
* (although if possible it should accept the new values). Any
* computationally expensive setup code should take place here.
*
* 6. Host finally checks the number of values, resolution, extents
* etc per output (which may vary depending on the number of channels,
* step size and block size as well as the parameter values).
*
* 7. Host will repeatedly call the process method to pass in blocks
* of input data. This method may return features extracted from that
* data (if the plugin is causal).
*
* 8. Host will call getRemainingFeatures exactly once, after all the
* input data has been processed. This may return any non-causal or
* leftover features.
*
* 9. At any point after initialise was called, the host may
* optionally call the reset method and restart processing. (This
* does not mean it can change the parameters, which are fixed from
* initialise until destruction.)
*
* A plugin does not need to handle the case where setParameter or
* selectProgram is called after initialise has been called. It's the
* host's responsibility not to do that. Similarly, the plugin may
* safely assume that initialise is called no more than once.
*/
class Plugin : public PluginBase
{
public:
virtual ~Plugin() { }
/**
* Initialise a plugin to prepare it for use with the given number
* of input channels, step size (window increment, in sample
* frames) and block size (window size, in sample frames).
*
* The input sample rate should have been already specified at
* construction time.
*
* Return true for successful initialisation, false if the number
* of input channels, step size and/or block size cannot be
* supported.
*/
virtual bool initialise(size_t inputChannels,
size_t stepSize,
size_t blockSize) = 0;
/**
* Reset the plugin after use, to prepare it for another clean
* run. Not called for the first initialisation (i.e. initialise
* must also do a reset).
*/
virtual void reset() = 0;
enum InputDomain { TimeDomain, FrequencyDomain };
/**
* Get the plugin's required input domain. If this is TimeDomain,
* the samples provided to the process() function (below) will be
* in the time domain, as for a traditional audio processing
* plugin. If this is FrequencyDomain, the host will carry out a
* windowed FFT of size equal to the negotiated block size on the
* data before passing the frequency bin data in to process().
* The plugin does not get to choose the window type -- the host
* will either let the user do so, or will use a Hanning window.
*/
virtual InputDomain getInputDomain() const = 0;
/**
* Get the preferred block size (window size -- the number of
* sample frames passed in each block to the process() function).
* This should be called before initialise().
*
* A plugin that can handle any block size may return 0. The
* final block size will be set in the initialise() call.
*/
virtual size_t getPreferredBlockSize() const { return 0; }
/**
* Get the preferred step size (window increment -- the distance
* in sample frames between the start frames of consecutive blocks
* passed to the process() function) for the plugin. This should
* be called before initialise().
*
* A plugin may return 0 if it has no particular interest in the
* step size. In this case, the host should make the step size
* equal to the block size if the plugin is accepting input in the
* time domain. If the plugin is accepting input in the frequency
* domain, the host may use any step size. The final step size
* will be set in the initialise() call.
*/
virtual size_t getPreferredStepSize() const { return 0; }
/**
* Get the minimum supported number of input channels.
*/
virtual size_t getMinChannelCount() const { return 1; }
/**
* Get the maximum supported number of input channels.
*/
virtual size_t getMaxChannelCount() const { return 1; }
struct OutputDescriptor
{
/**
* The name of the output, in computer-usable form. Should be
* reasonably short and without whitespace or punctuation, using
* the characters [a-zA-Z0-9_] only.
* Example: "zero_crossing_count"
*/
std::string identifier;
/**
* The human-readable name of the output.
* Example: "Zero Crossing Counts"
*/
std::string name;
/**
* A human-readable short text describing the output. May be
* empty if the name has said it all already.
* Example: "The number of zero crossing points per processing block"
*/
std::string description;
/**
* The unit of the output, in human-readable form.
*/
std::string unit;
/**
* True if the output has the same number of values per sample
* for every output sample. Outputs for which this is false
* are unlikely to be very useful in a general-purpose host.
*/
bool hasFixedBinCount;
/**
* The number of values per result of the output. Undefined
* if hasFixedBinCount is false. If this is zero, the output
* is point data (i.e. only the time of each output is of
* interest, the value list will be empty).
*/
size_t binCount;
/**
* The (human-readable) names of each of the bins, if
* appropriate. This is always optional.
*/
std::vector<std::string> binNames;
/**
* True if the results in each output bin fall within a fixed
* numeric range (minimum and maximum values). Undefined if
* binCount is zero.
*/
bool hasKnownExtents;
/**
* Minimum value of the results in the output. Undefined if
* hasKnownExtents is false or binCount is zero.
*/
float minValue;
/**
* Maximum value of the results in the output. Undefined if
* hasKnownExtents is false or binCount is zero.
*/
float maxValue;
/**
* True if the output values are quantized to a particular
* resolution. Undefined if binCount is zero.
*/
bool isQuantized;
/**
* Quantization resolution of the output values (e.g. 1.0 if
* they are all integers). Undefined if isQuantized is false
* or binCount is zero.
*/
float quantizeStep;
enum SampleType {
/// Results from each process() align with that call's block start
OneSamplePerStep,
/// Results are evenly spaced in time (sampleRate specified below)
FixedSampleRate,
/// Results are unevenly spaced and have individual timestamps
VariableSampleRate
};
/**
* Positioning in time of the output results.
*/
SampleType sampleType;
/**
* Sample rate of the output results, as samples per second.
* Undefined if sampleType is OneSamplePerStep.
*
* If sampleType is VariableSampleRate and this value is
* non-zero, then it may be used to calculate a resolution for
* the output (i.e. the "duration" of each sample, in time,
* will be 1/sampleRate seconds). It's recommended to set
* this to zero if that behaviour is not desired.
*/
float sampleRate;
};
typedef std::vector<OutputDescriptor> OutputList;
/**
* Get the outputs of this plugin. An output's index in this list
* is used as its numeric index when looking it up in the
* FeatureSet returned from the process() call.
*/
virtual OutputList getOutputDescriptors() const = 0;
struct Feature
{
/**
* True if an output feature has its own timestamp. This is
* mandatory if the output has VariableSampleRate, and is
* likely to be disregarded otherwise.
*/
bool hasTimestamp;
/**
* Timestamp of the output feature. This is mandatory if the
* output has VariableSampleRate, and is likely to be
* disregarded otherwise. Undefined if hasTimestamp is false.
*/
RealTime timestamp;
/**
* Results for a single sample of this feature. If the output
* hasFixedBinCount, there must be the same number of values
* as the output's binCount count.
*/
std::vector<float> values;
/**
* Label for the sample of this feature.
*/
std::string label;
};
typedef std::vector<Feature> FeatureList;
typedef std::map<int, FeatureList> FeatureSet; // key is output no
/**
* Process a single block of input data.
*
* If the plugin's inputDomain is TimeDomain, inputBuffers will
* point to one array of floats per input channel, and each of
* these arrays will contain blockSize consecutive audio samples
* (the host will zero-pad as necessary). The timestamp will be
* the real time in seconds of the start of the supplied block of
* samples.
*
* If the plugin's inputDomain is FrequencyDomain, inputBuffers
* will point to one array of floats per input channel, and each
* of these arrays will contain blockSize/2+1 consecutive pairs of
* real and imaginary component floats corresponding to bins
* 0..(blockSize/2) of the FFT output. That is, bin 0 (the first
* pair of floats) contains the DC output, up to bin blockSize/2
* which contains the Nyquist-frequency output. There will
* therefore be blockSize+2 floats per channel in total. The
* timestamp will be the real time in seconds of the centre of the
* FFT input window (i.e. the very first block passed to process
* might contain the FFT of half a block of zero samples and the
* first half-block of the actual data, with a timestamp of zero).
*
* Return any features that have become available after this
* process call. (These do not necessarily have to fall within
* the process block, except for OneSamplePerStep outputs.)
*/
virtual FeatureSet process(const float *const *inputBuffers,
RealTime timestamp) = 0;
/**
* After all blocks have been processed, calculate and return any
* remaining features derived from the complete input.
*/
virtual FeatureSet getRemainingFeatures() = 0;
/**
* Used to distinguish between Vamp::Plugin and other potential
* sibling subclasses of PluginBase. Do not reimplement this
* function in your subclass.
*/
virtual std::string getType() const { return "Feature Extraction Plugin"; }
protected:
Plugin(float inputSampleRate) :
m_inputSampleRate(inputSampleRate) { }
float m_inputSampleRate;
};
}
#endif

View file

@ -0,0 +1,851 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#include "PluginAdapter.h"
//#define DEBUG_PLUGIN_ADAPTER 1
namespace Vamp {
class PluginAdapterBase::Impl
{
public:
Impl(PluginAdapterBase *);
~Impl();
const VampPluginDescriptor *getDescriptor();
protected:
PluginAdapterBase *m_base;
static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
float inputSampleRate);
static void vampCleanup(VampPluginHandle handle);
static int vampInitialise(VampPluginHandle handle, unsigned int channels,
unsigned int stepSize, unsigned int blockSize);
static void vampReset(VampPluginHandle handle);
static float vampGetParameter(VampPluginHandle handle, int param);
static void vampSetParameter(VampPluginHandle handle, int param, float value);
static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
static unsigned int vampGetOutputCount(VampPluginHandle handle);
static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
unsigned int i);
static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
static VampFeatureList *vampProcess(VampPluginHandle handle,
const float *const *inputBuffers,
int sec,
int nsec);
static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
static void vampReleaseFeatureSet(VampFeatureList *fs);
void cleanup(Plugin *plugin);
void checkOutputMap(Plugin *plugin);
unsigned int getOutputCount(Plugin *plugin);
VampOutputDescriptor *getOutputDescriptor(Plugin *plugin,
unsigned int i);
VampFeatureList *process(Plugin *plugin,
const float *const *inputBuffers,
int sec, int nsec);
VampFeatureList *getRemainingFeatures(Plugin *plugin);
VampFeatureList *convertFeatures(Plugin *plugin,
const Plugin::FeatureSet &features);
// maps both plugins and descriptors to adapters
typedef std::map<const void *, Impl *> AdapterMap;
static AdapterMap *m_adapterMap;
static Impl *lookupAdapter(VampPluginHandle);
bool m_populated;
VampPluginDescriptor m_descriptor;
Plugin::ParameterList m_parameters;
Plugin::ProgramList m_programs;
typedef std::map<Plugin *, Plugin::OutputList *> OutputMap;
OutputMap m_pluginOutputs;
std::map<Plugin *, VampFeatureList *> m_fs;
std::map<Plugin *, std::vector<size_t> > m_fsizes;
std::map<Plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
void resizeFS(Plugin *plugin, int n);
void resizeFL(Plugin *plugin, int n, size_t sz);
void resizeFV(Plugin *plugin, int n, int j, size_t sz);
};
PluginAdapterBase::PluginAdapterBase()
{
m_impl = new Impl(this);
}
PluginAdapterBase::~PluginAdapterBase()
{
delete m_impl;
}
const VampPluginDescriptor *
PluginAdapterBase::getDescriptor()
{
return m_impl->getDescriptor();
}
PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
m_base(base),
m_populated(false)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl;
#endif
}
const VampPluginDescriptor *
PluginAdapterBase::Impl::getDescriptor()
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl;
#endif
if (m_populated) return &m_descriptor;
Plugin *plugin = m_base->createPlugin(48000);
if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
<< "Plugin object API version "
<< plugin->getVampApiVersion()
<< " does not match actual API version "
<< VAMP_API_VERSION << std::endl;
delete plugin;
return 0;
}
m_parameters = plugin->getParameterDescriptors();
m_programs = plugin->getPrograms();
m_descriptor.vampApiVersion = plugin->getVampApiVersion();
m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
m_descriptor.name = strdup(plugin->getName().c_str());
m_descriptor.description = strdup(plugin->getDescription().c_str());
m_descriptor.maker = strdup(plugin->getMaker().c_str());
m_descriptor.pluginVersion = plugin->getPluginVersion();
m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
m_descriptor.parameterCount = m_parameters.size();
m_descriptor.parameters = (const VampParameterDescriptor **)
malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
unsigned int i;
for (i = 0; i < m_parameters.size(); ++i) {
VampParameterDescriptor *desc = (VampParameterDescriptor *)
malloc(sizeof(VampParameterDescriptor));
desc->identifier = strdup(m_parameters[i].identifier.c_str());
desc->name = strdup(m_parameters[i].name.c_str());
desc->description = strdup(m_parameters[i].description.c_str());
desc->unit = strdup(m_parameters[i].unit.c_str());
desc->minValue = m_parameters[i].minValue;
desc->maxValue = m_parameters[i].maxValue;
desc->defaultValue = m_parameters[i].defaultValue;
desc->isQuantized = m_parameters[i].isQuantized;
desc->quantizeStep = m_parameters[i].quantizeStep;
desc->valueNames = 0;
if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
desc->valueNames = (const char **)
malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
}
desc->valueNames[m_parameters[i].valueNames.size()] = 0;
}
m_descriptor.parameters[i] = desc;
}
m_descriptor.programCount = m_programs.size();
m_descriptor.programs = (const char **)
malloc(m_programs.size() * sizeof(const char *));
for (i = 0; i < m_programs.size(); ++i) {
m_descriptor.programs[i] = strdup(m_programs[i].c_str());
}
if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
m_descriptor.inputDomain = vampFrequencyDomain;
} else {
m_descriptor.inputDomain = vampTimeDomain;
}
m_descriptor.instantiate = vampInstantiate;
m_descriptor.cleanup = vampCleanup;
m_descriptor.initialise = vampInitialise;
m_descriptor.reset = vampReset;
m_descriptor.getParameter = vampGetParameter;
m_descriptor.setParameter = vampSetParameter;
m_descriptor.getCurrentProgram = vampGetCurrentProgram;
m_descriptor.selectProgram = vampSelectProgram;
m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
m_descriptor.getMinChannelCount = vampGetMinChannelCount;
m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
m_descriptor.getOutputCount = vampGetOutputCount;
m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
m_descriptor.process = vampProcess;
m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
if (!m_adapterMap) {
m_adapterMap = new AdapterMap;
}
(*m_adapterMap)[&m_descriptor] = this;
delete plugin;
m_populated = true;
return &m_descriptor;
}
PluginAdapterBase::Impl::~Impl()
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl;
#endif
if (!m_populated) return;
free((void *)m_descriptor.identifier);
free((void *)m_descriptor.name);
free((void *)m_descriptor.description);
free((void *)m_descriptor.maker);
free((void *)m_descriptor.copyright);
for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
const VampParameterDescriptor *desc = m_descriptor.parameters[i];
free((void *)desc->identifier);
free((void *)desc->name);
free((void *)desc->description);
free((void *)desc->unit);
if (desc->valueNames) {
for (unsigned int j = 0; desc->valueNames[j]; ++j) {
free((void *)desc->valueNames[j]);
}
free((void *)desc->valueNames);
}
}
free((void *)m_descriptor.parameters);
for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
free((void *)m_descriptor.programs[i]);
}
free((void *)m_descriptor.programs);
if (m_adapterMap) {
m_adapterMap->erase(&m_descriptor);
if (m_adapterMap->empty()) {
delete m_adapterMap;
m_adapterMap = 0;
}
}
}
PluginAdapterBase::Impl *
PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl;
#endif
if (!m_adapterMap) return 0;
AdapterMap::const_iterator i = m_adapterMap->find(handle);
if (i == m_adapterMap->end()) return 0;
return i->second;
}
VampPluginHandle
PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
float inputSampleRate)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl;
#endif
if (!m_adapterMap) {
m_adapterMap = new AdapterMap();
}
if (m_adapterMap->find(desc) == m_adapterMap->end()) {
std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
return 0;
}
Impl *adapter = (*m_adapterMap)[desc];
if (desc != &adapter->m_descriptor) return 0;
Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
if (plugin) {
(*m_adapterMap)[plugin] = adapter;
}
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl;
#endif
return plugin;
}
void
PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) {
delete ((Plugin *)handle);
return;
}
adapter->cleanup(((Plugin *)handle));
}
int
PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
unsigned int channels,
unsigned int stepSize,
unsigned int blockSize)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl;
#endif
bool result = ((Plugin *)handle)->initialise
(channels, stepSize, blockSize);
return result ? 1 : 0;
}
void
PluginAdapterBase::Impl::vampReset(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl;
#endif
((Plugin *)handle)->reset();
}
float
PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
int param)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) return 0.0;
Plugin::ParameterList &list = adapter->m_parameters;
return ((Plugin *)handle)->getParameter(list[param].identifier);
}
void
PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
int param, float value)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) return;
Plugin::ParameterList &list = adapter->m_parameters;
((Plugin *)handle)->setParameter(list[param].identifier, value);
}
unsigned int
PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) return 0;
Plugin::ProgramList &list = adapter->m_programs;
std::string program = ((Plugin *)handle)->getCurrentProgram();
for (unsigned int i = 0; i < list.size(); ++i) {
if (list[i] == program) return i;
}
return 0;
}
void
PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
unsigned int program)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) return;
Plugin::ProgramList &list = adapter->m_programs;
((Plugin *)handle)->selectProgram(list[program]);
}
unsigned int
PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl;
#endif
return ((Plugin *)handle)->getPreferredStepSize();
}
unsigned int
PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl;
#endif
return ((Plugin *)handle)->getPreferredBlockSize();
}
unsigned int
PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl;
#endif
return ((Plugin *)handle)->getMinChannelCount();
}
unsigned int
PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl;
#endif
return ((Plugin *)handle)->getMaxChannelCount();
}
unsigned int
PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
// std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl;
if (!adapter) return 0;
return adapter->getOutputCount((Plugin *)handle);
}
VampOutputDescriptor *
PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
unsigned int i)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
// std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl;
if (!adapter) return 0;
return adapter->getOutputDescriptor((Plugin *)handle, i);
}
void
PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl;
#endif
if (desc->identifier) free((void *)desc->identifier);
if (desc->name) free((void *)desc->name);
if (desc->description) free((void *)desc->description);
if (desc->unit) free((void *)desc->unit);
if (desc->hasFixedBinCount && desc->binNames) {
for (unsigned int i = 0; i < desc->binCount; ++i) {
if (desc->binNames[i]) {
free((void *)desc->binNames[i]);
}
}
}
if (desc->binNames) free((void *)desc->binNames);
free((void *)desc);
}
VampFeatureList *
PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
const float *const *inputBuffers,
int sec,
int nsec)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) return 0;
return adapter->process((Plugin *)handle,
inputBuffers, sec, nsec);
}
VampFeatureList *
PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl;
#endif
Impl *adapter = lookupAdapter(handle);
if (!adapter) return 0;
return adapter->getRemainingFeatures((Plugin *)handle);
}
void
PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
{
#ifdef DEBUG_PLUGIN_ADAPTER
std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
#endif
}
void
PluginAdapterBase::Impl::cleanup(Plugin *plugin)
{
if (m_fs.find(plugin) != m_fs.end()) {
size_t outputCount = 0;
if (m_pluginOutputs[plugin]) {
outputCount = m_pluginOutputs[plugin]->size();
}
VampFeatureList *list = m_fs[plugin];
for (unsigned int i = 0; i < outputCount; ++i) {
for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
if (list[i].features[j].label) {
free(list[i].features[j].label);
}
if (list[i].features[j].values) {
free(list[i].features[j].values);
}
}
if (list[i].features) free(list[i].features);
}
m_fs.erase(plugin);
m_fsizes.erase(plugin);
m_fvsizes.erase(plugin);
}
if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
delete m_pluginOutputs[plugin];
m_pluginOutputs.erase(plugin);
}
if (m_adapterMap) {
m_adapterMap->erase(plugin);
if (m_adapterMap->empty()) {
delete m_adapterMap;
m_adapterMap = 0;
}
}
delete ((Plugin *)plugin);
}
void
PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
{
if (m_pluginOutputs.find(plugin) == m_pluginOutputs.end() ||
!m_pluginOutputs[plugin]) {
m_pluginOutputs[plugin] = new Plugin::OutputList
(plugin->getOutputDescriptors());
// std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl;
}
}
unsigned int
PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
{
checkOutputMap(plugin);
return m_pluginOutputs[plugin]->size();
}
VampOutputDescriptor *
PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
unsigned int i)
{
checkOutputMap(plugin);
Plugin::OutputDescriptor &od =
(*m_pluginOutputs[plugin])[i];
VampOutputDescriptor *desc = (VampOutputDescriptor *)
malloc(sizeof(VampOutputDescriptor));
desc->identifier = strdup(od.identifier.c_str());
desc->name = strdup(od.name.c_str());
desc->description = strdup(od.description.c_str());
desc->unit = strdup(od.unit.c_str());
desc->hasFixedBinCount = od.hasFixedBinCount;
desc->binCount = od.binCount;
if (od.hasFixedBinCount && od.binCount > 0) {
desc->binNames = (const char **)
malloc(od.binCount * sizeof(const char *));
for (unsigned int i = 0; i < od.binCount; ++i) {
if (i < od.binNames.size()) {
desc->binNames[i] = strdup(od.binNames[i].c_str());
} else {
desc->binNames[i] = 0;
}
}
} else {
desc->binNames = 0;
}
desc->hasKnownExtents = od.hasKnownExtents;
desc->minValue = od.minValue;
desc->maxValue = od.maxValue;
desc->isQuantized = od.isQuantized;
desc->quantizeStep = od.quantizeStep;
switch (od.sampleType) {
case Plugin::OutputDescriptor::OneSamplePerStep:
desc->sampleType = vampOneSamplePerStep; break;
case Plugin::OutputDescriptor::FixedSampleRate:
desc->sampleType = vampFixedSampleRate; break;
case Plugin::OutputDescriptor::VariableSampleRate:
desc->sampleType = vampVariableSampleRate; break;
}
desc->sampleRate = od.sampleRate;
return desc;
}
VampFeatureList *
PluginAdapterBase::Impl::process(Plugin *plugin,
const float *const *inputBuffers,
int sec, int nsec)
{
// std::cerr << "PluginAdapterBase::Impl::process" << std::endl;
RealTime rt(sec, nsec);
checkOutputMap(plugin);
return convertFeatures(plugin, plugin->process(inputBuffers, rt));
}
VampFeatureList *
PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
{
// std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl;
checkOutputMap(plugin);
return convertFeatures(plugin, plugin->getRemainingFeatures());
}
VampFeatureList *
PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
const Plugin::FeatureSet &features)
{
int lastN = -1;
int outputCount = 0;
if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
resizeFS(plugin, outputCount);
VampFeatureList *fs = m_fs[plugin];
for (Plugin::FeatureSet::const_iterator fi = features.begin();
fi != features.end(); ++fi) {
int n = fi->first;
// std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl;
if (n >= int(outputCount)) {
std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
continue;
}
if (n > lastN + 1) {
for (int i = lastN + 1; i < n; ++i) {
fs[i].featureCount = 0;
}
}
const Plugin::FeatureList &fl = fi->second;
size_t sz = fl.size();
if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
fs[n].featureCount = sz;
for (size_t j = 0; j < sz; ++j) {
// std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl;
VampFeature *feature = &fs[n].features[j];
feature->hasTimestamp = fl[j].hasTimestamp;
feature->sec = fl[j].timestamp.sec;
feature->nsec = fl[j].timestamp.nsec;
feature->valueCount = fl[j].values.size();
if (feature->label) free(feature->label);
if (fl[j].label.empty()) {
feature->label = 0;
} else {
feature->label = strdup(fl[j].label.c_str());
}
if (feature->valueCount > m_fvsizes[plugin][n][j]) {
resizeFV(plugin, n, j, feature->valueCount);
}
for (unsigned int k = 0; k < feature->valueCount; ++k) {
// std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl;
feature->values[k] = fl[j].values[k];
}
}
lastN = n;
}
if (lastN == -1) return 0;
if (int(outputCount) > lastN + 1) {
for (int i = lastN + 1; i < int(outputCount); ++i) {
fs[i].featureCount = 0;
}
}
return fs;
}
void
PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
{
// std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl;
int i = m_fsizes[plugin].size();
if (i >= n) return;
// std::cerr << "resizing from " << i << std::endl;
m_fs[plugin] = (VampFeatureList *)realloc
(m_fs[plugin], n * sizeof(VampFeatureList));
while (i < n) {
m_fs[plugin][i].featureCount = 0;
m_fs[plugin][i].features = 0;
m_fsizes[plugin].push_back(0);
m_fvsizes[plugin].push_back(std::vector<size_t>());
i++;
}
}
void
PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
{
// std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
// << sz << ")" << std::endl;
size_t i = m_fsizes[plugin][n];
if (i >= sz) return;
// std::cerr << "resizing from " << i << std::endl;
m_fs[plugin][n].features = (VampFeature *)realloc
(m_fs[plugin][n].features, sz * sizeof(VampFeature));
while (m_fsizes[plugin][n] < sz) {
m_fs[plugin][n].features[m_fsizes[plugin][n]].valueCount = 0;
m_fs[plugin][n].features[m_fsizes[plugin][n]].values = 0;
m_fs[plugin][n].features[m_fsizes[plugin][n]].label = 0;
m_fvsizes[plugin][n].push_back(0);
m_fsizes[plugin][n]++;
}
}
void
PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
{
// std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
// << j << ", " << sz << ")" << std::endl;
size_t i = m_fvsizes[plugin][n][j];
if (i >= sz) return;
// std::cerr << "resizing from " << i << std::endl;
m_fs[plugin][n].features[j].values = (float *)realloc
(m_fs[plugin][n].features[j].values, sz * sizeof(float));
m_fvsizes[plugin][n][j] = sz;
}
PluginAdapterBase::Impl::AdapterMap *
PluginAdapterBase::Impl::m_adapterMap = 0;
}

View file

@ -0,0 +1,117 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_ADAPTER_H_
#define _VAMP_PLUGIN_ADAPTER_H_
#include <vamp/vamp.h>
#include "Plugin.h"
#include <map>
namespace Vamp {
/**
* \class PluginAdapterBase PluginAdapter.h <vamp-sdk/PluginAdapter.h>
*
* PluginAdapter and PluginAdapterBase provide a wrapper class that a
* plugin library can use to make its C++ Vamp::Plugin objects
* available through the Vamp C API.
*
* Almost all Vamp plugin libraries will want to make use of this. To
* do so, all they need to do is declare a PluginAdapter<T> for each
* plugin class T in their library. It's very simple, and you need to
* know absolutely nothing about how it works in order to use it.
* Just cut and paste from an existing plugin's discovery function.
* \see vampGetPluginDescriptor
*/
class PluginAdapterBase
{
public:
virtual ~PluginAdapterBase();
/**
* Return a VampPluginDescriptor describing the plugin that is
* wrapped by this adapter.
*/
const VampPluginDescriptor *getDescriptor();
protected:
PluginAdapterBase();
virtual Plugin *createPlugin(float inputSampleRate) = 0;
class Impl;
Impl *m_impl;
};
/**
* \class PluginAdapter PluginAdapter.h <vamp-sdk/PluginAdapter.h>
*
* PluginAdapter turns a PluginAdapterBase into a specific wrapper for
* a particular plugin implementation.
*
* See PluginAdapterBase.
*/
template <typename P>
class PluginAdapter : public PluginAdapterBase
{
public:
PluginAdapter() : PluginAdapterBase() { }
virtual ~PluginAdapter() { }
protected:
Plugin *createPlugin(float inputSampleRate) {
P *p = new P(inputSampleRate);
Plugin *plugin = dynamic_cast<Plugin *>(p);
if (!plugin) {
std::cerr << "ERROR: PluginAdapter::createPlugin: "
<< "Template type is not a plugin!"
<< std::endl;
delete p;
return 0;
}
return plugin;
}
};
}
#endif

View file

@ -0,0 +1,252 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_BASE_H_
#define _VAMP_PLUGIN_BASE_H_
#include <string>
#include <vector>
#define VAMP_SDK_VERSION "1.1"
namespace Vamp {
/**
* A base class for plugins with optional configurable parameters,
* programs, etc. The Vamp::Plugin is derived from this, and
* individual Vamp plugins should derive from that.
*
* This class does not provide the necessary interfaces to instantiate
* or run a plugin. It only specifies an interface for retrieving
* those controls that the host may wish to show to the user for
* editing. It could meaningfully be subclassed by real-time plugins
* or other sorts of plugin as well as Vamp plugins.
*/
class PluginBase
{
public:
virtual ~PluginBase() { }
/**
* Get the Vamp API compatibility level of the plugin.
*/
virtual unsigned int getVampApiVersion() const { return 1; }
/**
* Get the computer-usable name of the plugin. This should be
* reasonably short and contain no whitespace or punctuation
* characters. It may only contain the characters [a-zA-Z0-9_].
* This is the authoritative way for a program to identify a
* plugin within a given library.
*
* This text may be visible to the user, but it should not be the
* main text used to identify a plugin to the user (that will be
* the name, below).
*
* Example: "zero_crossings"
*/
virtual std::string getIdentifier() const = 0;
/**
* Get a human-readable name or title of the plugin. This
* should be brief and self-contained, as it may be used to
* identify the plugin to the user in isolation (i.e. without also
* showing the plugin's "identifier").
*
* Example: "Zero Crossings"
*/
virtual std::string getName() const = 0;
/**
* Get a human-readable description for the plugin, typically
* a line of text that may optionally be displayed in addition
* to the plugin's "name". May be empty if the name has said
* it all already.
*
* Example: "Detect and count zero crossing points"
*/
virtual std::string getDescription() const = 0;
/**
* Get the name of the author or vendor of the plugin in
* human-readable form. This should be a short identifying text,
* as it may be used to label plugins from the same source in a
* menu or similar.
*/
virtual std::string getMaker() const = 0;
/**
* Get the copyright statement or licensing summary for the
* plugin. This can be an informative text, without the same
* presentation constraints as mentioned for getMaker above.
*/
virtual std::string getCopyright() const = 0;
/**
* Get the version number of the plugin.
*/
virtual int getPluginVersion() const = 0;
struct ParameterDescriptor
{
/**
* The name of the parameter, in computer-usable form. Should
* be reasonably short, and may only contain the characters
* [a-zA-Z0-9_].
*/
std::string identifier;
/**
* The human-readable name of the parameter.
*/
std::string name;
/**
* A human-readable short text describing the parameter. May be
* empty if the name has said it all already.
*/
std::string description;
/**
* The unit of the parameter, in human-readable form.
*/
std::string unit;
/**
* The minimum value of the parameter.
*/
float minValue;
/**
* The maximum value of the parameter.
*/
float maxValue;
/**
* The default value of the parameter. The plugin should
* ensure that parameters have this value on initialisation
* (i.e. the host is not required to explicitly set parameters
* if it wants to use their default values).
*/
float defaultValue;
/**
* True if the parameter values are quantized to a particular
* resolution.
*/
bool isQuantized;
/**
* Quantization resolution of the parameter values (e.g. 1.0
* if they are all integers). Undefined if isQuantized is
* false.
*/
float quantizeStep;
/**
* Names for the quantized values. If isQuantized is true,
* this may either be empty or contain one string for each of
* the quantize steps from minValue up to maxValue inclusive.
* Undefined if isQuantized is false.
*
* If these names are provided, they should be shown to the
* user in preference to the values themselves. The user may
* never see the actual numeric values unless they are also
* encoded in the names.
*/
std::vector<std::string> valueNames;
};
typedef std::vector<ParameterDescriptor> ParameterList;
/**
* Get the controllable parameters of this plugin.
*/
virtual ParameterList getParameterDescriptors() const {
return ParameterList();
}
/**
* Get the value of a named parameter. The argument is the identifier
* field from that parameter's descriptor.
*/
virtual float getParameter(std::string) const { return 0.0; }
/**
* Set a named parameter. The first argument is the identifier field
* from that parameter's descriptor.
*/
virtual void setParameter(std::string, float) { }
typedef std::vector<std::string> ProgramList;
/**
* Get the program settings available in this plugin. A program
* is a named shorthand for a set of parameter values; changing
* the program may cause the plugin to alter the values of its
* published parameters (and/or non-public internal processing
* parameters). The host should re-read the plugin's parameter
* values after setting a new program.
*
* The programs must have unique names.
*/
virtual ProgramList getPrograms() const { return ProgramList(); }
/**
* Get the current program.
*/
virtual std::string getCurrentProgram() const { return ""; }
/**
* Select a program. (If the given program name is not one of the
* available programs, do nothing.)
*/
virtual void selectProgram(std::string) { }
/**
* Get the type of plugin. This is to be implemented by the
* immediate subclass, not by actual plugins. Do not attempt to
* implement this in plugin code.
*/
virtual std::string getType() const = 0;
};
}
#endif

View file

@ -0,0 +1,418 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#include "PluginHostAdapter.h"
namespace Vamp
{
PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
float inputSampleRate) :
Plugin(inputSampleRate),
m_descriptor(descriptor)
{
// std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
if (!m_handle) {
// std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
}
}
PluginHostAdapter::~PluginHostAdapter()
{
// std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
if (m_handle) m_descriptor->cleanup(m_handle);
}
std::vector<std::string>
PluginHostAdapter::getPluginPath()
{
std::vector<std::string> path;
std::string envPath;
char *cpath = getenv("VAMP_PATH");
if (cpath) envPath = cpath;
#ifdef _WIN32
#define PATH_SEPARATOR ';'
#define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
#else
#define PATH_SEPARATOR ':'
#ifdef __APPLE__
#define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
#else
#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
#endif
#endif
if (envPath == "") {
envPath = DEFAULT_VAMP_PATH;
char *chome = getenv("HOME");
if (chome) {
std::string home(chome);
std::string::size_type f;
while ((f = envPath.find("$HOME")) != std::string::npos &&
f < envPath.length()) {
envPath.replace(f, 5, home);
}
}
#ifdef _WIN32
char *cpfiles = getenv("ProgramFiles");
if (!cpfiles) cpfiles = "C:\\Program Files";
std::string pfiles(cpfiles);
std::string::size_type f;
while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
f < envPath.length()) {
envPath.replace(f, 14, pfiles);
}
#endif
}
std::string::size_type index = 0, newindex = 0;
while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
path.push_back(envPath.substr(index, newindex - index));
index = newindex + 1;
}
path.push_back(envPath.substr(index));
return path;
}
bool
PluginHostAdapter::initialise(size_t channels,
size_t stepSize,
size_t blockSize)
{
if (!m_handle) return false;
return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
true : false;
}
void
PluginHostAdapter::reset()
{
if (!m_handle) return;
m_descriptor->reset(m_handle);
}
PluginHostAdapter::InputDomain
PluginHostAdapter::getInputDomain() const
{
if (m_descriptor->inputDomain == vampFrequencyDomain) {
return FrequencyDomain;
} else {
return TimeDomain;
}
}
unsigned int
PluginHostAdapter::getVampApiVersion() const
{
return m_descriptor->vampApiVersion;
}
std::string
PluginHostAdapter::getIdentifier() const
{
return m_descriptor->identifier;
}
std::string
PluginHostAdapter::getName() const
{
return m_descriptor->name;
}
std::string
PluginHostAdapter::getDescription() const
{
return m_descriptor->description;
}
std::string
PluginHostAdapter::getMaker() const
{
return m_descriptor->maker;
}
int
PluginHostAdapter::getPluginVersion() const
{
return m_descriptor->pluginVersion;
}
std::string
PluginHostAdapter::getCopyright() const
{
return m_descriptor->copyright;
}
PluginHostAdapter::ParameterList
PluginHostAdapter::getParameterDescriptors() const
{
ParameterList list;
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
const VampParameterDescriptor *spd = m_descriptor->parameters[i];
ParameterDescriptor pd;
pd.identifier = spd->identifier;
pd.name = spd->name;
pd.description = spd->description;
pd.unit = spd->unit;
pd.minValue = spd->minValue;
pd.maxValue = spd->maxValue;
pd.defaultValue = spd->defaultValue;
pd.isQuantized = spd->isQuantized;
pd.quantizeStep = spd->quantizeStep;
if (pd.isQuantized && spd->valueNames) {
for (unsigned int j = 0; spd->valueNames[j]; ++j) {
pd.valueNames.push_back(spd->valueNames[j]);
}
}
list.push_back(pd);
}
return list;
}
float
PluginHostAdapter::getParameter(std::string param) const
{
if (!m_handle) return 0.0;
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
if (param == m_descriptor->parameters[i]->identifier) {
return m_descriptor->getParameter(m_handle, i);
}
}
return 0.0;
}
void
PluginHostAdapter::setParameter(std::string param,
float value)
{
if (!m_handle) return;
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
if (param == m_descriptor->parameters[i]->identifier) {
m_descriptor->setParameter(m_handle, i, value);
return;
}
}
}
PluginHostAdapter::ProgramList
PluginHostAdapter::getPrograms() const
{
ProgramList list;
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
list.push_back(m_descriptor->programs[i]);
}
return list;
}
std::string
PluginHostAdapter::getCurrentProgram() const
{
if (!m_handle) return "";
int pn = m_descriptor->getCurrentProgram(m_handle);
return m_descriptor->programs[pn];
}
void
PluginHostAdapter::selectProgram(std::string program)
{
if (!m_handle) return;
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
if (program == m_descriptor->programs[i]) {
m_descriptor->selectProgram(m_handle, i);
return;
}
}
}
size_t
PluginHostAdapter::getPreferredStepSize() const
{
if (!m_handle) return 0;
return m_descriptor->getPreferredStepSize(m_handle);
}
size_t
PluginHostAdapter::getPreferredBlockSize() const
{
if (!m_handle) return 0;
return m_descriptor->getPreferredBlockSize(m_handle);
}
size_t
PluginHostAdapter::getMinChannelCount() const
{
if (!m_handle) return 0;
return m_descriptor->getMinChannelCount(m_handle);
}
size_t
PluginHostAdapter::getMaxChannelCount() const
{
if (!m_handle) return 0;
return m_descriptor->getMaxChannelCount(m_handle);
}
PluginHostAdapter::OutputList
PluginHostAdapter::getOutputDescriptors() const
{
OutputList list;
if (!m_handle) {
// std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
return list;
}
unsigned int count = m_descriptor->getOutputCount(m_handle);
for (unsigned int i = 0; i < count; ++i) {
VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
OutputDescriptor d;
d.identifier = sd->identifier;
d.name = sd->name;
d.description = sd->description;
d.unit = sd->unit;
d.hasFixedBinCount = sd->hasFixedBinCount;
d.binCount = sd->binCount;
if (d.hasFixedBinCount) {
for (unsigned int j = 0; j < sd->binCount; ++j) {
d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
}
}
d.hasKnownExtents = sd->hasKnownExtents;
d.minValue = sd->minValue;
d.maxValue = sd->maxValue;
d.isQuantized = sd->isQuantized;
d.quantizeStep = sd->quantizeStep;
switch (sd->sampleType) {
case vampOneSamplePerStep:
d.sampleType = OutputDescriptor::OneSamplePerStep; break;
case vampFixedSampleRate:
d.sampleType = OutputDescriptor::FixedSampleRate; break;
case vampVariableSampleRate:
d.sampleType = OutputDescriptor::VariableSampleRate; break;
}
d.sampleRate = sd->sampleRate;
list.push_back(d);
m_descriptor->releaseOutputDescriptor(sd);
}
return list;
}
PluginHostAdapter::FeatureSet
PluginHostAdapter::process(const float *const *inputBuffers,
RealTime timestamp)
{
FeatureSet fs;
if (!m_handle) return fs;
int sec = timestamp.sec;
int nsec = timestamp.nsec;
VampFeatureList *features = m_descriptor->process(m_handle,
inputBuffers,
sec, nsec);
convertFeatures(features, fs);
m_descriptor->releaseFeatureSet(features);
return fs;
}
PluginHostAdapter::FeatureSet
PluginHostAdapter::getRemainingFeatures()
{
FeatureSet fs;
if (!m_handle) return fs;
VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
convertFeatures(features, fs);
m_descriptor->releaseFeatureSet(features);
return fs;
}
void
PluginHostAdapter::convertFeatures(VampFeatureList *features,
FeatureSet &fs)
{
if (!features) return;
unsigned int outputs = m_descriptor->getOutputCount(m_handle);
for (unsigned int i = 0; i < outputs; ++i) {
VampFeatureList &list = features[i];
if (list.featureCount > 0) {
for (unsigned int j = 0; j < list.featureCount; ++j) {
Feature feature;
feature.hasTimestamp = list.features[j].hasTimestamp;
feature.timestamp = RealTime(list.features[j].sec,
list.features[j].nsec);
for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
feature.values.push_back(list.features[j].values[k]);
}
if (list.features[j].label) {
feature.label = list.features[j].label;
}
fs[i].push_back(feature);
}
}
}
}
}

View file

@ -0,0 +1,117 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_HOST_ADAPTER_H_
#define _VAMP_PLUGIN_HOST_ADAPTER_H_
#include <vamp/vamp.h>
#include <vamp-sdk/Plugin.h>
#include <vector>
namespace Vamp {
/**
* \class PluginHostAdapter PluginHostAdapter.h <vamp-sdk/PluginHostAdapter.h>
*
* PluginHostAdapter is a wrapper class that a Vamp host can use to
* make the C-language VampPluginDescriptor object appear as a C++
* Vamp::Plugin object.
*
* The Vamp API is defined in vamp/vamp.h as a C API. The C++ objects
* used for convenience by plugins and hosts actually communicate
* using the C low-level API, but the details of this communication
* are handled seamlessly by the Vamp SDK implementation provided the
* plugin and host use the proper C++ wrapper objects.
*
* See also PluginAdapter, the plugin-side wrapper that makes a C++
* plugin object available using the C query API.
*/
class PluginHostAdapter : public Plugin
{
public:
PluginHostAdapter(const VampPluginDescriptor *descriptor,
float inputSampleRate);
virtual ~PluginHostAdapter();
static std::vector<std::string> getPluginPath();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
void reset();
InputDomain getInputDomain() const;
unsigned int getVampApiVersion() const;
std::string getIdentifier() const;
std::string getName() const;
std::string getDescription() const;
std::string getMaker() const;
int getPluginVersion() const;
std::string getCopyright() const;
ParameterList getParameterDescriptors() const;
float getParameter(std::string) const;
void setParameter(std::string, float);
ProgramList getPrograms() const;
std::string getCurrentProgram() const;
void selectProgram(std::string);
size_t getPreferredStepSize() const;
size_t getPreferredBlockSize() const;
size_t getMinChannelCount() const;
size_t getMaxChannelCount() const;
OutputList getOutputDescriptors() const;
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
FeatureSet getRemainingFeatures();
protected:
void convertFeatures(VampFeatureList *, FeatureSet &);
const VampPluginDescriptor *m_descriptor;
VampPluginHandle m_handle;
};
}
#endif

View file

@ -0,0 +1,254 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
/*
This is a modified version of a source file from the
Rosegarden MIDI and audio sequencer and notation editor.
This file copyright 2000-2006 Chris Cannam.
Relicensed by the author as detailed above.
*/
#include <iostream>
#if (__GNUC__ < 3)
#include <strstream>
#define stringstream strstream
#else
#include <sstream>
#endif
using std::cerr;
using std::endl;
#include "RealTime.h"
#ifndef _WIN32
#include <sys/time.h>
#endif
namespace Vamp {
// A RealTime consists of two ints that must be at least 32 bits each.
// A signed 32-bit int can store values exceeding +/- 2 billion. This
// means we can safely use our lower int for nanoseconds, as there are
// 1 billion nanoseconds in a second and we need to handle double that
// because of the implementations of addition etc that we use.
//
// The maximum valid RealTime on a 32-bit system is somewhere around
// 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
#define ONE_BILLION 1000000000
RealTime::RealTime(int s, int n) :
sec(s), nsec(n)
{
if (sec == 0) {
while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
} else if (sec < 0) {
while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
} else {
while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
while (nsec < 0) { nsec += ONE_BILLION; --sec; }
}
}
RealTime
RealTime::fromSeconds(double sec)
{
return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
}
RealTime
RealTime::fromMilliseconds(int msec)
{
return RealTime(msec / 1000, (msec % 1000) * 1000000);
}
#ifndef _WIN32
RealTime
RealTime::fromTimeval(const struct timeval &tv)
{
return RealTime(tv.tv_sec, tv.tv_usec * 1000);
}
#endif
std::ostream &operator<<(std::ostream &out, const RealTime &rt)
{
if (rt < RealTime::zeroTime) {
out << "-";
} else {
out << " ";
}
int s = (rt.sec < 0 ? -rt.sec : rt.sec);
int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
out << s << ".";
int nn(n);
if (nn == 0) out << "00000000";
else while (nn < (ONE_BILLION / 10)) {
out << "0";
nn *= 10;
}
out << n << "R";
return out;
}
std::string
RealTime::toString() const
{
std::stringstream out;
out << *this;
#if (__GNUC__ < 3)
out << std::ends;
#endif
std::string s = out.str();
// remove trailing R
return s.substr(0, s.length() - 1);
}
std::string
RealTime::toText(bool fixedDp) const
{
if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
std::stringstream out;
if (sec >= 3600) {
out << (sec / 3600) << ":";
}
if (sec >= 60) {
out << (sec % 3600) / 60 << ":";
}
if (sec >= 10) {
out << ((sec % 60) / 10);
}
out << (sec % 10);
int ms = msec();
if (ms != 0) {
out << ".";
out << (ms / 100);
ms = ms % 100;
if (ms != 0) {
out << (ms / 10);
ms = ms % 10;
} else if (fixedDp) {
out << "0";
}
if (ms != 0) {
out << ms;
} else if (fixedDp) {
out << "0";
}
} else if (fixedDp) {
out << ".000";
}
#if (__GNUC__ < 3)
out << std::ends;
#endif
std::string s = out.str();
return s;
}
RealTime
RealTime::operator/(int d) const
{
int secdiv = sec / d;
int secrem = sec % d;
double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
return RealTime(secdiv, int(nsecdiv + 0.5));
}
double
RealTime::operator/(const RealTime &r) const
{
double lTotal = double(sec) * ONE_BILLION + double(nsec);
double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
if (rTotal == 0) return 0.0;
else return lTotal/rTotal;
}
long
RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
{
if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
// We like integers. The last term is always zero unless the
// sample rate is greater than 1MHz, but hell, you never know...
long frame =
time.sec * sampleRate +
(time.msec() * sampleRate) / 1000 +
((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
return frame;
}
RealTime
RealTime::frame2RealTime(long frame, unsigned int sampleRate)
{
if (frame < 0) return -frame2RealTime(-frame, sampleRate);
RealTime rt;
rt.sec = frame / long(sampleRate);
frame -= rt.sec * long(sampleRate);
rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
return rt;
}
const RealTime RealTime::zeroTime(0,0);
}

View file

@ -0,0 +1,154 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
/*
This is a modified version of a source file from the
Rosegarden MIDI and audio sequencer and notation editor.
This file copyright 2000-2006 Chris Cannam.
Relicensed by the author as detailed above.
*/
#ifndef _VAMP_REAL_TIME_H_
#define _VAMP_REAL_TIME_H_
#include <iostream>
#include <string>
#ifndef _WIN32
struct timeval;
#endif
namespace Vamp {
/**
* \class RealTime RealTime.h <vamp-sdk/RealTime.h>
*
* RealTime represents time values to nanosecond precision
* with accurate arithmetic and frame-rate conversion functions.
*/
struct RealTime
{
int sec;
int nsec;
int usec() const { return nsec / 1000; }
int msec() const { return nsec / 1000000; }
RealTime(): sec(0), nsec(0) {}
RealTime(int s, int n);
RealTime(const RealTime &r) :
sec(r.sec), nsec(r.nsec) { }
static RealTime fromSeconds(double sec);
static RealTime fromMilliseconds(int msec);
#ifndef _WIN32
static RealTime fromTimeval(const struct timeval &);
#endif
RealTime &operator=(const RealTime &r) {
sec = r.sec; nsec = r.nsec; return *this;
}
RealTime operator+(const RealTime &r) const {
return RealTime(sec + r.sec, nsec + r.nsec);
}
RealTime operator-(const RealTime &r) const {
return RealTime(sec - r.sec, nsec - r.nsec);
}
RealTime operator-() const {
return RealTime(-sec, -nsec);
}
bool operator <(const RealTime &r) const {
if (sec == r.sec) return nsec < r.nsec;
else return sec < r.sec;
}
bool operator >(const RealTime &r) const {
if (sec == r.sec) return nsec > r.nsec;
else return sec > r.sec;
}
bool operator==(const RealTime &r) const {
return (sec == r.sec && nsec == r.nsec);
}
bool operator!=(const RealTime &r) const {
return !(r == *this);
}
bool operator>=(const RealTime &r) const {
if (sec == r.sec) return nsec >= r.nsec;
else return sec >= r.sec;
}
bool operator<=(const RealTime &r) const {
if (sec == r.sec) return nsec <= r.nsec;
else return sec <= r.sec;
}
RealTime operator/(int d) const;
// Find the fractional difference between times
//
double operator/(const RealTime &r) const;
// Return a human-readable debug-type string to full precision
// (probably not a format to show to a user directly)
//
std::string toString() const;
// Return a user-readable string to the nearest millisecond
// in a form like HH:MM:SS.mmm
//
std::string toText(bool fixedDp = false) const;
// Convenience functions for handling sample frames
//
static long realTime2Frame(const RealTime &r, unsigned int sampleRate);
static RealTime frame2RealTime(long frame, unsigned int sampleRate);
static const RealTime zeroTime;
};
std::ostream &operator<<(std::ostream &out, const RealTime &rt);
}
#endif

View file

@ -0,0 +1,228 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#include "PluginChannelAdapter.h"
namespace Vamp {
namespace HostExt {
class PluginChannelAdapter::Impl
{
public:
Impl(Plugin *plugin);
~Impl();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
protected:
Plugin *m_plugin;
size_t m_blockSize;
size_t m_inputChannels;
size_t m_pluginChannels;
float **m_buffer;
const float **m_forwardPtrs;
};
PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) :
PluginWrapper(plugin)
{
m_impl = new Impl(plugin);
}
PluginChannelAdapter::~PluginChannelAdapter()
{
delete m_impl;
}
bool
PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
return m_impl->initialise(channels, stepSize, blockSize);
}
PluginChannelAdapter::FeatureSet
PluginChannelAdapter::process(const float *const *inputBuffers,
RealTime timestamp)
{
return m_impl->process(inputBuffers, timestamp);
}
PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
m_plugin(plugin),
m_blockSize(0),
m_inputChannels(0),
m_pluginChannels(0),
m_buffer(0),
m_forwardPtrs(0)
{
}
PluginChannelAdapter::Impl::~Impl()
{
// the adapter will delete the plugin
if (m_buffer) {
if (m_inputChannels > m_pluginChannels) {
delete[] m_buffer[0];
} else {
for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) {
delete[] m_buffer[i];
}
}
delete[] m_buffer;
m_buffer = 0;
}
if (m_forwardPtrs) {
delete[] m_forwardPtrs;
m_forwardPtrs = 0;
}
}
bool
PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
m_blockSize = blockSize;
size_t minch = m_plugin->getMinChannelCount();
size_t maxch = m_plugin->getMaxChannelCount();
m_inputChannels = channels;
if (m_inputChannels < minch) {
m_forwardPtrs = new const float *[minch];
if (m_inputChannels > 1) {
// We need a set of zero-valued buffers to add to the
// forwarded pointers
m_buffer = new float*[minch - channels];
for (size_t i = 0; i < minch; ++i) {
m_buffer[i] = new float[blockSize];
for (size_t j = 0; j < blockSize; ++j) {
m_buffer[i][j] = 0.f;
}
}
}
m_pluginChannels = minch;
std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
} else if (m_inputChannels > maxch) {
// We only need m_buffer if we are mixing down to a single
// channel -- otherwise we can just forward the same float* as
// passed in to process(), expecting the excess to be ignored
if (maxch == 1) {
m_buffer = new float *[1];
m_buffer[0] = new float[blockSize];
std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
} else {
std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
}
m_pluginChannels = maxch;
} else {
std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
m_pluginChannels = m_inputChannels;
}
return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
}
PluginChannelAdapter::FeatureSet
PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
RealTime timestamp)
{
// std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl;
if (m_inputChannels < m_pluginChannels) {
if (m_inputChannels == 1) {
for (size_t i = 0; i < m_pluginChannels; ++i) {
m_forwardPtrs[i] = inputBuffers[0];
}
} else {
for (size_t i = 0; i < m_inputChannels; ++i) {
m_forwardPtrs[i] = inputBuffers[i];
}
for (size_t i = m_inputChannels; i < m_pluginChannels; ++i) {
m_forwardPtrs[i] = m_buffer[i - m_inputChannels];
}
}
return m_plugin->process(m_forwardPtrs, timestamp);
} else if (m_inputChannels > m_pluginChannels) {
if (m_pluginChannels == 1) {
for (size_t j = 0; j < m_blockSize; ++j) {
m_buffer[0][j] = inputBuffers[0][j];
}
for (size_t i = 1; i < m_inputChannels; ++i) {
for (size_t j = 0; j < m_blockSize; ++j) {
m_buffer[0][j] += inputBuffers[i][j];
}
}
for (size_t j = 0; j < m_blockSize; ++j) {
m_buffer[0][j] /= m_inputChannels;
}
return m_plugin->process(m_buffer, timestamp);
} else {
return m_plugin->process(inputBuffers, timestamp);
}
} else {
return m_plugin->process(inputBuffers, timestamp);
}
}
}
}

View file

@ -0,0 +1,128 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
#define _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
#include "PluginWrapper.h"
namespace Vamp {
namespace HostExt {
/**
* \class PluginChannelAdapter PluginChannelAdapter.h <vamp-sdk/hostext/PluginChannelAdapter.h>
*
* PluginChannelAdapter is a Vamp plugin adapter that implements a
* policy for management of plugins that expect a different number of
* input channels from the number actually available in the source
* audio data.
*
* A host using PluginChannelAdapter may ignore the getMinChannelCount
* and getMaxChannelCount reported by the plugin, and still expect the
* plugin to run.
*
* PluginChannelAdapter implements the following policy:
*
* - If the plugin supports the provided number of channels directly,
* PluginChannelAdapter will just run the plugin as normal.
*
* - If the plugin only supports exactly one channel but more than
* one channel is provided, PluginChannelAdapter will use the mean of
* the channels. This ensures that the resulting values remain
* within the same magnitude range as expected for mono data.
*
* - If the plugin requires more than one channel but exactly one is
* provided, the provided channel will be duplicated across all the
* plugin input channels.
*
* If none of the above apply:
*
* - If the plugin requires more channels than are provided, the
* minimum acceptable number of channels will be produced by adding
* empty (zero valued) channels to those provided.
*
* - If the plugin requires fewer channels than are provided, the
* maximum acceptable number of channels will be produced by
* discarding the excess channels.
*
* Hosts requiring a different channel policy from the above will need
* to implement it themselves, instead of using PluginChannelAdapter.
*
* Note that PluginChannelAdapter does not override the minimum and
* maximum channel counts returned by the wrapped plugin. The host
* will need to be aware that it is using a PluginChannelAdapter, and
* be prepared to ignore these counts as necessary. (This contrasts
* with the approach used in PluginInputDomainAdapter, which aims to
* make the host completely unaware of which underlying input domain
* is in fact in use.)
*
* (The rationale for this is that a host may wish to use the
* PluginChannelAdapter but still discriminate in some way on the
* basis of the number of channels actually supported. For example, a
* simple stereo audio host may prefer to reject plugins that require
* more than two channels on the grounds that doesn't actually
* understand what they are for, rather than allow the channel adapter
* to make a potentially meaningless channel conversion for them.)
*
* In every respect other than its management of channels, the
* PluginChannelAdapter behaves identically to the plugin that it
* wraps. The wrapped plugin will be deleted when the wrapper is
* deleted.
*
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
*/
class PluginChannelAdapter : public PluginWrapper
{
public:
PluginChannelAdapter(Plugin *plugin); // I take ownership of plugin
virtual ~PluginChannelAdapter();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
protected:
class Impl;
Impl *m_impl;
};
}
}
#endif

View file

@ -0,0 +1,458 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#include "PluginInputDomainAdapter.h"
#include <cmath>
namespace Vamp {
namespace HostExt {
class PluginInputDomainAdapter::Impl
{
public:
Impl(Plugin *plugin, float inputSampleRate);
~Impl();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
size_t getPreferredStepSize() const;
size_t getPreferredBlockSize() const;
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
protected:
Plugin *m_plugin;
float m_inputSampleRate;
size_t m_channels;
size_t m_blockSize;
float **m_freqbuf;
double *m_ri;
double *m_ro;
double *m_io;
void fft(unsigned int n, bool inverse,
double *ri, double *ii, double *ro, double *io);
size_t makeBlockSizeAcceptable(size_t) const;
};
PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
PluginWrapper(plugin)
{
m_impl = new Impl(plugin, m_inputSampleRate);
}
PluginInputDomainAdapter::~PluginInputDomainAdapter()
{
delete m_impl;
}
bool
PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
return m_impl->initialise(channels, stepSize, blockSize);
}
Plugin::InputDomain
PluginInputDomainAdapter::getInputDomain() const
{
return TimeDomain;
}
size_t
PluginInputDomainAdapter::getPreferredStepSize() const
{
return m_impl->getPreferredStepSize();
}
size_t
PluginInputDomainAdapter::getPreferredBlockSize() const
{
return m_impl->getPreferredBlockSize();
}
Plugin::FeatureSet
PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
{
return m_impl->process(inputBuffers, timestamp);
}
PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
m_plugin(plugin),
m_inputSampleRate(inputSampleRate),
m_channels(0),
m_blockSize(0),
m_freqbuf(0)
{
}
PluginInputDomainAdapter::Impl::~Impl()
{
// the adapter will delete the plugin
if (m_channels > 0) {
for (size_t c = 0; c < m_channels; ++c) {
delete[] m_freqbuf[c];
}
delete[] m_freqbuf;
delete[] m_ri;
delete[] m_ro;
delete[] m_io;
}
}
bool
PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
if (m_plugin->getInputDomain() == TimeDomain) {
m_blockSize = blockSize;
m_channels = channels;
return m_plugin->initialise(channels, stepSize, blockSize);
}
if (blockSize < 2) {
std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not supported" << std::endl;
return false;
}
if (blockSize & (blockSize-1)) {
std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
return false;
}
if (m_channels > 0) {
for (size_t c = 0; c < m_channels; ++c) {
delete[] m_freqbuf[c];
}
delete[] m_freqbuf;
delete[] m_ri;
delete[] m_ro;
delete[] m_io;
}
m_blockSize = blockSize;
m_channels = channels;
m_freqbuf = new float *[m_channels];
for (size_t c = 0; c < m_channels; ++c) {
m_freqbuf[c] = new float[m_blockSize + 2];
}
m_ri = new double[m_blockSize];
m_ro = new double[m_blockSize];
m_io = new double[m_blockSize];
return m_plugin->initialise(channels, stepSize, blockSize);
}
size_t
PluginInputDomainAdapter::Impl::getPreferredStepSize() const
{
size_t step = m_plugin->getPreferredStepSize();
if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
step = getPreferredBlockSize() / 2;
}
return step;
}
size_t
PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
{
size_t block = m_plugin->getPreferredBlockSize();
if (m_plugin->getInputDomain() == FrequencyDomain) {
if (block == 0) {
block = 1024;
} else {
block = makeBlockSizeAcceptable(block);
}
}
return block;
}
size_t
PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
{
if (blockSize < 2) {
std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not" << std::endl
<< "supported, increasing from " << blockSize << " to 2" << std::endl;
blockSize = 2;
} else if (blockSize & (blockSize-1)) {
// not a power of two, can't handle that with our current fft
// implementation
size_t nearest = blockSize;
size_t power = 0;
while (nearest > 1) {
nearest >>= 1;
++power;
}
nearest = 1;
while (power) {
nearest <<= 1;
--power;
}
if (blockSize - nearest > (nearest*2) - blockSize) {
nearest = nearest*2;
}
std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
blockSize = nearest;
}
return blockSize;
}
// for some visual studii apparently
#ifndef M_PI
#define M_PI 3.14159265358979232846
#endif
Plugin::FeatureSet
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
RealTime timestamp)
{
if (m_plugin->getInputDomain() == TimeDomain) {
return m_plugin->process(inputBuffers, timestamp);
}
// The timestamp supplied should be (according to the Vamp::Plugin
// spec) the time of the start of the time-domain input block.
// However, we want to pass to the plugin an FFT output calculated
// from the block of samples _centred_ on that timestamp.
//
// We have two options:
//
// 1. Buffer the input, calculating the fft of the values at the
// passed-in block minus blockSize/2 rather than starting at the
// passed-in block. So each time we call process on the plugin,
// we are passing in the same timestamp as was passed to our own
// process plugin, but not (the frequency domain representation
// of) the same set of samples. Advantages: avoids confusion in
// the host by ensuring the returned values have timestamps
// comparable with that passed in to this function (in fact this
// is pretty much essential for one-value-per-block outputs);
// consistent with hosts such as SV that deal with the
// frequency-domain transform themselves. Disadvantages: means
// making the not necessarily correct assumption that the samples
// preceding the first official block are all zero (or some other
// known value).
//
// 2. Increase the passed-in timestamps by half the blocksize. So
// when we call process, we are passing in the frequency domain
// representation of the same set of samples as passed to us, but
// with a different timestamp. Advantages: simplicity; avoids
// iffy assumption mentioned above. Disadvantages: inconsistency
// with SV in cases where stepSize != blockSize/2; potential
// confusion arising from returned timestamps being calculated
// from the adjusted input timestamps rather than the original
// ones (and inaccuracy where the returned timestamp is implied,
// as in one-value-per-block).
//
// Neither way is ideal, but I don't think either is strictly
// incorrect either. I think this is just a case where the same
// plugin can legitimately produce differing results from the same
// input data, depending on how that data is packaged.
//
// We'll go for option 2, adjusting the timestamps. Note in
// particular that this means some results can differ from those
// produced by SV.
// std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
timestamp = timestamp + RealTime::frame2RealTime
(m_blockSize/2, int(m_inputSampleRate + 0.5));
// std::cerr << " to " << timestamp << std::endl;
for (size_t c = 0; c < m_channels; ++c) {
for (size_t i = 0; i < m_blockSize; ++i) {
// Hanning window
m_ri[i] = double(inputBuffers[c][i])
* (0.50 - 0.50 * cos((2 * M_PI * i)
/ m_blockSize));
}
for (size_t i = 0; i < m_blockSize/2; ++i) {
// FFT shift
double value = m_ri[i];
m_ri[i] = m_ri[i + m_blockSize/2];
m_ri[i + m_blockSize/2] = value;
}
fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
for (size_t i = 0; i <= m_blockSize/2; ++i) {
m_freqbuf[c][i * 2] = m_ro[i];
m_freqbuf[c][i * 2 + 1] = m_io[i];
}
}
return m_plugin->process(m_freqbuf, timestamp);
}
void
PluginInputDomainAdapter::Impl::fft(unsigned int n, bool inverse,
double *ri, double *ii, double *ro, double *io)
{
if (!ri || !ro || !io) return;
unsigned int bits;
unsigned int i, j, k, m;
unsigned int blockSize, blockEnd;
double tr, ti;
if (n < 2) return;
if (n & (n-1)) return;
double angle = 2.0 * M_PI;
if (inverse) angle = -angle;
for (i = 0; ; ++i) {
if (n & (1 << i)) {
bits = i;
break;
}
}
static unsigned int tableSize = 0;
static int *table = 0;
if (tableSize != n) {
delete[] table;
table = new int[n];
for (i = 0; i < n; ++i) {
m = i;
for (j = k = 0; j < bits; ++j) {
k = (k << 1) | (m & 1);
m >>= 1;
}
table[i] = k;
}
tableSize = n;
}
if (ii) {
for (i = 0; i < n; ++i) {
ro[table[i]] = ri[i];
io[table[i]] = ii[i];
}
} else {
for (i = 0; i < n; ++i) {
ro[table[i]] = ri[i];
io[table[i]] = 0.0;
}
}
blockEnd = 1;
for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
double delta = angle / (double)blockSize;
double sm2 = -sin(-2 * delta);
double sm1 = -sin(-delta);
double cm2 = cos(-2 * delta);
double cm1 = cos(-delta);
double w = 2 * cm1;
double ar[3], ai[3];
for (i = 0; i < n; i += blockSize) {
ar[2] = cm2;
ar[1] = cm1;
ai[2] = sm2;
ai[1] = sm1;
for (j = i, m = 0; m < blockEnd; j++, m++) {
ar[0] = w * ar[1] - ar[2];
ar[2] = ar[1];
ar[1] = ar[0];
ai[0] = w * ai[1] - ai[2];
ai[2] = ai[1];
ai[1] = ai[0];
k = j + blockEnd;
tr = ar[0] * ro[k] - ai[0] * io[k];
ti = ar[0] * io[k] + ai[0] * ro[k];
ro[k] = ro[j] - tr;
io[k] = io[j] - ti;
ro[j] += tr;
io[j] += ti;
}
}
blockEnd = blockSize;
}
if (inverse) {
double denom = (double)n;
for (i = 0; i < n; i++) {
ro[i] /= denom;
io[i] /= denom;
}
}
}
}
}

View file

@ -0,0 +1,103 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
#define _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
#include "PluginWrapper.h"
namespace Vamp {
namespace HostExt {
/**
* \class PluginInputDomainAdapter PluginInputDomainAdapter.h <vamp-sdk/hostext/PluginInputDomainAdapter.h>
*
* PluginInputDomainAdapter is a Vamp plugin adapter that converts
* time-domain input into frequency-domain input for plugins that need
* it. This permits a host to use time- and frequency-domain plugins
* interchangeably without needing to handle the conversion itself.
*
* This adapter uses a basic Hanning windowed FFT that supports
* power-of-two block sizes only. If a frequency domain plugin
* requests a non-power-of-two blocksize, the adapter will adjust it
* to a nearby power of two instead. Thus, getPreferredBlockSize()
* will always return a power of two if the wrapped plugin is a
* frequency domain one. If the plugin doesn't accept the adjusted
* power of two block size, initialise() will fail.
*
* The adapter provides no way for the host to discover whether the
* underlying plugin is actually a time or frequency domain plugin
* (except that if the preferred block size is not a power of two, it
* must be a time domain plugin).
*
* The FFT implementation is simple and self-contained, but unlikely
* to be the fastest available: a host can usually do better if it
* cares enough.
*
* In every respect other than its input domain handling, the
* PluginInputDomainAdapter behaves identically to the plugin that it
* wraps. The wrapped plugin will be deleted when the wrapper is
* deleted.
*
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
*/
class PluginInputDomainAdapter : public PluginWrapper
{
public:
PluginInputDomainAdapter(Plugin *plugin); // I take ownership of plugin
virtual ~PluginInputDomainAdapter();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
InputDomain getInputDomain() const;
size_t getPreferredStepSize() const;
size_t getPreferredBlockSize() const;
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
protected:
class Impl;
Impl *m_impl;
};
}
}
#endif

View file

@ -0,0 +1,601 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#include "vamp-sdk/PluginHostAdapter.h"
#include "PluginLoader.h"
#include "PluginInputDomainAdapter.h"
#include "PluginChannelAdapter.h"
#include <fstream>
#include <cctype> // tolower
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#define PLUGIN_SUFFIX "dll"
#else /* ! _WIN32 */
#include <dirent.h>
#include <dlfcn.h>
#ifdef __APPLE__
#define PLUGIN_SUFFIX "dylib"
#else /* ! __APPLE__ */
#define PLUGIN_SUFFIX "so"
#endif /* ! __APPLE__ */
#endif /* ! _WIN32 */
using namespace std;
namespace Vamp {
namespace HostExt {
class PluginLoader::Impl
{
public:
Impl();
virtual ~Impl();
PluginKeyList listPlugins();
Plugin *loadPlugin(PluginKey key,
float inputSampleRate,
int adapterFlags);
PluginKey composePluginKey(string libraryName, string identifier);
PluginCategoryHierarchy getPluginCategory(PluginKey key);
string getLibraryPathForPlugin(PluginKey key);
protected:
class PluginDeletionNotifyAdapter : public PluginWrapper {
public:
PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
virtual ~PluginDeletionNotifyAdapter();
protected:
Impl *m_loader;
};
virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
map<PluginKey, string> m_pluginLibraryNameMap;
bool m_allPluginsEnumerated;
void enumeratePlugins(PluginKey forPlugin = "");
map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
void generateTaxonomy();
map<Plugin *, void *> m_pluginLibraryHandleMap;
bool decomposePluginKey(PluginKey key,
string &libraryName, string &identifier);
void *loadLibrary(string path);
void unloadLibrary(void *handle);
void *lookupInLibrary(void *handle, const char *symbol);
string splicePath(string a, string b);
vector<string> listFiles(string dir, string ext);
};
PluginLoader *
PluginLoader::m_instance = 0;
PluginLoader::PluginLoader()
{
m_impl = new Impl();
}
PluginLoader::~PluginLoader()
{
delete m_impl;
}
PluginLoader *
PluginLoader::getInstance()
{
if (!m_instance) m_instance = new PluginLoader();
return m_instance;
}
vector<PluginLoader::PluginKey>
PluginLoader::listPlugins()
{
return m_impl->listPlugins();
}
Plugin *
PluginLoader::loadPlugin(PluginKey key,
float inputSampleRate,
int adapterFlags)
{
return m_impl->loadPlugin(key, inputSampleRate, adapterFlags);
}
PluginLoader::PluginKey
PluginLoader::composePluginKey(string libraryName, string identifier)
{
return m_impl->composePluginKey(libraryName, identifier);
}
PluginLoader::PluginCategoryHierarchy
PluginLoader::getPluginCategory(PluginKey key)
{
return m_impl->getPluginCategory(key);
}
string
PluginLoader::getLibraryPathForPlugin(PluginKey key)
{
return m_impl->getLibraryPathForPlugin(key);
}
PluginLoader::Impl::Impl() :
m_allPluginsEnumerated(false)
{
}
PluginLoader::Impl::~Impl()
{
}
vector<PluginLoader::PluginKey>
PluginLoader::Impl::listPlugins()
{
if (!m_allPluginsEnumerated) enumeratePlugins();
vector<PluginKey> plugins;
for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
mi != m_pluginLibraryNameMap.end(); ++mi) {
plugins.push_back(mi->first);
}
return plugins;
}
void
PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
{
vector<string> path = PluginHostAdapter::getPluginPath();
string libraryName, identifier;
if (forPlugin != "") {
if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
<< forPlugin << "\" in enumerate" << std::endl;
return;
}
}
for (size_t i = 0; i < path.size(); ++i) {
vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
for (vector<string>::iterator fi = files.begin();
fi != files.end(); ++fi) {
if (libraryName != "") {
// libraryName is lowercased and lacking an extension,
// as it came from the plugin key
string temp = *fi;
for (size_t i = 0; i < temp.length(); ++i) {
temp[i] = tolower(temp[i]);
}
string::size_type pi = temp.find('.');
if (pi == string::npos) {
if (libraryName != temp) continue;
} else {
if (libraryName != temp.substr(0, pi)) continue;
}
}
string fullPath = path[i];
fullPath = splicePath(fullPath, *fi);
void *handle = loadLibrary(fullPath);
if (!handle) continue;
VampGetPluginDescriptorFunction fn =
(VampGetPluginDescriptorFunction)lookupInLibrary
(handle, "vampGetPluginDescriptor");
if (!fn) {
unloadLibrary(handle);
continue;
}
int index = 0;
const VampPluginDescriptor *descriptor = 0;
while ((descriptor = fn(VAMP_API_VERSION, index))) {
++index;
if (identifier != "") {
if (descriptor->identifier != identifier) continue;
}
PluginKey key = composePluginKey(*fi, descriptor->identifier);
// std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
if (m_pluginLibraryNameMap.find(key) ==
m_pluginLibraryNameMap.end()) {
m_pluginLibraryNameMap[key] = fullPath;
}
}
unloadLibrary(handle);
}
}
if (forPlugin == "") m_allPluginsEnumerated = true;
}
PluginLoader::PluginKey
PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
{
string basename = libraryName;
string::size_type li = basename.rfind('/');
if (li != string::npos) basename = basename.substr(li + 1);
li = basename.find('.');
if (li != string::npos) basename = basename.substr(0, li);
for (size_t i = 0; i < basename.length(); ++i) {
basename[i] = tolower(basename[i]);
}
return basename + ":" + identifier;
}
bool
PluginLoader::Impl::decomposePluginKey(PluginKey key,
string &libraryName,
string &identifier)
{
string::size_type ki = key.find(':');
if (ki == string::npos) {
return false;
}
libraryName = key.substr(0, ki);
identifier = key.substr(ki + 1);
return true;
}
PluginLoader::PluginCategoryHierarchy
PluginLoader::Impl::getPluginCategory(PluginKey plugin)
{
if (m_taxonomy.empty()) generateTaxonomy();
if (m_taxonomy.find(plugin) == m_taxonomy.end()) {
return PluginCategoryHierarchy();
}
return m_taxonomy[plugin];
}
string
PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
{
if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
if (m_allPluginsEnumerated) return "";
enumeratePlugins(plugin);
}
if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
return "";
}
return m_pluginLibraryNameMap[plugin];
}
Plugin *
PluginLoader::Impl::loadPlugin(PluginKey key,
float inputSampleRate, int adapterFlags)
{
string libname, identifier;
if (!decomposePluginKey(key, libname, identifier)) {
std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
<< key << "\" in loadPlugin" << std::endl;
return 0;
}
string fullPath = getLibraryPathForPlugin(key);
if (fullPath == "") return 0;
void *handle = loadLibrary(fullPath);
if (!handle) return 0;
VampGetPluginDescriptorFunction fn =
(VampGetPluginDescriptorFunction)lookupInLibrary
(handle, "vampGetPluginDescriptor");
if (!fn) {
unloadLibrary(handle);
return 0;
}
int index = 0;
const VampPluginDescriptor *descriptor = 0;
while ((descriptor = fn(VAMP_API_VERSION, index))) {
if (string(descriptor->identifier) == identifier) {
Vamp::PluginHostAdapter *plugin =
new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this);
m_pluginLibraryHandleMap[adapter] = handle;
if (adapterFlags & ADAPT_INPUT_DOMAIN) {
if (adapter->getInputDomain() == Plugin::FrequencyDomain) {
adapter = new PluginInputDomainAdapter(adapter);
}
}
if (adapterFlags & ADAPT_CHANNEL_COUNT) {
adapter = new PluginChannelAdapter(adapter);
}
return adapter;
}
++index;
}
cerr << "Vamp::HostExt::PluginLoader: Plugin \""
<< identifier << "\" not found in library \""
<< fullPath << "\"" << endl;
return 0;
}
void
PluginLoader::Impl::generateTaxonomy()
{
// cerr << "PluginLoader::Impl::generateTaxonomy" << endl;
vector<string> path = PluginHostAdapter::getPluginPath();
string libfragment = "/lib/";
vector<string> catpath;
string suffix = "cat";
for (vector<string>::iterator i = path.begin();
i != path.end(); ++i) {
// It doesn't matter that we're using literal forward-slash in
// this bit, as it's only relevant if the path contains
// "/lib/", which is only meaningful and only plausible on
// systems with forward-slash delimiters
string dir = *i;
string::size_type li = dir.find(libfragment);
if (li != string::npos) {
catpath.push_back
(dir.substr(0, li)
+ "/share/"
+ dir.substr(li + libfragment.length()));
}
catpath.push_back(dir);
}
char buffer[1024];
for (vector<string>::iterator i = catpath.begin();
i != catpath.end(); ++i) {
vector<string> files = listFiles(*i, suffix);
for (vector<string>::iterator fi = files.begin();
fi != files.end(); ++fi) {
string filepath = splicePath(*i, *fi);
ifstream is(filepath.c_str(), ifstream::in | ifstream::binary);
if (is.fail()) {
// cerr << "failed to open: " << filepath << endl;
continue;
}
// cerr << "opened: " << filepath << endl;
while (!!is.getline(buffer, 1024)) {
string line(buffer);
// cerr << "line = " << line << endl;
string::size_type di = line.find("::");
if (di == string::npos) continue;
string id = line.substr(0, di);
string encodedCat = line.substr(di + 2);
if (id.substr(0, 5) != "vamp:") continue;
id = id.substr(5);
while (encodedCat.length() >= 1 &&
encodedCat[encodedCat.length()-1] == '\r') {
encodedCat = encodedCat.substr(0, encodedCat.length()-1);
}
// cerr << "id = " << id << ", cat = " << encodedCat << endl;
PluginCategoryHierarchy category;
string::size_type ai;
while ((ai = encodedCat.find(" > ")) != string::npos) {
category.push_back(encodedCat.substr(0, ai));
encodedCat = encodedCat.substr(ai + 3);
}
if (encodedCat != "") category.push_back(encodedCat);
m_taxonomy[id] = category;
}
}
}
}
void *
PluginLoader::Impl::loadLibrary(string path)
{
void *handle = 0;
#ifdef _WIN32
handle = LoadLibrary(path.c_str());
if (!handle) {
cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
<< path << "\"" << endl;
}
#else
handle = dlopen(path.c_str(), RTLD_LAZY);
if (!handle) {
cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
<< path << "\": " << dlerror() << endl;
}
#endif
return handle;
}
void
PluginLoader::Impl::unloadLibrary(void *handle)
{
#ifdef _WIN32
FreeLibrary((HINSTANCE)handle);
#else
dlclose(handle);
#endif
}
void *
PluginLoader::Impl::lookupInLibrary(void *handle, const char *symbol)
{
#ifdef _WIN32
return (void *)GetProcAddress((HINSTANCE)handle, symbol);
#else
return (void *)dlsym(handle, symbol);
#endif
}
string
PluginLoader::Impl::splicePath(string a, string b)
{
#ifdef _WIN32
return a + "\\" + b;
#else
return a + "/" + b;
#endif
}
vector<string>
PluginLoader::Impl::listFiles(string dir, string extension)
{
vector<string> files;
#ifdef _WIN32
string expression = dir + "\\*." + extension;
WIN32_FIND_DATA data;
HANDLE fh = FindFirstFile(expression.c_str(), &data);
if (fh == INVALID_HANDLE_VALUE) return files;
bool ok = true;
while (ok) {
files.push_back(data.cFileName);
ok = FindNextFile(fh, &data);
}
FindClose(fh);
#else
size_t extlen = extension.length();
DIR *d = opendir(dir.c_str());
if (!d) return files;
struct dirent *e = 0;
while ((e = readdir(d))) {
if (!(e->d_type & DT_REG) || !e->d_name) continue;
size_t len = strlen(e->d_name);
if (len < extlen + 2 ||
e->d_name + len - extlen - 1 != "." + extension) {
continue;
}
files.push_back(e->d_name);
}
closedir(d);
#endif
return files;
}
void
PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter)
{
void *handle = m_pluginLibraryHandleMap[adapter];
if (handle) unloadLibrary(handle);
m_pluginLibraryHandleMap.erase(adapter);
}
PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin,
Impl *loader) :
PluginWrapper(plugin),
m_loader(loader)
{
}
PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
{
// We need to delete the plugin before calling pluginDeleted, as
// the delete call may require calling through to the descriptor
// (for e.g. cleanup) but pluginDeleted may unload the required
// library for the call. To prevent a double deletion when our
// parent's destructor runs (after this one), be sure to set
// m_plugin to 0 after deletion.
delete m_plugin;
m_plugin = 0;
if (m_loader) m_loader->pluginDeleted(this);
}
}
}

View file

@ -0,0 +1,218 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_LOADER_H_
#define _VAMP_PLUGIN_LOADER_H_
#include <vector>
#include <string>
#include <map>
#include "PluginWrapper.h"
namespace Vamp {
class Plugin;
namespace HostExt {
/**
* \class PluginLoader PluginLoader.h <vamp-sdk/hostext/PluginLoader.h>
*
* Vamp::HostExt::PluginLoader is a convenience class for discovering
* and loading Vamp plugins using the typical plugin-path, library
* naming, and categorisation conventions described in the Vamp SDK
* documentation. This class is intended to greatly simplify the task
* of becoming a Vamp plugin host for any C++ application.
*
* Hosts are not required by the Vamp specification to use the same
* plugin search path and naming conventions as implemented by this
* class, and are certainly not required to use this actual class.
* But we do strongly recommend it.
*
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
*/
class PluginLoader
{
public:
/**
* Obtain a pointer to the singleton instance of PluginLoader.
* Use this to obtain your loader object.
*/
static PluginLoader *getInstance();
/**
* PluginKey is a string type that is used to identify a plugin
* uniquely within the scope of "the current system". It consists
* of the lower-cased base name of the plugin library, a colon
* separator, and the identifier string for the plugin. It is
* only meaningful in the context of a given plugin path (the one
* returned by PluginHostAdapter::getPluginPath()).
*
* Use composePluginKey() to construct a plugin key from a known
* plugin library name and identifier.
*
* Note: the fact that the library component of the key is
* lower-cased implies that library names are matched
* case-insensitively by the PluginLoader class, regardless of the
* case sensitivity of the underlying filesystem. (Plugin
* identifiers _are_ case sensitive, however.) Also, it is not
* possible to portably extract a working library name from a
* plugin key, as the result may fail on case-sensitive
* filesystems. Use getLibraryPathForPlugin() instead.
*/
typedef std::string PluginKey;
/**
* PluginKeyList is a sequence of plugin keys, such as returned by
* listPlugins().
*/
typedef std::vector<PluginKey> PluginKeyList;
/**
* PluginCategoryHierarchy is a sequence of general->specific
* category names, as may be associated with a single plugin.
* This sequence describes the location of a plugin within a
* category forest, containing the human-readable names of the
* plugin's category tree root, followed by each of the nodes down
* to the leaf containing the plugin.
*
* \see getPluginCategory()
*/
typedef std::vector<std::string> PluginCategoryHierarchy;
/**
* Search for all available Vamp plugins, and return a list of
* them in the order in which they were found.
*/
PluginKeyList listPlugins();
/**
* AdapterFlags contains a set of values that may be OR'd together
* to indicate in which circumstances PluginLoader should use a
* plugin adapter to make a plugin easier to use for a host that
* does not want to cater for complex features.
*
* The available flags are:
*
* ADAPT_INPUT_DOMAIN - If the plugin expects frequency domain
* input, wrap it in a PluginInputDomainAdapter that automatically
* converts the plugin to one that expects time-domain input.
* This enables a host to accommodate time- and frequency-domain
* plugins without needing to do any conversion itself.
*
* ADAPT_CHANNEL_COUNT - Wrap the plugin in a PluginChannelAdapter
* to handle any mismatch between the number of channels of audio
* the plugin can handle and the number available in the host.
* This enables a host to use plugins that may require the input
* to be mixed down to mono, etc., without having to worry about
* doing that itself.
*
* ADAPT_ALL - Perform all available adaptations, where meaningful.
*
* See PluginInputDomainAdapter and PluginChannelAdapter for more
* details of the classes that the loader may use if these flags
* are set.
*/
enum AdapterFlags {
ADAPT_INPUT_DOMAIN = 0x01,
ADAPT_CHANNEL_COUNT = 0x02,
ADAPT_ALL = 0xff
};
/**
* Load a Vamp plugin, given its identifying key. If the plugin
* could not be loaded, returns 0.
*
* The returned plugin should be deleted (using the standard C++
* delete keyword) after use.
*
* \param adapterFlags a bitwise OR of the values in the AdapterFlags
* enumeration, indicating under which circumstances an adapter should be
* used to wrap the original plugin. If adapterFlags is 0, no
* optional adapters will be used. Otherwise, the returned plugin
* may be of an adapter class type which will behave identically
* to the original plugin, apart from any particular features
* implemented by the adapter itself.
*
* \see AdapterFlags, PluginInputDomainAdapter, PluginChannelAdapter
*/
Plugin *loadPlugin(PluginKey key,
float inputSampleRate,
int adapterFlags = 0);
/**
* Given a Vamp plugin library name and plugin identifier, return
* the corresponding plugin key in a form suitable for passing in to
* loadPlugin().
*/
PluginKey composePluginKey(std::string libraryName,
std::string identifier);
/**
* Return the category hierarchy for a Vamp plugin, given its
* identifying key.
*
* If the plugin has no category information, return an empty
* hierarchy.
*
* \see PluginCategoryHierarchy
*/
PluginCategoryHierarchy getPluginCategory(PluginKey plugin);
/**
* Return the file path of the dynamic library from which the
* given plugin will be loaded (if available).
*/
std::string getLibraryPathForPlugin(PluginKey plugin);
protected:
PluginLoader();
virtual ~PluginLoader();
class Impl;
Impl *m_impl;
static PluginLoader *m_instance;
};
}
}
#endif

View file

@ -0,0 +1,201 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#include "PluginWrapper.h"
namespace Vamp {
namespace HostExt {
class PluginRateExtractor : public Plugin
{
public:
PluginRateExtractor() : Plugin(0) { }
float getRate() const { return m_inputSampleRate; }
};
PluginWrapper::PluginWrapper(Plugin *plugin) :
Plugin(((PluginRateExtractor *)plugin)->getRate()),
m_plugin(plugin)
{
}
PluginWrapper::~PluginWrapper()
{
delete m_plugin;
}
bool
PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
return m_plugin->initialise(channels, stepSize, blockSize);
}
void
PluginWrapper::reset()
{
m_plugin->reset();
}
Plugin::InputDomain
PluginWrapper::getInputDomain() const
{
return m_plugin->getInputDomain();
}
unsigned int
PluginWrapper::getVampApiVersion() const
{
return m_plugin->getVampApiVersion();
}
std::string
PluginWrapper::getIdentifier() const
{
return m_plugin->getIdentifier();
}
std::string
PluginWrapper::getName() const
{
return m_plugin->getName();
}
std::string
PluginWrapper::getDescription() const
{
return m_plugin->getDescription();
}
std::string
PluginWrapper::getMaker() const
{
return m_plugin->getMaker();
}
int
PluginWrapper::getPluginVersion() const
{
return m_plugin->getPluginVersion();
}
std::string
PluginWrapper::getCopyright() const
{
return m_plugin->getCopyright();
}
PluginBase::ParameterList
PluginWrapper::getParameterDescriptors() const
{
return m_plugin->getParameterDescriptors();
}
float
PluginWrapper::getParameter(std::string parameter) const
{
return m_plugin->getParameter(parameter);
}
void
PluginWrapper::setParameter(std::string parameter, float value)
{
m_plugin->setParameter(parameter, value);
}
PluginBase::ProgramList
PluginWrapper::getPrograms() const
{
return m_plugin->getPrograms();
}
std::string
PluginWrapper::getCurrentProgram() const
{
return m_plugin->getCurrentProgram();
}
void
PluginWrapper::selectProgram(std::string program)
{
m_plugin->selectProgram(program);
}
size_t
PluginWrapper::getPreferredStepSize() const
{
return m_plugin->getPreferredStepSize();
}
size_t
PluginWrapper::getPreferredBlockSize() const
{
return m_plugin->getPreferredBlockSize();
}
size_t
PluginWrapper::getMinChannelCount() const
{
return m_plugin->getMinChannelCount();
}
size_t PluginWrapper::getMaxChannelCount() const
{
return m_plugin->getMaxChannelCount();
}
Plugin::OutputList
PluginWrapper::getOutputDescriptors() const
{
return m_plugin->getOutputDescriptors();
}
Plugin::FeatureSet
PluginWrapper::process(const float *const *inputBuffers, RealTime timestamp)
{
return m_plugin->process(inputBuffers, timestamp);
}
Plugin::FeatureSet
PluginWrapper::getRemainingFeatures()
{
return m_plugin->getRemainingFeatures();
}
}
}

View file

@ -0,0 +1,106 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _VAMP_PLUGIN_WRAPPER_H_
#define _VAMP_PLUGIN_WRAPPER_H_
#include <vamp-sdk/Plugin.h>
namespace Vamp {
namespace HostExt {
/**
* \class PluginWrapper PluginWrapper.h <vamp-sdk/hostext/PluginWrapper.h>
*
* PluginWrapper is a simple base class for adapter plugins. It takes
* a pointer to a "to be wrapped" Vamp plugin on construction, and
* provides implementations of all the Vamp plugin methods that simply
* delegate through to the wrapped plugin. A subclass can therefore
* override only the methods that are meaningful for the particular
* adapter.
*
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
*/
class PluginWrapper : public Plugin
{
public:
virtual ~PluginWrapper();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
void reset();
InputDomain getInputDomain() const;
unsigned int getVampApiVersion() const;
std::string getIdentifier() const;
std::string getName() const;
std::string getDescription() const;
std::string getMaker() const;
int getPluginVersion() const;
std::string getCopyright() const;
ParameterList getParameterDescriptors() const;
float getParameter(std::string) const;
void setParameter(std::string, float);
ProgramList getPrograms() const;
std::string getCurrentProgram() const;
void selectProgram(std::string);
size_t getPreferredStepSize() const;
size_t getPreferredBlockSize() const;
size_t getMinChannelCount() const;
size_t getMaxChannelCount() const;
OutputList getOutputDescriptors() const;
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
FeatureSet getRemainingFeatures();
protected:
PluginWrapper(Plugin *plugin); // I take ownership of plugin
Plugin *m_plugin;
};
}
}
#endif

View file

@ -0,0 +1,9 @@
dlname='%LINK_ABI%'
library_names='%LIBNAME% %LINK_ABI% %LINK_DEV%'
old_library='%STATIC%'
dependency_libs=''
current=2
age=0
revision=0
installed=yes
libdir='%LIBS%'

View file

@ -0,0 +1,9 @@
dlname='%LINK_ABI%'
library_names='%LIBNAME% %LINK_ABI% %LINK_DEV%'
old_library='%STATIC%'
dependency_libs=''
current=1
age=1
revision=0
installed=yes
libdir='%LIBS%'

339
libs/vamp-sdk/vamp/vamp.h Normal file
View file

@ -0,0 +1,339 @@
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Vamp
An API for audio analysis and feature extraction plugins.
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of the Centre for
Digital Music; Queen Mary, University of London; and Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef VAMP_HEADER_INCLUDED
#define VAMP_HEADER_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
/**
* Plugin API version. This is incremented when a change is made that
* changes the binary layout of the descriptor records. When this
* happens, there should be a mechanism for retaining compatibility
* with older hosts and/or plugins.
*
* See also the vampApiVersion field in the plugin descriptor, and the
* hostApiVersion argument to the vampGetPluginDescriptor function.
*/
#define VAMP_API_VERSION 1
/**
* C language API for Vamp plugins.
*
* This is the formal plugin API for Vamp. Plugin authors may prefer
* to use the C++ classes provided in the Vamp plugin SDK, instead of
* using this API directly. There is an adapter class provided that
* makes C++ plugins available using this C API with relatively little
* work, and the C++ headers are more thoroughly documented.
*
* IMPORTANT: The comments in this file summarise the purpose of each
* of the declared fields and functions, but do not provide a complete
* guide to their permitted values and expected usage. Please refer
* to the C++ headers in the Vamp plugin SDK for further details and
* plugin lifecycle documentation.
*/
typedef struct _VampParameterDescriptor
{
/** Computer-usable name of the parameter. Must not change. [a-zA-Z0-9_] */
const char *identifier;
/** Human-readable name of the parameter. May be translatable. */
const char *name;
/** Human-readable short text about the parameter. May be translatable. */
const char *description;
/** Human-readable unit of the parameter. */
const char *unit;
/** Minimum value. */
float minValue;
/** Maximum value. */
float maxValue;
/** Default value. Plugin is responsible for setting this on initialise. */
float defaultValue;
/** 1 if parameter values are quantized to a particular resolution. */
int isQuantized;
/** Quantization resolution, if isQuantized. */
float quantizeStep;
/** Human-readable names of the values, if isQuantized. May be NULL. */
const char **valueNames;
} VampParameterDescriptor;
typedef enum
{
/** Each process call returns results aligned with call's block start. */
vampOneSamplePerStep,
/** Returned results are evenly spaced at samplerate specified below. */
vampFixedSampleRate,
/** Returned results have their own individual timestamps. */
vampVariableSampleRate
} VampSampleType;
typedef struct _VampOutputDescriptor
{
/** Computer-usable name of the output. Must not change. [a-zA-Z0-9_] */
const char *identifier;
/** Human-readable name of the output. May be translatable. */
const char *name;
/** Human-readable short text about the output. May be translatable. */
const char *description;
/** Human-readable name of the unit of the output. */
const char *unit;
/** 1 if output has equal number of values for each returned result. */
int hasFixedBinCount;
/** Number of values per result, if hasFixedBinCount. */
unsigned int binCount;
/** Names of returned value bins, if hasFixedBinCount. May be NULL. */
const char **binNames;
/** 1 if each returned value falls within the same fixed min/max range. */
int hasKnownExtents;
/** Minimum value for a returned result in any bin, if hasKnownExtents. */
float minValue;
/** Maximum value for a returned result in any bin, if hasKnownExtents. */
float maxValue;
/** 1 if returned results are quantized to a particular resolution. */
int isQuantized;
/** Quantization resolution for returned results, if isQuantized. */
float quantizeStep;
/** Time positioning method for returned results (see VampSampleType). */
VampSampleType sampleType;
/** Sample rate of returned results, if sampleType is vampFixedSampleRate.
"Resolution" of result, if sampleType is vampVariableSampleRate. */
float sampleRate;
} VampOutputDescriptor;
typedef struct _VampFeature
{
/** 1 if the feature has a timestamp (i.e. if vampVariableSampleRate). */
int hasTimestamp;
/** Seconds component of timestamp. */
int sec;
/** Nanoseconds component of timestamp. */
int nsec;
/** Number of values. Must be binCount if hasFixedBinCount. */
unsigned int valueCount;
/** Values for this returned sample. */
float *values;
/** Label for this returned sample. May be NULL. */
char *label;
} VampFeature;
typedef struct _VampFeatureList
{
/** Number of features in this feature list. */
unsigned int featureCount;
/** Features in this feature list. May be NULL if featureCount is zero. */
VampFeature *features;
} VampFeatureList;
typedef enum
{
vampTimeDomain,
vampFrequencyDomain
} VampInputDomain;
typedef void *VampPluginHandle;
typedef struct _VampPluginDescriptor
{
/** API version with which this descriptor is compatible. */
unsigned int vampApiVersion;
/** Computer-usable name of the plugin. Must not change. [a-zA-Z0-9_] */
const char *identifier;
/** Human-readable name of the plugin. May be translatable. */
const char *name;
/** Human-readable short text about the plugin. May be translatable. */
const char *description;
/** Human-readable name of plugin's author or vendor. */
const char *maker;
/** Version number of the plugin. */
int pluginVersion;
/** Human-readable summary of copyright or licensing for plugin. */
const char *copyright;
/** Number of parameter inputs. */
unsigned int parameterCount;
/** Fixed descriptors for parameter inputs. */
const VampParameterDescriptor **parameters;
/** Number of programs. */
unsigned int programCount;
/** Fixed names for programs. */
const char **programs;
/** Preferred input domain for audio input (time or frequency). */
VampInputDomain inputDomain;
/** Create and return a new instance of this plugin. */
VampPluginHandle (*instantiate)(const struct _VampPluginDescriptor *,
float inputSampleRate);
/** Destroy an instance of this plugin. */
void (*cleanup)(VampPluginHandle);
/** Initialise an instance following parameter configuration. */
int (*initialise)(VampPluginHandle,
unsigned int inputChannels,
unsigned int stepSize,
unsigned int blockSize);
/** Reset an instance, ready to use again on new input data. */
void (*reset)(VampPluginHandle);
/** Get a parameter value. */
float (*getParameter)(VampPluginHandle, int);
/** Set a parameter value. May only be called before initialise. */
void (*setParameter)(VampPluginHandle, int, float);
/** Get the current program (if programCount > 0). */
unsigned int (*getCurrentProgram)(VampPluginHandle);
/** Set the current program. May only be called before initialise. */
void (*selectProgram)(VampPluginHandle, unsigned int);
/** Get the plugin's preferred processing window increment in samples. */
unsigned int (*getPreferredStepSize)(VampPluginHandle);
/** Get the plugin's preferred processing window size in samples. */
unsigned int (*getPreferredBlockSize)(VampPluginHandle);
/** Get the minimum number of input channels this plugin can handle. */
unsigned int (*getMinChannelCount)(VampPluginHandle);
/** Get the maximum number of input channels this plugin can handle. */
unsigned int (*getMaxChannelCount)(VampPluginHandle);
/** Get the number of feature outputs (distinct sets of results). */
unsigned int (*getOutputCount)(VampPluginHandle);
/** Get a descriptor for a given feature output. Returned pointer
is valid only until next call to getOutputDescriptor for this
handle, or releaseOutputDescriptor for this descriptor. Host
must call releaseOutputDescriptor after use. */
VampOutputDescriptor *(*getOutputDescriptor)(VampPluginHandle,
unsigned int);
/** Destroy a descriptor for a feature output. */
void (*releaseOutputDescriptor)(VampOutputDescriptor *);
/** Process an input block and return a set of features. Returned
pointer is valid only until next call to process,
getRemainingFeatures, or cleanup for this handle, or
releaseFeatureSet for this feature set. Host must call
releaseFeatureSet after use. */
VampFeatureList *(*process)(VampPluginHandle,
const float *const *inputBuffers,
int sec,
int nsec);
/** Return any remaining features at the end of processing. */
VampFeatureList *(*getRemainingFeatures)(VampPluginHandle);
/** Release a feature set returned from process or getRemainingFeatures. */
void (*releaseFeatureSet)(VampFeatureList *);
} VampPluginDescriptor;
/** Get the descriptor for a given plugin index in this library.
Return NULL if the index is outside the range of valid indices for
this plugin library.
The hostApiVersion argument tells the library code the highest
Vamp API version supported by the host. The function should
return a plugin descriptor compatible with the highest API version
supported by the library that is no higher than that supported by
the host. Provided the descriptor has the correct vampApiVersion
field for its actual compatibility level, the host should be able
to do the right thing with it: use it if possible, discard it
otherwise.
*/
const VampPluginDescriptor *vampGetPluginDescriptor
(unsigned int hostApiVersion, unsigned int index);
/** Function pointer type for vampGetPluginDescriptor. */
typedef const VampPluginDescriptor *(*VampGetPluginDescriptorFunction)
(unsigned int, unsigned int);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,10 @@
prefix=%PREFIX%
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: vamp
Version: 1.0
Description: An API for audio analysis and feature extraction plugins
Libs:
Cflags: -I${includedir}

View file

@ -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 = "2885"; static const char* ardour_svn_revision = "2884";
#endif #endif

View file

@ -1,260 +1,617 @@
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<Session version="0.821.0"> <Session version="2.0.0" id-counter="1191241714">
<Options> <Config>
<recording-plugins val="no"/> <Option name="output-auto-connect" value="2"/>
<slave type="none"/> <Option name="input-auto-connect" value="1"/>
<send-midi-timecode val="no"/> <Option name="mtc-port-name" value="control"/>
<send-midi-machine-control val="no"/> <Option name="mmc-port-name" value="control"/>
<input-auto-connect val="1"/> <Option name="midi-port-name" value="control"/>
<output-auto-connect val="2"/> <Option name="mmc-control" value="0"/>
<max-level val="0"/> <Option name="midi-feedback" value="0"/>
<min-level val="0"/> <Option name="xfade-model" value="0"/>
<meter-hold val="10.000000"/> <Option name="edit-mode" value="0"/>
<long-over-length val="10"/> <Option name="layer-model" value="0"/>
<short-over-length val="2"/> <Option name="solo-model" value="0"/>
<shuttle-speed-factor val="1.000000"/> <Option name="all-safe" value="0"/>
<shuttle-speed-threshold val="5.000000"/> <Option name="auto-play" value="0"/>
<rf-speed val="2.000000"/> <Option name="auto-return" value="0"/>
<smpte-frames-per-second val="30.000000"/> <Option name="auto-input" value="1"/>
<edit-mode val="slide"/> <Option name="punch-in" value="0"/>
<auto-play val="no"/> <Option name="punch-out" value="0"/>
<auto-input val="no"/> <Option name="seamless-loop" value="0"/>
<seamless-loop val="no"/> <Option name="rf-speed" value="2"/>
<punch-in val="no"/> <Option name="shuttle-speed-factor" value="1"/>
<punch-out val="no"/> <Option name="shuttle-speed-threshold" value="5"/>
<all-safe val="no"/> <Option name="meter-hold" value="10"/>
<auto-return val="no"/> <Option name="meter-falloff" value="1.5"/>
<mmc-control val="no"/> <end-marker-is-free val="no"/>
<recording-plugins val="no"/> </Config>
<auto-crossfade val="no"/>
<audible-click val="no"/>
<align-style val="existing"/>
</Options>
<Sources/> <Sources/>
<Regions/> <Regions/>
<DiskStreams> <DiskStreams>
<DiskStream channels="2" playlist="Audio 1.1" speed="1.000000" name="Audio 1" id="1088698381595945"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 1.1" speed="1" name="Audio 1" id="1088698381595945"/>
<DiskStream channels="2" playlist="Audio 2.1" speed="1.000000" name="Audio 2" id="1088698381722129"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 2.1" speed="1" name="Audio 2" id="1088698381722129"/>
<DiskStream channels="2" playlist="Audio 3.1" speed="1.000000" name="Audio 3" id="1088698419793849"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 3.1" speed="1" name="Audio 3" id="1088698419793849"/>
<DiskStream channels="2" playlist="Audio 4.1" speed="1.000000" name="Audio 4" id="1088698419943526"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 4.1" speed="1" name="Audio 4" id="1088698419943526"/>
<DiskStream channels="2" playlist="Audio 5.1" speed="1.000000" name="Audio 5" id="1088698450528071"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 5.1" speed="1" name="Audio 5" id="1088698450528071"/>
<DiskStream channels="2" playlist="Audio 6.1" speed="1.000000" name="Audio 6" id="1088698450754348"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 6.1" speed="1" name="Audio 6" id="1088698450754348"/>
<DiskStream channels="2" playlist="Audio 7.1" speed="1.000000" name="Audio 7" id="1088698450937150"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 7.1" speed="1" name="Audio 7" id="1088698450937150"/>
<DiskStream channels="2" playlist="Audio 8.1" speed="1.000000" name="Audio 8" id="1088698451167172"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 8.1" speed="1" name="Audio 8" id="1088698451167172"/>
<DiskStream channels="2" playlist="Audio 9.1" speed="1.000000" name="Audio 9" id="1088698483525991"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 9.1" speed="1" name="Audio 9" id="1088698483525991"/>
<DiskStream channels="2" playlist="Audio 10.1" speed="1.000000" name="Audio 10" id="1088698483801345"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 10.1" speed="1" name="Audio 10" id="1088698483801345"/>
<DiskStream channels="2" playlist="Audio 11.1" speed="1.000000" name="Audio 11" id="1088698484086727"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 11.1" speed="1" name="Audio 11" id="1088698484086727"/>
<DiskStream channels="2" playlist="Audio 12.1" speed="1.000000" name="Audio 12" id="1088698484325738"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 12.1" speed="1" name="Audio 12" id="1088698484325738"/>
<DiskStream channels="2" playlist="Audio 13.1" speed="1.000000" name="Audio 13" id="1088698484576054"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 13.1" speed="1" name="Audio 13" id="1088698484576054"/>
<DiskStream channels="2" playlist="Audio 14.1" speed="1.000000" name="Audio 14" id="1088698484839332"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 14.1" speed="1" name="Audio 14" id="1088698484839332"/>
<DiskStream channels="2" playlist="Audio 15.1" speed="1.000000" name="Audio 15" id="1088698485116518"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 15.1" speed="1" name="Audio 15" id="1088698485116518"/>
<DiskStream channels="2" playlist="Audio 16.1" speed="1.000000" name="Audio 16" id="1088698485412133"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 16.1" speed="1" name="Audio 16" id="1088698485412133"/>
</DiskStreams> </DiskStreams>
<Locations> <Locations>
<Location name="end" start="14400000" end="14400000" flags="33"/> <Location id="1191241715" name="start" start="0" end="0" flags="IsMark,IsStart"/>
<Location name="Loop" start="0" end="14400000" flags="12"/> <Location id="1191241716" name="end" start="14400000" end="14400000" flags="IsMark,IsEnd"/>
<Location name="Punch" start="0" end="14400000" flags="10"/>
</Locations> </Locations>
<Connections/> <Connections/>
<Routes> <Routes>
<Route flags="0x2" muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0"> <Route flags="MasterOut" default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0">
<IO name="master" id="1088698373992392" inputs="{ardour:Audio 16/out 1,ardour:Audio 15/out 1,ardour:Audio 14/out 1,ardour:Audio 13/out 1,ardour:Audio 12/out 1,ardour:Audio 11/out 1,ardour:Audio 10/out 1,ardour:Audio 9/out 1,ardour:Audio 8/out 1,ardour:Audio 7/out 1,ardour:Audio 6/out 1,ardour:Audio 5/out 1,ardour:Audio 4/out 1,ardour:Audio 3/out 1,ardour:Audio 2/out 1,ardour:Audio 1/out 1}{ardour:Audio 16/out 2,ardour:Audio 15/out 2,ardour:Audio 14/out 2,ardour:Audio 13/out 2,ardour:Audio 12/out 2,ardour:Audio 11/out 2,ardour:Audio 10/out 2,ardour:Audio 9/out 2,ardour:Audio 8/out 2,ardour:Audio 7/out 2,ardour:Audio 6/out 2,ardour:Audio 5/out 2,ardour:Audio 4/out 2,ardour:Audio 3/out 2,ardour:Audio 2/out 2,ardour:Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1" iolimits="-1,2,-1,2" automation-state="0x0" automation-style="0x1"> <IO name="master" id="1088698373992392" inputs="{Audio 16/out 1,Audio 15/out 1,Audio 14/out 1,Audio 13/out 1,Audio 12/out 1,Audio 11/out 1,Audio 10/out 1,Audio 9/out 1,Audio 8/out 1,Audio 7/out 1,Audio 6/out 1,Audio 5/out 1,Audio 4/out 1,Audio 3/out 1,Audio 2/out 1,Audio 1/out 1}{Audio 16/out 2,Audio 15/out 2,Audio 14/out 2,Audio 13/out 2,Audio 12/out 2,Audio 11/out 2,Audio 10/out 2,Audio 9/out 2,Audio 8/out 2,Audio 7/out 2,Audio 6/out 2,Audio 5/out 2,Audio 4/out 2,Audio 3/out 2,Audio 2/out 2,Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1.000000000000" iolimits="-1,2,-1,2">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241498" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241497"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241501" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241500"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241256"/>
</IO> </IO>
<controllable name="solo" id="1191241265"/>
<controllable name="mute" id="1191241266"/>
<remote_control id="1"/>
<extra> <extra>
<GUI color="3746:15634:28532" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="3746:15634:28532" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" diskstream-id="1088698381595945"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" mode="Normal" diskstream-id="1088698381595945">
<IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241504" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241503"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241507" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241506"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241268"/>
</IO> </IO>
<controllable name="solo" id="1191241277"/>
<controllable name="mute" id="1191241278"/>
<remote_control id="2"/>
<extra> <extra>
<GUI color="25329:39287:16285" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="25329:39287:16285" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241279"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" diskstream-id="1088698381722129"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" mode="Normal" diskstream-id="1088698381722129">
<IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241510" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241509"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241513" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241512"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241281"/>
</IO> </IO>
<controllable name="solo" id="1191241290"/>
<controllable name="mute" id="1191241291"/>
<remote_control id="3"/>
<extra> <extra>
<GUI color="6057:31092:43721" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="6057:31092:43721" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241292"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=3:signal=3" diskstream-id="1088698419793849"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=3:signal=3" mode="Normal" diskstream-id="1088698419793849">
<IO name="Audio 3" id="1088698419793786" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 3" id="1088698419793786" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241516" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241515"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241519" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241518"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241294"/>
</IO> </IO>
<controllable name="solo" id="1191241303"/>
<controllable name="mute" id="1191241304"/>
<remote_control id="4"/>
<extra> <extra>
<GUI color="21964:7276:28849" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="21964:7276:28849" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241305"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=4:signal=4" diskstream-id="1088698419943526"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=4:signal=4" mode="Normal" diskstream-id="1088698419943526">
<IO name="Audio 4" id="1088698419943460" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 4" id="1088698419943460" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241522" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241521"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241525" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241524"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241307"/>
</IO> </IO>
<controllable name="solo" id="1191241316"/>
<controllable name="mute" id="1191241317"/>
<remote_control id="5"/>
<extra> <extra>
<GUI color="46694:21380:28653" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="46694:21380:28653" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241318"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=5:signal=5" diskstream-id="1088698450528071"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=5:signal=5" mode="Normal" diskstream-id="1088698450528071">
<IO name="Audio 5" id="1088698450528006" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 5" id="1088698450528006" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241528" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241527"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241531" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241530"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241320"/>
</IO> </IO>
<controllable name="solo" id="1191241329"/>
<controllable name="mute" id="1191241330"/>
<remote_control id="6"/>
<extra> <extra>
<GUI color="29643:15912:24582" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="29643:15912:24582" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241331"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=6:signal=6" diskstream-id="1088698450754348"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=6:signal=6" mode="Normal" diskstream-id="1088698450754348">
<IO name="Audio 6" id="1088698450754242" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 6" id="1088698450754242" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241534" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241533"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241537" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241536"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241333"/>
</IO> </IO>
<controllable name="solo" id="1191241342"/>
<controllable name="mute" id="1191241343"/>
<remote_control id="7"/>
<extra> <extra>
<GUI color="32959:22941:32677" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="32959:22941:32677" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241344"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=7:signal=7" diskstream-id="1088698450937150"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=7:signal=7" mode="Normal" diskstream-id="1088698450937150">
<IO name="Audio 7" id="1088698450937083" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 7" id="1088698450937083" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241540" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241539"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241543" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241542"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241346"/>
</IO> </IO>
<controllable name="solo" id="1191241355"/>
<controllable name="mute" id="1191241356"/>
<remote_control id="8"/>
<extra> <extra>
<GUI color="44734:28458:19344" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="44734:28458:19344" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241357"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=8:signal=8" diskstream-id="1088698451167172"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=8:signal=8" mode="Normal" diskstream-id="1088698451167172">
<IO name="Audio 8" id="1088698451167106" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 8" id="1088698451167106" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241546" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241545"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241549" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241548"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241359"/>
</IO> </IO>
<controllable name="solo" id="1191241368"/>
<controllable name="mute" id="1191241369"/>
<remote_control id="9"/>
<extra> <extra>
<GUI color="21903:23957:19369" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="21903:23957:19369" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241370"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=9:signal=9" diskstream-id="1088698483525991"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=9:signal=9" mode="Normal" diskstream-id="1088698483525991">
<IO name="Audio 9" id="1088698483525928" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 9" id="1088698483525928" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241552" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241551"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241555" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241554"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241372"/>
</IO> </IO>
<controllable name="solo" id="1191241381"/>
<controllable name="mute" id="1191241382"/>
<remote_control id="10"/>
<extra> <extra>
<GUI color="33035:25949:38549" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="33035:25949:38549" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241383"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=10:signal=10" diskstream-id="1088698483801345"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=10:signal=10" mode="Normal" diskstream-id="1088698483801345">
<IO name="Audio 10" id="1088698483801234" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 10" id="1088698483801234" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241558" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241557"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241561" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241560"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241385"/>
</IO> </IO>
<controllable name="solo" id="1191241394"/>
<controllable name="mute" id="1191241395"/>
<remote_control id="11"/>
<extra> <extra>
<GUI color="2516:42834:42296" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="2516:42834:42296" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241396"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=11:signal=11" diskstream-id="1088698484086727"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=11:signal=11" mode="Normal" diskstream-id="1088698484086727">
<IO name="Audio 11" id="1088698484086663" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 11" id="1088698484086663" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241564" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241563"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241567" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241566"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241398"/>
</IO> </IO>
<controllable name="solo" id="1191241407"/>
<controllable name="mute" id="1191241408"/>
<remote_control id="12"/>
<extra> <extra>
<GUI color="6503:47471:19625" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="6503:47471:19625" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241409"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=12:signal=12" diskstream-id="1088698484325738"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=12:signal=12" mode="Normal" diskstream-id="1088698484325738">
<IO name="Audio 12" id="1088698484325672" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 12" id="1088698484325672" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241570" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241569"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241573" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241572"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241411"/>
</IO> </IO>
<controllable name="solo" id="1191241420"/>
<controllable name="mute" id="1191241421"/>
<remote_control id="13"/>
<extra> <extra>
<GUI color="45790:43192:14035" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="45790:43192:14035" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241422"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=13:signal=13" diskstream-id="1088698484576054"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=13:signal=13" mode="Normal" diskstream-id="1088698484576054">
<IO name="Audio 13" id="1088698484575978" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 13" id="1088698484575978" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241576" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241575"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241579" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241578"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241424"/>
</IO> </IO>
<controllable name="solo" id="1191241433"/>
<controllable name="mute" id="1191241434"/>
<remote_control id="14"/>
<extra> <extra>
<GUI color="17234:12393:35999" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="17234:12393:35999" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241435"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=14:signal=14" diskstream-id="1088698484839332"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=14:signal=14" mode="Normal" diskstream-id="1088698484839332">
<IO name="Audio 14" id="1088698484839137" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 14" id="1088698484839137" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241582" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241581"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241585" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241584"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241437"/>
</IO> </IO>
<controllable name="solo" id="1191241446"/>
<controllable name="mute" id="1191241447"/>
<remote_control id="15"/>
<extra> <extra>
<GUI color="12863:41046:23045" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="12863:41046:23045" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241448"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=15:signal=15" diskstream-id="1088698485116518"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=15:signal=15" mode="Normal" diskstream-id="1088698485116518">
<IO name="Audio 15" id="1088698485116451" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 15" id="1088698485116451" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241588" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241587"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241591" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241590"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241450"/>
</IO> </IO>
<controllable name="solo" id="1191241459"/>
<controllable name="mute" id="1191241460"/>
<remote_control id="16"/>
<extra> <extra>
<GUI color="34243:17628:4689" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="34243:17628:4689" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241461"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=16:signal=16" diskstream-id="1088698485412133"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=16:signal=16" mode="Normal" diskstream-id="1088698485412133">
<IO name="Audio 16" id="1088698485412068" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 16" id="1088698485412068" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241594" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241593"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241597" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241596"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241463"/>
</IO> </IO>
<controllable name="solo" id="1191241472"/>
<controllable name="mute" id="1191241473"/>
<remote_control id="17"/>
<extra> <extra>
<GUI color="2155:38658:37648" strip_width="wide" shown_mixer="yes" track_height="normal" shown_editor="yes"/> <GUI color="2155:38658:37648" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241474"/>
</Route> </Route>
</Routes> </Routes>
<EditGroups/> <EditGroups/>
<MixGroups/> <MixGroups/>
<Playlists/> <Playlists/>
<UnusedPlaylists/>
<Click> <Click>
<IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1" iolimits="0,0,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1.000000000000" iolimits="0,0,-1,-1">
<Panner linked="no" link_direction="0" automation="t1-pan-click.automation"/> <Panner linked="no" link_direction="SameDirection" bypassed="no"/>
<controllable name="gaincontrol" id="1191241476"/>
</IO> </IO>
</Click> </Click>
<TempoMap> <TempoMap>
<Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/> <Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/>
<Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/> <Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/>
</TempoMap> </TempoMap>
<ControlProtocols>
<Protocol name="Generic MIDI" feedback="0" feedback_interval="10000" active="yes">
<controls/>
</Protocol>
</ControlProtocols>
</Session> </Session>

View file

@ -1,92 +1,155 @@
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<Session version="0.821.0"> <Session version="2.0.0" id-counter="1191241115">
<Options> <Config>
<recording-plugins val="no"/> <Option name="output-auto-connect" value="2"/>
<slave type="none"/> <Option name="input-auto-connect" value="1"/>
<send-midi-timecode val="no"/> <Option name="mtc-port-name" value="control"/>
<send-midi-machine-control val="no"/> <Option name="mmc-port-name" value="control"/>
<input-auto-connect val="1"/> <Option name="midi-port-name" value="control"/>
<output-auto-connect val="2"/> <Option name="mmc-control" value="0"/>
<max-level val="0"/> <Option name="midi-feedback" value="0"/>
<min-level val="0"/> <Option name="xfade-model" value="0"/>
<meter-hold val="10.000000"/> <Option name="edit-mode" value="0"/>
<long-over-length val="10"/> <Option name="layer-model" value="0"/>
<short-over-length val="2"/> <Option name="solo-model" value="0"/>
<shuttle-speed-factor val="1.000000"/> <Option name="all-safe" value="0"/>
<shuttle-speed-threshold val="5.000000"/> <Option name="auto-play" value="0"/>
<rf-speed val="2.000000"/> <Option name="auto-return" value="0"/>
<smpte-frames-per-second val="30.000000"/> <Option name="auto-input" value="1"/>
<edit-mode val="slide"/> <Option name="punch-in" value="0"/>
<auto-play val="no"/> <Option name="punch-out" value="0"/>
<auto-input val="no"/> <Option name="seamless-loop" value="0"/>
<seamless-loop val="no"/> <Option name="rf-speed" value="2"/>
<punch-in val="no"/> <Option name="shuttle-speed-factor" value="1"/>
<punch-out val="no"/> <Option name="shuttle-speed-threshold" value="5"/>
<all-safe val="no"/> <Option name="meter-hold" value="10"/>
<auto-return val="no"/> <Option name="meter-falloff" value="1.5"/>
<mmc-control val="no"/> <end-marker-is-free val="no"/>
<recording-plugins val="no"/> </Config>
<auto-crossfade val="no"/>
<audible-click val="no"/>
<align-style val="existing"/>
</Options>
<Sources/> <Sources/>
<Regions/> <Regions/>
<DiskStreams> <DiskStreams>
<DiskStream channels="2" playlist="Audio 1.1" speed="1.000000" name="Audio 1" id="1088698381595945"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 1.1" speed="1" name="Audio 1" id="1088698381595945"/>
<DiskStream channels="2" playlist="Audio 2.1" speed="1.000000" name="Audio 2" id="1088698381722129"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 2.1" speed="1" name="Audio 2" id="1088698381722129"/>
</DiskStreams> </DiskStreams>
<Locations> <Locations>
<Location name="end" start="14400000" end="14400000" flags="33"/> <Location id="1191241116" name="start" start="0" end="0" flags="IsMark,IsStart"/>
<Location name="Loop" start="0" end="14400000" flags="12"/> <Location id="1191241117" name="end" start="14400000" end="14400000" flags="IsMark,IsEnd"/>
<Location name="Punch" start="0" end="14400000" flags="10"/>
</Locations> </Locations>
<Connections/> <Connections/>
<Routes> <Routes>
<Route flags="0x2" muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0"> <Route flags="MasterOut" default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0">
<IO name="master" id="1088698373992392" inputs="{ardour:Audio 2/out 1,ardour:Audio 1/out 1}{ardour:Audio 2/out 2,ardour:Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1" iolimits="-1,2,-1,2" automation-state="0x0" automation-style="0x1"> <IO name="master" id="1088698373992392" inputs="{Audio 2/out 1,Audio 1/out 1}{Audio 2/out 2,Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1.000000000000" iolimits="-1,2,-1,2">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241081" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241080"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241084" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241083"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241021"/>
</IO> </IO>
<controllable name="solo" id="1191241030"/>
<controllable name="mute" id="1191241031"/>
<remote_control id="1"/>
<extra> <extra>
<GUI color="3746:15634:28532" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="3746:15634:28532" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" diskstream-id="1088698381595945"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" mode="Normal" diskstream-id="1088698381595945">
<IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241087" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241086"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241090" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241089"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241033"/>
</IO> </IO>
<controllable name="solo" id="1191241042"/>
<controllable name="mute" id="1191241043"/>
<remote_control id="2"/>
<extra> <extra>
<GUI color="25329:39287:16285" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="25329:39287:16285" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241044"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" diskstream-id="1088698381722129"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" mode="Normal" diskstream-id="1088698381722129">
<IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241093" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241092"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241096" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241095"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241046"/>
</IO> </IO>
<controllable name="solo" id="1191241055"/>
<controllable name="mute" id="1191241056"/>
<remote_control id="3"/>
<extra> <extra>
<GUI color="6057:31092:43721" strip_width="wide" shown_mixer="yes" track_height="normal" shown_editor="yes"/> <GUI color="6057:31092:43721" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241057"/>
</Route> </Route>
</Routes> </Routes>
<EditGroups/> <EditGroups/>
<MixGroups/> <MixGroups/>
<Playlists/> <Playlists/>
<UnusedPlaylists/>
<Click> <Click>
<IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1" iolimits="0,0,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1.000000000000" iolimits="0,0,-1,-1">
<Panner linked="no" link_direction="0" automation="t1-pan-click.automation"/> <Panner linked="no" link_direction="SameDirection" bypassed="no"/>
<controllable name="gaincontrol" id="1191241059"/>
</IO> </IO>
</Click> </Click>
<TempoMap> <TempoMap>
<Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/> <Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/>
<Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/> <Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/>
</TempoMap> </TempoMap>
<ControlProtocols>
<Protocol name="Generic MIDI" feedback="0" feedback_interval="10000" active="yes">
<controls/>
</Protocol>
</ControlProtocols>
</Session> </Session>

File diff suppressed because it is too large Load diff

View file

@ -1,116 +1,221 @@
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<Session version="0.821.0"> <Session version="2.0.0" id-counter="1191241255">
<Options> <Config>
<recording-plugins val="no"/> <Option name="output-auto-connect" value="2"/>
<slave type="none"/> <Option name="input-auto-connect" value="1"/>
<send-midi-timecode val="no"/> <Option name="mtc-port-name" value="control"/>
<send-midi-machine-control val="no"/> <Option name="mmc-port-name" value="control"/>
<input-auto-connect val="1"/> <Option name="midi-port-name" value="control"/>
<output-auto-connect val="2"/> <Option name="mmc-control" value="0"/>
<max-level val="0"/> <Option name="midi-feedback" value="0"/>
<min-level val="0"/> <Option name="xfade-model" value="0"/>
<meter-hold val="10.000000"/> <Option name="edit-mode" value="0"/>
<long-over-length val="10"/> <Option name="layer-model" value="0"/>
<short-over-length val="2"/> <Option name="solo-model" value="0"/>
<shuttle-speed-factor val="1.000000"/> <Option name="all-safe" value="0"/>
<shuttle-speed-threshold val="5.000000"/> <Option name="auto-play" value="0"/>
<rf-speed val="2.000000"/> <Option name="auto-return" value="0"/>
<smpte-frames-per-second val="30.000000"/> <Option name="auto-input" value="1"/>
<edit-mode val="slide"/> <Option name="punch-in" value="0"/>
<auto-play val="no"/> <Option name="punch-out" value="0"/>
<auto-input val="no"/> <Option name="seamless-loop" value="0"/>
<seamless-loop val="no"/> <Option name="rf-speed" value="2"/>
<punch-in val="no"/> <Option name="shuttle-speed-factor" value="1"/>
<punch-out val="no"/> <Option name="shuttle-speed-threshold" value="5"/>
<all-safe val="no"/> <Option name="meter-hold" value="10"/>
<auto-return val="no"/> <Option name="meter-falloff" value="1.5"/>
<mmc-control val="no"/> <end-marker-is-free val="no"/>
<recording-plugins val="no"/> </Config>
<auto-crossfade val="no"/>
<audible-click val="no"/>
<align-style val="existing"/>
</Options>
<Sources/> <Sources/>
<Regions/> <Regions/>
<DiskStreams> <DiskStreams>
<DiskStream channels="2" playlist="Audio 1.1" speed="1.000000" name="Audio 1" id="1088698381595945"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 1.1" speed="1" name="Audio 1" id="1088698381595945"/>
<DiskStream channels="2" playlist="Audio 2.1" speed="1.000000" name="Audio 2" id="1088698381722129"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 2.1" speed="1" name="Audio 2" id="1088698381722129"/>
<DiskStream channels="2" playlist="Audio 3.1" speed="1.000000" name="Audio 3" id="1088698419793849"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 3.1" speed="1" name="Audio 3" id="1088698419793849"/>
<DiskStream channels="2" playlist="Audio 4.1" speed="1.000000" name="Audio 4" id="1088698419943526"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 4.1" speed="1" name="Audio 4" id="1088698419943526"/>
</DiskStreams> </DiskStreams>
<Locations> <Locations>
<Location name="end" start="14400000" end="14400000" flags="33"/> <Location id="1191241256" name="start" start="0" end="0" flags="IsMark,IsStart"/>
<Location name="Loop" start="0" end="14400000" flags="12"/> <Location id="1191241257" name="end" start="14400000" end="14400000" flags="IsMark,IsEnd"/>
<Location name="Punch" start="0" end="14400000" flags="10"/>
</Locations> </Locations>
<Connections/> <Connections/>
<Routes> <Routes>
<Route flags="0x2" muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0"> <Route flags="MasterOut" default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0">
<IO name="master" id="1088698373992392" inputs="{ardour:Audio 4/out 1,ardour:Audio 3/out 1,ardour:Audio 2/out 1,ardour:Audio 1/out 1}{ardour:Audio 4/out 2,ardour:Audio 3/out 2,ardour:Audio 2/out 2,ardour:Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1" iolimits="-1,2,-1,2" automation-state="0x0" automation-style="0x1"> <IO name="master" id="1088698373992392" inputs="{Audio 4/out 1,Audio 3/out 1,Audio 2/out 1,Audio 1/out 1}{Audio 4/out 2,Audio 3/out 2,Audio 2/out 2,Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1.000000000000" iolimits="-1,2,-1,2">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241195" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241194"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241198" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241197"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241109"/>
</IO> </IO>
<controllable name="solo" id="1191241118"/>
<controllable name="mute" id="1191241119"/>
<remote_control id="1"/>
<extra> <extra>
<GUI color="3746:15634:28532" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="3746:15634:28532" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" diskstream-id="1088698381595945"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" mode="Normal" diskstream-id="1088698381595945">
<IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241201" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241200"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241204" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241203"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241121"/>
</IO> </IO>
<controllable name="solo" id="1191241130"/>
<controllable name="mute" id="1191241131"/>
<remote_control id="2"/>
<extra> <extra>
<GUI color="25329:39287:16285" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="25329:39287:16285" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241132"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" diskstream-id="1088698381722129"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" mode="Normal" diskstream-id="1088698381722129">
<IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241207" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241206"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241210" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241209"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241134"/>
</IO> </IO>
<controllable name="solo" id="1191241143"/>
<controllable name="mute" id="1191241144"/>
<remote_control id="3"/>
<extra> <extra>
<GUI color="6057:31092:43721" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="6057:31092:43721" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241145"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=3:signal=3" diskstream-id="1088698419793849"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=3:signal=3" mode="Normal" diskstream-id="1088698419793849">
<IO name="Audio 3" id="1088698419793786" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 3" id="1088698419793786" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241213" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241212"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241216" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241215"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241147"/>
</IO> </IO>
<controllable name="solo" id="1191241156"/>
<controllable name="mute" id="1191241157"/>
<remote_control id="4"/>
<extra> <extra>
<GUI color="21964:7276:28849" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="21964:7276:28849" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241158"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=4:signal=4" diskstream-id="1088698419943526"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=4:signal=4" mode="Normal" diskstream-id="1088698419943526">
<IO name="Audio 4" id="1088698419943460" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 4" id="1088698419943460" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241219" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241218"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241222" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241221"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241160"/>
</IO> </IO>
<controllable name="solo" id="1191241169"/>
<controllable name="mute" id="1191241170"/>
<remote_control id="5"/>
<extra> <extra>
<GUI color="46694:21380:28653" shown_mixer="yes" track_height="normal" shown_editor="yes" strip_width="wide"/> <GUI color="46694:21380:28653" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241171"/>
</Route> </Route>
</Routes> </Routes>
<EditGroups/> <EditGroups/>
<MixGroups/> <MixGroups/>
<Playlists/> <Playlists/>
<UnusedPlaylists/>
<Click> <Click>
<IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1" iolimits="0,0,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1.000000000000" iolimits="0,0,-1,-1">
<Panner linked="no" link_direction="0" automation="t1-pan-click.automation"/> <Panner linked="no" link_direction="SameDirection" bypassed="no"/>
<controllable name="gaincontrol" id="1191241173"/>
</IO> </IO>
</Click> </Click>
<TempoMap> <TempoMap>
<Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/> <Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/>
<Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/> <Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/>
</TempoMap> </TempoMap>
<ControlProtocols>
<Protocol name="Generic MIDI" feedback="0" feedback_interval="10000" active="yes">
<controls/>
</Protocol>
</ControlProtocols>
</Session> </Session>

View file

@ -1,164 +1,353 @@
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<Session version="0.821.0"> <Session version="2.0.0" id-counter="1191241420">
<Options> <Config>
<recording-plugins val="no"/> <Option name="output-auto-connect" value="2"/>
<slave type="none"/> <Option name="input-auto-connect" value="1"/>
<send-midi-timecode val="no"/> <Option name="mtc-port-name" value="control"/>
<send-midi-machine-control val="no"/> <Option name="mmc-port-name" value="control"/>
<input-auto-connect val="1"/> <Option name="midi-port-name" value="control"/>
<output-auto-connect val="2"/> <Option name="mmc-control" value="0"/>
<max-level val="0"/> <Option name="midi-feedback" value="0"/>
<min-level val="0"/> <Option name="xfade-model" value="0"/>
<meter-hold val="10.000000"/> <Option name="edit-mode" value="0"/>
<long-over-length val="10"/> <Option name="layer-model" value="0"/>
<short-over-length val="2"/> <Option name="solo-model" value="0"/>
<shuttle-speed-factor val="1.000000"/> <Option name="all-safe" value="0"/>
<shuttle-speed-threshold val="5.000000"/> <Option name="auto-play" value="0"/>
<rf-speed val="2.000000"/> <Option name="auto-return" value="0"/>
<smpte-frames-per-second val="30.000000"/> <Option name="auto-input" value="1"/>
<edit-mode val="slide"/> <Option name="punch-in" value="0"/>
<auto-play val="no"/> <Option name="punch-out" value="0"/>
<auto-input val="no"/> <Option name="seamless-loop" value="0"/>
<seamless-loop val="no"/> <Option name="rf-speed" value="2"/>
<punch-in val="no"/> <Option name="shuttle-speed-factor" value="1"/>
<punch-out val="no"/> <Option name="shuttle-speed-threshold" value="5"/>
<all-safe val="no"/> <Option name="meter-hold" value="10"/>
<auto-return val="no"/> <Option name="meter-falloff" value="1.5"/>
<mmc-control val="no"/> <end-marker-is-free val="no"/>
<recording-plugins val="no"/> </Config>
<auto-crossfade val="no"/>
<audible-click val="no"/>
<align-style val="existing"/>
</Options>
<Sources/> <Sources/>
<Regions/> <Regions/>
<DiskStreams> <DiskStreams>
<DiskStream channels="2" playlist="Audio 1.1" speed="1.000000" name="Audio 1" id="1088698381595945"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 1.1" speed="1" name="Audio 1" id="1088698381595945"/>
<DiskStream channels="2" playlist="Audio 2.1" speed="1.000000" name="Audio 2" id="1088698381722129"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 2.1" speed="1" name="Audio 2" id="1088698381722129"/>
<DiskStream channels="2" playlist="Audio 3.1" speed="1.000000" name="Audio 3" id="1088698419793849"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 3.1" speed="1" name="Audio 3" id="1088698419793849"/>
<DiskStream channels="2" playlist="Audio 4.1" speed="1.000000" name="Audio 4" id="1088698419943526"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 4.1" speed="1" name="Audio 4" id="1088698419943526"/>
<DiskStream channels="2" playlist="Audio 5.1" speed="1.000000" name="Audio 5" id="1088698450528071"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 5.1" speed="1" name="Audio 5" id="1088698450528071"/>
<DiskStream channels="2" playlist="Audio 6.1" speed="1.000000" name="Audio 6" id="1088698450754348"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 6.1" speed="1" name="Audio 6" id="1088698450754348"/>
<DiskStream channels="2" playlist="Audio 7.1" speed="1.000000" name="Audio 7" id="1088698450937150"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 7.1" speed="1" name="Audio 7" id="1088698450937150"/>
<DiskStream channels="2" playlist="Audio 8.1" speed="1.000000" name="Audio 8" id="1088698451167172"/> <AudioDiskstream flags="Recordable" channels="2" playlist="Audio 8.1" speed="1" name="Audio 8" id="1088698451167172"/>
</DiskStreams> </DiskStreams>
<Locations> <Locations>
<Location name="end" start="14400000" end="14400000" flags="33"/> <Location id="1191241421" name="start" start="0" end="0" flags="IsMark,IsStart"/>
<Location name="Loop" start="0" end="14400000" flags="12"/> <Location id="1191241422" name="end" start="14400000" end="14400000" flags="IsMark,IsEnd"/>
<Location name="Punch" start="0" end="14400000" flags="10"/>
</Locations> </Locations>
<Connections/> <Connections/>
<Routes> <Routes>
<Route flags="0x2" muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0"> <Route flags="MasterOut" default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=0:signal=0">
<IO name="master" id="1088698373992392" inputs="{ardour:Audio 8/out 1,ardour:Audio 7/out 1,ardour:Audio 6/out 1,ardour:Audio 5/out 1,ardour:Audio 4/out 1,ardour:Audio 3/out 1,ardour:Audio 2/out 1,ardour:Audio 1/out 1}{ardour:Audio 8/out 2,ardour:Audio 7/out 2,ardour:Audio 6/out 2,ardour:Audio 5/out 2,ardour:Audio 4/out 2,ardour:Audio 3/out 2,ardour:Audio 2/out 2,ardour:Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1" iolimits="-1,2,-1,2" automation-state="0x0" automation-style="0x1"> <IO name="master" id="1088698373992392" inputs="{Audio 8/out 1,Audio 7/out 1,Audio 6/out 1,Audio 5/out 1,Audio 4/out 1,Audio 3/out 1,Audio 2/out 1,Audio 1/out 1}{Audio 8/out 2,Audio 7/out 2,Audio 6/out 2,Audio 5/out 2,Audio 4/out 2,Audio 3/out 2,Audio 2/out 2,Audio 1/out 2}" outputs="{%JACK_INPUT%1}{%JACK_INPUT%2}" gain="1.000000000000" iolimits="-1,2,-1,2">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241308" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241307"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241311" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241310"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241170"/>
</IO> </IO>
<controllable name="solo" id="1191241179"/>
<controllable name="mute" id="1191241180"/>
<remote_control id="1"/>
<extra> <extra>
<GUI color="3746:15634:28532" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="3746:15634:28532" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" diskstream-id="1088698381595945"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=1:signal=1" mode="Normal" diskstream-id="1088698381595945">
<IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 1" id="1088698381595877" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241314" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241313"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241317" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241316"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241182"/>
</IO> </IO>
<controllable name="solo" id="1191241191"/>
<controllable name="mute" id="1191241192"/>
<remote_control id="2"/>
<extra> <extra>
<GUI color="25329:39287:16285" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="25329:39287:16285" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241193"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" diskstream-id="1088698381722129"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" mode="Normal" diskstream-id="1088698381722129">
<IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241320" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241319"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241323" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241322"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241195"/>
</IO> </IO>
<controllable name="solo" id="1191241204"/>
<controllable name="mute" id="1191241205"/>
<remote_control id="3"/>
<extra> <extra>
<GUI color="6057:31092:43721" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="6057:31092:43721" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241206"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=3:signal=3" diskstream-id="1088698419793849"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=3:signal=3" mode="Normal" diskstream-id="1088698419793849">
<IO name="Audio 3" id="1088698419793786" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 3" id="1088698419793786" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241326" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241325"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241329" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241328"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241208"/>
</IO> </IO>
<controllable name="solo" id="1191241217"/>
<controllable name="mute" id="1191241218"/>
<remote_control id="4"/>
<extra> <extra>
<GUI color="21964:7276:28849" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="21964:7276:28849" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241219"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=4:signal=4" diskstream-id="1088698419943526"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=4:signal=4" mode="Normal" diskstream-id="1088698419943526">
<IO name="Audio 4" id="1088698419943460" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 4" id="1088698419943460" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241332" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241331"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241335" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241334"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241221"/>
</IO> </IO>
<controllable name="solo" id="1191241230"/>
<controllable name="mute" id="1191241231"/>
<remote_control id="5"/>
<extra> <extra>
<GUI color="46694:21380:28653" track_height="normal" strip_width="wide" shown_mixer="yes" shown_editor="yes"/> <GUI color="46694:21380:28653" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241232"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=5:signal=5" diskstream-id="1088698450528071"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=5:signal=5" mode="Normal" diskstream-id="1088698450528071">
<IO name="Audio 5" id="1088698450528006" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 5" id="1088698450528006" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241338" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241337"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241341" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241340"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241234"/>
</IO> </IO>
<controllable name="solo" id="1191241243"/>
<controllable name="mute" id="1191241244"/>
<remote_control id="6"/>
<extra> <extra>
<GUI color="29643:15912:24582" track_height="normal" shown_mixer="yes" shown_editor="yes" strip_width="wide"/> <GUI color="29643:15912:24582" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241245"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=6:signal=6" diskstream-id="1088698450754348"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=6:signal=6" mode="Normal" diskstream-id="1088698450754348">
<IO name="Audio 6" id="1088698450754242" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 6" id="1088698450754242" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241344" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241343"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241347" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241346"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241247"/>
</IO> </IO>
<controllable name="solo" id="1191241256"/>
<controllable name="mute" id="1191241257"/>
<remote_control id="7"/>
<extra> <extra>
<GUI color="32959:22941:32677" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="32959:22941:32677" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241258"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=7:signal=7" diskstream-id="1088698450937150"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=7:signal=7" mode="Normal" diskstream-id="1088698450937150">
<IO name="Audio 7" id="1088698450937083" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 7" id="1088698450937083" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241350" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241349"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241353" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241352"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241260"/>
</IO> </IO>
<controllable name="solo" id="1191241269"/>
<controllable name="mute" id="1191241270"/>
<remote_control id="8"/>
<extra> <extra>
<GUI color="44734:28458:19344" strip_width="wide" track_height="normal" shown_mixer="yes" shown_editor="yes"/> <GUI color="44734:28458:19344" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241271"/>
</Route> </Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=8:signal=8" diskstream-id="1088698451167172"> <Route default-type="audio" active="yes" muted="no" soloed="no" phase-invert="no" denormal-protection="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=8:signal=8" mode="Normal" diskstream-id="1088698451167172">
<IO name="Audio 8" id="1088698451167106" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="Audio 8" id="1088698451167106" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{master/in 1}{master/in 2}" gain="1.000000000000" iolimits="1,-1,-1,-1">
<Panner linked="no" link_direction="0"> <Panner linked="no" link_direction="SameDirection" bypassed="no">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="0" y="0"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/> <Output x="1" y="0"/>
<StreamPanner x="0" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241356" default="0" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241355"/>
</StreamPanner>
<StreamPanner x="1" type="Equal Power Stereo" muted="no">
<Automation>
<AutomationList id="1191241359" default="1" min_yval="0" max_yval="1" max_xval="0" state="Off" style="Absolute"/>
</Automation>
<controllable name="panner" id="1191241358"/>
</StreamPanner>
</Panner> </Panner>
<controllable name="gaincontrol" id="1191241273"/>
</IO> </IO>
<controllable name="solo" id="1191241282"/>
<controllable name="mute" id="1191241283"/>
<remote_control id="9"/>
<extra> <extra>
<GUI color="21903:23957:19369" strip_width="wide" shown_mixer="yes" track_height="normal" shown_editor="yes"/> <GUI color="21903:23957:19369" strip_width="Wide" shown_mixer="yes" shown_editor="yes" track_height="normal">
<gain track_height="normal" shown="no"/>
<pan track_height="normal" shown="no"/>
</GUI>
</extra> </extra>
<alignment style="ExistingMaterial"/>
<controllable name="recenable" id="1191241284"/>
</Route> </Route>
</Routes> </Routes>
<EditGroups/> <EditGroups/>
<MixGroups/> <MixGroups/>
<Playlists/> <Playlists/>
<UnusedPlaylists/>
<Click> <Click>
<IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1" iolimits="0,0,-1,-1" automation-state="0x0" automation-style="0x1"> <IO name="click" id="1088698373994975" inputs="" outputs="{%JACK_INPUT%1}" gain="1.000000000000" iolimits="0,0,-1,-1">
<Panner linked="no" link_direction="0" automation="t1-pan-click.automation"/> <Panner linked="no" link_direction="SameDirection" bypassed="no"/>
<controllable name="gaincontrol" id="1191241286"/>
</IO> </IO>
</Click> </Click>
<TempoMap> <TempoMap>
<Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/> <Tempo start="1|1|0" beats-per-minute="120.000000" movable="no"/>
<Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/> <Meter start="1|1|0" note-type="4.000000" beats-per-bar="4.000000" movable="no"/>
</TempoMap> </TempoMap>
<ControlProtocols>
<Protocol name="Generic MIDI" feedback="0" feedback_interval="10000" active="yes">
<controls/>
</Protocol>
</ControlProtocols>
</Session> </Session>