Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

playback_stream.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: playback_stream.cpp,v 1.1 2001/03/06 15:09:25 mbn Exp $
00003 
00004         ------------------------------------------------------------------------
00005         ClanLib, the platform independent game SDK.
00006 
00007         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00008         version 2. See COPYING for details.
00009 
00010         For a total list of contributers see CREDITS.
00011 
00012         ------------------------------------------------------------------------
00013 
00014         File purpose:
00015                 Sound card impl. that uses the ClanSound library.
00016 
00017 */
00018 
00019 #ifdef WIN32
00020 #pragma warning (disable:4786)
00021 #endif
00022 
00023 #ifdef USE_CLANSOUND
00024 
00025 #include <API/Core/System/mutex.h>
00026 #include <API/Sound/stream_soundprovider.h>
00027 #include "API/Core/System/cl_assert.h"
00028 #include <Sound/Sound/ClanSound/cardplayback_clan.h>
00029 #include <Sound/Sound/ClanSound/playback_stream.h>
00030 #include <Sound/Sound/ClanSound/soundcard_clan.h>
00031 
00032 CL_Playback_Stream::CL_Playback_Stream(
00033         CL_SoundCard_ClanSound *card,
00034         CL_StreamSoundProvider *_provider,
00035         CL_SoundBuffer_Generic *owner)
00036 : CL_CardPlayback_ClanSound(card)
00037 {
00038         this->owner = owner;
00039         provider = _provider;
00040         provider_session = provider->begin_session();
00041         
00042         frequency = provider_session->get_frequency();
00043         volume = 256;
00044 
00045         format = provider_session->get_format();
00046         pos = 0;
00047         playing = false;
00048         filled_pos = 0;
00049         first_time = true;
00050         
00051         buffer_size = frequency/4;
00052         ring_buffer = new short[buffer_size*2];
00053         stream_eof = false;
00054 
00055         card->add(this);
00056 }
00057 
00058 CL_Playback_Stream::~CL_Playback_Stream()
00059 {
00060         card->remove(this);
00061 
00062         delete[] ring_buffer;
00063         provider->end_session(provider_session);
00064 }
00065 
00066 void CL_Playback_Stream::keep_alive()
00067 {
00068         int bytes_wanted = ask_update();
00069         if (bytes_wanted == 0) return;
00070 
00071         char *copy_buffer = new char[bytes_wanted];
00072         int bytes_given = provider_session->get_data(copy_buffer, bytes_wanted);
00073 
00074         if (bytes_given > 0) update(copy_buffer, bytes_given);
00075         delete[] copy_buffer;
00076         
00077         if (provider_session->eof())
00078         {
00079                 stream_eof = true;
00080                 playing = false;
00081         }
00082 }
00083 
00084 int CL_Playback_Stream::get_position()
00085 {
00086         return (int) pos;
00087 }
00088 
00089 float CL_Playback_Stream::get_position_relative()
00090 {
00091         return pos / get_length();
00092 }
00093 
00094 bool CL_Playback_Stream::set_position_relative(float new_pos)
00095 {
00096         return set_position((int) (new_pos * get_length()));
00097 }
00098 
00099 int CL_Playback_Stream::get_length()
00100 {
00101         return -1;
00102 }
00103 
00104 int CL_Playback_Stream::get_frequency()
00105 {
00106         return frequency;
00107 }
00108 
00109 bool CL_Playback_Stream::set_frequency(int new_freq)
00110 {
00111         frequency = new_freq;
00112         return true;
00113 }
00114 
00115 float CL_Playback_Stream::get_volume()
00116 {
00117         return volume;
00118 }
00119 
00120 bool CL_Playback_Stream::set_volume(float new_volume)
00121 {
00122         volume = new_volume;
00123         return true;
00124 }
00125 
00126 float CL_Playback_Stream::get_pan()
00127 {
00128         return pan;
00129 }
00130 
00131 bool CL_Playback_Stream::set_pan(float new_pan)
00132 {
00133         pan = new_pan;
00134         return true;
00135 }
00136 
00137 void CL_Playback_Stream::set_looping(bool looping)
00138 {
00139         static bool warning = true;
00140 
00141         if (warning)
00142         {
00143                 cl_info(info_sound, "Not implemented yet.");
00144                 warning = false;
00145         }
00146 }
00147 
00148 bool CL_Playback_Stream::get_looping()
00149 {
00150         return false;
00151 }
00152 
00153 void CL_Playback_Stream::play()
00154 {
00155         playing = true;
00156 }
00157 
00158 void CL_Playback_Stream::stop()
00159 {
00160         playing = false;
00161 }
00162 
00163 bool CL_Playback_Stream::is_playing()
00164 {
00165         return playing;
00166 }
00167 
00168 bool CL_Playback_Stream::set_position(int new_pos)
00169 {
00170         if (provider_session->set_position(new_pos))
00171         {
00172                 flush();
00173                 return true;
00174         }
00175         
00176         return false;
00177 }
00178 
00179 void CL_Playback_Stream::flush()
00180 {
00181 }
00182 
00183 void CL_Playback_Stream::get_playback_data(int *data, int num_samples)
00184 {
00185         int i;
00186         int freq = frequency;
00187         int vol = (int) (volume*128);
00188 
00189         if (freq == 0 || vol == 0)
00190         {
00191                 memset(data, 0, num_samples*sizeof(int)*2);
00192                 return;
00193         }
00194 
00195         double speed = freq/(double) 22050;
00196 
00197 /*
00198         int samples_available = (int) (get_samples_available()*speed);
00199         if (num_samples > samples_available) // clear the rest of the buffer
00200         {
00201                 memset(&data[samples_available], 0, num_samples-samples_available);
00202                 num_samples = samples_available;
00203                 
00204                 if (stream_eof) playing = false; // reached end of stream.
00205         }
00206 */
00207 
00208         // pos is volatile, so we make a copy of it to make the compiler optimize better.
00209         double cached_pos = pos;
00210         int *ptr = data;
00211         for (i=0; i<num_samples; i++)
00212         {
00213                 int cur_pos = (int) cached_pos;
00214 
00215                 if (cur_pos == filled_pos) // out of data. fill with zeroes until we get some.
00216                 {
00217                         ring_buffer[cur_pos*2+0] = 0;
00218                         ring_buffer[cur_pos*2+1] = 0;
00219                         continue;
00220                 }
00221 
00222                 if (cur_pos < buffer_size)
00223                 {
00224                         *(ptr++) = ring_buffer[cur_pos*2+0];
00225                         *(ptr++) = ring_buffer[cur_pos*2+1];
00226                 }
00227 
00228                 cached_pos += speed;
00229                 if (cur_pos != (int) cached_pos)
00230                 {
00231                         ring_buffer[cur_pos*2+0] = 0;
00232                         ring_buffer[cur_pos*2+1] = 0;
00233                 }
00234 
00235                 if (cached_pos >= buffer_size) cached_pos -= buffer_size;
00236         }
00237         pos = cached_pos;
00238 
00239 //      if (num_samples >= samples_available) pos = filled_pos; // reached end of buffer
00240 
00241         // apply volume and panning:
00242         ptr = data;
00243         int left_pan = int (128-pan*128);
00244         int right_pan = int (128+pan*128);
00245         if (left_pan < 0) left_pan = 0;
00246         if (left_pan > 128) left_pan = 128;
00247         if (right_pan < 0) right_pan = 0;
00248         if (right_pan > 128) right_pan = 128;
00249 
00250         for (i=0; i<num_samples; i++)
00251         {
00252                 // left channel:
00253                 (*ptr) = (*ptr)*vol*left_pan/16384; ptr++;
00254                         
00255                 // right channel:
00256                 (*ptr) = (*ptr)*vol*right_pan/16384; ptr++;
00257         }
00258 }
00259 
00260 void CL_Playback_Stream::mix_to(int *data, int num_samples)
00261 {
00262         if (playing == false) return;
00263 
00264         static int temp[16*1024*2];
00265 
00266         for (int i=0; i<num_samples; i+=16*1024)
00267         {
00268                 int size = num_samples-i;
00269                 if (size > 16*1024) size = 16*1024;
00270                 
00271                 get_playback_data(temp, size);
00272                 filter(temp, size);
00273                 int k = i*2;
00274                 for (int j=0; j<size*2; j++) data[k+j] += temp[j];
00275         }
00276 }
00277 
00278 int CL_Playback_Stream::get_samples_available()
00279 {
00280         if (pos < filled_pos) return (int) (pos+(buffer_size-filled_pos));
00281         if (pos > filled_pos) return (int) (filled_pos - pos);
00282 
00283         return 0;
00284 }
00285 
00286 int CL_Playback_Stream::ask_update()
00287 {
00288 //      CL_MutexSection(card->get_mutex());
00289 
00290         int _filled_pos = filled_pos;
00291         int _pos = (int) pos;
00292 
00293         int space_left = buffer_size;
00294         
00295         if (_pos < _filled_pos) space_left = (int) (buffer_size-_filled_pos+_pos);
00296         if (_pos > _filled_pos) space_left = (int) (_pos-_filled_pos);
00297 
00298 //      std::cout << "read: " << _pos << ", write: " << _filled_pos << ", space left: " << space_left << std::endl;
00299 
00300         space_left -= 16;
00301         if (space_left <= buffer_size/5) return 0; // only fill if more than 20% of buffer is empty.
00302 
00303         switch (format)
00304         {
00305         case sf_8bit_signed:
00306                 break;
00307         
00308         case sf_8bit_signed_stereo:
00309         case sf_16bit_signed:
00310                 space_left *= 2;
00311                 break;
00312                 
00313         case sf_16bit_signed_stereo:
00314                 space_left *= 4;
00315                 break;
00316                 
00317         default:
00318                 cl_assert(false);
00319         }
00320         
00321         return space_left;
00322 }
00323 
00324 int CL_Playback_Stream::update(void *data, int data_size)
00325 {
00326 //      CL_MutexSection(card->get_mutex());
00327 
00328         if (first_time)
00329         {
00330                 first_time = false;
00331                 filled_pos = (int) pos;
00332         }
00333 
00334         int num_samples = data_size;
00335         int sample_size=0;
00336 
00337         switch (format)
00338         {
00339         case sf_8bit_signed:
00340                 sample_size = 1;
00341                 break;
00342         
00343         case sf_8bit_signed_stereo:
00344         case sf_16bit_signed:
00345                 sample_size = 2;
00346                 break;
00347                 
00348         case sf_16bit_signed_stereo:
00349                 sample_size = 4;
00350                 break;
00351                 
00352         default:
00353                 cl_assert(false);
00354         }
00355         
00356         num_samples /= sample_size;
00357 
00358         if (filled_pos+num_samples > buffer_size) // exceeds end of ring buffer
00359         {
00360                 char *_data = (char *) data;
00361 
00362                 int fill_length = buffer_size - filled_pos;
00363         
00364                 update_format(filled_pos, fill_length, data);
00365                 update_format(0, num_samples - fill_length, _data+fill_length*sample_size);
00366                 
00367                 filled_pos = num_samples - fill_length;
00368         }
00369         else
00370         {
00371                 update_format(filled_pos, num_samples, data);
00372                 filled_pos += num_samples;
00373         }
00374 
00375         return 0;
00376 }
00377 
00378 void CL_Playback_Stream::update_format(int pos, int num_samples, void *data)
00379 {
00380         switch (format)
00381         {
00382         case sf_8bit_signed:
00383                 {
00384                         unsigned char *input_c = (unsigned char *) data;
00385                         for (int i=0; i<num_samples; i++)
00386                         {
00387                                 ring_buffer[(pos+i)*2+0] = input_c[i];
00388                                 ring_buffer[(pos+i)*2+1] = input_c[i];
00389                         }
00390                 }
00391                 break;
00392         
00393         case sf_8bit_signed_stereo:
00394                 {
00395                         unsigned char *input_c = (unsigned char *) data;
00396                         for (int i=0; i<num_samples; i++)
00397                         {
00398                                 ring_buffer[(pos+i)*2+0] = input_c[i*2+0];
00399                                 ring_buffer[(pos+i)*2+1] = input_c[i*2+1];
00400                         }
00401                 }
00402                 break;
00403 
00404         case sf_16bit_signed:
00405                 {
00406                         short *input_s = (short *) data;
00407                         for (int i=0; i<num_samples; i++)
00408                         {
00409                                 ring_buffer[(pos+i)*2+0] = input_s[i];
00410                                 ring_buffer[(pos+i)*2+1] = input_s[i];
00411                         }
00412                 }
00413                 break;
00414                 
00415         case sf_16bit_signed_stereo:
00416                 {
00417                         short *input_s = (short *) data;
00418                         for (int i=0; i<num_samples; i++)
00419                         {
00420                                 ring_buffer[(pos+i)*2+0] = input_s[i*2+0];
00421                                 ring_buffer[(pos+i)*2+1] = input_s[i*2+1];
00422                         }
00423                 }
00424                 break;
00425                 
00426         default:
00427                 cl_assert(false);
00428         }
00429 }
00430 
00431 #endif

Generated at Wed Apr 4 19:54:02 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001