libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/ring_buffer.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 #ifndef PSYNTH_SOUND_RING_BUFFER_H_
00032 #define PSYNTH_SOUND_RING_BUFFER_H_
00033 
00034 #include <psynth/sound/buffer.hpp>
00035 #include <psynth/sound/ring_buffer_range.hpp>
00036 
00037 namespace psynth
00038 {
00039 namespace sound
00040 {
00041 
00045 template <class Buffer, template <class> class BRange>
00046 class ring_buffer_base
00047 {
00048 public:
00049     typedef BRange<typename Buffer::range> range_base;
00050     typedef BRange<typename Buffer::const_range> const_range_base;
00051 
00052     typedef typename range_base::difference_type difference_type;
00053     typedef typename range_base::size_type       size_type;
00054     typedef typename range_base::unsafe_position unsafe_position;
00055     typedef typename range_base::position        position;
00056     
00057     /* Create with size and optional initial value and
00058      * alignment */
00059 
00060     explicit ring_buffer_base (size_type size = 0,
00061                                std::size_t alignment = 0)
00062         : _buffer (size, alignment)
00063         , _range  (range_base (range (_buffer)))
00064     {}
00065 
00066     template <typename Allocator>
00067     explicit ring_buffer_base (size_type size,
00068                                std::size_t alignment,
00069                                Allocator alloc_in)
00070         : _buffer (size, alignment, alloc_in)
00071         , _range  (range_base (range (_buffer)))
00072     {}
00073     
00074     explicit ring_buffer_base (const Buffer& buf)
00075         : _buffer (buf)
00076         , _range (range_base (range (_buffer)))
00077     {
00078         _range.advance (size ());
00079     }
00080 
00081     template <typename F2, bool IP2, typename Alloc2>
00082     explicit ring_buffer_base (const buffer<F2, IP2, Alloc2>& buf)
00083         : _buffer (buf)
00084         , _range (range_base (range (_buffer)))
00085     {
00086         _range.advance (size ());
00087     }
00088 
00089     ring_buffer_base& operator= (const ring_buffer_base& buf)
00090     {
00091         _buffer = buf._buffer;
00092         _range  = range_base (range (_buffer));
00093         _range.advance (buf._range.count ());
00094         return *this;
00095     }
00096 
00097     template <class Buffer2, template<class>class BRange2>
00098     ring_buffer_base& operator= (const ring_buffer_base<Buffer2, BRange2>& buf)
00099     {
00100         _buffer = buf._buffer;
00101         _range  = range_base (range (_buffer));
00102         _range.advance (buf._range.count ());
00103         return *this;
00104     }
00105 
00106     size_type size () const
00107     { return _range.size (); }
00108 
00109     void swap (ring_buffer_base& buf)
00110     {
00111         // required by MutableContainerConcept
00112         using std::swap;
00113         swap (_buffer, buf._buffer);
00114         swap (_range,  buf._range);
00115     }
00116     
00117     void recreate (size_type size,
00118                    std::size_t alignment = 0)
00119     {
00120         _buffer.recreate (size, alignment);
00121         _range = range_base (range (_buffer));
00122     }
00123     
00124     template <typename Allocator>
00125     void recreate (size_type size,
00126                    std::size_t alignment,
00127                    const Allocator alloc_in)
00128     {
00129         _buffer.recreate (size, alignment, alloc_in);
00130         _range = range_base (range (_buffer));
00131     }
00132 
00133     
00134 #ifdef PSYNTH_BUFFER_MODEL_RANGE
00135 
00136     position begin_pos () const
00137     { return _range.begin_pos (); }
00138 
00139     position end_pos () const
00140     { return _range.end_pos (); }
00141 
00142     safe_position safe_begin_pos () const
00143     { return _range.safe_begin_pos (); }
00144 
00145     safe_position safe_end_pos () const
00146     { return _range.safe_end_pos (); }
00147 
00149     size_type available (const safe_position& r) const
00150     { return _range.available (r); }
00151 
00153     size_type available () const
00154     { return _range.available (); }
00155 
00157     ring_buffer_error check_position (const safe_position& r) const
00158     { return _range.check_position (r); }
00159 
00161     template<class Position, class Range>
00162     size_type read (Position& r, Range& buf) const
00163     { return _range.read (r, buf, buf.size ()); };
00164     
00166     template<class Position, class Range>
00167     size_type read (Position& r, Range& buf, size_type samples) const
00168     { return _range.read (r, buf, samples); }
00169 
00171     template<class Position, class Range, class CC = default_channel_converter>
00172     size_type read_and_convert (Position& r, const Range& buf, CC cc = CC ()) const
00173     { return _range.read_and_convert (r, buf, buf.size (), cc); };
00174 
00176     template<class Position, class Range, class CC = default_channel_converter>
00177     size_type read_and_convert (Position& r, const Range& buf,
00178                                 size_type samples, CC cc = CC ()) const
00179     { return _range.read_and_convert (r, buf, samples, cc); }
00180 
00182     template<class Position, class Range, class CC = default_channel_converter>
00183     size_type read_and_convert (Position& r, Range& buf, CC cc = CC ()) const
00184     { return _range.read_and_convert (r, buf, buf.size (), cc); };
00185 
00187     template<class Position, class Range, class CC = default_channel_converter>
00188     size_type read_and_convert (Position& r, Range& buf,
00189                                 size_type samples, CC cc = CC ()) const
00190     { return _range.read_and_convert (r, buf, samples, cc); }
00191     
00193     template <class Range>
00194     void write (const Range& buf)
00195     { return _range.write (buf, buf.size ()); }
00196 
00198     template <class Range>
00199     void write (const Range& buf, size_type samples)
00200     { _range.write (buf, samples); }
00201     
00203     template <class Range, class CC = default_channel_converter>
00204     void write_and_convert (const Range& buf, CC cc = CC ())
00205     { _range.write_and_convert (buf, buf.size (), cc); }
00206     
00208     template <class Range, class CC = default_channel_converter>
00209     void write_and_convert (const Range& buf, size_type samples, CC cc = CC ())
00210     { _range.write_and_convert (buf, samples, cc); }
00211 
00213     void zero ()
00214     { _range.zero (); }
00215 
00217     bool is_backwards () const
00218     { return _range.is_backwards (); }
00219     
00221     void set_backwards ()
00222     { return _range.set_backwards (); }
00223 
00224     template <typename Position> // Models PositionConcept
00225     void advance (Position& r, difference_type n) const
00226     { return _range.advance (r, n); }
00227 
00228     template <typename Position>
00229     void increment (Position& r) const
00230     { return _range.increment (r); }
00231 
00232     template <typename Position>
00233     void decrement (Position& r) const
00234     { return _range.decrement (r); }
00235 
00236     void advance (size_type n)
00237     { return _range.advance (n); }
00238 
00239     difference_type count () const
00240     { return _range.count (); }
00241     
00242     safe_position sync (const safe_position& r) const
00243     { return _range.sync (); }
00244 
00245 #endif /* PSYNTH_BUFFER_MODEL_RANGE */
00246     
00247 protected:
00248     Buffer      _buffer;
00249     range_base  _range;
00250 };
00251 
00252 
00253 template <class Buffer>
00254 class ring_buffer : public ring_buffer_base<Buffer, ring_buffer_range>
00255 {
00256     typedef ring_buffer_base<Buffer, ring_buffer_range> parent_type;
00257 
00258 public:
00259     typedef typename Buffer::allocator_type allocator_type;
00260     
00261     typedef typename parent_type::range_base       range;
00262     typedef typename parent_type::const_range_base const_range;
00263     
00264     typedef typename range::value_type          value_type;
00265     typedef typename range::reference           reference;
00266     
00267     typedef typename range::unsafe_iterator            unsafe_iterator;
00268     typedef typename const_range::unsafe_iterator      const_unsafe_iterator;
00269     typedef typename range::iterator                   iterator;
00270     typedef typename const_range::iterator             const_iterator;
00271 
00277     explicit ring_buffer (typename parent_type::size_type size = 0,
00278                           std::size_t alignment = 0,
00279                           const typename Buffer::allocator_type
00280                           alloc_in = typename Buffer::allocator_type ())
00281         : parent_type (size, alignment, alloc_in)
00282     {}
00283     
00284     explicit ring_buffer (const Buffer& buf)
00285         : parent_type (buf)
00286     {}
00287 
00288     template <typename F2, bool IP2, typename Alloc2>
00289     explicit ring_buffer (const buffer<F2, IP2, Alloc2>& buf)
00290         : parent_type (buf)
00291     {
00292     }
00293 
00294     ring_buffer& operator= (const ring_buffer& buf)
00295     {
00296         parent_type::operator= (buf);
00297         return *this;
00298     }
00299 
00300     template <class Buffer2>
00301     ring_buffer& operator= (const ring_buffer<Buffer2>& buf)
00302     {
00303         parent_type::operator= (buf);
00304         return *this;
00305     }
00306 
00307     using parent_type::recreate;
00308     
00309     void recreate (typename parent_type::size_type size,
00310                    typename Buffer::range::value_type val,
00311                    std::size_t alignment = 0)
00312     {
00313         this->_buffer.recreate (size, val, alignment);
00314         this->_range = range (sound::range (this->_buffer));
00315     }
00316 
00317 #ifdef PSYNTH_BUFFER_MODELS_RANGE
00318     
00319     iterator begin ()
00320     { return this->_range.begin (); }
00321 
00322     iterator end ()
00323     { return this->_range.end (); }
00324 
00325     safe_iterator safe_begin ()
00326     { return this->_range.safe_begin (); }
00327 
00328     safe_iterator safe_end ()
00329     { return this->_range.safe_end (); }
00330 
00331     const_iterator begin () const
00332     { return this->_range.begin (); }
00333 
00334     const_iterator end () const
00335     { return this->_range.end (); }
00336 
00337     const_safe_iterator safe_begin () const
00338     { return this->_range.safe_begin (); }
00339 
00340     const_safe_iterator safe_end () const
00341     { return this->_range.safe_end (); }    
00342 
00343 #endif /* PSYNTH_BUFFER_MODEL_RANGE */
00344     
00345     allocator_type&       allocator ()
00346     { return this->_buffer.allocator (); }
00347 
00348     allocator_type const& allocator () const
00349     { return this->_buffer.allocator (); }
00350 
00351 private:
00352     template <typename B> friend 
00353     typename ring_buffer<B>::range&
00354     range (ring_buffer<B>& buf);
00355 
00356     template <typename B> friend 
00357     const typename ring_buffer<B>::const_range
00358     const_range (const ring_buffer<B>& buf);
00359 };
00360 
00361 /*
00362  *
00363  *  @todo BufferConcept
00364  *
00365  */
00366 
00372 template <typename B>
00373 typename ring_buffer<B>::range&
00374 range (ring_buffer<B>& buf)
00375 {
00376     return buf._range;
00377 }
00378 
00379 template <typename B>
00380 const typename ring_buffer<B>::const_range
00381 const_range (const ring_buffer<B>& buf)
00382 {
00383     return buf._range;
00384 }
00385 
00386 /*
00387  *
00388  *  FrameBasedConcept
00389  *  
00390  */
00391 
00392 template <typename Buffer>
00393 struct sample_type<ring_buffer<Buffer> > :
00394     public sample_type<Buffer> {}; 
00395 
00396 template <typename Buffer>
00397 struct channel_space_type<ring_buffer<Buffer> > :
00398     public channel_space_type<Buffer> {}; 
00399 
00400 template <typename Buffer>
00401 struct sample_mapping_type<ring_buffer<Buffer> > :
00402     public sample_mapping_type<Buffer> {}; 
00403 
00404 template <typename Buffer>
00405 struct is_planar<ring_buffer<Buffer> > :
00406     public is_planar<Buffer> {}; 
00407 
00408 
00409 /*
00410  *
00411  *  @todo DynamicStepTypeConcept
00412  *  
00413  */
00414     
00415 } /* namespace sound */
00416 } /* namespace psynth */
00417 
00418 #endif /* PSYNTH_SOUND_RING_BUFFER_H_ */
00419