1 #ifndef AUDIODEVICE_HPP__
2 #define AUDIODEVICE_HPP__
3 
4 #include <QIODevice>
5 
6 class QDataStream;
7 
8 //
9 // abstract base class for audio devices
10 //
11 class AudioDevice : public QIODevice
12 {
13 public:
14   enum Channel {Mono, Left, Right, Both}; // these are mapped to combobox index so don't change
15 
toString(Channel c)16   static char const * toString (Channel c)
17   {
18     return Mono == c ? "Mono" : Left == c ? "Left" : Right == c ? "Right" : "Both";
19   }
20 
fromString(QString const & str)21   static Channel fromString (QString const& str)
22   {
23     QString s (str.toCaseFolded ().trimmed ().toLatin1 ());
24     return "both" == s ? Both : "right" == s ? Right : "left" == s ? Left : Mono;
25   }
26 
27   bool initialize (OpenMode mode, Channel channel);
28 
isSequential() const29   bool isSequential () const override {return true;}
30 
bytesPerFrame() const31   size_t bytesPerFrame () const {return sizeof (qint16) * (Mono == m_channel ? 1 : 2);}
32 
channel() const33   Channel channel () const {return m_channel;}
34 
35 protected:
AudioDevice(QObject * parent=nullptr)36   AudioDevice (QObject * parent = nullptr)
37     : QIODevice {parent}
38   {
39   }
40 
store(char const * source,size_t numFrames,qint16 * dest)41   void store (char const * source, size_t numFrames, qint16 * dest)
42   {
43     qint16 const * begin (reinterpret_cast<qint16 const *> (source));
44     for ( qint16 const * i = begin; i != begin + numFrames * (bytesPerFrame () / sizeof (qint16)); i += bytesPerFrame () / sizeof (qint16))
45       {
46         switch (m_channel)
47           {
48           case Mono:
49             *dest++ = *i;
50             break;
51 
52           case Right:
53             *dest++ = *(i + 1);
54             break;
55 
56           case Both:    // should be able to happen but if it
57             // does we'll take left
58             Q_ASSERT (Both == m_channel);
59           case Left:
60             *dest++ = *i;
61             break;
62           }
63       }
64   }
65 
load(qint16 const sample,qint16 * dest)66   qint16 * load (qint16 const sample, qint16 * dest)
67   {
68     switch (m_channel)
69       {
70       case Mono:
71         *dest++ = sample;
72         break;
73 
74       case Left:
75         *dest++ = sample;
76         *dest++ = 0;
77         break;
78 
79       case Right:
80         *dest++ = 0;
81         *dest++ = sample;
82         break;
83 
84       case Both:
85         *dest++ = sample;
86         *dest++ = sample;
87         break;
88       }
89     return dest;
90   }
91 
92 private:
93   Channel m_channel;
94 };
95 
96 Q_DECLARE_METATYPE (AudioDevice::Channel);
97 
98 #endif
99