diff --git a/apps/openmw/mwsound/loudness.cpp b/apps/openmw/mwsound/loudness.cpp index 12fe8ae4d..21f399ddc 100644 --- a/apps/openmw/mwsound/loudness.cpp +++ b/apps/openmw/mwsound/loudness.cpp @@ -8,49 +8,61 @@ namespace MWSound { - void analyzeLoudness(const std::vector &data, int sampleRate, ChannelConfig chans, - SampleType type, std::vector &out, float valuesPerSecond) - { - int samplesPerSegment = static_cast(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(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(&data[sample*advance]); - value /= float(std::numeric_limits::max()); - } - else if (type == SampleType_Float32) - { - value = *reinterpret_cast(&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(&data[sample*advance]); + value /= float(std::numeric_limits::max()); + } + else if (type == SampleType_Float32) + { + value = *reinterpret_cast(&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(sec * mSamplesPerSec); + index = std::max(0, std::min(index, mSamples.size()-1)); + return mSamples[index]; +} } diff --git a/apps/openmw/mwsound/loudness.hpp b/apps/openmw/mwsound/loudness.hpp index df727bd0b..a0af2b558 100644 --- a/apps/openmw/mwsound/loudness.hpp +++ b/apps/openmw/mwsound/loudness.hpp @@ -1,20 +1,38 @@ +#ifndef GAME_SOUND_LOUDNESS_H +#define GAME_SOUND_LOUDNESS_H + +#include + #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& data, int sampleRate, ChannelConfig chans, SampleType type, - std::vector& out, float valuesPerSecond); +class Sound_Loudness { + // Loudness sample info + float mSamplesPerSec; + std::vector 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& data, int sampleRate, + ChannelConfig chans, SampleType type, + float valuesPerSecond); + + float getLoudnessAtTime(float sec) const; +}; } + +#endif /* GAME_SOUND_LOUDNESS_H */ diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 381c5ba18..82d56ffa0 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -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(loudnessFPS)); + if(loudness != 0) + loudness->analyzeLoudness(data, srate, chans, type, static_cast(loudnessFPS)); ALuint buf = 0; try { diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 8af46a478..b4c788faa 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -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. diff --git a/apps/openmw/mwsound/sound.cpp b/apps/openmw/mwsound/sound.cpp deleted file mode 100644 index 8b6bfda82..000000000 --- a/apps/openmw/mwsound/sound.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "sound.hpp" - -namespace MWSound -{ - - float Sound::getCurrentLoudness() - { - if (mLoudnessVector.empty()) - return 0.f; - int index = static_cast(getTimeOffset() * mLoudnessFPS); - - index = std::max(0, std::min(index, int(mLoudnessVector.size()-1))); - - return mLoudnessVector[index]; - } - - void Sound::setLoudnessVector(const std::vector &loudnessVector, float loudnessFPS) - { - mLoudnessVector = loudnessVector; - mLoudnessFPS = loudnessFPS; - } - -} diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 96f59cea0..53b258a6a 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -22,9 +22,6 @@ namespace MWSound int mFlags; float mFadeOutTime; - std::vector 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& 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() { } diff --git a/apps/openmw/mwsound/sound_buffer.hpp b/apps/openmw/mwsound/sound_buffer.hpp index 37f49e518..8ee7ae342 100644 --- a/apps/openmw/mwsound/sound_buffer.hpp +++ b/apps/openmw/mwsound/sound_buffer.hpp @@ -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) diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index cbda19d59..5c437a699 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -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. diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 6e95c1116..d48c614dd 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -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)