mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-20 13:46:30 +01:00
fix up BWF creation; make CoreAudioSource work; add CAImportable; refactor SourceFactory to try sndfile first, CoreAudio second
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3126 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
a969d63986
commit
3188ad3ab0
17 changed files with 390 additions and 183 deletions
|
|
@ -1075,7 +1075,10 @@ class Editor : public PublicEditor
|
|||
SoundFileOmega* sfbrowser;
|
||||
|
||||
void bring_in_external_audio (Editing::ImportMode mode, nframes64_t& pos);
|
||||
|
||||
void _do_import (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&);
|
||||
void do_import (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&);
|
||||
bool idle_do_import (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&);
|
||||
|
||||
void _do_embed (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&);
|
||||
void do_embed (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&);
|
||||
|
|
|
|||
|
|
@ -280,8 +280,25 @@ Editor::get_nth_selected_audio_track (int nth) const
|
|||
return atv->audio_track();
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::idle_do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mode, SrcQuality quality, nframes64_t& pos)
|
||||
{
|
||||
_do_import (paths, chns, mode, quality, pos);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mode, SrcQuality quality, nframes64_t& pos)
|
||||
{
|
||||
#ifdef GTKOSX
|
||||
Glib::signal_idle().connect (bind (mem_fun (*this, &Editor::idle_do_import), paths, chns, mode, quality, pos));
|
||||
#else
|
||||
_do_import (paths, chns, mode, quality, pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::_do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mode, SrcQuality quality, nframes64_t& pos)
|
||||
{
|
||||
boost::shared_ptr<AudioTrack> track;
|
||||
vector<ustring> to_import;
|
||||
|
|
@ -653,6 +670,9 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
|
|||
boost::shared_ptr<Source> s;
|
||||
|
||||
if ((s = session->source_by_path_and_channel (path, n)) == 0) {
|
||||
|
||||
cerr << "add embed/import source with defer_peaks = true\n";
|
||||
|
||||
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable
|
||||
(*session, path, n,
|
||||
(mode == ImportAsTapeTrack ?
|
||||
|
|
|
|||
|
|
@ -498,7 +498,11 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
|
|||
|
||||
frame = 0;
|
||||
|
||||
if (Profile->get_sae() || Config->get_only_copy_imported_files()) {
|
||||
do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, SrcBest, frame);
|
||||
} else {
|
||||
do_embed (paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
|
||||
}
|
||||
|
||||
} else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
|
||||
|
||||
|
|
@ -507,9 +511,14 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
|
|||
if (tv->get_diskstream()) {
|
||||
/* select the track, then embed */
|
||||
selection->set (tv);
|
||||
|
||||
if (Profile->get_sae() || Config->get_only_copy_imported_files()) {
|
||||
do_import (paths, Editing::ImportDistinctFiles, Editing::ImportToTrack, SrcBest, frame);
|
||||
} else {
|
||||
do_embed (paths, Editing::ImportDistinctFiles, ImportToTrack, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
context->drag_finish (true, false, time);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ osc_files = [ 'osc.cc' ]
|
|||
vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
|
||||
lv2_files = [ 'lv2_plugin.cc' ]
|
||||
audiounit_files = [ 'audio_unit.cc' ]
|
||||
coreaudio_files = [ 'coreaudiosource.cc' ]
|
||||
coreaudio_files = [ 'coreaudiosource.cc', 'caimportable.cc' ]
|
||||
extra_sources = [ ]
|
||||
timefx_sources = [ ]
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ class AudioFileSource : public AudioSource {
|
|||
bool removable() const;
|
||||
bool writable() const { return _flags & Writable; }
|
||||
|
||||
static Sample* get_interleave_buffer (nframes_t size);
|
||||
|
||||
private:
|
||||
Glib::ustring old_peak_path (Glib::ustring audio_path);
|
||||
Glib::ustring broken_peak_path (Glib::ustring audio_path);
|
||||
|
|
|
|||
48
libs/ardour/ardour/caimportable.h
Normal file
48
libs/ardour/ardour/caimportable.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ardour_ca_importable_source_h__
|
||||
#define __ardour_ca_importable_source_h__
|
||||
|
||||
#include <pbd/failed_constructor.h>
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/importable_source.h>
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class CAImportableSource : public ImportableSource {
|
||||
public:
|
||||
CAImportableSource (const std::string& path);
|
||||
virtual ~CAImportableSource();
|
||||
|
||||
nframes_t read (Sample* buffer, nframes_t nframes);
|
||||
uint32_t channels() const;
|
||||
nframes_t length() const;
|
||||
nframes_t samplerate() const;
|
||||
void seek (nframes_t pos);
|
||||
|
||||
protected:
|
||||
mutable CAAudioFile af;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* __ardour_ca_importable_source_h__ */
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
#define __coreaudio_source_h__
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
|
||||
#include <ardour/audiofilesource.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
|
@ -48,11 +47,8 @@ class CoreAudioSource : public AudioFileSource {
|
|||
mutable CAAudioFile af;
|
||||
uint16_t n_channels;
|
||||
|
||||
mutable float *tmpbuf;
|
||||
mutable nframes_t tmpbufsize;
|
||||
mutable Glib::Mutex _tmpbuf_lock;
|
||||
|
||||
void init ();
|
||||
int safe_read (Sample*, nframes_t start, nframes_t cnt, AudioBufferList&) const;
|
||||
};
|
||||
|
||||
}; /* namespace ARDOUR */
|
||||
|
|
|
|||
|
|
@ -102,8 +102,6 @@ class SndFileSource : public AudioFileSource {
|
|||
void handle_header_position_change ();
|
||||
|
||||
static int64_t get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists);
|
||||
|
||||
static Sample* get_interleave_buffer (nframes_t size);
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include <glibmm/miscutils.h>
|
||||
#include <glibmm/fileutils.h>
|
||||
#include <glibmm/thread.h>
|
||||
|
||||
#include <ardour/audiofilesource.h>
|
||||
#include <ardour/sndfile_helpers.h>
|
||||
|
|
@ -69,6 +70,21 @@ uint64_t AudioFileSource::header_position_offset = 0;
|
|||
/* XXX maybe this too */
|
||||
char AudioFileSource::bwf_serial_number[13] = "000000000000";
|
||||
|
||||
struct SizedSampleBuffer {
|
||||
nframes_t size;
|
||||
Sample* buf;
|
||||
|
||||
SizedSampleBuffer (nframes_t sz) : size (sz) {
|
||||
buf = new Sample[size];
|
||||
}
|
||||
|
||||
~SizedSampleBuffer() {
|
||||
delete [] buf;
|
||||
}
|
||||
};
|
||||
|
||||
Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
_channel (0)
|
||||
|
|
@ -716,3 +732,22 @@ AudioFileSource::mark_immutable ()
|
|||
_flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sample*
|
||||
AudioFileSource::get_interleave_buffer (nframes_t size)
|
||||
{
|
||||
SizedSampleBuffer* ssb;
|
||||
|
||||
if ((ssb = thread_interleave_buffer.get()) == 0) {
|
||||
ssb = new SizedSampleBuffer (size);
|
||||
thread_interleave_buffer.set (ssb);
|
||||
}
|
||||
|
||||
if (ssb->size < size) {
|
||||
ssb = new SizedSampleBuffer (size);
|
||||
thread_interleave_buffer.set (ssb);
|
||||
}
|
||||
|
||||
return ssb->buf;
|
||||
}
|
||||
|
|
|
|||
118
libs/ardour/caimportable.cc
Normal file
118
libs/ardour/caimportable.cc
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include <ardour/caimportable.h>
|
||||
#include <sndfile.h>
|
||||
#include <pbd/error.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
using namespace PBD;
|
||||
|
||||
CAImportableSource::CAImportableSource (const string& path)
|
||||
{
|
||||
try {
|
||||
af.Open (path.c_str());
|
||||
|
||||
CAStreamBasicDescription file_format (af.GetFileDataFormat());
|
||||
CAStreamBasicDescription client_format (file_format);
|
||||
|
||||
/* set canonial form (PCM, native float packed, 32 bit, with the correct number of channels
|
||||
and interleaved (since we plan to deinterleave ourselves)
|
||||
*/
|
||||
|
||||
client_format.SetCanonical(client_format.NumberChannels(), true);
|
||||
af.SetClientFormat (client_format);
|
||||
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose ("CAImportable: %1", cax.mOperation) << endmsg;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CAImportableSource::~CAImportableSource ()
|
||||
{
|
||||
}
|
||||
|
||||
nframes_t
|
||||
CAImportableSource::read (Sample* buffer, nframes_t nframes)
|
||||
{
|
||||
nframes_t nread = 0;
|
||||
AudioBufferList abl;
|
||||
nframes_t per_channel;
|
||||
bool at_end = false;
|
||||
|
||||
abl.mNumberBuffers = 1;
|
||||
abl.mBuffers[0].mNumberChannels = channels();
|
||||
|
||||
per_channel = nframes / abl.mBuffers[0].mNumberChannels;
|
||||
|
||||
while (nread < per_channel) {
|
||||
|
||||
UInt32 new_cnt = per_channel - nread;
|
||||
|
||||
abl.mBuffers[0].mDataByteSize = new_cnt * abl.mBuffers[0].mNumberChannels * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = buffer + nread;
|
||||
|
||||
try {
|
||||
af.Read (new_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CAImportable: %1", cax.mOperation);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_cnt == 0) {
|
||||
/* EOF */
|
||||
at_end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
nread += new_cnt;
|
||||
}
|
||||
|
||||
if (!at_end && nread < per_channel) {
|
||||
return 0;
|
||||
} else {
|
||||
return nread * abl.mBuffers[0].mNumberChannels;
|
||||
}
|
||||
}
|
||||
|
||||
uint
|
||||
CAImportableSource::channels () const
|
||||
{
|
||||
return af.GetFileDataFormat().NumberChannels();
|
||||
}
|
||||
|
||||
nframes_t
|
||||
CAImportableSource::length () const
|
||||
{
|
||||
return af.GetNumberFrames();
|
||||
}
|
||||
|
||||
nframes_t
|
||||
CAImportableSource::samplerate() const
|
||||
{
|
||||
CAStreamBasicDescription client_asbd;
|
||||
|
||||
try {
|
||||
client_asbd = af.GetClientDataFormat ();
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose ("CAImportable: %1", cax.mOperation) << endmsg;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return client_asbd.mSampleRate;
|
||||
}
|
||||
|
||||
void
|
||||
CAImportableSource::seek (nframes_t pos)
|
||||
{
|
||||
try {
|
||||
af.Seek (pos);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose ("CAImportable: %1 to %2", cax.mOperation, pos) << endmsg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2006 Paul Davis
|
||||
Written by Taybin Rutkin
|
||||
|
||||
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
|
||||
|
|
@ -17,6 +18,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <pbd/error.h>
|
||||
#include <ardour/coreaudiosource.h>
|
||||
#include <ardour/utils.h>
|
||||
|
|
@ -28,6 +31,7 @@
|
|||
|
||||
#include <AudioToolbox/AudioFormat.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
|
|
@ -48,18 +52,12 @@ CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag
|
|||
void
|
||||
CoreAudioSource::init ()
|
||||
{
|
||||
tmpbuf = 0;
|
||||
tmpbufsize = 0;
|
||||
|
||||
cerr << "CoreAudioSource::init() " << name() << endl;
|
||||
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
try {
|
||||
af.Open(_path.c_str());
|
||||
|
||||
CAStreamBasicDescription file_asbd (af.GetFileDataFormat());
|
||||
n_channels = file_asbd.NumberChannels();
|
||||
cerr << "number of channels: " << n_channels << endl;
|
||||
CAStreamBasicDescription file_format (af.GetFileDataFormat());
|
||||
n_channels = file_format.NumberChannels();
|
||||
|
||||
if (_channel >= n_channels) {
|
||||
error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, _channel, name()) << endmsg;
|
||||
|
|
@ -68,9 +66,15 @@ CoreAudioSource::init ()
|
|||
|
||||
_length = af.GetNumberFrames();
|
||||
|
||||
CAStreamBasicDescription client_asbd(file_asbd);
|
||||
client_asbd.SetCanonical(client_asbd.NumberChannels(), false);
|
||||
af.SetClientFormat (client_asbd);
|
||||
CAStreamBasicDescription client_format (file_format);
|
||||
|
||||
/* set canonial form (PCM, native float packed, 32 bit, with the correct number of channels
|
||||
and interleaved (since we plan to deinterleave ourselves)
|
||||
*/
|
||||
|
||||
client_format.SetCanonical(client_format.NumberChannels(), true);
|
||||
af.SetClientFormat (client_format);
|
||||
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose ("CoreAudioSource: %1 (%2)", cax.mOperation, name()) << endmsg;
|
||||
throw failed_constructor ();
|
||||
|
|
@ -79,81 +83,117 @@ CoreAudioSource::init ()
|
|||
|
||||
CoreAudioSource::~CoreAudioSource ()
|
||||
{
|
||||
cerr << "CoreAudioSource::~CoreAudioSource() " << name() << endl;
|
||||
GoingAway (); /* EMIT SIGNAL */
|
||||
|
||||
if (tmpbuf) {
|
||||
delete [] tmpbuf;
|
||||
}
|
||||
|
||||
cerr << "deletion done" << endl;
|
||||
}
|
||||
|
||||
nframes_t
|
||||
CoreAudioSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
|
||||
int
|
||||
CoreAudioSource::safe_read (Sample* dst, nframes_t start, nframes_t cnt, AudioBufferList& abl) const
|
||||
{
|
||||
nframes_t nread = 0;
|
||||
|
||||
while (nread < cnt) {
|
||||
|
||||
try {
|
||||
af.Seek (start);
|
||||
af.Seek (start+nread);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start, _name.substr (1)) << endmsg;
|
||||
return 0;
|
||||
error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start+nread, _name.substr (1)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
AudioBufferList abl;
|
||||
abl.mNumberBuffers = 1;
|
||||
abl.mBuffers[0].mNumberChannels = n_channels;
|
||||
UInt32 new_cnt = cnt - nread;
|
||||
|
||||
abl.mBuffers[0].mDataByteSize = new_cnt * n_channels * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = dst + nread;
|
||||
|
||||
UInt32 new_cnt = cnt;
|
||||
if (n_channels == 1) {
|
||||
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = dst;
|
||||
try {
|
||||
af.Read (new_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
}
|
||||
_read_data_count = new_cnt * sizeof(float);
|
||||
return new_cnt;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt32 real_cnt = cnt * n_channels;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (_tmpbuf_lock);
|
||||
|
||||
if (tmpbufsize < real_cnt) {
|
||||
|
||||
if (tmpbuf) {
|
||||
delete [] tmpbuf;
|
||||
if (new_cnt == 0) {
|
||||
/* EOF */
|
||||
if (start+cnt == _length) {
|
||||
/* we really did hit the end */
|
||||
nread = cnt;
|
||||
}
|
||||
tmpbufsize = real_cnt;
|
||||
tmpbuf = new float[tmpbufsize];
|
||||
break;
|
||||
}
|
||||
|
||||
abl.mBuffers[0].mDataByteSize = tmpbufsize * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = tmpbuf;
|
||||
|
||||
cerr << "channel: " << _channel << endl;
|
||||
|
||||
try {
|
||||
af.Read (real_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
nread += new_cnt;
|
||||
}
|
||||
float *ptr = tmpbuf + _channel;
|
||||
real_cnt /= n_channels;
|
||||
|
||||
/* stride through the interleaved data */
|
||||
|
||||
for (uint32_t n = 0; n < real_cnt; ++n) {
|
||||
dst[n] = *ptr;
|
||||
ptr += n_channels;
|
||||
if (nread < cnt) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nframes_t
|
||||
CoreAudioSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
|
||||
{
|
||||
nframes_t file_cnt;
|
||||
AudioBufferList abl;
|
||||
|
||||
abl.mNumberBuffers = 1;
|
||||
abl.mBuffers[0].mNumberChannels = n_channels;
|
||||
|
||||
if (start > _length) {
|
||||
|
||||
/* read starts beyond end of data, just memset to zero */
|
||||
|
||||
file_cnt = 0;
|
||||
|
||||
} else if (start + cnt > _length) {
|
||||
|
||||
/* read ends beyond end of data, read some, memset the rest */
|
||||
|
||||
file_cnt = _length - start;
|
||||
|
||||
} else {
|
||||
|
||||
/* read is entirely within data */
|
||||
|
||||
file_cnt = cnt;
|
||||
}
|
||||
|
||||
if (file_cnt != cnt) {
|
||||
nframes_t delta = cnt - file_cnt;
|
||||
memset (dst+file_cnt, 0, sizeof (Sample) * delta);
|
||||
}
|
||||
|
||||
if (file_cnt) {
|
||||
|
||||
if (n_channels == 1) {
|
||||
if (safe_read (dst, start, file_cnt, abl) == 0) {
|
||||
_read_data_count = cnt * sizeof (Sample);
|
||||
return cnt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Sample* interleave_buf = get_interleave_buffer (file_cnt * n_channels);
|
||||
|
||||
if (safe_read (interleave_buf, start, file_cnt, abl) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_read_data_count = cnt * sizeof(float);
|
||||
|
||||
return real_cnt;
|
||||
Sample *ptr = interleave_buf + _channel;
|
||||
|
||||
/* stride through the interleaved data */
|
||||
|
||||
for (uint32_t n = 0; n < file_cnt; ++n) {
|
||||
dst[n] = *ptr;
|
||||
ptr += n_channels;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
float
|
||||
|
|
|
|||
|
|
@ -334,7 +334,6 @@ Playlist::release_notifications ()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Playlist::notify_modified ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
const uint32_t ResampledImportableSource::blocksize = 4096U;
|
||||
const uint32_t ResampledImportableSource::blocksize = 16384U;
|
||||
|
||||
ResampledImportableSource::ResampledImportableSource (boost::shared_ptr<ImportableSource> src, nframes_t rate, SrcQuality srcq)
|
||||
: source (src)
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ Session::destroy ()
|
|||
|
||||
// auditioner.reset ();
|
||||
|
||||
#undef TRACK_DESTRUCTION
|
||||
#define TRACK_DESTRUCTION
|
||||
#ifdef TRACK_DESTRUCTION
|
||||
cerr << "delete named selections\n";
|
||||
#endif /* TRACK_DESTRUCTION */
|
||||
|
|
@ -578,11 +578,16 @@ Session::destroy ()
|
|||
tmp = i;
|
||||
++tmp;
|
||||
|
||||
cerr << "Drop refs to " << i->second->name() << endl;
|
||||
|
||||
i->second->drop_references ();
|
||||
|
||||
cerr << "move on\n";
|
||||
|
||||
i = tmp;
|
||||
}
|
||||
|
||||
cerr << "clear audio sources\n";
|
||||
audio_sources.clear ();
|
||||
|
||||
#ifdef TRACK_DESTRUCTION
|
||||
|
|
@ -2892,6 +2897,8 @@ Session::remove_source (boost::weak_ptr<Source> src)
|
|||
return;
|
||||
}
|
||||
|
||||
cerr << "remove source for " << source->name() << endl;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (audio_source_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include <glibmm/miscutils.h>
|
||||
#include <glibmm/thread.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
|
||||
#include <ardour/sndfilesource.h>
|
||||
|
|
@ -46,21 +45,6 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou
|
|||
AudioFileSource::Removable|
|
||||
AudioFileSource::RemovableIfEmpty|
|
||||
AudioFileSource::CanRename);
|
||||
struct SizedSampleBuffer {
|
||||
nframes_t size;
|
||||
Sample* buf;
|
||||
|
||||
SizedSampleBuffer (nframes_t sz) : size (sz) {
|
||||
buf = new Sample[size];
|
||||
}
|
||||
|
||||
~SizedSampleBuffer() {
|
||||
delete [] buf;
|
||||
}
|
||||
};
|
||||
|
||||
Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
|
|
@ -191,7 +175,6 @@ SndFileSource::SndFileSource (Session& s, ustring path, SampleFormat sfmt, Heade
|
|||
delete _broadcast_info;
|
||||
_broadcast_info = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +239,7 @@ SndFileSource::open ()
|
|||
|
||||
set_timeline_position (get_timecode_info (sf, _broadcast_info, timecode_info_exists));
|
||||
|
||||
if (!timecode_info_exists) {
|
||||
if (_length != 0 && !timecode_info_exists) {
|
||||
delete _broadcast_info;
|
||||
_broadcast_info = 0;
|
||||
_flags = Flag (_flags & ~Broadcast);
|
||||
|
|
@ -328,6 +311,11 @@ SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
|
|||
file_cnt = cnt;
|
||||
}
|
||||
|
||||
if (file_cnt != cnt) {
|
||||
nframes_t delta = cnt - file_cnt;
|
||||
memset (dst+file_cnt, 0, sizeof (Sample) * delta);
|
||||
}
|
||||
|
||||
if (file_cnt) {
|
||||
|
||||
if (sf_seek (sf, (sf_count_t) start, SEEK_SET|SFM_READ) != (sf_count_t) start) {
|
||||
|
|
@ -344,11 +332,6 @@ SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
|
|||
}
|
||||
}
|
||||
|
||||
if (file_cnt != cnt) {
|
||||
nframes_t delta = cnt - file_cnt;
|
||||
memset (dst+file_cnt, 0, sizeof (Sample) * delta);
|
||||
}
|
||||
|
||||
real_cnt = cnt * _info.channels;
|
||||
|
||||
Sample* interleave_buf = get_interleave_buffer (real_cnt);
|
||||
|
|
@ -908,20 +891,3 @@ SndFileSource::one_of_several_channels () const
|
|||
return _info.channels > 1;
|
||||
}
|
||||
|
||||
Sample*
|
||||
SndFileSource::get_interleave_buffer (nframes_t size)
|
||||
{
|
||||
SizedSampleBuffer* ssb;
|
||||
|
||||
if ((ssb = thread_interleave_buffer.get()) == 0) {
|
||||
ssb = new SizedSampleBuffer (size);
|
||||
thread_interleave_buffer.set (ssb);
|
||||
}
|
||||
|
||||
if (ssb->size < size) {
|
||||
ssb = new SizedSampleBuffer (size);
|
||||
thread_interleave_buffer.set (ssb);
|
||||
}
|
||||
|
||||
return ssb->buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@
|
|||
#include <ardour/silentfilesource.h>
|
||||
#include <ardour/configuration.h>
|
||||
|
||||
#undef USE_COREAUDIO_FOR_FILES
|
||||
#ifdef HAVE_COREAUDIO
|
||||
#define USE_COREAUDIO_FOR_FILES
|
||||
#endif
|
||||
|
||||
#ifdef USE_COREAUDIO_FOR_FILES
|
||||
#include <ardour/coreaudiosource.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
|
@ -73,6 +76,7 @@ peak_thread_work ()
|
|||
if (!as) {
|
||||
continue;
|
||||
}
|
||||
|
||||
as->setup_peakfile ();
|
||||
}
|
||||
}
|
||||
|
|
@ -121,12 +125,12 @@ SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef USE_COREAUDIO_FOR_FILES
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
|
||||
{
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -138,46 +142,50 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
|
|||
|
||||
catch (failed_constructor& err) {
|
||||
|
||||
/* this is allowed to throw */
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
|
||||
{
|
||||
/* this is allowed to throw */
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
|
||||
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // USE_COREAUDIO_FOR_FILES
|
||||
|
||||
#ifdef USE_COREAUDIO_FOR_FILES
|
||||
|
||||
/* this is allowed to throw */
|
||||
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
SourceCreated (ret);
|
||||
return ret;
|
||||
#else
|
||||
throw; // rethrow
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return boost::shared_ptr<Source>(); // keep stupid gcc happy
|
||||
}
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce, bool defer_peaks)
|
||||
{
|
||||
if (!(flags & Destructive)) {
|
||||
|
||||
try {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
||||
/* this is allowed to throw */
|
||||
|
||||
#ifdef USE_COREAUDIO_FOR_FILES
|
||||
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
|
|
@ -187,61 +195,19 @@ SourceFactory::createReadable (Session& s, string path, int chn, AudioFileSource
|
|||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
||||
/* this is allowed to throw */
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
throw; // rethrow
|
||||
#endif
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce, bool defer_peaks)
|
||||
{
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
|
||||
if (setup_peakfile (ret, defer_peaks)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
||||
ret->check_for_analysis_data_on_disk ();
|
||||
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // USE_COREAUDIO_FOR_FILES
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createWritable (Session& s, std::string path, bool destructive, nframes_t rate, bool announce, bool defer_peaks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __ardour_svn_revision_h__
|
||||
#define __ardour_svn_revision_h__
|
||||
static const char* ardour_svn_revision = "3107";
|
||||
static const char* ardour_svn_revision = "3117";
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue