|
libpsynth 0.2.1
|
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_SOUND_BIT_ALIGNED_PIXEL_REFERENCE_HPP 00040 #define PSYNTH_SOUND_BIT_ALIGNED_PIXEL_REFERENCE_HPP 00041 00042 #include <functional> 00043 #include <boost/mpl/accumulate.hpp> 00044 #include <boost/mpl/at.hpp> 00045 #include <boost/mpl/bool.hpp> 00046 #include <boost/mpl/if.hpp> 00047 #include <boost/mpl/plus.hpp> 00048 #include <boost/mpl/push_back.hpp> 00049 #include <boost/mpl/vector.hpp> 00050 00051 #include <psynth/base/compat.hpp> 00052 #include <psynth/sound/frame.hpp> 00053 #include <psynth/sound/sample.hpp> 00054 00055 namespace psynth 00056 { 00057 namespace sound 00058 { 00059 00069 template <int RangeSize, bool Mutable> 00070 class bit_range 00071 { 00072 public: 00073 typedef typename boost::mpl::if_c<Mutable, 00074 unsigned char, 00075 const unsigned char>::type byte_type; 00076 00077 typedef std::ptrdiff_t difference_type; 00078 template <int RS, bool M> friend class bit_range; 00079 00080 private: 00081 byte_type* _current_byte; // the starting byte of the bit range 00082 int _bit_offset; // offset from the beginning of the 00083 // current byte. 0<=_bit_offset<=7 00084 00085 public: 00086 bit_range () 00087 : _current_byte (0) 00088 , _bit_offset (0) 00089 {} 00090 00091 bit_range (byte_type* current_byte, int bit_offset) 00092 : _current_byte (current_byte) 00093 , _bit_offset(bit_offset) 00094 { assert (bit_offset >= 0 && bit_offset < 8); } 00095 00096 bit_range (const bit_range& br) 00097 : _current_byte (br._current_byte) 00098 , _bit_offset (br._bit_offset) 00099 {} 00100 00101 template <bool M> 00102 bit_range (const bit_range<RangeSize, M>& br) 00103 : _current_byte(br._current_byte) 00104 , _bit_offset (br._bit_offset) 00105 {} 00106 00107 bit_range& operator= (const bit_range& br) 00108 { 00109 _current_byte = br._current_byte; 00110 _bit_offset = br._bit_offset; 00111 return *this; 00112 } 00113 00114 bool operator== (const bit_range& br) const 00115 { 00116 return 00117 _current_byte == br._current_byte && 00118 _bit_offset == br._bit_offset; 00119 } 00120 00121 bit_range& operator++ () 00122 { 00123 _current_byte += (_bit_offset + RangeSize) / 8; 00124 _bit_offset = (_bit_offset + RangeSize) % 8; 00125 return *this; 00126 } 00127 00128 bit_range& operator-- () 00129 { 00130 bit_advance (- RangeSize); 00131 return *this; 00132 } 00133 00134 void bit_advance (difference_type num_bits) 00135 { 00136 int new_offset = int (_bit_offset + num_bits); 00137 _current_byte += new_offset / 8; 00138 _bit_offset = new_offset % 8; 00139 if (_bit_offset<0) { 00140 _bit_offset+=8; 00141 --_current_byte; 00142 } 00143 } 00144 00145 difference_type bit_distance_to (const bit_range& b) const 00146 { 00147 return 00148 (b.current_byte() - current_byte()) * 8 + 00149 b.bit_offset() - bit_offset(); 00150 } 00151 00152 byte_type* current_byte () const 00153 { 00154 return _current_byte; 00155 } 00156 00157 int bit_offset () const 00158 { 00159 return _bit_offset; 00160 } 00161 }; 00162 00209 template <typename BitField, 00210 typename SampleBitSizes, 00211 // MPL integral vector defining the number of bits for each 00212 // sample. For example, for 565RGB, vector_c<int, 5, 6, 5> 00213 typename Layout, 00214 bool IsMutable> 00215 struct bit_aligned_frame_reference 00216 { 00217 BOOST_STATIC_CONSTANT( 00218 int, bit_size = (boost::mpl::accumulate<SampleBitSizes, boost::mpl::int_<0>, 00219 boost::mpl::plus<boost::mpl::_1, boost::mpl::_2> 00220 >::type::value)); 00221 00222 typedef psynth::sound::bit_range<bit_size, IsMutable> bit_range_type; 00223 typedef BitField bitfield_type; 00224 typedef typename boost::mpl::if_c<IsMutable, 00225 unsigned char*, 00226 const unsigned char*>::type data_ptr_type; 00227 typedef Layout layout; 00228 00229 typedef typename packed_frame_type< 00230 bitfield_type, SampleBitSizes,Layout>::type value_type; 00231 typedef const bit_aligned_frame_reference reference; 00232 typedef const bit_aligned_frame_reference< 00233 BitField, SampleBitSizes, Layout, false> const_reference; 00234 00235 BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable); 00236 00237 bit_aligned_frame_reference () {} 00238 00239 bit_aligned_frame_reference (data_ptr_type data_ptr, int bit_offset) 00240 : _bit_range (data_ptr, bit_offset) 00241 {} 00242 00243 explicit bit_aligned_frame_reference (const bit_range_type& bit_range) 00244 : _bit_range (bit_range) 00245 {} 00246 00247 template <bool IsMutable2> bit_aligned_frame_reference ( 00248 const bit_aligned_frame_reference< 00249 BitField, SampleBitSizes, Layout, IsMutable2>& p) 00250 : _bit_range(p._bit_range) 00251 {} 00252 00253 // Mono references can be constructed from the sample reference 00254 explicit bit_aligned_frame_reference ( 00255 const typename kth_element_type< 00256 bit_aligned_frame_reference, 0>::type sample0) 00257 : _bit_range (static_cast<data_ptr_type>(&sample0), sample0.first_bit()) 00258 { 00259 BOOST_STATIC_ASSERT((num_samples< 00260 bit_aligned_frame_reference>::value == 1)); 00261 } 00262 00263 // Construct from another compatible frame type 00264 bit_aligned_frame_reference (const bit_aligned_frame_reference& p) 00265 : _bit_range(p._bit_range) 00266 {} 00267 00268 template <typename BF, typename CR> 00269 bit_aligned_frame_reference (packed_frame<BF,CR,Layout>& p) 00270 : _bit_range (static_cast<data_ptr_type>(&sound::at_c<0>( p)), 00271 sound::at_c<0> (p).first_bit ()) 00272 { 00273 check_compatible<packed_frame<BF,CR,Layout> >(); 00274 } 00275 00276 const bit_aligned_frame_reference& operator= ( 00277 const bit_aligned_frame_reference& p) const 00278 { 00279 static_copy (p,*this); 00280 return *this; 00281 } 00282 00283 template <typename P> 00284 const bit_aligned_frame_reference& operator= (const P& p) const 00285 { 00286 assign (p, boost::mpl::bool_<is_frame<P>::value>()); 00287 return *this; 00288 } 00289 00290 template <typename P> 00291 bool operator== (const P& p) const 00292 { 00293 return equal (p, boost::mpl::bool_<is_frame<P>::value>()); 00294 } 00295 00296 template <typename P> 00297 bool operator!= (const P& p) const 00298 { return !(*this == p); } 00299 00300 const bit_aligned_frame_reference* operator->() const 00301 { return this; } 00302 00303 const bit_range_type& bit_range() const 00304 { return _bit_range; } 00305 00306 private: 00307 mutable bit_range_type _bit_range; 00308 00309 template <typename B, typename C, typename L, bool M> 00310 friend struct bit_aligned_frame_reference; 00311 00312 template <typename Frame> 00313 static void check_compatible() 00314 { 00315 base::psynth_function_requires<FramesCompatibleConcept< 00316 Frame, bit_aligned_frame_reference> >(); 00317 } 00318 00319 template <typename Frame> 00320 void assign (const Frame& p, boost::mpl::true_) const 00321 { 00322 check_compatible<Frame>(); 00323 static_copy (p, *this); 00324 } 00325 00326 template <typename Frame> 00327 bool equal (const Frame& p, boost::mpl::true_) const 00328 { 00329 check_compatible<Frame>(); 00330 return static_equal (*this, p); 00331 } 00332 00333 static void check_mono () 00334 { 00335 BOOST_STATIC_ASSERT((boost::is_same< 00336 typename Layout::channel_space_type, 00337 mono_space>::value)); 00338 } 00339 00340 template <typename Sample> 00341 void assign (const Sample& chan, boost::mpl::false_) const 00342 { 00343 check_mono (); 00344 sound::at_c<0>(*this) = chan; 00345 } 00346 00347 template <typename Sample> 00348 bool equal (const Sample& chan, boost::mpl::false_) const 00349 { 00350 check_mono (); 00351 return sound::at_c<0>(*this)==chan; 00352 } 00353 }; 00354 00355 /* 00356 * 00357 * ChannelBasedConcept 00358 * 00359 */ 00360 00361 template <typename BitField, typename SampleBitSizes, 00362 typename L, bool IsMutable, int K> 00363 struct kth_element_type<bit_aligned_frame_reference< 00364 BitField,SampleBitSizes,L,IsMutable>, K> 00365 { 00366 public: 00367 typedef const packed_dynamic_sample_reference< 00368 BitField, boost::mpl::at_c<SampleBitSizes, K>::type::value, IsMutable> type; 00369 }; 00370 00371 template <typename B, typename C, typename L, bool M, int K> 00372 struct kth_element_reference_type<bit_aligned_frame_reference<B,C,L,M>, K> 00373 : public kth_element_type<bit_aligned_frame_reference<B,C,L,M>, K> {}; 00374 00375 template <typename B, typename C, typename L, bool M, int K> 00376 struct kth_element_const_reference_type<bit_aligned_frame_reference<B,C,L,M>, K> 00377 : public kth_element_type<bit_aligned_frame_reference<B,C,L,M>, K> {}; 00378 00379 00380 namespace detail 00381 { 00382 00383 // returns sum of IntegralVector[0] ... IntegralVector[K-1] 00384 template <typename IntegralVector, int K> 00385 struct sum_k : 00386 public boost::mpl::plus<sum_k<IntegralVector, K-1>, 00387 typename boost::mpl::at_c<IntegralVector, K-1>::type > {}; 00388 00389 template <typename IntegralVector> 00390 struct sum_k<IntegralVector, 0> : public boost::mpl::int_<0> {}; 00391 00392 } /* namespace detail */ 00393 00395 template <int K, typename BitField, typename SampleBitSizes, 00396 typename L, bool Mutable> inline 00397 typename kth_element_reference_type< 00398 bit_aligned_frame_reference<BitField,SampleBitSizes,L,Mutable>,K>::type 00399 at_c (const bit_aligned_frame_reference<BitField,SampleBitSizes,L,Mutable>& p) 00400 { 00401 typedef bit_aligned_frame_reference<BitField,SampleBitSizes,L,Mutable> frame_t; 00402 typedef typename kth_element_reference_type<frame_t,K>::type sample_t; 00403 typedef typename frame_t::bit_range_type bit_range_type; 00404 00405 bit_range_type bit_range (p.bit_range()); 00406 bit_range.bit_advance (detail::sum_k<SampleBitSizes, K>::value); 00407 00408 return sample_t (bit_range.current_byte(), bit_range.bit_offset ()); 00409 } 00410 00411 /* 00412 * 00413 * FrameConcept 00414 * 00415 */ 00416 00421 template <typename B, typename C, typename L, bool M> 00422 struct is_frame<bit_aligned_frame_reference<B,C,L,M> > : public boost::mpl::true_{}; 00423 00424 /* 00425 * 00426 * FrameBasedConcept 00427 * 00428 */ 00429 00430 template <typename B, typename C, typename L, bool M> 00431 struct channel_space_type<bit_aligned_frame_reference<B,C,L,M> > 00432 { 00433 typedef typename L::channel_space type; 00434 }; 00435 00436 template <typename B, typename C, typename L, bool M> 00437 struct sample_mapping_type<bit_aligned_frame_reference<B,C,L,M> > 00438 { 00439 typedef typename L::sample_mapping type; 00440 }; 00441 00442 template <typename B, typename C, typename L, bool M> 00443 struct is_planar<bit_aligned_frame_reference<B,C,L,M> > : boost::mpl::false_ {}; 00444 00445 00446 /* 00447 * 00448 * frame_reference_type 00449 * 00450 */ 00451 00452 namespace detail 00453 { 00454 00455 // returns a vector containing K copies of the type T 00456 template <unsigned K, typename T> 00457 struct k_copies; 00458 00459 template <typename T> struct k_copies<0,T> 00460 { 00461 typedef boost::mpl::vector0<> type; 00462 }; 00463 00464 template <unsigned K, typename T> 00465 struct k_copies : public boost::mpl::push_back<typename k_copies<K-1,T>::type, T> {}; 00466 00467 } /* namespace detail */ 00468 00469 /* 00470 Constructs a homogeneous bit_aligned_frame_reference given a sample 00471 reference 00472 */ 00473 template <typename BitField, int NumBits, typename Layout> 00474 struct frame_reference_type<const packed_dynamic_sample_reference< 00475 BitField,NumBits,false>, Layout, false, false> 00476 { 00477 private: 00478 typedef typename boost::mpl::size<typename Layout::channel_space>::type 00479 size_type; 00480 00481 typedef typename detail::k_copies< 00482 size_type::value, boost::mpl::integral_c<unsigned,NumBits> >::type 00483 sample_bit_sizes_type; 00484 00485 public: 00486 typedef bit_aligned_frame_reference<BitField, sample_bit_sizes_type, 00487 Layout, false> type; 00488 }; 00489 00490 00491 /* 00492 Same but for the mutable case. We cannot combine the mutable and 00493 read-only cases because this triggers ambiguity 00494 */ 00495 template <typename BitField, int NumBits, typename Layout> 00496 struct frame_reference_type<const packed_dynamic_sample_reference< 00497 BitField,NumBits,true>, Layout, false, true> 00498 { 00499 private: 00500 typedef typename boost::mpl::size<typename Layout::channel_space>::type 00501 size_type; 00502 00503 typedef typename detail::k_copies< 00504 size_type::value, boost::mpl::integral_c<unsigned, NumBits> >::type 00505 sample_bit_sizes_type; 00506 00507 public: 00508 typedef bit_aligned_frame_reference< 00509 BitField, sample_bit_sizes_type, Layout, true> type; 00510 }; 00511 00512 } /* namespace sound */ 00513 } /* namespace psynth */ 00514 00515 namespace std 00516 { 00517 00518 /* 00519 We are forced to define swap inside std namespace because on some 00520 platforms (Visual Studio 8) STL calls swap qualified. 00521 00522 swap with 'left bias': 00523 - swap between proxy and anything 00524 - swap between value type and proxy 00525 - swap between proxy and proxy 00526 00527 Having three overloads allows us to swap between different (but 00528 compatible) models of FrameConcept 00529 */ 00530 template <typename B, typename C, typename L, typename R> inline 00531 void swap (const psynth::sound::bit_aligned_frame_reference<B,C,L,true> x, R& y) 00532 { 00533 psynth::sound::swap_proxy< 00534 typename psynth::sound::bit_aligned_frame_reference< 00535 B,C,L,true>::value_type>(x, y); 00536 } 00537 00538 00539 template <typename B, typename C, typename L> inline 00540 void swap (typename psynth::sound::bit_aligned_frame_reference< 00541 B,C,L,true>::value_type& x, 00542 const psynth::sound::bit_aligned_frame_reference<B,C,L,true> y) 00543 { 00544 psynth::sound::swap_proxy< 00545 typename psynth::sound::bit_aligned_frame_reference< 00546 B,C,L,true>::value_type>(x, y); 00547 } 00548 00549 template <typename B, typename C, typename L> inline 00550 void swap (const psynth::sound::bit_aligned_frame_reference<B,C,L,true> x, 00551 const psynth::sound::bit_aligned_frame_reference<B,C,L,true> y) 00552 { 00553 psynth::sound::swap_proxy< 00554 typename psynth::sound::bit_aligned_frame_reference< 00555 B,C,L,true>::value_type> (x, y); 00556 } 00557 00558 } /* namespace std */ 00559 00560 #endif /* PSYNTH_SOUND_BIT_ALIGNED_FRAME_REFERENCE */
1.7.4