/* Copyright (C) 2019 * swift project Community / Contributors * * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, * or distributed except according to the terms contained in the LICENSE file. */ //! \file #ifndef BLACKCORE_AFV_AUDIO_AUDIO_INPUT_H #define BLACKCORE_AFV_AUDIO_AUDIO_INPUT_H #include "blacksound/sampleprovider/bufferedwaveprovider.h" #include "blacksound/codecs/opusencoder.h" #include "blackmisc/audio/audiodeviceinfo.h" #ifdef Q_OS_MAC #include "blackmisc/macos/microphoneaccess.h" #endif #include #include #include #include namespace BlackCore { namespace Afv { namespace Audio { //! Input buffer class CAudioInputBuffer : public QIODevice { Q_OBJECT public: //! Inout buffer CAudioInputBuffer(QObject *parent); //! Start void start(const QAudioFormat &format); //! Stop void stop(); //! \copydoc QIODevice::readData virtual qint64 readData(char *data, qint64 maxlen) override; //! \copydoc QIODevice::writeData virtual qint64 writeData(const char *data, qint64 len) override; signals: //! Frame is available void frameAvailable(const QByteArray &frame); private: static constexpr qint64 frameSize = 960; QByteArray m_buffer; QAudioFormat m_format; }; //! Opus data arguments struct OpusDataAvailableArgs { uint sequenceCounter = 0; //!< sequence counter QByteArray audio; //!< audio data }; //! Input volume stream arguments struct InputVolumeStreamArgs { //! Peak volume raw double PeakRaw = 0.0; //! Peak volume in dB double PeakDB = -1.0 * std::numeric_limits::infinity(); //! Peak volume in VU double PeakVU = 0.0; }; //! Input class CInput : public QObject { Q_OBJECT public: //! Ctor CInput(int sampleRate, QObject *parent = nullptr); //! Dtor virtual ~CInput() override { this->stop(); } //! Number of encoded bytes @{ int opusBytesEncoded() const { return m_opusBytesEncoded; } void setOpusBytesEncoded(int opusBytesEncoded) { m_opusBytesEncoded = opusBytesEncoded; } //! @} //! Volume @{ double volume() const { return m_volume; } bool setVolume(double volume); //! @} //! Started? bool started() const { return m_started; } //! Start void start(const BlackMisc::Audio::CAudioDeviceInfo &inputDevice); //! Stop void stop(); //! Corresponding device const BlackMisc::Audio::CAudioDeviceInfo &device() const { return m_device; } signals: //! Volume stream data void inputVolumeStream(const InputVolumeStreamArgs &args); //! OPUS data void opusDataAvailable(const OpusDataAvailableArgs &args); private: void audioInDataAvailable(const QByteArray &frame); static constexpr qint64 c_frameSize = 960; int m_sampleRate = 0; BlackSound::Codecs::COpusEncoder m_encoder; QScopedPointer m_audioInput; BlackMisc::Audio::CAudioDeviceInfo m_device; QAudioFormat m_inputFormat; bool m_started = false; int m_opusBytesEncoded = 0; int m_sampleCount = 0; double m_volume = 1.0; qint16 m_maxSampleInput = 0.0; const int SampleCountPerEvent = 4800; const double maxDb = 0; const double minDb = -40; uint m_audioSequenceCounter = 0; CAudioInputBuffer *m_audioInputBuffer = nullptr; #ifdef Q_OS_MAC BlackMisc::CMacOSMicrophoneAccess m_micAccess; void delayedInitMicrophone(); #endif }; } // ns } // ns } // ns #endif // guard