Wouldn't it be nice if plugin presets had a description/comment?
[ardour.git] / libs / ardour / audio_port.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <cassert>
20
21 #include "pbd/malign.h"
22 #include "pbd/stacktrace.h"
23
24 #include "ardour/audio_buffer.h"
25 #include "ardour/audioengine.h"
26 #include "ardour/audio_port.h"
27 #include "ardour/data_type.h"
28 #include "ardour/port_engine.h"
29
30 using namespace ARDOUR;
31 using namespace std;
32
33 #define ENGINE AudioEngine::instance()
34 #define port_engine AudioEngine::instance()->port_engine()
35
36 AudioPort::AudioPort (const std::string& name, PortFlags flags)
37         : Port (name, DataType::AUDIO, flags)
38         , _buffer (new AudioBuffer (0))
39 {
40         assert (name.find_first_of (':') == string::npos);
41         cache_aligned_malloc ((void**) &_data, sizeof (Sample) * 8192);
42         _src.setup (_resampler_quality);
43         _src.set_rrfilt (10);
44 }
45
46 AudioPort::~AudioPort ()
47 {
48         cache_aligned_free (_data);
49         delete _buffer;
50 }
51
52 void
53 AudioPort::cycle_start (pframes_t nframes)
54 {
55         /* caller must hold process lock */
56         Port::cycle_start (nframes);
57
58         if (sends_output()) {
59                 _buffer->prepare ();
60         } else if (!externally_connected ()) {
61                 /* ardour internal port, just silence input, don't resample */
62                 // TODO reset resampler only once
63                 _src.reset ();
64                 memset (_data, 0, _cycle_nframes * sizeof (float));
65         } else {
66                 _src.inp_data  = (float*)port_engine.get_buffer (_port_handle, nframes);
67                 _src.inp_count = nframes;
68                 _src.out_count = _cycle_nframes;
69                 _src.set_rratio (_cycle_nframes / (double)nframes);
70                 _src.out_data  = _data;
71                 _src.process ();
72                 while (_src.out_count > 0) {
73                         *_src.out_data =  _src.out_data[-1];
74                         ++_src.out_data;
75                         --_src.out_count;
76                 }
77         }
78 }
79
80 void
81 AudioPort::cycle_end (pframes_t nframes)
82 {
83         if (sends_output() && !_buffer->written() && _port_handle) {
84                 if (!_buffer->data (0)) {
85                         get_audio_buffer (nframes);
86                 }
87                 if (_buffer->capacity() >= nframes) {
88                         _buffer->silence (nframes);
89                 }
90         }
91
92         if (sends_output() && _port_handle) {
93
94                 if (!externally_connected ()) {
95                         /* ardour internal port, data goes nowhere, skip resampling */
96                         // TODO reset resampler only once
97                         _src.reset ();
98                         return;
99                 }
100
101                 _src.inp_count = _cycle_nframes;
102                 _src.out_count = nframes;
103                 _src.set_rratio (nframes / (double)_cycle_nframes);
104                 _src.inp_data  = _data;
105                 _src.out_data  = (float*)port_engine.get_buffer (_port_handle, nframes);
106                 _src.process ();
107                 while (_src.out_count > 0) {
108                         *_src.out_data =  _src.out_data[-1];
109                         ++_src.out_data;
110                         --_src.out_count;
111                 }
112         }
113 }
114
115 void
116 AudioPort::cycle_split ()
117 {
118 }
119
120 AudioBuffer&
121 AudioPort::get_audio_buffer (pframes_t nframes)
122 {
123         /* caller must hold process lock */
124         assert (_port_handle);
125
126         Sample* addr;
127
128         if (!externally_connected ()) {
129                 addr = (Sample *) port_engine.get_buffer (_port_handle, nframes);
130         } else {
131                 /* _data was read and resampled as necessary in ::cycle_start */
132                 addr = &_data[_global_port_buffer_offset];
133         }
134
135         _buffer->set_data (addr, nframes);
136
137         return *_buffer;
138 }
139
140 Sample*
141 AudioPort::engine_get_whole_audio_buffer ()
142 {
143         /* caller must hold process lock */
144         assert (_port_handle);
145         return (Sample *) port_engine.get_buffer (_port_handle, ENGINE->samples_per_cycle());
146 }