mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-28 17:56:37 +00:00 
			
		
		
		
	Implement non-streaming sounds with OpenAL
This commit is contained in:
		
							parent
							
								
									9adf1e8461
								
							
						
					
					
						commit
						d57051375d
					
				
					 1 changed files with 160 additions and 6 deletions
				
			
		|  | @ -47,6 +47,32 @@ static ALenum getALFormat(Sound_Decoder::ChannelConfig chans, Sound_Decoder::Sam | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| ALuint LoadBuffer(std::auto_ptr<Sound_Decoder> decoder) | ||||
| { | ||||
|     int srate; | ||||
|     Sound_Decoder::ChannelConfig chans; | ||||
|     Sound_Decoder::SampleType type; | ||||
|     ALenum format; | ||||
| 
 | ||||
|     decoder->GetInfo(&srate, &chans, &type); | ||||
|     format = getALFormat(chans, type); | ||||
| 
 | ||||
|     std::vector<char> data(32768); | ||||
|     size_t got, total = 0; | ||||
|     while((got=decoder->Read(&data[total], data.size()-total)) > 0) | ||||
|     { | ||||
|         total += got; | ||||
|         data.resize(total*2); | ||||
|     } | ||||
|     data.resize(total); | ||||
| 
 | ||||
|     ALuint buf; | ||||
|     alGenBuffers(1, &buf); | ||||
|     alBufferData(buf, format, &data[0], total, srate); | ||||
|     return buf; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class OpenAL_SoundStream : public Sound | ||||
| { | ||||
|     // This should be something sane, like 4, but currently cell loads tend to
 | ||||
|  | @ -71,6 +97,21 @@ public: | |||
|     virtual bool isPlaying(); | ||||
| }; | ||||
| 
 | ||||
| class OpenAL_Sound : public Sound | ||||
| { | ||||
| public: | ||||
|     ALuint Source; | ||||
|     ALuint Buffer; | ||||
| 
 | ||||
|     OpenAL_Sound(ALuint src, ALuint buf); | ||||
|     virtual ~OpenAL_Sound(); | ||||
| 
 | ||||
|     virtual void Play(); | ||||
|     virtual void Stop(); | ||||
|     virtual bool isPlaying(); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| OpenAL_SoundStream::OpenAL_SoundStream(std::auto_ptr<Sound_Decoder> decoder) | ||||
|   : Decoder(decoder) | ||||
| { | ||||
|  | @ -190,6 +231,38 @@ bool OpenAL_SoundStream::isPlaying() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| OpenAL_Sound::OpenAL_Sound(ALuint src, ALuint buf) | ||||
|   : Source(src), Buffer(buf) | ||||
| { | ||||
| } | ||||
| OpenAL_Sound::~OpenAL_Sound() | ||||
| { | ||||
|     alDeleteSources(1, &Source); | ||||
|     alDeleteBuffers(1, &Buffer); | ||||
|     alGetError(); | ||||
| } | ||||
| 
 | ||||
| void OpenAL_Sound::Play() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void OpenAL_Sound::Stop() | ||||
| { | ||||
|     alSourceStop(Source); | ||||
|     throwALerror(); | ||||
| } | ||||
| 
 | ||||
| bool OpenAL_Sound::isPlaying() | ||||
| { | ||||
|     ALint state; | ||||
| 
 | ||||
|     alGetSourcei(Source, AL_SOURCE_STATE, &state); | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     return state==AL_PLAYING; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool OpenAL_Output::Initialize(const std::string &devname) | ||||
| { | ||||
|     if(Context) | ||||
|  | @ -233,16 +306,97 @@ void OpenAL_Output::Deinitialize() | |||
| Sound* OpenAL_Output::PlaySound(const std::string &fname, std::auto_ptr<Sound_Decoder> decoder, | ||||
|                                 float volume, float pitch, bool loop) | ||||
| { | ||||
|     fail("PlaySound not yet supported"); | ||||
|     return NULL; | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     decoder->Open(fname); | ||||
| 
 | ||||
|     ALuint src=0, buf=0; | ||||
|     try | ||||
|     { | ||||
|         buf = LoadBuffer(decoder); | ||||
|         alGenSources(1, &src); | ||||
|         throwALerror(); | ||||
|     } | ||||
|     catch(std::exception &e) | ||||
|     { | ||||
|         if(alIsSource(buf)) | ||||
|             alDeleteSources(1, &src); | ||||
|         if(alIsBuffer(buf)) | ||||
|             alDeleteBuffers(1, &buf); | ||||
|         alGetError(); | ||||
|         throw; | ||||
|     } | ||||
| 
 | ||||
|     std::auto_ptr<OpenAL_Sound> sound(new OpenAL_Sound(src, buf)); | ||||
|     alSource3f(src, AL_POSITION, 0.0f, 0.0f, 0.0f); | ||||
|     alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f); | ||||
|     alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f); | ||||
| 
 | ||||
|     alSourcef(src, AL_REFERENCE_DISTANCE, 1.0f); | ||||
|     alSourcef(src, AL_MAX_DISTANCE, 1000.0f); | ||||
|     alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); | ||||
| 
 | ||||
|     alSourcef(src, AL_GAIN, volume); | ||||
|     alSourcef(src, AL_PITCH, pitch); | ||||
| 
 | ||||
|     alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE); | ||||
|     alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE)); | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     alSourcei(src, AL_BUFFER, buf); | ||||
|     alSourcePlay(src); | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     return sound.release(); | ||||
| } | ||||
| 
 | ||||
| Sound* OpenAL_Output::PlaySound3D(const std::string &fname, std::auto_ptr<Sound_Decoder> decoder, | ||||
|                                    MWWorld::Ptr ptr, float volume, float pitch, | ||||
|                                    float min, float max, bool loop) | ||||
|                                   MWWorld::Ptr ptr, float volume, float pitch, | ||||
|                                   float min, float max, bool loop) | ||||
| { | ||||
|     fail("PlaySound3D not yet supported"); | ||||
|     return NULL; | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     decoder->Open(fname); | ||||
| 
 | ||||
|     ALuint src=0, buf=0; | ||||
|     try | ||||
|     { | ||||
|         buf = LoadBuffer(decoder); | ||||
|         alGenSources(1, &src); | ||||
|         throwALerror(); | ||||
|     } | ||||
|     catch(std::exception &e) | ||||
|     { | ||||
|         if(alIsSource(buf)) | ||||
|             alDeleteSources(1, &src); | ||||
|         if(alIsBuffer(buf)) | ||||
|             alDeleteBuffers(1, &buf); | ||||
|         alGetError(); | ||||
|         throw; | ||||
|     } | ||||
| 
 | ||||
|     std::auto_ptr<OpenAL_Sound> sound(new OpenAL_Sound(src, buf)); | ||||
|     const float *pos = ptr.getCellRef().pos.pos; | ||||
|     alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]); | ||||
|     alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f); | ||||
|     alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f); | ||||
| 
 | ||||
|     alSourcef(src, AL_REFERENCE_DISTANCE, min); | ||||
|     alSourcef(src, AL_MAX_DISTANCE, max); | ||||
|     alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f); | ||||
| 
 | ||||
|     alSourcef(src, AL_GAIN, volume); | ||||
|     alSourcef(src, AL_PITCH, pitch); | ||||
| 
 | ||||
|     alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE); | ||||
|     alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE)); | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     alSourcei(src, AL_BUFFER, buf); | ||||
|     alSourcePlay(src); | ||||
|     throwALerror(); | ||||
| 
 | ||||
|     return sound.release(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue