Sound: Add pitch option (#5960)

* Sound: Add pitch option
This commit is contained in:
Rui 2017-06-11 20:58:26 +09:00 committed by Loïc Blot
parent 03ff53e16b
commit ff73c7a5da
10 changed files with 68 additions and 54 deletions

View File

@ -622,12 +622,14 @@ Examples of sound parameter tables:
{ {
gain = 1.0, -- default gain = 1.0, -- default
fade = 0.0, -- default, change to a value > 0 to fade the sound in fade = 0.0, -- default, change to a value > 0 to fade the sound in
pitch = 1.0, -- default
} }
-- Play locationless to one player -- Play locationless to one player
{ {
to_player = name, to_player = name,
gain = 1.0, -- default gain = 1.0, -- default
fade = 0.0, -- default, change to a value > 0 to fade the sound in fade = 0.0, -- default, change to a value > 0 to fade the sound in
pitch = 1.0, -- default
} }
-- Play locationless to one player, looped -- Play locationless to one player, looped
{ {
@ -658,6 +660,7 @@ one player using `to_player = name,`
* e.g. `{}` * e.g. `{}`
* e.g. `{name = "default_place_node"}` * e.g. `{name = "default_place_node"}`
* e.g. `{name = "default_place_node", gain = 1.0}` * e.g. `{name = "default_place_node", gain = 1.0}`
* e.g. `{name = "default_place_node", gain = 1.0, pitch = 1.0}`
Registered definitions of stuff Registered definitions of stuff
------------------------------- -------------------------------

View File

@ -156,6 +156,8 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
writeF1000(os, sound_place_failed.gain); writeF1000(os, sound_place_failed.gain);
os << serializeString(palette_image); os << serializeString(palette_image);
writeU32(os, color.color); writeU32(os, color.color);
writeF1000(os, sound_place.pitch);
writeF1000(os, sound_place_failed.pitch);
} }
void ItemDefinition::deSerialize(std::istream &is) void ItemDefinition::deSerialize(std::istream &is)
@ -214,6 +216,8 @@ void ItemDefinition::deSerialize(std::istream &is)
sound_place_failed.gain = readF1000(is); sound_place_failed.gain = readF1000(is);
palette_image = deSerializeString(is); palette_image = deSerializeString(is);
color.set(readU32(is)); color.set(readU32(is));
sound_place.pitch = readF1000(is);
sound_place_failed.pitch = readF1000(is);
} catch(SerializationError &e) {}; } catch(SerializationError &e) {};
} }

View File

