Advertisement
dlangu0393

[GoogleSpeechAPI]AudioInput: speechInput.cpp

Jan 24th, 2012
1,219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Based on Qt Example
  3.  * PCM2WAV is not mine, I found it in Google and modified it.
  4.  */
  5.  
  6. #include "speechInput.h"
  7.  
  8. #include <QtEndian>
  9. #include <QDebug>
  10. #include <QPainter>
  11.  
  12. WavPcmFile::WavPcmFile(const QString & name, const QAudioFormat & format_, QObject *parent_)
  13.     : QFile(name, parent_), format(format_)
  14. {
  15. }
  16.  
  17. bool WavPcmFile::hasSupportedFormat()
  18. {
  19.     return (format.sampleSize() == 8
  20.         && format.sampleType() == QAudioFormat::UnSignedInt)
  21.         || (format.sampleSize() > 8
  22.         && format.sampleType() == QAudioFormat::SignedInt
  23.         && format.byteOrder() == QAudioFormat::LittleEndian);
  24. }
  25.  
  26. bool WavPcmFile::open()
  27. {
  28.     if (!hasSupportedFormat()) {
  29.         setErrorString("Wav PCM supports only 8-bit unsigned samples "
  30.             "or 16-bit (or more) signed samples (in little endian)");
  31.         return false;
  32.     } else {
  33.         if (!QFile::open(ReadWrite | Truncate))
  34.             return false;
  35.         writeHeader();
  36.         return true;
  37.     }
  38. }
  39.  
  40. void WavPcmFile::writeHeader()
  41. {
  42.     QDataStream out(this);
  43.     out.setByteOrder(QDataStream::LittleEndian);
  44.  
  45.     // RIFF chunk
  46.     out.writeRawData("RIFF", 4);
  47.     out << quint32(0); // Placeholder for the RIFF chunk size (filled by close())
  48.     out.writeRawData("WAVE", 4);
  49.  
  50.     // Format description chunk
  51.     out.writeRawData("fmt ", 4);
  52.     out << quint32(16); // "fmt " chunk size (always 16 for PCM)
  53.     out << quint16(1);  // data format (1 => PCM)
  54.     out << quint16(format.channelCount());
  55.     out << quint32(format.sampleRate());
  56.     out << quint32(format.sampleRate() * format.channelCount()
  57.         * format.sampleSize() / 8 ); // bytes per second
  58.     out << quint16(format.channelCount() * format.sampleSize() / 8); // Block align
  59.     out << quint16(format.sampleSize()); // Significant Bits Per Sample
  60.  
  61.     // Data chunk
  62.     out.writeRawData("data", 4);
  63.     out << quint32(0);  // Placeholder for the data chunk size (filled by close())
  64.  
  65.     Q_ASSERT(pos() == 44); // Must be 44 for WAV PCM
  66. }
  67.  
  68. void WavPcmFile::close()
  69. {
  70.     // Fill the header size placeholders
  71.     quint32 fileSize = size();
  72.  
  73.     QDataStream out(this);
  74.     // RIFF chunk size
  75.     seek(4);
  76.     out << quint32(fileSize - 8);
  77.  
  78.     // data chunk size
  79.     seek(40);
  80.     out << quint32(fileSize - 44);
  81.  
  82.     QFile::close();
  83. }
  84.  
  85. AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent, const QString &filename)
  86.     :   QIODevice(parent)
  87.     ,   m_format(format)
  88.     ,   m_maxAmplitude(0)
  89.     ,   m_level(0.0)
  90.  
  91. {
  92.     switch (m_format.sampleSize()) {
  93.     case 8:
  94.         switch (m_format.sampleType()) {
  95.         case QAudioFormat::UnSignedInt:
  96.             m_maxAmplitude = 255;
  97.             break;
  98.         case QAudioFormat::SignedInt:
  99.             m_maxAmplitude = 127;
  100.             break;
  101.         default:
  102.             break;
  103.         }
  104.         break;
  105.     case 16:
  106.         switch (m_format.sampleType()) {
  107.         case QAudioFormat::UnSignedInt:
  108.             m_maxAmplitude = 65535;
  109.             break;
  110.         case QAudioFormat::SignedInt:
  111.             m_maxAmplitude = 32767;
  112.             break;
  113.         default:
  114.             break;
  115.         }
  116.         break;
  117.     default:
  118.         break;
  119.     }
  120.  
  121.     m_file = new WavPcmFile(filename,format,this);
  122.  
  123. }
  124.  
  125. AudioInfo::~AudioInfo()
  126. {
  127. }
  128.  
  129. void AudioInfo::start()
  130. {
  131.     m_file->open();
  132.     open(QIODevice::WriteOnly);
  133. }
  134.  
  135. void AudioInfo::stop()
  136. {
  137.     close();
  138.     m_file->close();
  139. }
  140.  
  141. qint64 AudioInfo::readData(char *data, qint64 maxlen)
  142. {
  143.     Q_UNUSED(data)
  144.         Q_UNUSED(maxlen)
  145.  
  146.         return 0;
  147. }
  148.  
  149. qint64 AudioInfo::writeData(const char *data, qint64 len)
  150. {
  151.     if (m_maxAmplitude) {
  152.         Q_ASSERT(m_format.sampleSize() % 8 == 0);
  153.         const int channelBytes = m_format.sampleSize() / 8;
  154.         const int sampleBytes = m_format.channels() * channelBytes;
  155.         Q_ASSERT(len % sampleBytes == 0);
  156.         const int numSamples = len / sampleBytes;
  157.  
  158.         quint16 maxValue = 0;
  159.         const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data);
  160.  
  161.         for (int i = 0; i < numSamples; ++i) {
  162.             for(int j = 0; j < m_format.channels(); ++j) {
  163.                 quint16 value = 0;
  164.  
  165.                 if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
  166.                     value = *reinterpret_cast<const quint8*>(ptr);
  167.                 } else if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::SignedInt) {
  168.                     value = qAbs(*reinterpret_cast<const qint8*>(ptr));
  169.                 } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
  170.                     if (m_format.byteOrder() == QAudioFormat::LittleEndian)
  171.                         value = qFromLittleEndian<quint16>(ptr);
  172.                     else
  173.                         value = qFromBigEndian<quint16>(ptr);
  174.                 } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::SignedInt) {
  175.                     if (m_format.byteOrder() == QAudioFormat::LittleEndian)
  176.                         value = qAbs(qFromLittleEndian<qint16>(ptr));
  177.                     else
  178.                         value = qAbs(qFromBigEndian<qint16>(ptr));
  179.                 }
  180.  
  181.                 maxValue = qMax(value, maxValue);
  182.                 ptr += channelBytes;
  183.             }
  184.         }
  185.  
  186.         maxValue = qMin(maxValue, m_maxAmplitude);
  187.         m_level = qreal(maxValue) / m_maxAmplitude;
  188.     }
  189.  
  190.     m_file->write(data,len);
  191.  
  192.     emit update();
  193.     return len;
  194. }
  195.  
  196.  
  197. RenderArea::RenderArea(QWidget *parent)
  198.     : QWidget(parent)
  199. {
  200.     setBackgroundRole(QPalette::Base);
  201.     setAutoFillBackground(true);
  202.  
  203.     m_level = 0;
  204.     setMinimumHeight(30);
  205.     setMinimumWidth(100);
  206. }
  207.  
  208. void RenderArea::paintEvent(QPaintEvent * /* event */)
  209. {
  210.     QPainter painter(this);
  211.  
  212.     painter.setPen(Qt::black);
  213.     painter.drawRect(QRect(painter.viewport().left(),
  214.         painter.viewport().top(),
  215.         painter.viewport().right()-20,
  216.         painter.viewport().bottom()-20));
  217.     if (m_level == 0.0)
  218.         return;
  219.  
  220.     painter.setPen(Qt::red);
  221.  
  222.     int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*m_level;
  223.     for (int i = 0; i < 10; ++i) {
  224.         int x1 = painter.viewport().left()+11;
  225.         int y1 = painter.viewport().top()+10+i;
  226.         int x2 = painter.viewport().left()+20+pos;
  227.         int y2 = painter.viewport().top()+10+i;
  228.         if (x2 < painter.viewport().left()+10)
  229.             x2 = painter.viewport().left()+10;
  230.  
  231.         painter.drawLine(QPoint(x1-10, y1-10),QPoint(x2-10, y2-10));
  232.     }
  233. }
  234.  
  235. void RenderArea::setLevel(qreal value)
  236. {
  237.     m_level = value;
  238.     repaint();
  239. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement