30#ifndef APF_COMBINE_CHANNELS_H
31#define APF_COMBINE_CHANNELS_H
47namespace CombineChannelsResult
71template<
typename Derived,
typename ListProxy,
typename Out>
75 using T =
typename std::iterator_traits<
typename std::remove_reference<
76 ListProxy>::type::value_type::iterator>::value_type;
101 this->derived().before_the_loop();
103 for (
auto& item: _in)
105 using namespace CombineChannelsResult;
107 switch (_selection = f.select(item))
113 this->derived().case_one(item, f);
119 this->derived().case_two(item, f);
123 throw std::runtime_error(
"Predicate must return 0, 1 or 2!");
127 this->derived().after_the_loop();
131 std::fill(_out.begin(), _out.end(), T());
135 void before_the_loop() {}
137 template<
typename ItemType,
typename F>
138 void case_one(
const ItemType&, F&)
140 throw std::logic_error(
"CombineChannelsBase: case 1 not implemented!");
143 template<
typename ItemType,
typename F>
144 void case_two(
const ItemType&, F&)
146 throw std::logic_error(
"CombineChannelsBase: case 2 not implemented!");
149 void after_the_loop() {}
155 template<
typename ItemType>
156 void _case_one_copy(
const ItemType& item)
160 std::copy(item.begin(), item.end()
165 std::copy(item.begin(), item.end(), _out.begin());
170 template<
typename ItemType,
typename FunctionType>
171 void _case_one_transform(
const ItemType& item, FunctionType& f)
175 std::transform(item.begin(), item.end()
180 std::transform(item.begin(), item.end(), _out.begin(), f);
186 CombineChannelsResult::type _selection;
192template<
typename L,
typename Out>
194 CombineChannelsCopy<L, Out>, L, Out>
202 template<
typename ItemType,
typename F>
203 void case_one(
const ItemType& item, F&)
205 this->_case_one_copy(item);
213template<
typename L,
typename Out>
215 CombineChannels<L, Out>, L, Out>
223 template<
typename ItemType,
typename F>
224 void case_one(
const ItemType& item, F& f)
226 this->_case_one_transform(item, f);
234template<
typename L,
typename Out>
236 CombineChannelsInterpolation<L, Out>, L, Out>
241 using typename _base::T;
242 using _base::_selection;
243 using _base::_accumulate;
249 template<
typename ItemType,
typename F>
250 void case_one(
const ItemType& item, F& f)
252 this->_case_one_transform(item, f);
255 template<
typename ItemType,
typename F>
256 void case_two(
const ItemType& item, F& f)
258 assert(_selection == CombineChannelsResult::change);
274struct fade_out_tag {};
278template<
typename Derived,
typename L,
typename Out,
typename Crossfade>
283 using typename _base::T;
284 using _base::_accumulate;
290 , _fade_out_buffer(fade.size())
291 , _fade_in_buffer(fade.size())
292 , _crossfade_data(fade)
295 void before_the_loop()
297 _accumulate_fade_in = _accumulate_fade_out =
false;
300 void after_the_loop()
302 if (_accumulate_fade_out)
306 std::transform(_fade_out_buffer.begin(), _fade_out_buffer.end()
307 , _crossfade_data.fade_out_begin()
309 , std::multiplies<T>());
313 std::transform(_fade_out_buffer.begin(), _fade_out_buffer.end()
314 , _crossfade_data.fade_out_begin()
316 , std::multiplies<T>());
320 if (_accumulate_fade_in)
324 std::transform(_fade_in_buffer.begin(), _fade_in_buffer.end()
325 , _crossfade_data.fade_in_begin()
327 , std::multiplies<T>());
331 std::transform(_fade_in_buffer.begin(), _fade_in_buffer.end()
332 , _crossfade_data.fade_in_begin()
334 , std::multiplies<T>());
341 bool _accumulate_fade_in, _accumulate_fade_out;
342 std::vector<T> _fade_out_buffer, _fade_in_buffer;
345 const Crossfade& _crossfade_data;
350template<
typename L,
typename Out,
typename Crossfade>
352 CombineChannelsCrossfadeCopy<L, Out, Crossfade>, L, Out, Crossfade>
356 L, Out, Crossfade>, L, Out, Crossfade>;
358 using _base::_fade_out_buffer;
359 using _base::_fade_in_buffer;
360 using _base::_accumulate_fade_in;
361 using _base::_accumulate_fade_out;
362 using _base::_selection;
366 :
_base(in, out, fade)
369 template<
typename ItemType,
typename F>
370 void case_one(
const ItemType& item, F&)
372 this->_case_one_copy(item);
375 template<
typename ItemType,
typename F>
376 void case_two(ItemType& item, F& f)
378 if (_selection != CombineChannelsResult::fade_in)
380 if (_accumulate_fade_out)
382 std::copy(item.begin(), item.end()
387 std::copy(item.begin(), item.end(), _fade_out_buffer.begin());
388 _accumulate_fade_out =
true;
391 if (_selection != CombineChannelsResult::fade_out)
395 if (_accumulate_fade_in)
397 std::copy(item.begin(), item.end()
402 std::copy(item.begin(), item.end(), _fade_in_buffer.begin());
403 _accumulate_fade_in =
true;
411template<
typename L,
typename Out,
typename Crossfade>
413 CombineChannelsCrossfade<L, Out, Crossfade>, L, Out, Crossfade>
417 L, Out, Crossfade>, L, Out, Crossfade>;
418 using _base::_selection;
419 using _base::_accumulate_fade_in;
420 using _base::_accumulate_fade_out;
424 :
_base(in, out, fade)
427 template<
typename ItemType,
typename F>
428 void case_one(
const ItemType& item, F& f)
430 this->_case_one_transform(item, f);
433 template<
typename ItemType,
typename F>
434 void case_two(ItemType& item, F& f)
436 if (_selection != CombineChannelsResult::fade_in)
438 if (_accumulate_fade_out)
440 std::transform(item.begin(), item.end()
442 , std::bind(f, std::placeholders::_1, fade_out_tag()));
446 std::transform(item.begin(), item.end()
447 , this->_fade_out_buffer.begin()
448 , std::bind(f, std::placeholders::_1, fade_out_tag()));
449 _accumulate_fade_out =
true;
452 if (_selection != CombineChannelsResult::fade_out)
456 if (_accumulate_fade_in)
458 std::transform(item.begin(), item.end()
463 std::transform(item.begin(), item.end()
464 , this->_fade_in_buffer.begin(), f);
465 _accumulate_fade_in =
true;
481 using iterator =
typename std::vector<T>::const_iterator;
482 using reverse_iterator =
typename std::vector<T>::const_reverse_iterator;
493 iterator fade_out_begin()
const {
return _crossfade_data.begin(); }
494 reverse_iterator fade_in_begin()
const {
return _crossfade_data.rbegin(); }
495 size_t size()
const {
return _size; }
498 const std::vector<T> _crossfade_data;
Curiously Recurring Template Pattern (CRTP) base class.
Base class for CombineChannels*.
void process(F f)
Do the actual combining.
CombineChannelsBase(L &in, Out &out)
Constructor.
Combine channels: accumulate.
Base class for CombineChannelsCrossfade*.
Combine channels: crossfade and accumulate.
Combine channels: transform, crossfade and accumulate.
Combine channels: interpolate and accumulate.
Combine channels: transform and accumulate.
Iterator with a built-in number.
Raised cosine (function object).
Crossfade using a raised cosine.
accumulating_iterator< I > make_accumulating_iterator(I base_iterator)
Helper function to create an accumulating_iterator.
Several more or less useful iterators and some macros.
Miscellaneous helper classes.
Audio Processing Framework.