Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

/root/src/subsynth/syn/Util/AudioFormat.h

Go to the documentation of this file.
00001 
00002 /****************** <SYN heading BEGIN do not edit this line> *****************
00003  *
00004  * subsynth - modular audio synthesizer
00005  * subsynth is (C) Copyright 2001-2002 by Kevin Meinert
00006  *
00007  * Original Author: Kevin Meinert
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public
00020  * License along with this library; if not, write to the
00021  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00022  * Boston, MA 02111-1307, USA.
00023  *
00024  * -----------------------------------------------------------------
00025  * File:          $RCSfile: AudioFormat.h,v $
00026  * Date modified: $Date: 2002/04/14 19:56:42 $
00027  * Version:       $Revision: 1.37 $
00028  * -----------------------------------------------------------------
00029  *
00030  ****************** <SYN heading END do not edit this line> ******************/
00031 
00032 #ifndef SUBSYNTH_AUDIO_FORMAT_UTILS____
00033 #define SUBSYNTH_AUDIO_FORMAT_UTILS____
00034 
00035 #include <assert.h>
00036 #include <vector>
00037 #include <iostream>
00038 #include <memory.h> // memcpy...
00039 #ifdef max
00040 #undef max
00041 #endif
00042 
00043 #ifdef min
00044 #undef min
00045 #endif
00046 
00047 namespace syn
00048 {
00054    template <typename type>
00055    class audio_data_traits
00056    {
00057    public:
00058       static type  min();
00059       static type  max();
00060       static type  bytes();
00061       static int range();
00062       static float rangef();
00063 
00073       static type  one_fourth_range();
00074    };   
00075 
00077    template <>
00078    class audio_data_traits<float>
00079    {
00080    public:
00081       static float min() { return -1.0f; }
00082       static float max() { return 1.0f; }
00083       static float bytes() { return 4; }
00084       static float rangef() { return 2.0f; }
00085       static int range() { return (int)rangef(); }
00086       
00087       static float one_fourth_range() 
00088       { return range() / 4.0f; }
00089    };
00090 
00092    template <>
00093    class audio_data_traits<signed char>
00094    {
00095    public:
00096       static signed char min() { return -128; }
00097       static signed char max() { return 127; }
00098       static signed char bytes() { return 1; }
00099       static int range() { return 256; }
00100       static float rangef() 
00101       { return (float)range(); }
00102 
00103       static signed char one_fourth_range() 
00104       { return range() / 4; }
00105    };
00106 
00108    template <>
00109    class audio_data_traits<unsigned char>
00110    {
00111    public:
00112       static unsigned char min() { return 0; }
00113       static unsigned char max() { return 255; }
00114       static unsigned char bytes() { return 1; }
00115       static int range() { return 256; }
00116       static float rangef()
00117       { return (float)range(); }
00118 
00119       static unsigned char one_fourth_range()
00120       { return range() / 4; }
00121    };
00122 
00124    template <>
00125    class audio_data_traits<signed short>
00126    {
00127    public:
00128       static signed short min() { return -32768; }
00129       static signed short max() { return 32767; }
00130       static signed short bytes() { return 2; }
00131       static int range() { return 65536; }
00132       static float rangef() 
00133       { return (float)range(); }
00134       
00135       static signed short one_fourth_range() 
00136       { return range() / 4; }
00137    };
00138 
00140    template <>
00141    class audio_data_traits<unsigned short>
00142    {
00143    public:
00144       static unsigned short min() { return 0; }
00145       static unsigned short max() { return 65535; }
00146       static unsigned short bytes() { return 2; }
00147       static int range() { return 65536; }
00148       static float rangef() 
00149       { return (float)range(); }
00150       
00151       static unsigned short one_fourth_range() 
00152       { return range() / 4; }
00153    };
00154 
00158    template <typename in, typename out>
00159    inline void audio_convert( const in& i, out& o )
00160    {
00161       const in in_range = audio_data_traits<in>::one_fourth_range();
00162       const in in_min = audio_data_traits<in>::min();
00163       //const in in_max = audio_data_traits<in>::max();
00164       const out out_range = audio_data_traits<out>::one_fourth_range();
00165       const out out_min = audio_data_traits<out>::min();
00166       //const out out_max = audio_data_traits<out>::max();
00167 
00168       // degenerate case: types are the same, no conversion needed
00169       /*
00170       if (in_range == out_range && in_min == out_min && in_max == out_max)
00171       {
00172          // we should never get here
00173          assert( false );
00174          return;
00175       }
00176       */
00177       
00178       // do conversion:
00179       // offset by <in>::min, then scale, then offset back by <out>::min
00180          
00181       // when <in> is larger capacity type...
00182       if ( (audio_data_traits<in>::range() >= audio_data_traits<out>::range() ||
00183          // special case, float is bigger capacity data type than all others...
00184            audio_data_traits<in>::range() == audio_data_traits<float>::range()) &&
00185            audio_data_traits<out>::range() != audio_data_traits<float>::range() ) 
00186       {
00187          const in scale = ((in)out_range) / in_range;
00188          const in inv_scale = in_range / ((in)out_range);
00189          if (scale != 0.0) // float to int (float mult, 2 adds)
00190             o = (out) (((i - in_min) * scale) + out_min);
00191          else              // 16 to 8 bit (shift right, 2 adds)
00192             o = (out) (((i - in_min) / inv_scale) + out_min);
00193       }
00194       else // <out> is larger capacity type
00195       {
00196          const out scale = out_range / ((out)in_range);
00197          assert( scale != 0.0 && "scale should never be 0 in this case" ); 
00198          
00199          // 8 to 16 bit conversion (shift left, 2 adds)
00200          // integer to float (float mult, 2 float adds)
00201          o = (out) (((i - in_min) * scale) + out_min);
00202       }
00203 
00204       // degenerate case: float(1.0) to int(0) is incorrect
00205       if (audio_data_traits<in>::range() == audio_data_traits<float>::range() && 
00206          audio_data_traits<out>::range() != audio_data_traits<float>::range() && 
00207           i >= 0.9999f)
00208           o -= (out)1;
00209    }
00210 
00214    template <> inline void audio_convert( const signed char& i, signed char& o ) { o = i; }
00215    template <> inline void audio_convert( const unsigned char& i, unsigned char& o ) { o = i; }
00216    template <> inline void audio_convert( const signed short& i, signed short& o ) { o = i; }
00217    template <> inline void audio_convert( const unsigned short& i, unsigned short& o ) { o = i; }
00218    template <> inline void audio_convert( const float& i, float& o ) { o = i; }
00219    
00220 
00221    
00222    
00227    class AudioFormat
00228    {
00229    public:
00230       enum Packing
00231       {
00232          INTERLACED
00233       };
00234 
00235       enum SampleType
00236       {
00237          UNSIGNED8, SIGNED8,
00238          UNSIGNED16, SIGNED16,
00239          FLOAT32 // FLOAT64 unsupported for now..
00240       };
00241       
00243       AudioFormat( SampleType dt = FLOAT32, int chan = 1, int sampRate = 44100 ) : samplingRateHz( sampRate ),
00244                       channels( chan ),
00245                       datatype( dt )
00246       {
00247       }
00248       
00252       void copy( const AudioFormat& af )
00253       {
00254          samplingRateHz = af.samplingRateHz;
00255          channels = af.channels; 
00256          datatype = af.datatype;
00257       }
00258 
00260       AudioFormat( const AudioFormat& af )
00261       {
00262          this->copy( af );
00263       }
00264             
00266       const AudioFormat& operator=( const AudioFormat& af )
00267       {
00268          this->copy( af );
00269          return *this;
00270       }
00271       
00273       bool operator==( const AudioFormat& af ) const
00274       {
00275          if (af.channels == this->channels &&
00276              af.datatype == this->datatype &&
00277              af.samplingRateHz == this->samplingRateHz)
00278          {
00279             return true;
00280          } 
00281          return false;
00282       }
00283 
00285       bool operator!=( const AudioFormat& af ) const 
00286       {
00287          return !this->operator==( af );
00288       }
00289       
00291       inline int sampsize() const
00292       {
00293          switch (datatype)
00294          {
00295          case UNSIGNED8: case SIGNED8:
00296             return 1;
00297          case UNSIGNED16: case SIGNED16:
00298             return 2;
00299          case FLOAT32:
00300             return 4;
00301          default:
00302             std::cout << "error: sampsize==" << datatype << std::endl;
00303             assert( false && "unknown sampsize" );
00304             return 0;
00305          }
00306       }
00307       
00310       int         samplingRateHz;// 44100, 22050
00311       
00316       int         channels;      // 1 == mono, 2 == stereo, 4 == quad, 8 == oct
00317 
00321       SampleType  datatype;
00322    };
00323 
00324 
00328    inline void* new_audio_data( const AudioFormat& fmt, int samples )
00329    {
00330       char* bok = new char[samples * fmt.channels * fmt.sampsize()];
00331       return (void*)bok;
00332    }
00333 
00335    inline void delete_audio_data( void* d )
00336    {
00337       delete[] (char*)d;
00338    }
00339 
00343    template <typename in, typename out>
00344    inline void size_calculator( const unsigned int& srcbytes, unsigned int& destbytes )
00345    {
00346       const float in_bytes = (float)audio_data_traits<in>::bytes();
00347       const float out_bytes = (float)audio_data_traits<out>::bytes();
00348       const float scale = in_bytes / out_bytes;
00349       destbytes = (unsigned int) (((float)srcbytes) * scale);
00350    }
00351 
00354    inline void size_calculator( const AudioFormat& srcfmt, AudioFormat destfmt, const unsigned int& srcbytes, unsigned int& destbytes )
00355    {
00356       const float in_bytes = (float)srcfmt.sampsize();
00357       const float out_bytes = (float)destfmt.sampsize();
00358       const float scale = in_bytes / out_bytes;
00359       destbytes = (unsigned int) (((float)srcbytes) * scale);
00360    }
00361    
00363    inline void bytes_calculator( AudioFormat fmt, const unsigned int& samples, unsigned int& destbytes )
00364    {
00365       destbytes = samples * fmt.sampsize();
00366    }
00367 
00373    inline bool audio_channels_convert( const AudioFormat& srcfmt, 
00374                                        const AudioFormat& destfmt, 
00375                                        const void* srcdata, 
00376                                        const int samples, 
00377                                        void* destdata, int& destsamples )
00378    {
00379       destsamples = samples;
00380       assert( destfmt.sampsize() == srcfmt.sampsize() );
00381       int item_size = srcfmt.sampsize();
00382             
00383       // nothing to do
00384       if (srcfmt.channels == destfmt.channels)
00385          return false;
00386       
00387       // split
00388       const char* srcptr = (const char*)srcdata;
00389       char* destptr = (char*)destdata;
00390       if (srcfmt.channels == 1 && destfmt.channels == 2)
00391       {
00392          destsamples = samples * 2;
00393          for (int x = 0; x < samples * item_size; x += item_size)
00394          {
00395             memcpy( &destptr[x * destfmt.channels], &srcptr[x * srcfmt.channels], item_size );
00396             memcpy( &destptr[x * destfmt.channels + item_size], &srcptr[x * srcfmt.channels], item_size );
00397          }
00398       }      
00399       // mixdown
00400       else if (srcfmt.channels == 2 && destfmt.channels == 1)
00401       {
00402          destsamples = samples / 2;
00403          for (int x = 0; x < samples * item_size; x += item_size)
00404          {
00405             // fast mixdown (throw out one channel), rewrite this to also support the correct one...
00406             memcpy( &destptr[x * destfmt.channels], &srcptr[x * srcfmt.channels], item_size );
00407          }
00408       }
00409       return true;
00410    }
00411    
00415    inline bool audio_samprate_convert( const AudioFormat& srcfmt, 
00416                             const AudioFormat& destfmt, 
00417                             const void* srcdata, 
00418                             const int samples, 
00419                             void* destdata ) 
00420    {return false;}
00421    
00426    template< typename t, int stride >
00427    inline const t* audio_iterate( const t* data, int x )
00428    {
00429       return &data[x * stride];
00430    }   
00431    
00432    inline const char* audio_iterate( const char* data, const AudioFormat& fmt, int x )
00433    {
00434       return &data[x * fmt.channels * fmt.sampsize()];
00435    }
00436    
00440    inline bool audio_format_convert( const AudioFormat& srcfmt, 
00441                             const AudioFormat& destfmt, 
00442                             const void* srcdata, 
00443                             const int samples, 
00444                             void* destdata )
00445    {
00446       const AudioFormat::SampleType& srctype = srcfmt.datatype;
00447       const AudioFormat::SampleType& desttype = destfmt.datatype;
00448       
00449       assert( srcfmt.samplingRateHz == destfmt.samplingRateHz 
00450          && "no rate conversion right now sorry." );
00451       assert( srcfmt.channels == destfmt.channels
00452          && "channels gotta be the same, sorry..." );
00453       
00454       int x;
00455       switch (srctype)
00456       {
00457       case AudioFormat::UNSIGNED8:
00458          switch (desttype)
00459          {
00460          case AudioFormat::UNSIGNED8:
00461             for (x = 0; x < samples; ++x)
00462                audio_convert( ((unsigned char*)srcdata)[x], ((unsigned char*)destdata)[x] );
00463             break;
00464          case AudioFormat::SIGNED8:
00465             for (x = 0; x < samples; ++x)
00466                audio_convert( ((unsigned char*)srcdata)[x], ((signed char*)destdata)[x] );
00467             break;
00468          case AudioFormat::UNSIGNED16:
00469             for (x = 0; x < samples; ++x)
00470                audio_convert( ((unsigned char*)srcdata)[x], ((unsigned short*)destdata)[x] );
00471             break;
00472          case AudioFormat::SIGNED16:
00473             for (x = 0; x < samples; ++x)
00474                audio_convert( ((unsigned char*)srcdata)[x], ((signed short*)destdata)[x] );
00475             break;
00476          case AudioFormat::FLOAT32:
00477             for (x = 0; x < samples; ++x)
00478                audio_convert( ((unsigned char*)srcdata)[x], ((float*)destdata)[x] );
00479             break;
00480          }
00481          break;
00482       case AudioFormat::SIGNED8:
00483          switch (desttype)
00484          {
00485          case AudioFormat::UNSIGNED8:
00486             for (x = 0; x < samples; ++x)
00487                audio_convert( ((signed char*)srcdata)[x], ((unsigned char*)destdata)[x] );
00488             break;
00489          case AudioFormat::SIGNED8:
00490             for (x = 0; x < samples; ++x)
00491                audio_convert( ((signed char*)srcdata)[x], ((signed char*)destdata)[x] );
00492             break;
00493          case AudioFormat::UNSIGNED16:
00494             for (x = 0; x < samples; ++x)
00495                audio_convert( ((signed char*)srcdata)[x], ((unsigned short*)destdata)[x] );
00496             break;
00497          case AudioFormat::SIGNED16:
00498             for (x = 0; x < samples; ++x)
00499                audio_convert( ((signed char*)srcdata)[x], ((signed short*)destdata)[x] );
00500             break;
00501          case AudioFormat::FLOAT32:
00502             for (x = 0; x < samples; ++x)
00503                audio_convert( ((signed char*)srcdata)[x], ((float*)destdata)[x] );
00504             break;
00505          }
00506          break;
00507       case AudioFormat::UNSIGNED16:
00508          switch (desttype)
00509          {
00510          case AudioFormat::UNSIGNED8:
00511             for (x = 0; x < samples; ++x)
00512                audio_convert( ((unsigned short*)srcdata)[x], ((unsigned char*)destdata)[x] );
00513             break;
00514          case AudioFormat::SIGNED8:
00515             for (x = 0; x < samples; ++x)
00516                audio_convert( ((unsigned short*)srcdata)[x], ((signed char*)destdata)[x] );
00517             break;
00518          case AudioFormat::UNSIGNED16:
00519             for (x = 0; x < samples; ++x)
00520                audio_convert( ((unsigned short*)srcdata)[x], ((unsigned short*)destdata)[x] );
00521             break;
00522          case AudioFormat::SIGNED16:
00523             for (x = 0; x < samples; ++x)
00524                audio_convert( ((unsigned short*)srcdata)[x], ((signed short*)destdata)[x] );
00525             break;
00526          case AudioFormat::FLOAT32:
00527             for (x = 0; x < samples; ++x)
00528                audio_convert( ((unsigned short*)srcdata)[x], ((float*)destdata)[x] );
00529             break;
00530          }
00531          break;
00532       case AudioFormat::SIGNED16:
00533          switch (desttype)
00534          {
00535          case AudioFormat::UNSIGNED8:
00536             for (x = 0; x < samples; ++x)
00537                audio_convert( ((signed short*)srcdata)[x], ((unsigned char*)destdata)[x] );
00538             break;
00539          case AudioFormat::SIGNED8:
00540             for (x = 0; x < samples; ++x)
00541                audio_convert( ((signed short*)srcdata)[x], ((signed char*)destdata)[x] );
00542             break;
00543          case AudioFormat::UNSIGNED16:
00544             for (x = 0; x < samples; ++x)
00545                audio_convert( ((signed short*)srcdata)[x], ((unsigned short*)destdata)[x] );
00546             break;
00547          case AudioFormat::SIGNED16:
00548             for (x = 0; x < samples; ++x)
00549                audio_convert( ((signed short*)srcdata)[x], ((signed short*)destdata)[x] );
00550             break;
00551          case AudioFormat::FLOAT32:
00552             for (x = 0; x < samples; ++x)
00553                audio_convert( ((signed short*)srcdata)[x], ((float*)destdata)[x] );
00554             break;
00555          }
00556          break;
00557       case AudioFormat::FLOAT32:
00558          switch (desttype)
00559          {
00560          case AudioFormat::UNSIGNED8:
00561             for (x = 0; x < samples; ++x)
00562                audio_convert( ((float*)srcdata)[x], ((unsigned char*)destdata)[x] );
00563             break;
00564          case AudioFormat::SIGNED8:
00565             for (x = 0; x < samples; ++x)
00566                audio_convert( ((float*)srcdata)[x], ((signed char*)destdata)[x] );
00567             break;
00568          case AudioFormat::UNSIGNED16:
00569             for (x = 0; x < samples; ++x)
00570                audio_convert( ((float*)srcdata)[x], ((unsigned short*)destdata)[x] );
00571             break;
00572          case AudioFormat::SIGNED16:
00573             for (x = 0; x < samples; ++x)
00574                audio_convert( ((float*)srcdata)[x], ((signed short*)destdata)[x] );
00575             break;
00576          case AudioFormat::FLOAT32:
00577             for (x = 0; x < samples; ++x)
00578                audio_convert( ((float*)srcdata)[x], ((float*)destdata)[x] );
00579             break;
00580          }
00581          break;
00582       }
00583 
00584       return true;
00585    }
00586    
00590    inline bool audio_convert( const AudioFormat& srcfmt, 
00591                             const AudioFormat& destfmt, 
00592                             const void* srcdata, 
00593                             const int samples, 
00594                             void* destdata, int& destsamples )
00595    {
00596       // do channel conversion if needed...
00597       AudioFormat temp_fmt;
00598       const char* channel_convert_temp_buffer = NULL;
00599       std::vector<char> mChannelConvertTempBuffer; // move this !  very bad to allocate this here...
00600       if (srcfmt.channels != destfmt.channels)
00601       {
00602          temp_fmt = srcfmt;
00603          temp_fmt.channels = destfmt.channels;
00604          unsigned int bytes;
00605          bytes_calculator( temp_fmt, samples * temp_fmt.channels, bytes );
00606          if (mChannelConvertTempBuffer.size() < bytes) // only grow it... (prevent thrashing)
00607             mChannelConvertTempBuffer.resize( bytes );
00608 
00609          audio_channels_convert( srcfmt, temp_fmt, srcdata, samples, &mChannelConvertTempBuffer[0], destsamples );
00610          channel_convert_temp_buffer = &mChannelConvertTempBuffer[0];
00611       }
00612       else
00613       {
00614          temp_fmt = srcfmt;
00615          channel_convert_temp_buffer = (const char*)srcdata;
00616          destsamples = samples;
00617       }   
00618       
00619       // do format conversion if needed
00620       assert( temp_fmt.channels == destfmt.channels );
00621       return audio_format_convert( temp_fmt, destfmt, channel_convert_temp_buffer, destsamples, destdata );
00622    }
00623 
00628    template <class type>
00629    type audio_clamp( const type& t )
00630    {
00631       if (t > audio_data_traits<type>::max())
00632          return audio_data_traits<type>::max();
00633       else if (t < audio_data_traits<type>::min())
00634          return audio_data_traits<type>::min();
00635       
00636       return t;
00637    }
00638       
00639 } // end namespace
00640 
00641 
00642 #endif

Generated at Mon Apr 15 09:26:08 2002 for subsynth by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001