Re-added volume amplification for softae and coreae, xcode build and windows build will need updating.
m_vizRemapBuffer = (uint8_t *)_aligned_malloc(m_vizRemapBufferSize,16);
m_isRaw = COREAUDIO_IS_RAW(dataFormat);
+ m_limiter.SetSamplerate(AE.GetSampleRate());
}
CCoreAudioAEStream::~CCoreAudioAEStream()
{
float *floatBuffer = (float *)buffer;
unsigned int samples = readsize / m_OutputBytesPerSample;
+ unsigned int frames = samples / m_chLayoutCountOutput;
// we have a frame, if we have a viz we need to hand the data to it.
// Keep in mind that our buffer is already in output format.
if (m_OutputFormat.m_dataFormat == AE_FMT_FLOAT)
{
// TODO : Why the hell is vizdata limited ?
- unsigned int frames = samples / m_chLayoutCountOutput;
unsigned int samplesClamped = (samples > 512) ? 512 : samples;
if (samplesClamped)
{
#endif
CAEUtil::ClampArray(floatBuffer, samples);
}
+ // apply volume amplification by using the sogt limiter
+ // TODO - maybe reinvent the coreaudio compressor for this after frodo
+ else if (GetAmplification() != 1.0f)
+ {
+ for(unsigned int i = 0; i < frames; i++)
+ {
+ int frameIdx = i*m_chLayoutCountOutput;
+ float amplification = RunLimiter(&floatBuffer[frameIdx], m_chLayoutCountOutput);
+ float *frameStart = &floatBuffer[frameIdx];
+#ifdef __SSE___
+ CAEUtil::SSEMulArray(frameStart, amplification, m_chLayoutCountOutput);
+#else
+ for(unsigned int n = 0; n < m_chLayoutCountOutput; n++)
+ frameStart[n] *= amplification;
+#endif
+
+ }
+ }
}
return readsize;
#include "cores/AudioEngine/Interfaces/AEStream.h"
#include "cores/AudioEngine/Utils/AEConvert.h"
#include "cores/AudioEngine/Utils/AERemap.h"
+#include "Utils/AELimiter.h"
#if defined(TARGET_DARWIN_IOS)
# include "CoreAudioAEHALIOS.h"
virtual float GetVolume();
virtual float GetReplayGain();
+ virtual float GetAmplification() { return m_limiter.GetAmplification(); }
virtual void SetVolume(float volume);
virtual void SetReplayGain(float factor);
+ virtual void SetAmplification(float amplify){ m_limiter.SetAmplification(amplify); }
+
+ virtual float RunLimiter(float* frame, int channels) { return m_limiter.Run(frame, channels); }
virtual const unsigned int GetChannelCount() const;
virtual const unsigned int GetSampleRate() const;
CAERemap m_remap; /* the remapper */
float m_volume; /* the volume level */
float m_rgain; /* replay gain level */
+ CAELimiter m_limiter; /* volume amplification/limiter*/
IAEStream *m_slave; /* slave aestream */
CAEConvert::AEConvertToFn m_convertFn;
virtual float GetVolume ();
virtual float GetReplayGain();
+ virtual float GetAmplification() { return 1.0f; }
virtual void SetVolume (float volume);
virtual void SetReplayGain(float factor);
+ virtual void SetAmplification(float amplify){}
void SetMute(const bool muted);
virtual const unsigned int GetFrameSize () const;
if (!frame)
continue;
- float volume = stream->GetVolume() * stream->GetReplayGain();
+ float volume = stream->GetVolume() * stream->GetReplayGain() * stream->RunLimiter(frame, channelCount);
#ifdef __SSE__
if (channelCount > 1)
CAEUtil::SSEMulAddArray(dst, frame, volume, channelCount);
m_ssrcData.end_of_input = 0;
}
+ m_limiter.SetSamplerate(AE.GetSampleRate());
+
m_chLayoutCount = m_format.m_channelLayout.Count();
m_valid = true;
}
#include "Utils/AEConvert.h"
#include "Utils/AERemap.h"
#include "Utils/AEBuffer.h"
+#include "Utils/AELimiter.h"
class IAEPostProc;
class CSoftAEStream : public IAEStream
virtual float GetVolume () { return m_volume; }
virtual float GetReplayGain () { return m_rgain ; }
+ virtual float GetAmplification() { return m_limiter.GetAmplification(); }
virtual void SetVolume (float volume) { m_volume = std::max( 0.0f, std::min(1.0f, volume)); }
virtual void SetReplayGain (float factor) { m_rgain = std::max( 0.0f, factor); }
+ virtual void SetAmplification(float amplify){ m_limiter.SetAmplification(amplify); }
+
+ virtual float RunLimiter(float* frame, int channels) { return m_limiter.Run(frame, channels); }
virtual const unsigned int GetFrameSize () const { return m_format.m_frameSize; }
virtual const unsigned int GetChannelCount() const { return m_initChannelLayout.Count(); }
bool m_paused;
bool m_autoStart;
bool m_draining;
+ CAELimiter m_limiter;
/* vizualization internals */
CAERemap m_vizRemap;
virtual void SetReplayGain(float factor) = 0;
/**
+ * Gets the stream's volume amplification in linear units.
+ * @return The volume amplification factor between 1.0 and 1000.0
+ */
+ virtual float GetAmplification() = 0;
+
+ /**
+ * Sets the stream's volume amplification in linear units.
+ * @param The volume amplification factor between 1.0 and 1000.0
+ */
+ virtual void SetAmplification(float amplify) = 0;
+
+ /**
+ * Runs the limiter over one frame
+ * @param pointer to the frame
+ * @param number of channels
+ * @return amplification factor that should be applied
+ */
+ virtual float RunLimiter(float* frame, int channels) = 0;
+
+ /**
* Returns the size of one audio frame in bytes (channelCount * resolution)
* @return The size in bytes of one frame
*/
SRCS += Utils/AEWAVLoader.cpp
SRCS += Utils/AEELDParser.cpp
SRCS += Utils/AEDeviceInfo.cpp
+SRCS += Utils/AELimiter.cpp
SRCS += Encoders/AEEncoderFFmpeg.cpp
--- /dev/null
+/*
+ * Copyright (C) 2010-2012 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "system.h"
+#include "AELimiter.h"
+#include "settings/AdvancedSettings.h"
+#include "utils/MathUtils.h"
+#include <algorithm>
+#include <math.h>
+
+CAELimiter::CAELimiter()
+{
+ m_amplify = 1.0f;
+ m_attenuation = 1.0f;
+ m_samplerate = 48000.0f;
+ m_holdcounter = 0;
+ m_increase = 0.0f;
+}
+
+float CAELimiter::Run(float* frame, int channels)
+{
+ float* end = frame + channels;
+ float highest = 0.0f;
+ while (frame != end)
+ highest = std::max(highest, fabsf(*(frame++)));
+
+ float sample = highest * m_amplify;
+ if (sample * m_attenuation > 1.0f)
+ {
+ m_attenuation = 1.0f / sample;
+ m_holdcounter = MathUtils::round_int(m_samplerate * g_advancedSettings.m_limiterHold);
+ m_increase = powf(std::min(sample, 10000.0f), 1.0f / (g_advancedSettings.m_limiterRelease * m_samplerate));
+ }
+
+ float attenuation = m_attenuation;
+
+ if (m_holdcounter > 0)
+ {
+ m_holdcounter--;
+ }
+ else
+ {
+ if (m_increase > 0.0f)
+ {
+ m_attenuation *= m_increase;
+ if (m_attenuation > 1.0f)
+ {
+ m_increase = 0.0f;
+ m_attenuation = 1.0f;
+ }
+ }
+ }
+
+ return attenuation * m_amplify;
+}
+
--- /dev/null
+#pragma once
+/*
+ * Copyright (C) 2010-2012 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <algorithm>
+
+class CAELimiter
+{
+ private:
+ float m_amplify;
+ float m_attenuation;
+ float m_samplerate;
+ int m_holdcounter;
+ float m_increase;
+
+ public:
+ CAELimiter();
+
+ void SetAmplification(float amplify)
+ {
+ m_amplify = std::max(std::min(amplify, 1000.0f), 1.0f);
+ }
+
+ float GetAmplification()
+ {
+ return m_amplify;
+ }
+
+ void SetSamplerate(int samplerate)
+ {
+ m_samplerate = samplerate;
+ }
+
+ float Run(float* frame, int channels);
+};
void CDVDAudio::SetDynamicRangeCompression(long drc)
{
-
+ CSingleLock lock (m_critSection);
+ if (m_pAudioStream)
+ m_pAudioStream->SetAmplification(powf(10.0f, (float)drc / 2000.0f));
}
float CDVDAudio::GetCurrentAttenuation()