pan y pitchs faders horizontales, funciona varias instancias con

multidispositivo y patcheable en jack.
This commit is contained in:
snt 2024-05-10 20:03:14 +02:00
parent 7631e54d51
commit 103a33820e
12 changed files with 188 additions and 105 deletions

View file

@ -46,11 +46,11 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
m_progressTime = new QTimeEdit;
m_progressTime->setToolTip("Current Time");
m_progressTime->setObjectName("Current Time");
m_progressTime->setDisplayFormat("mm:ss:zz");
m_progressTime->setDisplayFormat("mm:ss:zzz");
m_progressTime->setReadOnly(true);
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
m_progressTime->setMinimumWidth(80);
m_progressTime->setMaximumWidth(80);
//m_progressTime->setMaximumWidth(80);
m_progressTime->setFocusPolicy(Qt::NoFocus);
m_progressTime->setAlignment(Qt::AlignHCenter);
m_progressTime->setContentsMargins(0,0,0,0);
@ -68,22 +68,22 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
status->addWidget(m_progressTime);
status->addWidget(m_totalTimeValue);
layout->addLayout(status);
QHBoxLayout *volumeBox = new QHBoxLayout;
m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL);
volumeBox->addWidget(m_volume);
connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
QVBoxLayout *volumeBox = new QVBoxLayout;
m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL);
volumeBox->addWidget(m_pitch);
connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int)));
m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL);
volumeBox->addWidget(m_pan);
connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int)));
m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL);
volumeBox->addWidget(m_pitch);
m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL);
volumeBox->addWidget(m_volume);
connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
volumeBox->setSpacing(0);
volumeBox->setContentsMargins(0, 0, 0, 0);
connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int)));
layout->addLayout(volumeBox);
layout->setAlignment(Qt::AlignHCenter);
layout->setSpacing(0);
layout->setContentsMargins(2, 2, 2, 2);
layout->setContentsMargins(1, 1, 1, 1);
this->setLayout(layout);
}
@ -113,13 +113,17 @@ void AudioLayerWidget::toggleSuspendResume()
switch (m_status) {
case Status::PlayingLoop:
case Status::PlayingOnce:
case Status::PlayingFolder:
case Status::PlayingFolderLoop:
case Status::PlayingFolderRandom:
m_oldStatus = m_status;
this->setPlaybackStatus(Status::Paused);
emit uiPlaybackChanged(m_layer, Status::Paused);
break;
case Status::Paused:
case Status::Stopped:
this->setPlaybackStatus(Status::PlayingLoop);
emit uiPlaybackChanged(m_layer, Status::PlayingLoop);
this->setPlaybackStatus(m_oldStatus);
emit uiPlaybackChanged(m_layer, m_oldStatus);
case Status::Iddle:
break;
}
@ -174,10 +178,9 @@ void AudioLayerWidget::setMediaFile(QString file)
void AudioLayerWidget::setPlaybackStatus(Status s)
{
Status status = static_cast<Status>(s);
m_suspendResumeButton->blockSignals(true);
m_status = status;
m_suspendResumeButton->setText(StatusStr[status]);
m_status = s;
m_suspendResumeButton->setText(StatusStr[s]);
m_suspendResumeButton->blockSignals(false);
}

View file

@ -21,6 +21,7 @@ public:
private:
Status m_status;
Status m_oldStatus;
int m_layer;
QPushButton *m_suspendResumeButton;
ClickableLabel *m_fileValue;

View file

