libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/sample.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_HPP_
00040 #define PSYNTH_SAMPLE_HPP_
00041 
00042 #include <limits>
00043 #include <cassert>
00044 #include <boost/cstdint.hpp>
00045 
00046 #include <psynth/base/compat.hpp>
00047 #include <psynth/sound/util.hpp>
00048 
00049 namespace psynth
00050 {
00051 namespace sound
00052 {
00053 
00069 namespace detail
00070 {
00071 template <typename T, bool is_class> struct sample_traits_impl;
00072 
00073 /* sample traits for custom class */
00074 template <typename T> 
00075 struct sample_traits_impl<T, true>
00076 {
00077     typedef typename T::value_type      value_type;
00078     typedef typename T::reference       reference;
00079     typedef typename T::pointer         pointer;
00080     typedef typename T::const_reference const_reference;
00081     typedef typename T::const_pointer   const_pointer;
00082     BOOST_STATIC_CONSTANT(bool, is_mutable = T::is_mutable);
00083     static value_type min_value () { return T::min_value(); }
00084     static value_type max_value () { return T::max_value(); }
00085     static value_type zero_value () { return T::zero_value(); }
00086 };
00087 
00088 /* sample traits implementation for built-in integral or floating
00089    point sample type */
00090 template <typename T> 
00091 struct sample_traits_impl<T, false>
00092 {
00093     typedef T           value_type;
00094     typedef T&          reference;
00095     typedef T*          pointer;
00096     typedef const T&    const_reference;
00097     typedef T const*    const_pointer;
00098     BOOST_STATIC_CONSTANT(bool, is_mutable=true);
00099     static value_type min_value () { return (std::numeric_limits<T>::min) (); }
00100     static value_type max_value () { return (std::numeric_limits<T>::max) (); }
00101     static value_type zero_value () { return T(0); }
00102 };
00103 
00104 /* sample traits implementation for constant built-in scalar or
00105    floating point type */
00106 template <typename T> 
00107 struct sample_traits_impl<const T, false> :
00108         public sample_traits_impl<T, false>
00109 {
00110         typedef const T&    reference;
00111         typedef const T*    pointer;
00112         BOOST_STATIC_CONSTANT(bool, is_mutable = false);
00113 };
00114 
00115 } /* namespace detail */
00116 
00137 template <typename T>
00138 struct sample_traits :
00139         public detail::sample_traits_impl<T, boost::is_class<T>::value> {};
00140 
00141 // Sample traits for C++ reference type - remove the reference
00142 template <typename T>
00143 struct sample_traits<T&> : public sample_traits<T> {};
00144 
00145 // Sample traits for constant C++ reference type
00146 template <typename T> struct sample_traits<const T&> : public sample_traits<T>
00147 {
00148     typedef typename sample_traits<T>::const_reference reference;
00149     typedef typename sample_traits<T>::const_pointer   pointer;
00150     BOOST_STATIC_CONSTANT(bool, is_mutable = false);
00151 };
00152 
00153 
00154 /*
00155  *
00156  *    scoped_sample_value
00157  *
00158  */
00159 
00186 template <typename BaseSampleValue,
00187           // base sample (models SampleValueConcept)
00188           typename MinVal,
00189           typename MaxVal,
00190           typename ZeroVal
00191           // classes with a static apply() function returning the
00192           // minimum/maximum sample values
00193           >
00194 struct scoped_sample_value
00195 {
00196     typedef scoped_sample_value    value_type;
00197     typedef value_type&            reference;
00198     typedef value_type*            pointer;
00199     typedef const value_type&      const_reference;
00200     typedef const value_type*      const_pointer;
00201     
00202     BOOST_STATIC_CONSTANT(bool, is_mutable =
00203                           sample_traits<BaseSampleValue>::is_mutable);
00204 
00205     typedef BaseSampleValue base_sample;
00206 
00207     static value_type min_value () { return MinVal::apply (); }
00208     static value_type max_value () { return MaxVal::apply (); }
00209     static value_type zero_value () { return ZeroVal::apply (); }
00210 
00211     scoped_sample_value () {}
00212     scoped_sample_value (const scoped_sample_value& c) : _value(c._value) {}
00213     scoped_sample_value (BaseSampleValue val) : _value(val) {}
00214 
00215     scoped_sample_value& operator++ () { ++_value; return *this; }
00216     scoped_sample_value& operator-- () { --_value; return *this; }
00217 
00218     scoped_sample_value operator ++ (int)
00219     {
00220         scoped_sample_value tmp = *this;
00221         this->operator++ ();
00222         return tmp;
00223     }
00224     
00225     scoped_sample_value operator--(int)
00226     {
00227         scoped_sample_value tmp = *this;
00228         this->operator-- ();
00229         return tmp;
00230     }
00231 
00232     template <typename Scalar2>
00233     scoped_sample_value& operator+=(Scalar2 v) { _value+=v; return *this; }
00234     template <typename Scalar2>
00235     scoped_sample_value& operator-=(Scalar2 v) { _value-=v; return *this; }
00236     template <typename Scalar2>
00237     scoped_sample_value& operator*=(Scalar2 v) { _value*=v; return *this; }
00238     template <typename Scalar2>
00239     scoped_sample_value& operator/=(Scalar2 v) { _value/=v; return *this; }
00240 
00241     scoped_sample_value& operator= (BaseSampleValue v)
00242     { _value=v; return *this; }
00243 
00244     operator BaseSampleValue () const { return _value; }
00245 
00246 private:
00247     BaseSampleValue _value;
00248 };
00249 
00250 struct float_zero { static float apply () { return 0.0f; } };
00251 struct float_one  { static float apply () { return 1.0f; } };
00252 struct float_minus_one  { static float apply () { return -1.0f; } };
00253 struct float_half  { static float apply () { return 0.5f; } };
00254 
00255 
00256 
00257 /*
00258  *
00259  *  Support for sub-byte samples. These are integral samples whose
00260  *  value is contained in a range of bits inside an integral type
00261  *
00262  */
00263 
00264 /*
00265   It is necessary for packed samples to have their own value
00266   type. They cannot simply use an integral large enough to store the
00267   data. Here is why:
00268 
00269   - Any operation that requires returning the result by value will
00270     otherwise return the built-in integral type, which will have
00271     incorrect range That means that after getting the value of the
00272     sample we cannot properly do sample_convert, sample_invert, etc.
00273 
00274   - Two samples are declared compatible if they have the same value
00275     type. That means that a packed sample is incorrectly declared
00276     compatible with an integral type
00277 */
00278 namespace detail
00279 {
00280 /* returns the smallest fast unsigned integral type that has at
00281    least NumBits bits */
00282 template <int NumBits>
00283 struct min_fast_uint :
00284         public boost::mpl::if_c<
00285     (NumBits<=8), 
00286         uint_least8_t, 
00287         typename boost::mpl::if_c<
00288         (NumBits<=16), 
00289             uint_least16_t, 
00290             typename boost::mpl::if_c<
00291             (NumBits<=32), 
00292                 uint_least32_t, 
00293                 uintmax_t
00294                 >::type
00295             >::type
00296             > {};
00297 }
00298 
00321 template <int NumBits>
00322 class packed_sample_value
00323 {
00324     static const std::size_t num_values = 1 << NumBits;
00325 
00326 public:
00327     typedef typename detail::min_fast_uint<NumBits>::type integer_t;
00328 
00329     typedef packed_sample_value   value_type;
00330     typedef value_type&           reference;
00331     typedef const value_type&     const_reference;
00332     typedef value_type*           pointer;
00333     typedef const value_type*     const_pointer;
00334 
00335     static value_type min_value () { return value_type (0); }
00336     static value_type zero_value () { return min_value () / 2 + max_value () / 2; }
00337     static value_type max_value () { return value_type (num_values - 1); }
00338     BOOST_STATIC_CONSTANT(bool, is_mutable = true);
00339 
00340     packed_sample_value () {}
00341     packed_sample_value (integer_t v) : _value(v % num_values) {}
00342     packed_sample_value (const packed_sample_value& v) : _value (v._value) {}
00343     template <typename Scalar>
00344     packed_sample_value (Scalar v) : _value (integer_t (v) % num_values) {}
00345     // suppress GCC implicit conversion warnings in sample regression file 
00346 
00347     operator integer_t () const { return _value; }
00348 
00349 private:
00350     integer_t _value;
00351 };
00352 
00353 namespace detail
00354 {
00355 
00356 template <std::size_t K>
00357 struct static_copy_bytes
00358 {
00359     void operator () (const unsigned char* from, unsigned char* to) const
00360     {
00361         *to = *from;
00362         static_copy_bytes<K-1> () (++from, ++to);
00363     }
00364 };
00365 
00366 template <>
00367 struct static_copy_bytes<0>
00368 {
00369     void operator () (const unsigned char* , unsigned char*) const {}
00370 };
00371 
00372 template <typename Derived, typename BitField, int NumBits, bool Mutable>
00373 class packed_sample_reference_base
00374 {
00375 protected:
00376     typedef typename boost::mpl::if_c<Mutable, void*, const void*>::type data_ptr_t;
00377 
00378 public:
00379     typedef packed_sample_value<NumBits>   value_type;
00380     typedef const Derived                  reference;
00381     typedef value_type*                    pointer;
00382     typedef const value_type*              const_pointer;
00383     BOOST_STATIC_CONSTANT(int,  num_bits = NumBits);
00384     BOOST_STATIC_CONSTANT(bool, is_mutable = Mutable);
00385 
00386     static value_type min_value ()
00387     {
00388         return sample_traits<value_type>::min_value();
00389     }
00390     
00391     static value_type max_value ()
00392     {
00393         return sample_traits<value_type>::max_value();
00394     }
00395 
00396     static value_type zero_value ()
00397     {
00398         return sample_traits<value_type>::zero_value();
00399     }
00400 
00401     typedef BitField                       bitfield_t;
00402     typedef typename value_type::integer_t integer_t;
00403 
00404     packed_sample_reference_base (data_ptr_t data_ptr)
00405         : _data_ptr(data_ptr) {}
00406     packed_sample_reference_base (const packed_sample_reference_base& ref)
00407         : _data_ptr(ref._data_ptr) {}
00408 
00409     const Derived& operator= (integer_t v) const { set (v); return derived (); }
00410     const Derived& operator++ () const { set(get()+1); return derived (); }
00411     const Derived& operator-- () const { set(get()-1); return derived (); }
00412 
00413     Derived operator++(int) const
00414     {
00415         Derived tmp=derived();
00416         this->operator++();
00417         return tmp;
00418     }
00419     
00420     Derived operator--(int) const
00421     {
00422         Derived tmp=derived();
00423         this->operator--();
00424         return tmp;
00425     }
00426 
00427     template <typename Scalar2>
00428     const Derived& operator+= (Scalar2 v) const { set(get()+v); return derived(); }
00429     template <typename Scalar2>
00430     const Derived& operator-= (Scalar2 v) const { set(get()-v); return derived(); }
00431     template <typename Scalar2>
00432     const Derived& operator*= (Scalar2 v) const { set(get()*v); return derived(); }
00433     template <typename Scalar2>
00434     const Derived& operator/= (Scalar2 v) const { set(get()/v); return derived(); }
00435 
00436     operator integer_t () const { return get (); }
00437     data_ptr_t operator & () const {return _data_ptr;}
00438 
00439 protected:
00440     data_ptr_t _data_ptr;
00441     // void* pointer to the first byte of the bit range
00442     static const integer_t max_val = (1 << NumBits) - 1;
00443 
00444 #ifdef PSYNTH_NONWORD_POINTER_ALIGNMENT_SUPPORTED
00445     const bitfield_t& get_data () const
00446     {
00447         return *static_cast<const bitfield_t*> (_data_ptr);
00448     }
00449     
00450     void set_data(const bitfield_t& val) const
00451     {
00452         *static_cast<bitfield_t*> (_data_ptr) = val;
00453     }
00454 #else
00455     bitfield_t get_data() const
00456     {
00457         bitfield_t ret;
00458         static_copy_bytes<sizeof(bitfield_t)> ()(
00459             psynth_reinterpret_cast_c<const unsigned char*>(_data_ptr),
00460             psynth_reinterpret_cast<unsigned char*>(&ret));
00461         return ret;
00462     }
00463     
00464     void set_data(const bitfield_t& val) const
00465     {
00466         static_copy_bytes<sizeof(bitfield_t)> ()(
00467             psynth_reinterpret_cast_c<const unsigned char*>(&val),
00468             psynth_reinterpret_cast<unsigned char*>(_data_ptr));
00469     }
00470 #endif
00471 
00472 private:
00473     void set(integer_t value) const
00474     {
00475         // TODO: can this be done faster??
00476         const integer_t num_values = max_val+1;
00477         this->derived ().set_unsafe (
00478             ((value % num_values) + num_values) % num_values); 
00479     }
00480     
00481     integer_t get () const { return derived ().get (); }
00482 
00483     const Derived& derived() const
00484     {
00485         return static_cast<const Derived&>(*this);
00486     }
00487 };
00488 
00489 } /* namespace detail */
00490 
00510 template <typename BitField,
00511           // A type that holds the bits of the pixel from which the
00512           // sample is referenced. Typically an integral type, like
00513           // boost::uint16_t
00514           int FirstBit, int NumBits,
00515           // Defines the sequence of bits in the data value that
00516           // contain the sample
00517           bool Mutable
00518           // true if the reference is mutable
00519           >
00520 class packed_sample_reference;
00521 
00522 template <typename BitField,
00523           // A type that holds the bits of the pixel from which the
00524           // sample is referenced. Typically an integral type, like
00525           // boost::uint16_t
00526           int NumBits,
00527           // Defines the sequence of bits in the data value that
00528           // contain the sample
00529           bool Mutable
00530           // true if the reference is mutable
00531           >
00532 class packed_dynamic_sample_reference;
00533 
00539 template <typename BitField, int FirstBit, int NumBits>
00540 class packed_sample_reference<BitField, FirstBit, NumBits, false> :
00541     public detail::packed_sample_reference_base<
00542     packed_sample_reference<BitField, FirstBit, NumBits, false>,
00543     BitField, NumBits, false>
00544 {
00545     typedef detail::packed_sample_reference_base<
00546         packed_sample_reference<BitField, FirstBit, NumBits, false>,
00547         BitField,NumBits,false> parent_t;
00548     friend class packed_sample_reference<BitField, FirstBit, NumBits, true>;
00549 
00550     static const BitField sample_mask =
00551         static_cast<BitField>(parent_t::max_val) << FirstBit;
00552 
00553     void operator= (const packed_sample_reference&);
00554 
00555 public:
00556     typedef const packed_sample_reference<BitField,FirstBit,NumBits,false>
00557     const_reference;
00558     typedef const packed_sample_reference<BitField,FirstBit,NumBits,true>
00559     mutable_reference;
00560     typedef typename parent_t::integer_t integer_t;
00561 
00562     explicit packed_sample_reference (const void* data_ptr)
00563         : parent_t (data_ptr) {}
00564     packed_sample_reference(const packed_sample_reference& ref)
00565         : parent_t (ref._data_ptr) {}
00566     packed_sample_reference(const mutable_reference& ref)
00567         : parent_t (ref._data_ptr) {}
00568 
00569     unsigned first_bit () const { return FirstBit; }
00570 
00571     integer_t get () const
00572     {
00573         return integer_t ((this->get_data () & sample_mask) >> FirstBit);
00574     }
00575 };
00576 
00582 template <typename BitField, int FirstBit, int NumBits>
00583 class packed_sample_reference<BitField, FirstBit, NumBits, true> 
00584    : public detail::packed_sample_reference_base<
00585     packed_sample_reference<BitField, FirstBit, NumBits, true>,
00586     BitField, NumBits, true>
00587 {
00588     typedef detail::packed_sample_reference_base<
00589         packed_sample_reference<BitField, FirstBit, NumBits, true>,
00590         BitField, NumBits, true> parent_t;
00591     friend class packed_sample_reference<BitField, FirstBit, NumBits, false>;
00592 
00593     static const BitField sample_mask =
00594         static_cast<BitField> (parent_t::max_val) << FirstBit;
00595 
00596 public:
00597     typedef const packed_sample_reference<BitField,FirstBit,NumBits,false>
00598     const_reference;
00599     typedef const packed_sample_reference<BitField,FirstBit,NumBits,true>
00600     mutable_reference;
00601     typedef typename parent_t::integer_t integer_t;
00602 
00603     explicit packed_sample_reference (void* data_ptr)
00604         : parent_t (data_ptr) {}
00605 
00606     packed_sample_reference (const packed_sample_reference& ref)
00607         : parent_t (ref._data_ptr) {}
00608 
00609     const packed_sample_reference& operator= (integer_t value) const
00610     {
00611         assert (value<=parent_t::max_val);
00612         set_unsafe (value);
00613         return *this;
00614     }
00615     
00616     const packed_sample_reference& operator= (const mutable_reference& ref) const
00617     {
00618         set_from_reference (ref.get_data ());
00619         return *this;
00620     }
00621     
00622     const packed_sample_reference& operator= (const const_reference&   ref) const
00623     {
00624         set_from_reference (ref.get_data ());
00625         return *this;
00626     }
00627 
00628     template <bool Mutable1>
00629     const packed_sample_reference& operator= (
00630         const packed_dynamic_sample_reference<BitField,NumBits,Mutable1>& ref)
00631         const
00632     {
00633         set_unsafe (ref.get ());
00634         return *this;
00635     }
00636 
00637     unsigned first_bit () const { return FirstBit; }
00638 
00639     integer_t get () const
00640     {
00641         return integer_t((this->get_data()&sample_mask) >> FirstBit);
00642     }
00643     
00644     void set_unsafe (integer_t value) const
00645     {
00646         this->set_data ((this->get_data() & ~sample_mask) |
00647                         (( static_cast< BitField >( value )<<FirstBit)));
00648     }
00649     
00650 private:
00651     
00652     void set_from_reference (const BitField& other_bits) const
00653     {
00654         this->set_data((this->get_data() & ~sample_mask) |
00655                        (other_bits & sample_mask));
00656     }
00657 };
00658 
00659 } /* namespace sound */
00660 } /* namespace psynth */
00661 
00662 namespace std
00663 {
00664 
00665 /*
00666   We are forced to define swap inside std namespace because on some
00667   platforms (Visual Studio 8) STL calls swap qualified.
00668   
00669   swap with 'left bias': 
00670   - swap between proxy and anything
00671   - swap between value type and proxy
00672   - swap between proxy and proxy
00673 */
00674 
00679 template <typename BF, int FB, int NB, bool M, typename R> inline
00680 void swap(const psynth::sound::packed_sample_reference<BF,FB,NB,M> x, R& y)
00681 { 
00682     psynth::sound::swap_proxy<
00683         typename psynth::sound::packed_sample_reference<BF,FB,NB,M>::value_type>(
00684             x, y); 
00685 }
00686 
00687 
00692 template <typename BF, int FB, int NB, bool M> inline
00693 void swap(
00694     typename psynth::sound::packed_sample_reference<BF,FB,NB,M>::value_type& x,
00695     const psynth::sound::packed_sample_reference<BF,FB,NB,M> y)
00696 { 
00697     psynth::sound::swap_proxy<
00698         typename psynth::sound::packed_sample_reference<BF,FB,NB,M>::value_type>(
00699             x, y); 
00700 }
00701 
00702 
00707 template <typename BF, int FB, int NB, bool M> inline
00708 void swap (
00709     const psynth::sound::packed_sample_reference<BF,FB,NB,M> x,
00710     const psynth::sound::packed_sample_reference<BF,FB,NB,M> y)
00711 { 
00712     psynth::sound::swap_proxy<
00713         typename psynth::sound::packed_sample_reference<BF,FB,NB,M>::value_type>(
00714             x, y); 
00715 }
00716 
00717 } /* namespace std */
00718 
00719 namespace psynth
00720 {
00721 namespace sound
00722 {
00723 
00758 template <typename BitField, int NumBits> 
00759 class packed_dynamic_sample_reference<BitField,NumBits,false>
00760    : public detail::packed_sample_reference_base<
00761     packed_dynamic_sample_reference<BitField, NumBits, false>,
00762     BitField, NumBits, false>
00763 {
00764     typedef detail::packed_sample_reference_base<
00765         packed_dynamic_sample_reference<BitField, NumBits, false>,
00766         BitField,NumBits,false> parent_t;
00767     friend class packed_dynamic_sample_reference<BitField, NumBits, true>;
00768 
00769     unsigned _first_bit;     // 0..7
00770 
00771     void operator= (const packed_dynamic_sample_reference&);
00772 
00773 public:
00774     typedef const packed_dynamic_sample_reference<BitField, NumBits, false>
00775     const_reference;
00776     typedef const packed_dynamic_sample_reference<BitField,NumBits,true>
00777     mutable_reference;
00778     typedef typename parent_t::integer_t
00779     integer_t;
00780 
00781     packed_dynamic_sample_reference (const void* data_ptr, unsigned first_bit)
00782         : parent_t(data_ptr)
00783         , _first_bit(first_bit) {}
00784     
00785     packed_dynamic_sample_reference (const const_reference& ref)
00786         : parent_t (ref._data_ptr)
00787         , _first_bit(ref._first_bit) {}
00788     
00789     packed_dynamic_sample_reference (const mutable_reference& ref)
00790         : parent_t (ref._data_ptr)
00791         , _first_bit (ref._first_bit) {}
00792 
00793     unsigned first_bit () const { return _first_bit; }
00794 
00795     integer_t get () const
00796     { 
00797         const BitField sample_mask = parent_t::max_val << _first_bit;
00798         return (static_cast<integer_t>(this->get_data () & sample_mask ) >>
00799                 _first_bit);
00800     }
00801 };
00802 
00812 template <typename BitField, int NumBits> 
00813 class packed_dynamic_sample_reference<BitField, NumBits, true>
00814    : public detail::packed_sample_reference_base<
00815     packed_dynamic_sample_reference<BitField, NumBits, true>,
00816     BitField, NumBits, true>
00817 {
00818     typedef detail::packed_sample_reference_base<
00819         packed_dynamic_sample_reference<BitField, NumBits, true>,
00820         BitField, NumBits, true> parent_t;
00821     
00822     friend class packed_dynamic_sample_reference<BitField, NumBits, false>;
00823 
00824     unsigned _first_bit;
00825 
00826 public:
00827     typedef const packed_dynamic_sample_reference<BitField,NumBits, false>
00828     const_reference;
00829     
00830     typedef const packed_dynamic_sample_reference<BitField,NumBits, true>
00831     mutable_reference;
00832 
00833     typedef typename parent_t::integer_t integer_t;
00834 
00835     packed_dynamic_sample_reference (void* data_ptr, unsigned first_bit)
00836         : parent_t (data_ptr)
00837         , _first_bit (first_bit) {}
00838     
00839     packed_dynamic_sample_reference (const packed_dynamic_sample_reference& ref)
00840         : parent_t(ref._data_ptr)
00841         , _first_bit (ref._first_bit) {}
00842 
00843     const packed_dynamic_sample_reference&
00844     operator= (integer_t value) const
00845     {
00846         assert (value <= parent_t::max_val);
00847         set_unsafe (value);
00848         return *this;
00849     }
00850     
00851     const packed_dynamic_sample_reference&
00852     operator= (const mutable_reference& ref) const
00853     {
00854         set_unsafe (ref.get());
00855         return *this;
00856     }
00857     
00858     const packed_dynamic_sample_reference&
00859     operator= (const const_reference& ref) const
00860     {
00861         set_unsafe (ref.get ());
00862         return *this;
00863     }
00864 
00865     template <typename BitField1, int FirstBit1, bool Mutable1>
00866     const packed_dynamic_sample_reference& operator= (
00867         const packed_sample_reference<BitField1, FirstBit1,
00868                                       NumBits, Mutable1>& ref) const 
00869     {
00870         set_unsafe (ref.get());
00871         return *this;
00872     }
00873 
00874     unsigned first_bit () const { return _first_bit; }
00875 
00876     integer_t get() const
00877     { 
00878         const BitField sample_mask = parent_t::max_val<<_first_bit;
00879         return (static_cast<integer_t>(this->get_data() & sample_mask ) >>
00880                 _first_bit);
00881     }
00882     
00883     void set_unsafe(integer_t value) const
00884     { 
00885         const BitField sample_mask = parent_t::max_val << _first_bit;
00886         this->set_data ((this->get_data() & ~sample_mask) | value << _first_bit); 
00887     }
00888 };
00889 
00890 } /* namespace sound */
00891 } /* namespace psynth */
00892 
00893 namespace std
00894 {
00895 
00896 /*
00897   We are forced to define swap inside std namespace because on some
00898   platforms (Visual Studio 8) STL calls swap qualified.
00899   
00900   swap with 'left bias': 
00901   - swap between proxy and anything
00902   - swap between value type and proxy
00903   - swap between proxy and proxy
00904 */
00905 
00910 template <typename BF, int NB, bool M, typename R> inline
00911 void swap(const psynth::sound::packed_dynamic_sample_reference<BF,NB,M> x, R& y)
00912 { 
00913     psynth::sound::swap_proxy<
00914         typename psynth::sound::packed_dynamic_sample_reference<
00915             BF,NB,M>::value_type> (x, y); 
00916 }
00917 
00918 
00923 template <typename BF, int NB, bool M> inline
00924 void swap (typename psynth::sound::packed_dynamic_sample_reference<BF,NB,M>::value_type& x,
00925            const psynth::sound::packed_dynamic_sample_reference<BF,NB,M> y)
00926 { 
00927     psynth::sound::swap_proxy<
00928         typename psynth::sound::packed_dynamic_sample_reference<
00929             BF, NB, M>::value_type> (x,y); 
00930 }
00931 
00936 template <typename BF, int NB, bool M> inline
00937 void swap(const psynth::sound::packed_dynamic_sample_reference<BF,NB,M> x,
00938           const psynth::sound::packed_dynamic_sample_reference<BF,NB,M> y)
00939 { 
00940     psynth::sound::swap_proxy<
00941         typename psynth::sound::packed_dynamic_sample_reference<BF,NB,M>::value_type> (x,y); 
00942 }
00943 
00944 } /* namespace std */
00945 
00946 
00947 namespace psynth
00948 {
00949 namespace sound
00950 {
00951 
00952 /*
00953  *
00954  *    Built-in sample models
00955  *
00956  */
00957 
00965 typedef boost::uint8_t  bits8;
00966 
00974 typedef boost::uint16_t bits16;
00975 
00983 typedef boost::uint32_t bits32;
00984 
00992 typedef boost::int8_t   bits8s;
00993 
01001 typedef boost::int16_t  bits16s;
01002 
01010 typedef boost::int32_t  bits32s;
01011 
01019 typedef scoped_sample_value<float, float_zero, float_one, float_half> bits32f;
01020 
01028 typedef scoped_sample_value<float, float_minus_one, float_one, float_zero>
01029 bits32sf;
01030 
01031 } /* namespace sound */
01032 } /* namespace psynth */
01033 
01034 namespace boost
01035 {
01036 
01041 template <int NumBits>
01042 struct is_integral<psynth::sound::packed_sample_value<NumBits> > :
01043         public boost::mpl::true_ {};
01044 
01045 template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
01046 struct is_integral<psynth::sound::packed_sample_reference<
01047                        BitField, FirstBit, NumBits, IsMutable> > :
01048         public boost::mpl::true_ {};
01049 
01050 template <typename BitField, int NumBits, bool IsMutable>
01051 struct is_integral<psynth::sound::packed_dynamic_sample_reference<
01052                        BitField, NumBits, IsMutable> > :
01053         public boost::mpl::true_ {};
01054 
01055 template <typename BaseSampleValue,
01056           typename MinVal, typename MaxVal, typename ZeroVal> 
01057 struct is_integral<psynth::sound::scoped_sample_value<
01058                        BaseSampleValue, MinVal, MaxVal, ZeroVal> > :
01059         public is_integral<BaseSampleValue> {};
01060 
01061 } /* namespace boost */
01062 
01063 #endif /* PSYNTH_SAMPLE_HPP_ */