@ -764,6 +764,7 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
[23 + len] u16 object_id [23 + len] u16 object_id
[25 + len] bool loop [25 + len] bool loop
[26 + len] f32 fade [26 + len] f32 fade
[30 + len] f32 pitch
*/ */
s32 server_id; s32 server_id;
@ -774,29 +775,31 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
v3f pos; v3f pos;
u16 object_id; u16 object_id;
bool loop; bool loop;
float fade = 0; float fade = 0.0f;
float pitch = 1.0f;
*pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop; *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
try { try {
*pkt >> fade; *pkt >> fade;
*pkt >> pitch;
} catch (PacketError &e) {}; } catch (PacketError &e) {};
// Start playing // Start playing
int client_id = -1; int client_id = -1;
switch(type) { switch(type) {
case 0: // local case 0: // local
client_id = m_sound->playSound(name, loop, gain, fade); client_id = m_sound->playSound(name, loop, gain, fade, pitch);
break; break;
case 1: // positional case 1: // positional
client_id = m_sound->playSoundAt(name, loop, gain, pos); client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
break; break;
case 2: case 2:
{ // object { // object
ClientActiveObject *cao = m_env.getActiveObject(object_id); ClientActiveObject *cao = m_env.getActiveObject(object_id);
if (cao) if (cao)
pos = cao->getPosition(); pos = cao->getPosition();
client_id = m_sound->playSoundAt(name, loop, gain, pos); client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
// TODO: Set up sound to move with object // TODO: Set up sound to move with object
break; break;
} }

View File

@ -252,11 +252,13 @@ static void serializeSimpleSoundSpec(const SimpleSoundSpec &ss,
{ {
os<<serializeString(ss.name); os<<serializeString(ss.name);
writeF1000(os, ss.gain); writeF1000(os, ss.gain);
writeF1000(os, ss.pitch);
} }
static void deSerializeSimpleSoundSpec(SimpleSoundSpec &ss, std::istream &is) static void deSerializeSimpleSoundSpec(SimpleSoundSpec &ss, std::istream &is)
{ {
ss.name = deSerializeString(is); ss.name = deSerializeString(is);
ss.gain = readF1000(is); ss.gain = readF1000(is);
ss.pitch = readF1000(is);
} }
void TextureSettings::readSettings() void TextureSettings::readSettings()

View File

@ -925,6 +925,7 @@ void read_server_sound_params(lua_State *L, int index,
getfloatfield(L, index, "gain", params.gain); getfloatfield(L, index, "gain", params.gain);
getstringfield(L, index, "to_player", params.to_player); getstringfield(L, index, "to_player", params.to_player);
getfloatfield(L, index, "fade", params.fade); getfloatfield(L, index, "fade", params.fade);
getfloatfield(L, index, "pitch", params.pitch);
lua_getfield(L, index, "pos"); lua_getfield(L, index, "pos");
if(!lua_isnil(L, -1)){ if(!lua_isnil(L, -1)){
v3f p = read_v3f(L, -1)*BS; v3f p = read_v3f(L, -1)*BS;
@ -958,6 +959,7 @@ void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
getstringfield(L, index, "name", spec.name); getstringfield(L, index, "name", spec.name);
getfloatfield(L, index, "gain", spec.gain); getfloatfield(L, index, "gain", spec.gain);
getfloatfield(L, index, "fade", spec.fade); getfloatfield(L, index, "fade", spec.fade);
getfloatfield(L, index, "pitch", spec.pitch);
} else if(lua_isstring(L, index)){ } else if(lua_isstring(L, index)){
spec.name = lua_tostring(L, index); spec.name = lua_tostring(L, index);
} }
@ -972,6 +974,8 @@ void push_soundspec(lua_State *L, const SimpleSoundSpec &spec)
lua_setfield(L, -2, "gain"); lua_setfield(L, -2, "gain");
lua_pushnumber(L, spec.fade); lua_pushnumber(L, spec.fade);
lua_setfield(L, -2, "fade"); lua_setfield(L, -2, "fade");
lua_pushnumber(L, spec.pitch);
lua_setfield(L, -2, "pitch");
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -227,12 +227,14 @@ int ModApiClient::l_sound_play(lua_State *L)
SimpleSoundSpec spec; SimpleSoundSpec spec;
read_soundspec(L, 1, spec); read_soundspec(L, 1, spec);
float gain = 1.0; float gain = 1.0f;
float pitch = 1.0f;
bool looped = false; bool looped = false;
s32 handle; s32 handle;
if (lua_istable(L, 2)) { if (lua_istable(L, 2)) {
getfloatfield(L, 2, "gain", gain); getfloatfield(L, 2, "gain", gain);
getfloatfield(L, 2, "pitch", pitch);
getboolfield(L, 2, "loop", looped); getboolfield(L, 2, "loop", looped);
lua_getfield(L, 2, "pos"); lua_getfield(L, 2, "pos");
@ -240,13 +242,13 @@ int ModApiClient::l_sound_play(lua_State *L)
v3f pos = read_v3f(L, -1) * BS; v3f pos = read_v3f(L, -1) * BS;
lua_pop(L, 1); lua_pop(L, 1);
handle = sound->playSoundAt( handle = sound->playSoundAt(
spec.name, looped, gain * spec.gain, pos); spec.name, looped, gain * spec.gain, pos, pitch);
lua_pushinteger(L, handle); lua_pushinteger(L, handle);
return 1; return 1;
} }
} }
handle = sound->playSound(spec.name, looped, gain * spec.gain); handle = sound->playSound(spec.name, looped, gain * spec.gain, 0.0f, pitch);
lua_pushinteger(L, handle); lua_pushinteger(L, handle);
return 1; return 1;

View File

@ -2098,7 +2098,7 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0); NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
pkt << id << spec.name << gain pkt << id << spec.name << gain
<< (u8) params.type << pos << params.object << (u8) params.type << pos << params.object
<< params.loop << params.fade; << params.loop << params.fade << params.pitch;
// Backwards compability // Backwards compability
bool play_sound = gain > 0; bool play_sound = gain > 0;

