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 fileclass 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; } }
-
Hi,
The
rpmChanged
slot 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 ?
-
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? -
@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) -
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 ?
-
@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.
-
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. -
now I had some time to play with this topic again:
I'm still wondering where to set my loop.I did it here```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);
for (int i=0;i<17;i++)
{
m_audioOutput->stop();
connect(m_pushTimer, SIGNAL(timeout()), this, SLOT(update()));
m_pushTimer->start(1000);m_audioOutput->start(m_generator); } qreal initialVolume = QAudio::convertVolume(m_audioOutput->volume(), QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); m_volumeSlider->setValue(qRound(initialVolume * 100));
}
I can compile but when it comes to running, i get a sigsev error from system. -
With that loop you are connecting the timeout signal 17 time, why ?
You should also post your backtrace.
-
@SGaist said in audiooutput:
With that loop you are connecting the timeout signal 17 time, why ?
still the old problem, I want the rattling noise,then I'll continue to attapt the programm to my needs. I do not know where to place the loop.Could you have a look to the example programm and give me a hint?
-
Did you try my suggestion of pre-generating the complete audio sequence ?
-
no, if i generate a wav file, I can not change sequenzes while running.I could play wav.files with other means.There are complete programs for metronoms they are too big and nearly not changeable.There must be a possibility to change this small program to my needs.When I had a first look to it i thought its easy but now its a challenge. I have set the loop to different places but always get a sigsev error when app starts.