Back-port tim mayberry's fixes for import; fix JACK slaving to never pay attention...
[ardour.git] / libs / ardour / resampled_source.cc
1 /*
2     Copyright (C) 2007 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 #include <pbd/error.h>
21 #include <ardour/resampled_source.h>
22 #include <pbd/failed_constructor.h>
23
24 #include "i18n.h"
25
26 using namespace ARDOUR;
27 using namespace PBD;
28
29 const uint32_t ResampledImportableSource::blocksize = 4096U;
30
31 ResampledImportableSource::ResampledImportableSource (const std::string& path,
32                 nframes_t rate, SrcQuality srcq)
33         : ImportableSource (path) 
34 {
35         int err;
36         
37         sf_seek (in.get(), 0, SEEK_SET) ;
38         
39         /* Initialize the sample rate converter. */
40         
41         int src_type;
42
43         switch (srcq) {
44         case SrcBest:
45                 src_type = SRC_SINC_BEST_QUALITY;
46                 break;
47         case SrcGood:
48                 src_type = SRC_SINC_MEDIUM_QUALITY;
49                 break;
50         case SrcQuick:
51                 src_type = SRC_SINC_FASTEST;
52                 break;
53         case SrcFast:
54                 src_type = SRC_ZERO_ORDER_HOLD;
55                 break;
56         case SrcFastest:
57                 src_type = SRC_LINEAR;
58                 break;
59         }
60         
61         if ((src_state = src_new (src_type, sf_info.channels, &err)) == 0) {    
62                 error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
63                 throw failed_constructor ();
64         }
65         
66         src_data.end_of_input = 0 ; /* Set this later. */
67         
68         /* Start with zero to force load in while loop. */
69         
70         src_data.input_frames = 0 ;
71         src_data.data_in = input ;
72         
73         src_data.src_ratio = ((float) rate) / sf_info.samplerate ;
74         
75         input = new float[blocksize];
76 }
77
78 ResampledImportableSource::~ResampledImportableSource ()
79 {
80         src_state = src_delete (src_state) ;
81         delete [] input;
82 }
83
84 nframes_t 
85 ResampledImportableSource::read (Sample* output, nframes_t nframes)
86 {
87         int err;
88
89         /* If the input buffer is empty, refill it. */
90         
91         if (src_data.input_frames == 0) {       
92
93                 src_data.input_frames = ImportableSource::read (input, blocksize);
94
95                 /* The last read will not be a full buffer, so set end_of_input. */
96
97                 if ((nframes_t) src_data.input_frames < blocksize) {
98                         src_data.end_of_input = SF_TRUE ;
99                 }               
100
101                 src_data.input_frames /= sf_info.channels;
102                 src_data.data_in = input ;
103         } 
104         
105         src_data.data_out = output;
106
107         if (!src_data.end_of_input) {
108                 src_data.output_frames = nframes / sf_info.channels ;
109         } else {
110                 src_data.output_frames = src_data.input_frames;
111         }
112
113         if ((err = src_process (src_state, &src_data))) {
114                 error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
115                 return 0 ;
116         } 
117         
118         /* Terminate if at end */
119         
120         if (src_data.end_of_input && src_data.output_frames_gen == 0) {
121                 return 0;
122         }
123         
124         src_data.data_in += src_data.input_frames_used * sf_info.channels ;
125         src_data.input_frames -= src_data.input_frames_used ;
126
127         return src_data.output_frames_gen * sf_info.channels;
128 }
129