fix errors in multi-range export (and possibly other export styles); compiler warning...
[ardour.git] / libs / ardour / session_export.cc
1 /*
2     Copyright (C) 1999-2002 Paul Davis 
3
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.
8
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.
13
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.
17
18 */
19
20 /* see gdither.cc for why we have to do this */
21
22 #define _ISOC9X_SOURCE  1
23 #define _ISOC99_SOURCE  1
24 #include <cmath>
25 #undef  _ISOC99_SOURCE
26 #undef  _ISOC9X_SOURCE
27 #undef  __USE_SVID 
28 #define __USE_SVID 1
29 #include <cstdlib>
30 #undef  __USE_SVID
31
32 #include <unistd.h>
33 #include <inttypes.h>
34 #include <float.h>
35
36 #include <sigc++/bind.h>
37
38 #include <pbd/error.h>
39 #include <glibmm/thread.h>
40
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/audioengine.h>
49 #include <ardour/audio_diskstream.h>
50 #include <ardour/panner.h>
51
52 #include "i18n.h"
53
54 using namespace std;
55 using namespace ARDOUR;
56 using namespace PBD;
57
58 static int
59 convert_spec_to_info (AudioExportSpecification& spec, SF_INFO& sfinfo)
60 {
61         if (spec.path.length() == 0) {
62                 error << _("Export: no output file specified") << endmsg;
63                 return -1;
64         }
65
66         /* XXX add checks that the directory path exists, and also 
67            check if we are overwriting an existing file...
68         */
69
70         sfinfo.format = spec.format;
71         sfinfo.samplerate = spec.sample_rate;
72         sfinfo.frames = spec.end_frame - spec.start_frame + 1;
73         sfinfo.channels = min (spec.channels, 2U);
74
75         return 0;
76 }
77
78 AudioExportSpecification::AudioExportSpecification ()
79 {
80         init ();
81 }
82
83 AudioExportSpecification::~AudioExportSpecification ()
84 {
85         clear ();
86 }
87
88 void
89 AudioExportSpecification::init ()
90 {
91         src_state = 0;
92         pos = 0;
93         total_frames = 0;
94         out = 0;
95         channels = 0;
96         running = false;
97         stop = false;
98         progress = 0.0;
99         status = 0;
100         dither = 0;
101         start_frame = 0;
102         end_frame = 0;
103         dataF = 0;
104         dataF2 = 0;
105         leftoverF = 0;
106         max_leftover_frames = 0;
107         leftover_frames = 0;
108         output_data = 0;
109         out_samples_max = 0;
110         data_width = 0;
111         do_freewheel = false;
112 }
113
114 void
115 AudioExportSpecification::clear ()
116 {
117         if (out) {
118                 sf_close (out);
119                 out = 0;
120         }
121
122         if (src_state) {
123                 src_delete (src_state);
124                 src_state = 0;
125         }
126
127         if (dither) {
128                 gdither_free (dither);
129                 dither = 0;
130         }
131
132         if (output_data) {
133                 free (output_data);
134                 output_data = 0;
135         }
136         if (dataF) {
137                 delete [] dataF;
138                 dataF = 0;
139         }
140         if (dataF2) {
141                 delete [] dataF2;
142                 dataF2 = 0;
143         }
144         if (leftoverF) {
145                 delete [] leftoverF;
146                 leftoverF = 0;
147         }
148
149         freewheel_connection.disconnect ();
150
151         init ();
152 }
153
154 int
155 AudioExportSpecification::prepare (nframes_t blocksize, nframes_t frate)
156 {
157         char errbuf[256];
158         GDitherSize dither_size;
159
160         frame_rate = frate;
161
162         if (channels == 0) {
163                 error << _("illegal frame range in export specification") << endmsg;
164                 return -1;
165         }
166
167         if (start_frame >= end_frame) {
168                 error << _("illegal frame range in export specification") << endmsg;
169                 return -1;
170         }
171
172         if ((data_width = sndfile_data_width(format)) == 0) {
173                 error << _("Bad data width size.  Report me!") << endmsg;
174                 return -1;
175         }
176
177         switch (data_width) {
178         case 8:
179                 dither_size = GDither8bit;
180                 break;
181
182         case 16:
183                 dither_size = GDither16bit;
184                 break;
185
186         case 24:
187                 dither_size = GDither32bit;
188                 break;
189
190         default:
191                 dither_size = GDitherFloat;
192                 break;
193         }
194
195         if (convert_spec_to_info (*this, sfinfo)) {
196                 return -1;
197         }
198
199         /* XXX make sure we have enough disk space for the output */
200         
201         if ((out = sf_open (path.c_str(), SFM_WRITE, &sfinfo)) == 0) {
202                 sf_error_str (0, errbuf, sizeof (errbuf) - 1);
203                 error << string_compose(_("Export: cannot open output file \"%1\" (%2)"), path, errbuf) << endmsg;
204                 return -1;
205         }
206
207         dataF = new float[blocksize * channels];
208
209         if (sample_rate != frame_rate) {
210                 int err;
211
212                 if ((src_state = src_new (src_quality, channels, &err)) == 0) {
213                         error << string_compose (_("cannot initialize sample rate conversion: %1"), src_strerror (err)) << endmsg;
214                         return -1;
215                 }
216                 
217                 src_data.src_ratio = sample_rate / (double) frame_rate;
218                 out_samples_max = (nframes_t) ceil (blocksize * src_data.src_ratio * channels);
219                 dataF2 = new float[out_samples_max];
220
221                 max_leftover_frames = 4 * blocksize;
222                 leftoverF = new float[max_leftover_frames * channels];
223                 leftover_frames = 0;
224
225         } else {
226                 out_samples_max = blocksize * channels;
227         }
228
229         dither = gdither_new (dither_type, channels, dither_size, data_width);
230
231         /* allocate buffers where dithering and output will occur */
232
233         switch (data_width) {
234         case 8:
235                 sample_bytes = 1;
236                 break;
237
238         case 16:
239                 sample_bytes = 2;
240                 break;
241
242         case 24:
243         case 32:
244                 sample_bytes = 4;
245                 break;
246
247         default:
248                 sample_bytes = 0; // float format
249                 break;
250         }
251
252         if (sample_bytes) {
253                 output_data = (void*) malloc (sample_bytes * out_samples_max);
254         }
255
256         return 0;
257 }
258
259 int
260 AudioExportSpecification::process (nframes_t nframes)
261 {
262         float* float_buffer = 0;
263         uint32_t chn;
264         uint32_t x;
265         uint32_t i;
266         sf_count_t written;
267         char errbuf[256];
268         nframes_t to_write = 0;
269         int cnt = 0;
270         
271         do {
272
273                 /* now do sample rate conversion */
274         
275                 if (sample_rate != frame_rate) {
276                 
277                         int err;
278                 
279                         src_data.output_frames = out_samples_max / channels;
280                         src_data.end_of_input = ((pos + nframes) >= end_frame);
281                         src_data.data_out = dataF2;
282
283                         if (leftover_frames > 0) {
284
285                                 /* input data will be in leftoverF rather than dataF */
286
287                                 src_data.data_in = leftoverF;
288
289                                 if (cnt == 0) {
290                                         
291                                         /* first time, append new data from dataF into the leftoverF buffer */
292
293                                         memcpy (leftoverF + (leftover_frames * channels), dataF, nframes * channels * sizeof(float));
294                                         src_data.input_frames = nframes + leftover_frames;
295                                 } else {
296                                         
297                                         /* otherwise, just use whatever is still left in leftoverF; the contents
298                                            were adjusted using memmove() right after the last SRC call (see
299                                            below)
300                                         */
301
302                                         src_data.input_frames = leftover_frames;
303                                 }
304                                         
305                         } else {
306
307                                 src_data.data_in = dataF;
308                                 src_data.input_frames = nframes;
309
310                         }
311
312                         ++cnt;
313
314                         if ((err = src_process (src_state, &src_data)) != 0) {
315                                 error << string_compose (_("an error occured during sample rate conversion: %1"),
316                                                   src_strerror (err))
317                                       << endmsg;
318                                 return -1;
319                         }
320                 
321                         to_write = src_data.output_frames_gen;
322                         leftover_frames = src_data.input_frames - src_data.input_frames_used;
323
324                         if (leftover_frames > 0) {
325                                 if (leftover_frames > max_leftover_frames) {
326                                         error << _("warning, leftover frames overflowed, glitches might occur in output") << endmsg;
327                                         leftover_frames = max_leftover_frames;
328                                 }
329                                 memmove (leftoverF, (char *) (src_data.data_in + (src_data.input_frames_used * channels)),
330                                          leftover_frames * channels * sizeof(float));
331                         }
332
333                         float_buffer = dataF2;
334                 
335                 } else {
336
337                         /* no SRC, keep it simple */
338                 
339                         to_write = nframes;
340                         leftover_frames = 0;
341                         float_buffer = dataF;
342                 }
343         
344                 if (output_data) {
345                         memset (output_data, 0, sample_bytes * to_write * channels);
346                 }
347         
348                 switch (data_width) {
349                 case 8:
350                 case 16:
351                 case 24:
352                         for (chn = 0; chn < channels; ++chn) { 
353                                 gdither_runf (dither, chn, to_write, float_buffer, output_data);
354                         }
355                         break;
356                 
357                 case 32:
358                         for (chn = 0; chn < channels; ++chn) {
359                         
360                                 int *ob = (int *) output_data;
361                                 const double int_max = (float) INT_MAX;
362                                 const double int_min = (float) INT_MIN;
363                         
364                                 for (x = 0; x < to_write; ++x) {
365                                         i = chn + (x * channels);
366                                 
367                                         if (float_buffer[i] > 1.0f) {
368                                                 ob[i] = INT_MAX;
369                                         } else if (float_buffer[i] < -1.0f) {
370                                                 ob[i] = INT_MIN;
371                                         } else {
372                                                 if (float_buffer[i] >= 0.0f) {
373                                                         ob[i] = lrintf (int_max * float_buffer[i]);
374                                                 } else {
375                                                         ob[i] = - lrintf (int_min * float_buffer[i]);
376                                                 }
377                                         }
378                                 }
379                         }
380                         break;
381                 
382                 default:
383                         for (x = 0; x < to_write * channels; ++x) {
384                                 if (float_buffer[x] > 1.0f) {
385                                         float_buffer[x] = 1.0f;
386                                 } else if (float_buffer[x] < -1.0f) {
387                                         float_buffer[x] = -1.0f;
388                                 } 
389                         }
390                         break;
391                 }
392         
393                 /* and export to disk */
394         
395                 switch (data_width) {
396                 case 8:
397                         /* XXXX no way to deliver 8 bit audio to libsndfile */
398                         written = to_write;
399                         break;
400                 
401                 case 16:
402                         written = sf_writef_short (out, (short*) output_data, to_write);
403                         break;
404                 
405                 case 24:
406                 case 32:
407                         written = sf_writef_int (out, (int*) output_data, to_write);
408                         break;
409                 
410                 default:
411                         written = sf_writef_float (out, float_buffer, to_write);
412                         break;
413                 }
414         
415                 if ((nframes_t) written != to_write) {
416                         sf_error_str (out, errbuf, sizeof (errbuf) - 1);
417                         error << string_compose(_("Export: could not write data to output file (%1)"), errbuf) << endmsg;
418                         return -1;
419                 }
420
421
422         } while (leftover_frames >= nframes);
423
424         return 0;
425 }
426
427 int
428 Session::start_audio_export (AudioExportSpecification& spec)
429 {
430         if (spec.prepare (current_block_size, frame_rate())) {
431                 return -1;
432         }
433
434         spec.pos = spec.start_frame;
435         spec.end_frame = spec.end_frame;
436         spec.total_frames = spec.end_frame - spec.start_frame;
437         spec.running = true; 
438         spec.do_freewheel = false; /* force a call to ::prepare_to_export() before proceeding to normal operation */
439
440         spec.freewheel_connection = _engine.Freewheel.connect (sigc::bind (mem_fun (*this, &Session::process_export), &spec));
441
442         return _engine.freewheel (true);
443 }
444
445 int
446 Session::stop_audio_export (AudioExportSpecification& spec)
447 {
448         /* don't stop freewheeling but do stop paying attention to it for now */
449
450         spec.freewheel_connection.disconnect ();
451         spec.clear (); /* resets running/stop etc */
452
453         return 0;
454 }
455
456 int 
457 Session::prepare_to_export (AudioExportSpecification& spec)
458 {
459         int ret = -1;
460
461         wait_till_butler_finished ();
462
463         /* take everyone out of awrite to avoid disasters */
464
465         {
466                 boost::shared_ptr<RouteList> r = routes.reader ();
467
468                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
469                         (*i)->protect_automation ();
470                 }
471         }
472
473         /* get everyone to the right position */
474
475         {
476                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
477
478                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
479                         if ((*i)-> seek (spec.start_frame, true)) {
480                                 error << string_compose (_("%1: cannot seek to %2 for export"),
481                                                   (*i)->name(), spec.start_frame)
482                                       << endmsg;
483                                 goto out;
484                         }
485                 }
486         }
487
488         /* make sure we are actually rolling */
489
490         if (get_record_enabled()) {
491                 disable_record (false);
492         }
493
494         _exporting = true;
495         
496         /* no slaving */
497
498         post_export_slave = Config->get_slave_source ();
499         post_export_position = _transport_frame;
500
501         Config->set_slave_source (None);
502
503         /* get transport ready */
504
505         set_transport_speed (1.0, false);
506         butler_transport_work ();
507         g_atomic_int_set (&butler_should_do_transport_work, 0);
508         post_transport ();
509
510         /* we are ready to go ... */
511
512         ret = 0;
513
514   out:
515         return ret;
516 }
517
518 int
519 Session::process_export (nframes_t nframes, AudioExportSpecification* spec)
520 {
521         uint32_t chn;
522         uint32_t x;
523         int ret = -1;
524         nframes_t this_nframes;
525
526         /* This is not required to be RT-safe because we are running while freewheeling */
527
528         if (spec->do_freewheel == false) {
529                 
530                 /* first time in export function: get set up */
531
532                 if (prepare_to_export (*spec)) {
533                         spec->running = false;
534                         spec->status = -1;
535                         return -1;
536                 }
537                 
538                 spec->do_freewheel = true;
539         }
540
541         if (!_exporting) {
542                 /* finished, but still freewheeling */
543                 process_without_events (nframes);
544                 return 0;
545         }
546                 
547         if (!spec->running || spec->stop || (this_nframes = min ((spec->end_frame - spec->pos), nframes)) == 0) {
548                 process_without_events (nframes);
549                 return stop_audio_export (*spec);
550         }
551
552         /* make sure we've caught up with disk i/o, since
553            we're running faster than realtime c/o JACK.
554         */
555
556         wait_till_butler_finished ();
557         
558         /* do the usual stuff */
559         
560         process_without_events (nframes);
561
562         /* and now export the results */
563
564         nframes = this_nframes;
565
566         memset (spec->dataF, 0, sizeof (spec->dataF[0]) * nframes * spec->channels);
567
568         /* foreach output channel ... */
569         
570         for (chn = 0; chn < spec->channels; ++chn) {
571                 
572                 AudioExportPortMap::iterator mi = spec->port_map.find (chn);
573                 
574                 if (mi == spec->port_map.end()) {
575                         /* no ports exported to this channel */
576                         continue;
577                 }
578                 
579                 vector<PortChannelPair>& mapped_ports ((*mi).second);
580                 
581                 for (vector<PortChannelPair>::iterator t = mapped_ports.begin(); t != mapped_ports.end(); ++t) {
582                         
583                         /* OK, this port's output is supposed to appear on this channel 
584                          */
585
586                         Port* port = (*t).first;
587                         Sample* port_buffer = port->get_buffer (nframes);
588
589                         /* now interleave the data from the channel into the float buffer */
590                                 
591                         for (x = 0; x < nframes; ++x) {
592                                 spec->dataF[chn+(x*spec->channels)] += (float) port_buffer[x];
593                         }
594                 }
595         }
596
597         if (spec->process (nframes)) {
598                 goto out;
599         }
600         
601         spec->pos += nframes;
602         spec->progress = 1.0 - (((float) spec->end_frame - spec->pos) / spec->total_frames);
603
604         /* and we're good to go */
605
606         ret = 0;
607
608   out: 
609         if (ret) {
610                 sf_close (spec->out);
611                 spec->out = 0;
612                 unlink (spec->path.c_str());
613                 spec->running = false;
614                 spec->status = ret;
615                 _exporting = false;
616         }
617
618         return ret;
619 }
620
621 void
622 Session::finalize_audio_export ()
623 {
624         _engine.freewheel (false);
625         _exporting = false;
626
627         /* can't use stop_transport() here because we need
628            an immediate halt and don't require all the declick
629            stuff that stop_transport() implements.
630         */
631
632         realtime_stop (true);
633         schedule_butler_transport_work ();
634
635         /* restart slaving */
636
637         if (post_export_slave != None) {
638                 Config->set_slave_source (post_export_slave);
639         } else {
640                 locate (post_export_position, false, false, false);
641         }
642 }