Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. qt audio output divide 100000 generate sinus wav
QtWS25 Last Chance

qt audio output divide 100000 generate sinus wav

Scheduled Pinned Locked Moved General and Desktop
sinuswav
3 Posts 2 Posters 1.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    noob
    wrote on 7 Oct 2015, 12:58 last edited by noob 10 Jul 2015, 13:13
    #1

    i work with example qt audio output and I do not understand the 2 lines, why we set duration * 1000000
    m_generator = new Generator(m_format, DurationSeconds*1000000, ToneSampleRateHz, this);
    and then divide by 100000
    qint64 length = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8)) * durationUs / 100000;

    ????????????????????????

    code:



    #include <QAudioDeviceInfo>
    #include <QAudioOutput>
    #include <QDebug>
    #include <QVBoxLayout>
    #include <qmath.h>
    #include <qendian.h>

    #include "audiooutput.h"

    #define PUSH_MODE_LABEL "Enable push mode"
    #define PULL_MODE_LABEL "Enable pull mode"
    #define SUSPEND_LABEL "Suspend playback"
    #define RESUME_LABEL "Resume playback"
    #define VOLUME_LABEL "Volume:"

    const int DurationSeconds = 1;
    const int ToneSampleRateHz = 600; // default = 600;
    const int DataSampleRateHz = 44100;
    const int BufferSize = 32768;

    Generator::Generator(const QAudioFormat &format,
    qint64 durationUs,
    int sampleRate,
    QObject *parent)
    : QIODevice(parent)
    , m_pos(0)
    {
    if (format.isValid())
    generateData(format, durationUs, sampleRate);
    }

    Generator::~Generator()
    {

    }

    void Generator::start()
    {
    open(QIODevice::ReadOnly);
    }

    void Generator::stop()
    {
    m_pos = 0;
    close();
    }

    void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate)
    {
    const int channelBytes = format.sampleSize() / 8;
    const int sampleBytes = format.channelCount() * channelBytes;

    qint64 length = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8))
                        * durationUs / 100000;
    
    Q_ASSERT(length % sampleBytes == 0);
    
    Q_UNUSED(sampleBytes) // suppress warning in release builds
    

    //QMessageBox::warning(this, "sd", "sd", QMessageBox::Ok)
    m_buffer.resize(length);
    unsigned char *ptr = reinterpret_cast<unsigned char *>(m_buffer.data());
    int sampleIndex = 0;

    while (length) {
        const qreal x = qSin(2 * M_PI * sampleRate * qreal(sampleIndex % format.sampleRate()) / format.sampleRate());
        for (int i=0; i<format.channelCount(); ++i) {
            if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
                const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
                *reinterpret_cast<quint8*>(ptr) = value;
            } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
                const qint8 value = static_cast<qint8>(x * 127);
                *reinterpret_cast<quint8*>(ptr) = value;
            } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
                quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
                if (format.byteOrder() == QAudioFormat::LittleEndian)
                    qToLittleEndian<quint16>(value, ptr);
                else
                    qToBigEndian<quint16>(value, ptr);
            } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
                qint16 value = static_cast<qint16>(x * 32767);
                if (format.byteOrder() == QAudioFormat::LittleEndian)
                    qToLittleEndian<qint16>(value, ptr);
                else
                    qToBigEndian<qint16>(value, ptr);
            }
    
            ptr += channelBytes;
            length -= channelBytes;
        }
        ++sampleIndex;
    }
    

    }

    qint64 Generator::readData(char *data, qint64 len)
    {
    qint64 total = 0;
    if (!m_buffer.isEmpty()) {
    while (len - total > 0) {
    const qint64 chunk = qMin((m_buffer.size() - m_pos), len - total);
    memcpy(data + total, m_buffer.constData() + m_pos, chunk);
    m_pos = (m_pos + chunk) % m_buffer.size();
    total += chunk;
    }
    }
    return total;
    }

    qint64 Generator::writeData(const char *data, qint64 len)
    {
    Q_UNUSED(data);
    Q_UNUSED(len);

    return 0;
    

    }

    qint64 Generator::bytesAvailable() const
    {
    return m_buffer.size() + QIODevice::bytesAvailable();
    }

    AudioTest::AudioTest()
    : m_pushTimer(new QTimer(this))
    , m_modeButton(0)
    , m_suspendResumeButton(0)
    , m_deviceBox(0)
    , m_device(QAudioDeviceInfo::defaultOutputDevice())
    , m_generator(0)
    , m_audioOutput(0)
    , m_output(0)
    , m_buffer(BufferSize, 0)
    {
    initializeWindow();
    initializeAudio();
    }

    void AudioTest::initializeWindow()
    {
    QScopedPointer<QWidget> window(new QWidget);
    QScopedPointer<QVBoxLayout> layout(new QVBoxLayout);

    m_deviceBox = new QComboBox(this);
    const QAudioDeviceInfo &defaultDeviceInfo = QAudioDeviceInfo::defaultOutputDevice();
    m_deviceBox->addItem(defaultDeviceInfo.deviceName(), qVariantFromValue(defaultDeviceInfo));
    foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
        if (deviceInfo != defaultDeviceInfo)
            m_deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo));
    }
    connect(m_deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
    layout->addWidget(m_deviceBox);
    
    m_modeButton = new QPushButton(this);
    m_modeButton->setText(tr(PUSH_MODE_LABEL));
    connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode()));
    layout->addWidget(m_modeButton);
    
    m_suspendResumeButton = new QPushButton(this);
    m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
    connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume()));
    layout->addWidget(m_suspendResumeButton);
    
    QHBoxLayout *volumeBox = new QHBoxLayout;
    m_volumeLabel = new QLabel;
    m_volumeLabel->setText(tr(VOLUME_LABEL));
    m_volumeSlider = new QSlider(Qt::Horizontal);
    m_volumeSlider->setMinimum(0);
    m_volumeSlider->setMaximum(100);
    m_volumeSlider->setSingleStep(10);
    connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
    volumeBox->addWidget(m_volumeLabel);
    volumeBox->addWidget(m_volumeSlider);
    layout->addLayout(volumeBox);
    
    window->setLayout(layout.data());
    layout.take(); // ownership transferred
    
    setCentralWidget(window.data());
    QWidget *const windowPtr = window.take(); // ownership transferred
    windowPtr->show();
    

    }

    void AudioTest::initializeAudio()
    {
    connect(m_pushTimer, SIGNAL(timeout()), SLOT(pushTimerExpired()));

    m_pullMode = true;
    
    m_format.setSampleRate(DataSampleRateHz);
    m_format.setChannelCount(1);
    m_format.setSampleSize(16);
    m_format.setCodec("audio/pcm");
    m_format.setByteOrder(QAudioFormat::LittleEndian);
    m_format.setSampleType(QAudioFormat::SignedInt);
    
    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(m_format)) {
        qWarning() << "Default format not supported - trying to use nearest";
        m_format = info.nearestFormat(m_format);
    }
    
    m_generator = new Generator(m_format, DurationSeconds*1000000, ToneSampleRateHz, this);
    
    createAudioOutput();
    

    }

    void AudioTest::createAudioOutput()
    {
    delete m_audioOutput;
    m_audioOutput = 0;
    m_audioOutput = new QAudioOutput(m_device, m_format, this);
    m_generator->start();
    m_audioOutput->start(m_generator);
    m_volumeSlider->setValue(int(m_audioOutput->volume()*100.0f));
    }

    AudioTest::~AudioTest()
    {

    }

    void AudioTest::deviceChanged(int index)
    {
    m_pushTimer->stop();
    m_generator->stop();
    m_audioOutput->stop();
    m_audioOutput->disconnect(this);
    m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>();
    createAudioOutput();
    }

    void AudioTest::volumeChanged(int value)
    {
    if (m_audioOutput)
    m_audioOutput->setVolume(qreal(value/100.0f));
    }

    void AudioTest::pushTimerExpired()
    {
    if (m_audioOutput && m_audioOutput->state() != QAudio::StoppedState) {
    int chunks = m_audioOutput->bytesFree()/m_audioOutput->periodSize();
    while (chunks) {
    const qint64 len = m_generator->read(m_buffer.data(), m_audioOutput->periodSize());
    if (len)
    m_output->write(m_buffer.data(), len);
    if (len != m_audioOutput->periodSize())
    break;
    --chunks;
    }
    }
    }

    void AudioTest::toggleMode()
    {
    m_pushTimer->stop();
    m_audioOutput->stop();

    if (m_pullMode) {
        //switch to push mode (periodically push to QAudioOutput using a timer)
        m_modeButton->setText(tr(PULL_MODE_LABEL));
        m_output = m_audioOutput->start();
        m_pullMode = false;
        m_pushTimer->start(20);
    } else {
        //switch to pull mode (QAudioOutput pulls from Generator as needed)
        m_modeButton->setText(tr(PUSH_MODE_LABEL));
        m_pullMode = true;
        m_audioOutput->start(m_generator);
    }
    
    m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
    

    }

    void AudioTest::toggleSuspendResume()
    {
    if (m_audioOutput->state() == QAudio::SuspendedState) {
    m_audioOutput->resume();
    m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
    } else if (m_audioOutput->state() == QAudio::ActiveState) {
    m_audioOutput->suspend();
    m_suspendResumeButton->setText(tr(RESUME_LABEL));
    } else if (m_audioOutput->state() == QAudio::StoppedState) {
    m_audioOutput->resume();
    m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
    } else if (m_audioOutput->state() == QAudio::IdleState) {
    // no-op
    }
    }

    1 Reply Last reply
    0
    • N Offline
      N Offline
      noob
      wrote on 7 Oct 2015, 14:24 last edited by
      #2

      someone help

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on 7 Oct 2015, 20:22 last edited by
        #3

        Hi and welcome to devnet,

        Please practice some patience, this forum is community driven. Not all people active here are living in the same time zone as you.

        In audio you generally use mili to microsecond for length. In the current case, it allows you to easily play with the duration in the example even though right now you have a one to one relation ship.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1

        1/3

        7 Oct 2015, 12:58

        • Login

        • Login or register to search.
        1 out of 3
        • First post
          1/3
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved