'libs/ardour' - Platform specific changes and includes
[ardour.git] / libs / ardour / resampled_source.cc
index b5d23fb4a22a55d48678474621d9198bc06f319b..0a8131910827fefd5817ae76ece8619d572cdead 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2007 Paul Davis 
+    Copyright (C) 2007 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 */
 
-#include <pbd/error.h>
-#include <ardour/resampled_source.h>
-#include <pbd/failed_constructor.h>
+#include "pbd/error.h"
+#include "ardour/resampled_source.h"
+#include "pbd/failed_constructor.h"
 
 #include "i18n.h"
 
 using namespace ARDOUR;
 using namespace PBD;
 
-const uint32_t ResampledImportableSource::blocksize = 4096U;
+#ifdef PLATFORM_WINDOWS
+const uint32_t ResampledImportableSource::blocksize = 524288U;
+#else
+const uint32_t ResampledImportableSource::blocksize = 16384U;
+#endif
 
-ResampledImportableSource::ResampledImportableSource (const std::string& path,
-               nframes_t rate, SrcQuality srcq)
-       : ImportableSource (path) 
+ResampledImportableSource::ResampledImportableSource (boost::shared_ptr<ImportableSource> src, framecnt_t rate, SrcQuality srcq)
+       : source (src)
+       , src_state (0)
 {
-       int err;
-       
-       sf_seek (in.get(), 0, SEEK_SET) ;
-       
-       /* Initialize the sample rate converter. */
-       
-       int src_type = SRC_LINEAR;
+       _src_type = SRC_SINC_BEST_QUALITY;
 
        switch (srcq) {
        case SrcBest:
-               src_type = SRC_SINC_BEST_QUALITY;
+               _src_type = SRC_SINC_BEST_QUALITY;
                break;
        case SrcGood:
-               src_type = SRC_SINC_MEDIUM_QUALITY;
+               _src_type = SRC_SINC_MEDIUM_QUALITY;
                break;
        case SrcQuick:
-               src_type = SRC_SINC_FASTEST;
+               _src_type = SRC_SINC_FASTEST;
                break;
        case SrcFast:
-               src_type = SRC_ZERO_ORDER_HOLD;
+               _src_type = SRC_ZERO_ORDER_HOLD;
                break;
        case SrcFastest:
-               src_type = SRC_LINEAR;
+               _src_type = SRC_LINEAR;
                break;
        }
-       
-       if ((src_state = src_new (src_type, sf_info.channels, &err)) == 0) {    
-               error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
-               throw failed_constructor ();
-       }
-       
-       src_data.end_of_input = 0 ; /* Set this later. */
-       
-       /* Start with zero to force load in while loop. */
-       
-       src_data.input_frames = 0 ;
-       src_data.data_in = input ;
-       
-       src_data.src_ratio = ((float) rate) / sf_info.samplerate ;
-       
+
        input = new float[blocksize];
+
+       seek (0);
+
+       src_data.src_ratio = ((float) rate) / source->samplerate();
 }
 
 ResampledImportableSource::~ResampledImportableSource ()
@@ -81,49 +69,77 @@ ResampledImportableSource::~ResampledImportableSource ()
        delete [] input;
 }
 
-nframes_t 
-ResampledImportableSource::read (Sample* output, nframes_t nframes)
+framecnt_t
+ResampledImportableSource::read (Sample* output, framecnt_t nframes)
 {
        int err;
 
        /* If the input buffer is empty, refill it. */
-       
-       if (src_data.input_frames == 0) {       
 
-               src_data.input_frames = ImportableSource::read (input, blocksize);
+       if (src_data.input_frames == 0) {
+
+               src_data.input_frames = source->read (input, blocksize);
 
                /* The last read will not be a full buffer, so set end_of_input. */
 
-               if ((nframes_t) src_data.input_frames < blocksize) {
-                       src_data.end_of_input = SF_TRUE ;
-               }               
+               if ((framecnt_t) src_data.input_frames < blocksize) {
+                       src_data.end_of_input = true;
+               }
+
+               src_data.input_frames /= source->channels();
+               src_data.data_in = input;
+       }
 
-               src_data.input_frames /= sf_info.channels;
-               src_data.data_in = input ;
-       } 
-       
        src_data.data_out = output;
 
        if (!src_data.end_of_input) {
-               src_data.output_frames = nframes / sf_info.channels ;
+               src_data.output_frames = nframes / source->channels();
        } else {
-               src_data.output_frames = src_data.input_frames;
+               src_data.output_frames = std::min ((framecnt_t) src_data.input_frames, nframes / source->channels());
        }
 
        if ((err = src_process (src_state, &src_data))) {
                error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
                return 0 ;
-       } 
-       
+       }
+
        /* Terminate if at end */
-       
+
        if (src_data.end_of_input && src_data.output_frames_gen == 0) {
                return 0;
        }
-       
-       src_data.data_in += src_data.input_frames_used * sf_info.channels ;
+
+       src_data.data_in += src_data.input_frames_used * source->channels();
        src_data.input_frames -= src_data.input_frames_used ;
 
-       return src_data.output_frames_gen * sf_info.channels;
+       return src_data.output_frames_gen * source->channels();
 }
 
+void
+ResampledImportableSource::seek (framepos_t pos)
+{
+       source->seek (pos);
+
+       /* and reset things so that we start from scratch with the conversion */
+
+       if (src_state) {
+               src_delete (src_state);
+       }
+
+       int err;
+
+       if ((src_state = src_new (_src_type, source->channels(), &err)) == 0) {
+               error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
+               throw failed_constructor ();
+       }
+
+       src_data.input_frames = 0;
+       src_data.data_in = input;
+       src_data.end_of_input = 0;
+}
+
+framepos_t
+ResampledImportableSource::natural_position () const
+{
+        return source->natural_position() * ratio ();
+}