summaryrefslogtreecommitdiffstats
path: root/pica-client/audiodevice.h
diff options
context:
space:
mode:
Diffstat (limited to 'pica-client/audiodevice.h')
-rw-r--r--pica-client/audiodevice.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/pica-client/audiodevice.h b/pica-client/audiodevice.h
index ef7e5b3..6b2db1c 100644
--- a/pica-client/audiodevice.h
+++ b/pica-client/audiodevice.h
@@ -99,6 +99,14 @@ signals:
// Counterpart of VideoDevice::accelerationInUse().
void deviceFormatInUse(QString description);
+ // The capture device is delivering samples pinned at full scale, with the
+ // share of them in the last window and the peak that was seen. Not an
+ // error in the errorOccurred() sense - the call carries on - but it wants
+ // acting on, because nothing downstream can undo it. Numbers rather than
+ // a message because the receiver drives the gain control with them; see
+ // AudioVideoCallController::capture_clipping().
+ void captureClipping(double pinnedPercent, double peakDb);
+
public:
virtual QList<MediaDeviceInfo> Enumerate(enum MediaDeviceStreamDirection dir);
@@ -155,6 +163,34 @@ private:
// joining either thread.
EchoCancellerPtr m_echoCanceller;
+ // Watches the microphone for samples pinned at the rail and warns once
+ // every kLevelReportSec of audio if too many of them are.
+ //
+ // Detection only - there is deliberately no gain applied here. Clipping
+ // happens in the converter, before we see anything, and scaling a clipped
+ // buffer down just produces a quieter clipped buffer: the flattened peaks,
+ // the harmonics they generate and the non-linearity that stops the echo
+ // canceller converging are all still in it. The only fix is less gain
+ // ahead of the ADC, which means the capture device's own mixer control.
+ void resetCaptureLevel();
+ void checkCaptureLevel(const qint16 *pcm, int nsamples);
+
+ qint64 m_clipCount;
+ qint64 m_levelCount;
+ int m_levelPeak;
+
+ // |sample| at or above this counts as pinned. 32512 is -0.13 dBFS: low
+ // enough to catch a converter that rails slightly short of 0x7fff, high
+ // enough that ordinary loud speech does not trip it.
+ static const int kClipThreshold = 32512;
+
+ // Fraction of pinned samples in a window that is worth complaining about,
+ // in percent. A stray sample at full scale is normal; a twentieth of a
+ // percent of them is not.
+ static constexpr double kClipWarnPercent = 0.05;
+
+ static const int kLevelReportSec = 2;
+
// The FFmpeg and the native halves of each direction. Which one runs is
// decided by PlatformDriverName().
void captureFFmpeg(const QString &driver);