Revision control
Copy as Markdown
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef AUDIOINPUT_H
#define AUDIOINPUT_H
#include "audiorecorder.h"
#include <QAudioSource>
#include <QMediaDevices>
#include <QtCore/qcompilerdetection.h>
#include <QBasicTimer>
#include <QComboBox>
#include <QProgressBar>
#include <QPushButton>
#include <QSlider>
#include <QVBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QByteArray>
#include <atomic>
#include <memory>
enum class AudioTestMode : uint8_t {
Pull,
Push,
Callback,
};
class AudioInfo : public QIODevice
{
Q_OBJECT
public:
AudioInfo(const QAudioFormat &format);
void start();
void stop();
[[nodiscard]] float level() const { return m_level; }
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
signals:
void levelChanged(float level);
private:
const QAudioFormat m_format;
float m_level = 0.f; // 0.0 <= m_level <= 1.0
};
class RenderArea : public QWidget
{
Q_OBJECT
public:
explicit RenderArea(QWidget *parent = nullptr);
void setLevel(float value);
protected:
void paintEvent(QPaintEvent *event) override;
private:
float m_level = 0.f;
};
class InputTest final : public QWidget
{
Q_OBJECT
public:
InputTest();
~InputTest() override;
private:
void initializeWindow();
void startAudioSource(const QAudioDevice &, const QAudioFormat &);
void cleanupAudioSource();
void initializeErrorWindow();
void restartAudioStream(bool record);
void timerEvent(QTimerEvent *) override;
template <typename T>
void processCallback(QSpan<const T> buffer, const QAudioFormat &format) noexcept
Q_DECL_NONBLOCKING_FUNCTION;
void startPullMode(bool record);
void startPushMode(bool record);
void startCallbackMode(bool record);
QString getRecordingFileName() const;
private:
void init();
void toggleSuspend();
void deviceChanged(int index);
void sliderChanged(int value);
void updateAudioDevices();
void formatChanged(QComboBox *box);
void updateRecordingProgress();
void updateControlsForRecording();
void setRecorder(std::unique_ptr<AudioRecorder> recorder);
private:
QVBoxLayout *m_layout = nullptr;
// Owned by layout
RenderArea *m_canvas = nullptr;
QComboBox *m_modeBox = nullptr;
QPushButton *m_suspendResumeButton = nullptr;
QComboBox *m_deviceBox = nullptr;
QComboBox *m_periodBox = nullptr;
QSlider *m_volumeSlider = nullptr;
QComboBox *m_formatBox = nullptr;
QComboBox *m_rateBox = nullptr;
QComboBox *m_channelsBox = nullptr;
QPushButton *m_recordButton = nullptr;
QProgressBar *m_recordProgressBar = nullptr;
QMediaDevices *m_devices = nullptr;
QAudioDevice m_currentDevice;
std::unique_ptr<AudioInfo> m_audioInfo;
std::unique_ptr<QAudioSource> m_audioSource;
AudioTestMode m_mode = AudioTestMode::Pull;
QBasicTimer m_callbackVisualizerTimer;
QBasicTimer m_recordingProgressTimer;
std::atomic<float> m_level = 0.f;
std::unique_ptr<AudioRecorder> m_recorder;
};
#endif // AUDIOINPUT_H