/*
ALURE stream
*/
class ALUREStream {
public union { LinkElement<thisclass> link; struct { thisclass prev, next; }; };
ALSoundManager manager;
alureStream *stream;
char *name;
int bufferSize;
int usesBuffers;
uint samples;
float duration;
float refreshRate;
ALuint *buf;
ALSource source;
bool created;
bool loop;
bool badError;
SoundVector position, velocity;
float pitch,gain;
float threadDelay;
bool terminated;
bufferSize=128*1024;
usesBuffers=0;//3;
threadDelay=0.01f;
~ALUREStream()
{
alureDestroyStream(stream, usesBuffers, buf);
delete source;
//unusedBuffers+=usesBuffers;
delete name;
delete buf;
}
inline bool Playing() { return ( source && source.state == playing ); }
// uint Main() { Sleep(threadDelay); DelayExpired(); return 0; }
void Stop() { if(created) { alureStopSource(source.id,AL_TRUE); } } //terminated = true; ((GuiApplication)__thisModule).Unlock(); Wait(); ((GuiApplication)__thisModule).Lock(); } }
#if defined(NEVER)
bool DelayExpired() {
while ( /*created && !badError &&*/ !terminated) {
ALint state = AL_PLAYING;
ALint processed = 0;
alureSleep(threadDelay);
if ( !source || source.state!=playing ) continue;
alGetError();
alGetSourcei(source.id, AL_SOURCE_STATE, &state);
alGetSourcei(source.id, AL_BUFFERS_PROCESSED, &processed);
// printf( "Processed: %d\n", processed );
// printf( "I: %s", alureGetErrorString());
if(processed > 0)
{
ALuint *bufs=new ALuint[usesBuffers];
ALsizei filled;
alSourceUnqueueBuffers(source.id, processed, bufs);
filled = alureBufferDataFromStream(stream, processed, bufs);
if(filled <= 0) {
if(loop) {
alureRewindStream(stream);
filled = alureBufferDataFromStream(stream, processed, bufs);
if(filled <= 0) {
printf( "ALUREStream:DelayExpiredinThread:Bad error when attempting to loop.\n" );
badError=true;
((GuiApplication)__thisModule).Lock(); OnError(); ((GuiApplication)__thisModule).Unlock();
delete bufs;
return false;
}
} else if(state != AL_PLAYING) {
((GuiApplication)__thisModule).Lock(); OnComplete(); ((GuiApplication)__thisModule).Unlock();
delete bufs;
return false;
}
}
alSourceQueueBuffers(source.id, filled, bufs);
delete bufs;
}
if(state != AL_PLAYING) { alSourcePlay(source.id); }
((GuiApplication)__thisModule).Lock(); BetweenFrames(); ((GuiApplication)__thisModule).Unlock();
}
// this.timer.delay = (1.0f/refreshRate);
// this.timer.Start();
return true;
}
#endif
bool LoadIntoSource(char *fn, ALSource s, bool CalcSize ) {
name=CopyString(fn);
if ( !source ) { printf("ALUREStream:Create complains the required source was not provided.\n" ); return false; }
//if ( usesBuffers > unusedBuffers ) { printf("ALUREStream:Create Not enough buffers available. Requested: %d Available: %d\n", usesBuffers, unusedBuffers ); return false; }
alGetError();
source=s;
if ( buf ) { printf( "ALUREStream:Create warns, the buffers were already created, was .Create() mistakenly called twice?\n" ); delete buf; }
buf=new ALuint[usesBuffers];
//unusedBuffers-=usesBuffers;
stream=alureCreateStreamFromFile((ALchar *) fn,bufferSize,0/*usesBuffers*/,null);//buf);
if ( !stream ) { printf( "ALUREStream:Create could not load the file: %s\n", fn, alureGetErrorString()); return false; }
if ( CalcSize ) CalculateSize(fn);
return (created=true);
}
virtual void OnComplete() { }
bool Play() {
if ( !this ) { printf( "ALUREStream:Play:Called on a null object.\n" ); return false; }
if ( !source ) { printf( "ALUREStream:Play:No source defined for the stream '%s'. Did it load properly?\n", name ); return false; }
if ( source.state == stopped ) {
printf ( "Play() was called on a stream.\n" );
alGetError();
// alSourceQueueBuffers(source.id,usesBuffers,buf);
// if ( ALError("ALUREStream:Play:alSourceQueueBuffers") ) { printf( "ALUREStream:Play failed to queue buffers.\n" ); return false; }
// alSourcePlay(source.id);
alurePlaySourceStream(source.id,stream,usesBuffers,0/*# of loops*/,null,null); // add eos_callback tie-in here
source.state=playing;
// if ( ALError("ALUREStream:Play:alSourcePlay") ) { printf( "ALUREStream:Play failed to start source.\n" ); return false; }
// this.timer.delay = (1.0f/refreshRate);
// this.timer.Start();
// Create();
} else if ( source.state == paused || source.state==stopped ) { source.Resume(); return true; }
else if ( source.state == empty ) { printf( "ALUREStream:Play called on an empty source (no buffer selected).\n" ); return false; }
else if ( source.state == playing ) { printf( "ALUREStream:Play() called on a playing stream.\n" ); return true; }
return true;
}
virtual void BetweenFrames() { }
virtual void OnError() { }
// Slightly inefficient, but precise.
int CalculateSize( char * fn ) {
ALuint total = 0;
ALuint b;
ALint freq = 0;
alureStream *s;
s = alureCreateStreamFromFile( (ALchar *) fn, 19200, 1, &b);
if(s) {
do {
ALint size, bits, channels;
alGetBufferi(b, AL_SIZE, &size);
alGetBufferi(b, AL_BITS, &bits);
alGetBufferi(b, AL_CHANNELS, &channels);
if(!freq) alGetBufferi(b, AL_FREQUENCY, &freq);
total += bits / channels * 8 / bits;
} while(alureBufferDataFromStream(s, 1, &b) > 0);
alureDestroyStream(s,1,&b);
}
duration=(float)total/(float)freq;
samples=(uint) total;
}
}