Воспроизведение аудиоданных с использованием QIODevice (Qt4.6 с VC ++) - PullRequest
11 голосов
/ 06 августа 2010

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

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

После этого я использовал функцию ifread .read () и записал все данные в буфер. После того, как буфер записан, он отправляется на устройство записи звука, которое готовит его для 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 Studios 2008 в Windows XP SP2 с использованием библиотеки Qt 4.6.3.

Ответы [ 2 ]

12 голосов
/ 09 августа 2010

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

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

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

  • «Режим вытягивания»: void QAudioOutput::start(QIODevice *)

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

  • «Режим Push»: QIODevice* QAudioOutput::start()

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

    qint64 dataRemaining = ... // assign correct value here
    while (dataRemaining) {
        qint64 bytesWritten = audioOutput->write(buffer, dataRemaining);
        dataRemaining -= bytesWritten;
        buffer += bytesWritten;
        // Then wait for a short time
    }
    

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

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

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

2 голосов
/ 09 августа 2010

Вы уверены, что используете правильный (высокоуровневый) 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...