Играйте аудиоданные с помощью QIODevice (Qt4.6 с VC ++)

Я работаю над проигрыванием аудио от аудиопотока с помощью VC ++ с библиотекой QtMultimedia. Так как я не слишком испытан с библиотеками QT, я запустил путем чтения в .wav файле и записи этого в буфер:

ifstream wavFile;
char* file = "error_ex.wav";
wavFile.open( file, ios::binary );

После этого я использовал .read ifstream (), функционируют и пишут все данные в буфер. После того, как буфер записан, он отослан аудио устройству записи, которое готовит его к QT:

QByteArray fData;

for( int i = 0; i < (int)data.size(); ++i )
{
    fData.push_back(data.at(i));
}

m_pBuffer->open(QIODevice::ReadWrite);
m_pBuffer->write( fData );

m_pBuffer->close();

(m_pBuffer имеет тип QBuffer),

После того как QBuffer готов, я пытаюсь играть буфер:

QIODevice* ioDevice = m_pAudioOut->start();
ioDevice->write( m_pBuffer->buffer() );

(m_pAudioOut имеет тип QAudioOutput),

Это приводит к маленькому поп от докладчиков, и затем он прекращает играть. Какие-либо идеи, почему?

Выполнение Visual Studio 2008 на Windows XP SP2, пользующемся библиотекой Qt 4.6.3.

11
задан Tony 6 August 2010 в 19:01
поделиться

2 ответа

Как указал Фрэнк, если вам нужно просто воспроизводить аудиоданные из файла, API более высокого уровня выполнит эту работу и упростит код вашего приложения. Фонон будет одним из вариантов; в качестве альтернативы проект QtMobility предоставляет API QMediaPlayer для высокоуровневых вариантов использования.

Учитывая, что вопрос конкретно касается использования QIODevice , однако, и что вы упомянули, что чтение из файла WAV было всего лишь вашим первоначальным подходом, я предполагаю, что вам действительно нужен потоковый API, т. Е. Один что позволяет клиенту управлять буферизацией, а не передавать это управление абстракции более высокого уровня, такой как Phonon.

QAudioOutput может использоваться в двух разных режимах, в зависимости от того, какая перегрузка start () вызывается:

  • «Режим извлечения»: void QAudioOutput :: start (QIODevice *)

    В этом режиме QAudioOutput будет извлекать данные из предоставленного QIODevice без дальнейшего вмешательства со стороны клиента. Это хороший выбор, если используется QIODevice, предоставляемый Qt (например, QFile , QAbstractSocket и т. Д.).

  • «Режим передачи»: QIODevice * QAudioOutput :: start ()

    В этом режиме клиент QAudioOutput должен передать режим аудиоустройству, вызвав QIODevice :: write () . Это нужно будет делать в цикле, например:

     qint64 dataRemaining = ...// присваиваем здесь правильное значение
    while (dataRemaining) {
    qint64 bytesWritten = audioOutput-> запись (буфер, dataRemaining);
    dataRemaining - = bytesWritten;
    buffer + = bytesWritten;
     // Затем ждем ненадолго
    }
    

    Как реализовано ожидание, будет зависеть от контекста вашего приложения - если звук записывается из выделенного потока, это может быть просто sleep () . В качестве альтернативы, если звук записывается из основного потока, вы, вероятно, захотите, чтобы запись запускалась QTimer .

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

Вы можете увидеть код, использующий оба режима в приложении examples / multimedia / audiooutput, которое поставляется с Qt.

12
ответ дан 3 December 2019 в 08:28
поделиться

Вы уверены, что используете правильный (высокоуровневый) API? Было бы странно, если бы вам пришлось обрабатывать потоки данных и буферизацию вручную. Кроме того, QIODevice::write() не обязательно записывает весь буфер, но может остановиться после n байт, как и POSIX write() (поэтому всегда нужно проверять возвращаемое значение).

Я пока не изучал QtMultimedia, но используя более зрелый Phonon, вывод видео и аудио работал просто отлично для меня в прошлом. Это работает так:

  1. Создаем объект Phonon::AudioOutput
  2. Создаем объект Phonon::MediaObject
  3. Phonon::createPath( mediaObject, audioObject )
  4. mediaObject->setCurrentSource( Phonon::MediaSource( path ) );
  5. mediaObject->play();

Есть также примеры в Qt.

2
ответ дан 3 December 2019 в 08:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: