Reputation: 106
I am developing an application in which i have a timeline which represents a song and I can put some effects to it. By moving the effect the song should start playing from specific time. I tried to use QMediaPlayer and that would be fine but when I move the effect, playback doesnt start immediately and that is the problem. There is just a very little delay but it is a problem in this case. I tried to look for the answers and I found some topics about low latency audio. I tried to implement Portaudio but I am pretty lost using it and even when I dont know if that would help.
Can somebody please give me some advice what should I use or what should I focus on?
Thank you.
TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
{
m_mediaPlayer = new QMediaPlayer(NULL, QMediaPlayer::LowLatency);
m_mediaPlayer->setMedia(QUrl::fromLocalFile("/Users/simonvaros/Desktop/hudba.wav"));
m_effect = QRect(0, 0, 100, height());
m_grab = false;
m_effectWidth = m_effect.width();
m_dif = 0;
m_pos = 0;
m_lastTime = QTime::currentTime();
}
void TimelineWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter p (this);
QPen pen = QPen();
QRect outline = QRect(0, 0, width() - 1, height() - 1);
p.setPen(pen);
p.setBrush(QBrush(QColor("white")));
p.drawRect(outline);
p.setBrush(QBrush(QColor("red")));
p.drawRect(m_effect);
}
void TimelineWidget::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
m_grab = false;
}
void TimelineWidget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
int pos = event->pos().x();
if (pos > m_effect.x() && pos < m_effect.x() + m_effect.width())
{
m_grab = true;
m_dif = pos - m_effect.x();
}
}
void TimelineWidget::mouseMoveEvent(QMouseEvent *event)
{
QWidget::mouseMoveEvent(event);
if (m_grab)
{
m_pos = event->pos().x();
m_effect.setX(m_pos - m_dif);
m_mediaPlayer->setPosition((double)(m_pos / width()) * m_mediaPlayer->duration());
m_mediaPlayer->play();
m_effect.setWidth(m_effectWidth);
}
repaint();
}
#include <QWidget>
#include <QMediaPlayer>
class TimelineWidget : public QWidget
{
Q_OBJECT
public:
explicit TimelineWidget(QWidget *parent = nullptr);
private:
void paintEvent(QPaintEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
QMediaPlayer *m_mediaPlayer;
QRect m_effect;
bool m_grab;
int m_effectWidth;
int m_dif;
double m_pos;
signals:
public slots:
};
Upvotes: 1
Views: 1066
Reputation: 4602
First, invoking the QMediaPlayer with "LowLatency", is not meant for music, it is only for beeps, ringtones .. this is stated in QT documentation.
QMediaPlayer::LowLatency | 0x01 | The player is expected to be used with simple audio formats, but playback should start without significant delay. Such playback service can be used for beeps, ringtones, etc.
So you need to instantiate with QMediaPlayer::StreamPlayback
Here is code sample how to invoke QMediaPlayer from a buffer:
player = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
QFile file("/Users/simonvaros/Desktop/hudba.wav");
file.open(QIODevice::ReadOnly);
QByteArray *ba = new QByteArray();
ba->append(file.readAll());
QBuffer *buffer = new QBuffer(ba);
buffer->open(QIODevice::ReadOnly);
buffer->reset(); // same as buffer.seek(0);
qDebug() << "Buffer size:" << buffer->size(); // is the file loaded
player->setMedia(QMediaContent(), buffer);
player->play();
Upvotes: 1