From 8b30a91774f141970412714726744b253eb1da9b Mon Sep 17 00:00:00 2001 From: Krisjanis Rijnieks Date: Tue, 17 Nov 2020 21:27:26 +0200 Subject: [PATCH] Add ofOpenALSoundPlayer patch for msys2 testing --- ofpatch/msys2/sound/ofOpenALSoundPlayer.cpp | 1076 +++++++++++++++++++ ofpatch/msys2/sound/ofOpenALSoundPlayer.h | 157 +++ 2 files changed, 1233 insertions(+) create mode 100644 ofpatch/msys2/sound/ofOpenALSoundPlayer.cpp create mode 100644 ofpatch/msys2/sound/ofOpenALSoundPlayer.h diff --git a/ofpatch/msys2/sound/ofOpenALSoundPlayer.cpp b/ofpatch/msys2/sound/ofOpenALSoundPlayer.cpp new file mode 100644 index 0000000..9ae533e --- /dev/null +++ b/ofpatch/msys2/sound/ofOpenALSoundPlayer.cpp @@ -0,0 +1,1076 @@ +#include "ofOpenALSoundPlayer.h" + +#ifdef OF_SOUND_PLAYER_OPENAL + +#include "ofConstants.h" +#include "glm/gtc/constants.hpp" +#include "glm/common.hpp" +#include "ofLog.h" +#include "ofEvents.h" +#include + +#if defined (TARGET_OF_IOS) || defined (TARGET_OSX) +#include +#include +#else +#include +#include +#endif + +#ifdef OF_USING_MPG123 +#include +#endif + +using namespace std; + +static ALCdevice * alDevice = nullptr; +static ALCcontext * alContext = nullptr; +vector ofOpenALSoundPlayer::window; +float ofOpenALSoundPlayer::windowSum = 0.f; + + +kiss_fftr_cfg ofOpenALSoundPlayer::systemFftCfg=0; +vector ofOpenALSoundPlayer::systemWindowedSignal; +vector ofOpenALSoundPlayer::systemBins; +vector ofOpenALSoundPlayer::systemCx_out; + +static set & players(){ + static set * players = new set; + return *players; +} + +void ofOpenALSoundUpdate(){ + alcProcessContext(alContext); +} + +// ---------------------------------------------------------------------------- +// from http://devmaster.net/posts/2893/openal-lesson-6-advanced-loading-and-error-handles +static string getALErrorString(ALenum error) { + switch(error) { + case AL_NO_ERROR: + return "AL_NO_ERROR"; + case AL_INVALID_NAME: + return "AL_INVALID_NAME"; + case AL_INVALID_ENUM: + return "AL_INVALID_ENUM"; + case AL_INVALID_VALUE: + return "AL_INVALID_VALUE"; + case AL_INVALID_OPERATION: + return "AL_INVALID_OPERATION"; + case AL_OUT_OF_MEMORY: + return "AL_OUT_OF_MEMORY"; + }; + return "UNKWOWN_ERROR"; +} + +static string getALCErrorString(ALCenum error) { + switch(error) { + case ALC_NO_ERROR: + return "ALC_NO_ERROR"; + case ALC_INVALID_DEVICE: + return "ALC_INVALID_DEVICE"; + case ALC_INVALID_CONTEXT: + return "ALC_INVALID_CONTEXT"; + case ALC_INVALID_ENUM: + return "ALC_INVALID_ENUM"; + case ALC_INVALID_VALUE: + return "ALC_INVALID_VALUE"; + case ALC_OUT_OF_MEMORY: + return "ALC_OUT_OF_MEMORY"; + }; + return "UNKWOWN_ERROR"; +} + +#ifdef OF_USING_MPG123 +static string getMpg123EncodingString(int encoding) { + switch(encoding) { + case MPG123_ENC_16: + return "MPG123_ENC_16"; +#if MPG123_API_VERSION>=36 + case MPG123_ENC_24: + return "MPG123_ENC_24"; +#endif + case MPG123_ENC_32: + return "MPG123_ENC_32"; + case MPG123_ENC_8: + return "MPG123_ENC_8"; + case MPG123_ENC_ALAW_8: + return "MPG123_ENC_ALAW_8"; + case MPG123_ENC_FLOAT: + return "MPG123_ENC_FLOAT"; + case MPG123_ENC_FLOAT_32: + return "MPG123_ENC_FLOAT_32"; + case MPG123_ENC_FLOAT_64: + return "MPG123_ENC_FLOAT_64"; + case MPG123_ENC_SIGNED: + return "MPG123_ENC_SIGNED"; + case MPG123_ENC_SIGNED_16: + return "MPG123_ENC_SIGNED_16"; +#if MPG123_API_VERSION>=36 + case MPG123_ENC_SIGNED_24: + return "MPG123_ENC_SIGNED_24"; +#endif + case MPG123_ENC_SIGNED_32: + return "MPG123_ENC_SIGNED_32"; + case MPG123_ENC_SIGNED_8: + return "MPG123_ENC_SIGNED_8"; + case MPG123_ENC_ULAW_8: + return "MPG123_ENC_ULAW_8"; + case MPG123_ENC_UNSIGNED_16: + return "MPG123_ENC_UNSIGNED_16"; +#if MPG123_API_VERSION>=36 + case MPG123_ENC_UNSIGNED_24: + return "MPG123_ENC_UNSIGNED_24"; +#endif + case MPG123_ENC_UNSIGNED_32: + return "MPG123_ENC_UNSIGNED_32"; + case MPG123_ENC_UNSIGNED_8: + return "MPG123_ENC_UNSIGNED_8"; + default: + return "MPG123_ENC_ANY"; + } +} +#endif + +#define BUFFER_STREAM_SIZE 4096 + +// now, the individual sound player: +//------------------------------------------------------------ +ofOpenALSoundPlayer::ofOpenALSoundPlayer(){ + bLoop = false; + bLoadedOk = false; + pan = 0.0f; // range for oF is -1 to 1, + volume = 1.0f; + internalFreq = 44100; + speed = 1; + bPaused = false; + isStreaming = false; + channels = 0; + duration = 0; + fftCfg = 0; + streamf = 0; +#ifdef OF_USING_MPG123 + mp3streamf = 0; +#endif + players().insert(this); +} + +// ---------------------------------------------------------------------------- +ofOpenALSoundPlayer::~ofOpenALSoundPlayer(){ + unload(); + kiss_fftr_free(fftCfg); + players().erase(this); + if( players().empty() ){ + close(); + } +} + +//--------------------------------------- +// this should only be called once +void ofOpenALSoundPlayer::initialize(){ + if( !alDevice ){ + alDevice = alcOpenDevice( nullptr ); + if( !alDevice ){ + ofLogError("ofOpenALSoundPlayer") << "initialize(): couldn't open OpenAL default device"; + return; + }else{ + ofLogVerbose("ofOpenALSoundPlayer") << "initialize(): opening "<< alcGetString( alDevice, ALC_DEVICE_SPECIFIER ); + } + // Create OpenAL context and make it current. If fails, close the OpenAL device that was just opened. + alContext = alcCreateContext( alDevice, nullptr ); + if( !alContext ){ + ALCenum err = alcGetError( alDevice ); + ofLogError("ofOpenALSoundPlayer") << "initialize(): couldn't not create OpenAL context : "<< getALCErrorString( err ); + close(); + return; + } + + if( alcMakeContextCurrent( alContext )==ALC_FALSE ){ + ALCenum err = alcGetError( alDevice ); + ofLogError("ofOpenALSoundPlayer") << "initialize(): couldn't not make current the create OpenAL context : "<< getALCErrorString( err ); + close(); + return; + }; + alListener3f( AL_POSITION, 0,0,0 ); +#ifdef OF_USING_MPG123 + mpg123_init(); +#endif + + } + ofLogVerbose("ofOpenALSoundPlayer") << "initialize(): Done"; +} + +//--------------------------------------- +void ofOpenALSoundPlayer::createWindow(int size){ + if(int(window.size())!=size){ + windowSum = 0; + window.resize(size); + // hanning window + for(int i = 0; i < size; i++){ + window[i] = .54 - .46 * cos((glm::two_pi() * i) / (size - 1)); + windowSum += window[i]; + } + } +} + +//--------------------------------------- +void ofOpenALSoundPlayer::close(){ + // Destroy the OpenAL context (if any) before closing the device + if( alDevice ){ + if( alContext ){ +#ifdef OF_USING_MPG123 + mpg123_exit(); +#endif + alcMakeContextCurrent(nullptr); + alcDestroyContext(alContext); + alContext = nullptr; + } + if( alcCloseDevice( alDevice )==ALC_FALSE ){ + ofLogNotice("ofOpenALSoundPlayer") << "initialize(): error closing OpenAL device."; + } + alDevice = nullptr; + } +} + +// ---------------------------------------------------------------------------- +bool ofOpenALSoundPlayer::sfReadFile(const std::filesystem::path& path, vector & buffer, vector & fftAuxBuffer){ + SF_INFO sfInfo; + SNDFILE* f = sf_open(path.string().c_str(),SFM_READ,&sfInfo); + if(!f){ + ofLogError("ofOpenALSoundPlayer") << "sfReadFile(): couldn't read \"" << path << "\""; + return false; + } + + buffer.resize(sfInfo.frames*sfInfo.channels); + fftAuxBuffer.resize(sfInfo.frames*sfInfo.channels); + + int subformat = sfInfo.format & SF_FORMAT_SUBMASK ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE){ + double scale ; + sf_command (f, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ; + if (scale < 1e-10) + scale = 1.0 ; + else + scale = 32700.0 / scale ; + + sf_count_t samples_read = sf_read_float (f, &fftAuxBuffer[0], fftAuxBuffer.size()); + if(samples_read<(int)fftAuxBuffer.size()){ + ofLogWarning("ofOpenALSoundPlayer") << "sfReadFile(): read " << samples_read << " float samples, expected " + << fftAuxBuffer.size() << " for \"" << path << "\""; + } + for (int i = 0 ; i < int(fftAuxBuffer.size()) ; i++){ + fftAuxBuffer[i] *= scale ; + buffer[i] = 32565.0 * fftAuxBuffer[i]; + } + }else{ + sf_count_t frames_read = sf_readf_short(f,&buffer[0],sfInfo.frames); + if(frames_read & buffer,vector & fftAuxBuffer){ + int err = MPG123_OK; + mpg123_handle * f = mpg123_new(nullptr,&err); + if(mpg123_open(f,path.string().c_str())!=MPG123_OK){ + ofLogError("ofOpenALSoundPlayer") << "mpg123ReadFile(): couldn't read \"" << path << "\""; + return false; + } + + mpg123_enc_enum encoding; + long int rate; + mpg123_getformat(f,&rate,&channels,(int*)&encoding); + if(encoding!=MPG123_ENC_SIGNED_16){ + ofLogError("ofOpenALSoundPlayer") << "mpg123ReadFile(): " << getMpg123EncodingString(encoding) + << " encoding for \"" << path << "\"" << " unsupported, expecting MPG123_ENC_SIGNED_16"; + return false; + } + samplerate = rate; + + size_t done=0; + size_t buffer_size = mpg123_outblock( f ); + buffer.resize(buffer_size/2); + while(mpg123_read(f,(unsigned char*)&buffer[buffer.size()-buffer_size/2],buffer_size,&done)!=MPG123_DONE){ + buffer.resize(buffer.size()+buffer_size/2); + }; + buffer.resize(buffer.size()-(buffer_size/2-done/2)); + mpg123_close(f); + mpg123_delete(f); + + fftAuxBuffer.resize(buffer.size()); + for(int i=0;i<(int)buffer.size();i++){ + fftAuxBuffer[i] = float(buffer[i])/32565.f; + } + duration = float(buffer.size()/channels) / float(samplerate); + return true; +} +#endif + +//------------------------------------------------------------ +bool ofOpenALSoundPlayer::sfStream(const std::filesystem::path& path,vector & buffer,vector & fftAuxBuffer){ + if(!streamf){ + SF_INFO sfInfo; + streamf = sf_open(path.string().c_str(),SFM_READ,&sfInfo); + if(!streamf){ + ofLogError("ofOpenALSoundPlayer") << "sfStream(): couldn't read \"" << path << "\""; + return false; + } + + stream_subformat = sfInfo.format & SF_FORMAT_SUBMASK ; + if (stream_subformat == SF_FORMAT_FLOAT || stream_subformat == SF_FORMAT_DOUBLE){ + sf_command (streamf, SFC_CALC_SIGNAL_MAX, &stream_scale, sizeof (stream_scale)) ; + if (stream_scale < 1e-10) + stream_scale = 1.0 ; + else + stream_scale = 32700.0 / stream_scale ; + } + channels = sfInfo.channels; + duration = float(sfInfo.frames) / float(sfInfo.samplerate); + samplerate = sfInfo.samplerate; + stream_samples_read = 0; + } + + int curr_buffer_size = BUFFER_STREAM_SIZE*channels; + if(speed>1) curr_buffer_size *= (int)round(speed); + buffer.resize(curr_buffer_size); + fftAuxBuffer.resize(buffer.size()); + if (stream_subformat == SF_FORMAT_FLOAT || stream_subformat == SF_FORMAT_DOUBLE){ + sf_count_t samples_read = sf_read_float (streamf, &fftAuxBuffer[0], fftAuxBuffer.size()); + stream_samples_read += samples_read; + if(samples_read<(int)fftAuxBuffer.size()){ + fftAuxBuffer.resize(samples_read); + buffer.resize(samples_read); + setPosition(0); + if(!bLoop) stopThread(); + stream_samples_read = 0; + stream_end = true; + } + for (int i = 0 ; i < int(fftAuxBuffer.size()) ; i++){ + fftAuxBuffer[i] *= stream_scale ; + buffer[i] = 32565.0 * fftAuxBuffer[i]; + } + }else{ + sf_count_t frames_read = sf_readf_short(streamf,&buffer[0],curr_buffer_size/channels); + stream_samples_read += frames_read*channels; + if(frames_read & buffer,vector & fftAuxBuffer){ + if(!mp3streamf){ + int err = MPG123_OK; + mp3streamf = mpg123_new(nullptr,&err); + if(mpg123_open(mp3streamf,path.string().c_str())!=MPG123_OK){ + mpg123_close(mp3streamf); + mpg123_delete(mp3streamf); + ofLogError("ofOpenALSoundPlayer") << "mpg123Stream(): couldn't read \"" << path << "\""; + return false; + } + + long int rate; + mpg123_getformat(mp3streamf,&rate,&channels,(int*)&stream_encoding); + if(stream_encoding!=MPG123_ENC_SIGNED_16){ + ofLogError("ofOpenALSoundPlayer") << "mpg123Stream(): " << getMpg123EncodingString(stream_encoding) + << " encoding for \"" << path << "\"" << " unsupported, expecting MPG123_ENC_SIGNED_16"; + return false; + } + samplerate = rate; + mp3_buffer_size = mpg123_outblock( mp3streamf ); + + + mpg123_seek(mp3streamf,0,SEEK_END); + off_t samples = mpg123_tell(mp3streamf); + duration = float(samples/channels) / float(samplerate); + mpg123_seek(mp3streamf,0,SEEK_SET); + } + + int curr_buffer_size = mp3_buffer_size; + if(speed>1) curr_buffer_size *= (int)round(speed); + buffer.resize(curr_buffer_size); + fftAuxBuffer.resize(buffer.size()); + size_t done=0; + if(mpg123_read(mp3streamf,(unsigned char*)&buffer[0],curr_buffer_size*2,&done)==MPG123_DONE){ + setPosition(0); + buffer.resize(done/2); + fftAuxBuffer.resize(done/2); + if(!bLoop) stopThread(); + stream_end = true; + } + + + for(int i=0;i<(int)buffer.size();i++){ + fftAuxBuffer[i] = float(buffer[i])/32565.f; + } + + return true; +} +#endif + +//------------------------------------------------------------ +bool ofOpenALSoundPlayer::stream(const std::filesystem::path& fileName, vector & buffer){ +#ifdef OF_USING_MPG123 + if(ofFilePath::getFileExt(fileName)=="mp3" || ofFilePath::getFileExt(fileName)=="MP3" || mp3streamf){ + if(!mpg123Stream(fileName,buffer,fftAuxBuffer)) return false; + }else +#endif + if(!sfStream(fileName,buffer,fftAuxBuffer)) return false; + + fftBuffers.resize(channels); + int numFrames = buffer.size()/channels; + + for(int i=0;i & buffer){ +#ifdef OF_USING_MPG123 + if(ofFilePath::getFileExt(fileName)!="mp3" && ofFilePath::getFileExt(fileName)!="MP3"){ + if(!sfReadFile(fileName,buffer,fftAuxBuffer)) return false; + }else{ + if(!mpg123ReadFile(fileName,buffer,fftAuxBuffer)) return false; + } +#else + if(!sfReadFile(fileName,buffer,fftAuxBuffer)) return false; +#endif + fftBuffers.resize(channels); + int numFrames = buffer.size()/channels; + + for(int i=0;i > multibuffer; + multibuffer.resize(channels); + sources.resize(channels); + alGenSources(channels, &sources[0]); + if(isStreaming){ + for(int s=0; s<2;s++){ + for(int i=0;i > multibuffer; + multibuffer.resize(channels); + while(isThreadRunning()){ + std::unique_lock lock(mutex); + for(int i=0; i1){ + for(int j=0;j lock(mutex); + + // Delete sources before buffers. + alDeleteSources(sources.size(),&sources[0]); + alDeleteBuffers(buffers.size(),&buffers[0]); + + sources.clear(); + buffers.clear(); + } + + // Free resources and close file descriptors. +#ifdef OF_USING_MPG123 + if(mp3streamf){ + mpg123_close(mp3streamf); + mpg123_delete(mp3streamf); + } + mp3streamf = 0; +#endif + + if(streamf){ + sf_close(streamf); + } + streamf = 0; + + bLoadedOk = false; +} + +//------------------------------------------------------------ +bool ofOpenALSoundPlayer::isPlaying() const{ + if(sources.empty()) return false; + if(isStreaming) return isThreadRunning(); + ALint state; + bool playing=false; + for(int i=0;i<(int)sources.size();i++){ + alGetSourcei(sources[i],AL_SOURCE_STATE,&state); + playing |= (state == AL_PLAYING); + } + return playing; +} + +//------------------------------------------------------------ +bool ofOpenALSoundPlayer::isPaused() const{ + if(sources.empty()) return false; + ALint state; + bool paused=true; + for(int i=0;i<(int)sources.size();i++){ + alGetSourcei(sources[i],AL_SOURCE_STATE,&state); + paused &= (state == AL_PAUSED); + } + return paused; +} + +//------------------------------------------------------------ +float ofOpenALSoundPlayer::getSpeed() const{ + return speed; +} + +//------------------------------------------------------------ +float ofOpenALSoundPlayer::getPan() const{ + return pan; +} + +//------------------------------------------------------------ +float ofOpenALSoundPlayer::getVolume() const{ + return volume; +} + +//------------------------------------------------------------ +void ofOpenALSoundPlayer::setVolume(float vol){ + volume = vol; + if(sources.empty()) return; + if(channels==1){ + alSourcef (sources[sources.size()-1], AL_GAIN, vol); + }else{ + setPan(pan); + } +} + +//------------------------------------------------------------ +void ofOpenALSoundPlayer::setPosition(float pct){ + setPositionMS(duration*pct*1000.f); +} + +//------------------------------------------------------------ +void ofOpenALSoundPlayer::setPositionMS(int ms){ + if(sources.empty()) return; +#ifdef OF_USING_MPG123 + if(mp3streamf){ + mpg123_seek(mp3streamf,float(ms)/1000.f*samplerate,SEEK_SET); + }else +#endif + if(streamf){ + stream_samples_read = sf_seek(streamf,float(ms)/1000.f*samplerate,SEEK_SET) * channels; + }else{ + for(int i=0;i<(int)channels;i++){ + alSourcef(sources[sources.size()-channels+i],AL_SEC_OFFSET,float(ms)/1000.f); + } + } +} + +//------------------------------------------------------------ +float ofOpenALSoundPlayer::getPosition() const{ + if(duration==0 || sources.empty()) + return 0; + else + return getPositionMS()/(1000.f*duration); +} + +//------------------------------------------------------------ +int ofOpenALSoundPlayer::getPositionMS() const{ + if(sources.empty()) return 0; + float pos; +#ifdef OF_USING_MPG123 + if(mp3streamf){ + pos = float(mpg123_tell(mp3streamf)) / float(samplerate); + }else +#endif + if(streamf){ + pos = float(stream_samples_read) / float(channels) / float(samplerate); + }else{ + alGetSourcef(sources[sources.size()-1],AL_SEC_OFFSET,&pos); + } + return pos * 1000.f; +} + +//------------------------------------------------------------ +void ofOpenALSoundPlayer::setPan(float p){ + if(sources.empty()) return; + p = glm::clamp(p, -1.f, 1.f); + pan = p; + if(channels==1){ + float pos[3] = {p,0,0}; + alSourcefv(sources[sources.size()-1],AL_POSITION,pos); + }else{ + // calculates left/right volumes from pan-value (constant panning law) + // see: Curtis Roads: Computer Music Tutorial p 460 + // thanks to jasch + float angle = p * 0.7853981633974483f; // in radians from -45. to +45. + float cosAngle = cos(angle); + float sinAngle = sin(angle); + float leftVol = (cosAngle - sinAngle) * 0.7071067811865475; // multiplied by sqrt(2)/2 + float rightVol = (cosAngle + sinAngle) * 0.7071067811865475; // multiplied by sqrt(2)/2 + for(int i=0;i<(int)channels;i++){ + if(i==0){ + alSourcef(sources[sources.size()-channels+i],AL_GAIN,leftVol*volume); + }else{ + alSourcef(sources[sources.size()-channels+i],AL_GAIN,rightVol*volume); + } + } + } +} + + +//------------------------------------------------------------ +void ofOpenALSoundPlayer::setPaused(bool bP){ + if(sources.empty()) return; + std::unique_lock lock(mutex); + if(bP){ + alSourcePausev(sources.size(),&sources[0]); + if(isStreaming){ + stopThread(); + } + }else{ + alSourcePlayv(sources.size(),&sources[0]); + if(isStreaming){ + startThread(); + } + } + + bPaused = bP; +} + + +//------------------------------------------------------------ +void ofOpenALSoundPlayer::setSpeed(float spd){ + for(int i=0;i lock(mutex); + int err = alGetError(); + + // if the sound is set to multiplay, then create new sources, + // do not multiplay on loop or we won't be able to stop it + if (bMultiPlay && !bLoop){ + sources.resize(sources.size()+channels); + alGetError(); // Clear error. + alGenSources(channels, &sources[sources.size()-channels]); + err = alGetError(); + if (err != AL_NO_ERROR){ + ofLogError("ofOpenALSoundPlayer") << "play(): couldn't create multiplay stereo sources: " + << (int) err << " " << getALErrorString(err); + return; + } + for(int i=0;i lock(mutex); + alSourceStopv(channels,&sources[sources.size()-channels]); + if(isStreaming){ + setPosition(0); + stopThread(); + } +} + +// ---------------------------------------------------------------------------- +void ofOpenALSoundPlayer::initFFT(int bands){ + if(int(bins.size())==bands) return; + int signalSize = (bands-1)*2; + if(fftCfg!=0) kiss_fftr_free(fftCfg); + fftCfg = kiss_fftr_alloc(signalSize, 0, nullptr, nullptr); + cx_out.resize(bands); + bins.resize(bands); + createWindow(signalSize); +} + +// ---------------------------------------------------------------------------- +void ofOpenALSoundPlayer::initSystemFFT(int bands){ + if(int(systemBins.size())==bands) return; + int signalSize = (bands-1)*2; + if(systemFftCfg!=0) kiss_fftr_free(systemFftCfg); + systemFftCfg = kiss_fftr_alloc(signalSize, 0, nullptr, nullptr); + systemCx_out.resize(bands); + systemBins.resize(bands); + createWindow(signalSize); +} + +float * ofOpenALSoundPlayer::getCurrentBufferSum(int size){ + if(int(windowedSignal.size())!=size){ + windowedSignal.resize(size); + } + windowedSignal.assign(windowedSignal.size(),0); + for(int k=0;k=(int)fftBuffers[0].size()) continue; + for(int i=0;i::iterator it; + for(it=players().begin();it!=players().end();it++){ + if(!(*it)->isPlaying()) continue; + float * buffer = (*it)->getCurrentBufferSum(signalSize); + for(int i=0;i & signal){ + for(int i = 0; i < (int)signal.size(); i++) + signal[i] *= window[i]; +} + + +#endif diff --git a/ofpatch/msys2/sound/ofOpenALSoundPlayer.h b/ofpatch/msys2/sound/ofOpenALSoundPlayer.h new file mode 100644 index 0000000..042f7b3 --- /dev/null +++ b/ofpatch/msys2/sound/ofOpenALSoundPlayer.h @@ -0,0 +1,157 @@ +#pragma once + +#include "ofConstants.h" + +#ifdef OF_SOUND_PLAYER_OPENAL +#include "ofSoundBaseTypes.h" +#include "ofThread.h" + + + +typedef unsigned int ALuint; + +#include "kiss_fft.h" +#include "kiss_fftr.h" + + + +typedef struct SNDFILE_tag SNDFILE ; + + +#ifdef OF_USING_MPG123 + typedef struct mpg123_handle_struct mpg123_handle; +#endif + +class ofEventArgs; + +// TO DO : +// --------------------------- +// -fft via fmod, as in the last time... +// -close fmod if it's up +// -loadSoundForStreaming(char * fileName); +// --------------------------- + +// interesting: +// http://www.compuphase.com/mp3/mp3loops.htm + + +// ---------------------------------------------------------------------------- SOUND SYSTEM FMOD + +// --------------------- global functions: +void ofFmodSoundStopAll(); +void ofFmodSoundSetVolume(float vol); +void ofOpenALSoundUpdate(); // calls FMOD update. +float * ofFmodSoundGetSpectrum(int nBands); // max 512... + + +// --------------------- player functions: +class ofOpenALSoundPlayer : public ofBaseSoundPlayer, public ofThread { + + public: + + ofOpenALSoundPlayer(); + virtual ~ofOpenALSoundPlayer(); + + bool load(const std::filesystem::path& fileName, bool stream = false); + void unload(); + void play(); + void stop(); + + void setVolume(float vol); + void setPan(float vol); // -1 to 1 + void setSpeed(float spd); + void setPaused(bool bP); + void setLoop(bool bLp); + void setMultiPlay(bool bMp); + void setPosition(float pct); // 0 = start, 1 = end; + void setPositionMS(int ms); + + + float getPosition() const; + int getPositionMS() const; + bool isPlaying() const; + float getSpeed() const; + float getPan() const; + float getVolume() const; + bool isPaused() const; + bool isLoaded() const; + + static void initialize(); + static void close(); + + float * getSpectrum(int bands); + + static float * getSystemSpectrum(int bands); + + protected: + void threadedFunction(); + + private: + friend void ofOpenALSoundUpdate(); + void update(ofEventArgs & args); + void initFFT(int bands); + float * getCurrentBufferSum(int size); + + static void createWindow(int size); + static void runWindow(std::vector & signal); + static void initSystemFFT(int bands); + + bool sfReadFile(const std::filesystem::path& path,std::vector & buffer,std::vector & fftAuxBuffer); + bool sfStream(const std::filesystem::path& path,std::vector & buffer,std::vector & fftAuxBuffer); +#ifdef OF_USING_MPG123 + bool mpg123ReadFile(const std::filesystem::path& path,std::vector & buffer,std::vector & fftAuxBuffer); + bool mpg123Stream(const std::filesystem::path& path,std::vector & buffer,std::vector & fftAuxBuffer); +#endif + + bool readFile(const std::filesystem::path& fileName,std::vector & buffer); + bool stream(const std::filesystem::path& fileName, std::vector & buffer); + + bool isStreaming; + bool bMultiPlay; + bool bLoop; + bool bLoadedOk; + bool bPaused; + float pan; // 0 - 1 + float volume; // 0 - 1 + float internalFreq; // 44100 ? + float speed; // -n to n, 1 = normal, -1 backwards + unsigned int length; // in samples; + + static std::vector window; + static float windowSum; + + int channels; + float duration; //in secs + int samplerate; + std::vector buffers; + std::vector sources; + + // fft structures + std::vector > fftBuffers; + kiss_fftr_cfg fftCfg; + std::vector windowedSignal; + std::vector bins; + std::vector cx_out; + + + static kiss_fftr_cfg systemFftCfg; + static std::vector systemWindowedSignal; + static std::vector systemBins; + static std::vector systemCx_out; + + SNDFILE* streamf; + size_t stream_samples_read; +#ifdef OF_USING_MPG123 + mpg123_handle * mp3streamf; + int stream_encoding; +#endif + int mp3_buffer_size; + int stream_subformat; + double stream_scale; + std::vector buffer; + std::vector fftAuxBuffer; + + bool stream_end; +}; + +#endif