ambient sounds, maybe

This commit is contained in:
darkrose 2015-04-11 18:19:43 +10:00
parent 542b5d5904
commit 3d7bc18030
14 changed files with 151 additions and 46 deletions

BIN
data/sounds/env_water.ogg Normal file

Binary file not shown.

View File

@ -151,20 +151,9 @@ void * MeshUpdateThread::Thread()
BEGIN_DEBUG_EXCEPTION_HANDLER BEGIN_DEBUG_EXCEPTION_HANDLER
while(getRun()) while (getRun()) {
{
/*// Wait for output queue to flush.
// Allow 2 in queue, this makes less frametime jitter.
// Umm actually, there is no much difference
if(m_queue_out.size() >= 2)
{
sleep_ms(3);
continue;
}*/
QueuedMeshUpdate *q = m_queue_in.pop(); QueuedMeshUpdate *q = m_queue_in.pop();
if(q == NULL) if (q == NULL) {
{
sleep_ms(3); sleep_ms(3);
continue; continue;
} }
@ -178,10 +167,6 @@ void * MeshUpdateThread::Thread()
r.mesh = mesh_new; r.mesh = mesh_new;
r.ack_block_to_server = q->ack_block_to_server; r.ack_block_to_server = q->ack_block_to_server;
/*infostream<<"MeshUpdateThread: Processed "
<<"("<<q->p.X<<","<<q->p.Y<<","<<q->p.Z<<")"
<<std::endl;*/
m_queue_out.push_back(r); m_queue_out.push_back(r);
delete q; delete q;
@ -2261,6 +2246,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
data->fill(getDayNightRatio(), b); data->fill(getDayNightRatio(), b);
} }
data->m_sounds = &b->m_sounds;
// Debug wait // Debug wait
//while(m_mesh_update_thread.m_queue_in.size() > 0) sleep_ms(10); //while(m_mesh_update_thread.m_queue_in.size() > 0) sleep_ms(10);

View File

@ -31,6 +31,7 @@
#include "settings.h" #include "settings.h"
#include "environment.h" #include "environment.h"
#include "nodemetadata.h" #include "nodemetadata.h"
#include "sound.h"
#ifndef SERVER #ifndef SERVER
// Create a cuboid. // Create a cuboid.
@ -484,6 +485,32 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
data->m_temp_mods.get(p,&mod); data->m_temp_mods.get(p,&mod);
selected = (mod == NODEMOD_SELECTION); selected = (mod == NODEMOD_SELECTION);
if (g_sound) {
std::string snd = content_features(n).sound_ambient;
std::map<v3s16,MapBlockSound>::iterator i = data->m_sounds->find(p);
if (snd != "") {
bool add_sound = true;
if (i != data->m_sounds->end()) {
if (i->second.name == snd && g_sound->soundExists(i->second.id)) {
add_sound = false;
}else{
g_sound->stopSound(i->second.id);
}
}
if (add_sound) {
v3f pf = intToFloat(p+blockpos_nodes,BS);
MapBlockSound bsnd;
bsnd.id = g_sound->playSoundAt(snd,true,pf, true);
bsnd.name = snd;
if (bsnd.id > 0)
(*data->m_sounds)[p] = bsnd;
}
}else if (i != data->m_sounds->end()) {
g_sound->stopSound(i->second.id);
data->m_sounds->erase(i);
}
}
/* /*
Add torches to mesh Add torches to mesh
*/ */

View File

@ -2078,6 +2078,7 @@ void content_mapnode_init(bool repeat)
f->setAllTextureTypes(MATERIAL_ALPHA_VERTEX); f->setAllTextureTypes(MATERIAL_ALPHA_VERTEX);
f->post_effect_color = video::SColor(64, 100, 100, 200); f->post_effect_color = video::SColor(64, 100, 100, 200);
#endif #endif
f->sound_ambient = "env-water";
f->suffocation_per_second = 2; f->suffocation_per_second = 2;
i = CONTENT_WATERSOURCE; i = CONTENT_WATERSOURCE;
@ -2197,6 +2198,7 @@ void content_mapnode_init(bool repeat)
f->liquid_alternative_source = CONTENT_LAVASOURCE; f->liquid_alternative_source = CONTENT_LAVASOURCE;
f->liquid_viscosity = LAVA_VISC; f->liquid_viscosity = LAVA_VISC;
f->damage_per_second = 4*2; f->damage_per_second = 4*2;
f->sound_ambient = "env-lava";
#ifndef SERVER #ifndef SERVER
f->post_effect_color = video::SColor(192, 255, 64, 0); f->post_effect_color = video::SColor(192, 255, 64, 0);
#endif #endif

