|
libpsynth 0.2.1
|
00001 00015 /* 00016 * Copyright (C) 2010 Juan Pedro Bolivar Puente 00017 * 00018 * This file is part of Psychosynth. 00019 * 00020 * Psychosynth is free software: you can redistribute it and/or modify 00021 * it under the terms of the GNU General Public License as published by 00022 * the Free Software Foundation, either version 3 of the License, or 00023 * (at your option) any later version. 00024 * 00025 * Psychosynth is distributed in the hope that it will be useful, 00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00028 * GNU General Public License for more details. 00029 * 00030 * You should have received a copy of the GNU General Public License 00031 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00032 * 00033 */ 00034 00035 /* 00036 * Copyright 2005-2007 Adobe Systems Incorporated 00037 * 00038 * Use, modification and distribution are subject to the Boost 00039 * Software License, Version 1.0. (See accompanying file 00040 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 00041 */ 00042 00043 #ifndef PSYNTH_SOUND_ALGORITHM_HPP 00044 #define PSYNTH_SOUND_ALGORITHM_HPP 00045 00046 #include <cassert> 00047 #include <cstddef> 00048 #include <cstring> 00049 #include <algorithm> 00050 #include <iterator> 00051 #include <memory> 00052 #include <typeinfo> 00053 00054 #include <psynth/base/compat.hpp> 00055 #include <psynth/base/concept.hpp> 00056 #include <psynth/sound/concept.hpp> 00057 #include <psynth/sound/channel_base_algorithm.hpp> 00058 #include <psynth/sound/buffer_range.hpp> 00059 #include <psynth/sound/buffer_range_factory.hpp> 00060 #include <psynth/sound/bit_aligned_frame_iterator.hpp> 00061 00062 //#ifdef _MSC_VER 00063 //#pragma warning(push) 00064 //#pragma warning(disable : 4244) 00065 // conversion from 'psynth::image<V,Alloc>::coord_t' to 'int', possible 00066 // loss of data (visual studio compiler doesn't realize that the two 00067 // types are the same) 00068 //#endif 00069 00070 namespace psynth 00071 { 00072 namespace sound 00073 { 00074 00075 template <typename SamplePtr, typename ChannelSpace> 00076 struct planar_frame_iterator; 00077 template <typename Iterator> 00078 class memory_based_step_iterator; 00079 00081 struct error_type {}; 00082 00142 template <typename Derived, typename Result = void> 00143 struct binary_operation_obj 00144 { 00145 typedef Result result_type; 00146 00147 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00148 result_type operator () (const std::pair<const V1*, const V2*>& p) const 00149 { 00150 return apply (*p.first, *p.second, 00151 typename ranges_are_compatible<V1,V2>::type()); 00152 } 00153 00154 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00155 result_type operator () (const V1& v1, const V2& v2) const 00156 { 00157 return apply (v1, v2, typename ranges_are_compatible<V1,V2>::type ()); 00158 } 00159 00160 result_type operator () (const error_type&) const 00161 { 00162 throw std::bad_cast(); 00163 } 00164 00165 private: 00166 00167 // dispatch from apply overload to a function with distinct name 00168 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00169 result_type apply(const V1& v1, const V2& v2, boost::mpl::false_) const 00170 { 00171 return ((const Derived*) this)->apply_incompatible (v1,v2); 00172 } 00173 00174 // dispatch from apply overload to a function with distinct name 00175 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00176 result_type apply(const V1& v1, const V2& v2, boost::mpl::true_) const 00177 { 00178 return ((const Derived*)this)->apply_compatible(v1,v2); 00179 } 00180 00181 // function with distinct name - it can be overloaded by subclasses 00182 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00183 result_type apply_incompatible (const V1& v1, const V2& v2) const 00184 { 00185 throw std::bad_cast(); 00186 } 00187 }; 00188 00189 } /* namespace sound */ 00190 } /* namespace psynth */ 00191 00192 00199 namespace std 00200 { 00201 00207 template<typename T, typename Cs> 00208 PSYNTH_FORCEINLINE psynth::sound::frame<T,Cs>* 00209 copy (psynth::sound::frame<T,Cs>* first, 00210 psynth::sound::frame<T,Cs>* last, 00211 psynth::sound::frame<T,Cs>* dst) 00212 { 00213 return (psynth::sound::frame<T,Cs>*) std::copy ( 00214 (unsigned char*) first, 00215 (unsigned char*) last, 00216 (unsigned char*) dst); 00217 } 00218 00224 template<typename T, typename Cs> 00225 PSYNTH_FORCEINLINE psynth::sound::frame<T,Cs>* 00226 copy (const psynth::sound::frame<T,Cs>* first, 00227 const psynth::sound::frame<T,Cs>* last, 00228 psynth::sound::frame<T,Cs>* dst) 00229 { 00230 return (psynth::sound::frame<T,Cs>*) std::copy( 00231 (unsigned char*) first, 00232 (unsigned char*) last, 00233 (unsigned char*) dst); 00234 } 00235 00236 } /* namespace std */ 00237 00238 namespace psynth 00239 { 00240 namespace sound 00241 { 00242 namespace detail 00243 { 00244 00245 template <typename I, typename O> 00246 struct copy_fn 00247 { 00248 PSYNTH_FORCEINLINE I operator() (I first, I last, O dst) const 00249 { 00250 return std::copy (first, last, dst); 00251 } 00252 }; 00253 00254 } /* namespace detail */ 00255 } /* namespace sound */ 00256 } /* namespace psynth */ 00257 00258 namespace std 00259 { 00260 00266 template<typename Cs, typename IC1, typename IC2> PSYNTH_FORCEINLINE 00267 psynth::sound::planar_frame_iterator<IC2,Cs> 00268 copy (psynth::sound::planar_frame_iterator<IC1,Cs> first, 00269 psynth::sound::planar_frame_iterator<IC1,Cs> last, 00270 psynth::sound::planar_frame_iterator<IC2,Cs> dst) 00271 { 00272 psynth::base::psynth_function_requires < 00273 psynth::sound::SamplesCompatibleConcept< 00274 typename std::iterator_traits<IC1>::value_type, 00275 typename std::iterator_traits<IC2>::value_type> >(); 00276 static_for_each (first, last, dst, psynth::sound::detail::copy_fn<IC1,IC2>()); 00277 return dst + (last - first); 00278 } 00279 00280 } // namespace std 00281 00282 00283 namespace psynth 00284 { 00285 namespace sound 00286 { 00287 00292 template <typename Range1, typename Range2> PSYNTH_FORCEINLINE 00293 void copy_frames (const Range1& src, const Range2& dst) 00294 { 00295 assert (src.size () == dst.size ()); 00296 std::copy (src.begin(), src.end(), dst.begin()); 00297 } 00298 00311 namespace detail 00312 { 00313 00314 template <typename CC> 00315 class copy_and_convert_frames_fn : 00316 public binary_operation_obj <copy_and_convert_frames_fn<CC> > 00317 { 00318 private: 00319 CC _cc; 00320 00321 public: 00322 typedef typename 00323 binary_operation_obj<copy_and_convert_frames_fn<CC> >::result_type 00324 result_type; 00325 00326 copy_and_convert_frames_fn () {} 00327 00328 copy_and_convert_frames_fn (CC cc_in) 00329 : _cc(cc_in) 00330 {} 00331 00332 // when the two channel spaces are incompatible, a channel 00333 // conversion is performed 00334 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00335 result_type apply_incompatible (const V1& src, const V2& dst) const 00336 { 00337 copy_frames (channel_converted_range<typename V2::value_type>(src, _cc), 00338 dst); 00339 } 00340 00341 // If the two channel spaces are compatible, copy_and_convert is 00342 // just copy 00343 template <typename V1, typename V2> PSYNTH_FORCEINLINE 00344 result_type apply_compatible (const V1& src, const V2& dst) const 00345 { 00346 copy_frames (src,dst); 00347 } 00348 }; 00349 00350 } /* namespace detail */ 00351 00355 template <typename V1, typename V2,typename CC> 00356 PSYNTH_FORCEINLINE 00357 void copy_and_convert_frames (const V1& src, const V2& dst, CC cc) 00358 { 00359 detail::copy_and_convert_frames_fn<CC> ccp (cc); 00360 ccp (src, dst); 00361 } 00362 00363 struct default_channel_converter; 00364 00368 template <typename Range1, typename Range2> 00369 PSYNTH_FORCEINLINE 00370 void copy_and_convert_frames (const Range1& src, const Range2& dst) 00371 { 00372 detail::copy_and_convert_frames_fn<default_channel_converter> ccp; 00373 ccp (src, dst); 00374 } 00375 00376 } /* namespace sound */ 00377 } /* namespace psynth */ 00378 00379 00389 namespace psynth 00390 { 00391 namespace sound 00392 { 00393 00394 namespace detail 00395 { 00396 00398 struct std_fill_type 00399 { 00400 template <typename It, typename P> 00401 void operator () (It first, It last, const P& p_in) 00402 { 00403 std::fill (first, last, p_in); 00404 } 00405 }; 00406 00408 template <typename It, typename P> 00409 PSYNTH_FORCEINLINE 00410 void fill_aux (It first, It last, const P& p, boost::mpl::true_) 00411 { 00412 static_for_each (first, last, p, std_fill_type ()); 00413 } 00414 00416 template <typename It, typename P> 00417 PSYNTH_FORCEINLINE 00418 void fill_aux(It first, It last, const P& p, boost::mpl::false_) 00419 { 00420 std::fill (first, last, p); 00421 } 00422 00423 } /* namespace detail */ 00424 00429 template <typename Range, typename Value> PSYNTH_FORCEINLINE 00430 void fill_frames (const Range& buf_range, const Value& val) 00431 { 00432 detail::fill_aux (buf_range.begin (), buf_range.end (), 00433 val, is_planar<Range>()); 00434 } 00435 00440 template <typename Range, typename Value> PSYNTH_FORCEINLINE 00441 void fill_frames (Range& buf_range, const Value& val) 00442 { 00443 detail::fill_aux (buf_range.begin (), buf_range.end (), 00444 val, is_planar<Range>()); 00445 } 00446 00447 namespace detail 00448 { 00449 00450 template <typename It> PSYNTH_FORCEINLINE 00451 void destruct_range_impl (It first, It last, boost::mpl::true_) 00452 { 00453 typedef typename std::iterator_traits<It>::value_type value_t; 00454 if (boost::has_trivial_destructor<value_t>::value) 00455 return; 00456 while (first != last) { 00457 first->~value_t (); 00458 ++first; 00459 } 00460 } 00461 00462 template <typename It> PSYNTH_FORCEINLINE 00463 void destruct_range_impl (It, It, boost::mpl::false_) {} 00464 00465 template <typename It> PSYNTH_FORCEINLINE 00466 void destruct_range (It first, It last) 00467 { 00468 destruct_range_impl (first, last, typename boost::is_pointer<It>::type ()); 00469 } 00470 00471 struct std_destruct_t 00472 { 00473 template <typename It> void operator ()(It first, It last) const 00474 { 00475 destruct_range (first,last); 00476 } 00477 }; 00478 00480 template <typename It> 00481 PSYNTH_FORCEINLINE 00482 void destruct_aux (It first, It last, boost::mpl::true_) 00483 { 00484 static_for_each (first, last, std_destruct_t ()); 00485 } 00486 00488 template <typename It> 00489 PSYNTH_FORCEINLINE 00490 void destruct_aux (It first, It last, boost::mpl::false_) 00491 { 00492 destruct_range (first,last); 00493 } 00494 00495 } /* namespace detail */ 00496 00501 template <typename Range> PSYNTH_FORCEINLINE 00502 void destruct_frames (const Range& buf_range) 00503 { 00504 detail::destruct_aux (buf_range.begin (), buf_range.end (), 00505 is_planar<Range>()); 00506 } 00507 00508 00517 namespace detail 00518 { 00519 00525 template <typename It, typename P> 00526 PSYNTH_FORCEINLINE 00527 void uninitialized_fill_aux (It first, It last, 00528 const P& p, boost::mpl::true_) 00529 { 00530 int sample=0; 00531 try { 00532 typedef typename std::iterator_traits<It>::value_type frame_t; 00533 while (sample < num_samples<frame_t>::value) { 00534 std::uninitialized_fill (dynamic_at_c (first, sample), 00535 dynamic_at_c (last, sample), 00536 dynamic_at_c (p, sample)); 00537 ++ sample; 00538 } 00539 } 00540 catch (...) 00541 { 00542 for (int c = 0; c < sample; ++c) 00543 destruct_range (dynamic_at_c (first,c), dynamic_at_c (last,c)); 00544 throw; 00545 } 00546 } 00547 00553 template <typename It, typename P> 00554 PSYNTH_FORCEINLINE 00555 void uninitialized_fill_aux (It first, It last, 00556 const P& p, boost::mpl::false_) 00557 { 00558 std::uninitialized_fill (first, last, p); 00559 } 00560 00561 } /* namespace detail */ 00562 00570 template <typename Range, typename Value> 00571 PSYNTH_FORCEINLINE 00572 void uninitialized_fill_frames (const Range& buf_range, const Value& val) 00573 { 00574 detail::uninitialized_fill_aux (buf_range.begin(), 00575 buf_range.end(), 00576 val, is_planar<Range>()); 00577 } 00578 00588 namespace detail 00589 { 00590 00591 template <typename It> PSYNTH_FORCEINLINE 00592 void default_construct_range_impl (It first, It last, boost::mpl::true_) 00593 { 00594 typedef typename std::iterator_traits<It>::value_type value_t; 00595 It first1=first; 00596 try { 00597 while (first!=last) { 00598 new (first) value_t (); 00599 ++first; 00600 } 00601 } catch (...) { 00602 destruct_range (first1, first); 00603 throw; 00604 } 00605 } 00606 00607 template <typename It> PSYNTH_FORCEINLINE 00608 void default_construct_range_impl (It, It, boost::mpl::false_) {} 00609 00610 template <typename It> PSYNTH_FORCEINLINE 00611 void default_construct_range (It first, It last) 00612 { 00613 default_construct_range_impl ( 00614 first, last, typename boost::is_pointer<It>::type()); 00615 } 00616 00618 template <typename It> 00619 PSYNTH_FORCEINLINE 00620 void default_construct_aux (It first, It last, boost::mpl::true_) 00621 { 00622 int sample=0; 00623 try { 00624 typedef typename std::iterator_traits<It>::value_type frame_t; 00625 while (sample < num_samples<frame_t>::value) { 00626 default_construct_range (dynamic_at_c (first, sample), 00627 dynamic_at_c (last, sample)); 00628 ++sample; 00629 } 00630 } catch (...) { 00631 for (int c=0; c<sample; ++c) 00632 destruct_range (dynamic_at_c(first,c), dynamic_at_c(last,c)); 00633 throw; 00634 } 00635 } 00636 00638 template <typename It> 00639 PSYNTH_FORCEINLINE 00640 void default_construct_aux (It first, It last, boost::mpl::false_) 00641 { 00642 default_construct_range (first, last); 00643 } 00644 00645 template <typename Range, bool IsPlanar> 00646 struct has_trivial_frame_constructor : 00647 public boost::has_trivial_constructor <typename Range::value_type> {}; 00648 00649 template <typename Range> 00650 struct has_trivial_frame_constructor<Range, true> : 00651 public boost::has_trivial_constructor < 00652 typename sample_type<Range>::type> {}; 00653 00654 } /* namespace detail */ 00655 00665 template <typename Range> 00666 PSYNTH_FORCEINLINE 00667 void default_construct_frames (const Range& buf_range) 00668 { 00669 if (detail::has_trivial_frame_constructor< 00670 Range, is_planar<Range>::value>::value) 00671 return; 00672 00673 detail::default_construct_aux (buf_range.begin (), 00674 buf_range.end (), 00675 is_planar<Range>()); 00676 } 00677 00678 namespace detail 00679 { 00680 00682 template <typename It1, typename It2> 00683 PSYNTH_FORCEINLINE 00684 void uninitialized_copy_aux (It1 first1, It1 last1, 00685 It2 first2, boost::mpl::true_) 00686 { 00687 int sample = 0; 00688 try { 00689 typedef typename std::iterator_traits<It1>::value_type frame_t; 00690 while (sample < num_samples<frame_t>::value) { 00691 std::uninitialized_copy (dynamic_at_c (first1,sample), 00692 dynamic_at_c (last1,sample), 00693 dynamic_at_c (first2,sample)); 00694 ++ sample; 00695 } 00696 } catch (...) { 00697 It2 last2 = first2; 00698 std::advance (last2, std::distance (first1, last1)); 00699 for (int c = 0; c < sample; ++c) 00700 destruct_range (dynamic_at_c (first2, c), 00701 dynamic_at_c (last2, c)); 00702 throw; 00703 } 00704 } 00705 00707 template <typename It1, typename It2> 00708 PSYNTH_FORCEINLINE 00709 void uninitialized_copy_aux (It1 first1, It1 last1, 00710 It2 first2, boost::mpl::false_) 00711 { 00712 std::uninitialized_copy(first1,last1,first2); 00713 } 00714 00715 } /* namespace detail */ 00716 00724 template <typename Range1, typename Range2> 00725 PSYNTH_FORCEINLINE 00726 void uninitialized_copy_frames (const Range1& range1, const Range2& range2) 00727 { 00728 typedef boost::mpl::bool_<is_planar<Range1>::value && 00729 is_planar<Range2>::value> is_planar; 00730 assert (range1.size () == range2.size ()); 00731 00732 detail::uninitialized_copy_aux (range1.begin (), range1.end (), 00733 range2.begin (), is_planar ()); 00734 } 00735 00749 template <typename V, typename F> 00750 PSYNTH_FORCEINLINE 00751 F for_each_frame (const V& buf, F fun) 00752 { 00753 return std::for_each (buf.begin (), buf.end(), fun); 00754 } 00755 00767 template <typename Range, typename F> 00768 PSYNTH_FORCEINLINE 00769 F for_each_frame_position (const Range& buf, F fun) 00770 { 00771 for (auto loc = buf.begin (); loc != buf.end (); ++loc) 00772 fun (loc); 00773 00774 return fun; 00775 } 00776 00785 template <typename Range, typename F> 00786 PSYNTH_FORCEINLINE 00787 void generate_frames (const Range& v, F fun) 00788 { 00789 std::generate (v.begin (), v.end (), fun); 00790 } 00791 00797 template <typename I1, typename I2> PSYNTH_FORCEINLINE 00798 bool equal_n (I1 i1, std::ptrdiff_t n, I2 i2); 00799 00800 namespace detail 00801 { 00802 00803 template <typename I1, typename I2> 00804 struct equal_n_fn 00805 { 00806 PSYNTH_FORCEINLINE 00807 bool operator () (I1 i1, std::ptrdiff_t n, I2 i2) const 00808 { 00809 return std::equal (i1, i1+n, i2); 00810 } 00811 }; 00812 00818 template<typename T, typename Cs> 00819 struct equal_n_fn<const frame<T,Cs>*, const frame<T,Cs>*> 00820 { 00821 PSYNTH_FORCEINLINE 00822 bool operator () (const frame<T,Cs>* i1, std::ptrdiff_t n, 00823 const frame<T,Cs>* i2) const 00824 { 00825 return memcmp (i1, i2, n * sizeof (frame<T,Cs>)) == 0; 00826 } 00827 }; 00828 00829 template<typename T, typename Cs> 00830 struct equal_n_fn<frame<T,Cs>*, frame<T,Cs>*> : 00831 equal_n_fn<const frame<T,Cs>*, const frame<T,Cs>*> {}; 00832 00840 template<typename IC, typename Cs> 00841 struct equal_n_fn<planar_frame_iterator<IC,Cs>, 00842 planar_frame_iterator<IC,Cs> > 00843 { 00844 PSYNTH_FORCEINLINE 00845 bool operator () (const planar_frame_iterator<IC,Cs> i1, 00846 std::ptrdiff_t n, 00847 const planar_frame_iterator<IC,Cs> i2) const 00848 { 00849 ptrdiff_t num_bytes = n * sizeof ( 00850 typename std::iterator_traits<IC>::value_type); 00851 00852 for (std::ptrdiff_t i=0; i<boost::mpl::size<Cs>::value; ++i) 00853 if (memcmp (dynamic_at_c (i1, i), 00854 dynamic_at_c (i2, i), num_bytes) != 0) 00855 return false; 00856 return true; 00857 } 00858 }; 00859 00860 } /* namespace detail */ 00861 00862 template <typename I1, typename I2> PSYNTH_FORCEINLINE 00863 bool equal_n (I1 i1, std::ptrdiff_t n, I2 i2) 00864 { 00865 return detail::equal_n_fn<I1,I2>() (i1, n, i2); 00866 } 00867 00868 } /* namespace sound */ 00869 } /* namespace psynth */ 00870 00871 namespace std 00872 { 00893 } /* namespace std */ 00894 00895 namespace psynth 00896 { 00897 namespace sound 00898 { 00899 00904 template <typename Range1, typename Range2> PSYNTH_FORCEINLINE 00905 bool equal_frames (const Range1& v1, const Range2& v2) 00906 { 00907 assert (v1.size() == v2.size()); 00908 return std::equal (v1.begin (), v1.end (), v2.begin ()); 00909 // std::equal has overloads with PSYNTH iterators for optimal 00910 // performance 00911 // @todo Not anymore actually. 00912 } 00913 00924 template <typename Range1, typename Range2, typename F> PSYNTH_FORCEINLINE 00925 F transform_frames (const Range1& src, const Range2& dst, F fun) 00926 { 00927 assert (src.size() == dst.size()); 00928 for (std::ptrdiff_t x = 0; x < src.size (); ++x) 00929 dst [x] = fun (src [x]); 00930 return fun; 00931 } 00932 00937 template <typename Range1, typename Range2, typename Range3, typename F> 00938 PSYNTH_FORCEINLINE 00939 F transform_frames (const Range1& src1, const Range2& src2, 00940 const Range3& dst, F fun) 00941 { 00942 assert (src1.size () == dst.size() && 00943 src2.size () == dst.size ()); 00944 for (std::ptrdiff_t x = 0; x < dst.size (); ++x) 00945 dst [x] = fun (src1 [x], src2 [x]); 00946 return fun; 00947 } 00948 00960 template <typename Range1, typename Range2, typename F> PSYNTH_FORCEINLINE 00961 F transform_frame_positions (const Range1& src,const Range2& dst, F fun) 00962 { 00963 assert (src.size () == dst.size ()); 00964 typename Range1::iterator loc = src.begin (); 00965 00966 for (std::ptrdiff_t x = 0; x < src.size (); ++x, ++loc) 00967 dst [x] = fun (loc); 00968 00969 return fun; 00970 } 00971 00976 template <typename Range1, typename Range2, typename Range3, typename F> 00977 PSYNTH_FORCEINLINE 00978 F transform_frame_positions (const Range1& src1, 00979 const Range2& src2, 00980 const Range3& dst, F fun) 00981 { 00982 assert (src1.size () == dst.size ()); 00983 assert (src2.size () == dst.size ()); 00984 typename Range1::iterator loc1 = src1.begin (); 00985 typename Range2::iterator loc2 = src2.begin (); 00986 for (std::ptrdiff_t x = 0; x < src1.width(); 00987 ++x, ++loc1, ++loc2) 00988 dst [x] = fun (loc1, loc2); 00989 00990 return fun; 00991 } 00992 00993 } /* namespace sound */ 00994 } /* namespace psynth */ 00995 00996 //#ifdef _MSC_VER 00997 //#pragma warning(pop) 00998 //#endif 00999 01000 #endif /* PSYNTH_SOUND_ALGORITHM */
1.7.4