View File

@ -104,29 +104,19 @@ struct MediaInfo
struct ServerSoundParams struct ServerSoundParams
{ {
float gain; enum Type {
std::string to_player; SSP_LOCAL,
enum Type{ SSP_POSITIONAL,
SSP_LOCAL=0, SSP_OBJECT
SSP_POSITIONAL=1, } type = SSP_LOCAL;
SSP_OBJECT=2 float gain = 1.0f;
} type; float fade = 0.0f;
v3f pos; float pitch = 1.0f;
u16 object; bool loop = false;
float max_hear_distance; float max_hear_distance = 32*BS;
bool loop; v3f pos = v3f(0, 0, 0);
float fade; u16 object = 0;
std::string to_player = "";
ServerSoundParams():
gain(1.0),
to_player(""),
type(SSP_LOCAL),
pos(0,0,0),
object(0),
max_hear_distance(32*BS),
loop(false),
fade(0)
{}
v3f getPos(ServerEnvironment *env, bool *pos_exists) const; v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
}; };

View File

@ -34,16 +34,18 @@ public:
struct SimpleSoundSpec struct SimpleSoundSpec
{ {
SimpleSoundSpec(const std::string &name = "", float gain = 1.0, float fade = 0.0) SimpleSoundSpec(const std::string &name = "", float gain = 1.0f,
: name(name), gain(gain), fade(fade) float fade = 0.0f, float pitch = 1.0f)
: name(name), gain(gain), fade(fade), pitch(pitch)
{ {
} }
bool exists() const { return name != ""; } bool exists() const { return name != ""; }
std::string name; std::string name = "";
float gain; float gain = 1.0f;
float fade; float fade = 0.0f;
float pitch = 1.0f;
}; };
class ISoundManager class ISoundManager
@ -64,9 +66,9 @@ 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, float volume, virtual int playSound(const std::string &name, bool loop, float volume,
float fade = 0) = 0; float fade = 0.0f, float pitch = 1.0f) = 0;
virtual int playSoundAt( virtual int playSoundAt(const std::string &name, bool loop, float volume, v3f pos,
const std::string &name, bool loop, float volume, v3f pos) = 0; float pitch = 1.0f) = 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;
virtual void updateSoundPosition(int sound, v3f pos) = 0; virtual void updateSoundPosition(int sound, v3f pos) = 0;
@ -77,11 +79,11 @@ public:
int playSound(const SimpleSoundSpec &spec, bool loop) int playSound(const SimpleSoundSpec &spec, bool loop)
{ {
return playSound(spec.name, loop, spec.gain, spec.fade); return playSound(spec.name, loop, spec.gain, spec.fade, spec.pitch);
} }
int playSoundAt(const SimpleSoundSpec &spec, bool loop, v3f pos) int playSoundAt(const SimpleSoundSpec &spec, bool loop, v3f pos)
{ {
return playSoundAt(spec.name, loop, spec.gain, pos); return playSoundAt(spec.name, loop, spec.gain, pos, spec.pitch);
} }
}; };
@ -98,11 +100,13 @@ public:
} }
void updateListener(v3f pos, v3f vel, v3f at, v3f up) {} void updateListener(v3f pos, v3f vel, v3f at, v3f up) {}
void setListenerGain(float gain) {} void setListenerGain(float gain) {}
int playSound(const std::string &name, bool loop, float volume, float fade) int playSound(const std::string &name, bool loop, float volume, float fade,
float pitch)
{ {
return 0; return 0;
} }
int playSoundAt(const std::string &name, bool loop, float volume, v3f pos) int playSoundAt(const std::string &name, bool loop, float volume, v3f pos,
float pitch)
{ {
return 0; return 0;
} }

View File

