libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/planar_frame_iterator.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2010 Juan Pedro Bolivar Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 /*
00032  *  Copyright 2005-2007 Adobe Systems Incorporated
00033  * 
00034  *  Use, modification and distribution are subject to the Boost
00035  *  Software License, Version 1.0. (See accompanying file
00036  *  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
00037  */
00038 
00039 #ifndef PSYNTH_SOUND_PLANAR_PTR_H
00040 #define PSYNTH_SOUND_PLANAR_PTR_H
00041 
00042 #include <cassert>
00043 #include <iterator>
00044 #include <boost/iterator/iterator_facade.hpp>
00045 
00046 #include <psynth/base/compat.hpp>
00047 #include <psynth/sound/frame.hpp>
00048 #include <psynth/sound/step_iterator.hpp>
00049 
00050 namespace psynth
00051 {
00052 namespace sound
00053 {
00054 
00055 /*
00056   forward declaration (as this file is included in
00057   planar_frame_reference.hpp)
00058 */
00059 template <typename SampleReference, typename ChannelSpace> 
00060 struct planar_frame_reference;
00061 
00092 template <typename SamplePtr, typename ChannelSpace>
00093 struct planar_frame_iterator
00094     : public boost::iterator_facade<
00095     planar_frame_iterator<SamplePtr,ChannelSpace>,
00096     frame<typename std::iterator_traits<
00097               SamplePtr>::value_type,
00098           layout<ChannelSpace> >,
00099     std::random_access_iterator_tag,
00100     const planar_frame_reference<
00101         typename std::iterator_traits<
00102             SamplePtr>::reference,
00103         ChannelSpace> >
00104 
00105     , public detail::homogeneous_channel_base<
00106     SamplePtr,
00107     layout<ChannelSpace>,
00108     boost::mpl::size<ChannelSpace>::value >
00109 {
00110 private:
00111     typedef
00112     boost::iterator_facade<
00113     planar_frame_iterator<SamplePtr,ChannelSpace>,
00114     frame<typename std::iterator_traits<SamplePtr>::value_type,
00115           layout<ChannelSpace> >,
00116               std::random_access_iterator_tag,
00117               const planar_frame_reference<
00118                   typename std::iterator_traits<SamplePtr>::reference,
00119                   ChannelSpace> >
00120     parent_type;
00121 
00122     typedef detail::homogeneous_channel_base<
00123         SamplePtr, layout<ChannelSpace>,
00124         boost::mpl::size<ChannelSpace>::value>
00125     channel_base_parent_type;
00126 
00127     typedef typename std::iterator_traits<SamplePtr>::value_type sample_type;
00128 
00129 public:
00130     typedef typename parent_type::value_type         value_type;
00131     typedef typename parent_type::reference          reference;
00132     typedef typename parent_type::difference_type    difference_type;
00133 
00134     planar_frame_iterator () : channel_base_parent_type (0) {} 
00135     planar_frame_iterator (bool) {}
00136     // constructor that does not fill with zero (for performance)
00137 
00138     planar_frame_iterator (const SamplePtr& v0,
00139                            const SamplePtr& v1)
00140         : channel_base_parent_type (v0, v1) {}
00141     
00142     planar_frame_iterator (const SamplePtr& v0,
00143                            const SamplePtr& v1,
00144                            const SamplePtr& v2)
00145         : channel_base_parent_type (v0, v1, v2) {}
00146 
00147     planar_frame_iterator (const SamplePtr& v0,
00148                            const SamplePtr& v1,
00149                            const SamplePtr& v2,
00150                            const SamplePtr& v3)
00151         : channel_base_parent_type (v0, v1, v2, v3) {}
00152     
00153     planar_frame_iterator (const SamplePtr& v0,
00154                            const SamplePtr& v1,
00155                            const SamplePtr& v2,
00156                            const SamplePtr& v3,
00157                            const SamplePtr& v4)
00158         : channel_base_parent_type (v0, v1, v2, v3, v4) {}
00159 
00160     template <typename IC1, typename C1> 
00161     planar_frame_iterator (const planar_frame_iterator<IC1,C1>& ptr)
00162         : channel_base_parent_type (ptr) {}
00163 
00164 
00171     template <typename P> 
00172     planar_frame_iterator (P* pix)
00173         : channel_base_parent_type (pix, true)
00174     {
00175         boost::function_requires<FramesCompatibleConcept<P,value_type> >();
00176     }
00177 
00178     struct address_of
00179     {
00180         template <typename T>
00181         T* operator () (T& t) { return &t; }
00182     };
00183     
00184     template <typename P> 
00185     planar_frame_iterator& operator= (P* pix)
00186     {
00187         /*
00188           TODO:
00189           It seems that the following statements are optimized away by
00190           GCC in some strange cases...
00191          */
00192         boost::function_requires<FramesCompatibleConcept<P, value_type> >();    
00193         static_transform (*pix, *this, address_of ());
00194                 
00195         /*
00196           TODO:
00197           Performance compare to this:
00198           this->template semantic_at_c<0>()=&pix->template
00199           semantic_at_c<0>();
00200           this->template semantic_at_c<1>()=&pix->template
00201           semantic_at_c<1>();
00202           this->template semantic_at_c<2>()=&pix->template
00203           semantic_at_c<2>();
00204         */
00205         return *this;
00206     }
00207 
00215     reference operator[] (difference_type d) const
00216     {
00217         return memunit_advanced_ref (*this, d * sizeof (sample_type));
00218     }
00219 
00220     reference operator-> () const
00221     {
00222         return **this;
00223     }
00224 
00225     // PERFORMANCE_CHECK: Remove?
00226     bool operator< (const planar_frame_iterator& ptr) const
00227     {
00228         return sound::at_c<0>(*this) < sound::at_c<0>(ptr);
00229     }
00230     
00231     bool operator!= (const planar_frame_iterator& ptr) const
00232     {
00233         return sound::at_c<0>(*this) != sound::at_c<0>(ptr);
00234     }
00235     
00236 private:
00237     friend class boost::iterator_core_access;
00238 
00239     void increment()
00240     {
00241         static_transform (*this, *this, detail::inc<SamplePtr>());
00242     }
00243     
00244     void decrement ()
00245     {
00246         static_transform (*this, *this, detail::dec<SamplePtr>());
00247     }
00248     
00249     void advance (ptrdiff_t d)
00250     {
00251         static_transform (
00252             *this, *this,
00253             std::bind2nd (detail::plus_asymmetric<SamplePtr, ptrdiff_t>(), d));
00254     }
00255     
00256     reference dereference () const
00257     {
00258         return this->template deref<reference> ();
00259     }
00260 
00261     ptrdiff_t distance_to (const planar_frame_iterator& it) const
00262     {
00263         return sound::at_c<0>(it) - sound::at_c<0>(*this);
00264     }
00265     
00266     bool equal (const planar_frame_iterator& it) const
00267     {
00268         return sound::at_c<0>(*this) == sound::at_c<0>(it);
00269     }
00270 };
00271 
00272 namespace detail
00273 {
00274 
00275 template <typename IC>
00276 struct sample_iterator_is_mutable : public boost::mpl::true_ {};
00277 template <typename T>
00278 struct sample_iterator_is_mutable<const T*> : public boost::mpl::false_ {};
00279 
00280 } /* namespace detail */
00281 
00282 template <typename IC, typename C> 
00283 struct const_iterator_type<planar_frame_iterator<IC,C> >
00284 { 
00285 private:
00286     typedef typename std::iterator_traits<IC>::value_type sample_type;
00287 
00288 public:
00289     typedef
00290     planar_frame_iterator<typename sample_traits<sample_type>::const_pointer,
00291                           C> type; 
00292 };
00293 
00298 template <typename IC, typename C> 
00299 struct iterator_is_mutable<planar_frame_iterator<IC,C> > :
00300         public detail::sample_iterator_is_mutable<IC> {};
00301 
00302 /*
00303  *
00304  *    ChannelBasedConcept
00305  *
00306  */
00307 
00308 template <typename IC, typename C, int K>  
00309 struct kth_element_type<planar_frame_iterator<IC, C>, K>
00310 {
00311     typedef IC type;
00312 };
00313 
00314 template <typename IC, typename C, int K>  
00315 struct kth_element_reference_type<planar_frame_iterator<IC,C>, K> :
00316     public boost::add_reference<IC> {};
00317 
00318 template <typename IC, typename C, int K>  
00319 struct kth_element_const_reference_type<planar_frame_iterator<IC, C>, K> :
00320     public boost::add_reference<typename boost::add_const<IC>::type> {};
00321 
00322 
00323 /*
00324  *
00325  *    HomogeneousFrameBasedConcept
00326  *
00327  */
00328 
00329 template <typename IC, typename C>
00330 struct channel_space_type<planar_frame_iterator<IC,C> >
00331 {
00332     typedef C type;
00333 };
00334 
00335 template <typename IC, typename C>
00336 struct sample_mapping_type<planar_frame_iterator<IC,C> > :
00337     public sample_mapping_type<
00338     typename planar_frame_iterator<IC,C>::value_type> {};
00339 
00340 template <typename IC, typename C>
00341 struct is_planar<planar_frame_iterator<IC,C> > : public boost::mpl::true_ {};
00342 
00343 template <typename IC, typename C>
00344 struct sample_type<planar_frame_iterator<IC,C> >
00345 {
00346     typedef typename std::iterator_traits<IC>::value_type type;
00347 };
00348 
00349 
00350 /*
00351  *
00352  *    MemoryBasedIteratorConcept
00353  *
00354  */
00355 
00356 template <typename IC, typename C>
00357 inline std::ptrdiff_t memunit_step (const planar_frame_iterator<IC,C>&)
00358 {
00359     return sizeof (typename std::iterator_traits<IC>::value_type);
00360 }
00361 
00362 template <typename IC, typename C>
00363 inline std::ptrdiff_t memunit_distance (const planar_frame_iterator<IC,C>& p1,
00364                                         const planar_frame_iterator<IC,C>& p2)
00365 { 
00366     return memunit_distance (sound::at_c<0>(p1), sound::at_c<0>(p2)); 
00367 }
00368 
00369 template <typename IC>
00370 struct memunit_advance_fn
00371 {
00372     memunit_advance_fn (std::ptrdiff_t diff)
00373         : _diff (diff) {}
00374 
00375     IC operator () (const IC& p) const { return memunit_advanced (p, _diff); }
00376 
00377     std::ptrdiff_t _diff;
00378 };
00379 
00380 template <typename IC, typename C>
00381 inline void memunit_advance (planar_frame_iterator<IC, C>& p,
00382                              std::ptrdiff_t diff)
00383 { 
00384     static_transform (p, p, memunit_advance_fn<IC> (diff));
00385 }
00386 
00387 template <typename IC, typename C>
00388 inline planar_frame_iterator<IC,C> memunit_advanced (
00389     const planar_frame_iterator<IC,C>& p, std::ptrdiff_t diff)
00390 {
00391     planar_frame_iterator<IC,C> ret = p;
00392     memunit_advance (ret, diff);
00393     return ret;
00394 }
00395 
00396 template <typename SamplePtr, typename ChannelSpace> inline
00397 planar_frame_reference<typename std::iterator_traits<SamplePtr>::reference,
00398                        ChannelSpace> 
00399 memunit_advanced_ref (const planar_frame_iterator<SamplePtr, ChannelSpace>& ptr,
00400                       std::ptrdiff_t diff)
00401 {
00402     return planar_frame_reference<
00403         typename std::iterator_traits<SamplePtr>::reference,
00404         ChannelSpace> (ptr, diff);
00405 }
00406 
00407 
00408 /*
00409  *
00410  *    HasDynamicStepTypeConcept
00411  *
00412  */
00413 
00414 template <typename IC, typename C>
00415 struct dynamic_step_type<planar_frame_iterator<IC,C> >
00416 {
00417     typedef memory_based_step_iterator<planar_frame_iterator<IC,C> > type;
00418 };
00419 
00420 } /* namespace sound */
00421 } /* namespace psynth */
00422 
00423 #endif /* PSYNTH_SOUND_PLANAR_FRAME_ITERATOR */