На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: archimed7592
  
> Воспроизведение звука из QByteArray , Qt5, QAudioDecoder, QAudioOutput
    Приветствую всех

    Перерыл всю документацию, никак не могу разобраться где накосячил
    Задача - воспроизвести mp3 загруженный в QByteArray. Все работает..., но только один раз. При попытке воспроизвести другой mp3, воспроизводится первый.

    ExpandedWrap disabled
      #ifndef AUDUOPLAYER_H
      #define AUDUOPLAYER_H
       
      #include <QtCore/qglobal.h>
      #include <QAudioOutput>
      #include <QAudioDecoder>
      #include <QBuffer>
      #include <QFile>
       
       
      class AudioPlayer: public QObject
      {
          Q_OBJECT
       
      private:
          QAudioDeviceInfo* m_audioDevice;
          QAudioFormat* m_audioFormat;
          QAudioOutput* m_audioOutput;
          QAudioDecoder *m_audioDecoder;
          QBuffer *m_outputData;
          QBuffer* m_audioBuffer;
          
          QFile* m_audioFile;
       
      public slots:
          void OnBufferReady();
          void OnHandleStateChanged(QAudio::State state);
       
      public:
          AudioPlayer(const QAudioDeviceInfo &audioDevice, const QAudioFormat &format, QObject *parent = 0);
          ~AudioPlayer();
       
          void play(QIODevice* inputDevice);
          void play(QByteArray* data);
          void play(const QString &fileName);
       
      signals:
          void audioPlayerBusy();
          void audioPlayerFree();
      };
       
      #endif  // AUDUOPLAYER_H_


    ExpandedWrap disabled
      #include "AudioPlayer.h"
       
      AudioPlayer::AudioPlayer(const QAudioDeviceInfo &audioDevice, const QAudioFormat &format, QObject *parent): QObject(parent), m_audioFile(NULL)
      {
          m_audioDevice = new QAudioDeviceInfo(audioDevice);
          m_audioFormat = new QAudioFormat(format);
       
          m_audioOutput = new QAudioOutput(*m_audioDevice, *m_audioFormat, this);
          m_audioDecoder = new QAudioDecoder(this);
          m_audioBuffer = new QBuffer(this);
          m_outputData = new QBuffer(this);
       
          m_audioDecoder->setAudioFormat(*m_audioFormat);
       
          connect(m_audioOutput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(OnHandleStateChanged(QAudio::State)));
          connect(m_audioDecoder, SIGNAL(bufferReady()), this, SLOT(OnBufferReady()));
      }
       
      AudioPlayer::~AudioPlayer()
      {
      //  delete m_audioBuffer;
      }
       
      void AudioPlayer::play(const QString &fileName)
      {
          m_audioFile = new QFile(fileName);
          this->play(m_audioFile);
      }
       
      void AudioPlayer::play(QByteArray* data)
      {
          if(!data->isEmpty())
          {
              if (m_audioBuffer->isOpen())
                  m_audioBuffer->close();
              m_audioBuffer->setBuffer(data);
              play(m_audioBuffer);
          }
          else
          {
              emit audioPlayerFree();
          }
      }
       
      void AudioPlayer::play(QIODevice* inputDevice)
      {
          emit audioPlayerBusy();
       
          if(!inputDevice->isOpen())
              inputDevice->open(QIODevice::ReadOnly);
          m_audioDecoder->setSourceDevice(inputDevice);
          emit m_audioDecoder->start();
      }
       
      void AudioPlayer::OnBufferReady()
      {
          QAudioBuffer audioBuffer = m_audioDecoder->read();
          if (!audioBuffer.isValid())
              return;
       
          (m_outputData->buffer()).append(static_cast<const char*>(audioBuffer.data()), audioBuffer.byteCount());
          if(m_audioOutput->state() != QAudio::ActiveState)
          {
              m_outputData->open(QIODevice::ReadOnly);
              m_audioOutput->start(m_outputData);
          }
      }
       
      void AudioPlayer::OnHandleStateChanged(QAudio::State state)
      {
          if(state == QAudio::IdleState)
          {
              m_audioOutput->stop();
              m_audioBuffer->close();
              (m_outputData->buffer()).clear();
              delete m_audioFile;
              emit audioPlayerFree();
          }
      }


    Может кто встречался с таким зверем - ткните носом, что не так
      Цитата Radik @
      void AudioPlayer::play(const QString &fileName)
      {
          m_audioFile = new QFile(fileName);
          this->play(m_audioFile);
      }

      что-то я не вижу для play сигнатуры с QFile. что тут вообще вызывается? плюс тут лик.
        Цитата _lcf_ @
        Цитата Radik @
        void AudioPlayer::play(const QString &fileName)
        {
            m_audioFile = new QFile(fileName);
            this->play(m_audioFile);
        }

        что-то я не вижу для play сигнатуры с QFile. что тут вообще вызывается? плюс тут лик.

        Любой вызов AudioPlayer::play приведет к вызову AudioPlayer::play(QIODevice* inputDevice).
        В AudioPlayer::play(const QString &fileName) используется тот факт, что QFile наследник QIODevice. Фактически, этот метод нужен только для отладки, чтоб не цеплять базу в которой хранятся "образы" mp3
          Цитата Radik @
          Все работает..., но только один раз. При попытке воспроизвести другой mp3, воспроизводится первый.


          А там этот буфер, случайно, не асинхронно проигрывается? Попробуй проверить OpenMode непосредственно перед вызовом setBuffer
            Цитата Олег М @
            А там этот буфер, случайно, не асинхронно проигрывается? Попробуй проверить OpenMode непосредственно перед вызовом setBuffer

            В этом случае работал бы play(const QString &fileName).
            На мой взгляд три "скользких места":
            1. Не очищается m_audioOutput или m_outputData.
            2. Нужен "некий сброс" m_audioDecoder в исходное состояние. Пробовал переписать
            ExpandedWrap disabled
              void AudioPlayer::play(QIODevice* inputDevice)
              {
                  emit audioPlayerBusy();
               
                  delete m_audioDecoder;
                  m_audioDecoder = new QAudioDecoder(this);
                  m_audioDecoder->setAudioFormat(*m_audioFormat);
                  connect(m_audioDecoder, SIGNAL(bufferReady()), this, SLOT(OnBufferReady()));
               
                  if(!inputDevice->isOpen())
                      inputDevice->open(QIODevice::ReadOnly);
                  m_audioDecoder->setSourceDevice(inputDevice);
                  emit m_audioDecoder->start();
              }

            не помогло
            3. Может быть ноги растут из
            ExpandedWrap disabled
              m_audioDecoder->setSourceDevice(inputDevice);


            Вероятнее всего логическая ошибка в использовании QAudioOutput и/или QAudioDecoder, хотя
            ExpandedWrap disabled
              test::play(QByteArray* testData)
              {
                       delete m_aydioPlayer;
                       m_aydioPlayer = new AudioPlayer(/* все что нужно конструктору */);
                       m_aydioPlayer->play(testData);
              }

            первое время работает правильно, но через 20-30 вызовов ругается в консоль на неверное устройство
              Сам же отвечу на свой вопрос:
              проблема в

              ExpandedWrap disabled
                m_audioDecoder->setSourceDevice(inputDevice);


              т.к. QIODevice создается на основе членов класса, реально "переназначение" не делается. Вставил костыль в виде

              ExpandedWrap disabled
                m_audioDecoder->setSourceDevice(NULL);
                if(!inputDevice->isOpen())
                    inputDevice->open(QIODevice::ReadOnly);
                m_audioDecoder->setSourceDevice(inputDevice);


              и все волшебным образом заработало
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0343 ]   [ 16 queries used ]   [ Generated: 28.03.24, 22:26 GMT ]