@ -394,7 +394,7 @@ public:
} }
PlayingSound* createPlayingSound(SoundBuffer *buf, bool loop, PlayingSound* createPlayingSound(SoundBuffer *buf, bool loop,
float volume) float volume, float pitch)
{ {
infostream<<"OpenALSoundManager: Creating playing sound"<<std::endl; infostream<<"OpenALSoundManager: Creating playing sound"<<std::endl;
assert(buf); assert(buf);
@ -409,13 +409,14 @@ public:
alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
volume = MYMAX(0.0, volume); volume = MYMAX(0.0, volume);
alSourcef(sound->source_id, AL_GAIN, volume); alSourcef(sound->source_id, AL_GAIN, volume);
alSourcef(sound->source_id, AL_PITCH, pitch);
alSourcePlay(sound->source_id); alSourcePlay(sound->source_id);
warn_if_error(alGetError(), "createPlayingSound"); warn_if_error(alGetError(), "createPlayingSound");
return sound; return sound;
} }
PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop, PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop,
float volume, v3f pos) float volume, v3f pos, float pitch)
{ {
infostream<<"OpenALSoundManager: Creating positional playing sound" infostream<<"OpenALSoundManager: Creating positional playing sound"
<<std::endl; <<std::endl;
@ -432,15 +433,16 @@ public:
alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); alSourcei(sound->source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
volume = MYMAX(0.0, volume); volume = MYMAX(0.0, volume);
alSourcef(sound->source_id, AL_GAIN, volume); alSourcef(sound->source_id, AL_GAIN, volume);
alSourcef(sound->source_id, AL_PITCH, pitch);
alSourcePlay(sound->source_id); alSourcePlay(sound->source_id);
warn_if_error(alGetError(), "createPlayingSoundAt"); warn_if_error(alGetError(), "createPlayingSoundAt");
return sound; return sound;
} }
int playSoundRaw(SoundBuffer *buf, bool loop, float volume) int playSoundRaw(SoundBuffer *buf, bool loop, float volume, float pitch)
{ {
assert(buf); assert(buf);
PlayingSound *sound = createPlayingSound(buf, loop, volume); PlayingSound *sound = createPlayingSound(buf, loop, volume, pitch);
if(!sound) if(!sound)
return -1; return -1;
int id = m_next_id++; int id = m_next_id++;
@ -448,10 +450,10 @@ public:
return id; return id;
} }
int playSoundRawAt(SoundBuffer *buf, bool loop, float volume, v3f pos) int playSoundRawAt(SoundBuffer *buf, bool loop, float volume, v3f pos, float pitch)
{ {
assert(buf); assert(buf);
PlayingSound *sound = createPlayingSoundAt(buf, loop, volume, pos); PlayingSound *sound = createPlayingSoundAt(buf, loop, volume, pos, pitch);
if(!sound) if(!sound)
return -1; return -1;
int id = m_next_id++; int id = m_next_id++;
@ -561,7 +563,7 @@ public:
alListenerf(AL_GAIN, gain); alListenerf(AL_GAIN, gain);
} }
int playSound(const std::string &name, bool loop, float volume, float fade) int playSound(const std::string &name, bool loop, float volume, float fade, float pitch)
{ {
maintain(); maintain();
if(name == "") if(name == "")
@ -574,15 +576,15 @@ public:
} }
int handle = -1; int handle = -1;
if (fade > 0) { if (fade > 0) {
handle = playSoundRaw(buf, loop, 0); handle = playSoundRaw(buf, loop, 0.0f, 0.0f);
fadeSound(handle, fade, volume); fadeSound(handle, fade, volume);
} else { } else {
handle = playSoundRaw(buf, loop, volume); handle = playSoundRaw(buf, loop, volume, pitch);
} }
return handle; return handle;
} }
int playSoundAt(const std::string &name, bool loop, float volume, v3f pos) int playSoundAt(const std::string &name, bool loop, float volume, v3f pos, float pitch)
{ {
maintain(); maintain();
if(name == "") if(name == "")
@ -593,7 +595,7 @@ public:
<<std::endl; <<std::endl;
return -1; return -1;
} }
return playSoundRawAt(buf, loop, volume, pos); return playSoundRawAt(buf, loop, volume, pos, pitch);
} }
void stopSound(int sound) void stopSound(int sound)