QAudioOutput & playback system with multiple audio outputs
-
Hi, I have an issue about QAudioOutput usage for playback program with multiple audio outputs (not for multichannel audio, standard .wav only) and mixing/crossfading/etc. features. So, I'm designing some kind of program that can play up to 3 different wav files at the same time to appropriate audio interfaces (audio cards). All works fine except one annoying thing: when I call QAudioOutput::stop() or QAudioOutput::suspend() function for active output1, it stops but I hear a single "pop" on another active output2, as if it has been suspended and resumed instantly. What can it be? Should I use QThread for each created AudioOutput?
P.S.: Also, I hear this "pop"-effect every time I call QAudioOutput::stop(), even if I use a single audio output.
-
Ok, if there's no any suggestion, I can share my test code for proper comprehension of what am I talking about. Here is the test code of my program, that written with trial and error method, as far I can see the QAudioOutput class is very cranky.
Here is my mainwindow.h:
@#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QThread>
#include <QTimer>
#include <QFile>
#include <QFileDialog>
#include <QByteArray>
#include <QTime>
#include <QSlider>
#include <QtMultimedia>
#include <QAudio>
#include <QAudioOutput>
#include <QAudioDeviceInfo>
#include <QVector>
#include "exitdialog.h"
#include "wavfile.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();private:
Ui::MainWindow *ui;
QAudioDeviceInfo q_device,q_device2,q_device3;
QAudioFormat q_format,q_format2,q_format3;
QAudioOutput *q_audio,*q_audio2,*q_audio3;
QFile *preFile,*preFile2,*nowPlayingFile,*nowPlayingFile2,*nowPlayingFile3;
QFileInfo inputFile,inputFile2,inputFile3,*OpenedFile,*OpenedFile2,outputFile;
QString errorMessage,errorMessage1,path;
QThread *infoThread;
QThread *infoThread2;
QThread *infoThread3;
QTimer *fadeTimer,*fadeTimer2,*fadeOutTimer,*fadeOutTimer2,*sfTimer,*sbTimer,*sfTimer2,*sbTimer2,*tTimer,*tTimer2,tTimer3;
qreal Volume,Volume2,Volume3;
QVector<QFile> Array;
bool autocross, autocross2;
exitDialog *d;private slots:
void keyReleaseEvent(QKeyEvent *);
void setDevice(int index);
void setDevice2(int index);
void setDevice3(int index);
void addFiles();
void addFiles2();
void addFiles3();
void replaceFile();
void replaceFile2();
void replaceFile3();
void addRow();
void addRow2();
void itemRemove();
void itemRemove2();
void itemRemove3();
void itemClear();
void itemClear3();
void loadList(QString fileName);
void loadList2();
void convertList();
void openPlaylist();
void saveList();
void saveList2();
void itemPlay();
void itemPlay2();
void itemStop();
void itemStop2();
void itemStop3();
void itemPause();
void itemPause2();
void itemUnPause();
void itemUnPause2();
void fadeOut();
void fadeOut2();
void fade();
void fadeIn();
void fadeIn2();
void fade2();
void crossFade();
void crossFade2();
void seekF();
void seekB();
void seekF2();
void seekB2();
void updatePos();
void updatePos2();
void updatePos3();
void setPos();
void setPos2();
void setVolume();
void setVolume2();
void f1();
void f2();
void f3();
void f4();
void f5();
void f6();
void aboutToClose();
void closeEvent(QCloseEvent *event);signals:
void StopFadeSignal();
void StopFadeSignal2();
void StopFadeOut();
void StopFadeOut2();
};#endif // MAINWINDOW_H
@ -
Here is the play and stop functions (I can't place here the whole mainwindow.cpp - it is too large.)
@void MainWindow::itemPlay()
{
if(ui->tableWidget->rowCount() == 0)
{
ui->label->setText(errorMessage1);
}
else
{
if(ui->tableWidget->currentItem()->text().isEmpty())
{
ui->label->setText(errorMessage);
}
else
{
if(q_audio->state() == QAudio::ActiveState)
itemStop();
ui->tableWidget->setCurrentCell(ui->tableWidget->currentRow(),0,QItemSelectionModel::SelectCurrent);
for(int i = 0;i < Array.size();++i)
{
inputFile.setFile(Array.at(i)->fileName());
if(inputFile.baseName() == ui->tableWidget->item(ui->tableWidget->currentRow(),0)->text())
nowPlayingFile = Array.at(i);
}
WavFile *wav = new WavFile(this);
wav->open(nowPlayingFile->fileName());
nowPlayingFile->seek(wav->headerLength());
q_format = wav->fileFormat();
delete q_audio;
q_audio = 0;
q_audio = new QAudioOutput(q_device,q_format,this);
inputFile.setFile(nowPlayingFile->fileName());
if(ui->tableWidget->item(ui->tableWidget->currentRow(),1)->text().isEmpty())
{
q_audio->setVolume(1.0);
}
else
{
ui->tableWidget->setCurrentCell(ui->tableWidget->currentRow(),1,QItemSelectionModel::SelectCurrent);
Volume = ui->tableWidget->currentItem()->text().toInt();
q_audio->setVolume(Volume / 100);
}
q_audio->start(nowPlayingFile);
ui->tableWidget->setCurrentCell(ui->tableWidget->currentRow(),0,QItemSelectionModel::SelectCurrent);
ui->tableWidget->scrollToItem(ui->tableWidget->currentItem(),QAbstractItemView::PositionAtTop);
ui->tableWidget_2->scrollToItem(ui->tableWidget_2->item(ui->tableWidget->currentRow(),0),QAbstractItemView::PositionAtTop);
qint64 size = nowPlayingFile->size() - wav->headerLength();
qint64 duration = (size / (q_format.sampleRate() * q_format.channelCount() * q_format.sampleSize() / 8));
ui->seekSlider->setMaximum(duration * 1000);
infoThread->start();
int totalminutes = (duration / 60) % 60;
int totalseconds = (duration) % 60;
QString qname = inputFile.baseName();
QTime totaltime(0, totalminutes, totalseconds, 0);
ui->label->setText(qname);
ui->totalTimeDisp->display(totaltime.toString("mm:ss"));
wav->close();
delete wav;
for(int x=0;x<ui->tableWidget->rowCount();x++)
{
ui->tableWidget->item(x,0)->setBackgroundColor(QColor::fromRgb(213, 213, 160, 255));
}
ui->tableWidget->item(ui->tableWidget->currentRow(),0)->setBackgroundColor(Qt::lightGray);
if(ui->tableWidget->currentRow() == ui->tableWidget->rowCount() - 1)
{
return;
}
else
{
if(ui->tableWidget->item(ui->tableWidget->currentRow()+1,0)->text().isEmpty())
{
ui->tableWidget_2->setFocus();
ui->tableWidget_2->setCurrentCell(ui->tableWidget->currentRow()+1,0,QItemSelectionModel::SelectCurrent);
ui->tableWidget_2->setFocus();
autocross = true;
}
else
{
ui->tableWidget->setCurrentCell(ui->tableWidget->currentRow() + 1,0,QItemSelectionModel::SelectCurrent);
ui->tableWidget->setFocus();
autocross = false;
}
}
}
}
}void MainWindow::itemStop()
{
infoThread->exit();
ui->lcdNumber->display("00:00");
ui->totalTimeDisp->display("00:00");
ui->label->clear();
ui->seekSlider->setSliderPosition(0);
q_audio->stop();
fadeTimer->stop();
fadeOutTimer->stop();
autocross = false;
}@