ambient sounds, maybe

master
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
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;
}*/
while (getRun()) {
QueuedMeshUpdate *q = m_queue_in.pop();
if(q == NULL)
{
if (q == NULL) {
sleep_ms(3);
continue;
}
@ -178,10 +167,6 @@ void * MeshUpdateThread::Thread()
r.mesh = mesh_new;
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);
delete q;
@ -2261,6 +2246,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
data->fill(getDayNightRatio(), b);
}
data->m_sounds = &b->m_sounds;
// Debug wait
//while(m_mesh_update_thread.m_queue_in.size() > 0) sleep_ms(10);

View File

@ -31,6 +31,7 @@
#include "settings.h"
#include "environment.h"
#include "nodemetadata.h"
#include "sound.h"
#ifndef SERVER
// Create a cuboid.
@ -484,6 +485,32 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
data->m_temp_mods.get(p,&mod);
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
*/

View File

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

View File

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

View File

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

View File

@ -29,6 +29,9 @@
#include "main.h"
#include "light.h"
#include <sstream>
#ifndef SERVER
#include "sound.h"
#endif
/*
MapBlock
@ -65,15 +68,19 @@ MapBlock::~MapBlock()
{
JMutexAutoLock lock(mesh_mutex);
if(mesh)
{
if (mesh) {
delete mesh;
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
if(data)
if (data)
delete[] data;
}
@ -126,6 +133,7 @@ void MapBlock::updateMesh(u32 daynight_ratio, Environment *env, v3s16 camera_off
MeshMakeData data;
data.m_env = env;
data.fill(daynight_ratio, this);
data.m_sounds = &m_sounds;
MapBlockMesh *mesh_new = new MapBlockMesh(&data, camera_offset);

View File

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

View File

@ -34,6 +34,7 @@
#include "profiler.h"
#include "mesh.h"
#include "base64.h"
#include "sound.h"
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 Environment;
struct MapBlockSound
{
int id;
std::string name;
};
struct MeshMakeData
{
u32 m_daynight_ratio;
@ -128,6 +134,8 @@ struct MeshMakeData
v3s16 m_blockpos;
Environment *m_env;
std::map<v3s16,MapBlockSound> *m_sounds;
/*
Copy central data directly from block, and other data from
parent of block.

View File

@ -402,6 +402,8 @@ struct ContentFeatures
std::string sound_dig;
// Sound played when the node is placed
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 content is liquid, this is the same content.
@ -500,6 +502,7 @@ struct ContentFeatures
sound_step = "";
sound_dig = "";
sound_place = "";
sound_ambient = "";
liquid_alternative_flowing = CONTENT_IGNORE;
liquid_alternative_source = CONTENT_IGNORE;
liquid_viscosity = 0;

View File

@ -35,6 +35,8 @@ ISoundManager *g_sound = NULL;
void init_sounds(ISoundManager *sound)
{
// sounds must be mono sounds, stereo will not work right!
// exceptions: background music
// walking
// CMT_DIRT
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");
// environment and node sounds
// these must be mono sounds, stereo will not work right!
sound->loadSound("env-piston","env_piston.ogg");
sound->loadSound("env-dooropen","env_dooropen.ogg");
sound->loadSound("env-doorclose","env_doorclose.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-tnt","env_tnt.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
// sound. If name=="", call should be ignored without error.
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 bool soundExists(int sound) = 0;
@ -69,7 +69,7 @@ public:
void setListenerGain(float gain) {}
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) {}
bool soundExists(int sound) {return false;}

View File

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