From 1eb88d4f5d5cb05d62be1d4a0c88c7399f7c0de0 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Sat, 3 Feb 2018 00:55:26 +0800 Subject: Added the GL 3.2+ port. Fixed poor performance of the truetype renderer. (Partially) Fixed texture locking. Minor addition and fixes to the math library. --- smelt/glfw_m/sfx_oal.cpp | 368 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 smelt/glfw_m/sfx_oal.cpp (limited to 'smelt/glfw_m/sfx_oal.cpp') diff --git a/smelt/glfw_m/sfx_oal.cpp b/smelt/glfw_m/sfx_oal.cpp new file mode 100644 index 0000000..5b8d135 --- /dev/null +++ b/smelt/glfw_m/sfx_oal.cpp @@ -0,0 +1,368 @@ +// -*- C++ -*- +/* + * Simple MultimEdia LiTerator(SMELT) + * by Chris Xiong 2015 + * GFX implementation based on OpenAL + * + * WARNING: This library is in development and interfaces would be very + * unstable. + * + */ +#include "smelt_internal.hpp" + +static const char* SFX_OAL_SRCFN="smelt/glfw/sfx_oal.cpp"; +#ifndef ENABLE_DUMB +#ifdef ENABLE_OGG_SUPPORT +struct oggdata{const BYTE *data;DWORD size,pos;}; +static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq); +#endif +static void* readRiffWv(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq); +SMSFX SMELT_IMPL::smSFXLoad(const char *path) +{ + FILE *pFile;DWORD size,rsize; char *buff; + pFile=fopen(path,"rb"); + if(!pFile)return 0; + fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); + buff=(char*)malloc(sizeof(char)*size); + if(!buff)return 0; + rsize=fread(buff,1,size,pFile); + if(rsize!=size)return 0; + SMSFX ret=smSFXLoadFromMemory(buff,size); + free(buff); + fclose(pFile); + return ret; +} +SMSFX SMELT_IMPL::smSFXLoadFromMemory(const char *ptr,DWORD size) +{ + if(pOpenALDevice&&!mute) + { +#ifdef ENABLE_OGG_SUPPORT + bool isOgg=size>4&&ptr[0]=='O'&&ptr[1]=='g'&&ptr[2]=='g'&&ptr[3]=='S'; +#endif + void *decompdata=NULL,*decomp=NULL; + ALsizei decompsize=0,freq=0; + ALenum fmt=AL_FORMAT_STEREO16; + decompdata=readRiffWv((const BYTE*)ptr,size,&decompsize,&fmt,&freq); +#ifdef ENABLE_OGG_SUPPORT + if(!decompdata) + { + if(!isOgg)return 0; + else decompdata=readVorbis((const BYTE*)ptr,size,&decompsize,&fmt,&freq); + } +#endif + if(!decompdata)return 0; + decomp=decompdata; + ALuint buff=0;alGenBuffers(1,&buff); + alBufferData(buff,fmt,decomp,decompsize,freq); + free(decompdata);return(SMSFX)buff; + } + return 0; +} +SMCHN SMELT_IMPL::smSFXPlay(SMSFX fx,int vol,int pan,float pitch,bool loop) +{ + if(pOpenALDevice) + { + ALuint src=getSource(); + if(src) + { + if(vol<0)vol=0;if(vol>100)vol=100; + if(pan<-100)pan=-100;if(pan>100)pan=100; + alSourceStop(src); + alSourcei(src,AL_BUFFER,(ALint)fx); + alSourcef(src,AL_GAIN,((ALfloat)vol)/100.); + alSourcef(src,AL_PITCH,pitch); + alSource3f(src,AL_POSITION,((ALfloat)pan)/100.,.0,.0); + alSourcei(src,AL_LOOPING,loop?AL_TRUE:AL_FALSE); + alSourcePlay(src); + } + return src; + } + return 0; +} +float SMELT_IMPL::smSFXGetLengthf(SMSFX fx) +{ + ALuint buff=(ALuint)fx; + ALint freq; + DWORD lend=smSFXGetLengthd(fx); + alGetBufferi(buff,AL_FREQUENCY,&freq); + float ret=lend/(float)freq; + return ret; +} +DWORD SMELT_IMPL::smSFXGetLengthd(SMSFX fx) +{ + if(pOpenALDevice) + { + ALint size_b,chnc,bit; + ALuint buff=(ALuint)fx; + alGetBufferi(buff,AL_SIZE,&size_b); + alGetBufferi(buff,AL_CHANNELS,&chnc); + alGetBufferi(buff,AL_BITS,&bit); + DWORD ret=size_b*8/(chnc*bit); + return ret; + } + return -1; +} +void SMELT_IMPL::smSFXSetLoopPoint(SMSFX fx,DWORD l,DWORD r) +{ + if(pOpenALDevice) + { + ALint pt[2];pt[0]=l;pt[1]=r; + alBufferiv((ALuint)fx,AL_LOOP_POINTS_SOFT,pt); + } +} +void SMELT_IMPL::smSFXFree(SMSFX fx) +{ + if(pOpenALDevice) + { + ALuint buff=(ALuint)fx; + alDeleteBuffers(1,&buff); + } +} +void SMELT_IMPL::smChannelVol(SMCHN chn,int vol) +{ + if(pOpenALDevice) + { + if(vol<0)vol=0;if(vol>100)vol=100; + alSourcef((ALuint)chn,AL_GAIN,((ALfloat)vol)/100.); + } +} +void SMELT_IMPL::smChannelPan(SMCHN chn,int pan) +{ + if(pOpenALDevice) + { + if(pan<-100)pan=-100;if(pan>100)pan=100; + alSource3f((ALuint)chn,AL_POSITION,((ALfloat)pan)/100.,.0,.0); + } +} +void SMELT_IMPL::smChannelPitch(SMCHN chn,float pitch) +{ + if(pOpenALDevice)alSourcef((ALuint)chn,AL_PITCH,pitch); +} +void SMELT_IMPL::smChannelPause(SMCHN chn) +{ + if(pOpenALDevice)alSourcePause((ALuint)chn); +} +void SMELT_IMPL::smChannelResume(SMCHN chn) +{ + if(pOpenALDevice)alSourcePlay((ALuint)chn); +} +void SMELT_IMPL::smChannelStop(SMCHN chn) +{ + if(pOpenALDevice)alSourceStop((ALuint)chn); +} +void SMELT_IMPL::smChannelPauseAll() +{ + if(pOpenALDevice) + { + ALCcontext *ctx=alcGetCurrentContext(); + alcSuspendContext(ctx); + } +} +void SMELT_IMPL::smChannelResumeAll() +{ + if(pOpenALDevice) + { + ALCcontext *ctx=alcGetCurrentContext(); + alcProcessContext(ctx); + } +} +void SMELT_IMPL::smChannelStopAll() +{ + if(pOpenALDevice) + { + for(int i=0;isize-data->pos; + size_t want=nmemb*size; + if(want>avail)want=avail-(avail%size); + if(want>0) + { + memcpy(ptr,data->data+data->pos,want); + data->pos+=want; + } + return want/size; +} +static int oggSeek(void *ds,ogg_int64_t offset,int whence) +{ + oggdata *data=(oggdata*)ds; + ogg_int64_t pos=0; + switch(whence) + { + case SEEK_SET:pos=offset;break; + case SEEK_CUR:pos=((ogg_int64_t)data->pos)+offset;break; + case SEEK_END:pos=((ogg_int64_t)data->size)+offset;break; + default: return -1; + } + if((pos<0)||(pos>((ogg_int64_t)data->size)))return -1; + data->pos=(DWORD)pos; + return 0; +} +static long oggLocate(void *ds) +{ + oggdata* data=(oggdata*)ds; + return (long)data->pos; +} +static int oggClose(void *ds){return 0;} + +static ov_callbacks oggrt={oggRead,oggSeek,oggClose,oggLocate}; +static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq) +{ + oggdata adata={data,size,0}; + OggVorbis_File vf; + memset(&vf,0,sizeof(vf)); + if(ov_open_callbacks(&adata,&vf,NULL,0,oggrt)==0) + { + int bs=0; + vorbis_info *info=ov_info(&vf,-1); + *decomp_size=0; + *fmt=(info->channels==1)?AL_FORMAT_MONO16:AL_FORMAT_STEREO16; + *freq=info->rate; + if(!(info->channels==1||info->channels==2)){ov_clear(&vf);return NULL;} + char buf[1024*16];long rc=0;size_t allocated=1024*16; + BYTE *ret=(ALubyte*)malloc(allocated); + while((rc=ov_read(&vf,buf,sizeof(buf),0,2,1,&bs))!=0) + { + if(rc>0) + { + *decomp_size+=rc; + if((unsigned)*decomp_size>=allocated) + { + allocated<<=1; + ALubyte *tmp=(ALubyte*)realloc(ret,allocated); + if(!tmp){free(ret);ret=NULL;break;} + ret=tmp; + } + memcpy(ret+(*decomp_size-rc),buf,rc); + } + } + ov_clear(&vf); + return ret; + } + return NULL; +} +#endif +static void* readRiffWv(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq) +{ + if(data[0x0]!='R'||data[0x1]!='I'||data[0x2]!='F'||data[0x3]!='F')return NULL; + if(data[0x8]!='W'||data[0x9]!='A'||data[0xA]!='V'||data[0xB]!='E')return NULL; + if(data[0xC]!='f'||data[0xD]!='m'||data[0xE]!='t'||data[0xF]!=' ')return NULL; + if(data[0x16]==2) + { + if(data[0x22]==16)*fmt=AL_FORMAT_STEREO16; + else if(data[0x22]==8)*fmt=AL_FORMAT_STEREO8; + else return NULL; + } + else if(data[0x16]==1) + { + if(data[0x22]==16)*fmt=AL_FORMAT_MONO16; + else if(data[0x22]==8)*fmt=AL_FORMAT_MONO8; + else return NULL; + }else return NULL; + *decomp_size=(ALsizei)(data[0x28]|(data[0x29]<<8L)|(data[0x2A]<<16L)|(data[0x2B]<<24L)); + *freq=(ALsizei)(data[0x18]|(data[0x19]<<8L)|(data[0x1A]<<16L)|(data[0x1B]<<24L)); + ALubyte *ret=(ALubyte*)malloc(*decomp_size); + memcpy(ret,data+44,*decomp_size); + return ret; +} +ALuint SMELT_IMPL::getSource() +{ + for(int i=0;i=SRC_MAX)return 0; + ALuint ret=0; + alGenSources(1,&ret);if(!ret)return 0; + src[scnt++]=ret;return ret; +} +bool SMELT_IMPL::initOAL() +{ + if(pOpenALDevice)return true; + scnt=0;memset(src,0,sizeof(src)); + smLog("%s:" SLINE ": Initializing OpenAL...\n",SFX_OAL_SRCFN); + ALCdevice *dev=alcOpenDevice(NULL); + if(!dev) + { + smLog("%s:" SLINE ": alcOpenDevice() failed.\n",SFX_OAL_SRCFN); + return mute=true; + } + ALint caps[]={ALC_FREQUENCY,44100,0}; + ALCcontext *ctx=alcCreateContext(dev,caps); + if(!ctx) + { + smLog("%s:" SLINE ": alcCreateContext() failed.\n",SFX_OAL_SRCFN); + return mute=true; + } + alcMakeContextCurrent(ctx);alcProcessContext(ctx); + smLog("%s:" SLINE ": Done OpenAL initialization\n",SFX_OAL_SRCFN); + smLog("%s:" SLINE ": AL_VENDOR: %s\n",SFX_OAL_SRCFN,(char*)alGetString(AL_VENDOR)); + smLog("%s:" SLINE ": AL_RENDERER: %s\n",SFX_OAL_SRCFN,(char*)alGetString(AL_RENDERER)); + smLog("%s:" SLINE ": AL_VERSION: %s\n",SFX_OAL_SRCFN,(char*)alGetString(AL_VERSION)); + const char* ext=(const char*)alGetString(AL_EXTENSIONS); + lpp=strstr(ext,"AL_SOFT_loop_points")!=NULL; + if(!lpp)smLog("%s:" SLINE ": Warning: loop points not supported. Please recompile with OpenAL Soft.\n",SFX_OAL_SRCFN); + pOpenALDevice=(void*)dev; + return true; +} +void SMELT_IMPL::finiOAL() +{ + if(pOpenALDevice) + { + for(int i=0;i