Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
5489327a
Commit
5489327a
authored
Oct 18, 2019
by
Jean-Baptiste Mardelle
Browse files
Logarithmic scale for audio mixer volume
Related to
#357
parent
05d30edf
Pipeline
#9135
passed with stage
in 16 minutes and 41 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/audiomixer/audiolevelwidget.cpp
View file @
5489327a
...
...
@@ -32,16 +32,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QPainter>
#include <QFontDatabase>
const
double
log_factor
=
1.0
/
log10
(
1.0
/
127
);
static
inline
double
levelToDB
(
double
level
)
{
if
(
level
<=
0
)
{
return
-
100
;
}
return
100
*
(
1.0
-
log10
(
level
)
*
log_factor
);
}
AudioLevelWidget
::
AudioLevelWidget
(
int
width
,
QWidget
*
parent
)
:
QWidget
(
parent
)
,
audioChannels
(
2
)
...
...
@@ -163,7 +153,7 @@ void AudioLevelWidget::drawBackground(int channels)
}
// cppcheck-suppress unusedFunction
void
AudioLevelWidget
::
setAudioValues
(
const
QVector
<
int
>
&
values
)
void
AudioLevelWidget
::
setAudioValues
(
const
QVector
<
double
>
&
values
)
{
m_values
=
values
;
if
(
m_peaks
.
size
()
!=
m_values
.
size
())
{
...
...
@@ -213,7 +203,8 @@ void AudioLevelWidget::paintEvent(QPaintEvent *pe)
if
(
m_values
.
at
(
i
)
>=
100
)
{
continue
;
}
int
val
=
(
50
+
m_values
.
at
(
i
))
/
150.0
*
rect
.
height
();
//int val = (50 + m_values.at(i)) / 150.0 * rect.height();
int
val
=
m_values
.
at
(
i
)
*
rect
.
height
();
p
.
fillRect
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
)
+
1
,
0
,
m_channelFillWidth
,
height
()
-
val
,
palette
().
dark
());
p
.
fillRect
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
)
+
1
,
height
()
-
(
50
+
m_peaks
.
at
(
i
))
/
150.0
*
rect
.
height
(),
m_channelFillWidth
,
1
,
palette
().
text
());
}
...
...
src/audiomixer/audiolevelwidget.hpp
View file @
5489327a
...
...
@@ -50,15 +50,15 @@ private:
int
m_width
;
int
m_offset
;
QPixmap
m_pixmap
;
QVector
<
int
>
m_peaks
;
QVector
<
int
>
m_values
;
QVector
<
double
>
m_peaks
;
QVector
<
double
>
m_values
;
int
m_channelWidth
;
int
m_channelDistance
;
int
m_channelFillWidth
;
void
drawBackground
(
int
channels
=
2
);
public
slots
:
void
setAudioValues
(
const
QVector
<
int
>
&
values
);
void
setAudioValues
(
const
QVector
<
double
>
&
values
);
};
#endif
src/audiomixer/mixerwidget.cpp
View file @
5489327a
...
...
@@ -39,18 +39,44 @@
#include <QSlider>
#include <QDial>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QLabel>
#include <QStyle>
#include <QFontDatabase>
const
double
log_factor
=
1.0
/
log10
(
1.0
/
127
);
static
inline
double
IEC_Scale
(
double
dB
)
{
dB
=
log10
(
dB
)
*
20.0
;
double
fScale
=
1.0
f
;
if
(
dB
<
-
70.0
f
)
fScale
=
0.0
f
;
else
if
(
dB
<
-
60.0
f
)
fScale
=
(
dB
+
70.0
f
)
*
0.0025
f
;
else
if
(
dB
<
-
50.0
f
)
fScale
=
(
dB
+
60.0
f
)
*
0.005
f
+
0.025
f
;
else
if
(
dB
<
-
40.0
)
fScale
=
(
dB
+
50.0
f
)
*
0.0075
f
+
0.075
f
;
else
if
(
dB
<
-
30.0
f
)
fScale
=
(
dB
+
40.0
f
)
*
0.015
f
+
0.15
f
;
else
if
(
dB
<
-
20.0
f
)
fScale
=
(
dB
+
30.0
f
)
*
0.02
f
+
0.3
f
;
else
if
(
dB
<
-
0.001
f
||
dB
>
0.001
f
)
/* if (dB < 0.0f) */
fScale
=
(
dB
+
20.0
f
)
*
0.025
f
+
0.5
f
;
static
inline
int
levelToDB
(
double
level
)
return
fScale
;
}
static
inline
int
fromDB
(
double
level
)
{
if
(
level
<=
0
)
{
return
-
100
;
int
value
=
80
;
if
(
level
>
0.
)
{
// increase volume
value
=
100
-
((
pow
(
10
,
1.
-
level
/
24
)
-
1
)
/
.47
);
}
else
if
(
level
<
0.
)
{
value
=
(
10
-
pow
(
10
,
1.
-
level
/-
50
))
/
-
0.11395
+
79
;
}
return
100
*
(
1.0
-
log10
(
level
)
*
log_factor
)
;
return
value
;
}
void
MixerWidget
::
property_changed
(
mlt_service
,
MixerWidget
*
widget
,
char
*
name
)
...
...
@@ -59,10 +85,10 @@ void MixerWidget::property_changed( mlt_service , MixerWidget *widget, char *nam
mlt_properties
filter_props
=
MLT_FILTER_PROPERTIES
(
widget
->
m_monitorFilter
->
get_filter
());
int
pos
=
mlt_properties_get_int
(
filter_props
,
"_position"
);
if
(
!
widget
->
m_levels
.
contains
(
pos
))
{
widget
->
m_levels
[
pos
]
=
{
levelToDB
(
mlt_properties_get_double
(
filter_props
,
"_audio_level.0"
)),
levelToDB
(
mlt_properties_get_double
(
filter_props
,
"_audio_level.1"
))};
widget
->
m_levels
[
pos
]
=
{
IEC_Scale
(
mlt_properties_get_double
(
filter_props
,
"_audio_level.0"
)),
IEC_Scale
(
mlt_properties_get_double
(
filter_props
,
"_audio_level.1"
))};
if
(
widget
->
m_levels
.
size
()
>
50
)
{
widget
->
m_levels
.
erase
(
widget
->
m_levels
.
begin
());
}
}
}
}
}
...
...
@@ -116,16 +142,16 @@ void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackTag)
// Build volume widget
m_volumeSlider
=
new
QSlider
(
Qt
::
Vertical
,
this
);
m_volumeSlider
->
setRange
(
-
10
0
,
6
0
);
m_volumeSlider
->
setValue
(
0
);
m_volumeSlider
->
setRange
(
0
,
10
0
);
m_volumeSlider
->
setValue
(
8
0
);
m_volumeSlider
->
setToolTip
(
i18n
(
"Volume"
));
m_volumeSpin
=
new
QSpinBox
(
this
);
m_volumeSpin
->
setRange
(
-
10
0
,
60
);
m_volumeSpin
=
new
Q
Double
SpinBox
(
this
);
m_volumeSpin
->
setRange
(
-
5
0
,
24
);
m_volumeSpin
->
setSuffix
(
i18n
(
"dB"
));
m_volumeSpin
->
setFrame
(
false
);
connect
(
m_volumeSpin
,
static_cast
<
void
(
QSpinBox
::*
)(
int
)
>
(
&
Q
SpinBox
::
valueChanged
),
[
&
](
int
val
)
{
m_volumeSlider
->
setValue
(
val
);
connect
(
m_volumeSpin
,
static_cast
<
void
(
Q
Double
SpinBox
::*
)(
double
)
>
(
&
QDouble
SpinBox
::
valueChanged
),
[
&
](
double
val
)
{
m_volumeSlider
->
setValue
(
fromDB
(
val
)
)
;
});
m_balanceDial
=
new
QDial
(
this
);
...
...
@@ -152,7 +178,7 @@ void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackTag)
m_levelFilter
=
fl
;
int
volume
=
m_levelFilter
->
get_int
(
"level"
);
m_volumeSpin
->
setValue
(
volume
);
m_volumeSlider
->
setValue
(
volume
);
m_volumeSlider
->
setValue
(
fromDB
(
volume
)
)
;
}
else
if
(
filterService
==
QLatin1String
(
"panner"
))
{
m_balanceFilter
=
fl
;
int
val
=
m_balanceFilter
->
get_double
(
"start"
)
*
100
-
50
;
...
...
@@ -247,13 +273,21 @@ void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackTag)
connect
(
m_volumeSlider
,
&
QSlider
::
valueChanged
,
[
&
](
int
value
)
{
QSignalBlocker
bk
(
m_volumeSpin
);
m_volumeSpin
->
setValue
(
value
);
if
(
m_recording
)
{
m_volumeSpin
->
setValue
(
value
);
KdenliveSettings
::
setAudiocapturevolume
(
value
);
//TODO update capture volume
}
else
if
(
m_levelFilter
!=
nullptr
)
{
m_levelFilter
->
set
(
"level"
,
value
);
m_levelFilter
->
set
(
"disable"
,
value
==
0
?
1
:
0
);
double
dbValue
=
0
;
if
(
value
>
80
)
{
// increase volume
dbValue
=
24
*
(
1
-
log10
((
100
-
value
)
*
0.47
+
1
));
}
else
if
(
value
<
80
)
{
dbValue
=
-
50
*
(
1
-
log10
(
10
-
(
value
-
79
)
*
(
-
0.11395
)));
}
m_volumeSpin
->
setValue
(
dbValue
);
m_levelFilter
->
set
(
"level"
,
dbValue
);
m_levelFilter
->
set
(
"disable"
,
value
==
80
?
1
:
0
);
m_levels
.
clear
();
m_manager
->
purgeCache
();
}
...
...
@@ -305,7 +339,7 @@ void MixerWidget::mousePressEvent(QMouseEvent *event)
if
(
child
==
m_balanceDial
)
{
m_balanceSpin
->
setValue
(
0
);
}
else
if
(
child
==
m_volumeSlider
)
{
m_volumeSlider
->
setValue
(
0
);
m_volumeSlider
->
setValue
(
8
0
);
}
}
else
{
QWidget
::
mousePressEvent
(
event
);
...
...
@@ -343,11 +377,6 @@ void MixerWidget::updateLabel()
}
}
void
MixerWidget
::
setAudioLevel
(
const
QVector
<
int
>
vol
)
{
m_audioMeterWidget
->
setAudioValues
(
vol
);
}
void
MixerWidget
::
updateAudioLevel
(
int
pos
)
{
QMutexLocker
lk
(
&
m_storeMutex
);
...
...
@@ -387,10 +416,10 @@ void MixerWidget::gotRecLevels(QVector<qreal>levels)
m_audioMeterWidget
->
setAudioValues
({
-
100
,
-
100
});
break
;
case
1
:
m_audioMeterWidget
->
setAudioValues
({
levelToDB
(
levels
[
0
]),
-
100
});
m_audioMeterWidget
->
setAudioValues
({
IEC_Scale
(
levels
[
0
]),
-
100
});
break
;
default:
m_audioMeterWidget
->
setAudioValues
({
levelToDB
(
levels
[
0
]),
levelToDB
(
levels
[
1
])});
m_audioMeterWidget
->
setAudioValues
({
IEC_Scale
(
levels
[
0
]),
IEC_Scale
(
levels
[
1
])});
break
;
}
}
...
...
@@ -405,7 +434,6 @@ void MixerWidget::setRecordState(bool recording)
connect
(
pCore
->
getAudioDevice
(),
&
MediaCapture
::
audioLevels
,
this
,
&
MixerWidget
::
gotRecLevels
);
m_balanceDial
->
setEnabled
(
false
);
m_balanceSpin
->
setEnabled
(
false
);
m_volumeSlider
->
setRange
(
0
,
100
);
m_volumeSpin
->
setRange
(
0
,
100
);
m_volumeSpin
->
setSuffix
(
QStringLiteral
(
"%"
));
m_volumeSpin
->
setValue
(
KdenliveSettings
::
audiocapturevolume
());
...
...
@@ -415,11 +443,10 @@ void MixerWidget::setRecordState(bool recording)
m_balanceSpin
->
setEnabled
(
true
);
int
level
=
m_levelFilter
->
get_int
(
"level"
);
disconnect
(
pCore
->
getAudioDevice
(),
&
MediaCapture
::
audioLevels
,
this
,
&
MixerWidget
::
gotRecLevels
);
m_volumeSlider
->
setRange
(
-
100
,
60
);
m_volumeSpin
->
setRange
(
-
100
,
60
);
m_volumeSpin
->
setSuffix
(
i18n
(
"dB"
));
m_volumeSpin
->
setValue
(
level
);
m_volumeSlider
->
setValue
(
level
);
m_volumeSlider
->
setValue
(
fromDB
(
level
)
)
;
}
updateLabel
();
}
src/audiomixer/mixerwidget.hpp
View file @
5489327a
...
...
@@ -35,6 +35,7 @@ class AudioLevelWidget;
class
QSlider
;
class
QDial
;
class
QSpinBox
;
class
QDoubleSpinBox
;
class
QLabel
;
class
QToolButton
;
class
MixerManager
;
...
...
@@ -69,7 +70,6 @@ protected:
public
slots
:
void
updateAudioLevel
(
int
pos
);
void
setAudioLevel
(
const
QVector
<
int
>
vol
);
void
setRecordState
(
bool
recording
);
private
slots
:
...
...
@@ -81,11 +81,11 @@ protected:
std
::
shared_ptr
<
Mlt
::
Filter
>
m_levelFilter
;
std
::
shared_ptr
<
Mlt
::
Filter
>
m_monitorFilter
;
std
::
shared_ptr
<
Mlt
::
Filter
>
m_balanceFilter
;
QMap
<
int
,
QPair
<
int
,
int
>>
m_levels
;
QMap
<
int
,
QPair
<
double
,
double
>>
m_levels
;
KDualAction
*
m_muteAction
;
QSpinBox
*
m_balanceSpin
;
QDial
*
m_balanceDial
;
QSpinBox
*
m_volumeSpin
;
Q
Double
SpinBox
*
m_volumeSpin
;
private:
std
::
shared_ptr
<
AudioLevelWidget
>
m_audioMeterWidget
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment