1 /* === S Y N F I G ========================================================= */
2 /*! \file audiocontainer.cpp
3 ** \brief Audio Container implementation File
5 ** $Id: audiocontainer.cpp,v 1.1.1.1 2005/01/07 03:34:35 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
32 #include <sigc++/signal.h>
34 #include <ETL/stringf>
36 //#include <ETL/thread>
37 #include <glibmm/thread.h>
39 #include <synfig/general.h>
41 #include <glibmm/main.h>
43 #include "audiocontainer.h"
58 /* === U S I N G =========================================================== */
62 using namespace synfig;
64 /* === M A C R O S ========================================================= */
67 #define AUDIO_OUTPUT FSOUND_OUTPUT_OSS
70 /* === G L O B A L S ======================================================= */
71 const double delay_factor = 3;
73 /* === P R O C E D U R E S ================================================= */
75 /* === M E T H O D S ======================================================= */
77 /* === E N T R Y P O I N T ================================================= */
79 //Help constructing stuff
81 using studio::AudioContainer;
83 bool build_profile(FSOUND_SAMPLE *sample, double &samplerate, std::vector<char> &samples)
87 float sps = samplerate;
89 //trivial rejection...
90 if(!sample || sps < 1)
92 synfig::warning("build_profile: Sample rate was too low or sample was invalid");
96 //lock for all samples and process them into a subset
97 unsigned int mode = FSOUND_Sample_GetMode(sample);
99 //make sure that it's 8 bit... I hope this works...
101 //sample rate of the actual song...
102 int allsamplerate = 0;
103 FSOUND_Sample_GetDefaults(sample,&allsamplerate,0,0,0);
105 //get the size of the sample defaults from the mode
107 int channelsize = 1; //number of bytes
109 if(mode & FSOUND_16BITS) channelsize = 2; //this shouldn't happen
110 if(mode & FSOUND_STEREO) channels = 2;
112 //Get the sample information
113 int samplesize = channels*channelsize; //the only two things that increase samplesize
114 int numsamples = FSOUND_Sample_GetLength(sample); //number of samples in the sound
115 int sizeall = samplesize*numsamples; //should be the size of the entire song...
119 synfig::warning("ProfileAudio: Sample buffer cannot be size smaller than 1 (%X)",FSOUND_GetError());
123 //be sure that the new sample rate is less than or equal to the original
124 if(sps > allsamplerate) sps = allsamplerate;
126 float stride = allsamplerate/(float)sps;
128 //down sampling to 8 bit min/max values
129 synfig::warning("About to downsample from %d Hz to %.1f Hz, sample stride: %f", allsamplerate, sps, stride);
131 char *sampledata=0,*useless = 0;
132 unsigned int len1,len2;
133 // vector<char> samples;
135 if(!FSOUND_Sample_Lock(sample,0,sizeall,(void**)&sampledata,(void**)&useless,&len1,&len2))
137 synfig::warning("ProfileAudio: Unable to lock the sound buffer... (%X)",FSOUND_GetError());
140 synfig::warning("Locked: %X: %d bytes, %X: %d bytes",sampledata,len1,useless,len2);
145 char *iter = sampledata;
146 char *end = iter + sizeall;
149 float numinc = sps/(float)allsamplerate;
151 /* Loop per sample DDA alg.
156 //HACK - to prevent if statement inside inner loop
157 //synfig::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
160 int maxs = 0, mins = 0;
162 for(;curaccum < 1; curaccum += numinc)
164 for(i = 0; iter < end && i < channels; ++i, iter += channelsize)
166 maxs = std::max(maxs,(int)*iter);
167 mins = std::min(mins,(int)*iter);
170 //insert onto new list
171 samples.push_back(maxs);
172 samples.push_back(mins);
174 //and flush all the used samples for curaccum
177 }else if(channelsize == 2)
180 char *iter = sampledata;
181 char *end = iter + sizeall;
184 float numinc = sps/(float)allsamplerate;
186 /* Loop per sample DDA alg.
191 //HACK - to prevent if statement inside inner loop
192 //synfig::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
195 int maxs = 0, mins = 0;
197 for(;curaccum < 1; curaccum += numinc)
199 for(i = 0; iter < end && i < channels; ++i, iter += channelsize)
201 maxs = std::max(maxs,(int)*(short*)iter);
202 mins = std::min(mins,(int)*(short*)iter);
205 //insert onto new list
206 samples.push_back(maxs / 256);
207 samples.push_back(mins / 256);
209 //and flush all the used samples for curaccum
215 synfig::warning("Stats: %f seconds with %d bytes now %d bytes", (samples.size()/2)/sps, sizeall, samples.size());
216 synfig::warning(" %f seconds before", numsamples/(float)allsamplerate);
218 //we're done yay!, unlock
219 FSOUND_Sample_Unlock(sample,sampledata,useless,len1,len2);
220 synfig::info("Unlocked");
222 //FSOUND_PlaySound(FSOUND_FREE,sound); //test
225 samplerate = sps*2; //it must be x2 because we are sampling max and min
237 //FMOD Systemwide Specific data mostly here...
242 static double buffer_length_sec = 0;
244 //------- Scrubbing --------------
245 /* Scrubbing works as follows:
247 The sound is played using PlaySoundEx
248 we specify a user created DSP for scrubbing
249 set it initially to inactive
251 When the program initiates it
252 we set the initial data in the shared structure and activate the dsp unit
253 then for each cursor update we get we set the value in the shared structure
257 If IsPlaying just governs the channel play/stop value or if it also concerns the pause state
261 //so we can know where to create all this stuff
264 /* Linearly fit the frequency to hit the desired zero point...
266 /*struct scrubelement
270 //the amount of time left til the cursor hits this one
271 // it's incremental so that the cursor must pass previous
272 // ones before decrementing this value
276 //the time it should take to get to the next position...
278 //to prevent from writing to the same location at once... (pos, deltatime, delaystart)
281 //the queue system would provide a more accurate representation...
283 volatile double deltatime;
285 volatile double delaystart; //the amount of time we need to go before we start interpolating...
287 volatile int channel;
289 /*std::list<scrubelement> queue;
291 volatile int channel;
293 //current position is FSOUND_GetCurrentPosition and current time is always 0...
295 void add(const scrubelement &elem)
299 queue.push_back(elem);
304 //Function to safely get rid of all the old samples (dt < 0)
309 while(queue.size() && queue.front().dt < 0)
327 //All parameters and state should be set by the time we get here...
328 void scrub_dsp_process()
330 const double epsilon = 1e-5;
332 //Trivial reject... we go nowhere if we aren't playing (hit boundary...)
333 if(!FSOUND_IsPlaying(channel)) return;
335 //Get rid of all the old samples
338 //Trivial reject #2 - We also go nowhere with no future samples (pause)
339 /*if(queue.size() <= 0)
341 FSOUND_SetPaused(channel,true);
345 double dt = buffer_length_sec;
347 //Lock ourselves so we don't die
350 //printf("DSP data: delay = %.3f s, pos = %d, dt = %.3f\n", delaystart, (int)pos, deltatime);
359 dt = -delaystart; //add time back...
364 //Trivial reject for if we're past current sample...
365 if(delaystart > 0 || deltatime <= 0)
367 FSOUND_SetPaused(channel,true);
372 //Calculate stretched frequency based on delayed future sample...
374 //NOTE: BY NOT TRACKING POSITION AS A FLOAT AND JUST USING THE SOUNDS VALUE
375 // WE ARE LOSING A TINY AMOUNT OF PRECISION ACCURACY EVERY UPDATE
376 // (THIS SHOULDN'T BE A PROBLEM)
377 const double p0 = FSOUND_GetCurrentPosition(channel);
380 if(!FSOUND_GetPaused(channel))
382 curdp = FSOUND_GetFrequency(channel) * deltatime;
385 //need to rescale derivative...
387 //Extrapolate from difference in position and deltatime vs dt...
388 const double pa = p0 + curdp/2;
390 const double p1 = pos;
392 //const double pb = p0/3 + p1*2/3;
394 //will extrapolate if needed... (could be funky on a curve)
396 if(deltatime > epsilon)
401 //Decrement deltatime (we may have gone past but that's what happens when we don't get input...)
404 //we don't need to look at the current variables anymore...
407 const double invt = 1-t;
408 //double deltapos = (p1-p0)*t; //linear version
409 double deltapos = invt*invt*p0 + 2*t*invt*pa + t*t*p1 - p0; //quadratic smoothing version
411 //Attempted cubic smoothing
412 //const double invt2 = invt*invt;
413 //const double t2 = t*t;
414 //double deltapos = invt2*invt*p0 + 3*t*invt2*pa + 3*t2*invt*pb + t2*t*p1;
415 //double deltapos = p0 + t*(3*(pa-p0) + t*(3*(p0+2*pa+pb) + t*((p1-3*pb+3*ba-p0)))); //unwound cubic
417 //printf("\ttime = %.2f; p(%d,%d,%d) dp:%d - delta = %d\n",t,(int)p0,(int)p1,(int)p2,(int)curdp,(int)deltapos);
419 //Based on the delta info calculate the stretched frequency
420 const int dest_samplesize = FSOUND_DSP_GetBufferLength();
422 //rounded to nearest frequency... (hopefully...)
423 int freq = (int)(deltapos * FSOUND_GetOutputRate() / (double)dest_samplesize);
425 //NOTE: WE MIGHT WANT TO DO THIS TO BE MORE ACCURATE BUT YEAH... ISSUES WITH SMALL NUMBERS
426 //double newdp = deltapos / t;
428 //printf("\tfreq = %d Hz\n", freq);
430 // !If I failed... um assume we have to pause it... ?
433 FSOUND_SetPaused(channel,true);
436 //synfig::info("DSP f = %d Hz", freq);
437 FSOUND_SetPaused(channel,false);
438 if(!FSOUND_SetFrequency(channel,freq))
440 //ERROR WILL ROBINSON!!!...
441 printf("Error in Freq... what do I do?\n");
449 /* //for use with multiple
450 //each one is a 'handle' to a pointer that will be effected by something else
451 typedef scrubinfo** value_type;
452 typedef std::set< value_type > scrubslist;
455 //so we can lock access to the list...
458 void AddScrub(scrubinfo **i)
465 void RemoveScrub(scrubinfo **i)
472 scrubinfo * volatile * scrub;
475 //Scrubbing data structures
476 static const int default_scrub_priority = 5; //between clear and sfx/music mix
477 static scrubuserdata g_scrubdata = {0};
478 static FSOUND_DSPUNIT *scrubdspunit = 0;
480 void * scrubdspwrap(void *originalbuffer, void *newbuffer, int length, void *userdata)
482 //std::string dsp = "DSP";
485 scrubuserdata &sd = *(scrubuserdata*)userdata;
487 /* //For use with multiple scrubs...
488 //Lock so no one can write to it while we're reading from it...
491 //make a copy of it...
492 std::vector<scrubinfo**> v(sd.scrubs.begin(),sd.scrubs.end());
494 //other things can do stuff with it again...
495 sd.lock.UnLockRead();
497 //loop through the list and process all the active scrub units
498 std::vector<scrubinfo**>::iterator i = v.begin(),
502 //check to make sure this object is active...
505 (**i)->scrub_dsp_process();
510 if(sd.scrub && *sd.scrub)
512 //dsp += " processing...";
513 scrubinfo * info = (*sd.scrub);
514 info->scrub_dsp_process();
523 //------- Class for loading fmod on demand -------
525 class FMODInitializer
531 FMODInitializer():loaded(false),refcount(0) {}
542 synfig::info("Initializing FMOD on demand...");
545 FSOUND_SetOutput(AUDIO_OUTPUT);
547 /*int numdrivers = FSOUND_GetNumDrivers();
548 synfig::info("Num FMOD drivers = %d",numdrivers);
549 synfig::info("Current Driver is #%d", FSOUND_GetDriver());
551 for(int i = 0; i < numdrivers; ++i)
553 unsigned int caps = 0;
554 FSOUND_GetDriverCaps(i,&caps);
556 synfig::info(" Caps for driver %d (%s) = %x",i,FSOUND_GetDriverName(i),caps);
559 FSOUND_SetDriver(0);*/
561 //Modify buffer size...
562 //FSOUND_SetBufferSize(100);
564 if(!FSOUND_Init(44100, 32, 0))
566 synfig::warning("Unable to load FMOD");
571 //Create the DSP for processing scrubbing...
572 scrubdspunit = FSOUND_DSP_Create(&scrubdspwrap,default_scrub_priority,&g_scrubdata);
574 //Load the number of sec per buffer into the global variable...
575 buffer_length_sec = FSOUND_DSP_GetBufferLength() / (double)FSOUND_GetOutputRate();
581 //add to the refcount
583 //synfig::info("Audio: increment fmod refcount %d", refcount);
590 synfig::warning("FMOD refcount is already 0...");
594 //synfig::info("Audio: decrement fmod refcount %d", refcount);
596 //NOTE: UNCOMMENT THIS IF YOU WANT FMOD TO UNLOAD ITSELF WHEN IT ISN'T NEEDED ANYMORE...
601 bool is_loaded() const { return loaded; }
611 if(loaded && refcount <= 0)
614 synfig::info("Unloading FMOD");
615 if(scrubdspunit) FSOUND_DSP_Free(scrubdspunit);
623 //The global counter for FMOD....
624 FMODInitializer fmodinit;
628 //----- AudioProfile Implementation -----------
629 void studio::AudioProfile::clear()
635 handle<AudioContainer> studio::AudioProfile::get_parent() const
640 void studio::AudioProfile::set_parent(etl::handle<AudioContainer> i)
645 double studio::AudioProfile::get_offset() const
648 return parent->get_offset();
652 //---------- AudioContainer definitions ---------------------
654 struct studio::AudioContainer::AudioImp
656 //Sample load time information
657 FSOUND_SAMPLE * sample;
663 double offset; //time offset for playing...
665 //We don't need it now that we've adopted the play(t) time schedule...
666 //current time... and playing info....
670 //Make sure to sever our delayed start if we are stopped prematurely
671 sigc::connection delaycon;
676 etl::clock timer; //for getting the time diff between scrub input points
678 //Scrubbing information...
679 //the current position of the sound will be sufficient for normal stuff...
686 bool is_scrubbing() const {return scrptr != 0;}
687 void set_scrubbing(bool s)
697 //helper to make sure we are actually playing (and to get a new channel...)
701 if(!FSOUND_IsPlaying(channel))
705 //play sound paused etc.
706 channel = FSOUND_PlaySoundEx(FSOUND_FREE,sample,0,true);
707 if(channel < 0 || FSOUND_GetError() != FMOD_ERR_NONE)
709 synfig::warning("Could not play the sample...");
715 FSOUND_SetPaused(channel,true);
716 FSOUND_SetFrequency(channel,sfreq);
737 //reuse the channel...
739 channel = FSOUND_FREE;
748 public: //helper/accessor funcs
749 bool start_playing_now() //callback for timer...
754 //Make sure the sound is playing and if it is un pause it...
756 FSOUND_SetPaused(channel,false);
760 return false; //so the timer doesn't repeat itself
766 return FSOUND_IsPlaying(channel);
775 return FSOUND_GetPaused(channel);
782 public: //forward interface
784 //Accessors for the offset - in seconds
785 const double &get_offset() const {return offset;}
786 void set_offset(const double &d)
791 //Will override the parameter timevalue if the sound is running, and not if it's not...
792 bool get_current_time(double &out)
797 unsigned int pos = FSOUND_GetCurrentPosition(channel);
799 //adjust back by 1 frame... HACK....
800 //pos -= FSOUND_DSP_GetBufferLength();
803 out = pos/(double)sfreq + offset;
811 //Big implementation functions...
812 bool load(const std::string &filename, const std::string &filedirectory);
819 //scrubbing functions
820 void start_scrubbing(double t);
821 void scrub(double t);
822 void stop_scrubbing();
830 //--------------- Audio Container definitions --------------------------
831 studio::AudioContainer::AudioContainer()
836 studio::AudioContainer::~AudioContainer()
838 if(imp) delete (imp);
841 bool studio::AudioContainer::load(const string &filename,const string &filedirectory)
848 profilevalid = false;
849 return imp->load(filename,filedirectory);
852 handle<studio::AudioProfile> studio::AudioContainer::get_profile(float samplerate)
856 //if we already have done our work, then we're good
857 if(profilevalid && prof)
859 //synfig::info("Using already built profile");
863 //synfig::info("Before profile");
864 //make a new profile at current sample rate
866 //NOTE: We might want to reuse the structure already there...
867 prof = new AudioProfile;
868 prof->set_parent(this); //Our parent is THIS!!!
872 synfig::warning("Couldn't allocate audioprofile...");
873 return handle<studio::AudioProfile>();
876 //setting the info for the sample rate
877 //synfig::info("Setting info...");
879 synfig::info("Building Profile...");
880 prof->samplerate = samplerate;
881 if(build_profile(imp->sample,prof->samplerate,prof->samples))
883 synfig::info(" Success!");
888 return handle<studio::AudioProfile>();
893 return handle<studio::AudioProfile>();
898 void studio::AudioContainer::clear()
906 profilevalid = false;
909 void studio::AudioContainer::play(double t)
911 if(imp) imp->play(t);
914 void studio::AudioContainer::stop()
919 bool studio::AudioContainer::get_current_time(double &out)
921 if(imp) return imp->get_current_time(out);
925 void AudioContainer::set_offset(const double &s)
927 if(imp) imp->set_offset(s);
930 double AudioContainer::get_offset() const
932 static double zero = 0;
934 return imp->get_offset();
938 bool AudioContainer::is_playing() const
945 bool AudioContainer::is_scrubbing() const
948 return imp->is_scrubbing();
952 void AudioContainer::start_scrubbing(double t)
954 if(imp) imp->start_scrubbing(t);
957 void AudioContainer::stop_scrubbing()
959 if(imp) imp->stop_scrubbing();
962 void AudioContainer::scrub(double t)
964 if(imp) imp->scrub(t);
967 double AudioContainer::scrub_time() const
969 if(imp) return imp->scrub_time();
973 bool AudioContainer::isRunning() const
975 if(imp) return imp->isRunning();
979 bool AudioContainer::isPaused() const
981 if(imp) return imp->isPaused();
985 //----------- Audio imp information -------------------
987 bool studio::AudioContainer::AudioImp::load(const std::string &filename,
988 const std::string &filedirectory)
994 //And continue with the sound loading...
995 string file = filename;
997 //Trivial reject... (fixes stat call problem... where it just looks at directory and not file...)
998 if(file.length() == 0) return false;
1000 //we don't need the file directory?
1001 if(!is_absolute_path(file))
1003 file=filedirectory+filename;
1004 synfig::warning("Not absolute hoooray");
1006 synfig::info("Loading Audio file: %s", file.c_str());
1008 //check to see if file exists
1011 if(stat(file.c_str(),&s) == -1 && errno == ENOENT)
1013 synfig::info("There was no audio file...");
1018 //load fmod if we can...
1019 //synfig::warning("I'm compiled with FMOD!");
1023 int ch = FSOUND_FREE;
1024 FSOUND_SAMPLE *sm = FSOUND_Sample_Load(FSOUND_FREE,file.c_str(),FSOUND_LOOP_OFF|FSOUND_MPEGACCURATE,0,0);
1028 synfig::warning("Could not open the audio file as a sample: %s",file.c_str());
1032 //synfig::warning("Opened a file as a sample! :)");
1035 int bufferlen = FSOUND_DSP_GetBufferLength();
1036 synfig::info("Buffer length = %d samples, %.3lf s",bufferlen, bufferlen / (double)FSOUND_GetOutputRate());
1039 //set all the variables since everything has worked out...
1040 //get the length of the stream
1042 length = FSOUND_Sample_GetLength(sm);
1045 FSOUND_Sample_GetDefaults(sm,&sfreq,&volume,0,0);
1047 //double len = length / (double)sfreq;
1048 //synfig::info("Sound info: %.2lf s long, %d Hz, %d Vol",(double)length,sfreq,volume);
1051 //synfig::warning("Got all info, and setting up everything, %.2f sec.", length);
1052 //synfig::warning(" BigSample: composed of %d samples", FSOUND_Sample_GetLength(sm));
1053 synfig::info("Successfully opened %s as a sample and initialized it.",file.c_str());
1055 //set up the playable info
1059 //the length and sfreq params have already been initialized
1064 if(sm) FSOUND_Sample_Free(sm);
1076 void studio::AudioContainer::AudioImp::play(double t)
1081 //stop scrubbing if we are...
1082 if(is_scrubbing()) stop_scrubbing();
1090 unsigned int timeout = (int)floor(-t * 1000 + 0.5);
1091 //synfig::info("Playing audio delayed by %d ms",timeout);
1092 //delay for t seconds...
1093 delaycon = Glib::signal_timeout().connect(
1094 sigc::mem_fun(*this,&studio::AudioContainer::AudioImp::start_playing_now),timeout);
1097 FSOUND_SetFrequency(channel,sfreq);
1098 FSOUND_SetCurrentPosition(channel,0);
1102 unsigned int position = (int)floor(t*sfreq + 0.5);
1104 if(position >= FSOUND_Sample_GetLength(sample))
1106 synfig::warning("Can't play audio when past length...");
1111 FSOUND_SetFrequency(channel,sfreq);
1112 FSOUND_SetCurrentPosition(channel,position);
1113 FSOUND_SetPaused(channel,false);
1115 //synfig::info("Playing audio with position %d samples",position);
1120 void studio::AudioContainer::AudioImp::stop()
1122 delaycon.disconnect();
1125 if(fmodinit.is_loaded() && playing && isRunning())
1127 FSOUND_SetPaused(channel,true);
1134 void studio::AudioContainer::AudioImp::clear()
1137 delaycon.disconnect();
1144 if(FSOUND_IsPlaying(channel))
1146 FSOUND_StopSound(channel);
1148 channel = FSOUND_FREE;
1149 FSOUND_Sample_Free(sample);
1163 void AudioContainer::AudioImp::start_scrubbing(double t)
1165 //synfig::info("Start scrubbing: %lf", t);
1168 set_scrubbing(true);
1171 //make sure the other one is not scrubbing...
1172 if(g_scrubdata.scrub)
1174 *g_scrubdata.scrub = 0; //nullify the pointer...
1177 //Set up the initial state for the delayed audio position
1178 scrinfo.delaystart = 0;
1180 scrinfo.deltatime = 0;
1182 //set it to point to our pointer (dizzy...)
1183 g_scrubdata.scrub = &scrptr;
1185 //setup position info so we can know what to do on boundary conditions...
1186 curscrubpos = (t - get_offset()) * sfreq;
1188 //So we can get an accurate difference...
1191 //reposition the sound if it won't be when scrubbed (if it's already in the range...)
1192 int curi = (int)curscrubpos;
1193 if(curi >= 0 && curi < length)
1196 FSOUND_SetCurrentPosition(channel,curi);
1199 scrinfo.pos = curscrubpos;
1200 scrinfo.delaystart = delay_factor*buffer_length_sec;
1202 //synfig::info("\tStarting at %d samps, with %d p %.3f delay",
1203 // FSOUND_GetCurrentPosition(channel), (int)scrinfo.pos, scrinfo.delaystart);
1209 //synfig::info("\tActivating DSP");
1210 FSOUND_DSP_SetActive(scrubdspunit,true);
1214 void AudioContainer::AudioImp::stop_scrubbing()
1216 //synfig::info("Stop scrubbing");
1220 set_scrubbing(false);
1223 g_scrubdata.scrub = 0;
1226 //synfig::info("\tDeactivating DSP");
1227 FSOUND_DSP_SetActive(scrubdspunit,false);
1228 if(FSOUND_IsPlaying(channel)) FSOUND_SetPaused(channel,true);
1235 void AudioContainer::AudioImp::scrub(double t)
1238 //synfig::info("Scrub to %lf",t);
1241 //What should we do?
1243 /* Different special cases
1244 All outside, all inside,
1245 coming in (left or right),
1246 going out (left or right)
1248 double oldpos = curscrubpos;
1249 double newpos = (t - get_offset()) * sfreq;
1251 curscrubpos = newpos;
1253 //Ok the sound is running, now we need to tweek it
1256 //Outside so completely stopped...
1257 if(newpos < 0 || oldpos >= length)
1259 //synfig::info("\tOut +");
1260 if(FSOUND_IsPlaying(channel))
1262 FSOUND_SetPaused(channel,true);
1265 //Zero out the data!
1267 scrinfo.delaystart = 0;
1268 scrinfo.deltatime = 0;
1274 //going in? - start the sound at the beginning...
1275 /*else if(oldpos < 0)
1277 //Set up the sound to be playing paused at the start...
1279 FSOUND_SetCurrentPosition(channel,0);
1281 synfig::info("\tIn + %d", FSOUND_GetCurrentPosition(channel));
1285 scrinfo.delaystart = delay_factor*buffer_length_sec;
1286 scrinfo.deltatime = 0;
1289 //don't need to deal with leaving... automatically dealt with...
1291 else //We're all inside...
1293 //Set new position and decide what to do with time...
1295 scrinfo.pos = newpos;
1297 //should we restart the delay cycle... (is it done?)
1298 if(!isRunning() || (scrinfo.delaystart <= 0 && scrinfo.deltatime <= 0 && isPaused()))
1300 //synfig::info("Starting + at %d",(int)newpos);
1301 scrinfo.deltatime = 0;
1302 scrinfo.delaystart = delay_factor*buffer_length_sec;
1305 //Set up the sound paused at the current position
1307 int setpos = min(max((int)newpos,0),length);
1308 FSOUND_SetCurrentPosition(channel,setpos);
1313 //No! just increment the time delta...
1314 scrinfo.deltatime += timer.pop_time();
1316 //Nope... continue and just increment the deltatime and reset position...
1319 //set channel and unpause
1320 FSOUND_SetPaused(channel,false);
1321 scrinfo.channel = channel;
1324 }else if(newpos < oldpos)
1326 //completely stopped...
1327 if(newpos >= length || oldpos < 0)
1329 //synfig::info("Out -");
1330 if(FSOUND_IsPlaying(channel))
1332 FSOUND_SetPaused(channel,true);
1335 //Zero out the data!
1337 scrinfo.delaystart = 0;
1338 scrinfo.deltatime = 0;
1342 //going in? - start going backwards at the end...
1343 /*else if(oldpos >= length)
1345 synfig::info("In -");
1346 //Set up the sound to be playing paused at the start...
1348 FSOUND_SetCurrentPosition(channel,length-1);
1351 scrinfo.pos = length-1;
1352 scrinfo.delaystart = delay_factor*buffer_length_sec;
1353 scrinfo.deltatime = 0;
1356 //we don't have to worry about the leaving case...
1358 else //We're all inside...
1360 //Set new position and decide what to do with time...
1362 scrinfo.pos = newpos;
1364 //should we restart the delay cycle... (is it done?)
1365 if(!isRunning() ||(scrinfo.delaystart <= 0 && scrinfo.deltatime <= 0 && isPaused()))
1367 //synfig::info("Starting - at %d",(int)newpos);
1368 scrinfo.deltatime = 0;
1369 scrinfo.delaystart = delay_factor*buffer_length_sec;
1372 //reset timing so next update will be a valid diff...
1374 int setpos = min(max((int)newpos,0),length);
1375 FSOUND_SetCurrentPosition(channel,setpos);
1380 //No! just increment the time delta...
1381 scrinfo.deltatime += timer.pop_time();
1383 //Nope... continue and just increment the deltatime and reset position...
1386 //set channel and unpause
1387 FSOUND_SetPaused(channel,false);
1388 scrinfo.channel = channel;