Permalink
Browse files

Merge pull request #4502 from fritsch/pa-revisit-volume2

AESink: Revisit volume part 2
  • Loading branch information...
2 parents 42f30a2 + 679639c commit 86f4e313531fcf9149ea3e0d4503a5c0fe4ea303 @jmarshallnz jmarshallnz committed Apr 4, 2014
View
@@ -5352,16 +5352,7 @@ void CApplication::SetHardwareVolume(float hardwareVolume)
hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
m_volumeLevel = hardwareVolume;
- float value = 0.0f;
- if (hardwareVolume > VOLUME_MINIMUM)
- {
- float dB = CAEUtil::PercentToGain(hardwareVolume);
- value = CAEUtil::GainToScale(dB);
- }
- if (value >= 0.99f)
- value = 1.0f;
-
- CAEFactory::SetVolume(value);
+ CAEFactory::SetVolume(hardwareVolume);
}
float CApplication::GetVolume(bool percentage /* = true */) const
@@ -149,6 +149,7 @@ CActiveAE::CActiveAE() :
m_vizBuffers = NULL;
m_vizBuffersInput = NULL;
m_volume = 1.0;
+ m_volumeScaled = 1.0;
m_aeVolume = 1.0;
m_muted = false;
m_aeMuted = false;
@@ -225,6 +226,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
return;
case CActiveAEControlProtocol::VOLUME:
m_volume = *(float*)msg->data;
+ m_volumeScaled = CAEUtil::GainToScale(CAEUtil::PercentToGain(m_volume));
@fritsch
fritsch Apr 5, 2014 Team Kodi member

We need to check if m_volume > 0.0
and only then do something here.

@fritsch
fritsch Apr 5, 2014 Team Kodi member

Explanation:

PercentToGain(0.0) = -60;

