mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
More powerful SMF::open interface.
git-svn-id: svn://localhost/ardour2/branches/3.0@4554 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
d439459589
commit
b2a051f6c6
4 changed files with 31 additions and 25 deletions
|
|
@ -25,7 +25,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <ardour/midi_source.h>
|
#include <ardour/midi_source.h>
|
||||||
#include <evoral/LibSMF.hpp>
|
#include <evoral/SMF.hpp>
|
||||||
|
|
||||||
namespace Evoral { template<typename T> class Event; }
|
namespace Evoral { template<typename T> class Event; }
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace ARDOUR {
|
||||||
template<typename T> class MidiRingBuffer;
|
template<typename T> class MidiRingBuffer;
|
||||||
|
|
||||||
/** Standard Midi File (Type 0) Source */
|
/** Standard Midi File (Type 0) Source */
|
||||||
class SMFSource : public MidiSource, public Evoral::LibSMF<double> {
|
class SMFSource : public MidiSource, public Evoral::SMF<double> {
|
||||||
public:
|
public:
|
||||||
enum Flag {
|
enum Flag {
|
||||||
Writable = 0x1,
|
Writable = 0x1,
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ uint64_t SMFSource::header_position_offset;
|
||||||
|
|
||||||
SMFSource::SMFSource (Session& s, std::string path, Flag flags)
|
SMFSource::SMFSource (Session& s, std::string path, Flag flags)
|
||||||
: MidiSource (s, region_name_from_path(path, false))
|
: MidiSource (s, region_name_from_path(path, false))
|
||||||
, Evoral::LibSMF<double> ()
|
, Evoral::SMF<double> ()
|
||||||
, _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
|
, _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
|
||||||
, _allow_remove_if_empty(true)
|
, _allow_remove_if_empty(true)
|
||||||
{
|
{
|
||||||
|
|
@ -146,7 +146,7 @@ SMFSource::read_unlocked (MidiRingBuffer<double>& dst, nframes_t start, nframes_
|
||||||
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
|
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
|
||||||
|
|
||||||
// FIXME: don't seek to start and search every read (brutal!)
|
// FIXME: don't seek to start and search every read (brutal!)
|
||||||
Evoral::LibSMF<double>::seek_to_start();
|
Evoral::SMF<double>::seek_to_start();
|
||||||
|
|
||||||
// FIXME: assumes tempo never changes after start
|
// FIXME: assumes tempo never changes after start
|
||||||
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
|
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
|
||||||
|
|
@ -155,7 +155,7 @@ SMFSource::read_unlocked (MidiRingBuffer<double>& dst, nframes_t start, nframes_
|
||||||
|
|
||||||
const uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * ppqn());
|
const uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * ppqn());
|
||||||
|
|
||||||
while (!Evoral::LibSMF<double>::eof()) {
|
while (!Evoral::SMF<double>::eof()) {
|
||||||
int ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
|
int ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
|
||||||
if (ret == -1) { // EOF
|
if (ret == -1) { // EOF
|
||||||
//cerr << "SMF - EOF\n";
|
//cerr << "SMF - EOF\n";
|
||||||
|
|
@ -251,7 +251,7 @@ SMFSource::write_unlocked (MidiRingBuffer<double>& src, nframes_t cnt)
|
||||||
make_sure_controls_have_the_right_interpolation();
|
make_sure_controls_have_the_right_interpolation();
|
||||||
}
|
}
|
||||||
|
|
||||||
Evoral::LibSMF<double>::flush();
|
Evoral::SMF<double>::flush();
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
const nframes_t oldlen = _length;
|
const nframes_t oldlen = _length;
|
||||||
|
|
@ -301,7 +301,7 @@ SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event<double>
|
||||||
delta_time = (uint32_t)((ev.time() - last_event_time()) * ppqn());
|
delta_time = (uint32_t)((ev.time() - last_event_time()) * ppqn());
|
||||||
}
|
}
|
||||||
|
|
||||||
Evoral::LibSMF<double>::append_event_delta(delta_time, ev);
|
Evoral::SMF<double>::append_event_delta(delta_time, ev);
|
||||||
|
|
||||||
_write_data_count += ev.size();
|
_write_data_count += ev.size();
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +356,7 @@ void
|
||||||
SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame)
|
SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame)
|
||||||
{
|
{
|
||||||
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
|
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
|
||||||
Evoral::LibSMF<double>::begin_write ();
|
Evoral::SMF<double>::begin_write ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -369,7 +369,7 @@ SMFSource::mark_streaming_write_completed ()
|
||||||
}
|
}
|
||||||
|
|
||||||
_model->set_edited(false);
|
_model->set_edited(false);
|
||||||
Evoral::LibSMF<double>::end_write ();
|
Evoral::SMF<double>::end_write ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -634,7 +634,7 @@ SMFSource::load_model(bool lock, bool force_reload)
|
||||||
}
|
}
|
||||||
|
|
||||||
_model->start_write();
|
_model->start_write();
|
||||||
Evoral::LibSMF<double>::seek_to_start();
|
Evoral::SMF<double>::seek_to_start();
|
||||||
|
|
||||||
uint64_t time = 0; /* in SMF ticks */
|
uint64_t time = 0; /* in SMF ticks */
|
||||||
Evoral::Event<double> ev;
|
Evoral::Event<double> ev;
|
||||||
|
|
@ -706,6 +706,6 @@ SMFSource::destroy_model()
|
||||||
void
|
void
|
||||||
SMFSource::flush_midi()
|
SMFSource::flush_midi()
|
||||||
{
|
{
|
||||||
Evoral::LibSMF<double>::end_write();
|
Evoral::SMF<double>::end_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ public:
|
||||||
SMF() : _last_ev_time(0), _smf(0), _smf_track(0), _empty(true) {};
|
SMF() : _last_ev_time(0), _smf(0), _smf_track(0), _empty(true) {};
|
||||||
virtual ~SMF();
|
virtual ~SMF();
|
||||||
|
|
||||||
|
int open(const std::string& path, bool create=true, int track=1) THROW_FILE_ERROR;
|
||||||
|
void close() THROW_FILE_ERROR;
|
||||||
|
|
||||||
void seek_to_start() const;
|
void seek_to_start() const;
|
||||||
|
|
||||||
uint16_t ppqn() const { return _ppqn; }
|
uint16_t ppqn() const { return _ppqn; }
|
||||||
|
|
@ -63,9 +66,6 @@ public:
|
||||||
int flush_footer() { return 0; }
|
int flush_footer() { return 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int open(const std::string& path) THROW_FILE_ERROR;
|
|
||||||
void close() THROW_FILE_ERROR;
|
|
||||||
|
|
||||||
int read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const;
|
int read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -42,40 +42,46 @@ SMF<Time>::~SMF()
|
||||||
* Currently SMF is always read/write.
|
* Currently SMF is always read/write.
|
||||||
*
|
*
|
||||||
* \return 0 on success
|
* \return 0 on success
|
||||||
* -1 if the file can not be opened
|
* -1 if the file can not be opened or created
|
||||||
|
* -2 if the file exists but specified track does not
|
||||||
*/
|
*/
|
||||||
template<typename Time>
|
template<typename Time>
|
||||||
int
|
int
|
||||||
SMF<Time>::open(const std::string& path) THROW_FILE_ERROR
|
SMF<Time>::open(const std::string& path, bool create, int track) THROW_FILE_ERROR
|
||||||
{
|
{
|
||||||
if (_smf) {
|
if (_smf) {
|
||||||
smf_delete(_smf);
|
smf_delete(_smf);
|
||||||
}
|
}
|
||||||
|
|
||||||
_path = path;
|
_path = path;
|
||||||
assert(_path != "");
|
|
||||||
|
|
||||||
_smf = smf_load(_path.c_str());
|
_smf = smf_load(_path.c_str());
|
||||||
if (!_smf) {
|
if (!_smf) {
|
||||||
|
if (!create) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
_smf = smf_new();
|
_smf = smf_new();
|
||||||
if (smf_set_ppqn(_smf, _ppqn) != 0) {
|
if (smf_set_ppqn(_smf, _ppqn) != 0) {
|
||||||
throw FileError();
|
throw FileError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_smf == NULL) {
|
if (_smf == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < track; ++i) {
|
||||||
_smf_track = smf_track_new();
|
_smf_track = smf_track_new();
|
||||||
assert(_smf_track);
|
assert(_smf_track);
|
||||||
|
|
||||||
smf_add_track(_smf, _smf_track);
|
smf_add_track(_smf, _smf_track);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_smf_track = smf_get_track_by_number(_smf, 1);
|
_smf_track = smf_get_track_by_number(_smf, track);
|
||||||
assert(_smf_track);
|
if (!_smf_track)
|
||||||
|
return -2;
|
||||||
|
|
||||||
cerr << "number of events: " << _smf_track->number_of_events << endl;
|
cerr << "Track " << track << " # events: " << _smf_track->number_of_events << endl;
|
||||||
|
|
||||||
_empty = !(_smf_track->number_of_events > 0);
|
_empty = !(_smf_track->number_of_events > 0);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue