Pass a path argument to ImportableSource rather than SNDFILE handle so resource management is contained

git-svn-id: svn://localhost/ardour2/trunk@2667 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Tim Mayberry
2007-11-15 02:31:58 +00:00
parent 4076f7714a
commit 27b022bdeb
4 changed files with 61 additions and 39 deletions

View File

@@ -21,30 +21,39 @@
#define __ardour_importable_source_h__
#include <sndfile.h>
#include <pbd/failed_constructor.h>
#include <ardour/types.h>
namespace ARDOUR {
class ImportableSource {
public:
ImportableSource (SNDFILE* sf, SF_INFO* info) : in (sf), sf_info (info) {}
ImportableSource (const std::string& path)
: in (sf_open (path.c_str(), SFM_READ, &sf_info), sf_close)
{
if (!in) throw failed_constructor();
}
virtual ~ImportableSource() {}
virtual nframes_t read (Sample* buffer, nframes_t nframes) {
nframes_t per_channel = nframes / sf_info->channels;
per_channel = sf_readf_float (in, buffer, per_channel);
return per_channel * sf_info->channels;
nframes_t per_channel = nframes / sf_info.channels;
per_channel = sf_readf_float (in.get(), buffer, per_channel);
return per_channel * sf_info.channels;
}
virtual float ratio() const { return 1.0f; }
uint channels() const { return sf_info->channels; }
uint channels() const { return sf_info.channels; }
nframes_t length() const { return sf_info->frames; }
nframes_t length() const { return sf_info.frames; }
nframes_t samplerate() const { return sf_info.samplerate; }
protected:
SNDFILE* in;
SF_INFO* sf_info;
SF_INFO sf_info;
boost::shared_ptr<SNDFILE> in;
};
}

View File

@@ -30,7 +30,9 @@ namespace ARDOUR {
class ResampledImportableSource : public ImportableSource
{
public:
ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate, SrcQuality);
ResampledImportableSource (const std::string& path,
nframes_t rate, SrcQuality);
~ResampledImportableSource ();
nframes_t read (Sample* buffer, nframes_t nframes);

View File

@@ -53,6 +53,21 @@
using namespace ARDOUR;
using namespace PBD;
std::auto_ptr<ImportableSource>
open_importable_source (const string& path, nframes_t samplerate,
ARDOUR::SrcQuality quality)
{
std::auto_ptr<ImportableSource> source(new ImportableSource(path));
if (source->samplerate() == samplerate) {
return source;
}
return std::auto_ptr<ImportableSource>(
new ResampledImportableSource(path, samplerate, quality)
);
}
std::string
get_non_existent_filename (const std::string& basename, uint channel, uint channels)
{
@@ -144,7 +159,6 @@ write_audio_data_to_new_files (ImportableSource* source, Session::import_status&
int
Session::import_audiofile (import_status& status)
{
SF_INFO info;
string basepath;
int ret = -1;
vector<string> new_paths;
@@ -155,26 +169,22 @@ Session::import_audiofile (import_status& status)
for (vector<Glib::ustring>::iterator p = status.paths.begin(); p != status.paths.end(); ++p, ++cnt) {
boost::shared_ptr<SNDFILE> in (sf_open (p->c_str(), SFM_READ, &info), sf_close);
std::auto_ptr<ImportableSource> source;
if (!in) {
error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
status.done = 1;
status.cancel = 1;
return -1;
try
{
source = open_importable_source (*p, frame_rate(), status.quality);
}
std::auto_ptr<ImportableSource> importable;
if ((nframes_t) info.samplerate != frame_rate()) {
importable.reset(new ResampledImportableSource (in.get(), &info, frame_rate(), status.quality));
} else {
importable.reset(new ImportableSource (in.get(), &info));
catch (const failed_constructor& err)
{
error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
status.done = status.cancel = true;
return -1;
}
vector<boost::shared_ptr<AudioFileSource> > newfiles;
for (int n = 0; n < info.channels; ++n) {
for (uint n = 0; n < source->channels(); ++n) {
newfiles.push_back (boost::shared_ptr<AudioFileSource>());
}
@@ -182,9 +192,9 @@ Session::import_audiofile (import_status& status)
basepath = PBD::basename_nosuffix ((*p));
for (int n = 0; n < info.channels; ++n) {
for (uint n = 0; n < source->channels(); ++n) {
std::string filename = get_non_existent_filename (basepath, n, info.channels);
std::string filename = get_non_existent_filename (basepath, n, source->channels());
sys::path filepath = sdir.sound_path() / filename;
@@ -201,10 +211,10 @@ Session::import_audiofile (import_status& status)
newfiles[n]->prepare_for_peakfile_writes ();
}
if ((nframes_t) info.samplerate != frame_rate()) {
if ((nframes_t) source->samplerate() != frame_rate()) {
status.doing_what = string_compose (_("converting %1\n(resample from %2KHz to %3KHz)\n(%4 of %5)"),
basepath,
info.samplerate/1000.0f,
source->samplerate()/1000.0f,
frame_rate()/1000.0f,
cnt, status.paths.size());
@@ -215,13 +225,13 @@ Session::import_audiofile (import_status& status)
}
write_audio_data_to_new_files (importable.get(), status, newfiles);
write_audio_data_to_new_files (source.get(), status, newfiles);
if (status.cancel) {
goto out;
}
for (int n = 0; n < info.channels; ++n) {
for (uint n = 0; n < source->channels(); ++n) {
status.sources.push_back (newfiles[n]);
}

View File

@@ -28,12 +28,13 @@ using namespace PBD;
const uint32_t ResampledImportableSource::blocksize = 4096U;
ResampledImportableSource::ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate, SrcQuality srcq)
: ImportableSource (sf, info)
ResampledImportableSource::ResampledImportableSource (const std::string& path,
nframes_t rate, SrcQuality srcq)
: ImportableSource (path)
{
int err;
sf_seek (in, 0, SEEK_SET) ;
sf_seek (in.get(), 0, SEEK_SET) ;
/* Initialize the sample rate converter. */
@@ -57,7 +58,7 @@ ResampledImportableSource::ResampledImportableSource (SNDFILE* sf, SF_INFO* info
break;
}
if ((src_state = src_new (src_type, sf_info->channels, &err)) == 0) {
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 ();
}
@@ -69,7 +70,7 @@ ResampledImportableSource::ResampledImportableSource (SNDFILE* sf, SF_INFO* info
src_data.input_frames = 0 ;
src_data.data_in = input ;
src_data.src_ratio = ((float) rate) / sf_info->samplerate ;
src_data.src_ratio = ((float) rate) / sf_info.samplerate ;
input = new float[blocksize];
}
@@ -97,14 +98,14 @@ ResampledImportableSource::read (Sample* output, nframes_t nframes)
src_data.end_of_input = SF_TRUE ;
}
src_data.input_frames /= sf_info->channels;
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 / sf_info.channels ;
} else {
src_data.output_frames = src_data.input_frames;
}
@@ -120,9 +121,9 @@ ResampledImportableSource::read (Sample* output, nframes_t nframes)
return 0;
}
src_data.data_in += src_data.input_frames_used * sf_info->channels ;
src_data.data_in += src_data.input_frames_used * sf_info.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 * sf_info.channels;
}