audiooutput



  • hello again,
    i have found the audiooutput -example in the examples and want to understand the code but i'm not used to soundcards.As well i would like to change this small app in that way that I can output an intermittend tone.( tone ,pause,tone,pause and so on)
    Therefore I have created a sleeper in the .h file

    class Sleeper : public QThread
    {
    public:
        static void usleep(unsigned long usecs){QThread::usleep(usecs);}
        static void msleep(unsigned long msecs){QThread::msleep(msecs);}
        static void sleep(unsigned long secs){QThread::sleep(secs);}
    };
    

    next I have created a slider and connected its output to a variable:

    
    
       m_sleepSlider = new QSlider(Qt::Horizontal);
        connect(m_sleepSlider, SIGNAL(valueChanged(int)), this, SLOT(rpmChanged(int)));
        volumeBox->addWidget(m_volumeLabel);
        volumeBox->addWidget(m_volumeSlider);
         volumeBox->addWidget(m_sleepSlider);
    

    the slot:

    void AudioTest::rpmChanged(int value)
    {
        if (m_audioOutput)
            drehzahl=m_sleepSlider->value();
    }
    

    and now I want to create a for-loop that ihave a tone with 17 interupts.Where can I place this loop. Here it is not working:

    void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate)
    {for (int i=0;i>=17;i++){
        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
    
        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);
                }
                Sleeper::msleep(drehzahl);
                  }
    
                ptr += channelBytes;
                length -= channelBytes;
            }
            ++sampleIndex;
        }
    }
    

  • Lifetime Qt Champion

    Hi,

    The rpmChangedslot as written does nothing.

    Since you know the exact length of what you want to produce here, why not generate the full audio sample and then play it ?


  • Moderators

    @Leopold Instead of using a thread and a loop you could simply use a QTimer.



  • @Leopold said in audiooutput:

       }
            Sleeper::msleep(drehzahl);
              }
    

    the rpmChanged sets the variable "drehzahl" and so i want to change the length of the pauses.


  • Qt Champions 2017

    @Leopold

    If you sleep in the main thread of an event-driven program, then you most likely don't get the result you expect.

    Better use a QTimer as @jsulm suggested.



  • You are right,
    i have set a qtimer in genarateData now , but now the app does not start at all.
    And yes qtimer wouldbe much easier.I would like to build a metronom out of this example.But like i said i do not completely understand the code.There is no comment to the code.Where can i place the loop and the timer.If i have an example for one interrupt i think i can extent to what I want.Or does anybody know the code for a programmable metronom?


  • Moderators

    @Leopold You don't need any loop. Just set time out interval in QTimer correctly (to achieve needed frequency).



  • @jsulm ,
    hi, i do not think that I can solve it over the frequency.In the end state , i want to regulate the length of the pause and have an additional pause after 17 tones.Then I want the ability to set the anount of tones ( x instead of 17) and then regulate to which channel these tones will be output.
    for3 tones: tone,pause,tone,pause,tone,pause,pause and the same loop again.
    volume slider for volume,
    rpmslider for length of timer timer.start(rpmslider->volume(),this)
    tickslider for the amount of tones(x)



  • Nobody here who can explain the app?


  • Lifetime Qt Champion

    There are several possibilities. You can use a QTimer for the interval between two tones, increment a counter each time you play it up to 17 (or in your case the variable you'll use to be able to set the number you want). As for the tone itself, like I suggested before you can build a QByteArray containing the audio data you need to send and the send it to the output.

    As for channel selection, what do you have in mind ?



  • "As for channel selection, what do you have in mind ?"
    On one channel i want the sequenz with a doble pause after 17 tones and on the second channel (stereo) i want the sequenz with only tones and pauses.



  • @SGaist said in audiooutput:

    You can use a QTimer for the interval between two tones,

    this is what I want to to but i can not figure out where to set the loop. When I try to debug the programm it runs for ever in background but never reaches the return app.exec in main.


  • Lifetime Qt Champion

    The you have to build your stereo data accordingly.

    Start your QTimer when you want to start sending data or rather after you sent your first data to QAudioOutput.

    app.exec() will return either when you close the last window of your application or call QApplication::quit from e.g. a menu action.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.