|
libpsynth 0.2.1
|
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 */
1.7.4