mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-11 06:25:33 +08:00
Sound generator, a class playing simple notification sounds (1/2 frequency tones).
These tones are generated "in memory", so no sound files ("wav") are needed.
New lib blacksound for utils around audio
This commit is contained in:
committed by
Mathew Sutcliffe
parent
e877c5c368
commit
f9225814f9
@@ -7,26 +7,43 @@
|
||||
#define BLACKSOUND_SOUNDGENERATOR_H
|
||||
|
||||
#include "blackmisc/avselcal.h"
|
||||
#include "blackmisc/vaudiodevice.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QAudioFormat>
|
||||
#include <QAudioOutput>
|
||||
#include <QAudioDeviceInfo>
|
||||
|
||||
namespace BlackSound
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief Paying simple sounds
|
||||
*/
|
||||
class CSoundGenerator : public QIODevice
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
* \brief How to play
|
||||
*/
|
||||
enum PlayMode
|
||||
{
|
||||
Single,
|
||||
SingleWithAutomaticDeletion,
|
||||
EndlessLoop
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Tone to be played
|
||||
*/
|
||||
struct Tone
|
||||
{
|
||||
int m_frequencyHz;
|
||||
int m_secondaryFrequencyHz;
|
||||
qint64 m_durationMs;
|
||||
int m_frequencyHz; /*!< first tone's frequency, use 0 for silence */
|
||||
int m_secondaryFrequencyHz; /*!< second tone's frequency, or 0 */
|
||||
qint64 m_durationMs; /*!< How long to play */
|
||||
|
||||
/*!
|
||||
* \brief Play frequency f for t milliseconds
|
||||
@@ -37,41 +54,42 @@ namespace BlackSound
|
||||
* \brief Play 2 frequencies f for t milliseconds
|
||||
*/
|
||||
Tone(int frequencyHz, int secondaryFrequencyHz, qint64 durationMs) : m_frequencyHz(frequencyHz), m_secondaryFrequencyHz(secondaryFrequencyHz), m_durationMs(durationMs) {}
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Constructor
|
||||
* \param format
|
||||
* \param device device
|
||||
* \param format audio format
|
||||
* \param tones list of Tones
|
||||
* \param singlePlay play once?
|
||||
* \param mode play once?
|
||||
* \param parent
|
||||
* \see PlayMode
|
||||
*/
|
||||
CSoundGenerator(const QAudioFormat &format, const QList<Tone> &tones, bool singlePlay, QObject *parent);
|
||||
|
||||
CSoundGenerator(const QAudioDeviceInfo &device, const QAudioFormat &format, const QList<Tone> &tones, PlayMode mode, QObject *parent = nullptr);
|
||||
|
||||
/*!
|
||||
* \brief Constructor
|
||||
* \param tones list of Tones
|
||||
* \param singlePlay play once?
|
||||
* \param mode play once?
|
||||
* \param parent
|
||||
* \see PlayMode
|
||||
*/
|
||||
CSoundGenerator(const QList<Tone> &tones, bool singlePlay, QObject *parent);
|
||||
CSoundGenerator(const QList<Tone> &tones, PlayMode mode, QObject *parent = nullptr);
|
||||
|
||||
/*!
|
||||
* Destructor
|
||||
*/
|
||||
~CSoundGenerator();
|
||||
|
||||
/*!
|
||||
* \brief Open device
|
||||
*/
|
||||
void start();
|
||||
|
||||
/*!
|
||||
* \brief Close device, buffer stays intact
|
||||
*/
|
||||
void stop();
|
||||
void stop(bool destructor = false);
|
||||
|
||||
/*!
|
||||
* \brief sDuration of one cycle
|
||||
*/
|
||||
qint64 singleCyleDurationMs() const { return calculateDurationMs(this->m_tones); }
|
||||
|
||||
/*!
|
||||
* \copydoc QIODevice::readData()
|
||||
@@ -111,6 +129,13 @@ namespace BlackSound
|
||||
*/
|
||||
static QAudioFormat defaultAudioFormat();
|
||||
|
||||
/*!
|
||||
* \brief Find the closest Qt device to this audio device
|
||||
* \param audioDevice output audio device
|
||||
* \return
|
||||
*/
|
||||
static QAudioDeviceInfo findClosestOutputDevice(const BlackMisc::Voice::CAudioDevice &audioDevice);
|
||||
|
||||
/*!
|
||||
* \brief Play signal of tones once
|
||||
* \param volume 0-100
|
||||
@@ -128,18 +153,14 @@ namespace BlackSound
|
||||
*/
|
||||
static void playSelcal(qint32 volume, const BlackMisc::Aviation::CSelcal &selcal, QAudioDeviceInfo device = QAudioDeviceInfo::defaultOutputDevice());
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Device was closed
|
||||
* \remarks With singleShot the signal indicates that sound sequence has finished
|
||||
* \brief Play SELCAL tone
|
||||
* \param volume 0-100
|
||||
* \param selcal
|
||||
* \param audioDevice device to be used
|
||||
* \see BlackMisc::Aviation::CSelcal
|
||||
*/
|
||||
void stopped();
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \brief Generate tone data in internal buffer
|
||||
*/
|
||||
void generateData(const QAudioFormat &format, const QList<Tone> &tones);
|
||||
static void playSelcal(qint32 volume, const BlackMisc::Aviation::CSelcal &selcal, const BlackMisc::Voice::CAudioDevice &audioDevice);
|
||||
|
||||
/*!
|
||||
* \brief One cycle of tones takes t milliseconds
|
||||
@@ -149,12 +170,36 @@ namespace BlackSound
|
||||
return this->m_oneCycleDurationMs;
|
||||
}
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Device was closed
|
||||
* \remarks With singleShot the signal indicates that sound sequence has finished
|
||||
*/
|
||||
void stopped();
|
||||
|
||||
public slots:
|
||||
/*!
|
||||
* \brief Play sound, open device
|
||||
* \param volume 0..100
|
||||
*/
|
||||
void start(int volume);
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \brief Generate tone data in internal buffer
|
||||
*/
|
||||
void generateData();
|
||||
|
||||
private:
|
||||
QList<Tone> m_tones; /*! tones to be played */
|
||||
qint64 m_position; /*!< position in buffer */
|
||||
bool m_singlePlay; /*!< end data provisioning after playing all tones */
|
||||
bool m_playMode; /*!< end data provisioning after playing all tones, play endless loop */
|
||||
bool m_endReached; /*!< indicates end in combination with single play */
|
||||
qint64 m_oneCycleDurationMs; /*!< how long is one cycle of tones */
|
||||
QByteArray m_buffer;
|
||||
QByteArray m_buffer; /*!< generated buffer for data */
|
||||
QAudioDeviceInfo m_device; /*!< audio device */
|
||||
QAudioFormat m_audioFormat; /*!< used format */
|
||||
QScopedPointer<QAudioOutput> m_audioOutput;
|
||||
|
||||
/*!
|
||||
* \brief Duration of these tones
|
||||
@@ -163,4 +208,6 @@ namespace BlackSound
|
||||
|
||||
};
|
||||
} //namespace
|
||||
|
||||
|
||||
#endif // guard
|
||||
|
||||
Reference in New Issue
Block a user