libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/channel_base.hpp
Go to the documentation of this file.
00001 
00013 /*
00014  *  Copyright (C) 2010 Juan Pedro Bolivar Puente
00015  *
00016  *  This file is part of Psychosynth.
00017  *   
00018  *  Psychosynth is free software: you can redistribute it and/or modify
00019  *  it under the terms of the GNU General Public License as published by
00020  *  the Free Software Foundation, either version 3 of the License, or
00021  *  (at your option) any later version.
00022  *
00023  *  Psychosynth is distributed in the hope that it will be useful,
00024  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00025  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026  *  GNU General Public License for more details.
00027  *
00028  *  You should have received a copy of the GNU General Public License
00029  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00030  *
00031  */
00032 
00033 /*
00034  *  Copyright 2005-2007 Adobe Systems Incorporated
00035  * 
00036  *  Use, modification and distribution are subject to the Boost
00037  *  Software License, Version 1.0. (See accompanying file
00038  *  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
00039  */
00040 
00041 #ifndef PSYNTH_SOUND_CHANNEL_BASE_HPP
00042 #define PSYNTH_SOUND_CHANNEL_BASE_HPP
00043 
00044 #include <cassert>
00045 #include <type_traits>
00046 
00047 #include <boost/mpl/range_c.hpp>
00048 #include <boost/mpl/size.hpp>
00049 #include <boost/mpl/vector_c.hpp>
00050 #include <boost/utility/enable_if.hpp>
00051 
00052 #include <psynth/base/compat.hpp>
00053 #include <psynth/sound/util.hpp>
00054 #include <psynth/sound/concept.hpp>
00055 
00056 namespace psynth
00057 {
00058 namespace sound
00059 {
00060 
00061 // Forward-declare
00062 template <typename P>
00063 P* memunit_advanced(const P* p, std::ptrdiff_t diff);
00064 
00065 // Forward-declare semantic_at_c
00066 template <int K, typename ChannelBase>
00067 typename boost::disable_if<
00068     boost::is_const <ChannelBase>,
00069     typename kth_semantic_element_reference_type<ChannelBase,K>::type>::type
00070 semantic_at_c(ChannelBase& p);
00071 
00072 template <int K, typename ChannelBase>
00073 typename kth_semantic_element_const_reference_type<ChannelBase, K>::type
00074 semantic_at_c (const ChannelBase& p);
00075 
00076 // Forward declare element_reference_type
00077 template <typename ChannelBase> struct element_reference_type;
00078 template <typename ChannelBase> struct element_const_reference_type;
00079 
00080 template <typename ChannelBase, int K>
00081 struct kth_element_type;
00082 template <typename ChannelBase, int K>
00083 struct kth_element_type<const ChannelBase,K> :
00084         public kth_element_type<ChannelBase,K> {};
00085 
00086 template <typename ChannelBase, int K>
00087 struct kth_element_reference_type;
00088 template <typename ChannelBase, int K>
00089 struct kth_element_reference_type<const ChannelBase,K> :
00090         public kth_element_reference_type<ChannelBase,K> {};
00091 
00092 template <typename ChannelBase, int K>
00093 struct kth_element_const_reference_type;
00094 template <typename ChannelBase, int K>
00095 struct kth_element_const_reference_type<const ChannelBase,K> :
00096         public kth_element_const_reference_type<ChannelBase,K> {};
00097 
00098 namespace detail
00099 {
00100 
00101 template <typename DstLayout, typename SrcLayout, int K>
00102 struct mapping_transform 
00103     : public boost::mpl::at<typename SrcLayout::sample_mapping, 
00104                      typename detail::type_to_index<
00105                          typename DstLayout::sample_mapping,
00106                          boost::mpl::integral_c<int, K> >::type
00107                            >::type {};
00108 
00125 template <typename Element, typename Layout>
00126 struct homogeneous_channel_base<Element, Layout, 1>
00127 {
00128 private:
00129     Element _v0;
00130 public:
00131     typedef Layout layout;
00132 
00133     typename element_reference_type<homogeneous_channel_base>::type
00134     at (boost::mpl::int_<0>) { return _v0; }
00135 
00136     typename element_const_reference_type<homogeneous_channel_base>::type
00137     at (boost::mpl::int_<0>) const { return _v0; }
00138 
00139     homogeneous_channel_base () {}
00140     homogeneous_channel_base (Element v) : _v0(v) {}
00141  
00142     // grayscale frame values are convertible to sample type
00143     operator Element () const { return _v0; }
00144 
00145     template <typename E2, typename L2>
00146     homogeneous_channel_base (const homogeneous_channel_base<E2,L2,1>& c)
00147         : _v0(at_c<0>(c)) {}
00148 };
00149 
00150 
00158 template <typename Element, typename Layout>
00159 struct homogeneous_channel_base<Element,Layout,2> {
00160 private:
00161     Element _v0, _v1;
00162 public:
00163     typedef Layout layout;
00164 
00165     typename element_reference_type<homogeneous_channel_base>::type
00166     at (boost::mpl::int_<0>)       { return _v0; }
00167 
00168     typename element_const_reference_type<homogeneous_channel_base>::type
00169     at (boost::mpl::int_<0>) const { return _v0; }
00170 
00171     typename element_reference_type<homogeneous_channel_base>::type
00172     at (boost::mpl::int_<1>)       { return _v1; }
00173 
00174     typename element_const_reference_type<homogeneous_channel_base>::type
00175     at (boost::mpl::int_<1>) const { return _v1; }
00176 
00177     homogeneous_channel_base () {}
00178     explicit homogeneous_channel_base (Element v)
00179         : _v0 (v), _v1(v) {}
00180 
00181     homogeneous_channel_base (Element v0, Element v1)
00182         : _v0 (v0), _v1(v1) {}
00183 
00184     template <typename E2, typename L2>
00185     homogeneous_channel_base (const homogeneous_channel_base<E2,L2,2>& c)
00186         : _v0 (sound::at_c<mapping_transform<Layout, L2, 0>::value>(c))
00187         , _v1 (sound::at_c<mapping_transform<Layout, L2, 1>::value>(c)) {}
00188 
00189     // Support for l-value reference proxy copy construction
00190     template <typename E2, typename L2>
00191     homogeneous_channel_base (homogeneous_channel_base<E2,L2,2>& c)
00192         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c))
00193         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
00194 
00195     // Support for planar_frame_iterator construction and dereferencing
00196     template <typename P> homogeneous_channel_base(P* p, bool)
00197         : _v0 (&semantic_at_c<0>(*p))
00198         , _v1 (&semantic_at_c<1>(*p))
00199     {
00200     }
00201 
00202     template <typename Ref> Ref deref () const
00203     { 
00204         return Ref (*semantic_at_c<0>(*this), 
00205                     *semantic_at_c<1>(*this));
00206     }
00207 
00208     // Support for planar_frame_reference offset constructor
00209     template <typename Ptr>
00210     homogeneous_channel_base(const Ptr& ptr, std::ptrdiff_t diff) 
00211         : _v0 (*memunit_advanced (semantic_at_c<0>(ptr), diff)),
00212           _v1 (*memunit_advanced (semantic_at_c<1>(ptr), diff)) {}
00213 
00214     // Support for planar_frame_reference operator[]
00215     Element at_c_dynamic (std::size_t i) const
00216     {
00217         if (i == 0) return _v0;
00218         return _v1;
00219     }
00220 };
00221 
00229 template <typename Element, typename Layout>
00230 struct homogeneous_channel_base<Element,Layout,3>
00231 {
00232 private:
00233     Element _v0, _v1, _v2;
00234 
00235 public:
00236     typedef Layout layout;
00237 
00238     typename element_reference_type<homogeneous_channel_base>::type
00239     at (boost::mpl::int_<0>)       { return _v0; }
00240 
00241     typename element_const_reference_type<homogeneous_channel_base>::type
00242     at (boost::mpl::int_<0>) const { return _v0; }
00243 
00244     typename element_reference_type<homogeneous_channel_base>::type
00245     at (boost::mpl::int_<1>)       { return _v1; }
00246 
00247     typename element_const_reference_type<homogeneous_channel_base>::type
00248     at (boost::mpl::int_<1>) const { return _v1; }
00249 
00250     typename element_reference_type<homogeneous_channel_base>::type
00251     at (boost::mpl::int_<2>)       { return _v2; }
00252 
00253     typename element_const_reference_type<homogeneous_channel_base>::type
00254     at (boost::mpl::int_<2>) const { return _v2; }
00255 
00256     homogeneous_channel_base () {}
00257 
00258     explicit homogeneous_channel_base (Element v)
00259         : _v0(v), _v1(v), _v2(v) {}
00260 
00261     homogeneous_channel_base (Element v0, Element v1, Element v2)
00262         : _v0(v0), _v1(v1), _v2(v2) {}
00263 
00264     template <typename E2, typename L2>
00265     homogeneous_channel_base (const homogeneous_channel_base<E2,L2,3>& c)
00266         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c))
00267         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c))
00268         , _v2(sound::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
00269 
00270     // Support for l-value reference proxy copy construction
00271     template <typename E2, typename L2>
00272     homogeneous_channel_base(      homogeneous_channel_base<E2,L2,3>& c) 
00273         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c))
00274         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c))
00275         , _v2(sound::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
00276 
00277     // Support for planar_frame_iterator construction and dereferencing
00278     template <typename P> homogeneous_channel_base(P* p,bool)
00279         : _v0(&semantic_at_c<0>(*p)) 
00280         , _v1(&semantic_at_c<1>(*p)) 
00281         , _v2(&semantic_at_c<2>(*p)) {}
00282     
00283     template <typename Ref>
00284     Ref deref() const
00285     { 
00286         return Ref(*semantic_at_c<0>(*this), 
00287                    *semantic_at_c<1>(*this), 
00288                    *semantic_at_c<2>(*this));
00289     }
00290 
00291     // Support for planar_frame_reference offset constructor
00292     template <typename Ptr>
00293     homogeneous_channel_base (const Ptr& ptr, std::ptrdiff_t diff) 
00294         : _v0(*memunit_advanced(semantic_at_c<0>(ptr), diff))
00295         , _v1(*memunit_advanced(semantic_at_c<1>(ptr), diff))
00296         , _v2(*memunit_advanced(semantic_at_c<2>(ptr), diff)) {}
00297 
00298     // Support for planar_frame_reference operator[]
00299     Element at_c_dynamic(std::size_t i) const
00300     {
00301         switch (i) {
00302             case 0: return _v0;
00303             case 1: return _v1;
00304         }
00305         return _v2;
00306     }
00307 };
00308 
00316 template <typename Element, typename Layout>
00317 struct homogeneous_channel_base<Element,Layout,4>
00318 {
00319 private:
00320     Element _v0, _v1, _v2, _v3;
00321 
00322 public:
00323     typedef Layout layout;
00324 
00325     typename element_reference_type<homogeneous_channel_base>::type
00326     at (boost::mpl::int_<0>)       { return _v0; }
00327 
00328     typename element_const_reference_type<homogeneous_channel_base>::type
00329     at (boost::mpl::int_<0>) const { return _v0; }
00330 
00331     typename element_reference_type<homogeneous_channel_base>::type
00332     at (boost::mpl::int_<1>)       { return _v1; }
00333 
00334     typename element_const_reference_type<homogeneous_channel_base>::type
00335     at (boost::mpl::int_<1>) const { return _v1; }
00336 
00337     typename element_reference_type<homogeneous_channel_base>::type
00338     at (boost::mpl::int_<2>)       { return _v2; }
00339 
00340     typename element_const_reference_type<homogeneous_channel_base>::type
00341     at (boost::mpl::int_<2>) const { return _v2; }
00342 
00343     typename element_reference_type<homogeneous_channel_base>::type
00344     at (boost::mpl::int_<3>)       { return _v3; }
00345 
00346     typename element_const_reference_type<homogeneous_channel_base>::type
00347     at (boost::mpl::int_<3>) const { return _v3; }
00348 
00349     homogeneous_channel_base () {}
00350 
00351     explicit homogeneous_channel_base (Element v)
00352         : _v0(v), _v1(v), _v2(v), _v3(v) {}
00353     
00354     homogeneous_channel_base (Element v0, Element v1, Element v2, Element v3)
00355         : _v0(v0), _v1(v1), _v2(v2), _v3 (v3) {}
00356 
00357     template <typename E2, typename L2>
00358     homogeneous_channel_base (const homogeneous_channel_base<E2,L2,4>& c)
00359         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c)) 
00360         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c)) 
00361         , _v2(sound::at_c<mapping_transform<Layout,L2,2>::value>(c))
00362         , _v3(sound::at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
00363 
00364     // Support for l-value reference proxy copy construction
00365     template <typename E2, typename L2>
00366     homogeneous_channel_base (homogeneous_channel_base<E2,L2,4>& c)
00367         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c)) 
00368         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c)) 
00369         , _v2(sound::at_c<mapping_transform<Layout,L2,2>::value>(c))
00370         , _v3(sound::at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
00371 
00372     // Support for planar_frame_iterator construction and dereferencing
00373     template <typename P> homogeneous_channel_base(P* p,bool)
00374         : _v0(&semantic_at_c<0>(*p)) 
00375         , _v1(&semantic_at_c<1>(*p)) 
00376         , _v2(&semantic_at_c<2>(*p)) 
00377         , _v3(&semantic_at_c<3>(*p)) {}
00378 
00379     template <typename Ref>
00380     Ref deref () const
00381     { 
00382         return Ref (*semantic_at_c<0>(*this), 
00383                     *semantic_at_c<1>(*this), 
00384                     *semantic_at_c<2>(*this), 
00385                     *semantic_at_c<3>(*this));
00386     }
00387 
00388     // Support for planar_frame_reference offset constructor
00389     template <typename Ptr>
00390     homogeneous_channel_base (const Ptr& ptr, std::ptrdiff_t diff) 
00391         : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff))
00392         , _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff))
00393         , _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff))
00394         , _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)) {}
00395 
00396     // Support for planar_frame_reference operator[]
00397     Element at_c_dynamic(std::size_t i) const
00398     {
00399         switch (i) {
00400             case 0: return _v0;
00401             case 1: return _v1;
00402             case 2: return _v2;
00403         }
00404         return _v3;
00405     }
00406 };
00407 
00415 template <typename Element, typename Layout>
00416 struct homogeneous_channel_base<Element,Layout,5>
00417 {
00418 private:
00419     Element _v0, _v1, _v2, _v3, _v4;
00420 
00421 public:
00422     typedef Layout layout;
00423 
00424     typename element_reference_type<homogeneous_channel_base>::type
00425     at(boost::mpl::int_<0>)       { return _v0; }
00426 
00427     typename element_const_reference_type<homogeneous_channel_base>::type
00428     at(boost::mpl::int_<0>) const { return _v0; }
00429 
00430     typename element_reference_type<homogeneous_channel_base>::type
00431     at(boost::mpl::int_<1>)       { return _v1; }
00432 
00433     typename element_const_reference_type<homogeneous_channel_base>::type
00434     at(boost::mpl::int_<1>) const { return _v1; }
00435 
00436     typename element_reference_type<homogeneous_channel_base>::type
00437     at(boost::mpl::int_<2>)       { return _v2; }
00438 
00439     typename element_const_reference_type<homogeneous_channel_base>::type
00440     at(boost::mpl::int_<2>) const { return _v2; }
00441 
00442     typename element_reference_type<homogeneous_channel_base>::type
00443     at(boost::mpl::int_<3>)       { return _v3; }
00444 
00445     typename element_const_reference_type<homogeneous_channel_base>::type
00446     at(boost::mpl::int_<3>) const { return _v3; }
00447 
00448     typename element_reference_type<homogeneous_channel_base>::type
00449     at(boost::mpl::int_<4>)       { return _v4; }
00450 
00451     typename element_const_reference_type<homogeneous_channel_base>::type
00452     at(boost::mpl::int_<4>) const { return _v4; }
00453 
00454     homogeneous_channel_base() {}
00455 
00456     explicit homogeneous_channel_base(Element v)
00457         : _v0(v), _v1(v), _v2(v), _v3(v), _v4(v) {}
00458 
00459     homogeneous_channel_base (Element v0, Element v1, Element v2, Element v3,
00460                               Element v4)
00461         : _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) {}
00462 
00463     template <typename E2, typename L2>
00464     homogeneous_channel_base (const homogeneous_channel_base<E2,L2,5>& c)
00465         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c)) 
00466         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c))
00467         , _v2(sound::at_c<mapping_transform<Layout,L2,2>::value>(c))
00468         , _v3(sound::at_c<mapping_transform<Layout,L2,3>::value>(c))
00469         , _v4(sound::at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
00470 
00471     // Support for l-value reference proxy copy construction
00472     template <typename E2, typename L2>
00473     homogeneous_channel_base (homogeneous_channel_base<E2,L2,5>& c)
00474         : _v0(sound::at_c<mapping_transform<Layout,L2,0>::value>(c)) 
00475         , _v1(sound::at_c<mapping_transform<Layout,L2,1>::value>(c))
00476         , _v2(sound::at_c<mapping_transform<Layout,L2,2>::value>(c))
00477         , _v3(sound::at_c<mapping_transform<Layout,L2,3>::value>(c))
00478         , _v4(sound::at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
00479         
00480     // Support for planar_frame_iterator construction and dereferencing
00481     template <typename P> homogeneous_channel_base(P* p,bool)
00482         : _v0(&semantic_at_c<0>(*p)) 
00483         , _v1(&semantic_at_c<1>(*p)) 
00484         , _v2(&semantic_at_c<2>(*p)) 
00485         , _v3(&semantic_at_c<3>(*p))
00486         , _v4(&semantic_at_c<4>(*p)) {}
00487 
00488     template <typename Ref> Ref deref() const
00489     { 
00490         return Ref (*semantic_at_c<0>(*this), 
00491                     *semantic_at_c<1>(*this), 
00492                     *semantic_at_c<2>(*this), 
00493                     *semantic_at_c<3>(*this),
00494                     *semantic_at_c<4>(*this));
00495     }
00496 
00497     // Support for planar_frame_reference offset constructor
00498     template <typename Ptr>
00499     homogeneous_channel_base (const Ptr& ptr, std::ptrdiff_t diff) 
00500         : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff))
00501         , _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff))
00502         , _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff))
00503         , _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff))
00504         , _v4(*memunit_advanced(semantic_at_c<4>(ptr),diff)) {}
00505 
00506     // Support for planar_frame_reference operator[]
00507     Element at_c_dynamic(std::size_t i) const
00508     {
00509         switch (i) {
00510             case 0: return _v0;
00511             case 1: return _v1;
00512             case 2: return _v2;
00513             case 3: return _v3;
00514         }
00515         return _v4;
00516     }
00517 };
00518 
00519 /*
00520   The following way of casting adjacent samples (the contents of
00521   channel_base) into an array appears to be unsafe -- there is no
00522   guarantee that the compiler won't add any padding between adjacent
00523   samples.  Note, however, that GIL _must_ be compiled with compiler
00524   settings ensuring there is no padding in the channel base structs.
00525   This is because the channel base structs must model the interleaved
00526   organization in memory. In other words, the client may have existing
00527   RGB image in the form "RGBRGBRGB..." and we must be able to
00528   represent it with an array of RGB channel bases (i.e. RGB frames)
00529   with no padding. We have tested with char/int/float/double samples
00530   on gcc and VC and have so far discovered no problem.  We have even
00531   tried using strange samples consisting of short + char (3
00532   bytes). With the default 4-byte alignment on VC, the size of this
00533   sample is padded to 4 bytes, so an RGB frame of it will be 4x3=12
00534   bytes. The code below will still work properly.  However, the client
00535   must nevertheless ensure that proper compiler settings are used for
00536   their compiler and their sample types.
00537 */
00538 
00539 template <typename Element, typename Layout, int K>
00540 typename element_reference_type<
00541     homogeneous_channel_base<Element,Layout,K> >::type
00542 dynamic_at_c (homogeneous_channel_base<Element,Layout,K>& cb, std::size_t i)
00543 {
00544     assert (i < K);
00545     return (psynth_reinterpret_cast<Element*> (&cb)) [i];
00546 }
00547 
00548 template <typename Element, typename Layout, int K>
00549 typename element_const_reference_type<
00550     homogeneous_channel_base<Element,Layout,K> >::type 
00551 dynamic_at_c (const homogeneous_channel_base<Element,Layout,K>& cb,
00552               std::size_t i)
00553 {
00554     assert (i < K);
00555     return (psynth_reinterpret_cast_c<const Element*>(&cb))[i];
00556 }
00557 
00558 template <typename Element, typename Layout, int K>
00559 typename element_reference_type<
00560     homogeneous_channel_base<Element&,Layout,K> >::type       
00561 dynamic_at_c(const homogeneous_channel_base<Element&,Layout,K>& cb,
00562              std::size_t i)
00563 {
00564     assert (i < K);
00565     return cb.at_c_dynamic (i);
00566 }
00567 
00568 template <typename Element, typename Layout, int K>
00569 typename element_const_reference_type<
00570     homogeneous_channel_base<const Element&,Layout,K> >::type 
00571 dynamic_at_c (const homogeneous_channel_base<const Element&,Layout,K>& cb,
00572               std::size_t i)
00573 {
00574     assert (i < K);
00575     return cb.at_c_dynamic (i);
00576 }
00577 
00578 } /* namespace detail */
00579 
00580 template <typename Element, typename Layout, int K1, int K>  
00581 struct kth_element_type<detail::homogeneous_channel_base<Element,Layout,K1>, K>
00582 {
00583     typedef Element type;
00584 };
00585 
00586 template <typename Element, typename Layout, int K1, int K> 
00587 struct kth_element_reference_type<
00588     detail::homogeneous_channel_base<Element,Layout,K1>, K> :
00589     public boost::add_reference<Element> {};
00590 
00591 template <typename Element, typename Layout, int K1, int K> 
00592 struct kth_element_const_reference_type<
00593     detail::homogeneous_channel_base<Element,Layout,K1>, K> :
00594     public boost::add_reference<typename boost::add_const<Element>::type> {};
00595 
00600 template <int K, typename E, typename L, int N> inline
00601 typename boost::add_reference<E>::type
00602 at_c (detail::homogeneous_channel_base<E,L,N>& p)
00603 {
00604     return p.at (boost::mpl::int_<K>());
00605 }
00606 
00612 template <int K, typename E, typename L, int N> inline
00613 typename boost::add_reference<typename boost::add_const<E>::type>::type
00614 at_c (const detail::homogeneous_channel_base<E,L,N>& p)
00615 {
00616     return p.at (boost::mpl::int_<K>());
00617 }
00618 
00619 namespace detail
00620 {
00621     struct swap_fn
00622     {
00623         template <typename T>
00624         void operator() (T& x, T& y) const
00625         {
00626             using std::swap;
00627             swap (x,y);
00628         }
00629     };
00630 }
00631 template <typename E, typename L, int N> inline
00632 void swap (detail::homogeneous_channel_base<E,L,N>& x,
00633            detail::homogeneous_channel_base<E,L,N>& y)
00634 { 
00635     static_for_each (x, y, detail::swap_fn ());
00636 }
00637 
00638 } /* namespace sound */
00639 } /* namespace psynth */
00640 
00641 #endif /* PSYNTH_SOUND_CHANNEL_BASE */