View File

@ -955,6 +955,7 @@ void content_mapnode_special(bool repeat)
f->diggable = false; f->diggable = false;
f->buildable_to = true; f->buildable_to = true;
f->damage_per_second = 8; f->damage_per_second = 8;
f->sound_ambient = "env-fire";
#ifndef SERVER #ifndef SERVER
f->post_effect_color = video::SColor(192, 255, 64, 0); f->post_effect_color = video::SColor(192, 255, 64, 0);
#endif #endif

View File

@ -219,6 +219,7 @@ void content_mob_init()
f->punch_action = MPA_PICKUP; f->punch_action = MPA_PICKUP;
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_RAT)+" 1"; f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_RAT)+" 1";
f->motion = MM_WANDER; f->motion = MM_WANDER;
f->moves_silently = true;
f->spawn_on = CONTENT_STONE; f->spawn_on = CONTENT_STONE;
f->spawn_in = CONTENT_AIR; f->spawn_in = CONTENT_AIR;
f->spawn_max_height = -10; f->spawn_max_height = -10;

View File

@ -29,6 +29,9 @@
#include "main.h" #include "main.h"
#include "light.h" #include "light.h"
#include <sstream> #include <sstream>
#ifndef SERVER
#include "sound.h"
#endif
/* /*
MapBlock MapBlock
@ -65,15 +68,19 @@ MapBlock::~MapBlock()
{ {
JMutexAutoLock lock(mesh_mutex); JMutexAutoLock lock(mesh_mutex);
if(mesh) if (mesh) {
{
delete mesh; delete mesh;
mesh = NULL; mesh = NULL;
} }
if (g_sound) {
for (std::map<v3s16,MapBlockSound>::iterator i = m_sounds.begin(); i != m_sounds.end(); i++) {
g_sound->stopSound(i->second.id);
}
}
} }
#endif #endif
if(data) if (data)
delete[] data; delete[] data;
} }
@ -126,6 +133,7 @@ void MapBlock::updateMesh(u32 daynight_ratio, Environment *env, v3s16 camera_off
MeshMakeData data; MeshMakeData data;
data.m_env = env; data.m_env = env;
data.fill(daynight_ratio, this); data.fill(daynight_ratio, this);
data.m_sounds = &m_sounds;
MapBlockMesh *mesh_new = new MapBlockMesh(&data, camera_offset); MapBlockMesh *mesh_new = new MapBlockMesh(&data, camera_offset);

View File

@ -584,6 +584,8 @@ public:
#ifndef SERVER // Only on client #ifndef SERVER // Only on client
MapBlockMesh *mesh; MapBlockMesh *mesh;
JMutex mesh_mutex; JMutex mesh_mutex;
std::map<v3s16,MapBlockSound> m_sounds;
#endif #endif
NodeMetadataList m_node_metadata; NodeMetadataList m_node_metadata;

View File

@ -34,6 +34,7 @@
#include "profiler.h" #include "profiler.h"
#include "mesh.h" #include "mesh.h"
#include "base64.h" #include "base64.h"
#include "sound.h"
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block) void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
{ {

View File

@ -120,6 +120,12 @@ u8 getSmoothLight(v3s16 p, v3s16 corner, VoxelManipulator &vmanip, u32 daynight_
class MapBlock; class MapBlock;
class Environment; class Environment;
struct MapBlockSound
{
int id;
std::string name;
};
struct MeshMakeData struct MeshMakeData
{ {
u32 m_daynight_ratio; u32 m_daynight_ratio;
@ -128,6 +134,8 @@ struct MeshMakeData
v3s16 m_blockpos; v3s16 m_blockpos;
Environment *m_env; Environment *m_env;
std::map<v3s16,MapBlockSound> *m_sounds;
/* /*
Copy central data directly from block, and other data from Copy central data directly from block, and other data from
parent of block. parent of block.

View File

@ -402,6 +402,8 @@ struct ContentFeatures
std::string sound_dig; std::string sound_dig;
// Sound played when the node is placed // Sound played when the node is placed
std::string sound_place; std::string sound_place;
// Sound played by the node always
std::string sound_ambient;
// If the content is liquid, this is the flowing version of the liquid. // If the content is liquid, this is the flowing version of the liquid.
// If content is liquid, this is the same content. // If content is liquid, this is the same content.
@ -500,6 +502,7 @@ struct ContentFeatures
sound_step = ""; sound_step = "";
sound_dig = ""; sound_dig = "";
sound_place = ""; sound_place = "";
sound_ambient = "";
liquid_alternative_flowing = CONTENT_IGNORE; liquid_alternative_flowing = CONTENT_IGNORE;
liquid_alternative_source = CONTENT_IGNORE; liquid_alternative_source = CONTENT_IGNORE;
liquid_viscosity = 0; liquid_viscosity = 0;

View File

@ -35,6 +35,8 @@ ISoundManager *g_sound = NULL;
void init_sounds(ISoundManager *sound) void init_sounds(ISoundManager *sound)
{ {
// sounds must be mono sounds, stereo will not work right!
// exceptions: background music
// walking // walking
// CMT_DIRT // CMT_DIRT
sound->loadSound("dirt-step-left","step_dirt.1.ogg"); sound->loadSound("dirt-step-left","step_dirt.1.ogg");
@ -95,12 +97,12 @@ void init_sounds(ISoundManager *sound)
sound->loadSound("open-chest","open_chest.ogg"); sound->loadSound("open-chest","open_chest.ogg");
// environment and node sounds // environment and node sounds
// these must be mono sounds, stereo will not work right!
sound->loadSound("env-piston","env_piston.ogg"); sound->loadSound("env-piston","env_piston.ogg");
sound->loadSound("env-dooropen","env_dooropen.ogg"); sound->loadSound("env-dooropen","env_dooropen.ogg");
sound->loadSound("env-doorclose","env_doorclose.ogg"); sound->loadSound("env-doorclose","env_doorclose.ogg");
sound->loadSound("env-fire","env_fire.ogg"); sound->loadSound("env-fire","env_fire.ogg");
sound->loadSound("env-lava","env_lava.ogg"); sound->loadSound("env-lava","env_lava.ogg",0.2);
sound->loadSound("env-water","env_water.ogg",0.2);
sound->loadSound("env-steam","env_steam.ogg"); sound->loadSound("env-steam","env_steam.ogg");
sound->loadSound("env-tnt","env_tnt.ogg"); sound->loadSound("env-tnt","env_tnt.ogg");
sound->loadSound("env-teleport","env_teleport.ogg"); sound->loadSound("env-teleport","env_teleport.ogg");

View File

@ -48,7 +48,7 @@ public:
// playSound functions return -1 on failure, otherwise a handle to the // playSound functions return -1 on failure, otherwise a handle to the
// sound. If name=="", call should be ignored without error. // sound. If name=="", call should be ignored without error.
virtual int playSound(const std::string &name, bool loop) = 0; virtual int playSound(const std::string &name, bool loop) = 0;
virtual int playSoundAt(const std::string &name, bool loop, v3f pos, float gain=1.0) = 0; virtual int playSoundAt(const std::string &name, bool loop, v3f pos, float gain=1.0, bool queue=false) = 0;
virtual void stopSound(int sound) = 0; virtual void stopSound(int sound) = 0;
virtual bool soundExists(int sound) = 0; virtual bool soundExists(int sound) = 0;
@ -69,7 +69,7 @@ public:
void setListenerGain(float gain) {} void setListenerGain(float gain) {}
int playSound(const std::string &name, bool loop) {return 0;} int playSound(const std::string &name, bool loop) {return 0;}
int playSoundAt(const std::string &name, bool loop, v3f pos, float gain) {return 0;} int playSoundAt(const std::string &name, bool loop, v3f pos, float gain, bool queue) {return 0;}
void stopSound(int sound) {} void stopSound(int sound) {}
bool soundExists(int sound) {return false;} bool soundExists(int sound) {return false;}

View File

@ -177,9 +177,14 @@ SoundBuffer* loadOggFile(const std::string &filepath)
struct PlayingSound struct PlayingSound
{ {
SoundBuffer *buf;
ALuint source_id; ALuint source_id;
bool loop; bool loop;
bool should_delete; bool should_delete;
bool has_position;
v3f pos;
bool disabled;
float gain;
}; };
class OpenALSoundManager: public ISoundManager class OpenALSoundManager: public ISoundManager
@ -195,6 +200,7 @@ private:
std::map<int, PlayingSound*> m_sounds_playing; std::map<int, PlayingSound*> m_sounds_playing;
std::map<std::string, int> m_indexes; std::map<std::string, int> m_indexes;
v3f m_listener_pos; v3f m_listener_pos;
JMutex m_mutex;
public: public:
OpenALSoundManager(): OpenALSoundManager():
m_device(NULL), m_device(NULL),
@ -208,6 +214,8 @@ public:
infostream<<"Audio: Initializing..."<<std::endl; infostream<<"Audio: Initializing..."<<std::endl;
m_mutex.Init();
m_device = alcOpenDevice(NULL); m_device = alcOpenDevice(NULL);
if (!m_device) { if (!m_device) {
infostream<<"Audio: No audio device available, audio system " infostream<<"Audio: No audio device available, audio system "
@ -267,6 +275,7 @@ public:
~OpenALSoundManager() ~OpenALSoundManager()
{ {
infostream<<"Audio: Deinitializing..."<<std::endl; infostream<<"Audio: Deinitializing..."<<std::endl;
g_sound = NULL;
// KABOOM! // KABOOM!
// TODO: Clear SoundBuffers // TODO: Clear SoundBuffers
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
@ -329,14 +338,18 @@ public:
alSource3f(sound->source_id, AL_POSITION, 0, 0, 0); alSource3f(sound->source_id, AL_POSITION, 0, 0, 0);
alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0); alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0);
alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
float volume = MYMAX(0.0, buf->gain); sound->gain = 1.0;
alSourcef(sound->source_id, AL_GAIN, volume); alSourcef(sound->source_id, AL_GAIN, buf->gain);
alSourcePlay(sound->source_id); alSourcePlay(sound->source_id);
sound->should_delete = false; sound->should_delete = false;
sound->loop = loop;
sound->has_position = false;
sound->disabled = false;
sound->buf = buf;
return sound; return sound;
} }
PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop, v3f pos, float gain) PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop, v3f pos, float gain, bool queue)
{ {
infostream<<"OpenALSoundManager: Creating positional playing sound" infostream<<"OpenALSoundManager: Creating positional playing sound"
<<std::endl; <<std::endl;
@ -345,18 +358,29 @@ public:
errorstream<<"Attempting to play non-mono sound as positional sound"<<std::endl; errorstream<<"Attempting to play non-mono sound as positional sound"<<std::endl;
PlayingSound *sound = new PlayingSound; PlayingSound *sound = new PlayingSound;
assert(sound); assert(sound);
alGenSources(1, &sound->source_id); float distance = m_listener_pos.getDistanceFrom(pos);
alSourcei(sound->source_id, AL_BUFFER, buf->buffer_id); if (!queue && (!loop || distance < 240.0)) {
alSourcei(sound->source_id, AL_SOURCE_RELATIVE, false); alGenSources(1, &sound->source_id);
alSource3f(sound->source_id, AL_POSITION, pos.X, pos.Y, pos.Z); alSourcei(sound->source_id, AL_BUFFER, buf->buffer_id);
alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0); alSourcei(sound->source_id, AL_SOURCE_RELATIVE, false);
//alSourcef(sound->source_id, AL_ROLLOFF_FACTOR, 0.7); alSource3f(sound->source_id, AL_POSITION, pos.X, pos.Y, pos.Z);
alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 30.0); alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0);
alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 30.0);
float volume = MYMAX(0.0, buf->gain*gain); alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
alSourcef(sound->source_id, AL_GAIN, volume); float t_gain = MYMAX(0.0, buf->gain*gain);
alSourcePlay(sound->source_id); alSourcef(sound->source_id, AL_GAIN, t_gain);
alSourcePlay(sound->source_id);
sound->disabled = false;
}else{
sound->source_id = 0;
sound->disabled = true;
}
sound->gain = gain;
sound->should_delete = false; sound->should_delete = false;
sound->loop = loop;
sound->has_position = true;
sound->pos = pos;
sound->buf = buf;
return sound; return sound;
} }
@ -366,19 +390,27 @@ public:
PlayingSound *sound = createPlayingSound(buf, loop); PlayingSound *sound = createPlayingSound(buf, loop);
if (!sound) if (!sound)
return -1; return -1;
int id = m_next_id++; int id = -1;
m_sounds_playing[id] = sound; {
JMutexAutoLock lock(m_mutex);
id = m_next_id++;
m_sounds_playing[id] = sound;
}
return id; return id;
} }
int playSoundRawAt(SoundBuffer *buf, bool loop, v3f pos, float gain) int playSoundRawAt(SoundBuffer *buf, bool loop, v3f pos, float gain, bool queue)
{ {
assert(buf); assert(buf);
PlayingSound *sound = createPlayingSoundAt(buf, loop, pos, gain); PlayingSound *sound = createPlayingSoundAt(buf, loop, pos, gain, queue);
if (!sound) if (!sound)
return -1; return -1;
int id = m_next_id++; int id = -1;
m_sounds_playing[id] = sound; {
JMutexAutoLock lock(m_mutex);
id = m_next_id++;
m_sounds_playing[id] = sound;
}
return id; return id;
} }
@ -391,24 +423,53 @@ public:
m_music_last_id = 0; m_music_last_id = 0;
if (i == m_sounds_playing.end()) if (i == m_sounds_playing.end())
return; return;
PlayingSound *sound = i->second; PlayingSound *sound = i->second;
alSourceStop(sound->source_id);
alDeleteSources(1, &sound->source_id); alDeleteSources(1, &sound->source_id);
delete sound; delete sound;
m_sounds_playing.erase(id); m_sounds_playing.erase(id);
} }
// Remove stopped sounds // Remove stopped sounds
void maintain(float dtime) void maintain(float dtime)
{ {
JMutexAutoLock lock(m_mutex);
verbosestream<<"OpenALSoundManager::maintain(): " verbosestream<<"OpenALSoundManager::maintain(): "
<<m_sounds_playing.size()<<" playing sounds, " <<m_sounds_playing.size()<<" playing sounds, "
<<m_buffers.size()<<" sound names loaded"<<std::endl; <<m_buffers.size()<<" sound names loaded"<<std::endl;
std::set<int> del_list; std::set<int> del_list;
bool did_start = false;
for (std::map<int, PlayingSound*>::iterator i = m_sounds_playing.begin(); i != m_sounds_playing.end(); i++) { for (std::map<int, PlayingSound*>::iterator i = m_sounds_playing.begin(); i != m_sounds_playing.end(); i++) {
int id = i->first; int id = i->first;
PlayingSound *sound = i->second; PlayingSound *sound = i->second;
if (sound->has_position && sound->loop && !sound->should_delete) {
float distance = m_listener_pos.getDistanceFrom(sound->pos);
if (distance > 320.0 && !sound->disabled && !did_start) {
alSourceStop(sound->source_id);
alDeleteSources(1, &sound->source_id);
sound->disabled = true;
sound->source_id = 0;
}else if (distance < 240.0 && sound->disabled) {
did_start = true;
alGenSources(1, &sound->source_id);
alSourcei(sound->source_id, AL_BUFFER, sound->buf->buffer_id);
alSourcei(sound->source_id, AL_SOURCE_RELATIVE, false);
alSource3f(sound->source_id, AL_POSITION, sound->pos.X, sound->pos.Y, sound->pos.Z);
alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0);
alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 30.0);
alSourcei(sound->source_id, AL_LOOPING, AL_TRUE);
float t_gain = MYMAX(0.0, sound->buf->gain*sound->gain);
alSourcef(sound->source_id, AL_GAIN, t_gain);
alSourcePlay(sound->source_id);
sound->disabled = false;
}
continue;
}
if (sound->should_delete) { if (sound->should_delete) {
del_list.insert(id); del_list.insert(id);
}else{ // If not playing, remove it }else{ // If not playing, remove it
@ -490,7 +551,7 @@ public:
} }
return playSoundRaw(buf, loop); return playSoundRaw(buf, loop);
} }
int playSoundAt(const std::string &name, bool loop, v3f pos, float gain) int playSoundAt(const std::string &name, bool loop, v3f pos, float gain, bool queue=false)
{ {
if (name == "") if (name == "")
return 0; return 0;
@ -500,10 +561,11 @@ public:
<<std::endl; <<std::endl;
return -1; return -1;
} }
return playSoundRawAt(buf, loop, pos, gain); return playSoundRawAt(buf, loop, pos, gain, queue);
} }
void stopSound(int id) void stopSound(int id)
{ {
JMutexAutoLock lock(m_mutex);
std::map<int, PlayingSound*>::iterator i = m_sounds_playing.find(id); std::map<int, PlayingSound*>::iterator i = m_sounds_playing.find(id);
if (id == m_music_id) if (id == m_music_id)
m_music_id = 0; m_music_id = 0;
@ -516,6 +578,7 @@ public:
} }
bool soundExists(int sound) bool soundExists(int sound)
{ {
JMutexAutoLock lock(m_mutex);
return (m_sounds_playing.count(sound) != 0); return (m_sounds_playing.count(sound) != 0);
} }