-/* === S I N F G =========================================================== */
+/* === S Y N F I G ========================================================= */
/*! \file audiocontainer.cpp
** \brief Audio Container implementation File
**
-** $Id: audiocontainer.cpp,v 1.1.1.1 2005/01/07 03:34:35 darco Exp $
+** $Id$
**
** \legal
-** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
**
-** This software and associated documentation
-** are CONFIDENTIAL and PROPRIETARY property of
-** the above-mentioned copyright holder.
+** This package is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of
+** the License, or (at your option) any later version.
**
-** You may not copy, print, publish, or in any
-** other way distribute this software without
-** a prior written agreement with
-** the copyright holder.
+** This package is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
** \endlegal
*/
/* ========================================================================= */
//#include <ETL/thread>
#include <glibmm/thread.h>
-#include <sinfg/general.h>
+#include <synfig/general.h>
#include <glibmm/main.h>
#include <fmod.h>
#endif
+#include "general.h"
+
#endif
/* === U S I N G =========================================================== */
using namespace std;
using namespace etl;
-using namespace sinfg;
+using namespace synfig;
/* === M A C R O S ========================================================= */
#ifdef __WIN32
struct FSOUND_SAMPLE;
using studio::AudioContainer;
+#ifdef WITH_FMOD
bool build_profile(FSOUND_SAMPLE *sample, double &samplerate, std::vector<char> &samples)
+#else
+bool build_profile(FSOUND_SAMPLE */*sample*/, double &/*samplerate*/, std::vector<char> &/*samples*/)
+#endif
{
#ifdef WITH_FMOD
-
+
float sps = samplerate;
-
+
//trivial rejection...
if(!sample || sps < 1)
{
- sinfg::warning("build_profile: Sample rate was too low or sample was invalid");
+ synfig::warning("build_profile: Sample rate was too low or sample was invalid");
return false;
}
-
+
//lock for all samples and process them into a subset
unsigned int mode = FSOUND_Sample_GetMode(sample);
-
+
//make sure that it's 8 bit... I hope this works...
-
+
//sample rate of the actual song...
int allsamplerate = 0;
FSOUND_Sample_GetDefaults(sample,&allsamplerate,0,0,0);
-
+
//get the size of the sample defaults from the mode
int channels = 1;
int channelsize = 1; //number of bytes
-
+
if(mode & FSOUND_16BITS) channelsize = 2; //this shouldn't happen
if(mode & FSOUND_STEREO) channels = 2;
-
+
//Get the sample information
int samplesize = channels*channelsize; //the only two things that increase samplesize
int numsamples = FSOUND_Sample_GetLength(sample); //number of samples in the sound
int sizeall = samplesize*numsamples; //should be the size of the entire song...
-
+
if(sizeall <= 0)
{
- sinfg::warning("ProfileAudio: Sample buffer cannot be size smaller than 1 (%X)",FSOUND_GetError());
+ synfig::warning("ProfileAudio: Sample buffer cannot be size smaller than 1 (%X)",FSOUND_GetError());
return false;
}
-
+
//be sure that the new sample rate is less than or equal to the original
if(sps > allsamplerate) sps = allsamplerate;
-
+
float stride = allsamplerate/(float)sps;
-
- //down sampling to 8 bit min/max values
- sinfg::warning("About to downsample from %d Hz to %.1f Hz, sample stride: %f", allsamplerate, sps, stride);
-
+
+ //down sampling to 8 bit min/max values
+ synfig::warning("About to downsample from %d Hz to %.1f Hz, sample stride: %f", allsamplerate, sps, stride);
+
char *sampledata=0,*useless = 0;
unsigned int len1,len2;
// vector<char> samples;
{
if(!FSOUND_Sample_Lock(sample,0,sizeall,(void**)&sampledata,(void**)&useless,&len1,&len2))
{
- sinfg::warning("ProfileAudio: Unable to lock the sound buffer... (%X)",FSOUND_GetError());
+ synfig::warning("ProfileAudio: Unable to lock the sound buffer... (%X)",FSOUND_GetError());
return false;
}
- sinfg::warning("Locked: %X: %d bytes, %X: %d bytes",sampledata,len1,useless,len2);
-
+ synfig::warning("Locked: %X: %d bytes, %X: %d bytes",sampledata,len1,useless,len2);
+
if(channelsize == 1)
{
//process the data
char *iter = sampledata;
char *end = iter + sizeall;
-
+
float curaccum = 0;
float numinc = sps/(float)allsamplerate;
-
+
/* Loop per sample DDA alg.
*/
-
+
int i = 0;
-
+
//HACK - to prevent if statement inside inner loop
- //sinfg::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
+ //synfig::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
while(iter < end)
{
int maxs = 0, mins = 0;
-
+
for(;curaccum < 1; curaccum += numinc)
{
for(i = 0; iter < end && i < channels; ++i, iter += channelsize)
//insert onto new list
samples.push_back(maxs);
samples.push_back(mins);
-
+
//and flush all the used samples for curaccum
curaccum -= 1;
}
//process the data
char *iter = sampledata;
char *end = iter + sizeall;
-
+
float curaccum = 0;
float numinc = sps/(float)allsamplerate;
-
+
/* Loop per sample DDA alg.
*/
-
+
int i = 0;
-
+
//HACK - to prevent if statement inside inner loop
- //sinfg::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
+ //synfig::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
while(iter < end)
{
int maxs = 0, mins = 0;
-
+
for(;curaccum < 1; curaccum += numinc)
{
for(i = 0; iter < end && i < channels; ++i, iter += channelsize)
//insert onto new list
samples.push_back(maxs / 256);
samples.push_back(mins / 256);
-
+
//and flush all the used samples for curaccum
curaccum -= 1;
}
}
}
-
- sinfg::warning("Stats: %f seconds with %d bytes now %d bytes", (samples.size()/2)/sps, sizeall, samples.size());
- sinfg::warning(" %f seconds before", numsamples/(float)allsamplerate);
-
+
+ synfig::warning("Stats: %f seconds with %d bytes now %d bytes", (samples.size()/2)/sps, sizeall, samples.size());
+ synfig::warning(" %f seconds before", numsamples/(float)allsamplerate);
+
//we're done yay!, unlock
FSOUND_Sample_Unlock(sample,sampledata,useless,len1,len2);
- sinfg::info("Unlocked");
-
+ synfig::info("Unlocked");
+
//FSOUND_PlaySound(FSOUND_FREE,sound); //test
-
+
//we're done
samplerate = sps*2; //it must be x2 because we are sampling max and min
-
+
return true;
-
+
#else
-
+
return false;
-
+
#endif
}
//FMOD Systemwide Specific data mostly here...
struct scrubinfo;
-
+
#ifdef WITH_FMOD
static double buffer_length_sec = 0;
/* Things to check:
If IsPlaying just governs the channel play/stop value or if it also concerns the pause state
-
+
*/
//so we can know where to create all this stuff
struct scrubinfo
{
/* Linearly fit the frequency to hit the desired zero point...
- */
+ */
/*struct scrubelement
{
double pos;
double dt;
//the amount of time left til the cursor hits this one
- // it's incremental so that the cursor must pass previous
+ // it's incremental so that the cursor must pass previous
// ones before decrementing this value
- };
+ };
*/
-
+
//the time it should take to get to the next position...
-
+
//to prevent from writing to the same location at once... (pos, deltatime, delaystart)
//Glib::Mutex lock;
-
+
//the queue system would provide a more accurate representation...
volatile double pos;
volatile double deltatime;
-
+
volatile double delaystart; //the amount of time we need to go before we start interpolating...
-
+
volatile int channel;
/*std::list<scrubelement> queue;
-
+
volatile int channel;
-
+
//current position is FSOUND_GetCurrentPosition and current time is always 0...
-
+
void add(const scrubelement &elem)
{
lock.LockWrite();
-
+
queue.push_back(elem);
-
+
lock.UnlockWrite();
}
-
+
//Function to safely get rid of all the old samples (dt < 0)
void flush()
{
lock.LockWrite();
-
+
while(queue.size() && queue.front().dt < 0)
{
queue.pop_front();
}
-
- lock.UnlockWrite();
+
+ lock.UnlockWrite();
}*/
-
+
void Lock()
{
//lock.lock();
}
-
+
void Unlock()
{
//lock.unlock();
}
-
+
//All parameters and state should be set by the time we get here...
void scrub_dsp_process()
{
const double epsilon = 1e-5;
-
+
//Trivial reject... we go nowhere if we aren't playing (hit boundary...)
if(!FSOUND_IsPlaying(channel)) return;
-
+
//Get rid of all the old samples
//flush();
-
+
//Trivial reject #2 - We also go nowhere with no future samples (pause)
/*if(queue.size() <= 0)
{
FSOUND_SetPaused(channel,true);
return;
}*/
-
+
double dt = buffer_length_sec;
-
+
//Lock ourselves so we don't die
Lock();
-
+
//printf("DSP data: delay = %.3f s, pos = %d, dt = %.3f\n", delaystart, (int)pos, deltatime);
-
+
//Check delay
if(delaystart > 0)
{
delaystart -= dt;
-
+
if(delaystart < 0)
{
dt = -delaystart; //add time back...
delaystart = 0;
}
}
-
+
//Trivial reject for if we're past current sample...
if(delaystart > 0 || deltatime <= 0)
{
Unlock();
return;
}
-
+
//Calculate stretched frequency based on delayed future sample...
-
+
//NOTE: BY NOT TRACKING POSITION AS A FLOAT AND JUST USING THE SOUNDS VALUE
- // WE ARE LOSING A TINY AMOUNT OF PRECISION ACCURACY EVERY UPDATE
+ // WE ARE LOSING A TINY AMOUNT OF PRECISION ACCURACY EVERY UPDATE
// (THIS SHOULDN'T BE A PROBLEM)
- const double p0 = FSOUND_GetCurrentPosition(channel);
+ const double p0 = FSOUND_GetCurrentPosition(channel);
double curdp = 0;
-
+
if(!FSOUND_GetPaused(channel))
{
curdp = FSOUND_GetFrequency(channel) * deltatime;
}
- //need to rescale derivative...
+ //need to rescale derivative...
//Extrapolate from difference in position and deltatime vs dt...
const double pa = p0 + curdp/2;
-
+
const double p1 = pos;
-
+
//const double pb = p0/3 + p1*2/3;
-
+
//will extrapolate if needed... (could be funky on a curve)
double t = 0;
if(deltatime > epsilon)
{
t = dt / deltatime;
}
-
+
//Decrement deltatime (we may have gone past but that's what happens when we don't get input...)
deltatime -= dt;
-
+
//we don't need to look at the current variables anymore...
Unlock();
-
+
const double invt = 1-t;
//double deltapos = (p1-p0)*t; //linear version
double deltapos = invt*invt*p0 + 2*t*invt*pa + t*t*p1 - p0; //quadratic smoothing version
-
+
//Attempted cubic smoothing
//const double invt2 = invt*invt;
//const double t2 = t*t;
//double deltapos = invt2*invt*p0 + 3*t*invt2*pa + 3*t2*invt*pb + t2*t*p1;
//double deltapos = p0 + t*(3*(pa-p0) + t*(3*(p0+2*pa+pb) + t*((p1-3*pb+3*ba-p0)))); //unwound cubic
-
+
//printf("\ttime = %.2f; p(%d,%d,%d) dp:%d - delta = %d\n",t,(int)p0,(int)p1,(int)p2,(int)curdp,(int)deltapos);
-
+
//Based on the delta info calculate the stretched frequency
const int dest_samplesize = FSOUND_DSP_GetBufferLength();
-
+
//rounded to nearest frequency... (hopefully...)
int freq = (int)(deltapos * FSOUND_GetOutputRate() / (double)dest_samplesize);
-
+
//NOTE: WE MIGHT WANT TO DO THIS TO BE MORE ACCURATE BUT YEAH... ISSUES WITH SMALL NUMBERS
//double newdp = deltapos / t;
//printf("\tfreq = %d Hz\n", freq);
-
+
// !If I failed... um assume we have to pause it... ?
if(abs(freq) < 100)
{
FSOUND_SetPaused(channel,true);
}else
{
- //sinfg::info("DSP f = %d Hz", freq);
+ //synfig::info("DSP f = %d Hz", freq);
FSOUND_SetPaused(channel,false);
if(!FSOUND_SetFrequency(channel,freq))
{
- //ERROR WILL ROBINSON!!!...
+ //ERROR WILL ROBINSON!!!...
printf("Error in Freq... what do I do?\n");
}
}
- }
+ }
};
struct scrubuserdata
typedef scrubinfo** value_type;
typedef std::set< value_type > scrubslist;
scrubslist scrubs;
-
+
//so we can lock access to the list...
ReadWriteLock lock;
-
+
void AddScrub(scrubinfo **i)
{
lock.LockWrite();
scrubs.insert(i);
lock.UnLockWrite();
}
-
+
void RemoveScrub(scrubinfo **i)
{
lock.LockWrite();
scrubs.erase(i);
- lock.UnLockWrite();
+ lock.UnLockWrite();
}*/
-
+
scrubinfo * volatile * scrub;
};
if(userdata)
{
scrubuserdata &sd = *(scrubuserdata*)userdata;
-
+
/* //For use with multiple scrubs...
//Lock so no one can write to it while we're reading from it...
sd.lock.LockRead();
-
- //make a copy of it...
+
+ //make a copy of it...
std::vector<scrubinfo**> v(sd.scrubs.begin(),sd.scrubs.end());
-
+
//other things can do stuff with it again...
sd.lock.UnLockRead();
-
- //loop through the list and process all the active scrub units
+
+ //loop through the list and process all the active scrub units
std::vector<scrubinfo**>::iterator i = v.begin(),
- end = v.end();
+ end = v.end();
for(;i != end; ++i)
{
//check to make sure this object is active...
}
}
*/
-
+
if(sd.scrub && *sd.scrub)
{
//dsp += " processing...";
- scrubinfo * info = (*sd.scrub);
+ scrubinfo * info = (*sd.scrub);
info->scrub_dsp_process();
}
}
-
- //sinfg::info(dsp);
+
+ //synfig::info(dsp);
return newbuffer;
}
{
bool loaded;
int refcount;
-
+
public:
FMODInitializer():loaded(false),refcount(0) {}
- ~FMODInitializer()
+ ~FMODInitializer()
{
clear();
}
-
+
void addref()
{
if(!loaded)
{
#ifdef WITH_FMOD
- sinfg::info("Initializing FMOD on demand...");
-
+ synfig::info("Initializing FMOD on demand...");
+
{
FSOUND_SetOutput(AUDIO_OUTPUT);
-
+
/*int numdrivers = FSOUND_GetNumDrivers();
- sinfg::info("Num FMOD drivers = %d",numdrivers);
- sinfg::info("Current Driver is #%d", FSOUND_GetDriver());
-
+ synfig::info("Num FMOD drivers = %d",numdrivers);
+ synfig::info("Current Driver is #%d", FSOUND_GetDriver());
+
for(int i = 0; i < numdrivers; ++i)
{
unsigned int caps = 0;
FSOUND_GetDriverCaps(i,&caps);
-
- sinfg::info(" Caps for driver %d (%s) = %x",i,FSOUND_GetDriverName(i),caps);
+
+ synfig::info(" Caps for driver %d (%s) = %x",i,FSOUND_GetDriverName(i),caps);
}
-
+
FSOUND_SetDriver(0);*/
-
+
//Modify buffer size...
//FSOUND_SetBufferSize(100);
-
+
if(!FSOUND_Init(44100, 32, 0))
{
- sinfg::warning("Unable to load FMOD");
+ synfig::warning("Unable to load FMOD");
}else
{
loaded = true;
-
+
//Create the DSP for processing scrubbing...
scrubdspunit = FSOUND_DSP_Create(&scrubdspwrap,default_scrub_priority,&g_scrubdata);
-
+
//Load the number of sec per buffer into the global variable...
buffer_length_sec = FSOUND_DSP_GetBufferLength() / (double)FSOUND_GetOutputRate();
}
}
#endif
}
-
+
//add to the refcount
++refcount;
- //sinfg::info("Audio: increment fmod refcount %d", refcount);
+ //synfig::info("Audio: increment fmod refcount %d", refcount);
}
-
+
void decref()
{
if(refcount <= 0)
{
- sinfg::warning("FMOD refcount is already 0...");
+ synfig::warning("FMOD refcount is already 0...");
}else
{
--refcount;
- //sinfg::info("Audio: decrement fmod refcount %d", refcount);
-
+ //synfig::info("Audio: decrement fmod refcount %d", refcount);
+
//NOTE: UNCOMMENT THIS IF YOU WANT FMOD TO UNLOAD ITSELF WHEN IT ISN'T NEEDED ANYMORE...
flush();
}
}
bool is_loaded() const { return loaded; }
-
+
void clear()
{
refcount = 0;
flush();
}
-
+
void flush()
{
if(loaded && refcount <= 0)
{
#ifdef WITH_FMOD
- sinfg::info("Unloading FMOD");
+ synfig::info("Unloading FMOD");
if(scrubdspunit) FSOUND_DSP_Free(scrubdspunit);
- FSOUND_Close();
+ FSOUND_Close();
#endif
loaded = false;
}
//---------- AudioContainer definitions ---------------------
struct studio::AudioContainer::AudioImp
-{
+{
//Sample load time information
FSOUND_SAMPLE * sample;
int channel;
int sfreq;
int length;
-
+
//Time information
double offset; //time offset for playing...
-
+
//We don't need it now that we've adopted the play(t) time schedule...
- //current time... and playing info....
+ //current time... and playing info....
//float seekpost;
//bool useseekval;
-
+
//Make sure to sever our delayed start if we are stopped prematurely
sigc::connection delaycon;
-
+
//Action information
bool playing;
double curscrubpos;
etl::clock timer; //for getting the time diff between scrub input points
-
+
//Scrubbing information...
//the current position of the sound will be sufficient for normal stuff...
#ifdef WITH_FMOD
scrubinfo scrinfo;
#endif
-
+
scrubinfo *scrptr;
-
+
bool is_scrubbing() const {return scrptr != 0;}
+#ifdef WITH_FMOD
void set_scrubbing(bool s)
+#else
+ void set_scrubbing(bool /*s*/)
+#endif
{
#ifdef WITH_FMOD
if(s)
scrptr = &scrinfo;
- else
+ else
#endif
scrptr = 0;
}
-
+
//helper to make sure we are actually playing (and to get a new channel...)
bool init_play()
{
channel = FSOUND_PlaySoundEx(FSOUND_FREE,sample,0,true);
if(channel < 0 || FSOUND_GetError() != FMOD_ERR_NONE)
{
- sinfg::warning("Could not play the sample...");
+ synfig::warning("Could not play the sample...");
return false;
}
}
FSOUND_SetFrequency(channel,sfreq);
}
return true;
-
+
#else
-
+
return false;
-
+
#endif
}
-
+
public: //structors
AudioImp()
:sample(0),
length(0),
offset(0),
playing(false),
- scrptr(0)
+ scrptr(0)
{
//reuse the channel...
#ifdef WITH_FMOD
channel = FSOUND_FREE;
#endif
}
-
+
~AudioImp()
{
clear();
}
-
+
public: //helper/accessor funcs
bool start_playing_now() //callback for timer...
{
FSOUND_SetPaused(channel,false);
}
#endif
-
+
return false; //so the timer doesn't repeat itself
- }
-
+ }
+
bool isRunning()
{
#ifdef WITH_FMOD
return false;
#endif
}
-
+
bool isPaused()
- {
+ {
#ifdef WITH_FMOD
return FSOUND_GetPaused(channel);
#else
return false;
#endif
}
-
-
+
+
public: //forward interface
-
+
//Accessors for the offset - in seconds
const double &get_offset() const {return offset;}
- void set_offset(const double &d)
+ void set_offset(const double &d)
{
offset = d;
}
-
+
//Will override the parameter timevalue if the sound is running, and not if it's not...
+#ifdef WITH_FMOD
bool get_current_time(double &out)
+#else
+ bool get_current_time(double &/*out*/)
+#endif
{
if(isRunning())
{
#ifdef WITH_FMOD
unsigned int pos = FSOUND_GetCurrentPosition(channel);
-
+
//adjust back by 1 frame... HACK....
//pos -= FSOUND_DSP_GetBufferLength();
-
+
//set the position
out = pos/(double)sfreq + offset;
#endif
-
+
return true;
}
return false;
}
-
+
//Big implementation functions...
bool load(const std::string &filename, const std::string &filedirectory);
void clear();
-
+
//playing functions
void play(double t);
void stop();
-
+
//scrubbing functions
void start_scrubbing(double t);
void scrub(double t);
void stop_scrubbing();
-
+
double scrub_time()
{
return curscrubpos;
if(imp) delete (imp);
}
-bool studio::AudioContainer::load(const string &filename,const string &filedirectory)
+bool studio::AudioContainer::load(const std::string &filename,const std::string &filedirectory)
{
if(!imp)
{
imp = new AudioImp;
}
-
+
profilevalid = false;
return imp->load(filename,filedirectory);
}
+#ifdef WITH_FMOD
handle<studio::AudioProfile> studio::AudioContainer::get_profile(float samplerate)
+#else
+handle<studio::AudioProfile> studio::AudioContainer::get_profile(float /*samplerate*/)
+#endif
{
#ifdef WITH_FMOD
-
+
//if we already have done our work, then we're good
if(profilevalid && prof)
{
- //sinfg::info("Using already built profile");
+ //synfig::info("Using already built profile");
return prof;
}
-
- //sinfg::info("Before profile");
+
+ //synfig::info("Before profile");
//make a new profile at current sample rate
-
- //NOTE: We might want to reuse the structure already there...
+
+ //NOTE: We might want to reuse the structure already there...
prof = new AudioProfile;
prof->set_parent(this); //Our parent is THIS!!!
-
+
if(!prof)
{
- sinfg::warning("Couldn't allocate audioprofile...");
+ synfig::warning("Couldn't allocate audioprofile...");
return handle<studio::AudioProfile>();
}
-
+
//setting the info for the sample rate
- //sinfg::info("Setting info...");
-
- sinfg::info("Building Profile...");
+ //synfig::info("Setting info...");
+
+ synfig::info("Building Profile...");
prof->samplerate = samplerate;
if(build_profile(imp->sample,prof->samplerate,prof->samples))
{
- sinfg::info(" Success!");
+ synfig::info(" Success!");
profilevalid = true;
return prof;
}else
{
return handle<studio::AudioProfile>();
}
-
+
#else
-
+
return handle<studio::AudioProfile>();
-
+
#endif
}
void studio::AudioContainer::clear()
{
- if(imp)
+ if(imp)
{
delete imp;
imp = 0;
}
-
+
profilevalid = false;
}
-
+
void studio::AudioContainer::play(double t)
{
if(imp) imp->play(t);
bool AudioContainer::is_playing() const
{
- if(imp)
+ if(imp)
return imp->playing;
return false;
}
bool AudioContainer::is_scrubbing() const
{
- if(imp)
+ if(imp)
return imp->is_scrubbing();
return false;
}
//----------- Audio imp information -------------------
-bool studio::AudioContainer::AudioImp::load(const std::string &filename,
+#ifdef WITH_FMOD
+bool studio::AudioContainer::AudioImp::load(const std::string &filename,
const std::string &filedirectory)
+#else
+bool studio::AudioContainer::AudioImp::load(const std::string &/*filename*/,
+ const std::string &/*filedirectory*/)
+#endif
{
clear();
#ifdef WITH_FMOD
-
+
//And continue with the sound loading...
string file = filename;
-
+
//Trivial reject... (fixes stat call problem... where it just looks at directory and not file...)
if(file.length() == 0) return false;
-
+
//we don't need the file directory?
if(!is_absolute_path(file))
{
file=filedirectory+filename;
- sinfg::warning("Not absolute hoooray");
+ synfig::warning("Not absolute hoooray");
}
- sinfg::info("Loading Audio file: %s", file.c_str());
-
+ synfig::info("Loading Audio file: %s", file.c_str());
+
//check to see if file exists
{
struct stat s;
if(stat(file.c_str(),&s) == -1 && errno == ENOENT)
{
- sinfg::info("There was no audio file...");
+ synfig::info("There was no audio file...");
return false;
}
}
-
+
//load fmod if we can...
- //sinfg::warning("I'm compiled with FMOD!");
+ //synfig::warning("I'm compiled with FMOD!");
fmodinit.addref();
-
+
//load the stream
int ch = FSOUND_FREE;
FSOUND_SAMPLE *sm = FSOUND_Sample_Load(FSOUND_FREE,file.c_str(),FSOUND_LOOP_OFF|FSOUND_MPEGACCURATE,0,0);
-
+
if(!sm)
{
- sinfg::warning("Could not open the audio file as a sample: %s",file.c_str());
+ synfig::warning("Could not open the audio file as a sample: %s",file.c_str());
goto error;
}
-
- //sinfg::warning("Opened a file as a sample! :)");
-
+
+ //synfig::warning("Opened a file as a sample! :)");
+
/*{
int bufferlen = FSOUND_DSP_GetBufferLength();
- sinfg::info("Buffer length = %d samples, %.3lf s",bufferlen, bufferlen / (double)FSOUND_GetOutputRate());
+ synfig::info("Buffer length = %d samples, %.3lf s",bufferlen, bufferlen / (double)FSOUND_GetOutputRate());
}*/
-
+
//set all the variables since everything has worked out...
//get the length of the stream
{
length = FSOUND_Sample_GetLength(sm);
-
+
int volume = 0;
FSOUND_Sample_GetDefaults(sm,&sfreq,&volume,0,0);
-
- //double len = length / (double)sfreq;
- //sinfg::info("Sound info: %.2lf s long, %d Hz, %d Vol",(double)length,sfreq,volume);
+
+ //double len = length / (double)sfreq;
+ //synfig::info("Sound info: %.2lf s long, %d Hz, %d Vol",(double)length,sfreq,volume);
}
-
- //sinfg::warning("Got all info, and setting up everything, %.2f sec.", length);
- //sinfg::warning(" BigSample: composed of %d samples", FSOUND_Sample_GetLength(sm));
- sinfg::info("Successfully opened %s as a sample and initialized it.",file.c_str());
-
+
+ //synfig::warning("Got all info, and setting up everything, %.2f sec.", length);
+ //synfig::warning(" BigSample: composed of %d samples", FSOUND_Sample_GetLength(sm));
+ synfig::info("Successfully opened %s as a sample and initialized it.",file.c_str());
+
//set up the playable info
sample = sm;
channel = ch;
-
+
//the length and sfreq params have already been initialized
-
+
return true;
-
+
error:
if(sm) FSOUND_Sample_Free(sm);
file = "";
-
+
fmodinit.decref();
-
+
return false;
-
+
#else
return false;
#endif
}
+#ifdef WITH_FMOD
void studio::AudioContainer::AudioImp::play(double t)
+#else
+void studio::AudioContainer::AudioImp::play(double /*t*/)
+#endif
{
#ifdef WITH_FMOD
if(!sample) return;
-
+
//stop scrubbing if we are...
if(is_scrubbing()) stop_scrubbing();
-
+
//t -= offset;
t -= get_offset();
playing = true;
-
+
if(t < 0)
{
unsigned int timeout = (int)floor(-t * 1000 + 0.5);
- //sinfg::info("Playing audio delayed by %d ms",timeout);
+ //synfig::info("Playing audio delayed by %d ms",timeout);
//delay for t seconds...
delaycon = Glib::signal_timeout().connect(
- sigc::mem_fun(*this,&studio::AudioContainer::AudioImp::start_playing_now),timeout);
-
+ sigc::mem_fun(*this,&studio::AudioContainer::AudioImp::start_playing_now),timeout);
+
init_play();
FSOUND_SetFrequency(channel,sfreq);
FSOUND_SetCurrentPosition(channel,0);
return;
}
-
+
unsigned int position = (int)floor(t*sfreq + 0.5);
-
+
if(position >= FSOUND_Sample_GetLength(sample))
{
- sinfg::warning("Can't play audio when past length...");
+ synfig::warning("Can't play audio when past length...");
return;
}
-
+
init_play();
FSOUND_SetFrequency(channel,sfreq);
FSOUND_SetCurrentPosition(channel,position);
FSOUND_SetPaused(channel,false);
-
- //sinfg::info("Playing audio with position %d samples",position);
-
- #endif
+
+ //synfig::info("Playing audio with position %d samples",position);
+
+ #endif
}
void studio::AudioContainer::AudioImp::stop()
#ifdef WITH_FMOD
if(fmodinit.is_loaded() && playing && isRunning())
- {
+ {
FSOUND_SetPaused(channel,true);
}
#endif
-
+
playing = false;
}
{
#ifdef WITH_FMOD
delaycon.disconnect();
-
+
stop();
stop_scrubbing();
-
+
if(sample)
{
if(FSOUND_IsPlaying(channel))
FSOUND_Sample_Free(sample);
fmodinit.decref();
}
-
+
playing = false;
-
+
#else
channel = 0;
#endif
-
+
sample = 0;
- playing = false;
+ playing = false;
}
-void AudioContainer::AudioImp::start_scrubbing(double t)
+#ifdef WITH_FMOD
+void studio::AudioContainer::AudioImp::start_scrubbing(double t)
+#else
+void studio::AudioContainer::AudioImp::start_scrubbing(double /*t*/)
+#endif
{
- //sinfg::info("Start scrubbing: %lf", t);
+ //synfig::info("Start scrubbing: %lf", t);
if(playing) stop();
-
+
set_scrubbing(true);
-
+
#ifdef WITH_FMOD
//make sure the other one is not scrubbing...
if(g_scrubdata.scrub)
{
*g_scrubdata.scrub = 0; //nullify the pointer...
}
-
+
//Set up the initial state for the delayed audio position
scrinfo.delaystart = 0;
scrinfo.pos = 0;
scrinfo.deltatime = 0;
-
+
//set it to point to our pointer (dizzy...)
g_scrubdata.scrub = &scrptr;
//setup position info so we can know what to do on boundary conditions...
curscrubpos = (t - get_offset()) * sfreq;
-
+
//So we can get an accurate difference...
timer.reset();
-
- //reposition the sound if it won't be when scrubbed (if it's already in the range...)
+
+ //reposition the sound if it won't be when scrubbed (if it's already in the range...)
int curi = (int)curscrubpos;
if(curi >= 0 && curi < length)
{
init_play();
FSOUND_SetCurrentPosition(channel,curi);
-
+
//Set the values...
scrinfo.pos = curscrubpos;
scrinfo.delaystart = delay_factor*buffer_length_sec;
-
- //sinfg::info("\tStarting at %d samps, with %d p %.3f delay",
+
+ //synfig::info("\tStarting at %d samps, with %d p %.3f delay",
// FSOUND_GetCurrentPosition(channel), (int)scrinfo.pos, scrinfo.delaystart);
}
-
-
-
+
+
+
//enable the dsp...
- //sinfg::info("\tActivating DSP");
+ //synfig::info("\tActivating DSP");
FSOUND_DSP_SetActive(scrubdspunit,true);
#endif
}
-void AudioContainer::AudioImp::stop_scrubbing()
+void studio::AudioContainer::AudioImp::stop_scrubbing()
{
- //sinfg::info("Stop scrubbing");
-
+ //synfig::info("Stop scrubbing");
+
if(is_scrubbing())
{
set_scrubbing(false);
-
+
#ifdef WITH_FMOD
g_scrubdata.scrub = 0;
-
+
//stop the dsp...
- //sinfg::info("\tDeactivating DSP");
+ //synfig::info("\tDeactivating DSP");
FSOUND_DSP_SetActive(scrubdspunit,false);
if(FSOUND_IsPlaying(channel)) FSOUND_SetPaused(channel,true);
#endif
}
-
+
curscrubpos = 0;
}
-void AudioContainer::AudioImp::scrub(double t)
+#ifdef WITH_FMOD
+void studio::AudioContainer::AudioImp::scrub(double t)
+#else
+void studio::AudioContainer::AudioImp::scrub(double /*t*/)
+#endif
{
#ifdef WITH_FMOD
- //sinfg::info("Scrub to %lf",t);
+ //synfig::info("Scrub to %lf",t);
if(is_scrubbing())
- {
+ {
//What should we do?
-
+
/* Different special cases
All outside, all inside,
coming in (left or right),
*/
double oldpos = curscrubpos;
double newpos = (t - get_offset()) * sfreq;
-
+
curscrubpos = newpos;
-
- //Ok the sound is running, now we need to tweek it
+
+ //Ok the sound is running, now we need to tweak it
if(newpos > oldpos)
{
//Outside so completely stopped...
if(newpos < 0 || oldpos >= length)
{
- //sinfg::info("\tOut +");
+ //synfig::info("\tOut +");
if(FSOUND_IsPlaying(channel))
{
FSOUND_SetPaused(channel,true);
scrinfo.delaystart = 0;
scrinfo.deltatime = 0;
scrinfo.Unlock();
-
+
return;
}
-
+
//going in? - start the sound at the beginning...
/*else if(oldpos < 0)
{
//Set up the sound to be playing paused at the start...
init_play();
FSOUND_SetCurrentPosition(channel,0);
-
- sinfg::info("\tIn + %d", FSOUND_GetCurrentPosition(channel));
-
+
+ synfig::info("\tIn + %d", FSOUND_GetCurrentPosition(channel));
+
scrinfo.Lock();
scrinfo.pos = 0;
scrinfo.delaystart = delay_factor*buffer_length_sec;
scrinfo.Unlock();
}*/
//don't need to deal with leaving... automatically dealt with...
-
+
else //We're all inside...
{
//Set new position and decide what to do with time...
scrinfo.Lock();
scrinfo.pos = newpos;
-
- //should we restart the delay cycle... (is it done?)
+
+ //should we restart the delay cycle... (is it done?)
if(!isRunning() || (scrinfo.delaystart <= 0 && scrinfo.deltatime <= 0 && isPaused()))
{
- //sinfg::info("Starting + at %d",(int)newpos);
+ //synfig::info("Starting + at %d",(int)newpos);
scrinfo.deltatime = 0;
scrinfo.delaystart = delay_factor*buffer_length_sec;
scrinfo.Unlock();
-
+
//Set up the sound paused at the current position
init_play();
int setpos = min(max((int)newpos,0),length);
timer.reset();
return;
}
-
+
//No! just increment the time delta...
scrinfo.deltatime += timer.pop_time();
-
+
//Nope... continue and just increment the deltatime and reset position...
scrinfo.Unlock();
-
+
//set channel and unpause
FSOUND_SetPaused(channel,false);
scrinfo.channel = channel;
-
+
}
}else if(newpos < oldpos)
{
//completely stopped...
if(newpos >= length || oldpos < 0)
{
- //sinfg::info("Out -");
+ //synfig::info("Out -");
if(FSOUND_IsPlaying(channel))
{
FSOUND_SetPaused(channel,true);
}
-
+
//Zero out the data!
scrinfo.Lock();
scrinfo.delaystart = 0;
scrinfo.deltatime = 0;
scrinfo.Unlock();
}
-
+
//going in? - start going backwards at the end...
/*else if(oldpos >= length)
{
- sinfg::info("In -");
+ synfig::info("In -");
//Set up the sound to be playing paused at the start...
init_play();
- FSOUND_SetCurrentPosition(channel,length-1);
-
+ FSOUND_SetCurrentPosition(channel,length-1);
+
scrinfo.Lock();
scrinfo.pos = length-1;
scrinfo.delaystart = delay_factor*buffer_length_sec;
scrinfo.Unlock();
}*/
//we don't have to worry about the leaving case...
-
+
else //We're all inside...
{
//Set new position and decide what to do with time...
scrinfo.Lock();
scrinfo.pos = newpos;
-
- //should we restart the delay cycle... (is it done?)
+
+ //should we restart the delay cycle... (is it done?)
if(!isRunning() ||(scrinfo.delaystart <= 0 && scrinfo.deltatime <= 0 && isPaused()))
{
- //sinfg::info("Starting - at %d",(int)newpos);
+ //synfig::info("Starting - at %d",(int)newpos);
scrinfo.deltatime = 0;
scrinfo.delaystart = delay_factor*buffer_length_sec;
scrinfo.Unlock();
-
- //reset timing so next update will be a valid diff...
+
+ //reset timing so next update will be a valid diff...
init_play();
int setpos = min(max((int)newpos,0),length);
FSOUND_SetCurrentPosition(channel,setpos);
timer.reset();
return;
}
-
+
//No! just increment the time delta...
scrinfo.deltatime += timer.pop_time();
-
+
//Nope... continue and just increment the deltatime and reset position...
scrinfo.Unlock();
-
+
//set channel and unpause
FSOUND_SetPaused(channel,false);
scrinfo.channel = channel;