1 #include "qsoundout.h"
2 #include "QAudioFormat"
3
QSoundOut(QObject * parent)4 QSoundOut::QSoundOut(QObject *parent) :
5 QObject(parent)
6 {
7 rcnt = 0;
8 rrd = 0;
9 rwr = 0;
10 fptr = 0;
11 m_audio = nullptr;
12 m_dev = nullptr;
13
14 QAudioFormat fmt;
15 fmt.setSampleRate(SAMPLERATE);
16 fmt.setChannelCount(CHANNELS);
17 fmt.setSampleSize(SAMPLESIZE);
18 fmt.setByteOrder(QAudioFormat::LittleEndian);
19 fmt.setCodec("audio/pcm");
20 fmt.setSampleType(QAudioFormat::SignedInt);
21
22 m_audio = new QAudioOutput(fmt, this);
23 if (m_audio == nullptr)
24 return;
25 connect(m_audio, SIGNAL(notify()), this, SLOT(OnNotify()));
26 m_audio->setBufferSize(FRAMEBYTES * 2);
27 m_audio->setNotifyInterval(40); //1/25 sec = 40mS
28 m_dev = m_audio->start();
29 if (m_dev == nullptr)
30 {
31 disconnect(this, SLOT(OnNotify()));
32 delete(m_audio);
33 m_audio = nullptr;
34 return;
35 }
36
37 m_kick.setSingleShot(true);
38 m_kick.connect(&m_kick, SIGNAL(timeout()), this, SLOT(OnNotify()));
39 m_kick.start(40); //kick it first!
40 }
41
~QSoundOut()42 QSoundOut::~QSoundOut()
43 {
44 if (m_dev)
45 {
46 m_audio->stop();
47 disconnect(this, SLOT(OnNotify()));
48 delete(m_audio); //this will delete m_dev too!!!!
49 m_audio = nullptr;
50 }
51 }
52
OnNotify()53 void QSoundOut::OnNotify()
54 {
55 char dummy[FRAMEBYTES];
56
57 if ((m_dev == nullptr) || (m_audio == nullptr))
58 return;
59
60 m_lock.lock();
61 if (rcnt)
62 {
63 m_dev->write((const char*)&rbuf[rrd], (qint64)FRAMEBYTES);
64 rrd++;
65 if (rrd >= BUFFERS)
66 rrd = 0;
67 rcnt--;
68 }
69 else
70 {
71 memset(dummy, 0, FRAMEBYTES);
72 m_dev->write((const char*)dummy, (qint64)FRAMEBYTES);
73 }
74 m_lock.unlock();
75 }
76
FeedDAC(unsigned short left,unsigned short right)77 void QSoundOut::FeedDAC(unsigned short left, unsigned short right)
78 {
79 if ((m_dev == nullptr) || (m_audio == nullptr))
80 return;
81 switch (SAMPLESIZE)
82 {
83 case 8:
84 fbuf[fptr++] = left >> 8;
85 fbuf[fptr++] = right >> 8;
86 break;
87 case 16:
88 fbuf[fptr++] = left & 0xff;
89 fbuf[fptr++] = left >> 8;
90 fbuf[fptr++] = right & 0xff;
91 fbuf[fptr++] = right >> 8;
92 break;
93 }
94 if (fptr >= FRAMEBYTES)
95 {
96 fptr = 0;
97 m_lock.lock();
98 if (rcnt >= BUFFERS)
99 {
100 m_dev->write((const char*)&rbuf[rrd], (qint64)FRAMEBYTES);
101 rrd++;
102 if (rrd >= BUFFERS)
103 rrd = 0;
104 rcnt--;
105 }
106 memcpy(&rbuf[rwr], fbuf, FRAMEBYTES);
107 rwr++;
108 if (rwr >= BUFFERS)
109 rwr = 0;
110 rcnt++;
111 m_lock.unlock();
112 }
113 }
114