MIDI Import: Support for separating the channels of a Type1 midifile track(s)
This commit is contained in:
parent
0733b2d9e2
commit
58033262ae
@ -141,7 +141,7 @@ open_importable_source (const string& path, samplecnt_t samplerate, ARDOUR::SrcQ
|
||||
|
||||
vector<string>
|
||||
Session::get_paths_for_new_sources (bool /*allow_replacing*/, const string& import_file_path, uint32_t channels,
|
||||
vector<string> const & smf_track_names)
|
||||
vector<string> const & smf_names)
|
||||
|
||||
{
|
||||
vector<string> new_paths;
|
||||
@ -154,14 +154,9 @@ Session::get_paths_for_new_sources (bool /*allow_replacing*/, const string& impo
|
||||
|
||||
switch (type) {
|
||||
case DataType::MIDI:
|
||||
assert (smf_track_names.empty() || smf_track_names.size() == channels);
|
||||
if (channels > 1) {
|
||||
string mchn_name;
|
||||
if (smf_track_names.empty() || smf_track_names[n].empty()) {
|
||||
mchn_name = string_compose ("%1-t%2", basename, n);
|
||||
} else {
|
||||
mchn_name = string_compose ("%1-%2", basename, smf_track_names[n]);
|
||||
}
|
||||
assert (smf_names.size() == channels);
|
||||
string mchn_name = string_compose ("%1.%2", basename, smf_names[n]);
|
||||
filepath = new_midi_source_path (mchn_name);
|
||||
} else {
|
||||
filepath = new_midi_source_path (basename);
|
||||
@ -367,30 +362,34 @@ write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
|
||||
static void
|
||||
write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
|
||||
vector<boost::shared_ptr<Source> >& newfiles,
|
||||
bool split_type0)
|
||||
bool split_midi_channels)
|
||||
{
|
||||
uint32_t buf_size = 4;
|
||||
uint8_t* buf = (uint8_t*) malloc (buf_size);
|
||||
|
||||
status.progress = 0.0f;
|
||||
uint16_t num_tracks;
|
||||
bool type0 = source->is_type0 () && split_type0;
|
||||
const std::set<uint8_t>& chn = source->channels ();
|
||||
|
||||
if (type0) {
|
||||
num_tracks = source->channels().size();
|
||||
} else {
|
||||
num_tracks = source->num_tracks();
|
||||
}
|
||||
assert (newfiles.size() == num_tracks);
|
||||
bool type0 = source->smf_format()==0;
|
||||
|
||||
int total_files = newfiles.size();
|
||||
|
||||
try {
|
||||
vector<boost::shared_ptr<Source> >::iterator s = newfiles.begin();
|
||||
std::set<uint8_t>::const_iterator cur_chan = chn.begin();
|
||||
|
||||
for (unsigned i = 1; i <= num_tracks; ++i) {
|
||||
int cur_chan = 0;
|
||||
|
||||
for (int i = 0; i < total_files; ++i) {
|
||||
|
||||
int cur_track = i+1; //first Track of a type-1 file is metadata only. Start importing sourcefiles at Track index 1
|
||||
|
||||
if (split_midi_channels) { //if splitting channels we will need to fill 16x sources. empties will be disposed-of later
|
||||
cur_track = 1 + (int) floor((float)i/16.f); //calculate the Track needed for this sourcefile (offset by 1)
|
||||
}
|
||||
|
||||
boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource> (*s);
|
||||
if (!smfs) {
|
||||
continue; //should never happen. The calling code should provide exactly the number of tracks&channels we need
|
||||
}
|
||||
|
||||
Glib::Threads::Mutex::Lock source_lock(smfs->mutex());
|
||||
|
||||
@ -398,7 +397,7 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
|
||||
if (type0) {
|
||||
source->seek_to_start ();
|
||||
} else {
|
||||
source->seek_to_track (i);
|
||||
source->seek_to_track (cur_track);
|
||||
}
|
||||
|
||||
uint64_t t = 0;
|
||||
@ -427,12 +426,12 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
|
||||
continue;
|
||||
}
|
||||
|
||||
// type-0 files separate by channel
|
||||
if (type0) {
|
||||
/* if requested by user, each sourcefile gets only a single channel's data */
|
||||
if (split_midi_channels) {
|
||||
uint8_t type = buf[0] & 0xf0;
|
||||
uint8_t chan = buf[0] & 0x0f;
|
||||
if (type >= 0x80 && type <= 0xE0) {
|
||||
if (chan != *cur_chan) {
|
||||
if (chan != cur_chan) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -468,12 +467,14 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
info << string_compose (_("Track %1 of %2 contained no usable MIDI data"), i, num_tracks) << endmsg;
|
||||
info << string_compose (_("Track %1 of %2 contained no usable MIDI data"), i, total_files) << endmsg;
|
||||
}
|
||||
|
||||
++s; // next source
|
||||
if (type0) {
|
||||
++cur_chan;
|
||||
|
||||
++cur_chan;
|
||||
if (cur_chan > 15) {
|
||||
cur_chan=0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,7 +510,7 @@ Session::import_files (ImportStatus& status)
|
||||
Sources all_new_sources;
|
||||
boost::shared_ptr<AudioFileSource> afs;
|
||||
boost::shared_ptr<SMFSource> smfs;
|
||||
uint32_t channels = 0;
|
||||
uint32_t num_channels = 0;
|
||||
vector<string> smf_names;
|
||||
|
||||
status.sources.clear ();
|
||||
@ -524,7 +525,7 @@ Session::import_files (ImportStatus& status)
|
||||
if (type == DataType::AUDIO) {
|
||||
try {
|
||||
source = open_importable_source (*p, sample_rate(), status.quality);
|
||||
channels = source->channels();
|
||||
num_channels = source->channels();
|
||||
} catch (const failed_constructor& err) {
|
||||
error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
|
||||
status.done = status.cancel = true;
|
||||
@ -539,18 +540,53 @@ Session::import_files (ImportStatus& status)
|
||||
throw Evoral::SMF::FileError (*p);
|
||||
}
|
||||
|
||||
if (smf_reader->is_type0 () && status.split_midi_channels) {
|
||||
channels = smf_reader->channels().size();
|
||||
if (smf_reader->smf_format()==0) {
|
||||
/* Type0: we should prepare filenames for up to 16 channels in the file; we will throw out the empty ones later */
|
||||
if (status.split_midi_channels) {
|
||||
num_channels = 16;
|
||||
for (uint32_t i = 0; i<num_channels; i++) {
|
||||
smf_names.push_back( string_compose ("ch%1", 1+i ) ); //chanX
|
||||
}
|
||||
} else {
|
||||
num_channels = 1;
|
||||
smf_names.push_back("");
|
||||
}
|
||||
} else {
|
||||
channels = smf_reader->num_tracks();
|
||||
/* we should prepare filenames for up to 16 channels in each Track; we will throw out the empty ones later*/
|
||||
num_channels = status.split_midi_channels ? smf_reader->num_tracks()*16 : smf_reader->num_tracks();
|
||||
switch (status.midi_track_name_source) {
|
||||
case SMFTrackNumber:
|
||||
if (status.split_midi_channels) {
|
||||
for (uint32_t i = 0; i<num_channels; i++) {
|
||||
smf_names.push_back( string_compose ("t%1.ch%2", 1+i/16, 1+i%16 ) ); //trackX.chanX
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i<num_channels;i++) {
|
||||
smf_names.push_back( string_compose ("t%1", i+1 ) ); //trackX
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SMFTrackName:
|
||||
smf_reader->track_names (smf_names);
|
||||
if (status.split_midi_channels) {
|
||||
vector<string> temp;
|
||||
smf_reader->track_names (temp);
|
||||
for (uint32_t i = 0; i<num_channels;i++) {
|
||||
smf_names.push_back( string_compose ("%1.ch%2", temp[i/16], 1+i%16 ) ); //trackname.chanX
|
||||
}
|
||||
} else {
|
||||
smf_reader->track_names (smf_names);
|
||||
}
|
||||
break;
|
||||
case SMFInstrumentName:
|
||||
smf_reader->instrument_names (smf_names);
|
||||
if (status.split_midi_channels) {
|
||||
vector<string> temp;
|
||||
smf_reader->instrument_names (temp);
|
||||
for (uint32_t i = 0; i<num_channels;i++) {
|
||||
smf_names.push_back( string_compose ("%1.ch%2", temp[i/16], 1+i%16 ) ); //instrument.chanX
|
||||
}
|
||||
} else {
|
||||
smf_reader->instrument_names (smf_names);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -561,12 +597,12 @@ Session::import_files (ImportStatus& status)
|
||||
}
|
||||
}
|
||||
|
||||
if (channels == 0) {
|
||||
if (num_channels == 0) {
|
||||
error << _("Import: file contains no channels.") << endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p, channels, smf_names);
|
||||
vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p, num_channels, smf_names);
|
||||
Sources newfiles;
|
||||
samplepos_t natural_position = source ? source->natural_position() : 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user