X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudio_port.cc;h=1a6c30dcf25b5e6b07c66a27257603d59ad1d76c;hb=b285559767e21aae4467270590f048c3263fd742;hp=714be28f3409c4c0ce7fe4006fd7621bdb9598ba;hpb=449aab3c465bbbf66d221fac3d7ea559f1720357;p=ardour.git diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc index 714be28f34..1a6c30dcf2 100644 --- a/libs/ardour/audio_port.cc +++ b/libs/ardour/audio_port.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2006 Paul Davis + Copyright (C) 2006 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 @@ -17,110 +17,130 @@ */ #include -#include -#include -#include -#include -using namespace ARDOUR; -using namespace std; - -AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nframes_t capacity) - : Port (name, flags) - , BaseAudioPort (name, flags) - , PortFacade (name, flags) -{ - if (!external || receives_input()) { - - /* internal-only and input ports need their own buffers. - external output ports use the external port buffer. - */ - - _buffer = new AudioBuffer (capacity); - _own_buffer = true; - } - - if (!external) { - - _ext_port = 0; - set_name (name); - - } else { - - /* make the JackAudioPort create its own buffer. For input, - we will copy from it during cycle_start(). For output, - we will set up our buffer to point to its buffer, which - will in turn be using the JACK port buffer for data. - */ +#include "pbd/malign.h" +#include "pbd/stacktrace.h" - _ext_port = new JackAudioPort (name, flags, 0); +#include "ardour/audio_buffer.h" +#include "ardour/audioengine.h" +#include "ardour/audio_port.h" +#include "ardour/data_type.h" +#include "ardour/port_engine.h" - if (sends_output()) { - _buffer = &dynamic_cast(_ext_port)->get_audio_buffer(); - } +using namespace ARDOUR; +using namespace std; - Port::set_name (_ext_port->name()); - } +#define ENGINE AudioEngine::instance() +#define port_engine AudioEngine::instance()->port_engine() - reset (); +AudioPort::AudioPort (const std::string& name, PortFlags flags) + : Port (name, DataType::AUDIO, flags) + , _buffer (new AudioBuffer (0)) +{ + assert (name.find_first_of (':') == string::npos); + cache_aligned_malloc ((void**) &_data, sizeof (Sample) * 8192); + _src.setup (_resampler_quality); + _src.set_rrfilt (10); } -AudioPort::~AudioPort() +AudioPort::~AudioPort () { - if (_ext_port) { - delete _ext_port; - _ext_port = 0; - } + cache_aligned_free (_data); + delete _buffer; } void -AudioPort::reset() +AudioPort::cycle_start (pframes_t nframes) { - BaseAudioPort::reset(); - - if (_ext_port) { - _ext_port->reset (); + /* caller must hold process lock */ + Port::cycle_start (nframes); + + if (sends_output()) { + _buffer->prepare (); + } else if (!externally_connected ()) { + /* ardour internal port, just silence input, don't resample */ + // TODO reset resampler only once + _src.reset (); + memset (_data, 0, _cycle_nframes * sizeof (float)); + } else { + _src.inp_data = (float*)port_engine.get_buffer (_port_handle, nframes); + _src.inp_count = nframes; + _src.out_count = _cycle_nframes; + _src.set_rratio (_cycle_nframes / (double)nframes); + _src.out_data = _data; + _src.process (); + while (_src.out_count > 0) { + *_src.out_data = _src.out_data[-1]; + ++_src.out_data; + --_src.out_count; + } } } - void -AudioPort::cycle_start (nframes_t nframes, nframes_t offset) +AudioPort::cycle_end (pframes_t nframes) { - /* caller must hold process lock */ - - if (_ext_port) { - _ext_port->cycle_start (nframes, offset); + if (sends_output() && !_buffer->written() && _port_handle) { + if (!_buffer->data (0)) { + get_audio_buffer (nframes); + } + if (_buffer->capacity() >= nframes) { + _buffer->silence (nframes); + } } - if (_flags & IsInput) { - - if (_ext_port) { - _buffer->read_from (dynamic_cast(_ext_port)->get_audio_buffer(), nframes, offset); + if (sends_output() && _port_handle) { - if (!_connections.empty()) { - (*_mixdown) (_connections, _buffer, nframes, offset, false); - } + if (!externally_connected ()) { + /* ardour internal port, data goes nowhere, skip resampling */ + // TODO reset resampler only once + _src.reset (); + return; + } - } else { - - if (_connections.empty()) { - _buffer->silence (nframes, offset); - } else { - (*_mixdown) (_connections, _buffer, nframes, offset, true); - } + _src.inp_count = _cycle_nframes; + _src.out_count = nframes; + _src.set_rratio (nframes / (double)_cycle_nframes); + _src.inp_data = _data; + _src.out_data = (float*)port_engine.get_buffer (_port_handle, nframes); + _src.process (); + while (_src.out_count > 0) { + *_src.out_data = _src.out_data[-1]; + ++_src.out_data; + --_src.out_count; } + } +} + +void +AudioPort::cycle_split () +{ +} + +AudioBuffer& +AudioPort::get_audio_buffer (pframes_t nframes) +{ + /* caller must hold process lock */ + assert (_port_handle); + Sample* addr; + + if (!externally_connected ()) { + addr = (Sample *) port_engine.get_buffer (_port_handle, nframes); } else { - - // XXX if we could get the output stage to not purely mix into, but also - // to initially overwrite the buffer, we could avoid this silence step. - - _buffer->silence (nframes, offset); + /* _data was read and resampled as necessary in ::cycle_start */ + addr = &_data[_global_port_buffer_offset]; } + + _buffer->set_data (addr, nframes); + + return *_buffer; } -void -AudioPort::cycle_end (nframes_t nframes, nframes_t offset) +Sample* +AudioPort::engine_get_whole_audio_buffer () { + /* caller must hold process lock */ + assert (_port_handle); + return (Sample *) port_engine.get_buffer (_port_handle, ENGINE->samples_per_cycle()); }