@ -5,7 +5,8 @@ AudioWidget::AudioWidget(QWidget *parent) :
QWidget(parent)
, m_layout(new QHBoxLayout())
{
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
m_layers = Settings::getInstance()->getLayersNumber();
for (uint i= 0; i < m_layers; i++ ) {
AudioLayerWidget *alw = new AudioLayerWidget(this, i);
m_layout->insertWidget(i, alw);
connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SIGNAL(uiSliderChanged(int, Slider, int)));
@ -64,7 +65,7 @@ void AudioWidget::cursorChanged(int layer, float cursor)
void AudioWidget::refreshUi()
{
for (int i = 0; i < MAX_LAYERS; i++)
for (uint i = 0; i < m_layers; i++)
{
if (m_layerUpdate[i].updated) {
QLayoutItem * const item = m_layout->itemAt(i);

View file

@ -18,6 +18,7 @@ private:
QHBoxLayout *m_layout;
layerData m_layerUpdate[MAX_LAYERS];
QTimer *m_refreshUi;
uint m_layers;
public slots:
void volChanged(int layer, float vol);

View file

@ -7,7 +7,7 @@
#define DEFAULT_FILE "lms-audio.xlm"
#define MAX_LAYERS 4
#define MAX_AUDIODEVICES 8
#define UI_REFRESH_TIME 66
#define UI_REFRESH_TIME 100
#define FADE_TIME 25 // DMX Frame time, 40 fps, avoid clicks
struct dmxSetting {
@ -32,12 +32,12 @@ static const char* StatusStr[] =
{
"Stop",
"Pause",
"Playing One",
"Playing One Loop",
"Play One",
"Play One Loop",
"Iddle",
"Playing Folder",
"Playing Folder Loop",
"Playing Folder Random",
"Play Folder",
"Play Folder Loop",
"Play Folder Rand",
0x0
};

View file

@ -122,7 +122,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
#ifndef NOGUI
if (m_ui) {
m_lmsUi->m_aw->playbackChanged(layer, s);
//m_lmsUi->m_aw->cursorChanged(layer, m_mae.getCursor(layer));
m_played.clear();
m_played.append(m_ola->getValue(layer, DMX_FILE));
}
#endif
}
@ -153,8 +154,6 @@ void libreMediaServerAudio::refreshUi() {
m_updateUi[i][3] = -1;
}
if (m_mae.getAtEnd(i)) {
if (m_played.isEmpty())
m_played.append(m_ola->getValue(i, DMX_FILE));
if (m_currentStatus[i] == Status::PlayingOnce) {
m_currentStatus[i] = Status::Stopped;
}

View file

@ -85,7 +85,7 @@ ma_result MiniAudioEngine::startContext()
resourceManagerConfig = ma_resource_manager_config_init();
resourceManagerConfig.decodedFormat = ma_format_f32; /* ma_format_f32 should almost always be used as that's what the engine (and most everything else) uses for mixing. */
resourceManagerConfig.decodedChannels = 0;
resourceManagerConfig.decodedSampleRate = ma_standard_sample_rate_48000;
resourceManagerConfig.decodedSampleRate = ma_standard_sample_rate_44100;
resourceManagerConfig.jobThreadCount = 4;
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
if (result != MA_SUCCESS) {
@ -129,6 +129,7 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
result = ma_sound_init_from_file(&engine, file, \
MA_SOUND_FLAG_NO_SPATIALIZATION \
| MA_SOUND_FLAG_DECODE \
| MA_SOUND_FLAG_STREAM \
/*| MA_SOUND_FLAG_NO_PITCH \*/
, NULL, NULL, &m_currentSound[layer]);
if (result != MA_SUCCESS)
@ -144,22 +145,15 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
float MiniAudioEngine::getDuration(int layer)
{
ma_result result;
ma_uint64 lengthInPCMFrames;
ma_uint32 sampleRate;
float ret;
if (m_mediaLoaded[layer] == false)
return MA_DOES_NOT_EXIST;
result = ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &lengthInPCMFrames);
result = ma_sound_get_length_in_seconds(&m_currentSound[layer], &ret);
if (result != MA_SUCCESS) {
return result;
}
result = ma_sound_get_data_format(&m_currentSound[layer], NULL, NULL, &sampleRate, NULL, 0);
if (result != MA_SUCCESS) {
return MA_ERROR;
}
ret = 1000.0f * (lengthInPCMFrames / float(sampleRate));
return ret;
return (ret * 1000);
}
float MiniAudioEngine::getCursor(int layer)
@ -233,27 +227,25 @@ ma_result MiniAudioEngine::playbackChanged(int layer, Status status)
if (m_mediaLoaded[layer] == false)
return MA_DOES_NOT_EXIST;
bool loop = false;
switch (status) {
case Status::Paused:
result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
break;
case Status::Stopped:
result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
result = this->seekToCursor(layer, m_currentLayerValues[layer].cursor);
break;
case Status::PlayingLoop:
ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
ma_sound_set_looping(&m_currentSound[layer], true);
result = ma_sound_start(&m_currentSound[layer]);
break;
loop = true;
case Status::PlayingOnce:
case Status::PlayingFolder:
case Status::PlayingFolderLoop:
case Status::PlayingFolderRandom:
ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
ma_sound_set_looping(&m_currentSound[layer], false);
ma_sound_set_looping(&m_currentSound[layer], loop);
result = ma_sound_start(&m_currentSound[layer]);
break;
//this->volChanged(layer, m_currentLayerValues[layer].vol); // glitch when seek to cursor, how flush the audio buffer?
default:
break;
}
@ -273,8 +265,7 @@ ma_result MiniAudioEngine::seekToCursor(int layer, int cursor)
if (result != MA_SUCCESS) { return result; }
start = (cursor * end) / 65025;
result = ma_sound_seek_to_pcm_frame(&m_currentSound[layer], start);
//if (result != MA_SUCCESS) { return result; }
//result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end);
//result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end); // this do nothing here, it must be done after set_looping or start?
return (result);
}

View file

@ -1,11 +1,15 @@
#ifndef MINIAUDIOENGINE_H
#define MINIAUDIOENGINE_H
#define MA_ENABLE_ONLY_SPECIFIC_BACKENDS 1
#define MA_ENABLE_JACK 1
#define MA_NO_GENERATION 1
#define MA_DEBUG_OUTPUT 1
#define MA_DISABLE_PULSEAUDIO
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include "defines.h" // MAX_LAYERS
#include <QDebug> // prints messages
#define MA_DEBUG_OUTPUT
class MiniAudioEngine
{

View file

@ -1,5 +1,17 @@
#include "slidergroup.h"
#include <QCursor>
#include <QStyle>
DoubleSpinBoxClickable::DoubleSpinBoxClickable(QWidget *parent)
: QDoubleSpinBox{parent} {}
DoubleSpinBoxClickable::~DoubleSpinBoxClickable() {}
SliderClickDisable::SliderClickDisable(QWidget *parent)
: QSlider{parent} {}
SliderClickDisable::~SliderClickDisable() {}
SliderGroup::SliderGroup(QString name,
int min,
int max,
@ -7,42 +19,46 @@ SliderGroup::SliderGroup(QString name,
QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout;
QBoxLayout *layout;
if (decimals) {
layout = new QVBoxLayout;
slider.setOrientation(Qt::Vertical);
}
else {
layout = new QHBoxLayout;
slider.setOrientation(Qt::Horizontal);
slider.setMinimumHeight(10);
}
layout->setAlignment(Qt::AlignHCenter);
layout->setContentsMargins(0, 0, 0, 0);
//this->setMaximumWidth(40);
slider = new QSlider(Qt::Orientation::Vertical);
slider->setFocusPolicy(Qt::StrongFocus);
slider->setTickPosition(QSlider::TicksBothSides);
slider->setTickInterval((max - min) / 11);
slider->setMinimumHeight(0);
slider->setSingleStep(1);
slider->setRange(min, max);
slider->setValue(0);
slider->setMinimumWidth(50);
slider->setToolTip(name);
slider->setStyleSheet("QSlider {"
slider.setFocusPolicy(Qt::StrongFocus);
slider.setTickPosition(QSlider::TicksBothSides);
slider.setTickInterval((max - min) / 11);
slider.setMinimumHeight(0);
slider.setSingleStep(1);
slider.setRange(min, max);
slider.setValue(0);
slider.setMinimumWidth(50);
slider.setToolTip(name);
slider.setStyleSheet("QSlider {"
"border: 1px solid #5a4855;"
"margin: 0px;"
"height: 200px;"
"width: 50px;}"
"margin: 0px;}"
);
slider->setContentsMargins(0, 0, 0, 0);
valueBox = new QDoubleSpinBox();
valueBox->setFocusPolicy(Qt::NoFocus);
valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
valueBox->setMinimumWidth(50);
valueBox->setRange(min, max);
valueBox->setValue(0);
valueBox->setDecimals(decimals);
valueBox->setObjectName(name);
valueBox->setToolTip(name);
valueBox->setAlignment(Qt::AlignHCenter);
valueBox->setContentsMargins(0, 0, 0, 0);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
//connect(slider, SIGNAL(mousePressEvent(QMouseEvent)), this, SLOT(mousePressEvent(QMouseEvent *)));
layout->addWidget(slider);
layout->addWidget(valueBox);
slider.setContentsMargins(0, 0, 0, 0);
valueBox.setFocusPolicy(Qt::NoFocus);
valueBox.setButtonSymbols(QAbstractSpinBox::NoButtons);
valueBox.setMinimumWidth(50);
valueBox.setRange(min, max);
valueBox.setValue(0);
valueBox.setDecimals(decimals);
valueBox.setObjectName(name);
valueBox.setToolTip(name);
valueBox.setAlignment(Qt::AlignHCenter);
valueBox.setContentsMargins(0, 0, 0, 0);
connect(&slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
connect(&valueBox, SIGNAL(enableSlider()), this, SLOT(enableSlider()));
layout->addWidget(&slider);
layout->addWidget(&valueBox);
this->setStyleSheet("border: 1px solid #5a4855;"
"width: 50px;"
"margin: 0px;"
@ -55,27 +71,19 @@ SliderGroup::SliderGroup(QString name,
void SliderGroup::sliderValueChanged(int value)
{
valueBox->blockSignals(true);
valueBox->setValue(value);
valueBox->blockSignals(false);
valueBox.blockSignals(true);
valueBox.setValue(value);
valueBox.blockSignals(false);
emit valueChanged(value);
};
void SliderGroup::setValue(float value)
{
slider->blockSignals(true);
valueBox->blockSignals(true);
if (int(value) != slider->value())
slider->setValue(value);
valueBox->setValue(value);
slider->blockSignals(false);
valueBox->blockSignals(false);
}
void SliderGroup::mousePressEvent(QMouseEvent* event) {
Q_UNUSED(event);
if (slider->isEnabled())
slider->setDisabled(true);
else
slider->setDisabled(false);
slider.blockSignals(true);
valueBox.blockSignals(true);
if (int(value) != slider.value())
slider.setValue(value);
valueBox.setValue(value);
slider.blockSignals(false);
valueBox.blockSignals(false);
}

View file

@ -5,6 +5,78 @@
#include <QDoubleSpinBox>
#include <QVBoxLayout>
#include <QSlider>
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>
/*
//slider->installEventFilter(new QSliderAnalyser);
class QSliderAnalyser
: public QObject
{
public:
QSliderAnalyser()
{
}
virtual ~QSliderAnalyser()
{
}
protected:
bool eventFilter(QObject* object, QEvent* event) override
{
if (event->type() == QEvent::MouseButtonPress) {
qDebug() << event->type() << object->objectName();
}
return QObject::eventFilter(object, event);
}
};*/
class DoubleSpinBoxClickable: public QDoubleSpinBox
{
Q_OBJECT
public:
DoubleSpinBoxClickable(QWidget *parent = 0);
~DoubleSpinBoxClickable();
signals:
void enableSlider();
protected:
void mousePressEvent ( QMouseEvent * event )
{
if (event->button() == Qt::LeftButton) {
qDebug() << "enabling slider";
emit(enableSlider());
}
event->accept();
}
};
class SliderClickDisable
: public QSlider
{
Q_OBJECT
public:
explicit SliderClickDisable(QWidget *parent = Q_NULLPTR);
~SliderClickDisable();
protected:
void mousePressEvent ( QMouseEvent * event )
{
if (event->button() == Qt::RightButton)
{
if (this->isEnabled()) {
qDebug() << "disabling slider";
this->setDisabled(true);
}
event->accept();
}
QSlider::mousePressEvent(event);
}
};
class SliderGroup : public QWidget
{
@ -25,10 +97,12 @@ public slots:
void sliderValueChanged(int value);
private:
QSlider *slider;
QDoubleSpinBox *valueBox;
SliderClickDisable slider;
DoubleSpinBoxClickable valueBox;
private slots:
void enableSlider() { slider.setEnabled(true); }
void mousePressEvent(QMouseEvent* event);
};
#endif