diff --git a/src/audio/OpenAL/Context.cpp b/src/audio/OpenAL/Context.cpp index dd33338afc39662d3b1327629bf64e9d75fff944..ae84dd842829c2334a9a508f879059728e615010 100644 --- a/src/audio/OpenAL/Context.cpp +++ b/src/audio/OpenAL/Context.cpp @@ -26,4 +26,5 @@ SFLAudio::Context::createSource(SFLAudio::Emitter *emitter) { Source *source = createSource(emitter->getFormat(), emitter->getFrequency()); emitter->connect(source); + return source; } diff --git a/src/audio/OpenAL/Makefile.am b/src/audio/OpenAL/Makefile.am index f4711b3d0cd13daf066ee43661c52ee5dae2364d..b1e55aec8d7c78c16da972e47e20980d68300087 100644 --- a/src/audio/OpenAL/Makefile.am +++ b/src/audio/OpenAL/Makefile.am @@ -23,12 +23,12 @@ libsflaudio_la_SOURCES = \ Source.cpp Source.hpp \ WavEmitter.cpp WavEmitter.hpp -AM_CPPFLAGS = $(PORTAUDIO_CFLAGS) -I$(top_srcdir)/libs/portaudio/pa_common -I$(top_srcdir)/libs/ -AM_CXXFLAGS = $(PORTAUDIO_CXXFLAGS) -I$(top_srcdir)/libs/ +AM_CPPFLAGS = -I$(top_srcdir)/libs/portaudio/pa_common -I$(top_srcdir)/libs/ +AM_CXXFLAGS = $(PORTAUDIO_CXXFLAGS) $(PORTAUDIO_CFLAGS) -I$(top_srcdir)/libs/ $(libccext2_CFLAGS) $(libccgnu2_CFLAGS) AM_LDFLAGS = -L$(top_srcdir)/libs/portaudio/ -LIBADD = $(PORTAUDIO_LIBS) -lportaudio -lopenal -lalut -LDADD = libsflaudio.la $(PORTAUDIO_LIBS) -lopenal -lportaudio -lalut +LIBADD = $(PORTAUDIO_LIBS) -lportaudio -lopenal -lalut +LDADD = libsflaudio.la $(PORTAUDIO_LIBS) -lopenal -lportaudio -lalut $(libccgnu2_LIBS) example01_SOURCES = example01.cpp diff --git a/src/audio/OpenAL/MicEmitter.cpp b/src/audio/OpenAL/MicEmitter.cpp index 319932cd899f992e529f8562b4cd340f04f336d5..723092452831577ef1e7786c493163b928e769d3 100644 --- a/src/audio/OpenAL/MicEmitter.cpp +++ b/src/audio/OpenAL/MicEmitter.cpp @@ -35,33 +35,87 @@ SFLAudio::MicEmitter::MicEmitter(int format, int freq, int size, , mAlCaptureStart(palCaptureStart) , mAlCaptureStop(palCaptureStop) , mAlCaptureGetData(palCaptureGetData) + , mThread(0) +{} + +void +SFLAudio::MicEmitter::play() +{ + if(mThread == 0) { + mAlCaptureStart(); + + mThread = new MicEmitterThread(getFormat(), getFrequency(), mSize, mAlCaptureGetData); + mThread->setSource(getSource()); + mThread->start(); + } +} + +void +SFLAudio::MicEmitter::stop() { + if(mThread != 0) { + delete mThread; + mThread = 0; + } +} + + +SFLAudio::MicEmitterThread::MicEmitterThread(int format, + int freq, + int size, + PFNALCAPTUREGETDATAPROC palCaptureGetData) + : mSource(0) + , mFormat(format) + , mFreq(freq) + , mSize(size) + , mAlCaptureGetData(palCaptureGetData) +{ + setCancel(cancelDeferred); mData = (ALchar *)malloc(mSize); } +SFLAudio::MicEmitterThread::~MicEmitterThread() +{ + terminate(); + free(mData); +} void -SFLAudio::MicEmitter::play() -{ - fprintf( stderr, "recording... " ); - mAlCaptureStart(); +SFLAudio::MicEmitterThread::setSource(SFLAudio::Source *source) { + mSource = source; +} +void +SFLAudio::MicEmitterThread::fill() { ALsizei retval = 0; + std::cout << "filling capture buffer...\n"; while(retval < mSize) { - void *data = &mData[retval]; - ALsizei size = mSize - retval; - retval += mAlCaptureGetData(&mData[retval], - mSize - retval, - getFormat(), - getFrequency()); + int size = mAlCaptureGetData(&mData[retval], + mSize - retval, + mFormat, + mFreq); + retval += size; + if(size != 0) + std::cout << "read " << size << + " bytes from capture, for a total of " << retval << std::endl; } - mAlCaptureStop(); + std::cout << "capture buffer filled!\n"; +} + +void +SFLAudio::MicEmitterThread::run() +{ + while (!testCancel()) { + if(mData) { + fill(); + } - std::cout << "done." << std::endl; - std::cout << "playing... "; - Source *source = getSource(); - if(source && mData) { - source->play(mData, mSize); + if(mSource && mData) { + mSource->stream(mData, mSize); + } + else { + std::cerr << "source or buffer invalid.\n"; + } + std::cout << "done." << std::endl; } - std::cout << "done." << std::endl; } diff --git a/src/audio/OpenAL/MicEmitter.hpp b/src/audio/OpenAL/MicEmitter.hpp index b20035e27033c9f81937c924c53abba2d3f7acc0..719686fe84606b77af1a587022e74f72d8047311 100644 --- a/src/audio/OpenAL/MicEmitter.hpp +++ b/src/audio/OpenAL/MicEmitter.hpp @@ -22,12 +22,34 @@ #define __SFLAUDIO_MIC_EMITTER_HPP__ #include <AL/al.h> +#include <cc++/thread.h> #include "Emitter.hpp" + namespace SFLAudio { class Source; + class MicEmitterThread : public ost::Thread + { + public: + MicEmitterThread(int format, int freq, int size, PFNALCAPTUREGETDATAPROC palCaptureGetData); + ~MicEmitterThread(); + + void setSource(SFLAudio::Source *source); + virtual void run(); + void fill(); + + private: + SFLAudio::Source *mSource; + ALchar *mData; + ALsizei mFormat; + ALsizei mFreq; + ALsizei mSize; + + PFNALCAPTUREGETDATAPROC mAlCaptureGetData; + }; + class MicEmitter : public Emitter { private: @@ -39,15 +61,18 @@ namespace SFLAudio PFNALCAPTURESTOPPROC palCaptureStop, PFNALCAPTUREGETDATAPROC palCaptureGetData); virtual void play(); + virtual void stop(); + private: - ALchar *mData; ALsizei mSize; - PFNALCAPTURESTARTPROC mAlCaptureStart; PFNALCAPTURESTOPPROC mAlCaptureStop; PFNALCAPTUREGETDATAPROC mAlCaptureGetData; + + MicEmitterThread* mThread; }; + } #endif diff --git a/src/audio/OpenAL/OpenALLayer.cpp b/src/audio/OpenAL/OpenALLayer.cpp index 74803e60227f0edd7d280da6ed1ca9b72230c327..83e1d0e9c63ad6813f9cd2e41c3132637aca27d2 100644 --- a/src/audio/OpenAL/OpenALLayer.cpp +++ b/src/audio/OpenAL/OpenALLayer.cpp @@ -33,9 +33,10 @@ #define DEFAULT_DEVICE_NAME "default" #define DEFAULT_CAPTURE_DEVICE_NAME "default" -#define FREQ 22050 +#define MIC_FORMAT AL_FORMAT_MONO8 +#define FREQ 8192 #define SAMPLES (5 * FREQ) -#define SIZE (SAMPLES * 2) +#define SIZE (SAMPLES * 1) #define GP(type,var,name) \ var = (type)alGetProcAddress((const ALchar*) name); \ @@ -63,12 +64,12 @@ SFLAudio::Emitter * SFLAudio::OpenALLayer::openCaptureDevice() { if(palCaptureInit == 0 || - !palCaptureInit( AL_FORMAT_MONO16, FREQ, 1024 ) ) { + !palCaptureInit( MIC_FORMAT, FREQ, 1024 ) ) { printf( "Unable to initialize capture\n" ); return new NullEmitter(); } - return new MicEmitter(AL_FORMAT_MONO16, FREQ, SIZE, + return new MicEmitter(MIC_FORMAT, FREQ, SIZE, palCaptureStart, palCaptureStop, palCaptureGetData); diff --git a/src/audio/OpenAL/OpenALSource.cpp b/src/audio/OpenAL/OpenALSource.cpp index eb5c6175d852f4f2d14a48ab9702f79962da6aa8..b6716ae1709e363509c3d5de3614456fe003277f 100644 --- a/src/audio/OpenAL/OpenALSource.cpp +++ b/src/audio/OpenAL/OpenALSource.cpp @@ -32,7 +32,11 @@ SFLAudio::OpenALSource::OpenALSource(int format, int freq, ALuint buffer, ALuint : Source(format, freq) , mBuffer(buffer) , mSource(source) -{} + , mIsAttached(false) + , mIsStatic(true) +{ + mBuffers.push_back(buffer); +} SFLAudio::OpenALSource::~OpenALSource() { @@ -44,10 +48,14 @@ SFLAudio::OpenALSource::~OpenALSource() std::cerr << "OpenAL: alDeleteSources : " << alGetString(error) << std::endl; } - alDeleteBuffers(1, &mBuffer); - error = alGetError(); - if(error != AL_NO_ERROR) { - std::cerr << "OpenAL: alDeleteBuffers : " << alGetString(error) << std::endl; + for(std::list< ALuint >::iterator pos = mBuffers.begin(); + pos != mBuffers.end(); + pos++) { + alDeleteBuffers(1, &(*pos)); + error = alGetError(); + if(error != AL_NO_ERROR) { + std::cerr << "OpenAL: alDeleteBuffers : " << alGetString(error) << std::endl; + } } } @@ -115,44 +123,125 @@ SFLAudio::OpenALSource::deleteBuffer(ALuint &buffer) { } bool -SFLAudio::OpenALSource::attach(ALuint source, ALuint buffer) { - // Attach buffer to source - alSourcei(source, AL_BUFFER, buffer); +SFLAudio::OpenALSource::detach() +{ + alSourcei(mSource, AL_BUFFER, 0); ALenum error = alGetError(); if(error != AL_NO_ERROR) { std::cerr << "OpenAL: alSourcei : " << alGetString(error); return false; } + mIsAttached = false; + return true; } -SFLAudio::Source * -SFLAudio::OpenALSource::create(OpenALContext *, int format, int freq) { - ALuint buffer; - ALuint source; +ALuint +SFLAudio::OpenALSource::getSourceState() +{ +// ALint answer; +// alGetError(); + +// alGetSourcei(mSource, AL_SOURCE_TYPE, &answer); +// ALenum error = alGetError(); +// if(error != AL_NO_ERROR) { +// std::cerr << "OpenAL: alGetSourcei(state) : " << alGetString(error); +// return AL_UNDETERMINED; +// } + +// return answer; - // Generate buffer - if(!genBuffer(buffer)){ - deleteBuffer(buffer); - return new NullSource(); - } + if(!mIsAttached) { + return AL_UNDETERMINED; + } - // Generate source - if(!genSource(source)){ - deleteBuffer(buffer); - deleteSource(source); - return new NullSource(); - } + if(mIsStatic) { + return AL_STATIC; + } + + return AL_STREAMING; +} - // Attach buffer to source - if(!attach(source, buffer)) { - deleteBuffer(buffer); - deleteSource(source); - return new NullSource(); +bool +SFLAudio::OpenALSource::isStatic() +{ + return (getSourceState() == AL_STATIC); +} + +bool +SFLAudio::OpenALSource::isUndetermined() +{ + return (getSourceState() == AL_UNDETERMINED); +} + +bool +SFLAudio::OpenALSource::isStreaming() +{ + return (getSourceState() == AL_STREAMING); +} + +bool +SFLAudio::OpenALSource::isAttached() +{ + return (getSourceState() != AL_UNDETERMINED); +} + +bool check(const char *message) { + ALenum error = alGetError(); + if(error != AL_NO_ERROR) { + std::cerr << message << alGetString(error); + return false; + } + + return true; +} + +bool +SFLAudio::OpenALSource::attach() +{ + if(isAttached()) { + if(isStatic() == true) { + // it's already attached as static + return true; } + + detach(); + } + + // Attach buffer to source + alSourcei(mSource, AL_BUFFER, mBuffer); + ALenum error = alGetError(); + if(error != AL_NO_ERROR) { + std::cerr << "OpenAL: alSourcei : " << alGetString(error); + return false; + } - return new OpenALSource(format, freq, buffer, source); + mIsAttached = true; + mIsStatic = true; + + return true; +} + +SFLAudio::Source * +SFLAudio::OpenALSource::create(OpenALContext *, int format, int freq) { + ALuint buffer; + ALuint source; + + // Generate buffer + if(!genBuffer(buffer)){ + deleteBuffer(buffer); + return new NullSource(); + } + + // Generate source + if(!genSource(source)){ + deleteBuffer(buffer); + deleteSource(source); + return new NullSource(); + } + + return new OpenALSource(format, freq, buffer, source); } @@ -172,16 +261,49 @@ SFLAudio::OpenALSource::isPlaying() void SFLAudio::OpenALSource::stream(void *data, int size) { + int processed; + ALuint buffer; + + alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed); + + if(processed == 0) { + if(genBuffer(buffer) == false) { + return; + } + + // Attach streaming buffer to source + alSourceQueueBuffers(mSource, 1, &buffer); + ALenum error = alGetError(); + if(error != AL_NO_ERROR) { + std::cerr << "OpenAL: alSourceQueueBuffers : " << alGetString(error); + return; + } + mBuffers.push_back(buffer); + + mIsAttached = true; + mIsStatic = false; + + } + else { + alSourceUnqueueBuffers(mSource, 1, &buffer); + } + + alBufferData(buffer, getFormat(), data, size, getFrequency()); + alSourceQueueBuffers(mSource, 1, &buffer); + + if(!isPlaying()) { + alSourcePlay(mSource); + } } void SFLAudio::OpenALSource::play(void *data, int size) { - ALboolean loop; + attach(); alGetError(); - // Copy test.wav data into AL Buffer 0 + // Copy data into AL Buffer alBufferData(mBuffer, getFormat(), data, size, getFrequency()); ALenum error = alGetError(); if (error != AL_NO_ERROR) { diff --git a/src/audio/OpenAL/OpenALSource.hpp b/src/audio/OpenAL/OpenALSource.hpp index 09e0b6d04d89da7ed3c3755f24eeef2a5c8b0ef1..42b92b05cbf462fdc87dcbff7698ca9bf9fb5f93 100644 --- a/src/audio/OpenAL/OpenALSource.hpp +++ b/src/audio/OpenAL/OpenALSource.hpp @@ -21,6 +21,8 @@ #ifndef __SFLAUDIO_OPENAL_SOURCE_HPP__ #define __SFLAUDIO_OPENAL_SOURCE_HPP__ +#include <list> + #include <AL/al.h> #include <AL/alc.h> #include "Source.hpp" @@ -47,19 +49,34 @@ namespace SFLAudio virtual void stop(); private: + ALuint getSourceState(); + bool isStatic(); + bool isAttached(); + bool isStreaming(); + bool isUndetermined(); + bool attach(); + bool detach(); + + bool check(const char *message); + static bool genBuffer(ALuint &buffer); static bool genSource(ALuint &source); static bool deleteBuffer(ALuint &buffer); static bool deleteSource(ALuint &source); - static bool attach(ALuint source, ALuint buffer); private: + // Buffers that we'll eventually need to delete + std::list< ALuint > mBuffers; + // Buffers to hold sound data. ALuint mBuffer; // Sources are points of emitting sound. ALuint mSource; + + bool mIsAttached; + bool mIsStatic; }; } diff --git a/src/audio/OpenAL/README.txt b/src/audio/OpenAL/README.txt index 6233b5d8029059b2182ddc77e17004bcc414ef8f..6006f0f69bd08d61096afc02db837c08c63bddb6 100644 --- a/src/audio/OpenAL/README.txt +++ b/src/audio/OpenAL/README.txt @@ -3,3 +3,4 @@ example02.cpp: A simple WAV player with a direct handling of sound buffer. example03.cpp: A simple WAV player, with 2 files playing at the same time. example04.cpp: A simple WAV player. (Uses the simple WavEmitter class) example05.cpp: A Capture example. +example06.cpp: A OGG streaming example. \ No newline at end of file