diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-02-27 13:56:14 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-02-27 13:56:14 +0000 |
commit | 3188ad3ab03fb15b430cc6dc2341a66c90a9c393 (patch) | |
tree | 1f1d49f73976b4bb39c298d9e585c2b3c8cb2d49 /libs/ardour/coreaudiosource.cc | |
parent | a969d639864f7c8d3f19aa4bd8f498b4391fb1d8 (diff) |
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
Diffstat (limited to 'libs/ardour/coreaudiosource.cc')
-rw-r--r-- | libs/ardour/coreaudiosource.cc | 170 |
1 files changed, 105 insertions, 65 deletions
diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc index 703225e502..011bcce337 100644 --- a/libs/ardour/coreaudiosource.cc +++ b/libs/ardour/coreaudiosource.cc @@ -1,5 +1,6 @@ /* - Copyright (C) 2006 Paul Davis + 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 { - try { - af.Seek (start); - } catch (CAXException& cax) { - error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start, _name.substr (1)) << endmsg; - return 0; - } + nframes_t nread = 0; - AudioBufferList abl; - abl.mNumberBuffers = 1; - abl.mBuffers[0].mNumberChannels = n_channels; - - UInt32 new_cnt = cnt; - if (n_channels == 1) { - abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample); - abl.mBuffers[0].mData = dst; + while (nread < cnt) { + + try { + af.Seek (start+nread); + } catch (CAXException& cax) { + error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start+nread, _name.substr (1)) << endmsg; + return -1; + } + + UInt32 new_cnt = cnt - nread; + + abl.mBuffers[0].mDataByteSize = new_cnt * n_channels * sizeof(Sample); + abl.mBuffers[0].mData = dst + nread; + try { af.Read (new_cnt, &abl); } catch (CAXException& cax) { error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name); + return -1; } - _read_data_count = new_cnt * sizeof(float); - return new_cnt; - } - - 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; + nread += new_cnt; + } + + 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) { - cerr << "channel: " << _channel << endl; + /* read starts beyond end of data, just memset to zero */ - try { - af.Read (real_cnt, &abl); - } catch (CAXException& cax) { - error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name); - } - float *ptr = tmpbuf + _channel; - real_cnt /= n_channels; + file_cnt = 0; + + } else if (start + cnt > _length) { - /* stride through the interleaved data */ + /* read ends beyond end of data, read some, memset the rest */ + + file_cnt = _length - start; + + } else { - for (uint32_t n = 0; n < real_cnt; ++n) { - dst[n] = *ptr; - ptr += n_channels; + /* 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 |