forked from teamnwah/openmw-tes3coop
Load sound loudness and store it with the Sound_Buffer
Still not used for say yet, though
This commit is contained in:
parent
f4c22ec49e
commit
495e138907
9 changed files with 91 additions and 89 deletions
|
@ -8,49 +8,61 @@
|
|||
namespace MWSound
|
||||
{
|
||||
|
||||
void analyzeLoudness(const std::vector<char> &data, int sampleRate, ChannelConfig chans,
|
||||
SampleType type, std::vector<float> &out, float valuesPerSecond)
|
||||
void Sound_Loudness::analyzeLoudness(const std::vector< char >& data, int sampleRate, ChannelConfig chans, SampleType type, float valuesPerSecond)
|
||||
{
|
||||
int samplesPerSegment = static_cast<int>(sampleRate / valuesPerSecond);
|
||||
int numSamples = bytesToFrames(data.size(), chans, type);
|
||||
int advance = framesToBytes(1, chans, type);
|
||||
|
||||
mSamplesPerSec = valuesPerSecond;
|
||||
mSamples.clear();
|
||||
mSamples.reserve(numSamples/samplesPerSegment);
|
||||
|
||||
int segment=0;
|
||||
int sample=0;
|
||||
while (segment < numSamples/samplesPerSegment)
|
||||
{
|
||||
int samplesPerSegment = static_cast<int>(sampleRate / valuesPerSecond);
|
||||
int numSamples = bytesToFrames(data.size(), chans, type);
|
||||
int advance = framesToBytes(1, chans, type);
|
||||
|
||||
out.reserve(numSamples/samplesPerSegment);
|
||||
|
||||
int segment=0;
|
||||
int sample=0;
|
||||
while (segment < numSamples/samplesPerSegment)
|
||||
float sum=0;
|
||||
int samplesAdded = 0;
|
||||
while (sample < numSamples && sample < (segment+1)*samplesPerSegment)
|
||||
{
|
||||
float sum=0;
|
||||
int samplesAdded = 0;
|
||||
while (sample < numSamples && sample < (segment+1)*samplesPerSegment)
|
||||
// get sample on a scale from -1 to 1
|
||||
float value = 0;
|
||||
if (type == SampleType_UInt8)
|
||||
value = ((char)(data[sample*advance]^0x80))/128.f;
|
||||
else if (type == SampleType_Int16)
|
||||
{
|
||||
// get sample on a scale from -1 to 1
|
||||
float value = 0;
|
||||
if (type == SampleType_UInt8)
|
||||
value = ((char)(data[sample*advance]^0x80))/128.f;
|
||||
else if (type == SampleType_Int16)
|
||||
{
|
||||
value = *reinterpret_cast<const int16_t*>(&data[sample*advance]);
|
||||
value /= float(std::numeric_limits<int16_t>::max());
|
||||
}
|
||||
else if (type == SampleType_Float32)
|
||||
{
|
||||
value = *reinterpret_cast<const float*>(&data[sample*advance]);
|
||||
value = std::max(-1.f, std::min(1.f, value)); // Float samples *should* be scaled to [-1,1] already.
|
||||
}
|
||||
|
||||
sum += value*value;
|
||||
++samplesAdded;
|
||||
++sample;
|
||||
value = *reinterpret_cast<const int16_t*>(&data[sample*advance]);
|
||||
value /= float(std::numeric_limits<int16_t>::max());
|
||||
}
|
||||
else if (type == SampleType_Float32)
|
||||
{
|
||||
value = *reinterpret_cast<const float*>(&data[sample*advance]);
|
||||
value = std::max(-1.f, std::min(1.f, value)); // Float samples *should* be scaled to [-1,1] already.
|
||||
}
|
||||
|
||||
float rms = 0; // root mean square
|
||||
if (samplesAdded > 0)
|
||||
rms = std::sqrt(sum / samplesAdded);
|
||||
out.push_back(rms);
|
||||
++segment;
|
||||
sum += value*value;
|
||||
++samplesAdded;
|
||||
++sample;
|
||||
}
|
||||
|
||||
float rms = 0; // root mean square
|
||||
if (samplesAdded > 0)
|
||||
rms = std::sqrt(sum / samplesAdded);
|
||||
mSamples.push_back(rms);
|
||||
++segment;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float Sound_Loudness::getLoudnessAtTime(float sec) const
|
||||
{
|
||||
if(mSamplesPerSec <= 0.0f || mSamples.empty() || sec < 0.0f)
|
||||
return 0.0f;
|
||||
|
||||
size_t index = static_cast<size_t>(sec * mSamplesPerSec);
|
||||
index = std::max<size_t>(0, std::min(index, mSamples.size()-1));
|
||||
return mSamples[index];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,38 @@
|
|||
#ifndef GAME_SOUND_LOUDNESS_H
|
||||
#define GAME_SOUND_LOUDNESS_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sound_decoder.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
||||
/**
|
||||
* Analyzes the energy (closely related to loudness) of a sound buffer.
|
||||
* The buffer will be divided into segments according to \a valuesPerSecond,
|
||||
* and for each segment a loudness value in the range of [0,1] will be computed.
|
||||
* @param data the sound buffer to analyze, containing raw samples
|
||||
* @param sampleRate the sample rate of the sound buffer
|
||||
* @param chans channel layout of the buffer
|
||||
* @param type sample type of the buffer
|
||||
* @param out Will contain the output loudness values.
|
||||
* @param valuesPerSecond How many loudness values per second of audio to compute.
|
||||
*/
|
||||
void analyzeLoudness (const std::vector<char>& data, int sampleRate, ChannelConfig chans, SampleType type,
|
||||
std::vector<float>& out, float valuesPerSecond);
|
||||
class Sound_Loudness {
|
||||
// Loudness sample info
|
||||
float mSamplesPerSec;
|
||||
std::vector<float> mSamples;
|
||||
|
||||
public:
|
||||
Sound_Loudness() : mSamplesPerSec(0.0f) { }
|
||||
|
||||
/**
|
||||
* Analyzes the energy (closely related to loudness) of a sound buffer.
|
||||
* The buffer will be divided into segments according to \a valuesPerSecond,
|
||||
* and for each segment a loudness value in the range of [0,1] will be computed.
|
||||
* @param data the sound buffer to analyze, containing raw samples
|
||||
* @param sampleRate the sample rate of the sound buffer
|
||||
* @param chans channel layout of the buffer
|
||||
* @param type sample type of the buffer
|
||||
* @param valuesPerSecond How many loudness values per second of audio to compute.
|
||||
*/
|
||||
void analyzeLoudness(const std::vector<char>& data, int sampleRate,
|
||||
ChannelConfig chans, SampleType type,
|
||||
float valuesPerSecond);
|
||||
|
||||
float getLoudnessAtTime(float sec) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* GAME_SOUND_LOUDNESS_H */
|
||||
|
|
|
@ -751,7 +751,7 @@ void OpenAL_Output::deinit()
|
|||
}
|
||||
|
||||
|
||||
Sound_Handle OpenAL_Output::loadSound(const std::string &fname)
|
||||
Sound_Handle OpenAL_Output::loadSound(const std::string &fname, Sound_Loudness *loudness)
|
||||
{
|
||||
throwALerror();
|
||||
|
||||
|
@ -778,7 +778,8 @@ Sound_Handle OpenAL_Output::loadSound(const std::string &fname)
|
|||
decoder->readAll(data);
|
||||
decoder->close();
|
||||
|
||||
//analyzeLoudness(data, srate, chans, type, cached.mLoudnessVector, static_cast<float>(loudnessFPS));
|
||||
if(loudness != 0)
|
||||
loudness->analyzeLoudness(data, srate, chans, type, static_cast<float>(loudnessFPS));
|
||||
|
||||
ALuint buf = 0;
|
||||
try {
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace MWSound
|
|||
virtual void init(const std::string &devname="");
|
||||
virtual void deinit();
|
||||
|
||||
virtual Sound_Handle loadSound(const std::string &fname);
|
||||
virtual Sound_Handle loadSound(const std::string &fname, Sound_Loudness *loudness);
|
||||
virtual void unloadSound(Sound_Handle data);
|
||||
|
||||
/// @param offset Value from [0,1] meaning from which fraction the sound the playback starts.
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#include "sound.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
||||
float Sound::getCurrentLoudness()
|
||||
{
|
||||
if (mLoudnessVector.empty())
|
||||
return 0.f;
|
||||
int index = static_cast<int>(getTimeOffset() * mLoudnessFPS);
|
||||
|
||||
index = std::max(0, std::min(index, int(mLoudnessVector.size()-1)));
|
||||
|
||||
return mLoudnessVector[index];
|
||||
}
|
||||
|
||||
void Sound::setLoudnessVector(const std::vector<float> &loudnessVector, float loudnessFPS)
|
||||
{
|
||||
mLoudnessVector = loudnessVector;
|
||||
mLoudnessFPS = loudnessFPS;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,9 +22,6 @@ namespace MWSound
|
|||
int mFlags;
|
||||
float mFadeOutTime;
|
||||
|
||||
std::vector<float> mLoudnessVector;
|
||||
float mLoudnessFPS;
|
||||
|
||||
public:
|
||||
virtual void stop() = 0;
|
||||
virtual bool isPlaying() = 0;
|
||||
|
@ -32,11 +29,6 @@ namespace MWSound
|
|||
void setPosition(const osg::Vec3f &pos) { mPos = pos; }
|
||||
void setVolume(float volume) { mVolume = volume; }
|
||||
void setFadeout(float duration) { mFadeOutTime=duration; }
|
||||
void setLoudnessVector(const std::vector<float>& loudnessVector, float loudnessFPS);
|
||||
|
||||
/// Get loudness at the current time position on a [0,1] scale.
|
||||
/// Requires that loudnessVector was filled in by the user.
|
||||
float getCurrentLoudness();
|
||||
|
||||
MWBase::SoundManager::PlayType getPlayType() const
|
||||
{ return (MWBase::SoundManager::PlayType)(mFlags&MWBase::SoundManager::Play_TypeMask); }
|
||||
|
@ -51,7 +43,6 @@ namespace MWSound
|
|||
, mMaxDistance(maxdist)
|
||||
, mFlags(flags)
|
||||
, mFadeOutTime(0)
|
||||
, mLoudnessFPS(20)
|
||||
{ }
|
||||
virtual ~Sound() { }
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "soundmanagerimp.hpp"
|
||||
#include "sound_output.hpp"
|
||||
#include "loudness.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
|
@ -19,6 +20,7 @@ namespace MWSound
|
|||
float mMinDist, mMaxDist;
|
||||
|
||||
Sound_Handle mHandle;
|
||||
Sound_Loudness mLoudness;
|
||||
|
||||
Sound_Buffer(std::string resname, float volume, float mindist, float maxdist)
|
||||
: mResourceName(resname), mVolume(volume), mMinDist(mindist), mMaxDist(maxdist), mHandle(0)
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace MWSound
|
|||
class SoundManager;
|
||||
struct Sound_Decoder;
|
||||
class Sound;
|
||||
class Sound_Loudness;
|
||||
|
||||
// An opaque handle for the implementation's sound buffers.
|
||||
typedef void *Sound_Handle;
|
||||
|
@ -25,7 +26,7 @@ namespace MWSound
|
|||
virtual void init(const std::string &devname="") = 0;
|
||||
virtual void deinit() = 0;
|
||||
|
||||
virtual Sound_Handle loadSound(const std::string &fname) = 0;
|
||||
virtual Sound_Handle loadSound(const std::string &fname, Sound_Loudness *loudness=0) = 0;
|
||||
virtual void unloadSound(Sound_Handle data) = 0;
|
||||
|
||||
/// @param offset Value from [0,1] meaning from which fraction the sound the playback starts.
|
||||
|
|
|
@ -189,10 +189,10 @@ namespace MWSound
|
|||
voicefile, Sound_Buffer("sound/"+voicefile, 1.0f, minDistance, maxDistance)
|
||||
)).first;
|
||||
mVFS->normalizeFilename(sfxiter->second.mResourceName);
|
||||
sfxiter->second.mHandle = mOutput->loadSound(sfxiter->second.mResourceName);
|
||||
sfxiter->second.mHandle = mOutput->loadSound(sfxiter->second.mResourceName, &sfxiter->second.mLoudness);
|
||||
}
|
||||
else if(!sfxiter->second.mHandle)
|
||||
sfxiter->second.mHandle = mOutput->loadSound(sfxiter->second.mResourceName);
|
||||
sfxiter->second.mHandle = mOutput->loadSound(sfxiter->second.mResourceName, &sfxiter->second.mLoudness);
|
||||
|
||||
return &sfxiter->second;
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ namespace MWSound
|
|||
if (snditer == mActiveSounds.end())
|
||||
return 0.f;
|
||||
|
||||
return snditer->first->getCurrentLoudness();
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void SoundManager::say(const std::string& filename)
|
||||
|
|
Loading…
Reference in a new issue