libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/buffer_range_factory.hpp
Go to the documentation of this file.
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 */