mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-18 20:56:28 +01:00
MIDI vari-speed playback
This commit is contained in:
parent
3139b7e980
commit
7619946b4b
4 changed files with 61 additions and 24 deletions
|
|
@ -68,6 +68,13 @@ public:
|
||||||
framecnt_t interpolate (int channel, framecnt_t nframes, Sample* input, Sample* output);
|
framecnt_t interpolate (int channel, framecnt_t nframes, Sample* input, Sample* output);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BufferSet;
|
||||||
|
|
||||||
|
class LIBARDOUR_API CubicMidiInterpolation : public Interpolation {
|
||||||
|
public:
|
||||||
|
framecnt_t distance (framecnt_t nframes, bool roll = true);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include "ardour/diskstream.h"
|
#include "ardour/diskstream.h"
|
||||||
#include "ardour/midi_buffer.h"
|
#include "ardour/midi_buffer.h"
|
||||||
#include "ardour/utils.h"
|
#include "ardour/utils.h"
|
||||||
|
#include "ardour/interpolation.h"
|
||||||
|
|
||||||
struct tm;
|
struct tm;
|
||||||
|
|
||||||
|
|
@ -186,6 +187,8 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream
|
||||||
*/
|
*/
|
||||||
MidiBuffer _gui_feed_buffer;
|
MidiBuffer _gui_feed_buffer;
|
||||||
mutable Glib::Threads::Mutex _gui_feed_buffer_mutex;
|
mutable Glib::Threads::Mutex _gui_feed_buffer_mutex;
|
||||||
|
|
||||||
|
CubicMidiInterpolation interpolation;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace ARDOUR */
|
}; /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "ardour/interpolation.h"
|
#include "ardour/interpolation.h"
|
||||||
|
#include "ardour/midi_buffer.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
|
@ -150,3 +151,38 @@ CubicInterpolation::interpolate (int channel, framecnt_t nframes, Sample *input,
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
framecnt_t
|
||||||
|
CubicMidiInterpolation::distance (framecnt_t nframes, bool roll)
|
||||||
|
{
|
||||||
|
assert(phase.size() == 1);
|
||||||
|
|
||||||
|
framecnt_t i = 0;
|
||||||
|
|
||||||
|
double acceleration;
|
||||||
|
double distance = 0.0;
|
||||||
|
|
||||||
|
if (nframes < 3) {
|
||||||
|
return nframes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_speed != _target_speed) {
|
||||||
|
acceleration = _target_speed - _speed;
|
||||||
|
} else {
|
||||||
|
acceleration = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance = phase[0];
|
||||||
|
|
||||||
|
for (framecnt_t outsample = 0; outsample < nframes; ++outsample) {
|
||||||
|
distance += _speed + acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roll) {
|
||||||
|
phase[0] = distance - floor(distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = floor(distance);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,7 @@ MidiDiskstream::init ()
|
||||||
_capture_buf = new MidiRingBuffer<framepos_t>(size);
|
_capture_buf = new MidiRingBuffer<framepos_t>(size);
|
||||||
|
|
||||||
_n_channels = ChanCount(DataType::MIDI, 1);
|
_n_channels = ChanCount(DataType::MIDI, 1);
|
||||||
|
interpolation.add_channel_to (0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiDiskstream::~MidiDiskstream ()
|
MidiDiskstream::~MidiDiskstream ()
|
||||||
|
|
@ -522,44 +523,35 @@ MidiDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
|
||||||
|
|
||||||
playback_distance = nframes;
|
playback_distance = nframes;
|
||||||
|
|
||||||
|
} else if (_actual_speed != 1.0f && _target_speed > 0) {
|
||||||
|
|
||||||
|
interpolation.set_speed (_target_speed);
|
||||||
|
|
||||||
|
playback_distance = interpolation.distance (nframes);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* XXX: should be doing varispeed stuff here, similar to the code in AudioDiskstream::process */
|
|
||||||
|
|
||||||
playback_distance = nframes;
|
playback_distance = nframes;
|
||||||
|
|
||||||
#ifndef NO_SIMPLE_MIDI_VARISPEED
|
|
||||||
if (_target_speed > 0) {
|
|
||||||
playback_distance = nframes * _target_speed;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_disk_signal) {
|
if (need_disk_signal) {
|
||||||
/* copy the diskstream data to all output buffers */
|
/* copy the diskstream data to all output buffers */
|
||||||
|
|
||||||
MidiBuffer& mbuf (bufs.get_midi (0));
|
MidiBuffer& mbuf (bufs.get_midi (0));
|
||||||
#ifndef NO_SIMPLE_MIDI_VARISPEED
|
get_playback (mbuf, playback_distance);
|
||||||
get_playback (mbuf, nframes * _target_speed);
|
|
||||||
#else
|
|
||||||
get_playback (mbuf, nframes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* leave the audio count alone */
|
/* leave the audio count alone */
|
||||||
ChanCount cnt (DataType::MIDI, 1);
|
ChanCount cnt (DataType::MIDI, 1);
|
||||||
cnt.set (DataType::AUDIO, bufs.count().n_audio());
|
cnt.set (DataType::AUDIO, bufs.count().n_audio());
|
||||||
bufs.set_count (cnt);
|
bufs.set_count (cnt);
|
||||||
|
|
||||||
#ifndef NO_SIMPLE_MIDI_VARISPEED
|
/* vari-speed */
|
||||||
if (_target_speed > 0 && playback_distance != nframes) {
|
if (_target_speed > 0 && _actual_speed != 1.0f) {
|
||||||
MidiBuffer& mbuf (bufs.get_midi (0));
|
MidiBuffer& mbuf (bufs.get_midi (0));
|
||||||
for (MidiBuffer::iterator i = mbuf.begin(); i != mbuf.end(); ++i) {
|
for (MidiBuffer::iterator i = mbuf.begin(); i != mbuf.end(); ++i) {
|
||||||
MidiBuffer::TimeType *tme = i.timeptr();
|
MidiBuffer::TimeType *tme = i.timeptr();
|
||||||
*tme = (*tme) / _target_speed;
|
*tme = (*tme) * nframes / playback_distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -568,14 +560,13 @@ MidiDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
|
||||||
frameoffset_t
|
frameoffset_t
|
||||||
MidiDiskstream::calculate_playback_distance (pframes_t nframes)
|
MidiDiskstream::calculate_playback_distance (pframes_t nframes)
|
||||||
{
|
{
|
||||||
#ifndef NO_SIMPLE_MIDI_VARISPEED
|
|
||||||
frameoffset_t playback_distance = nframes * _target_speed;
|
|
||||||
#else
|
|
||||||
frameoffset_t playback_distance = nframes;
|
frameoffset_t playback_distance = nframes;
|
||||||
|
|
||||||
/* XXX: should be doing varispeed stuff once it's implemented in ::process() above */
|
if (!record_enabled() && _actual_speed != 1.0f && _actual_speed > 0.f) {
|
||||||
|
interpolation.set_speed (_target_speed);
|
||||||
|
playback_distance = interpolation.distance (nframes, false);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
if (_actual_speed < 0.0) {
|
if (_actual_speed < 0.0) {
|
||||||
return -playback_distance;
|
return -playback_distance;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue