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_OBJECT

    public:
    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;
    }@


Log in to reply
 

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