1 // audio backend helpers
2 // Copyright (C) 2010 Tim Blechmann
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.
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"
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;
44 /* to be called from the audio callback */
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());
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());
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
);
139 nova::copyvec(input_samples
[i
].get(), inputs
[i
], frames
);
143 for (uint16_t i
= 0; i
!= input_channels
; ++i
) {
144 nova::copyvec(input_samples
[i
].get(), 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
);
157 nova::copyvec(outputs
[i
], output_samples
[i
].get(), frames
);
158 outputs
[i
] += frames
;
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
187 uint16_t input_channels
, output_channels
;
190 audio_settings_basic(void):
191 samplerate_(0.f
), input_channels(0), output_channels(0)
194 float get_samplerate(void) const
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 */