Load sound loudness and store it with the Sound_Buffer

Still not used for say yet, though
openmw-38
Chris Robinson 9 years ago
parent f4c22ec49e
commit 495e138907

@ -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)
{
int samplesPerSegment = static_cast<int>(sampleRate / valuesPerSecond);
int numSamples = bytesToFrames(data.size(), chans, type);
int advance = framesToBytes(1, chans, type);
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);
out.reserve(numSamples/samplesPerSegment);
mSamplesPerSec = valuesPerSecond;
mSamples.clear();
mSamples.reserve(numSamples/samplesPerSegment);
int segment=0;
int sample=0;
while (segment < 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…
Cancel
Save