Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpenBoard
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lifo
Nicolas Ollinger
OpenBoard
Commits
1e731be1
Commit
1e731be1
authored
May 09, 2016
by
Craig Watson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added audio level calculation for the VU meter
parent
518b7d26
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
84 additions
and
4 deletions
+84
-4
UBMicrophoneInput.cpp
src/podcast/ffmpeg/UBMicrophoneInput.cpp
+81
-4
UBMicrophoneInput.h
src/podcast/ffmpeg/UBMicrophoneInput.h
+3
-0
No files found.
src/podcast/ffmpeg/UBMicrophoneInput.cpp
View file @
1e731be1
...
@@ -50,7 +50,6 @@ int UBMicrophoneInput::sampleFormat()
...
@@ -50,7 +50,6 @@ int UBMicrophoneInput::sampleFormat()
int
sampleSize
=
mAudioFormat
.
sampleSize
();
int
sampleSize
=
mAudioFormat
.
sampleSize
();
QAudioFormat
::
SampleType
sampleType
=
mAudioFormat
.
sampleType
();
QAudioFormat
::
SampleType
sampleType
=
mAudioFormat
.
sampleType
();
// qDebug() << "Input sample format: " << sampleSize << "bits " << sampleType;
switch
(
sampleType
)
{
switch
(
sampleType
)
{
case
QAudioFormat
:
:
Unknown
:
case
QAudioFormat
:
:
Unknown
:
...
@@ -61,10 +60,12 @@ int UBMicrophoneInput::sampleFormat()
...
@@ -61,10 +60,12 @@ int UBMicrophoneInput::sampleFormat()
return
AV_SAMPLE_FMT_S16
;
return
AV_SAMPLE_FMT_S16
;
if
(
sampleSize
==
32
)
if
(
sampleSize
==
32
)
return
AV_SAMPLE_FMT_S32
;
return
AV_SAMPLE_FMT_S32
;
break
;
case
QAudioFormat
:
:
UnSignedInt
:
case
QAudioFormat
:
:
UnSignedInt
:
if
(
sampleSize
==
8
)
if
(
sampleSize
==
8
)
return
AV_SAMPLE_FMT_U8
;
return
AV_SAMPLE_FMT_U8
;
break
;
case
QAudioFormat
:
:
Float
:
case
QAudioFormat
:
:
Float
:
return
AV_SAMPLE_FMT_FLT
;
return
AV_SAMPLE_FMT_FLT
;
...
@@ -72,6 +73,8 @@ int UBMicrophoneInput::sampleFormat()
...
@@ -72,6 +73,8 @@ int UBMicrophoneInput::sampleFormat()
default
:
default
:
return
AV_SAMPLE_FMT_NONE
;
return
AV_SAMPLE_FMT_NONE
;
}
}
return
AV_SAMPLE_FMT_NONE
;
}
}
QString
UBMicrophoneInput
::
codec
()
QString
UBMicrophoneInput
::
codec
()
...
@@ -96,11 +99,14 @@ bool UBMicrophoneInput::init()
...
@@ -96,11 +99,14 @@ bool UBMicrophoneInput::init()
mAudioFormat
=
mAudioDeviceInfo
.
preferredFormat
();
mAudioFormat
=
mAudioDeviceInfo
.
preferredFormat
();
mAudioInput
=
new
QAudioInput
(
mAudioDeviceInfo
,
mAudioFormat
,
NULL
);
mAudioInput
=
new
QAudioInput
(
mAudioDeviceInfo
,
mAudioFormat
,
NULL
);
//mAudioInput->setNotifyInterval(100);
connect
(
mAudioInput
,
SIGNAL
(
stateChanged
(
QAudio
::
State
)),
connect
(
mAudioInput
,
SIGNAL
(
stateChanged
(
QAudio
::
State
)),
this
,
SLOT
(
onAudioInputStateChanged
(
QAudio
::
State
)));
this
,
SLOT
(
onAudioInputStateChanged
(
QAudio
::
State
)));
qDebug
()
<<
"Input sample format: "
<<
mAudioFormat
.
sampleSize
()
<<
"bit"
<<
mAudioFormat
.
sampleType
()
<<
"at"
<<
mAudioFormat
.
sampleRate
()
<<
"Hz"
<<
"; codec: "
<<
mAudioFormat
.
codec
();
return
true
;
return
true
;
}
}
...
@@ -159,12 +165,26 @@ void UBMicrophoneInput::setInputDevice(QString name)
...
@@ -159,12 +165,26 @@ void UBMicrophoneInput::setInputDevice(QString name)
}
}
static
qint64
uSecsElapsed
=
0
;
void
UBMicrophoneInput
::
onDataReady
()
void
UBMicrophoneInput
::
onDataReady
()
{
{
int
numBytes
=
mAudioInput
->
bytesReady
();
int
numBytes
=
mAudioInput
->
bytesReady
();
if
(
numBytes
>
0
)
uSecsElapsed
+=
mAudioFormat
.
durationForBytes
(
numBytes
);
emit
dataAvailable
(
mIODevice
->
read
(
numBytes
));
// Only emit data every 100ms
if
(
uSecsElapsed
>
100000
)
{
uSecsElapsed
=
0
;
QByteArray
data
=
mIODevice
->
read
(
numBytes
);
quint8
level
=
audioLevel
(
data
);
if
(
level
!=
mLastAudioLevel
)
{
mLastAudioLevel
=
level
;
emit
audioLevelChanged
(
level
);
}
emit
dataAvailable
(
data
);
}
}
}
void
UBMicrophoneInput
::
onAudioInputStateChanged
(
QAudio
::
State
state
)
void
UBMicrophoneInput
::
onAudioInputStateChanged
(
QAudio
::
State
state
)
...
@@ -184,6 +204,63 @@ void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state)
...
@@ -184,6 +204,63 @@ void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state)
}
}
}
}
/**
* @brief Calculate the current audio level of an array of samples and return it
* @param data An array of audio samples
* @return A value between 0 and 255
*
* Audio level is calculated as the RMS (root mean square) of the samples
* in the supplied array.
*/
quint8
UBMicrophoneInput
::
audioLevel
(
const
QByteArray
&
data
)
{
int
bytesPerSample
=
mAudioFormat
.
bytesPerFrame
()
/
mAudioFormat
.
channelCount
();
const
char
*
ptr
=
data
.
constData
();
double
sum
=
0
;
int
n_samples
=
data
.
size
()
/
bytesPerSample
;
for
(
int
i
(
0
);
i
<
(
data
.
size
()
-
bytesPerSample
);
i
+=
bytesPerSample
)
{
sum
+=
pow
(
sampleRelativeLevel
(
ptr
+
i
),
2
);
}
double
rms
=
sqrt
(
sum
/
n_samples
);
// The vu meter looks a bit better when the RMS isn't displayed linearly, as perceived sound
// level increases logarithmically. So here RMS can be substituted by something like
// rms^(1/e)
rms
=
pow
(
rms
,
1.
/
exp
(
1
));
return
UINT8_MAX
*
rms
;
}
/**
* @brief Calculate one sample's level relative to its maximum value
* @param sample One sample, in the format specified by mAudioFormat
* @return A double between 0 and 1.0, where 1.0 is the maximum value the sample can take.
*/
double
UBMicrophoneInput
::
sampleRelativeLevel
(
const
char
*
sample
)
{
QAudioFormat
::
SampleType
type
=
mAudioFormat
.
sampleType
();
int
sampleSize
=
mAudioFormat
.
sampleSize
();
if
(
sampleSize
==
16
&&
type
==
QAudioFormat
::
SignedInt
)
return
double
(
*
reinterpret_cast
<
const
int16_t
*>
(
sample
))
/
INT16_MAX
;
if
(
sampleSize
==
8
&&
type
==
QAudioFormat
::
SignedInt
)
return
double
(
*
reinterpret_cast
<
const
int8_t
*>
(
sample
))
/
INT8_MAX
;
if
(
sampleSize
==
16
&&
type
==
QAudioFormat
::
UnSignedInt
)
return
double
(
*
reinterpret_cast
<
const
uint16_t
*>
(
sample
))
/
UINT16_MAX
;
if
(
sampleSize
==
8
&&
type
==
QAudioFormat
::
UnSignedInt
)
return
double
(
*
reinterpret_cast
<
const
uint8_t
*>
(
sample
))
/
UINT8_MAX
;
if
(
type
==
QAudioFormat
::
Float
)
return
(
*
reinterpret_cast
<
const
float
*>
(
sample
)
+
1.0
)
/
2.
;
return
-
1
;
}
/**
/**
* @brief Return a meaningful error string based on QAudio error codes
* @brief Return a meaningful error string based on QAudio error codes
...
...
src/podcast/ffmpeg/UBMicrophoneInput.h
View file @
1e731be1
...
@@ -44,6 +44,8 @@ private slots:
...
@@ -44,6 +44,8 @@ private slots:
void
onDataReady
();
void
onDataReady
();
private
:
private
:
double
sampleRelativeLevel
(
const
char
*
sample
);
quint8
audioLevel
(
const
QByteArray
&
data
);
QString
getErrorString
(
QAudio
::
Error
errorCode
);
QString
getErrorString
(
QAudio
::
Error
errorCode
);
QAudioInput
*
mAudioInput
;
QAudioInput
*
mAudioInput
;
...
@@ -52,6 +54,7 @@ private:
...
@@ -52,6 +54,7 @@ private:
QAudioFormat
mAudioFormat
;
QAudioFormat
mAudioFormat
;
qint64
mSeekPos
;
qint64
mSeekPos
;
quint8
mLastAudioLevel
;
};
};
#endif // UBMICROPHONEINPUT_H
#endif // UBMICROPHONEINPUT_H
Write
Preview
Markdown
is supported
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