set_block_size (_session.get_block_size());
allocate_temporary_buffers ();
-
- add_channel (1);
- assert(_n_channels == ChanCount(DataType::AUDIO, 1));
}
AudioDiskstream::~AudioDiskstream ()
{
Glib::Mutex::Lock lm (state_lock);
- if (input_change_pending == NoChange) {
+ if (input_change_pending.type == IOChange::NoChange) {
return;
}
set_align_style_from_io ();
}
- input_change_pending = NoChange;
+ input_change_pending = IOChange::NoChange;
/* implicit unlock */
}
/* now refill channel buffers */
if (speed() != 1.0f || speed() != -1.0f) {
- seek ((nframes_t) (_session.transport_frame() * (double) speed()));
+ seek ((framepos_t) (_session.transport_frame() * (double) speed()));
} else {
seek (_session.transport_frame());
}
}
void
-AudioDiskstream::non_realtime_locate (nframes_t location)
+AudioDiskstream::non_realtime_locate (framepos_t location)
{
/* now refill channel buffers */
if (speed() != 1.0f || speed() != -1.0f) {
- seek ((nframes_t) (location * (double) speed()));
+ seek ((framepos_t) (location * (double) speed()));
} else {
seek (location);
}
PropertyList plist;
plist.add (Properties::name, _name.val());
plist.add (Properties::start, 0);
- plist.add (Properties::length, max_frames - max_frames - srcs.front()->natural_position());
+ plist.add (Properties::length, max_framepos - (max_framepos - srcs.front()->natural_position()));
boost::shared_ptr<Region> region (RegionFactory::create (srcs, plist));
_playlist->add_region (region, srcs.front()->natural_position());
/* be sure to stretch the region out to the maximum length */
- region->set_length (max_frames - region->position(), this);
+ region->set_length (max_framepos - region->position(), this);
uint32_t n;
ChannelList::iterator chan;
}
void
-AudioDiskstream::prepare_record_status(nframes_t capture_start_frame)
+AudioDiskstream::prepare_record_status(framepos_t capture_start_frame)
{
if (recordable() && destructive()) {
boost::shared_ptr<ChannelList> c = channels.reader();
transvec.buf[0]->type = CaptureStart;
transvec.buf[0]->capture_val = capture_start_frame;
(*chan)->capture_transition_buf->increment_write_ptr(1);
- }
- else {
+ } else {
// bad!
fatal << X_("programming error: capture_transition_buf is full on rec start! inconceivable!")
<< endmsg;
}
int
-AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler)
+AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler)
{
uint32_t n;
boost::shared_ptr<ChannelList> c = channels.reader();
ChannelList::iterator chan;
int ret = -1;
- nframes_t rec_offset = 0;
- nframes_t rec_nframes = 0;
+ framecnt_t rec_offset = 0;
+ framecnt_t rec_nframes = 0;
bool collect_playback = false;
playback_distance = 0;
return 0;
}
- check_record_status (transport_frame, nframes, can_record);
+ check_record_status (transport_frame, can_record);
if (nframes == 0) {
return 0;
*/
- // Safeguard against situations where process() goes haywire when autopunching and last_recordable_frame < first_recordable_frame
+ // Safeguard against situations where process() goes haywire when autopunching
+ // and last_recordable_frame < first_recordable_frame
+
if (last_recordable_frame < first_recordable_frame) {
- last_recordable_frame = max_frames;
+ last_recordable_frame = max_framepos;
}
OverlapType ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
-
+
calculate_record_range (ot, transport_frame, nframes, rec_nframes, rec_offset);
if (rec_nframes && !was_recording) {
chaninfo->capture_buf->get_write_vector (&chaninfo->capture_vector);
- if (rec_nframes <= chaninfo->capture_vector.len[0]) {
+ if (rec_nframes <= (framecnt_t) chaninfo->capture_vector.len[0]) {
chaninfo->current_capture_buffer = chaninfo->capture_vector.buf[0];
AudioPort* const ap = _io->audio (n);
assert(ap);
- assert(rec_nframes <= ap->get_audio_buffer(nframes).capacity());
+ assert(rec_nframes <= (framecnt_t) ap->get_audio_buffer(nframes).capacity());
memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (nframes).data(rec_offset), sizeof (Sample) * rec_nframes);
} else {
- nframes_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1];
+ framecnt_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1];
if (rec_nframes > total) {
DiskOverrun ();
assert(ap);
Sample* buf = ap->get_audio_buffer(nframes).data();
- nframes_t first = chaninfo->capture_vector.len[0];
+ framecnt_t first = chaninfo->capture_vector.len[0];
memcpy (chaninfo->capture_wrap_buffer, buf, sizeof (Sample) * first);
memcpy (chaninfo->capture_vector.buf[0], buf, sizeof (Sample) * first);
/* we're doing playback */
- nframes_t necessary_samples;
+ framecnt_t necessary_samples;
/* no varispeed playback if we're recording, because the output .... TBD */
if (rec_nframes == 0 && _actual_speed != 1.0f) {
- necessary_samples = (nframes_t) floor ((nframes * fabs (_actual_speed))) + 1;
+ necessary_samples = (framecnt_t) floor ((nframes * fabs (_actual_speed))) + 1;
} else {
necessary_samples = nframes;
}
ChannelInfo* chaninfo (*chan);
- if (necessary_samples <= chaninfo->playback_vector.len[0]) {
+ if (necessary_samples <= (framecnt_t) chaninfo->playback_vector.len[0]) {
chaninfo->current_playback_buffer = chaninfo->playback_vector.buf[0];
} else {
- nframes_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1];
+ framecnt_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1];
if (necessary_samples > total) {
cerr << _name << " Need " << necessary_samples << " total = " << total << endl;
}
void
-AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr<ChannelList> c)
+AudioDiskstream::process_varispeed_playback (pframes_t nframes, boost::shared_ptr<ChannelList> c)
{
ChannelList::iterator chan;
}
bool
-AudioDiskstream::commit (nframes_t /* nframes */)
+AudioDiskstream::commit (framecnt_t /* nframes */)
{
bool need_butler = false;
capture_captured += adjust_capture_position;
adjust_capture_position = 0;
}
-
+
+ if (c->empty()) {
+ return false;
+ }
+
if (_slaved) {
if (_io && _io->active()) {
need_butler = c->front()->playback_buf->write_space() >= c->front()->playback_buf->bufsize() / 2;
}
} else {
if (_io && _io->active()) {
- need_butler = c->front()->playback_buf->write_space() >= disk_io_chunk_frames
- || c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
+ need_butler = ((framecnt_t) c->front()->playback_buf->write_space() >= disk_io_chunk_frames)
+ || ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames);
} else {
- need_butler = c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
+ need_butler = ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames);
}
}
_pending_overwrite = yn;
overwrite_frame = playback_sample;
- overwrite_offset = channels.reader()->front()->playback_buf->get_read_ptr();
+
+ boost::shared_ptr<ChannelList> c = channels.reader ();
+ if (!c->empty ()) {
+ overwrite_offset = c->front()->playback_buf->get_read_ptr();
+ }
}
int
AudioDiskstream::overwrite_existing_buffers ()
{
boost::shared_ptr<ChannelList> c = channels.reader();
+ if (c->empty ()) {
+ _pending_overwrite = false;
+ return 0;
+ }
+
Sample* mixdown_buffer;
float* gain_buffer;
int ret = -1;
overwrite_queued = false;
/* assume all are the same size */
- nframes_t size = c->front()->playback_buf->bufsize();
+ framecnt_t size = c->front()->playback_buf->bufsize();
mixdown_buffer = new Sample[size];
gain_buffer = new float[size];
size--;
uint32_t n=0;
- nframes_t start;
+ framepos_t start;
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) {
start = overwrite_frame;
- nframes_t cnt = size;
+ framecnt_t cnt = size;
/* to fill the buffer without resetting the playback sample, we need to
do it one or two chunks (normally two).
*/
- nframes_t to_read = size - overwrite_offset;
+ framecnt_t to_read = size - overwrite_offset;
if (read ((*chan)->playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, start, to_read, *chan, n, reversed)) {
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
}
int
-AudioDiskstream::seek (nframes_t frame, bool complete_refill)
+AudioDiskstream::seek (framepos_t frame, bool complete_refill)
{
uint32_t n;
int ret = -1;
}
int
-AudioDiskstream::can_internal_playback_seek (nframes_t distance)
+AudioDiskstream::can_internal_playback_seek (framecnt_t distance)
{
ChannelList::iterator chan;
boost::shared_ptr<ChannelList> c = channels.reader();
for (chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan)->playback_buf->read_space() < distance) {
+ if ((*chan)->playback_buf->read_space() < (size_t) distance) {
return false;
}
}
}
int
-AudioDiskstream::internal_playback_seek (nframes_t distance)
+AudioDiskstream::internal_playback_seek (framecnt_t distance)
{
ChannelList::iterator chan;
boost::shared_ptr<ChannelList> c = channels.reader();
(*chan)->playback_buf->increment_read_ptr (distance);
}
- first_recordable_frame += distance;
+ if (first_recordable_frame < max_framepos) {
+ first_recordable_frame += distance;
+ }
playback_sample += distance;
return 0;
}
int
-AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, nframes_t& start, nframes_t cnt,
+AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
+ framepos_t& start, framecnt_t cnt,
ChannelInfo* /*channel_info*/, int channel, bool reversed)
{
- nframes_t this_read = 0;
+ framecnt_t this_read = 0;
bool reloop = false;
- nframes_t loop_end = 0;
- nframes_t loop_start = 0;
- nframes_t offset = 0;
+ framepos_t loop_end = 0;
+ framepos_t loop_start = 0;
+ framecnt_t offset = 0;
Location *loc = 0;
/* XXX we don't currently play loops in reverse. not sure why */
if (!reversed) {
- nframes_t loop_length = 0;
+ framecnt_t loop_length = 0;
/* Make the use of a Location atomic for this read operation.
//cerr << "start is " << start << " loopstart: " << loop_start << " loopend: " << loop_end << endl;
}
+ if (reversed) {
+ start -= cnt;
+ }
+
while (cnt) {
- if (reversed) {
- start -= cnt;
- }
-
/* take any loop into account. we can't read past the end of the loop. */
if (loc && (loop_end - start < cnt)) {
AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
{
int32_t ret = 0;
- nframes_t to_read;
+ framecnt_t to_read;
RingBufferNPT<Sample>::rw_vector vector;
bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
- nframes_t total_space;
- nframes_t zero_fill;
+ framecnt_t total_space;
+ framecnt_t zero_fill;
uint32_t chan_n;
ChannelList::iterator i;
boost::shared_ptr<ChannelList> c = channels.reader();
- nframes_t ts;
+ framecnt_t ts;
if (c->empty()) {
return 0;
work with.
*/
- if (_slaved && total_space < (c->front()->playback_buf->bufsize() / 2)) {
+ if (_slaved && total_space < (framecnt_t) (c->front()->playback_buf->bufsize() / 2)) {
return 0;
}
zero_fill = total_space - file_frame;
total_space = file_frame;
- file_frame = 0;
} else {
} else {
- if (file_frame == max_frames) {
+ if (file_frame == max_framepos) {
/* at end: nothing to do but fill with silence */
return 0;
}
- if (file_frame > max_frames - total_space) {
+ if (file_frame > max_framepos - total_space) {
/* to close to the end: read what we can, and zero fill the rest */
- zero_fill = total_space - (max_frames - file_frame);
- total_space = max_frames - file_frame;
+ zero_fill = total_space - (max_framepos - file_frame);
+ total_space = max_framepos - file_frame;
} else {
zero_fill = 0;
}
}
- nframes_t file_frame_tmp = 0;
+ framepos_t file_frame_tmp = 0;
for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
ChannelInfo* chan (*i);
Sample* buf1;
Sample* buf2;
- nframes_t len1, len2;
+ framecnt_t len1, len2;
chan->playback_buf->get_write_vector (&vector);
- if (vector.len[0] > disk_io_chunk_frames) {
+ if ((framecnt_t) vector.len[0] > disk_io_chunk_frames) {
/* we're not going to fill the first chunk, so certainly do not bother with the
other part. it won't be connected with the part we do fill, as in:
to_read = min (ts, len1);
to_read = min (to_read, disk_io_chunk_frames);
+ assert (to_read >= 0);
+
if (to_read) {
if (read (buf1, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan, chan_n, reversed)) {
}
file_frame = file_frame_tmp;
-
+ assert (file_frame >= 0);
+
out:
return ret;
int32_t ret = 0;
RingBufferNPT<Sample>::rw_vector vector;
RingBufferNPT<CaptureTransition>::rw_vector transvec;
- nframes_t total;
+ framecnt_t total;
_write_data_count = 0;
ret = 1;
}
- to_write = min (disk_io_chunk_frames, (nframes_t) vector.len[0]);
+ to_write = min (disk_io_chunk_frames, (framecnt_t) vector.len[0]);
// check the transition buffer when recording destructive
// important that we get this after the capture buf
of vector.len[1] to be flushed to disk as well.
*/
- to_write = min ((nframes_t)(disk_io_chunk_frames - to_write), (nframes_t) vector.len[1]);
+ to_write = min ((framecnt_t)(disk_io_chunk_frames - to_write), (framecnt_t) vector.len[1]);
if ((*chan)->write_source->write (vector.buf[1], to_write) != to_write) {
error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
bool more_work = true;
int err = 0;
boost::shared_ptr<AudioRegion> region;
- nframes_t total_capture;
+ framecnt_t total_capture;
SourceList srcs;
SourceList::iterator src;
ChannelList::iterator chan;
if (s) {
srcs.push_back (s);
+ if (s->unstubify ()) {
+ error << string_compose (_("Could not move capture file from %1"), s->path()) << endmsg;
+ }
s->update_header (capture_info.front()->start, when, twhen);
s->set_captured_for (_name.val());
s->mark_immutable ();
+
if (Config->get_auto_analyse_audio()) {
Analyser::queue_source_for_analysis (s, true);
}
// cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
- _playlist->clear_history ();
+ _playlist->clear_changes ();
_playlist->freeze ();
for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
}
i_am_the_modifier++;
+
+ if (_playlist->explicit_relayering()) {
+ /* We are in `explicit relayering' mode, so we must specify which layer this new region
+ should end up on. Put it at the top.
+ */
+ region->set_layer (_playlist->top_layer() + 1);
+ region->set_pending_explicit_relayer (true);
+ }
+
_playlist->add_region (region, (*ci)->start, 1, non_layered());
i_am_the_modifier--;
}
void
-AudioDiskstream::transport_looped (nframes_t transport_frame)
+AudioDiskstream::transport_looped (framepos_t transport_frame)
{
if (was_recording) {
// all we need to do is finish this capture, with modified capture length
// no latency adjustment or capture offset needs to be made, as that already happened the first time
capture_start_frame = transport_frame;
first_recordable_frame = transport_frame; // mild lie
- last_recordable_frame = max_frames;
+ last_recordable_frame = max_framepos;
was_recording = true;
if (recordable() && destructive()) {
AudioDiskstream::finish_capture (bool /*rec_monitors_input*/, boost::shared_ptr<ChannelList> c)
{
was_recording = false;
- first_recordable_frame = max_frames;
- last_recordable_frame = max_frames;
+ first_recordable_frame = max_framepos;
+ last_recordable_frame = max_framepos;
if (capture_captured == 0) {
return;
capture_captured = 0;
/* now we've finished a capture, reset first_recordable_frame for next time */
- first_recordable_frame = max_frames;
+ first_recordable_frame = max_framepos;
}
void
ChannelInfo* chan = (*c)[n];
- if (chan->write_source) {
- chan->write_source->done_with_peakfile_writes ();
- chan->write_source->set_allow_remove_if_empty (true);
- chan->write_source.reset ();
- }
-
try {
- if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(), name(), n, destructive())) == 0) {
+ /* file starts off as a stub file, it will be converted
+ when we're done with a capture pass.
+ */
+
+ if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(),
+ name(), n, destructive(),
+ true)) == 0) {
throw failed_constructor();
}
}
chan->write_source->set_allow_remove_if_empty (!destructive());
- /* until we write, this file is considered removable */
-
- chan->write_source->mark_for_remove ();
-
return 0;
}
capturing_sources.clear ();
for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
+
if (!destructive()) {
- if ((*chan)->write_source && mark_write_complete) {
- (*chan)->write_source->mark_streaming_write_completed ();
- }
+ if ((*chan)->write_source) {
+
+ if (mark_write_complete) {
+ (*chan)->write_source->mark_streaming_write_completed ();
+ (*chan)->write_source->done_with_peakfile_writes ();
+ }
+
+ if ((*chan)->write_source->removable()) {
+ (*chan)->write_source->mark_for_remove ();
+ (*chan)->write_source->drop_references ();
+ }
+
+ (*chan)->write_source.reset ();
+ }
+
use_new_write_source (n);
if (record_enabled()) {
}
} else {
+
if ((*chan)->write_source == 0) {
use_new_write_source (n);
}
}
void
-AudioDiskstream::set_block_size (nframes_t /*nframes*/)
+AudioDiskstream::set_block_size (pframes_t /*nframes*/)
{
if (_session.get_block_size() > speed_buffer_size) {
speed_buffer_size = _session.get_block_size();
*/
double const sp = max (fabsf (_actual_speed), 1.2f);
- nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() * sp) + 1;
+ framecnt_t required_wrap_size = (framecnt_t) floor (_session.get_block_size() * sp) + 1;
if (required_wrap_size > wrap_buffer_size) {
{
boost::shared_ptr<ChannelList> c = channels.reader();
+ if (c->empty ()) {
+ return 0;
+ }
+
return (float) ((double) c->front()->playback_buf->read_space()/
(double) c->front()->playback_buf->bufsize());
}
{
boost::shared_ptr<ChannelList> c = channels.reader();
+ if (c->empty ()) {
+ return 0;
+ }
+
return (float) ((double) c->front()->capture_buf->write_space()/
(double) c->front()->capture_buf->bufsize());
}
boost::shared_ptr<AudioFileSource> fs;
boost::shared_ptr<AudioFileSource> first_fs;
SourceList pending_sources;
- nframes_t position;
+ framepos_t position;
if ((prop = node.property (X_("at"))) == 0) {
return -1;
}
- if (sscanf (prop->value().c_str(), "%" PRIu32, &position) != 1) {
+ if (sscanf (prop->value().c_str(), "%" PRIu64, &position) != 1) {
return -1;
}
try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, _session,
- prop->value(), false, _session.frame_rate()));
+ prop->value(), string(), false, _session.frame_rate()));
}
catch (failed_constructor& err) {
}
}
-AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t playback_bufsize, nframes_t capture_bufsize, nframes_t speed_size, nframes_t wrap_size)
+AudioDiskstream::ChannelInfo::ChannelInfo (framecnt_t playback_bufsize, framecnt_t capture_bufsize, framecnt_t speed_size, framecnt_t wrap_size)
{
peak_power = 0.0f;
source = 0;
}
void
-AudioDiskstream::ChannelInfo::resize_playback (nframes_t playback_bufsize)
+AudioDiskstream::ChannelInfo::resize_playback (framecnt_t playback_bufsize)
{
delete playback_buf;
playback_buf = new RingBufferNPT<Sample> (playback_bufsize);
}
void
-AudioDiskstream::ChannelInfo::resize_capture (nframes_t capture_bufsize)
+AudioDiskstream::ChannelInfo::resize_capture (framecnt_t capture_bufsize)
{
delete capture_buf;