Revision: 7275 http://playerstage.svn.sourceforge.net/playerstage/?rev=7275&view=rev Author: natepak Date: 2009-01-16 04:32:09 +0000 (Fri, 16 Jan 2009)
Log Message: ----------- Added audio_video directory Modified Paths: -------------- code/gazebo/trunk/server/SConscript code/gazebo/trunk/server/rendering/UserCamera.cc Added Paths: ----------- code/gazebo/trunk/server/audio_video/ code/gazebo/trunk/server/audio_video/AudioDecoder.cc code/gazebo/trunk/server/audio_video/AudioDecoder.hh code/gazebo/trunk/server/audio_video/OpenAL.cc code/gazebo/trunk/server/audio_video/OpenAL.hh code/gazebo/trunk/server/audio_video/SConscript Modified: code/gazebo/trunk/server/SConscript =================================================================== --- code/gazebo/trunk/server/SConscript 2009-01-15 23:15:17 UTC (rev 7274) +++ code/gazebo/trunk/server/SConscript 2009-01-16 04:32:09 UTC (rev 7275) @@ -1,7 +1,7 @@ #Import variables Import('env install_prefix sharedObjs headers') -dirs = Split('physics rendering sensors controllers gui')# bindings') +dirs = Split('physics rendering sensors controllers gui audio_video')# bindings') for subdir in dirs: SConscript('%s/SConscript' % subdir) Added: code/gazebo/trunk/server/audio_video/AudioDecoder.cc =================================================================== --- code/gazebo/trunk/server/audio_video/AudioDecoder.cc (rev 0) +++ code/gazebo/trunk/server/audio_video/AudioDecoder.cc 2009-01-16 04:32:09 UTC (rev 7275) @@ -0,0 +1,173 @@ +#include <stdlib.h> +#include <string.h> + +#include "AudioDecoder.hh" + +bool AudioDecoder::initialized = false; + +//////////////////////////////////////////////////////////////////////////////// +/// Constructor +AudioDecoder::AudioDecoder() +{ + this->formatCtx = NULL; + this->codecCtx = NULL; + this->codec = NULL; + this->audioStream = 0; + + // Initialize the ffmpeg library only once + if (!initialized) + { + initialized = true; + avcodec_init(); + avcodec_register_all(); + + // Register all formats and codecs + av_register_all(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Destructor +AudioDecoder::~AudioDecoder() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +/// Decode and audio file +int AudioDecoder::Decode(uint8_t **outBuffer, unsigned int *outBufferSize) +{ + AVPacket packet; + char tmpBuf[AVCODEC_MAX_AUDIO_FRAME_SIZE]; + int tmpBufsize = 0; + int bytesDecoded = 0; + unsigned int maxBufferSize = 0; + + if (this->codec == NULL) + { + printf("Set and audio file before decoding.\n"); + return -1; + } + + if (outBufferSize == NULL) + { + printf("outBufferSize is NULL!!\n"); + return -1; + } + + *outBufferSize = 0; + + if (*outBuffer) + { + delete [] *outBuffer; + *outBuffer = NULL; + } + + // Read the next frame of a stream + while (av_read_frame(this->formatCtx, &packet) >=0) + { + if (packet.stream_index == this->audioStream) + { + tmpBufsize = sizeof(tmpBuf); + + // Decode the frame + bytesDecoded = avcodec_decode_audio2( this->codecCtx, (int16_t*)tmpBuf, + &tmpBufsize, packet.data, packet.size ); + + if (bytesDecoded < 0) + { + printf("Error decoding audio\n"); + return -1; + } + + if (tmpBufsize <= 0) + { + printf("No data yet\n"); + return -1; + } + + // Resize the audio buffer as necessary + if (*outBufferSize + tmpBufsize > maxBufferSize) + { + maxBufferSize += tmpBufsize * 10; + *outBuffer = (uint8_t*)realloc(*outBuffer, + maxBufferSize * sizeof(*outBuffer[0]) ); + } + + memcpy(*outBuffer + *outBufferSize, tmpBuf, tmpBufsize); + *outBufferSize += tmpBufsize; + } + } + + av_free_packet(&packet); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get the sample rate from the latest decoded file +int AudioDecoder::GetSampleRate() +{ + return this->codecCtx->sample_rate; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Helper function to read in an audio file +int AudioDecoder::SetFile(const std::string &filename) +{ + unsigned int i; + + // Open file + if (av_open_input_file(&this->formatCtx, filename.c_str(), NULL, 0, NULL) != 0) + { + printf("Unable to open input file\n"); + return -1; + } + + // Retrieve some information + if (av_find_stream_info(this->formatCtx) < 0) + { + printf("Unable to find stream info\n"); + return -1; + } + + // Dump information about file onto standard error + //dump_format(formatCtx, 0, "dump.txt", false); + + // Find audio stream; + this->audioStream = -1; + for (i=0; i < this->formatCtx->nb_streams; i++) + { + if (this->formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) + { + this->audioStream = i; + break; + } + } + + if (this->audioStream == -1) + { + printf("Couldn't find audio stream\n"); + return -1; + } + + // Get the audio stream codec + this->codecCtx = this->formatCtx->streams[audioStream]->codec; + + // Find a decoder + this->codec = avcodec_find_decoder(codecCtx->codec_id); + + if (this->codec == NULL) + { + perror("couldn't find codec"); + return -1; + } + + if (this->codec->capabilities & CODEC_CAP_TRUNCATED) + this->codecCtx->flags |= CODEC_FLAG_TRUNCATED; + + // Open codec + if (avcodec_open(this->codecCtx, this->codec) < 0) + perror("couldn't open codec"); + + return 0; +} Added: code/gazebo/trunk/server/audio_video/AudioDecoder.hh =================================================================== --- code/gazebo/trunk/server/audio_video/AudioDecoder.hh (rev 0) +++ code/gazebo/trunk/server/audio_video/AudioDecoder.hh 2009-01-16 04:32:09 UTC (rev 7275) @@ -0,0 +1,40 @@ +#ifndef AUDIODECODER_HH +#define AUDIODECODER_HH + +extern "C" { +#include <libavformat/avformat.h> +#include <libavcodec/avcodec.h> +} + +#include <string> + +class AudioDecoder +{ + /// \brief Constructor + public: AudioDecoder(); + + /// \brief Destructor + public: virtual ~AudioDecoder(); + + /// \brief Set the file to decode + public: int SetFile(const std::string &filename); + + /// \brief Decode and audio file + public: int Decode(uint8_t **outBuffer, unsigned int *outBufferSize); + + /// \brief Get the sample rate from the latest decoded file + public: int GetSampleRate(); + + private: AVFormatContext *formatCtx; + private: AVCodecContext *codecCtx; + + // libavcodec audio codec + private: AVCodec *codec; + + // Index of the audio stream + private: int audioStream; + + private: static bool initialized; +}; + +#endif Added: code/gazebo/trunk/server/audio_video/OpenAL.cc =================================================================== --- code/gazebo/trunk/server/audio_video/OpenAL.cc (rev 0) +++ code/gazebo/trunk/server/audio_video/OpenAL.cc 2009-01-16 04:32:09 UTC (rev 7275) @@ -0,0 +1,396 @@ +#include <stdio.h> +#include <unistd.h> +#include <iostream> + +#include <AL/alut.h> +#include <AL/alc.h> + +#include "AudioDecoder.hh" +#include "OpenAL.hh" + +#ifndef NULL +#define NULL 0 +#endif + + +//////////////////////////////////////////////////////////////////////////////// +///// Constructor +OpenAL::OpenAL() +{ + this->context = NULL; + this->audioDevice = NULL; + + this->pos[0] = this->pos[1] = this->pos[2] = 0.0; + this->pos[0] = -10.0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Destructor +OpenAL::~OpenAL() +{ + if (this->context && this->audioDevice) + { + this->context = alcGetCurrentContext(); + this->audioDevice = alcGetContextsDevice(this->context); + alcMakeContextCurrent(NULL); + alcDestroyContext(this->context); + alcCloseDevice(this->audioDevice); + } + + this->sources.clear(); + this->buffers.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Initialize +int OpenAL::Init() +{ + // Open the default audio device + this->audioDevice = alcOpenDevice("ALSA Software on HDA Intel"); + if (this->audioDevice == NULL) + { + printf("Unable to open audio device\n"); + return -1; + } + + this->context = alcCreateContext(this->audioDevice, NULL); + + alcMakeContextCurrent(this->context); + + //Clear error code + alGetError(); + + // TODO: put in function to set distance model + //alDistanceModel(AL_EXPONENT_DISTANCE); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Create a sound source +unsigned int OpenAL::CreateSource() +{ + unsigned int source; + + //Create 1 source + alGenSources(1, &source); + + this->sources.push_back(source); + + return this->sources.size()-1; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Create an audio data buffer +unsigned int OpenAL::CreateBuffer(const std::string &audioFile) +{ + unsigned int buffer; + uint8_t *dataBuffer = NULL; + unsigned int dataBufferSize; + + // Create an audio decoder + AudioDecoder audioDecoder; + + // Create and openAL audio buffer + alGenBuffers(1, &buffer); + + // Store the openAL buffer + this->buffers.push_back(buffer); + + // Set the audio file to decode + audioDecoder.SetFile(audioFile); + audioDecoder.Decode(&dataBuffer, &dataBufferSize); + + // Fill the openAL data buffer + this->SetData(buffer, dataBuffer, dataBufferSize, + audioDecoder.GetSampleRate() ); + + if (dataBuffer) + delete [] dataBuffer; + + return this->buffers.size()-1; +} + + +//////////////////////////////////////////////////////////////////////////////// +/// Update all the sources and the listener +void OpenAL::Update() +{ + //ALfloat pos[3]; + ALfloat vel[3]; + + //for (int i=0; i< this->sourceCount; i++) + { + + //alGetSourcefv(0, AL_VELOCITY, vel); + //alGetSourcefv(0, AL_POSITION, pos); + + vel[0] = 0.1; + vel[1] = 0.0; + vel[2] = 0.0; + + this->pos[0] += 0.01; + this->pos[1] = 0; + this->pos[2] = 0; + + //printf("p[%f %f %f] v[%f %f %f]\n", pos[0], pos[1], pos[2], vel[0], vel[1], vel[2]); + this->SetSourcePos(0, this->pos[0], this->pos[1], this->pos[2] ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set the data +int OpenAL::SetData(unsigned int index, uint8_t *data, unsigned int dataSize, unsigned int freq) +{ + // Clear the error buffer; + alGetError(); + + printf("Set Data Freq[%d] DataSize[%d]\n",freq, dataSize); + + // Copy raw buffer into AL buffer 0 + // AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, + // AL_FORMAT_STEREO16 + alBufferData( this->buffers[0], AL_FORMAT_MONO16, data, dataSize, freq); + + if ( alGetError() != AL_NO_ERROR) + { + printf("Unable to copy data into openAL buffer\n"); + + alDeleteBuffers(1, &this->buffers[index]); + return -1; + } + + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief Attach a buffer to a source +int OpenAL::SetSourceBuffer(unsigned int sourceIndex, unsigned int bufferIndex) +{ + if (sourceIndex >= this->sources.size()) + { + std::cerr << "Invalid source index\n"; + return -1; + } + + if (bufferIndex >= this->buffers.size()) + { + std::cerr << "Invalid buffer index\n"; + return -1; + } + + // Buffer data must be set before calling this function + + // Attach buffer to source + alSourcei(this->sources[sourceIndex], AL_BUFFER, this->buffers[bufferIndex] ); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL SetSourceBuffer Error: [%d]\n" << this->error << "\n"; + return -1; + } + + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Play the source +void OpenAL::Play( unsigned int index ) +{ + // Play the source + alSourcePlay( this->sources[index] ); + + + // Wait until finished + /*ALint state; + do + { + usleep(100000); + alGetSourcei(this->sources[index], AL_SOURCE_STATE, &state); + } while ( state == AL_PLAYING); + */ + +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set the listener position +int OpenAL::SetListenerPos( float x, float y, float z ) +{ + // Clear error state + alGetError(); + + alListener3f(AL_POSITION, x, y, z); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL SetListenerPos Error: [%d]\n" << this->error << "\n"; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set the listener velocity +int OpenAL::SetListenerVel( float x, float y, float z ) +{ + // Clear error state + alGetError(); + + alListener3f(AL_VELOCITY, x, y, z); + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL SetListenerVel Error: [%d]" << this->error << "\n"; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set the listener orientation +int OpenAL::SetListenerOrient( float cx, float cy, float cz, + float ux, float uy, float uz ) +{ + ALfloat orient[]={cx, cy, cz, ux, uy, uz}; + + // Clear error state + alGetError(); + + alListenerfv( AL_ORIENTATION, orient ); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL SetListenerOrientation Error: [%d]" << this->error << "\n"; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the position of the source +int OpenAL::SetSourcePos(unsigned int index, float x, float y, float z) +{ + ALfloat p[3] = {x, y, z}; + + if (index >= this->sources.size()) + { + std::cerr << "Invalid source index[" << index <<" ]\n"; + return -1; + } + + // Clear error state + alGetError(); + + alSourcefv( this->sources[index], AL_POSITION, p); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL::SetSourcePos Error: [%d]" << this->error << "\n"; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the position of the source +int OpenAL::SetSourceVel(unsigned int index, float x, float y, float z) +{ + ALfloat v[3] = {x, y, z}; + + if (index >= this->sources.size()) + { + std::cerr << "Invalid source index[" << index <<" ]\n"; + return -1; + } + + // Clear error state + alGetError(); + + alSourcefv( this->sources[index], AL_VELOCITY, v); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL::SetSourceVel Error: [%d]" << this->error << "\n"; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the pitch of the source +int OpenAL::SetSourcePitch(unsigned int index, float p) +{ + if (index >= this->sources.size()) + { + std::cerr << "Invalid source index[" << index <<" ]\n"; + return -1; + } + + // clear error state + alGetError(); + + alSourcef(this->sources[index], AL_PITCH, p); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL::SetSourcePitch Error: [%d]\n" << this->error; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the pitch of the source +int OpenAL::SetSourceGain(unsigned int index, float g) +{ + if (index >= this->sources.size()) + { + std::cerr << "Invalid source index[" << index <<" ]\n"; + return -1; + } + + // clear error state + alGetError(); + + alSourcef(this->sources[index], AL_GAIN, g); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL::SetSourceGain Error: [%d]\n" << this->error; + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set whether the source loops the audio +int OpenAL::SetSourceLoop(unsigned int index, bool state) +{ + if (index >= this->sources.size()) + { + std::cerr << "Invalid source index[" << index <<" ]\n"; + return -1; + } + + // clear error state + alGetError(); + + // Set looping state + alSourcei(this->sources[index], AL_LOOPING, state); + + if ((this->error = alGetError()) != AL_NO_ERROR) + { + std::cerr << "OpenAL::SetSourceLoop Error: [%d]\n" << this->error << "\n"; + return -1; + } + + + return 0; +} Added: code/gazebo/trunk/server/audio_video/OpenAL.hh =================================================================== --- code/gazebo/trunk/server/audio_video/OpenAL.hh (rev 0) +++ code/gazebo/trunk/server/audio_video/OpenAL.hh 2009-01-16 04:32:09 UTC (rev 7275) @@ -0,0 +1,81 @@ +#ifndef OPENAL_HH +#define OPENAL_HH + +#include <AL/al.h> +#include <AL/alc.h> +#include <AL/alext.h> +#include <stdint.h> + +#include <deque> + + +class OpenAL +{ + /// \brief Constructor + public: OpenAL(); + + /// \brief Destructor + public: virtual ~OpenAL(); + + /// \brief Initialize + public: int Init(); + + /// \brief Update all the sources and the listener + public: void Update(); + + /// \brief Create a sound source + public: unsigned int CreateSource(); + + /// \brief Create an audio data buffer + public: unsigned int CreateBuffer(const std::string &audioFile); + + /// \brief Set the data + public: int SetData(unsigned int index, uint8_t *data, unsigned int dataSize, unsigned int freq); + + /// \brief Attach a buffer to a source + public: int SetSourceBuffer(unsigned int sourceIndex, unsigned int bufferIndex); + + /// \brief Play a sound + public: void Play(unsigned int source); + + /// \brief Set the listener position + public: int SetListenerPos( float x, float y, float z ); + + /// \brief Set the listener velocity + public: int SetListenerVel( float x, float y, float z ); + + /// \brief Set the listener orientation + public: int SetListenerOrient(float cx, float cy, float cz, + float ux, float uy, float uz); + + /// \brief Set the position of the source + public: int SetSourcePos(unsigned int index, float x, float y, float z); + + /// \brief Set the position of the source + public: int SetSourceVel(unsigned int index, float x, float y, float z); + + /// \brief Set the pitch of the source + public: int SetSourcePitch(unsigned int index, float p); + + /// \brief Set the pitch of the source + public: int SetSourceGain(unsigned int index, float g); + + /// \brief Set whether the source loops the audio + public: int SetSourceLoop(unsigned int index, bool state); + + private: ALCcontext *context; + private: ALCdevice *audioDevice; + + // OpenAL error code + private: ALenum error; + + // Audio sources. + private: std::deque<unsigned int> sources; + + // Audio data buffers + private: std::deque<unsigned int> buffers; + + private: ALfloat pos[3]; +}; + +#endif Added: code/gazebo/trunk/server/audio_video/SConscript =================================================================== --- code/gazebo/trunk/server/audio_video/SConscript (rev 0) +++ code/gazebo/trunk/server/audio_video/SConscript 2009-01-16 04:32:09 UTC (rev 7275) @@ -0,0 +1,41 @@ +#Import variable +Import('env sharedObjs headers') + +parseConfigs = [ + 'pkg-config --cflags --libs libavformat', + 'pkg-config --cflags --libs libavcodec', + 'pkg-config --cflags --libs openal', + 'pkg-config --cflags --libs freealut' +] + +myEnv = env.Clone() + +sources = ['AudioDecoder.cc', + 'OpenAL.cc' + ] + +headers.append( + ['server/audio_video/AudioDecoder.hh', + 'server/audio_video/OpenAL.hh', + ] ) +# +# Parse all the pacakge configurations +# +if not myEnv.GetOption('clean'): + for cfg in parseConfigs: + print "Checking for ["+cfg+"]" + try: + myEnv.ParseConfig(cfg) + print " Success" + except OSError,e: + print "Unable to parse config ["+cfg+"]" + if cfg.find("OpenAL") >= 0: + print "OpenAL not found. 3D audio is disabled." + print " http://connect.creativelabs.com/" + Exit(1) + if cfg.find("avcodec") >= 0 or cfg.find("avformat") >= 0: + print "FFMpeg not found. Audio decoding disabled." + print " http://ffmpeg.mplayerhq.hu/" + Exit(1) + +myEnv.SharedLibrary('gazeboav', sources) Modified: code/gazebo/trunk/server/rendering/UserCamera.cc =================================================================== --- code/gazebo/trunk/server/rendering/UserCamera.cc 2009-01-15 23:15:17 UTC (rev 7274) +++ code/gazebo/trunk/server/rendering/UserCamera.cc 2009-01-16 04:32:09 UTC (rev 7275) @@ -65,7 +65,7 @@ { OgreCamera::LoadCam(node); - this->SetClipDist(0.1, 100); + this->SetClipDist(0.1, 50); this->SetFOV( DTOR(60) ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ This SF.net email is sponsored by: SourcForge Community SourceForge wants to tell your story. http://p.sf.net/sfu/sf-spreadtheword _______________________________________________ Playerstage-commit mailing list Playerstage-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/playerstage-commit