Advertisement
Guest User

Untitled

a guest
Jul 24th, 2019
355
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.87 KB | None | 0 0
  1. [code]
  2. #ifndef SIGNALAUDIOPLAYER_H
  3. #define SIGNALAUDIOPLAYER_H
  4.  
  5. #include <QObject>
  6. #include <QThread>
  7. #include <QIODevice>
  8. #include <QAudioOutput>
  9. #include <QPointer>
  10. #include <QtEndian>
  11. #include "datapipe.h"
  12.  
  13. class SignalAudioPlayer : public QIODevice
  14. {
  15.     Q_OBJECT
  16. public:
  17.     SignalAudioPlayer();
  18.     ~SignalAudioPlayer();
  19.    
  20.     qint64 readData(char *data, qint64 maxlen);
  21.     qint64 writeData(const char *data, qint64 len);
  22.     qint64 bytesAvailable() const;
  23.    
  24. public slots:
  25.     void start();
  26.     void stop();
  27.     void dataInput(RawDataPipe* pipe);
  28. private slots:
  29.     void processing();
  30.    
  31. private:
  32.     QThread t;
  33.     Q_INVOKABLE void init_inthread();
  34.     Q_INVOKABLE void close_inthread();
  35.     Q_INVOKABLE void start_inthread();
  36.     Q_INVOKABLE void stop_inthread();
  37.     QByteArray inputData;
  38.     QByteArray outputData;
  39.     QByteArray dataSlice;
  40.     QAudioFormat audioFormat;
  41.     QPointer<QAudioOutput> audioOutput;
  42.     bool fIsOk;
  43.     bool fPlay;
  44.     int scaleFactor;
  45. };
  46.  
  47. #endif // SIGNALAUDIOPLAYER_H
  48. [/code]
  49.  
  50. [code]
  51. #include "signalaudioplayer.h"
  52. #include "trace_macro.h"
  53.  
  54. SignalAudioPlayer::SignalAudioPlayer()
  55. {
  56.     _TRACE("");
  57.     moveToThread(&t);
  58.     t.start();
  59.     QMetaObject::invokeMethod(this,"init_inthread",Qt::BlockingQueuedConnection);
  60. }
  61.  
  62. SignalAudioPlayer::~SignalAudioPlayer()
  63. {
  64.     _TRACE("");
  65.     QMetaObject::invokeMethod(this,"close_inthread",Qt::BlockingQueuedConnection);
  66.     t.quit();
  67.     t.wait();
  68. }
  69.  
  70. qint64 SignalAudioPlayer::readData(char *data, qint64 maxlen)
  71. {
  72.     //_TRACE(maxlen);
  73.     if(outputData.isEmpty()) return 0;
  74.     qint64 len = qMin(maxlen,(qint64)outputData.size());
  75.     memcpy(data,outputData.constData(),len);
  76.     if(fPlay
  77.             && audioOutput->state() == QAudio::ActiveState
  78.             && outputData.size() < qMax(audioOutput->bufferSize(),audioOutput->bytesFree())/4)
  79.     {
  80.         _TRACE("stop");
  81.         audioOutput->stop();
  82.     }
  83.     outputData.remove(0,len);
  84.     //_TRACE(outputData.size());
  85.     //_TRACE(audioOutput->bufferSize() << audioOutput->bytesFree());
  86.     return len;
  87. }
  88.  
  89. qint64 SignalAudioPlayer::writeData(const char *data, qint64 len)
  90. {
  91.     _TRACE("");
  92.     Q_UNUSED(data)
  93.     Q_UNUSED(len)
  94.     return 0;
  95. }
  96.  
  97. qint64 SignalAudioPlayer::bytesAvailable() const
  98. {
  99.     _TRACE("");
  100. //    int size = outputData.size();
  101. //    size -= 2048*8;
  102. //    if(size < 0)
  103. //    {
  104. //        size = 0;
  105. //    }
  106. //    return size;
  107.     return outputData.size() + QIODevice::bytesAvailable();
  108. }
  109.  
  110. void SignalAudioPlayer::start()
  111. {
  112.     QMetaObject::invokeMethod(this,"start_inthread",Qt::QueuedConnection);
  113. }
  114.  
  115. void SignalAudioPlayer::stop()
  116. {
  117.     QMetaObject::invokeMethod(this,"stop_inthread",Qt::QueuedConnection);
  118. }
  119.  
  120. void SignalAudioPlayer::dataInput(RawDataPipe *pipe)
  121. {
  122.     pipe->getData(&inputData);
  123.     if(!fIsOk || !fPlay)
  124.     {
  125.         inputData.clear();
  126.         return;
  127.     }
  128.     QMetaObject::invokeMethod(this,"processing",Qt::QueuedConnection);
  129. }
  130.  
  131. void SignalAudioPlayer::processing()
  132. {
  133.     if(!fIsOk || inputData.isEmpty()) return;
  134.     if(inputData.size() % 8 != 0)
  135.     {
  136.         _ERROR("inputData.size() % 8 != 0");
  137.         return;
  138.     }
  139.     dataSlice.resize(inputData.size()/2);
  140.     char* srcMem = (char*)inputData.constData();
  141.     char* dstMem = (char*)dataSlice.constData();
  142.     int k = 0;
  143.     int sample;
  144.     int maxSample = 0;
  145.     for(int i=0;i<dataSlice.size();i+=4)
  146.     {
  147.         sample = qFromLittleEndian<qint32>(srcMem+k);
  148.         if(abs(sample) > maxSample)
  149.         {
  150.             maxSample = abs(sample);
  151.         }
  152.         k+=8;
  153.     }
  154. //    for(int i=0;i<dataSlice.size();i+=2)
  155. //    {
  156. //        sample = qFromLittleEndian<qint16>(srcMem+k);
  157. //        if(abs(sample) > maxSample)
  158. //        {
  159. //            maxSample = abs(sample);
  160. //        }
  161. //        k+=4;
  162. //    }
  163.     scaleFactor = std::round((((double)INT_MAX)*0.7)/(double)maxSample);
  164.     if(scaleFactor < 1)
  165.     {
  166.         scaleFactor = 1;
  167.     }
  168.     //_TRACE(maxSample << scaleFactor);
  169.     k = 0;
  170.     for(int i=0;i<dataSlice.size();i+=4)
  171.     {
  172.         sample = qFromLittleEndian<qint32>(srcMem+k);
  173.         sample = sample * scaleFactor;
  174.         memcpy(dstMem+i,&sample,4);
  175.         k+=8;
  176.     }
  177. //    for(int i=0;i<dataSlice.size();i+=2)
  178. //    {
  179. //        sample = qFromLittleEndian<qint32>(srcMem+k);
  180. //        sample = sample * scaleFactor;
  181. //        memcpy(dstMem+i,&sample,2);
  182. //        k+=4;
  183. //    }
  184.     inputData.clear();
  185.     outputData.append(dataSlice);
  186.     if(outputData.size() > 1024000)
  187.     {
  188.         _TRACE("clear data!");
  189.         outputData.clear();
  190.     }
  191.     if(fPlay
  192.             && (audioOutput->state() == QAudio::StoppedState || audioOutput->state() == QAudio::IdleState)
  193.             && outputData.size() > qMax(audioOutput->bufferSize(),audioOutput->bytesFree()))
  194.     {
  195.         _TRACE("start");
  196.         audioOutput->start(this);
  197.     }
  198. }
  199.  
  200. void SignalAudioPlayer::init_inthread()
  201. {
  202.     _TRACE("");
  203.     fIsOk = true;
  204.     fPlay = false;
  205.     scaleFactor = 1;
  206.     audioFormat.setSampleRate(48000);
  207.     audioFormat.setChannelCount(1);
  208.     audioFormat.setSampleSize(32);
  209.     audioFormat.setCodec("audio/pcm");
  210.     audioFormat.setByteOrder(QAudioFormat::LittleEndian);
  211.     audioFormat.setSampleType(QAudioFormat::SignedInt);
  212.     if(!QAudioDeviceInfo::defaultOutputDevice().isFormatSupported(audioFormat))
  213.     {
  214.         _ERROR("Audio format not supported");
  215.         fIsOk = false;
  216.         return;
  217.     }
  218.     audioOutput = new QAudioOutput(audioFormat);
  219.     open(QIODevice::ReadOnly);
  220. }
  221.  
  222. void SignalAudioPlayer::close_inthread()
  223. {
  224.     _TRACE("");
  225.     delete audioOutput;
  226.     close();
  227. }
  228.  
  229. void SignalAudioPlayer::start_inthread()
  230. {
  231.     _TRACE("");
  232.     fPlay = true;
  233. }
  234.  
  235. void SignalAudioPlayer::stop_inthread()
  236. {
  237.     _TRACE("");
  238.     fPlay = false;
  239.     audioOutput->stop();
  240.     inputData.clear();
  241.     outputData.clear();
  242. }
  243. [/code]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement