libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/sample_algorithm.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_SAMPLE_ALGORITHM_HPP
00040 #define PSYNTH_SAMPLE_ALGORITHM_HPP
00041 
00042 #include <psynth/base/compat.hpp>
00043 #include <psynth/sound/sample.hpp>
00044 
00045 #include <boost/mpl/less.hpp>
00046 #include <boost/mpl/integral_c.hpp>
00047 #include <boost/mpl/greater.hpp>
00048 #include <boost/type_traits.hpp>
00049 
00050 namespace psynth
00051 {
00052 namespace sound
00053 {
00054 
00055 //#ifdef _MSC_VER
00056 //#pragma warning(push)
00057 //#pragma warning(disable: 4309)
00058 // disable truncation of constant value warning (using -1 to get the
00059 // max value of an integral)
00060 //#endif
00061 
00062 namespace detail
00063 {
00064 
00065 /* some forward declarations */
00066 template <typename SrcSampleV, typename DstSampleV,
00067           bool SrcIsIntegral, bool DstIsIntegral>
00068 struct sample_converter_unsigned_impl;
00069 template <typename SrcSampleV, typename DstSampleV,
00070           bool SrcIsGreater>
00071 struct sample_converter_unsigned_integral;
00072 template <typename SrcSampleV, typename DstSampleV,
00073           bool SrcLessThanDst, bool SrcDivisible>
00074 struct sample_converter_unsigned_integral_impl;
00075 template <typename SrcSampleV, typename DstSampleV,
00076           bool SrcLessThanDst, bool CannotFitInInteger>
00077 struct sample_converter_unsigned_integral_nondivisible;
00078 
00084 template <typename UnsignedIntegralSample>
00085 struct unsigned_integral_max_value :
00086         public boost::mpl::integral_c<UnsignedIntegralSample, -1> {};
00087 
00088 template <>
00089 struct unsigned_integral_max_value<uint8_t> :
00090         public boost::mpl::integral_c<uint32_t, 0xFF> {};
00091 template <>
00092 struct unsigned_integral_max_value<uint16_t> :
00093         public boost::mpl::integral_c<uint32_t, 0xFFFF> {};
00094 template <>
00095 struct unsigned_integral_max_value<uint32_t> :
00096         public boost::mpl::integral_c<uintmax_t, 0xFFFFFFFF> {};
00097 
00098 template <int K>
00099 struct unsigned_integral_max_value<packed_sample_value<K> >
00100     : public boost::mpl::integral_c<
00101     typename packed_sample_value<K>::integer_t, (1 << K) - 1> {};
00102 
00108 template <typename UnsignedIntegralSample>
00109 struct unsigned_integral_num_bits :
00110         public boost::mpl::int_<sizeof(UnsignedIntegralSample)*8> {};
00111 
00112 template <int K>
00113 struct unsigned_integral_num_bits<packed_sample_value<K> >
00114     : public boost::mpl::int_<K> {};
00115 
00116 } /* namespace detail */
00117 
00162 template <typename SrcSampleV, typename DstSampleV>
00163 // Model SampleValueConcept
00164 struct sample_converter_unsigned
00165     : public detail::sample_converter_unsigned_impl<
00166     SrcSampleV, DstSampleV,
00167     boost::is_integral<SrcSampleV>::value,
00168     boost::is_integral<DstSampleV>::value>
00169 {};
00170 
00172 template <typename T> struct sample_converter_unsigned<T,T> :
00173         public detail::identity<T> {};
00174 
00175 
00176 namespace detail
00177 {
00178 
00187 template <typename SrcSampleV, typename DstSampleV,
00188           bool SrcIsIntegral, bool DstIsIntegral> 
00189 struct sample_converter_unsigned_impl :
00190         public std::unary_function <DstSampleV, SrcSampleV>
00191 {
00192     DstSampleV operator () (SrcSampleV src) const
00193     { 
00194         return DstSampleV (
00195             sample_traits<DstSampleV>::min_value() +
00196             (src - sample_traits<SrcSampleV>::min_value()) /
00197             sample_range<SrcSampleV>() * sample_range<DstSampleV> ()); 
00198     }
00199     
00200 private:
00201     template <typename C>
00202     static double sample_range ()
00203     {
00204         return double (sample_traits<C>::max_value ()) -
00205             double (sample_traits<C>::min_value ());
00206     }
00207 };
00208 
00209 // When both the source and the destination are integral samples,
00210 // perform a faster conversion
00211 template <typename SrcSampleV, typename DstSampleV> 
00212 struct sample_converter_unsigned_impl<SrcSampleV, DstSampleV, true, true>
00213     : public sample_converter_unsigned_integral<SrcSampleV, DstSampleV,
00214     boost::mpl::less<unsigned_integral_max_value<SrcSampleV>,
00215               unsigned_integral_max_value<DstSampleV> >::value > {};
00216 
00217 
00222 template <typename SrcSampleV, typename DstSampleV> 
00223 struct sample_converter_unsigned_integral<SrcSampleV, DstSampleV, true>
00224     : public sample_converter_unsigned_integral_impl<
00225     SrcSampleV, DstSampleV, true,
00226     !(unsigned_integral_max_value<DstSampleV>::value %
00227       unsigned_integral_max_value<SrcSampleV>::value)> {};
00228 
00229 template <typename SrcSampleV, typename DstSampleV> 
00230 struct sample_converter_unsigned_integral<SrcSampleV,DstSampleV, false>
00231     : public sample_converter_unsigned_integral_impl<
00232     SrcSampleV, DstSampleV, false,
00233     !(unsigned_integral_max_value<SrcSampleV>::value %
00234       unsigned_integral_max_value<DstSampleV>::value) > {};
00235 
00236 
00241 /*
00242   Both source and destination are unsigned integral samples, the src
00243   max value is less than the dst max value, and the dst max value is
00244   divisible by the src max value
00245 */
00246 template <typename SrcSampleV, typename DstSampleV> 
00247 struct sample_converter_unsigned_integral_impl<SrcSampleV, DstSampleV, true, true>
00248 {
00249     DstSampleV operator () (SrcSampleV src) const
00250     { 
00251         typedef typename unsigned_integral_max_value<DstSampleV>::value_type
00252             integer_t;
00253         static const integer_t mul =
00254             unsigned_integral_max_value<DstSampleV>::value /
00255             unsigned_integral_max_value<SrcSampleV>::value;
00256         return DstSampleV (src * mul);
00257     }
00258 };
00259 
00260 /*
00261   Both source and destination are unsigned integral samples, the dst
00262   max value is less than (or equal to) the src max value, and the src
00263   max value is divisible by the dst max value
00264 */
00265 template <typename SrcSampleV, typename DstSampleV> 
00266 struct sample_converter_unsigned_integral_impl<SrcSampleV,DstSampleV, false, true>
00267 {
00268     DstSampleV operator () (SrcSampleV src) const
00269     { 
00270         typedef typename unsigned_integral_max_value<SrcSampleV>::value_type
00271             integer_t;
00272         static const integer_t div =
00273             unsigned_integral_max_value<SrcSampleV>::value /
00274             unsigned_integral_max_value<DstSampleV>::value;
00275         static const integer_t div2 = div / 2;
00276         return DstSampleV ((src + div2) / div);
00277     }
00278 };
00279 
00280 /* Prevent overflow for the largest integral type */
00281 template <typename DstSampleV> 
00282 struct sample_converter_unsigned_integral_impl<uintmax_t, DstSampleV, false, true>
00283 {
00284     DstSampleV operator () (uintmax_t src) const
00285     { 
00286         static const uintmax_t div =
00287             unsigned_integral_max_value<bits32>::value /
00288             unsigned_integral_max_value<DstSampleV>::value;
00289         static const uintmax_t div2 = div/2;
00290         if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
00291             return unsigned_integral_max_value<DstSampleV>::value;
00292         return DstSampleV ((src + div2) / div);
00293     }
00294 };
00295 
00296 /*
00297   Both source and destination are unsigned integral samples, and the
00298   dst max value is not divisible by the src max value See if you can
00299   represent the expression (src * dst_max) / src_max in integral form
00300 */
00301 template <typename SrcSampleV, typename DstSampleV, bool SrcLessThanDst> 
00302 struct sample_converter_unsigned_integral_impl<SrcSampleV, DstSampleV,
00303                                                SrcLessThanDst, false> 
00304     : public sample_converter_unsigned_integral_nondivisible<
00305     SrcSampleV, DstSampleV,
00306     SrcLessThanDst,
00307     boost::mpl::greater<
00308         boost::mpl::plus<unsigned_integral_num_bits<SrcSampleV>,
00309                   unsigned_integral_num_bits<DstSampleV> >,
00310         unsigned_integral_num_bits<uintmax_t> >::value>
00311 {};
00312 
00313 
00314 /*
00315   Both source and destination are unsigned integral samples, the src
00316   max value is less than the dst max value, and the dst max value is
00317   not divisible by the src max value The expression (src * dst_max) /
00318   src_max fits in an integer
00319 */
00320 template <typename SrcSampleV, typename DstSampleV> 
00321 struct sample_converter_unsigned_integral_nondivisible<
00322     SrcSampleV, DstSampleV, true, false>
00323 {
00324     DstSampleV operator () (SrcSampleV src) const
00325     {
00326         typedef typename detail::min_fast_uint<
00327             unsigned_integral_num_bits<SrcSampleV>::value +
00328             unsigned_integral_num_bits<DstSampleV>::value>::type integer_t;
00329         
00330         return DstSampleV (
00331             integer_t (src * unsigned_integral_max_value<DstSampleV>::value) /
00332             unsigned_integral_max_value<SrcSampleV>::value);
00333     }
00334 };
00335 
00336 /*
00337   Both source and destination are unsigned integral samples, the src
00338   max value is less than the dst max value, and the dst max value is
00339   not divisible by the src max value The expression (src * dst_max) /
00340   src_max cannot fit in an integer (overflows). Use a double
00341 */
00342 template <typename SrcSampleV, typename DstSampleV> 
00343 struct sample_converter_unsigned_integral_nondivisible <
00344     SrcSampleV, DstSampleV, true, true>
00345 {
00346     DstSampleV operator () (SrcSampleV src) const
00347     {
00348         static const double mul =
00349             unsigned_integral_max_value<DstSampleV>::value /
00350             double (unsigned_integral_max_value<SrcSampleV>::value);
00351         return DstSampleV (src * mul);
00352     }
00353 };
00354 
00355 /*
00356   Both source and destination are unsigned integral samples, the dst
00357   max value is less than (or equal to) the src max value, and the src
00358   max value is not divisible by the dst max value
00359 */
00360 template <typename SrcSampleV, typename DstSampleV, bool CannotFit> 
00361 struct sample_converter_unsigned_integral_nondivisible<
00362     SrcSampleV, DstSampleV, false, CannotFit>
00363 {
00364     DstSampleV operator () (SrcSampleV src) const
00365     { 
00366         typedef typename unsigned_integral_max_value<SrcSampleV>::value_type
00367             integer_t;
00368         static const double div =
00369             unsigned_integral_max_value<SrcSampleV>::value /
00370             double (unsigned_integral_max_value<DstSampleV>::value);
00371         static const integer_t div2 = integer_t (div/2);
00372         return DstSampleV ((src + div2) / div);
00373     }
00374 };
00375 
00376 } /* namespace detail */
00377 
00378 
00384 template <typename DstSampleV>
00385 struct sample_converter_unsigned<bits32f,DstSampleV> :
00386     public std::unary_function<bits32f,DstSampleV>
00387 {
00388     DstSampleV   operator () (bits32f x) const
00389     {
00390         return DstSampleV (x * sample_traits<DstSampleV>::max_value () + 0.5f);
00391     }
00392 };
00393 
00394 template <typename SrcSampleV>
00395 struct sample_converter_unsigned<SrcSampleV, bits32f> :
00396     public std::unary_function<SrcSampleV, bits32f>
00397 {
00398     bits32f operator () (SrcSampleV x) const
00399     {
00400         return bits32f (x / float (sample_traits<SrcSampleV>::max_value ()));
00401     }
00402 };
00403 
00404 template <>
00405 struct sample_converter_unsigned<bits32f, bits32f> :
00406     public std::unary_function<bits32f, bits32f>
00407 {
00408     bits32f operator() (bits32f x) const { return x; }
00409 };
00410 
00411 
00413 template <>
00414 struct sample_converter_unsigned<bits32, bits32f> :
00415     public std::unary_function<bits32, bits32f>
00416 {
00417     bits32f operator () (bits32 x) const
00418     { 
00419         // unfortunately without an explicit check it is possible to
00420         // get a round-off error. We must ensure that max_value of
00421         // bits32 matches max_value of bits32f
00422         if (x >= sample_traits<bits32>::max_value ())
00423             return sample_traits<bits32f>::max_value ();
00424         return float (x) / float (sample_traits<bits32>::max_value ());
00425     }
00426 };
00427 
00429 template <> struct sample_converter_unsigned<bits32f, bits32> :
00430     public std::unary_function<bits32f, bits32>
00431 {
00432     bits32 operator () (bits32f x) const
00433     { 
00434         // unfortunately without an explicit check it is possible to
00435         // get a round-off error. We must ensure that max_value of
00436         // bits32 matches max_value of bits32f
00437         if (x >= sample_traits<bits32f>::max_value ())
00438             return sample_traits<bits32>::max_value();
00439         return bits32 (x * sample_traits<bits32>::max_value () + 0.5f); 
00440     }
00441 };
00442 
00445 namespace detail
00446 {
00447 
00448 /*
00449   Converting from signed to unsigned integral sample. 
00450   It is both a unary function, and a metafunction (thus requires the
00451   'type' nested typedef, which equals result_type)
00452 */
00453 template <typename SampleValue> // Model SampleValueConcept
00454 struct sample_convert_to_unsigned : public detail::identity<SampleValue>
00455 {
00456     typedef SampleValue type;
00457 };
00458 
00459 template <>
00460 struct sample_convert_to_unsigned<bits8s> :
00461         public std::unary_function<bits8s, bits8>
00462 { 
00463     typedef bits8 type;
00464     type operator () (bits8s val) const { return val + 128; } 
00465 };
00466 
00467 template <>
00468 struct sample_convert_to_unsigned <bits16s> :
00469     public std::unary_function<bits16s, bits16>
00470 { 
00471     typedef bits16 type;
00472     type operator () (bits16s  val) const { return val + 32768; } 
00473 };
00474 
00475 template <> struct sample_convert_to_unsigned<bits32s> :
00476         public std::unary_function<bits32s, bits32>
00477 {
00478     typedef bits32 type;
00479     type operator () (bits32s x) const
00480     { return static_cast<bits32>(x + (1 << 31)); }
00481 };
00482 
00483 template <> struct sample_convert_to_unsigned<bits32sf> :
00484         public std::unary_function<bits32sf, bits32f>
00485 {
00486     typedef bits32f type;
00487     type operator () (bits32sf x) const
00488     { return static_cast<float>((x + 1.0f) * .5f); }
00489 };
00490 
00491 /*
00492   Converting from unsigned to signed integral sample
00493   It is both a unary function, and a metafunction (thus requires the
00494   'type' nested typedef, which equals result_type)
00495 */
00496 template <typename SampleValue>  // Model SampleValueConcept
00497 struct sample_convert_from_unsigned : public detail::identity<SampleValue>
00498 {
00499     typedef SampleValue type;
00500 };
00501 
00502 template <>
00503 struct sample_convert_from_unsigned<bits8s> :
00504     public std::unary_function<bits8, bits8s>
00505 { 
00506     typedef bits8s type;
00507     type  operator () (bits8  val) const
00508     { return val-128; } 
00509 };
00510 
00511 template <>
00512 struct sample_convert_from_unsigned<bits16s> :
00513     public std::unary_function<bits16,bits16s>
00514 { 
00515     typedef bits16s type;
00516     type operator () (bits16 val) const
00517     { return val-32768; } 
00518 };
00519 
00520 template <>
00521 struct sample_convert_from_unsigned<bits32s> :
00522     public std::unary_function<bits32, bits32s>
00523 {
00524     typedef bits32s type;
00525     type operator () (bits32 x) const
00526     { return static_cast<bits32s>(x-(1<<31)); }
00527 };
00528 
00529 template <>
00530 struct sample_convert_from_unsigned<bits32sf> :
00531     public std::unary_function<bits32f, bits32sf>
00532 {
00533     typedef bits32sf type;
00534     type operator () (bits32f x) const {
00535         return static_cast<float>(x * 2.0f - 1.0f);
00536     }
00537 };
00538 
00539 template <typename SrcSampleV, typename DstSampleV, bool DstIsUnsigned>
00540 struct sample_converter_impl
00541 {  
00542     PSYNTH_FORCEINLINE
00543     DstSampleV operator () (const SrcSampleV& src) const
00544     {
00545        typedef detail::sample_convert_to_unsigned<SrcSampleV> to_unsigned;      
00546        typedef sample_converter_unsigned<typename to_unsigned::result_type,
00547                                          DstSampleV> converter_unsigned;
00548        return converter_unsigned () (to_unsigned () (src));
00549     }
00550 };
00551 
00552 template <typename SrcSampleV, typename DstSampleV>
00553 struct sample_converter_impl<SrcSampleV, DstSampleV, false>
00554 {
00555     PSYNTH_FORCEINLINE
00556     DstSampleV operator () (const SrcSampleV& src) const
00557     {   
00558         typedef detail::sample_convert_to_unsigned<SrcSampleV> to_unsigned;     
00559         typedef detail::sample_convert_from_unsigned<DstSampleV> from_unsigned;
00560         typedef sample_converter_unsigned<typename to_unsigned::result_type,
00561                                           typename from_unsigned::argument_type>
00562             converter_unsigned;
00563         return from_unsigned () (converter_unsigned () (to_unsigned () (src))); 
00564     }
00565 };
00566     
00567 }  /* namespace detail */
00568 
00573 template <typename SrcSampleV, typename DstSampleV> // Model SampleValueConcept
00574 struct sample_converter : public std::unary_function<SrcSampleV, DstSampleV>
00575 {
00576     typedef detail::sample_convert_from_unsigned<DstSampleV> from_unsigned;
00577     typedef detail::sample_converter_impl<
00578         SrcSampleV, DstSampleV,
00579         std::is_same<typename from_unsigned::argument_type,
00580                      DstSampleV>::value> converter_impl;
00581     
00582     PSYNTH_FORCEINLINE
00583     DstSampleV operator () (const SrcSampleV& src) const
00584     {
00585         return converter_impl () (src);
00586     }
00587 };
00588 
00589 
00594 template <typename DstSample, typename SrcSample>
00595 // Model SampleConcept (could be sample references)
00596 inline typename sample_traits<DstSample>::value_type
00597 sample_convert (const SrcSample& src)
00598 { 
00599     return sample_converter<
00600         typename sample_traits<SrcSample>::value_type,
00601         typename sample_traits<DstSample>::value_type>() (src); 
00602 }
00603 
00613 struct default_sample_converter
00614 {
00615     template <typename Ch1, typename Ch2>
00616     void operator () (const Ch1& src, Ch2& dst) const
00617     {
00618         dst = sample_convert<Ch2> (src);
00619     }
00620 };
00621 
00622 namespace detail
00623 {
00624 
00625 /* fast integer division by 255 */
00626 inline uint32_t div255 (uint32_t in)
00627 {
00628     uint32_t tmp = in + 128;
00629     return (tmp + (tmp >> 8)) >> 8;
00630 }
00631 
00632 /* fast integer divison by 32768 */
00633 inline uint32_t div32768 (uint32_t in)
00634 {
00635     return (in + 16384) >> 15;
00636 }
00637 
00638 } /* namespace detail */
00639 
00661 template <typename SampleValue>
00662 struct sample_multiplier_unsigned :
00663     public std::binary_function<SampleValue,SampleValue,SampleValue>
00664 {
00665     SampleValue operator () (SampleValue a, SampleValue b) const
00666     {
00667         return SampleValue (
00668             a / double (sample_traits<SampleValue>::max_value()) * b);
00669     }
00670 };
00671 
00675 template<>
00676 struct sample_multiplier_unsigned<bits8> :
00677     public std::binary_function<bits8, bits8, bits8>
00678 {
00679     bits8 operator () (bits8 a, bits8 b) const
00680     {
00681         return bits8 (detail::div255 (uint32_t (a) * uint32_t (b)));
00682     }
00683 };
00684 
00689 template<>
00690 struct sample_multiplier_unsigned<bits16> :
00691     public std::binary_function<bits16,bits16,bits16>
00692 {
00693     bits16 operator () (bits16 a, bits16 b) const
00694     {
00695         return bits16 ((uint32_t (a) * uint32_t (b)) / 65535);
00696     }
00697 };
00698 
00702 template<>
00703 struct sample_multiplier_unsigned<bits32f> :
00704     public std::binary_function<bits32f, bits32f, bits32f>
00705 {
00706     bits32f operator () (bits32f a, bits32f b) const { return a * b; }
00707 };
00708 
00713 template <typename SampleValue>
00714 struct sample_multiplier :
00715     public std::binary_function<SampleValue, SampleValue, SampleValue>
00716 {
00717     SampleValue operator () (SampleValue a, SampleValue b) const
00718     {
00719         typedef detail::sample_convert_to_unsigned<SampleValue> to_unsigned;
00720         typedef detail::sample_convert_from_unsigned<SampleValue> from_unsigned;
00721         typedef sample_multiplier_unsigned<typename to_unsigned::result_type>
00722             multiplier_unsigned;
00723         return from_unsigned () (multiplier_unsigned () (
00724                                      to_unsigned () (a), to_unsigned () (b))); 
00725     }
00726 };
00727 
00729 template <>
00730 struct sample_multiplier<bits32f> :
00731     public std::binary_function<bits32f, bits32f, bits32f>
00732 {
00733     bits32f operator () (bits32f a, bits32f b) const
00734     { return a * b; }
00735 };
00736 
00741 template <typename Sample> // Models SampleConcept (could be a sample reference)
00742 inline typename sample_traits<Sample>::value_type
00743 sample_multiply (Sample a, Sample b)
00744 { 
00745     return sample_multiplier<
00746         typename sample_traits<Sample>::value_type> () (a, b);
00747 }
00748 
00770 template <typename Sample> // Models SampleConcept (could be a sample reference)
00771 inline typename sample_traits<Sample>::value_type sample_invert (Sample x)
00772 { 
00773     return
00774         sample_traits<Sample>::max_value() - x +
00775         sample_traits<Sample>::min_value(); 
00776 }
00777 
00778 //#ifdef _MSC_VER
00779 //#pragma warning(pop)
00780 //#endif
00781 
00782 }  /* namespace sound */
00783 }  /* namespace psynth */
00784 
00785 #endif