libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/util.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_UTILITIES_H
00042 #define PSYNTH_SOUND_UTILITIES_H
00043 
00044 #include <psynth/base/compat.hpp>
00045 
00046 #include <functional>
00047 #include <boost/config/no_tr1/cmath.hpp>
00048 #include <cstddef>
00049 #include <algorithm>
00050 #include <utility>
00051 #include <iterator>
00052 
00053 #include <boost/static_assert.hpp>
00054 #include <boost/mpl/size.hpp>
00055 #include <boost/mpl/distance.hpp>
00056 #include <boost/mpl/begin.hpp>
00057 #include <boost/mpl/find.hpp>
00058 #include <boost/mpl/range_c.hpp>
00059 #include <boost/iterator/iterator_adaptor.hpp>
00060 #include <boost/iterator/iterator_facade.hpp>
00061 
00062 namespace psynth
00063 {
00064 namespace sound
00065 {
00066 
00067 inline std::ptrdiff_t iround (float x)
00068 { return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f)); }
00069 inline std::ptrdiff_t iround (double x)
00070 { return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5)); }
00071 inline std::ptrdiff_t ifloor (float x )
00072 { return static_cast<std::ptrdiff_t> (std::floor(x)); }
00073 inline std::ptrdiff_t ifloor (double x)
00074 { return static_cast<std::ptrdiff_t> (std::floor(x)); }
00075 inline std::ptrdiff_t iceil (float x )
00076 { return static_cast<std::ptrdiff_t> (std::ceil(x)); }
00077 inline std::ptrdiff_t iceil(double x)
00078 { return static_cast<std::ptrdiff_t> (std::ceil(x)); }
00079 
00080 /*
00081  *
00082  *    computing size with alignment
00083  *
00084  */
00085 
00086 template <typename T> 
00087 inline T align (T val, std::size_t alignment)
00088 { 
00089     return val + (alignment - val % alignment) % alignment; 
00090 }
00091 
00096 template <typename ConstT, typename Value, typename Reference,
00097           typename ConstReference, typename ArgType, typename ResultType,
00098           bool IsMutable>
00099 struct deref_base : public std::unary_function<ArgType, ResultType>
00100 {
00101     typedef ConstT         const_type;
00102     typedef Value          value_type;
00103     typedef Reference      reference;
00104     typedef ConstReference const_reference;
00105     BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable);
00106 };
00107 
00115 template <typename D1, typename D2>
00116 class deref_compose : public deref_base<
00117     deref_compose<typename D1::const_type,
00118                   typename D2::const_type>,
00119     typename D1::value_type,
00120     typename D1::reference,
00121     typename D1::const_reference, 
00122     typename D2::argument_type,
00123     typename D1::result_type,
00124     D1::is_mutable && D2::is_mutable>
00125 {
00126     D1 _fn1;
00127     D2 _fn2;
00128 
00129 public:
00130     typedef typename D2::argument_type   argument_type;
00131     typedef typename D1::result_type     result_type;
00132 
00133     deref_compose () {}
00134 
00135     deref_compose (const D1& x, const D2& y)
00136         : _fn1(x)
00137         , _fn2(y) {}
00138 
00139     deref_compose (const deref_compose& dc)
00140         : _fn1(dc._fn1)
00141         , _fn2(dc._fn2) {}
00142 
00143     template <typename _D1, typename _D2>
00144     deref_compose (const deref_compose<_D1,_D2>& dc)
00145         : _fn1(dc._fn1)
00146         , _fn2(dc._fn2) {}
00147 
00148     result_type operator() (argument_type x) const { return _fn1(_fn2 (x)); }
00149     result_type operator() (argument_type x)       { return _fn1(_fn2 (x)); }
00150 };
00151 
00152 /* reinterpret_cast is implementation-defined. Static cast is not. */
00153 template <typename OutPtr, typename In> PSYNTH_FORCEINLINE
00154 OutPtr psynth_reinterpret_cast (In* p)
00155 {
00156     return static_cast<OutPtr> (static_cast<void*> (p));
00157 }
00158 
00159 template <typename OutPtr, typename In> PSYNTH_FORCEINLINE
00160 const OutPtr psynth_reinterpret_cast_c(const In* p)
00161 {
00162     return static_cast<const OutPtr>(static_cast<const void*>(p));
00163 }
00164 
00165 namespace detail
00166 {
00167 
00171 template <class InputIter, class Size, class OutputIter>
00172 std::pair<InputIter, OutputIter> do_copy_n (InputIter first, Size count,
00173                                             OutputIter result,
00174                                             std::input_iterator_tag)
00175 {
00176    for ( ; count > 0; --count) {
00177       *result = *first;
00178       ++first;
00179       ++result;
00180    }
00181    return std::pair<InputIter, OutputIter>(first, result);
00182 }
00183 
00184 template <class RAIter, class Size, class OutputIter>
00185 inline std::pair<RAIter, OutputIter>
00186 do_copy_n (RAIter first, Size count, OutputIter result,
00187            std::random_access_iterator_tag)
00188 {
00189    RAIter last = first + count;
00190    return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
00191 }
00192 
00193 template <class InputIter, class Size, class OutputIter>
00194 inline std::pair<InputIter, OutputIter>
00195 do_copy_n (InputIter first, Size count, OutputIter result)
00196 {
00197    return do_copy_n (
00198        first, count, result,
00199        typename std::iterator_traits<InputIter>::iterator_category());
00200 }
00201 
00202 template <class InputIter, class Size, class OutputIter>
00203 inline std::pair<InputIter, OutputIter>
00204 copy_n (InputIter first, Size count, OutputIter result)
00205 {
00206     return detail::do_copy_n (first, count, result);
00207 }
00208 
00210 template <typename T> 
00211 struct identity : public std::unary_function<T,T> {
00212     const T& operator()(const T& val) const { return val; }
00213 };
00214 
00215 
00218 template <typename T1, typename T2>
00219 struct plus_asymmetric : public std::binary_function<T1,T2,T1> {
00220     T1 operator()(T1 f1, T2 f2) const {
00221         return f1+f2;
00222     }
00223 };
00224 
00226 template <typename T>
00227 struct inc : public std::unary_function<T,T>
00228 {
00229     T operator () (T x) const { return ++x; }
00230 };
00231 
00233 template <typename T>
00234 struct dec : public std::unary_function<T,T>
00235 {
00236     T operator () (T x) const { return --x; }
00237 };
00238 
00244 template <typename Types, typename T>
00245 struct type_to_index 
00246     : public boost::mpl::distance<
00247     typename boost::mpl::begin<Types>::type, 
00248     typename boost::mpl::find<Types,T>::type>::type {};
00249 
00250 } /* namespace detail */
00251 
00252 
00257 template <typename ChannelSpace,
00258           typename SampleMapping = boost::mpl::range_c<
00259               int, 0, boost::mpl::size<ChannelSpace>::value> >
00260 struct layout
00261 {
00262     typedef ChannelSpace   channel_space;
00263     typedef SampleMapping  sample_mapping;
00264 };
00265 
00270 template <typename Value, typename T1, typename T2>
00271 // where value_type<T1>  == value_type<T2> == Value
00272 void swap_proxy (T1& left, T2& right)
00273 {
00274     Value tmp = left;
00275     left  = right;
00276     right = tmp;
00277 }
00278 
00283 inline bool little_endian ()
00284 {
00285     short tester = 0x0001;
00286     return  *(char*)&tester!=0;
00287 }
00288 
00293 inline bool big_endian()
00294 {
00295     return !little_endian();
00296 }
00297 
00298 } /* namespace sound */
00299 } /* namespace psynth */
00300 
00301 #endif /* PSYNTH_SOUND_UTIL */