From 49e67bc8566e8c5017b931837792a648cb0048c2 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Mon, 7 Dec 2015 23:49:44 +0800 Subject: Add RIFF wave format support. Update documentation. --- doc/SMELTdoc | 9 +++-- include/smelt.hpp | 86 +++++++++++++++++++++++++++++++++++++------- smelt/sdl/sfx_sdl.cpp | 35 ++++++++++++++++-- smelt/sdl/smelt_internal.hpp | 2 +- 4 files changed, 112 insertions(+), 20 deletions(-) diff --git a/doc/SMELTdoc b/doc/SMELTdoc index 2f6bdd2..4bbc7a3 100644 --- a/doc/SMELTdoc +++ b/doc/SMELTdoc @@ -158,10 +158,13 @@ float smGetTime() [core/FPS] Gets the time in milliseconds since the call to smInit(). SMSFX smSFXLoad(const char *path) [core/SFX] -Loads a sound file from the given path. Only ogg files are supported. +Loads a sound file from the given path. Only ogg and wav files are supported. +Further more, due to the restrictions of OpenAL, only 8/16bit mono/stereo formats +are supported. SMSFX smSFXLoadFromMemory(const char *ptr,DWORD size) [core/SFX] -Loads a sound file from the given memory block. Only ogg files are supported. +Loads a sound file from the given memory block. Limitations are the same to that +of smSFXLoad. SMCHN smSFXPlay(SMSFX fx,int vol=100,int pan=0,float pitch=1.,bool loop=0) [core/SFX] @@ -170,7 +173,7 @@ A channel is generated and can be used to control the playing of the SFX. The channel is valid until it stops. Volume should be 0~100. Panning should be -100~100. -The values would be clamped to the range given above. +The values will be clamped to the range given above. float smSFXGetLengthf(SMSFX fx) [core/SFX] Gets the sound length in seconds. diff --git a/include/smelt.hpp b/include/smelt.hpp index 111c4b8..5435d15 100644 --- a/include/smelt.hpp +++ b/include/smelt.hpp @@ -73,7 +73,9 @@ typedef size_t SMCHN;//Audio channel Handle typedef bool (*smHook)(); //Special FPS modes +//Unlimited FPS #define FPS_FREE 0 +//VSync #define FPS_VSYNC -1 //Primitives @@ -127,29 +129,29 @@ class SMELT public: SMELT(){} virtual ~SMELT(){} - /* + /** * Releases the acquired SMELT interface. * Decreases the internal reference counter by one. If the counter * reaches 0, SMELT core will release all resources managed by it * (if smFinale() is not yet called) and destroy the interface. */ virtual void smRelease()=0; - /* + /** * Initializes SMELT core. * Creates application window, initializes video, audio and input * handling. No functions in these categories can be called before * the core is initialized. * Returns true on succees, false on failure. Error details will be - * written to the log file. + * written to the log file and stderr. */ virtual bool smInit()=0; - /* + /** * Deinitializes SMELT core. * Closes application window and frees resources managed by the core. * The core will return to the status before calling smInit(). */ virtual void smFinale()=0; - /* + /** * Enters the main loop. * The main loop calls update function, focus gain function, focus * lost function and quit function periodally, handles input events @@ -159,27 +161,27 @@ public: * The main loop breaks when the update function returns true. */ virtual void smMainLoop()=0; - /* + /** * Sets the update function. * Update function is called every frame. * It returns true when you want to terminate the main loop. */ virtual void smUpdateFunc(smHook func)=0; - /* + /** * Sets the focus lost function. * Focus lost function is called when the application window loses * focus. * The return value of the focus lost function has no effect. */ virtual void smUnFocFunc(smHook func)=0; - /* + /** * Sets the focus gain function. * Focus gain function is called when the application window gains * focus. Also called when the application window is created. * The return value of the focus gain function has no effect. */ virtual void smFocFunc(smHook func)=0; - /* + /** * Sets the quit function. * Quit function is called when the user attempts to close the * application window. @@ -187,16 +189,17 @@ public: * Otherwise the main loop will break. */ virtual void smQuitFunc(smHook func)=0; - /* + /** * Sets the window title of the application window. * The default window title is "untitled". */ virtual void smWinTitle(const char* title)=0; - /* + /** * Tests if the application window has focus. + * Returns the test result. */ virtual bool smIsActive()=0; - /* + /** * Changes the behavior when the application window loses focus. * By default, the main loop pauses when the application loses focus * (para=false). @@ -225,21 +228,78 @@ public: virtual void smLog(const char* format,...)=0; /* * Saves the content of the application window to the given path. - * The picture is saved in BMP format. + * The picture is saved in the BMP format. */ virtual void smScreenShot(const char* path)=0; + /* + * Sets the desired FPS value. The macros FPS_* can be used + */ virtual void smSetFPS(int fps)=0; + /* + * Get *current* FPS value your application is running at. + * Not the value you set! + * Returns the FPS value, which is updated once a second. + */ virtual float smGetFPS()=0; + /* + * Get delta time between the current frame and the last frame. + * Return the value in seconds. + */ virtual float smGetDelta()=0; + /* + * Get elapsed time since calling smInit() in seconds. + * Returns the result. + */ virtual float smGetTime()=0; + /* + * Load a single sound file into memory. + * Currently only ogg and wav files are supported. + * This function loads and decodes the ogg data, which may take + * noticeable time to complete. Consider running it in a seperate + * thread if you are loading a larger file. + * Returns the SFX handle on success, or 0 on failure. + */ virtual SMSFX smSFXLoad(const char *path)=0; + /* + * Loads sound file from the given memory block. + * Only ogg and wav formats are supported. + * Returns the SFX handle on success, or 0 on failure. + */ virtual SMSFX smSFXLoadFromMemory(const char *ptr,DWORD size)=0; + /* + * Plays the sound. + * If loop is set to false, the audio won't loop even if loop points + * are set. + * Volume should be between 0 to 100. + * Panning should be between -100 to 100. + * The values will be clamped to the range given above. + * Returns the audio channel it occupies, or 0 if there's no audio + * channel available. + * Max audio channels can be modified in smelt_config.hpp. + */ virtual SMCHN smSFXPlay(SMSFX fx,int vol=100,int pan=0,float pitch=1.,bool loop=0)=0; + /* + * Gets the length of the audio, in seconds. + * Returns the result. + */ virtual float smSFXGetLengthf(SMSFX fx)=0; + /* + * Gets the length of the audio, in sample numbers. + * Returns the result. + */ virtual DWORD smSFXGetLengthd(SMSFX fx)=0; + /* + * Sets the loop points of the given sound. + * By default, the whole sound is looped. + * This function uses AL_SOFT_loop_points. So it may not work if + * SMELT isn't build against OpenAL Soft + */ virtual void smSFXSetLoopPoint(SMSFX fx,DWORD l,DWORD r)=0; + /* + * Unloads the audio file from memory. + */ virtual void smSFXFree(SMSFX fx)=0; virtual void smChannelVol(SMCHN chn,int vol)=0; diff --git a/smelt/sdl/sfx_sdl.cpp b/smelt/sdl/sfx_sdl.cpp index b61a8a0..c49162a 100644 --- a/smelt/sdl/sfx_sdl.cpp +++ b/smelt/sdl/sfx_sdl.cpp @@ -13,6 +13,7 @@ static const char* SFX_SDL_SRCFN="smelt/sdl/sfx_sdl.cpp"; struct oggdata{const BYTE *data;DWORD size,pos;}; static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq); +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; @@ -33,15 +34,20 @@ SMSFX SMELT_IMPL::smSFXLoadFromMemory(const char *ptr,DWORD size) if(pOpenALDevice&&!mute) { bool isOgg=size>4&&ptr[0]=='O'&&ptr[1]=='g'&&ptr[2]=='g'&&ptr[3]=='S'; - if(!isOgg)return 0; void *decompdata=NULL,*decomp=NULL; ALsizei decompsize=0,freq=0; ALenum fmt=AL_FORMAT_STEREO16; - decompdata=readVorbis((const BYTE*)ptr,size,&decompsize,&fmt,&freq); + decompdata=readRiffWv((const BYTE*)ptr,size,&decompsize,&fmt,&freq); + if(!decompdata) + { + if(!isOgg)return 0; + else decompdata=readVorbis((const BYTE*)ptr,size,&decompsize,&fmt,&freq); + } + if(!decompdata)return 0; decomp=decompdata; ALuint buff=0;alGenBuffers(1,&buff); alBufferData(buff,fmt,decomp,decompsize,freq); - free(decompdata);return (SMSFX)buff; + free(decompdata);return(SMSFX)buff; } return 0; } @@ -270,6 +276,29 @@ static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size, } return NULL; } +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 #include #include @@ -25,7 +26,6 @@ #include #include #include -#include #ifdef WIN32 #include #include -- cgit v1.2.3