GainToScale(-60) = pow(10.0f, -3) = 1.0 / (10^3) = 1.0 / 1000 = 0.001 != 0.0f
if (m_sinkHasVolume)
m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::VOLUME, &m_volume, sizeof(float));
return;
@@ -2068,11 +2070,11 @@ void CActiveAE::MixSounds(CSoundPacket &dstSample)
void CActiveAE::Deamplify(CSoundPacket &dstSample)
{
- if (m_volume < 1.0 || m_muted)
+ if (m_volumeScaled < 1.0 || m_muted)
{
float *buffer;
int nb_floats = dstSample.nb_samples * dstSample.config.channels / dstSample.planes;
- float volume = m_muted ? 0.0f : m_volume;
+ float volume = m_muted ? 0.0f : m_volumeScaled;
for(int j=0; j<dstSample.planes; j++)
{
@@ -337,7 +337,8 @@ class CActiveAE : public IAE, private CThread
std::list<SoundState> m_sounds_playing;
std::vector<CActiveAESound*> m_sounds;
- float m_volume;
+ float m_volume; // volume on a 0..1 scale corresponding to a proportion along the dB scale
+ float m_volumeScaled; // multiplier to scale samples in order to achieve the volume specified in m_volume
bool m_muted;
bool m_sinkHasVolume;
@@ -217,9 +217,7 @@ void CAESinkAUDIOTRACK::SetVolume(float scale)
if (!m_at_jni)
return;
- // Android uses fixed steps, reverse scale back to percent
- float gain = CAEUtil::ScaleToGain(scale);
- m_volume = CAEUtil::GainToPercent(gain);
+ m_volume = scale;
if (!m_passthrough)
{
CXBMCApp::SetSystemVolume(xbmc_jnienv(), m_volume);
@@ -724,7 +724,6 @@ bool CAESinkDARWINIOS::Initialize(AEAudioFormat &format, std::string &device)
format.m_sampleRate = m_audioSink->getRealisedSampleRate();
m_format = format;
- m_volume_changed = false;
m_audioSink->play(false);
return true;
@@ -799,14 +798,6 @@ bool CAESinkDARWINIOS::HasVolume()
return false;
}
-void CAESinkDARWINIOS::SetVolume(float scale)
-{
- // CoreAudio uses fixed steps, reverse scale back to percent
- float gain = CAEUtil::ScaleToGain(scale);
- m_volume = CAEUtil::GainToPercent(gain);
- m_volume_changed = true;
-}
-
void CAESinkDARWINIOS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
{
m_devices.clear();
@@ -51,18 +51,15 @@ class CAESinkDARWINIOS : public IAESink
virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio, bool blocking = false);
virtual void Drain ();
virtual bool HasVolume ();
- virtual void SetVolume (float scale);
static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
private:
static AEDeviceInfoList m_devices;
CAEDeviceInfo m_info;
AEAudioFormat m_format;
- double m_volume;
- bool m_volume_changed;
CAAudioUnitSink *m_audioSink;
#if DO_440HZ_TONE_TEST
SineWaveGenerator m_SineWaveGenerator;
#endif
-};
+};
@@ -596,7 +596,7 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
m_BytesPerSecond = pa_bytes_per_second(&spec);
unsigned int frameSize = pa_frame_size(&spec);
- m_Stream = pa_stream_new_extended(m_Context, "audio stream", info, 1, NULL);
+ m_Stream = pa_stream_new_extended(m_Context, "xbmc audio stream", info, 1, NULL);
pa_format_info_free(info[0]);
if (m_Stream == NULL)
@@ -654,26 +654,24 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
//update local volume if we are in non passthrough mode
if (!m_passthrough)
{
- unsigned int devidx = pa_stream_get_index(m_Stream);
+ unsigned int sink_input_idx = pa_stream_get_index(m_Stream);
SinkInputInfoStruct sii;
sii.mainloop = m_MainLoop;
- bool success = WaitForOperation(pa_context_get_sink_input_info(m_Context, devidx, SinkInputInfoCallback, &sii), m_MainLoop, "Get Sink Input Info");
+ bool success = WaitForOperation(pa_context_get_sink_input_info(m_Context, sink_input_idx, SinkInputInfoCallback, &sii), m_MainLoop, "Get Sink Input Info");
if(success && sii.is_valid)
{
- // we don't have per channel values so average them
+ // we don't have per channel values so use avg of them
pa_volume_t p_vol = pa_cvolume_avg(&sii.volume);
// store it internally
m_Volume = sii.volume;
- float sValue = std::min(p_vol / (float) PA_VOLUME_NORM, 1.0f);
+ float sValue = (float) pa_sw_volume_to_linear(p_vol);
CLog::Log(LOGDEBUG, "Restored Stream value to %f", sValue);
- sValue = std::min(sValue, 1.0f);
g_application.SetVolume(sValue, false);
if (sii.mute && sValue > 0)
{
CLog::Log(LOGDEBUG, "PulseAudio: Stream is muted - perhaps was a user wish - if volume is changed we unmute");
}
- }
-
+ }
}
const pa_buffer_attr *a;
@@ -814,20 +812,23 @@ void CAESinkPULSE::SetVolume(float volume)
{
if (m_IsAllocated && !m_passthrough)
{
+ // clamp possibly too large / low values
+ float per_cent_volume = std::max(0.0f, std::min(volume, 1.0f));
+
pa_threaded_mainloop_lock(m_MainLoop);
bool external_change = false;
- //check if internal volume does not match sink volume
- unsigned int devidx = pa_stream_get_index(m_Stream);
+ //check if internal volume and sink input volume do not match
+ unsigned int sink_input_idx = pa_stream_get_index(m_Stream);
SinkInputInfoStruct sii;
sii.mainloop = m_MainLoop;
- bool success = WaitForOperation(pa_context_get_sink_input_info(m_Context, devidx, SinkInputInfoCallback, &sii), m_MainLoop, "Get Sink Input Info");
+ bool success = WaitForOperation(pa_context_get_sink_input_info(m_Context, sink_input_idx, SinkInputInfoCallback, &sii), m_MainLoop, "Get Sink Input Info");
float sValue = 0.0f;
if(success && sii.is_valid)
{
- // we don't have per channel values so average them
+ // we don't have per channel values so use avg of them
pa_volume_t n_vol = pa_cvolume_avg(&sii.volume);
pa_volume_t o_vol = pa_cvolume_avg(&m_Volume);
- sValue = std::min(n_vol / (float) PA_VOLUME_NORM, 1.0f);
+ sValue = (float) pa_sw_volume_to_linear(n_vol);
if (n_vol != o_vol)
{
external_change = true;
@@ -836,24 +837,28 @@ void CAESinkPULSE::SetVolume(float volume)
CLog::Log(LOGDEBUG, "Restored Volume cause of external change to value to %f", sValue);
g_application.SetVolume(sValue, false);
}
+ // unmute if we should not be muted
+ if (sii.mute && sValue > 0)
+ {
+ pa_operation *op = pa_context_set_sink_input_mute(m_Context, sii.index, 0, NULL, NULL);
+ if (op == NULL)
+ CLog::Log(LOGERROR, "PulseAudio: Failed to unmute the stream");
+ else
+ pa_operation_unref(op);
+ }
}
- // unmute if we should not be muted
- if (sii.mute && sValue > 0)
+ else // we don't know stream volume so don't change anything
{
- pa_operation *op = pa_context_set_sink_input_mute(m_Context, sii.index, 0, NULL, NULL);
- if (op == NULL)
- CLog::Log(LOGERROR, "PulseAudio: Failed to unmute the stream");
- else
- pa_operation_unref(op);
+ external_change = true;
}
if (!external_change)
{
- pa_volume_t pavolume = pa_sw_volume_from_linear(volume);
+ pa_volume_t pavolume = pa_sw_volume_from_linear(per_cent_volume);
if ( pavolume <= 0 )
pa_cvolume_mute(&m_Volume, m_Channels);
else
pa_cvolume_set(&m_Volume, m_Channels, pavolume);
- pa_operation *op = pa_context_set_sink_input_volume(m_Context, devidx, &m_Volume, NULL, NULL);
+ pa_operation *op = pa_context_set_sink_input_volume(m_Context, sink_input_idx, &m_Volume, NULL, NULL);
if (op == NULL)
CLog::Log(LOGERROR, "PulseAudio: Failed to set volume");
else
@@ -108,7 +108,11 @@ class CAEUtil
*/
static inline const float GainToScale(const float dB)
{
- return pow(10.0f, dB/20);
+ float val = pow(10.0f, dB/20);
+ if (val >= 0.99f)
+ val = 1.0f;
+
+ return val;
}
/*! \brief convert a scale factor to dB gain for audio manipulation

0 comments on commit 86f4e31

Please sign in to comment.