mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 15:54:57 +01:00
Deinterlace MIDI: split a midi region into per-channel regions (libardour part)
code is similar-but-different-from Importing with split-midi-channels enabled
This commit is contained in:
parent
ca7e133e3d
commit
11543b1c9b
2 changed files with 82 additions and 0 deletions
|
|
@ -846,6 +846,8 @@ public:
|
||||||
boost::shared_ptr<AudioRegion> XMLAudioRegionFactory (const XMLNode&, bool full);
|
boost::shared_ptr<AudioRegion> XMLAudioRegionFactory (const XMLNode&, bool full);
|
||||||
boost::shared_ptr<MidiRegion> XMLMidiRegionFactory (const XMLNode&, bool full);
|
boost::shared_ptr<MidiRegion> XMLMidiRegionFactory (const XMLNode&, bool full);
|
||||||
|
|
||||||
|
void deinterlace_midi_region ( boost::shared_ptr<MidiRegion> mr );
|
||||||
|
|
||||||
/* source management */
|
/* source management */
|
||||||
|
|
||||||
void import_files (ImportStatus&);
|
void import_files (ImportStatus&);
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,10 @@
|
||||||
#include "ardour/audioregion.h"
|
#include "ardour/audioregion.h"
|
||||||
#include "ardour/ffmpegfileimportable.h"
|
#include "ardour/ffmpegfileimportable.h"
|
||||||
#include "ardour/import_status.h"
|
#include "ardour/import_status.h"
|
||||||
|
#include "ardour/midi_region.h"
|
||||||
|
#include "ardour/midi_source.h"
|
||||||
#include "ardour/mp3fileimportable.h"
|
#include "ardour/mp3fileimportable.h"
|
||||||
|
#include "ardour/playlist.h"
|
||||||
#include "ardour/region_factory.h"
|
#include "ardour/region_factory.h"
|
||||||
#include "ardour/resampled_source.h"
|
#include "ardour/resampled_source.h"
|
||||||
#include "ardour/runtime_functions.h"
|
#include "ardour/runtime_functions.h"
|
||||||
|
|
@ -499,6 +502,83 @@ remove_file_source (boost::shared_ptr<Source> source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Session::deinterlace_midi_region ( boost::shared_ptr<MidiRegion> mr )
|
||||||
|
{
|
||||||
|
typedef vector<boost::shared_ptr<Source> > Sources;
|
||||||
|
Sources newfiles;
|
||||||
|
|
||||||
|
try {
|
||||||
|
boost::shared_ptr<MidiSource> ms = mr->midi_source(0);
|
||||||
|
boost::shared_ptr<SMFSource> smf = boost::dynamic_pointer_cast<SMFSource> (mr->midi_source(0)); //ToDo: handle compound sources?
|
||||||
|
string source_path = smf->path();
|
||||||
|
|
||||||
|
/* write_midi_data_to_new_files expects to find raw midi on-disk (SMF*).
|
||||||
|
* this means that a split looks like a no-op if the file wasn't written to disk yet.
|
||||||
|
* I've chosen to flush the file to disk, rather than reimplement write_midi_data_to_new_files for a Source */
|
||||||
|
smf->session_saved(); //ToDo: should we just expose flush_midi() instead?
|
||||||
|
|
||||||
|
/* open the SMF file for reading */
|
||||||
|
boost::scoped_ptr<Evoral::SMF> smf_reader;
|
||||||
|
smf_reader.reset (new Evoral::SMF());
|
||||||
|
if (smf_reader->open( source_path )) {
|
||||||
|
throw Evoral::SMF::FileError (source_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create new file paths for 16 potential channels of midi data */
|
||||||
|
vector<string> smf_names;
|
||||||
|
for (int i = 0; i<16; i++) {
|
||||||
|
smf_names.push_back(string_compose("-ch%1", i+1));
|
||||||
|
}
|
||||||
|
vector<string> new_paths = get_paths_for_new_sources (false, source_path, 16, smf_names);
|
||||||
|
|
||||||
|
/* create source files and write 1 channel of midi data to each of them */
|
||||||
|
if (create_mono_sources_for_writing (new_paths, *this, sample_rate(), newfiles, 0) ) {
|
||||||
|
ImportStatus status;
|
||||||
|
write_midi_data_to_new_files (smf_reader.get(), status, newfiles, true /*split*/);
|
||||||
|
} else {
|
||||||
|
error << _("deinterlace_midi_region: failed to create sources") << endmsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
error << _("deinterlace_midi_region: error opening MIDI file for splitting") << endmsg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not all 16 channels will have midi data; delete any sources that turned up empty */
|
||||||
|
for (Sources::iterator x = newfiles.begin(); x != newfiles.end(); ) {
|
||||||
|
boost::shared_ptr<SMFSource> smfs;
|
||||||
|
if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
|
||||||
|
x = newfiles.erase(x);
|
||||||
|
} else {
|
||||||
|
++x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert new regions with the properties of the source region */
|
||||||
|
for (Sources::iterator x = newfiles.begin(); x != newfiles.end(); x++) {
|
||||||
|
|
||||||
|
/* hand over the new Source to the session*/
|
||||||
|
add_source(*x);
|
||||||
|
|
||||||
|
/* create a whole-file region for this new source, so it shows up in the Source List...*/
|
||||||
|
PropertyList plist;
|
||||||
|
plist.add (Properties::whole_file, true);
|
||||||
|
plist.add (Properties::start, mr->start());
|
||||||
|
plist.add (Properties::position, mr->position());
|
||||||
|
plist.add (Properties::length, mr->length());
|
||||||
|
plist.add (Properties::name, (*x)->name());
|
||||||
|
plist.add (Properties::tags, "(split-chans)");
|
||||||
|
boost::shared_ptr<Region> whole = RegionFactory::create (*x, plist);
|
||||||
|
|
||||||
|
/* ... and insert a discrete copy into the playlist*/
|
||||||
|
PropertyList plist2;
|
||||||
|
plist2.add (ARDOUR::Properties::whole_file, false);
|
||||||
|
boost::shared_ptr<Region> copy (RegionFactory::create (whole, plist2));
|
||||||
|
mr->playlist()->add_region (copy, mr->position());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This function is still unable to cleanly update an existing source, even though
|
// This function is still unable to cleanly update an existing source, even though
|
||||||
// it is possible to set the ImportStatus flag accordingly. The functinality
|
// it is possible to set the ImportStatus flag accordingly. The functinality
|
||||||
// is disabled at the GUI until the Source implementations are able to provide
|
// is disabled at the GUI until the Source implementations are able to provide
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue