|
libpsynth 0.2.1
|
00001 00016 /* 00017 * Copyright (C) 2010 Juan Pedro Bolivar Puente 00018 * 00019 * This file is part of Psychosynth. 00020 * 00021 * Psychosynth is free software: you can redistribute it and/or modify 00022 * it under the terms of the GNU General Public License as published by 00023 * the Free Software Foundation, either version 3 of the License, or 00024 * (at your option) any later version. 00025 * 00026 * Psychosynth is distributed in the hope that it will be useful, 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00029 * GNU General Public License for more details. 00030 * 00031 * You should have received a copy of the GNU General Public License 00032 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00033 * 00034 */ 00035 00036 /* 00037 * Copyright 2005-2007 Adobe Systems Incorporated 00038 * 00039 * Use, modification and distribution are subject to the Boost 00040 * Software License, Version 1.0. (See accompanying file 00041 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 00042 */ 00043 00044 #ifndef PSYNTH_SOUND_BUFFER_RANGE_FACTORY_HPP 00045 #define PSYNTH_SOUND_BUFFER_RANGE_FACTORY_HPP 00046 00047 #include <cassert> 00048 #include <cstddef> 00049 00050 #include <psynth/base/compat.hpp> 00051 #include <psynth/sound/metafunctions.hpp> 00052 #include <psynth/sound/mono.hpp> 00053 #include <psynth/sound/channel_convert.hpp> 00054 00068 namespace psynth 00069 { 00070 namespace sound 00071 { 00072 struct default_channel_converter; 00073 00074 template <typename T> struct dynamic_step_type; 00075 template <typename T> struct transposed_type; 00076 00081 template <typename Iterator> 00082 typename type_from_iterator<Iterator>::range 00083 interleaved_range (std::size_t size, Iterator frames) 00084 { 00085 typedef typename type_from_iterator<Iterator>::range RRange; 00086 return RRange (size, typename RRange::iterator (frames)); 00087 } 00088 00094 namespace detail 00095 { 00096 00097 template <typename Range, bool IsMutable> 00098 struct sample_pointer_type_impl; 00099 00100 template <typename Range> struct sample_pointer_type_impl<Range, true> 00101 { 00102 typedef typename sample_type<Range>::type* type; 00103 }; 00104 00105 template <typename Range> struct sample_pointer_type_impl<Range, false> 00106 { 00107 typedef const typename sample_type<Range>::type* type; 00108 }; 00109 00110 template <typename Range> struct sample_pointer_type 00111 : public sample_pointer_type_impl<Range, range_is_mutable<Range>::value> {}; 00112 00113 } /* namespace detail */ 00114 00115 00121 template <typename HomogeneousRange> 00122 typename detail::sample_pointer_type<HomogeneousRange>::type 00123 interleaved_range_get_raw_data(const HomogeneousRange& range) 00124 { 00125 BOOST_STATIC_ASSERT((!is_planar<HomogeneousRange>::value && 00126 range_is_basic<HomogeneousRange>::value)); 00127 BOOST_STATIC_ASSERT((boost::is_pointer< 00128 typename HomogeneousRange::iterator>::value)); 00129 00130 return &psynth::sound::at_c<0>(range [0]); 00131 } 00132 00138 template <typename HomogeneousRange> 00139 typename detail::sample_pointer_type<HomogeneousRange>::type 00140 planar_range_get_raw_data(const HomogeneousRange& range, int plane_index) 00141 { 00142 BOOST_STATIC_ASSERT((is_planar<HomogeneousRange>::value && 00143 range_is_basic<HomogeneousRange>::value)); 00144 return dynamic_at_c (range.begin (), plane_index); 00145 } 00146 00147 00159 template <typename SrcConstRefP, typename DstP, 00160 typename CC=default_channel_converter> 00161 // const_reference to the source frame and destination frame value 00162 class channel_convert_deref_fn : 00163 public deref_base<channel_convert_deref_fn<SrcConstRefP, DstP, CC>, 00164 DstP, DstP, const DstP&, SrcConstRefP, DstP, false> 00165 { 00166 public: 00167 channel_convert_deref_fn () {} 00168 channel_convert_deref_fn (CC cc_in) : _cc (cc_in) {} 00169 00170 DstP operator () (SrcConstRefP srcP) const 00171 { 00172 DstP dstP; 00173 _cc (srcP, dstP); 00174 return dstP; 00175 } 00176 00177 private: 00178 CC _cc; // channel-converter 00179 }; 00180 00181 00182 namespace detail 00183 { 00184 00185 // Add channel converter upon dereferencing 00186 template <typename SrcRange, typename CC, typename DstP, typename SrcP> 00187 struct channel_converted_range_type_impl 00188 { 00189 private: 00190 typedef channel_convert_deref_fn< 00191 typename SrcRange::const_type::reference,DstP,CC> deref_t; 00192 typedef typename SrcRange::template add_deref<deref_t> add_ref_t; 00193 00194 public: 00195 typedef typename add_ref_t::type type; 00196 static type make (const SrcRange& sv,CC cc) 00197 { 00198 return add_ref_t::make (sv, deref_t (cc)); 00199 } 00200 }; 00201 00202 /* If the Src range has the same frame type as the target, there is 00203 no need for channel conversion */ 00204 template <typename SrcRange, typename CC, typename DstP> 00205 struct channel_converted_range_type_impl<SrcRange,CC,DstP,DstP> 00206 { 00207 typedef SrcRange type; 00208 static type make (const SrcRange& sv, CC) 00209 { return sv; } 00210 }; 00211 00212 } /* namespace detail */ 00213 00214 00221 template <typename SrcRange, typename DstP, typename CC=default_channel_converter> 00222 struct channel_converted_range_type : 00223 public detail::channel_converted_range_type_impl<SrcRange, 00224 CC, 00225 DstP, 00226 typename SrcRange::value_type> 00227 { 00228 PSYNTH_CLASS_REQUIRE(DstP, psynth::sound, MutableFrameConcept) 00229 // Why does it have to be mutable??? 00230 }; 00231 00232 00238 template <typename DstP, typename Range, typename CC> 00239 inline typename channel_converted_range_type<Range, DstP, CC>::type 00240 channel_converted_range (const Range& src, CC cc) 00241 { 00242 return channel_converted_range_type<Range,DstP,CC>::make(src,cc); 00243 } 00244 00250 template <typename DstP, typename Range> 00251 inline typename channel_converted_range_type<Range,DstP>::type 00252 channel_converted_range (const Range& src) 00253 { 00254 return channel_converted_range<DstP>(src, default_channel_converter()); 00255 } 00256 00257 00265 template <typename Range> 00266 inline typename dynamic_step_type<Range>::type flipped_range (const Range& src) 00267 { 00268 typedef typename dynamic_step_type<Range>::type RRange; 00269 return RRange (src.size (), make_step_iterator (src.end () - 1, -1)); 00270 } 00271 00279 template <typename Range> 00280 inline typename buffer_range_type<Range>::type 00281 sub_range (const Range& src, size_t start, size_t size) 00282 { 00283 typedef typename buffer_range_type<Range>::type RRange; 00284 return RRange (size, src.at (start)); 00285 } 00286 00299 #ifdef PSYNTH_BUFFER_MODEL_RANGE 00300 00301 template <typename F, bool P, typename A> 00302 class buffer; 00303 00304 template <typename F, bool P, typename A> 00305 inline typename buffer_range_type<buffer<F,P,A> >::type 00306 sub_range (buffer<F,P,A>& src, size_t start, size_t size) 00307 { 00308 typedef typename buffer_range_type<buffer<F,P,A> >::type RRange; 00309 return RRange (size, src.at (start)); 00310 } 00311 00312 #endif /* PSYNTH_BUFFER_MODEL_RANGE */ 00313 00326 #ifdef PSYNTH_BUFFER_MODEL_RANGE 00327 00328 template <typename Range> 00329 inline typename buffer_range_type<Range>::type 00330 sub_range (Range& src, 00331 const typename Range::size_type start, 00332 const typename Range::size_type size) 00333 { 00334 typedef typename buffer_range_type<Range>::type RRange; 00335 return RRange (size, src.at (start)); 00336 } 00337 00338 #endif /* PSYNTH_BUFFER_MODEL_RANGE */ 00339 00348 template <typename Range> 00349 inline typename dynamic_step_type<Range>::type 00350 sub_sampled_range (const Range& src, typename Range::size_type step) 00351 { 00352 assert (step > 0); 00353 typedef typename dynamic_step_type<Range>::type RRange; 00354 return RRange ((src.size () + (step - 1)) / step, 00355 make_step_iterator (src.begin (), step)); 00356 } 00357 00358 00366 namespace detail 00367 { 00368 template <typename Range, bool AreSamplesTogether> 00369 struct nth_sample_range_basic_impl; 00370 00376 template <typename Range> 00377 struct nth_sample_range_basic_impl<Range, false> 00378 { 00379 typedef typename range_type<typename sample_type<Range>::type, 00380 mono_layout, false, true, 00381 range_is_mutable<Range>::value>::type type; 00382 00383 static type make (const Range& src, int n) 00384 { 00385 typedef typename type::iterator iterator; 00386 typedef typename iterator_adaptor_get_base <iterator>::type iterator_base; 00387 00388 return type (src.size (), 00389 iterator (iterator_base (& (src [0] [n])), 00390 src.frame_size ())); 00391 } 00392 }; 00393 00394 /* 00395 nth_sample_range when the samples are together in memory (true for 00396 simple grayscale or planar buffers) 00397 */ 00398 template <typename Range> 00399 struct nth_sample_range_basic_impl<Range, true> 00400 { 00401 typedef typename range_type<typename sample_type<Range>::type, 00402 mono_layout, false, false, 00403 range_is_mutable<Range>::value>::type type; 00404 00405 static type make (const Range& src, int n) 00406 { 00407 typedef typename type::iterator iterator; 00408 return interleaved_range (src.size (), (iterator) &(src [0][n])); 00409 } 00410 }; 00411 00412 template <typename Range, bool IsBasic> 00413 struct nth_sample_range_impl; 00414 00415 // For basic (memory-based) ranges dispatch to nth_sample_range_basic_impl 00416 template <typename Range> struct nth_sample_range_impl<Range,true> 00417 { 00418 private: 00419 typedef typename Range::iterator src_iterator; 00420 00421 // Determines whether the samples of a given frame iterator are 00422 // adjacent in memory. Planar and grayscale iterators have 00423 // samples adjacent in memory, whereas multi-sample interleaved 00424 // and iterators with non-fundamental step do not. 00425 BOOST_STATIC_CONSTANT(bool, adjacent= 00426 !iterator_is_step<src_iterator>::value && 00427 (is_planar<src_iterator>::value || 00428 num_samples<Range>::value==1)); 00429 public: 00430 typedef typename nth_sample_range_basic_impl <Range, adjacent>::type type; 00431 00432 static type make (const Range& src, int n) 00433 { 00434 return nth_sample_range_basic_impl <Range,adjacent>::make (src,n); 00435 } 00436 }; 00437 00450 template <typename SrcP> 00451 // SrcP is a reference to FrameConcept (could be frame value or 00452 // const/non-const reference) Examples: frame<T,L>, frame<T,L>&, const 00453 // frame<T,L>&, planar_frame_reference<T&,L>, 00454 // planar_frame_reference<const T&,L> 00455 struct nth_sample_deref_fn 00456 { 00457 BOOST_STATIC_CONSTANT(bool, is_mutable=frame_is_reference<SrcP>::value && 00458 frame_reference_is_mutable<SrcP>::value); 00459 00460 private: 00461 typedef typename boost::remove_reference<SrcP>::type src_frame_t; 00462 typedef typename sample_type<src_frame_t>::type sample_t; 00463 typedef typename src_frame_t::const_reference const_ref_t; 00464 typedef typename frame_reference_type< 00465 sample_t, mono_layout, false, is_mutable>::type ref_t; 00466 00467 int _n; // the sample to use 00468 00469 public: 00470 typedef nth_sample_deref_fn<const_ref_t> const_type; 00471 typedef typename frame_value_type< 00472 sample_t, mono_layout>::type value_type; 00473 typedef typename frame_reference_type< 00474 sample_t,mono_layout,false,false>::type const_reference; 00475 typedef SrcP argument_type; 00476 typedef typename boost::mpl::if_c< 00477 is_mutable, ref_t, value_type>::type reference; 00478 typedef reference result_type; 00479 00480 nth_sample_deref_fn (int n = 0) 00481 : _n(n) 00482 {} 00483 00484 template <typename P> 00485 nth_sample_deref_fn (const nth_sample_deref_fn<P>& d) 00486 : _n(d._n) {} 00487 00488 result_type operator () (argument_type src_f) const { 00489 return result_type (src_f[_n]); 00490 } 00491 }; 00492 00493 template <typename Range> 00494 struct nth_sample_range_impl<Range,false> 00495 { 00496 private: 00497 typedef nth_sample_deref_fn<typename Range::reference> deref_t; 00498 typedef typename Range::template add_deref<deref_t> AD; 00499 00500 public: 00501 typedef typename AD::type type; 00502 static type make(const Range& src, int n) 00503 { 00504 return AD::make(src, deref_t(n)); 00505 } 00506 }; 00507 00508 } /* namespace detail */ 00509 00521 template <typename Range> 00522 struct nth_sample_range_type 00523 { 00524 private: 00525 PSYNTH_CLASS_REQUIRE(Range, psynth::sound, BufferRangeConcept) 00526 typedef detail::nth_sample_range_impl<Range, range_is_basic<Range>::value> VB; 00527 00528 public: 00529 typedef typename VB::type type; 00530 static type make(const Range& src, int n) { return VB::make(src,n); } 00531 }; 00532 00533 00537 template <typename Range> 00538 typename nth_sample_range_type<Range>::type 00539 nth_sample_range (const Range& src, int n) 00540 { 00541 return nth_sample_range_type<Range>::make (src,n); 00542 } 00543 00544 00552 namespace detail 00553 { 00554 00555 template <int K, typename Range, bool AreSamplesTogether> 00556 struct kth_sample_range_basic_impl; 00557 00558 /* 00559 kth_sample_range when the samples are not adjacent in memory. This 00560 can happen for multi-sample interleaved buffers or buffers with a 00561 step 00562 */ 00563 template <int K, typename Range> 00564 struct kth_sample_range_basic_impl <K, Range, false> 00565 { 00566 private: 00567 typedef typename kth_element_type<typename Range::value_type,K>::type sample_t; 00568 00569 public: 00570 typedef typename range_type<sample_t, mono_layout, false, true, 00571 range_is_mutable<Range>::value>::type type; 00572 00573 static type make(const Range& src) 00574 { 00575 typedef typename type::iterator iterator; 00576 typedef typename iterator_adaptor_get_base<iterator>::type iterator_base; 00577 return type(src.size (), 00578 iterator (iterator_base (&sound::at_c<K> (src [0])), 00579 src.frame_size ())); 00580 } 00581 }; 00582 00583 /* 00584 kth_sample_range when the samples are together in memory (true for 00585 simple grayscale or planar buffers) 00586 */ 00587 template <int K, typename Range> 00588 struct kth_sample_range_basic_impl <K, Range, true> 00589 { 00590 private: 00591 typedef typename kth_element_type<typename Range::value_type, K>::type sample_t; 00592 00593 public: 00594 typedef typename range_type< 00595 sample_t, mono_layout, false, false, range_is_mutable<Range>::value>::type type; 00596 00597 static type make (const Range& src) 00598 { 00599 typedef typename type::iterator iterator; 00600 return interleaved_range (src.size (), (iterator) &sound::at_c<K> (src[0])); 00601 } 00602 }; 00603 00604 template <int K, typename Range, bool IsBasic> 00605 struct kth_sample_range_impl; 00606 00607 /* For basic (memory-based) ranges dispatch to __kth_sample_range_basic */ 00608 template <int K, typename Range> 00609 struct kth_sample_range_impl <K, Range, true> 00610 { 00611 private: 00612 typedef typename Range::iterator src_iterator; 00613 00614 // Determines whether the samples of a given frame iterator are 00615 // adjacent in memory. Planar and grayscale iterators have 00616 // samples adjacent in memory, whereas multi-sample interleaved 00617 // and iterators with non-fundamental step do not. 00618 BOOST_STATIC_CONSTANT(bool, adjacent= 00619 !iterator_is_step<src_iterator>::value && 00620 (is_planar<src_iterator>::value || 00621 num_samples<Range>::value==1)); 00622 00623 public: 00624 typedef typename kth_sample_range_basic_impl <K, Range, adjacent>::type type; 00625 00626 static type make (const Range& src) 00627 { 00628 return kth_sample_range_basic_impl <K, Range, adjacent>::make (src); 00629 } 00630 }; 00631 00643 template <int K, typename SrcP> 00644 // SrcP is a reference to FrameConcept (could be frame value or 00645 // const/non-const reference) Examples: frame<T,L>, frame<T,L>&, const 00646 // frame<T,L>&, planar_frame_reference<T&,L>, 00647 // planar_frame_reference<const T&,L> 00648 struct kth_sample_deref_fn 00649 { 00650 BOOST_STATIC_CONSTANT(bool, is_mutable = frame_is_reference<SrcP>::value && 00651 frame_reference_is_mutable<SrcP>::value); 00652 00653 private: 00654 typedef typename boost::remove_reference<SrcP>::type src_frame_t; 00655 typedef typename kth_element_type<src_frame_t, K>::type sample_t; 00656 typedef typename src_frame_t::const_reference const_ref_t; 00657 typedef typename frame_reference_type< 00658 sample_t, mono_layout, false, is_mutable>::type ref_t; 00659 00660 public: 00661 typedef kth_sample_deref_fn<K,const_ref_t> const_type; 00662 typedef typename frame_value_type< 00663 sample_t, mono_layout>::type value_type; 00664 typedef typename frame_reference_type< 00665 sample_t, mono_layout,false,false>::type const_reference; 00666 typedef SrcP argument_type; 00667 typedef typename boost::mpl::if_c< 00668 is_mutable, ref_t, value_type>::type reference; 00669 typedef reference result_type; 00670 00671 kth_sample_deref_fn () {} 00672 template <typename P> 00673 kth_sample_deref_fn (const kth_sample_deref_fn<K, P>&) {} 00674 00675 result_type operator () (argument_type srcframe) const 00676 { 00677 return result_type (sound::at_c<K>(srcframe)); 00678 } 00679 }; 00680 00681 template <int K, typename Range> 00682 struct kth_sample_range_impl<K,Range,false> 00683 { 00684 private: 00685 typedef kth_sample_deref_fn<K,typename Range::reference> deref_t; 00686 typedef typename Range::template add_deref<deref_t> AD; 00687 00688 public: 00689 typedef typename AD::type type; 00690 static type make (const Range& src) { return AD::make (src, deref_t ()); } 00691 }; 00692 00693 } /* namespace detail */ 00694 00707 template <int K, typename Range> 00708 struct kth_sample_range_type 00709 { 00710 private: 00711 PSYNTH_CLASS_REQUIRE(Range, psynth::sound, BufferRangeConcept) 00712 typedef detail::kth_sample_range_impl<K, Range, range_is_basic<Range>::value> VB; 00713 00714 public: 00715 typedef typename VB::type type; 00716 static type make (const Range& src) { return VB::make(src); } 00717 }; 00718 00720 template <int K, typename Range> 00721 typename kth_sample_range_type<K,Range>::type 00722 kth_sample_range(const Range& src) 00723 { 00724 return kth_sample_range_type<K,Range>::make(src); 00725 } 00726 00727 } /* namespace sound */ 00728 } /* namespace psynth */ 00729 00730 #endif /* PSYNTH_SOUND_BUFFER_RANGE_FACTORY */
1.7.4