• Как правильно проиграть wav файл в qt?

    @Smosia Автор вопроса
    @DancingOnWater Вернулся к проблеме. timerEvent не устраивает.

    Для чего я хочу использовать луп - если его не вызвать, то цикл с write() выполнится без задержек и не будет звука. Он просто почти за секунду запишет все данные в аудиобуфер и ни чего не произойдет. С помощью лупа я хочу сделать задержку. чтоб аудио устройство успело проиграть все что я в него записал.

    Я заменял сигнал QIODevice::bytesWritten() на сигнал QAudioOutput::stateChanged(). Он вызывается когда аудио устройство меняет свое состояние. И все тогда работает, но присутствует крохотная задержка между шагами цикла (видимо возникает из-за смены состояния), которая порождает задержки в звуке.

    По поводу 1 пункта. Сигнал bytesWritten() не вызывается вообще.
  • Как правильно проиграть wav файл в qt?

    @Smosia Автор вопроса
    @DancingOnWater спасибо за советы, но так и не разобрался. Поэтому отказался от слотов и реализовал проигрывание через timerEvent.
  • Как правильно проиграть wav файл в qt?

    @Smosia Автор вопроса
    @DancingOnWater Я хочу с помощью лупа дождаться завершения проигрывания того, что я записал в буфер. И, таким образом, проиграть весь wav файл посекундно.
    Я реализовал то, что я хотел через TimerEvent, который просто вызывается каждую секунду и делает write в QIODevice, но меня это не устроило. Таймер не может мне гарантированно дать 1 секунду, и из-за этого появлялись задержки в воспроизведении.
  • Как правильно проиграть wav файл в qt?

    @Smosia Автор вопроса
    Это из заголовка:
    QFile wavFile;
        QAudioFormat m_fileFormat;
        QAudioOutput * m_audioOutput;
        QIODevice * m_output;


    Сам код:
    #include "wavefile.h"
    #include <QByteArray>
    #include <QtEndian>
    #include <QEventLoop>
    #include <QObject>
    
    typedef struct WAV_HEADER
    {
        char       RIFF[4];        // RIFF Header      Magic header
        quint32    ChunkSize;      // RIFF Chunk Size
        char       WAVE[4];        // WAVE Header
        char       fmt[4];         // FMT header
        quint32    Subchunk1Size;  // Size of the fmt chunk
        quint16    AudioFormat;    // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
        quint16    NumOfChan;      // Number of channels 1=Mono 2=Sterio
        quint32    SamplesPerSec;  // Frequency in Hz
        quint32    bytesPerSec;    // bytes per second
        quint16    blockAlign;     // 2=16-bit mono, 4=16-bit stereo Количество байт для одной выборки, включая все каналы.
        quint16    bitsPerSample;  // Number of bits per sample Так называемая "глубина" или точность звучания. 8 бит, 16 бит и т.д.
        char       Subchunk2ID[4]; // "data"  string
        quint32    Subchunk2Size;  // Sampled data length
    } wav_hdr;
    
    bool WaveFile::open(const QString &FileName)
    {
        wavFile.setFileName(FileName);
        return wavFile.open(QIODevice::ReadOnly) && readHeader();
    }
    
    bool WaveFile::readHeader()
    {
        wavFile.seek(0);
        wav_hdr wavHeader;
        int headerSize = sizeof(wav_hdr);
        wavFile.read((char *)&wavHeader, headerSize);
    
        if ((memcmp(&wavHeader.RIFF, "RIFF", 4) == 0
            || memcmp(&wavHeader.RIFF, "RIFX", 4) == 0)
            && memcmp(&wavHeader.WAVE, "WAVE", 4) == 0
            && memcmp(&wavHeader.fmt, "fmt ", 4) == 0
            && (wavHeader.AudioFormat == 1 || wavHeader.AudioFormat == 0))
        {
            wavHeader.Subchunk2Size=qFromBigEndian<quint32>(wavHeader.Subchunk2Size);
            int bps = wavHeader.bitsPerSample;
            m_fileFormat.setChannelCount(wavHeader.NumOfChan);
            m_fileFormat.setCodec("audio/pcm");
            m_fileFormat.setSampleRate(wavHeader.SamplesPerSec);
            m_fileFormat.setSampleSize(wavHeader.bitsPerSample);
            m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
            if (memcmp(&wavHeader.RIFF, "RIFF", 4) == 0)
                m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
            else
                m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
    
            //получаю указатель на системное аудио устройство, на которое потом буду write
            m_audioOutput = new QAudioOutput(m_fileFormat);
            m_output=m_audioOutput->start();
    
            QByteArray buffer;
            QEventLoop loop;
            QObject::connect(m_output, SIGNAL(bytesWritten(qint64)), &loop, SLOT(quit()));
    
            //кол-во секунд в файле
            int seconds = wavHeader.Subchunk2Size/wavHeader.SamplesPerSec;
            for (int i = 0; i < seconds; i++)
            {
                //читаю в буфер 1 секунду
                buffer = wavFile.read(wavHeader.bytesPerSec);
                m_output->write(buffer.data(), buffer.size());
                loop.exec();
            }
    
            return true;
        }
        return false;
    }


    Я запускаю луп, для того чтобы успел проиграться кусочек который лежит в микшере. Сигнал bytesWritten(qint64) - это сигнал QIODevice, и он вызывается тогда, когда на на устройство были записаны данные. Но он не вызывается. Программа повисает в лупе. И проигрывается только 1 нота.