Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / server / supernova / audio_backend / audio_backend_common.hpp
blob334cbda8afa775799605f973b31e5ca9dd82db49
1 // audio backend helpers
2 // Copyright (C) 2010 Tim Blechmann
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.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef AUDIO_BACKEND_AUDIO_BACKEND_COMMON_HPP
20 #define AUDIO_BACKEND_AUDIO_BACKEND_COMMON_HPP
22 #include <boost/mpl/if.hpp>
23 #include <boost/static_assert.hpp>
25 #include "nova-simd/simd_memory.hpp"
26 #include "nova-tt/dummy_mutex.hpp"
27 #include "nova-tt/spin_lock.hpp"
29 #include "utilities/malloc_aligned.hpp"
30 #include "utilities/sized_array.hpp"
33 namespace nova {
34 namespace detail {
36 template <typename sample_type, typename io_sample_type, bool blocking, bool managed_memory = true>
37 class audio_delivery_helper:
38 boost::mpl::if_c<blocking, spin_lock, dummy_mutex>::type
40 typedef typename boost::mpl::if_c<blocking, spin_lock, dummy_mutex>::type lock_t;
41 typedef std::size_t size_t;
43 public:
44 /* to be called from the audio callback */
45 /* @{ */
46 void deliver_dac_output(const sample_type * source, size_t channel, size_t frames)
48 assert(channel < output_samples.size());
49 typename lock_t::scoped_lock lock(*this);
50 addvec_simd(output_samples[channel].get(), source, frames);
53 void deliver_dac_output_64(const sample_type * source, size_t channel)
55 assert(channel < output_samples.size());
56 typename lock_t::scoped_lock lock(*this);
57 addvec_simd<64>(output_samples[channel].get(), source);
60 void copy_dac_output(const sample_type * source, size_t channel, size_t frames)
62 assert(channel < output_samples.size());
63 copyvec_simd(output_samples[channel].get(), source, frames);
66 void copy_dac_output_64(const sample_type * source, size_t channel)
68 assert(channel < output_samples.size());
69 typename lock_t::scoped_lock lock(*this);
70 copyvec_simd<64>(output_samples[channel].get(), source);
73 void fetch_adc_input(sample_type * destination, size_t channel, size_t frames)
75 copyvec_simd(destination, input_samples[channel].get(), frames);
78 void fetch_adc_input_64(sample_type * destination, size_t channel)
80 copyvec_simd<64>(destination, input_samples[channel].get());
82 /* @} */
84 /* @{ */
85 /** buffers can be directly mapped to the io regions of the host application */
86 template <typename Iterator>
87 void input_mapping(Iterator const & buffer_begin, Iterator const & buffer_end)
89 BOOST_STATIC_ASSERT(!managed_memory);
91 size_t input_count = buffer_end - buffer_begin;
93 input_samples.resize(input_count);
94 std::copy(buffer_begin, buffer_end, input_samples.begin());
97 template <typename Iterator>
98 void output_mapping(Iterator const & buffer_begin, Iterator const & buffer_end)
100 BOOST_STATIC_ASSERT(!managed_memory);
102 size_t output_count = buffer_end - buffer_begin;
104 output_samples.resize(output_count);
105 std::copy(buffer_begin, buffer_end, output_samples.begin());
107 /* @} */
109 protected:
110 void clear_inputs(size_t frames_per_tick)
112 for (uint16_t channel = 0; channel != input_samples.size(); ++channel)
113 zerovec_simd(input_samples[channel].get(), frames_per_tick);
116 void clear_outputs(size_t frames_per_tick)
118 for (uint16_t channel = 0; channel != output_samples.size(); ++channel)
119 zerovec_simd(output_samples[channel].get(), frames_per_tick);
122 void prepare_helper_buffers(size_t input_channels, size_t output_channels, size_t frames)
124 BOOST_STATIC_ASSERT(managed_memory);
126 input_samples.resize(input_channels);
127 output_samples.resize(output_channels);
128 std::generate(input_samples.begin(), input_samples.end(), boost::bind(calloc_aligned<sample_type>, frames));
129 std::generate(output_samples.begin(), output_samples.end(), boost::bind(calloc_aligned<sample_type>, frames));
132 void fetch_inputs(const float ** inputs, size_t frames, int input_channels)
134 if (is_multiple_of_vectorsize(frames)) {
135 for (uint16_t i = 0; i != input_channels; ++i) {
136 if (is_aligned(inputs[i]))
137 nova::copyvec_simd(input_samples[i].get(), inputs[i], frames);
138 else
139 nova::copyvec(input_samples[i].get(), inputs[i], frames);
140 inputs[i] += frames;
142 } else {
143 for (uint16_t i = 0; i != input_channels; ++i) {
144 nova::copyvec(input_samples[i].get(), inputs[i], frames);
145 inputs[i] += frames;
150 void deliver_outputs(float ** outputs, size_t frames, int output_channels)
152 if (is_multiple_of_vectorsize(frames)) {
153 for (uint16_t i = 0; i != output_channels; ++i) {
154 if (is_aligned(outputs[i]))
155 nova::copyvec_simd(outputs[i], output_samples[i].get(), frames);
156 else
157 nova::copyvec(outputs[i], output_samples[i].get(), frames);
158 outputs[i] += frames;
160 } else {
161 for (uint16_t i = 0; i != output_channels; ++i) {
162 nova::copyvec(outputs[i], output_samples[i].get(), frames);
163 outputs[i] += frames;
168 static bool is_aligned(const void * arg)
170 size_t mask = sizeof(vec<float>::size) * sizeof(float) * 8 - 1;
171 return !((size_t)arg & mask);
174 static bool is_multiple_of_vectorsize(size_t count)
176 return !(count & (vec<float>::objects_per_cacheline - 1));
179 sized_array<aligned_storage_ptr<sample_type, managed_memory>,
180 aligned_allocator<sample_type> > input_samples, output_samples;
183 class audio_settings_basic
185 protected:
186 float samplerate_;
187 uint16_t input_channels, output_channels;
189 public:
190 audio_settings_basic(void):
191 samplerate_(0.f), input_channels(0), output_channels(0)
194 float get_samplerate(void) const
196 return samplerate_;
199 uint16_t get_input_count(void) const
201 return input_channels;
204 uint16_t get_output_count(void) const
206 return output_channels;
210 } /* namespace detail */
211 } /* namespace nova */
214 #endif /* AUDIO_BACKEND_AUDIO_BACKEND_COMMON_HPP */