voicegenerator.cpp Example File
demos/mobile/guitartuner/src/voicegenerator.cpp
 
 
 #include "voicegenerator.h"
 const int BufferSizeMilliseconds = 100;
 VoiceGenerator::VoiceGenerator(const QAudioFormat &format,
                                qreal frequency, qreal amplitude,
                                QObject *parent) :
     QIODevice(parent),
     m_format(format),
     m_amplitude(0.5)
 {
     Q_ASSERT(m_format.sampleSize() % 8 == 0);
     int sampleBytes = m_format.channels() * (m_format.sampleSize() / 8);
     
     qint64 samplesInBuffer = m_format.sampleRate()
                              * BufferSizeMilliseconds / 1000 + 1;
     qint64 length = samplesInBuffer * sampleBytes;
     m_buffer.resize(length);
     m_max_position = 0;
     m_position = 0;
     m_amplitude = amplitude;
     setFrequency(frequency);
 }
 VoiceGenerator::~VoiceGenerator()
 {
 }
 
 void VoiceGenerator::start()
 {
     open(QIODevice::ReadOnly);
 }
 
 void VoiceGenerator::stop()
 {
     close();
     m_position = 0;
 }
 
 void VoiceGenerator::setFrequency(qreal frequency)
 {
     Q_ASSERT(1 / frequency < BufferSizeMilliseconds);
     this->m_frequency = frequency;
     refreshData();
 }
 
 void VoiceGenerator::setAmplitude(qreal amplitude)
 {
     Q_ASSERT(amplitude >= 0);
     m_amplitude = amplitude;
     refreshData();
 }
 
 qreal VoiceGenerator::frequency()
 {
     return m_frequency;
 }
 
 void VoiceGenerator::refreshData()
 {
     const int channelBytes = m_format.sampleSize() / 8;
     const int sampleSize = m_format.channels() * channelBytes;
     const qint64 voiceOscillationsInBuffer = BufferSizeMilliseconds
                                          * m_frequency / 1000;
     const qint64 voiceSamplesInBuffer = voiceOscillationsInBuffer
                                    * m_format.sampleRate() / m_frequency;
     m_max_position = voiceSamplesInBuffer * sampleSize;
     qint64 dataGenerationLength = m_buffer.size();
     Q_ASSERT(m_max_position % (sampleSize) == 0);
     Q_ASSERT(dataGenerationLength <= m_buffer.size());
     short *t = (short*)m_buffer.data();
 
     uchar *ptr = reinterpret_cast<uchar *>(m_buffer.data());
     int sampleIndex = 0;
     while (dataGenerationLength > 0) {
         qreal realValue = 0;
         if (sampleIndex < voiceSamplesInBuffer) {
             realValue = m_amplitude
                        *qSin(2.0f * M_PI * m_frequency
                              * qreal(sampleIndex % m_format.sampleRate())
                                / m_format.sampleRate());
         }
         for (int i=0; i<m_format.channels(); ++i) {
             setValue(ptr, realValue);
             ptr += channelBytes;
             dataGenerationLength -= channelBytes;
         }
         ++sampleIndex;
     }
 }
 
 void VoiceGenerator::setValue(uchar *ptr, qreal realValue) {
     if (m_format.sampleSize() == 8)
     {
         quint8 value = 0;
         if (m_format.sampleType() == QAudioFormat::UnSignedInt) {
             value = static_cast<quint8>(
                         qRound((1.0 + realValue) / 2
                                * M_MAX_AMPLITUDE_8BIT_UNSIGNED));
         } else if (m_format.sampleType() == QAudioFormat::SignedInt) {
             value = static_cast<qint8>(
                         qRound(realValue
                                * M_MAX_AMPLITUDE_8BIT_SIGNED));
         }
         *reinterpret_cast<quint8*>(ptr) = value;
     } else if (m_format.sampleSize() == 16) {
         quint16 value = 0;
         if (m_format.sampleType() == QAudioFormat::UnSignedInt) {
             value = static_cast<quint16>(
                         qRound((1.0 + realValue) / 2
                                * M_MAX_AMPLITUDE_16BIT_UNSIGNED));
         } else if (m_format.sampleType() == QAudioFormat::SignedInt) {
             value = static_cast<qint16>(
                         qRound(realValue
                                * M_MAX_AMPLITUDE_16BIT_SIGNED));
         }
         if (m_format.byteOrder() == QAudioFormat::LittleEndian)
             qToLittleEndian<qint16>(value, ptr);
         else
             qToBigEndian<qint16>(value, ptr);
     }
 }
 qint64 VoiceGenerator::bytesAvailable() const
 {
     return m_max_position + QIODevice::bytesAvailable();
 }
 
 qint64 VoiceGenerator::readData(char *data, qint64 maxlen)
 {
     qint64 total = 0;
     qint64 chunk = 0;
     while (total < maxlen) {
         if (maxlen - total >= m_max_position - m_position) {
             
             
             chunk = m_max_position - m_position;
             memcpy(data, m_buffer.constData() + m_position, chunk);
             m_position = 0;
         }
         else {
             
             chunk = maxlen - total;
             memcpy(data, m_buffer.constData() + m_position, chunk);
             m_position = (m_position + chunk) % m_max_position;
         }
         data += chunk;
         total += chunk;
     }
     return total;
 }
 
 qint64 VoiceGenerator::writeData(const char *data, qint64 maxlen)
 {
     Q_UNUSED(data);
     Q_UNUSED(maxlen);
     return 0;
 }