2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* see gdither.cc for why we have to do this */
22 #define _ISOC9X_SOURCE 1
23 #define _ISOC99_SOURCE 1
36 #include <sigc++/bind.h>
38 #include <pbd/error.h>
39 #include <glibmm/thread.h>
41 #include <ardour/gdither.h>
42 #include <ardour/timestamps.h>
43 #include <ardour/ardour.h>
44 #include <ardour/session.h>
45 #include <ardour/export.h>
46 #include <ardour/sndfile_helpers.h>
47 #include <ardour/port.h>
48 #include <ardour/audio_port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/audio_diskstream.h>
51 #include <ardour/panner.h>
56 using namespace ARDOUR;
60 convert_spec_to_info (ExportSpecification& spec, SF_INFO& sfinfo)
62 if (spec.path.length() == 0) {
63 error << _("Export: no output file specified") << endmsg;
67 /* XXX add checks that the directory path exists, and also
68 check if we are overwriting an existing file...
71 sfinfo.format = spec.format;
72 sfinfo.samplerate = spec.sample_rate;
73 sfinfo.frames = spec.end_frame - spec.start_frame + 1;
74 sfinfo.channels = min (spec.channels, 2U);
79 ExportSpecification::ExportSpecification ()
84 ExportSpecification::~ExportSpecification ()
90 ExportSpecification::init ()
107 max_leftover_frames = 0;
112 do_freewheel = false;
116 ExportSpecification::clear ()
124 src_delete (src_state);
129 gdither_free (dither);
150 freewheel_connection.disconnect ();
156 ExportSpecification::prepare (nframes_t blocksize, nframes_t frate)
159 GDitherSize dither_size;
164 error << _("illegal channel count in export specification") << endmsg;
168 if (start_frame >= end_frame) {
169 error << _("illegal frame range in export specification") << endmsg;
173 if ((data_width = sndfile_data_width(format)) == 0) {
174 error << _("Bad data width size. Report me!") << endmsg;
178 switch (data_width) {
180 dither_size = GDither8bit;
184 dither_size = GDither16bit;
188 dither_size = GDither32bit;
192 dither_size = GDitherFloat;
196 if (convert_spec_to_info (*this, sfinfo)) {
200 /* XXX make sure we have enough disk space for the output */
202 if ((out = sf_open (path.c_str(), SFM_WRITE, &sfinfo)) == 0) {
203 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
204 error << string_compose(_("Export: cannot open output file \"%1\" (%2)"), path, errbuf) << endmsg;
208 dataF = new float[blocksize * channels];
210 if (sample_rate != frame_rate) {
213 if ((src_state = src_new (src_quality, channels, &err)) == 0) {
214 error << string_compose (_("cannot initialize sample rate conversion: %1"), src_strerror (err)) << endmsg;
218 src_data.src_ratio = sample_rate / (double) frame_rate;
219 out_samples_max = (nframes_t) ceil (blocksize * src_data.src_ratio * channels);
220 dataF2 = new float[out_samples_max];
222 max_leftover_frames = 4 * blocksize;
223 leftoverF = new float[max_leftover_frames * channels];
227 out_samples_max = blocksize * channels;
230 dither = gdither_new (dither_type, channels, dither_size, data_width);
232 /* allocate buffers where dithering and output will occur */
234 switch (data_width) {
249 sample_bytes = 0; // float format
254 output_data = (void*) malloc (sample_bytes * out_samples_max);
258 end_frame = end_frame;
259 total_frames = end_frame - start_frame;
261 do_freewheel = false; /* force a call to ::prepare_to_export() before proceeding to normal operation */
267 ExportSpecification::process (nframes_t nframes)
269 float* float_buffer = 0;
275 nframes_t to_write = 0;
280 /* now do sample rate conversion */
282 if (sample_rate != frame_rate) {
286 src_data.output_frames = out_samples_max / channels;
287 src_data.end_of_input = ((pos + nframes) >= end_frame);
288 src_data.data_out = dataF2;
290 if (leftover_frames > 0) {
292 /* input data will be in leftoverF rather than dataF */
294 src_data.data_in = leftoverF;
298 /* first time, append new data from dataF into the leftoverF buffer */
300 memcpy (leftoverF + (leftover_frames * channels), dataF, nframes * channels * sizeof(float));
301 src_data.input_frames = nframes + leftover_frames;
304 /* otherwise, just use whatever is still left in leftoverF; the contents
305 were adjusted using memmove() right after the last SRC call (see
309 src_data.input_frames = leftover_frames;
314 src_data.data_in = dataF;
315 src_data.input_frames = nframes;
321 if ((err = src_process (src_state, &src_data)) != 0) {
322 error << string_compose (_("an error occured during sample rate conversion: %1"),
328 to_write = src_data.output_frames_gen;
329 leftover_frames = src_data.input_frames - src_data.input_frames_used;
331 if (leftover_frames > 0) {
332 if (leftover_frames > max_leftover_frames) {
333 error << _("warning, leftover frames overflowed, glitches might occur in output") << endmsg;
334 leftover_frames = max_leftover_frames;
336 memmove (leftoverF, (char *) (src_data.data_in + (src_data.input_frames_used * channels)),
337 leftover_frames * channels * sizeof(float));
340 float_buffer = dataF2;
344 /* no SRC, keep it simple */
348 float_buffer = dataF;
352 memset (output_data, 0, sample_bytes * to_write * channels);
355 switch (data_width) {
359 for (chn = 0; chn < channels; ++chn) {
360 gdither_runf (dither, chn, to_write, float_buffer, output_data);
365 for (chn = 0; chn < channels; ++chn) {
367 int *ob = (int *) output_data;
368 const double int_max = (float) INT_MAX;
369 const double int_min = (float) INT_MIN;
371 for (x = 0; x < to_write; ++x) {
372 i = chn + (x * channels);
374 if (float_buffer[i] > 1.0f) {
376 } else if (float_buffer[i] < -1.0f) {
379 if (float_buffer[i] >= 0.0f) {
380 ob[i] = lrintf (int_max * float_buffer[i]);
382 ob[i] = - lrintf (int_min * float_buffer[i]);
390 for (x = 0; x < to_write * channels; ++x) {
391 if (float_buffer[x] > 1.0f) {
392 float_buffer[x] = 1.0f;
393 } else if (float_buffer[x] < -1.0f) {
394 float_buffer[x] = -1.0f;
400 /* and export to disk */
402 switch (data_width) {
404 /* XXXX no way to deliver 8 bit audio to libsndfile */
409 written = sf_writef_short (out, (short*) output_data, to_write);
414 written = sf_writef_int (out, (int*) output_data, to_write);
418 written = sf_writef_float (out, float_buffer, to_write);
422 if ((nframes_t) written != to_write) {
423 sf_error_str (out, errbuf, sizeof (errbuf) - 1);
424 error << string_compose(_("Export: could not write data to output file (%1)"), errbuf) << endmsg;
429 } while (leftover_frames >= nframes);
435 Session::start_export (ExportSpecification& spec)
437 if (!_engine.connected()) {
441 if (spec.prepare (current_block_size, frame_rate())) {
445 spec.freewheel_connection = _engine.Freewheel.connect (sigc::bind (mem_fun (*this, &Session::process_export), &spec));
447 cerr << "Start export at pos = " << spec.pos << endl;
449 return _engine.freewheel (true);
453 Session::stop_export (ExportSpecification& spec)
455 /* don't stop freewheeling but do stop paying attention to it for now */
457 spec.freewheel_connection.disconnect ();
458 spec.clear (); /* resets running/stop etc */
460 Exported (spec.path, name());
466 Session::pre_export ()
468 wait_till_butler_finished ();
470 /* take everyone out of awrite to avoid disasters */
473 boost::shared_ptr<RouteList> r = routes.reader ();
475 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
476 (*i)->protect_automation ();
480 /* make sure we are actually rolling */
482 if (get_record_enabled()) {
483 disable_record (false);
488 post_export_slave = Config->get_slave_source ();
489 post_export_position = _transport_frame;
491 Config->set_slave_source (None);
497 Session::prepare_to_export (ExportSpecification& spec)
501 /* get everyone to the right position */
504 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
506 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
507 if ((*i)-> seek (spec.start_frame, true)) {
508 error << string_compose (_("%1: cannot seek to %2 for export"),
509 (*i)->name(), spec.start_frame)
516 cerr << "Everybdy is at " << spec.start_frame << endl;
518 /* we just did the core part of a locate() call above, but
519 for the sake of any GUI, put the _transport_frame in
523 _transport_frame = spec.start_frame;
526 /* get transport ready. note how this is calling butler functions
527 from a non-butler thread. we waited for the butler to stop
528 what it was doing earlier in Session::pre_export() and nothing
529 since then has re-awakened it.
532 set_transport_speed (1.0, false);
533 butler_transport_work ();
534 g_atomic_int_set (&butler_should_do_transport_work, 0);
537 /* we are ready to go ... */
546 Session::process_export (nframes_t nframes, ExportSpecification* spec)
551 nframes_t this_nframes;
553 cerr << "Export process at pos = " << spec->pos << " _exporting = "
554 << _exporting << " running = " << spec->running << " stop = "
555 << spec->stop << endl;
557 /* This is not required to be RT-safe because we are running while freewheeling */
559 if (spec->do_freewheel == false) {
561 /* first time in export function: get set up */
563 if (prepare_to_export (*spec)) {
564 spec->running = false;
569 spec->do_freewheel = true;
573 /* finished, but still freewheeling */
574 cerr << "\tExport ... not exporting yet, no_roll() for " << nframes <<endl;
575 no_roll (nframes, 0);
579 if (!spec->running || spec->stop || (this_nframes = min ((spec->end_frame - spec->pos), nframes)) == 0) {
580 cerr << "\tExport ... not running or at end, no_roll() for " << nframes <<endl;
581 no_roll (nframes, 0);
582 return stop_export (*spec);
585 /* make sure we've caught up with disk i/o, since
586 we're running faster than realtime c/o JACK.
589 wait_till_butler_finished ();
591 /* do the usual stuff */
593 process_without_events (nframes);
595 /* and now export the results */
597 nframes = this_nframes;
599 memset (spec->dataF, 0, sizeof (spec->dataF[0]) * nframes * spec->channels);
601 /* foreach output channel ... */
603 for (chn = 0; chn < spec->channels; ++chn) {
605 ExportPortMap::iterator mi = spec->port_map.find (chn);
607 if (mi == spec->port_map.end()) {
608 /* no ports exported to this channel */
612 vector<PortChannelPair>& mapped_ports ((*mi).second);
614 for (vector<PortChannelPair>::iterator t = mapped_ports.begin(); t != mapped_ports.end(); ++t) {
616 /* OK, this port's output is supposed to appear on this channel
619 AudioPort* const aport = dynamic_cast<AudioPort*>((*t).first);
620 MidiPort* const mport = dynamic_cast<MidiPort*>((*t).first);
622 Sample* port_buffer = aport->get_audio_buffer().data();
624 /* now interleave the data from the channel into the float buffer */
626 for (x = 0; x < nframes; ++x) {
627 spec->dataF[chn+(x*spec->channels)] += (float) port_buffer[x];
629 } else if (mport != 0) {
630 cerr << "EXPORT MIDI PORT" << endl;
635 cerr << "\tprocess " << nframes << endl;
637 if (spec->process (nframes)) {
641 spec->pos += nframes;
642 spec->progress = 1.0 - (((float) spec->end_frame - spec->pos) / spec->total_frames);
644 cerr << "\t@ " << spec->pos << " prog = " << spec->progress << endl;
646 /* and we're good to go */
652 sf_close (spec->out);
654 unlink (spec->path.c_str());
655 spec->running = false;
664 Session::finalize_export ()
666 _engine.freewheel (false);
669 /* can't use stop_transport() here because we need
670 an immediate halt and don't require all the declick
671 stuff that stop_transport() implements.
674 realtime_stop (true);
675 schedule_butler_transport_work ();
677 /* restart slaving */
679 if (post_export_slave != None) {
680 Config->set_slave_source (post_export_slave);
682 locate (post_export_position, false, false, false);