Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.209.209.246] |
|
Сообщ.
#1
,
|
|
|
Приветствую всех
Перерыл всю документацию, никак не могу разобраться где накосячил Задача - воспроизвести mp3 загруженный в QByteArray. Все работает..., но только один раз. При попытке воспроизвести другой mp3, воспроизводится первый. #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_ #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(); } } Может кто встречался с таким зверем - ткните носом, что не так |
Сообщ.
#2
,
|
|
|
Цитата Radik @ void AudioPlayer::play(const QString &fileName) { m_audioFile = new QFile(fileName); this->play(m_audioFile); } что-то я не вижу для play сигнатуры с QFile. что тут вообще вызывается? плюс тут лик. |
Сообщ.
#3
,
|
|
|
Цитата _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 |
Сообщ.
#4
,
|
|
|
Цитата Radik @ Все работает..., но только один раз. При попытке воспроизвести другой mp3, воспроизводится первый. А там этот буфер, случайно, не асинхронно проигрывается? Попробуй проверить OpenMode непосредственно перед вызовом setBuffer |
Сообщ.
#5
,
|
|
|
Цитата Олег М @ А там этот буфер, случайно, не асинхронно проигрывается? Попробуй проверить OpenMode непосредственно перед вызовом setBuffer В этом случае работал бы play(const QString &fileName). На мой взгляд три "скользких места": 1. Не очищается m_audioOutput или m_outputData. 2. Нужен "некий сброс" m_audioDecoder в исходное состояние. Пробовал переписать 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. Может быть ноги растут из m_audioDecoder->setSourceDevice(inputDevice); Вероятнее всего логическая ошибка в использовании QAudioOutput и/или QAudioDecoder, хотя test::play(QByteArray* testData) { delete m_aydioPlayer; m_aydioPlayer = new AudioPlayer(/* все что нужно конструктору */); m_aydioPlayer->play(testData); } первое время работает правильно, но через 20-30 вызовов ругается в консоль на неверное устройство |
Сообщ.
#6
,
|
|
|
Сам же отвечу на свой вопрос:
проблема в m_audioDecoder->setSourceDevice(inputDevice); т.к. QIODevice создается на основе членов класса, реально "переназначение" не делается. Вставил костыль в виде m_audioDecoder->setSourceDevice(NULL); if(!inputDevice->isOpen()) inputDevice->open(QIODevice::ReadOnly); m_audioDecoder->setSourceDevice(inputDevice); и все волшебным образом заработало |