Я пытаюсь записать в буфер для QAudioOutput каждые 20 мс. Когда я пытаюсь выполнить этот код, я вижу, что размер процесса увеличивается примерно на 4-8 кБ в секунду. Я пытался найти какую-то функцию для очистки внутреннего буфера QIODevice или DAudioOuptut, но безуспешно.
Я использую Qt 5.2.1
В приведенном ниже примере написано только молчание (нули), но оно имеет тот же эффект:
#include <QLibraryInfo>
#include <QtCore/QCoreApplication>
#include <windows.h> // for Sleep
#include <QAudioOutput>
#include <QAudioDeviceInfo>
#include <QAudioFormat>
#include <array>
class QAudioOutput;
int main(int argc, char *argv[])
{
// Create QApplication
QCoreApplication app(argc, argv);
app.setApplicationName("Audiotest");
//Initialize device
QIODevice * _output;
QAudioDeviceInfo _device = QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat _format;
_format.setSampleRate(44100);
_format.setChannelCount(2);
_format.setSampleSize(16);
_format.setCodec("audio/pcm"); // This codec should be supported on all platforms and plugin implementation
_format.setByteOrder(QAudioFormat::LittleEndian);
_format.setSampleType(QAudioFormat::SignedInt);
if (!_device.isFormatSupported(_format)) {
printf("Default format not supported - trying to use nearest.\n");
_format = _device.nearestFormat(_format);
}
QAudioOutput * _audioOutput = new QAudioOutput(_device, _format);
_output = _audioOutput->start();
std::array<char, 32768> _buffer;
_buffer.fill(0);for (;;) {
const int periodSize = _audioOutput->periodSize();
const int chunks = _audioOutput->bytesFree() / periodSize;
for (int i = 0; i < chunks; ++i) {
const qint64 len = periodSize;
if (len && _output) {
_output->write(_buffer.data(), len);
}
if (len != periodSize) {
break;
}
}
Sleep(20);
}
return 0;
}
Когда ваш цикл работает, больше ничего не происходит. Ваш код должен быть асинхронным, и вы должны инвертировать поток управления. Реагируйте на уведомление устройства вывода звука о том, что оно обработало определенный интервал выборок.
Чтобы получить первое уведомление, вам нужно заправить устройство некоторыми данными.
// https://github.com/KubaO/stackoverflown/tree/master/questions/audio-37993427
#include <QtMultimedia>
#include <array>
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
auto device = QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
if (!device.isFormatSupported(format))
qFatal("Default format not supported");
QAudioOutput audioOutput{device, format};
auto output = audioOutput.start();
qDebug() << audioOutput.state();
std::array<char, 32768> buffer;
buffer.fill(0);
auto write = [&]{
qDebug() << "notify";
auto periodSize = audioOutput.periodSize();
auto chunks = audioOutput.bytesFree() / periodSize;
for (int i = 0; i < chunks; ++i) {
if (periodSize && output) {
auto len = output->write(buffer.data(), periodSize);
if (len != periodSize)
break;
}
}
};
audioOutput.setNotifyInterval(20);
QObject::connect(&audioOutput, &QAudioOutput::notify, write);
write();
return app.exec();
}
Не запускайте свой собственный цикл событий; вместо этого подключите QAudioOutput notify
подайте сигнал слоту в одном из ваших объектов QObject, и вызовите этот слот write () один раз. Сигнал уведомления будет передаваться всякий раз, когда QAudioOutput требуется больше аудиоданных для воспроизведения.
Все это будет происходить внутри QApplication :: exec (), которую вы должны вызывать (ближе к концу main ()), чтобы запустить цикл событий Qt вместо вас, а не свой собственный цикл for.