pan, pitch, loop
This commit is contained in:
parent
5d57eb705a
commit
ba9fcfadeb
12 changed files with 196 additions and 51 deletions
|
@ -13,6 +13,11 @@ v 0.1.3 (1/05/2024)
|
|||
- Ubuntu 22.04 jammy
|
||||
- Use SFML as audio engine
|
||||
- Qt 5.15.3
|
||||
- pan
|
||||
- pitch
|
||||
- loop
|
||||
- loop points
|
||||
- play offset
|
||||
|
||||
v 0.1.2 (12/08/2015)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
*******************************************************************************
|
||||
Libre Media Server Audio - An Open source Media Server.
|
||||
(c) Santiago Noreña 2014-2024 <libremediaserver@criptomart.net>
|
||||
http://git.criptomart.net/libremediaserver
|
||||
https://git.criptomart.net/libremediaserver
|
||||
*******************************************************************************
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
@ -11,7 +11,9 @@ You should have received a copy of the GNU General Public License along with thi
|
|||
0. Requisites
|
||||
- sudo apt-get install build-essential qmake-qt5 gcc g++ libtool libsfml-dev qtbase5-dev libqt5webkit5-dev qtwebengine5-dev
|
||||
- OLA https://www.openlighting.org/ola/linuxinstall/#Git
|
||||
-- ToDo: la instalación de OLA es un infierno, hay que empaquetarlo
|
||||
-- ToDo: la instalación de OLA es un infierno, hay que empaquetarlo o mirar si hay alguna lib de sACN
|
||||
|
||||
https://github.com/ETCLabs/sACN
|
||||
|
||||
1. Compiles
|
||||
$ qmake -spec linux-g++ -o Makefile libremediaserver-audio.pro
|
||||
|
|
|
@ -28,13 +28,19 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name):
|
|||
// status->addWidget(m_receiveDMX);
|
||||
status->addWidget(m_statusLabel);
|
||||
status->addWidget(m_statusValue);
|
||||
m_loopCheckLabel = new QLabel;
|
||||
m_loopCheckLabel->setText("Loop");
|
||||
m_loopCheck = new QCheckBox();
|
||||
connect(m_loopCheck, SIGNAL(stateChanged(int)), this, SLOT(loopChanged(int)));
|
||||
status->addWidget(m_loopCheckLabel);
|
||||
status->addWidget(m_loopCheck);
|
||||
layout->addLayout(status);
|
||||
|
||||
QHBoxLayout *folderLoaded = new QHBoxLayout;
|
||||
m_folderLabel = new QLabel;
|
||||
m_folderLabel->setText(FOLDER_LABEL);
|
||||
m_folderValue = new QLabel;
|
||||
m_folderValue->setMaximumWidth(150);
|
||||
m_folderValue->setMaximumWidth(200);
|
||||
folderLoaded->addWidget(m_folderLabel);
|
||||
folderLoaded->addWidget(m_folderValue);
|
||||
layout->addLayout(folderLoaded);
|
||||
|
@ -43,24 +49,42 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name):
|
|||
m_fileLabel = new QLabel;
|
||||
m_fileLabel->setText(FILE_LABEL);
|
||||
m_fileValue = new QLabel;
|
||||
m_fileValue->setMaximumWidth(150);
|
||||
m_fileValue->setMaximumWidth(200);
|
||||
fileLoaded->addWidget(m_fileLabel);
|
||||
fileLoaded->addWidget(m_fileValue);
|
||||
layout->addLayout(fileLoaded);
|
||||
|
||||
QHBoxLayout *volumeBox = new QHBoxLayout;
|
||||
QGridLayout *volumeBox = new QGridLayout;
|
||||
m_volumeLabel = new QLabel;
|
||||
m_volumeLabel->setText(tr(VOLUME_LABEL));
|
||||
m_volumeSlider = new QSlider(Qt::Horizontal);
|
||||
m_volumeSlider->setMinimum(0);
|
||||
m_volumeSlider->setMaximum(80);
|
||||
m_volumeSlider->setMaximum(90);
|
||||
m_volumeSlider->setSingleStep(1);
|
||||
connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
|
||||
volumeBox->addWidget(m_volumeLabel);
|
||||
volumeBox->addWidget(m_volumeSlider);
|
||||
volumeBox->addWidget(m_volumeLabel, 0, 0);
|
||||
volumeBox->addWidget(m_volumeSlider, 0, 1);
|
||||
m_panLabel = new QLabel;
|
||||
m_panLabel->setText("Pan");
|
||||
m_panSlider = new QSlider(Qt::Horizontal);
|
||||
m_panSlider->setMinimum(0);
|
||||
m_panSlider->setMaximum(255);
|
||||
m_panSlider->setSingleStep(1);
|
||||
connect(m_panSlider, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int)));
|
||||
volumeBox->addWidget(m_panLabel, 1, 0);
|
||||
volumeBox->addWidget(m_panSlider, 1, 1);
|
||||
m_pitchLabel = new QLabel;
|
||||
m_pitchLabel->setText("Pitch");
|
||||
m_pitchSlider = new QSlider(Qt::Horizontal);
|
||||
m_pitchSlider->setMinimum(0);
|
||||
m_pitchSlider->setMaximum(255);
|
||||
m_pitchSlider->setSingleStep(1);
|
||||
connect(m_pitchSlider, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int)));
|
||||
volumeBox->addWidget(m_pitchLabel, 2, 0);
|
||||
volumeBox->addWidget(m_pitchSlider, 2, 1);
|
||||
layout->addLayout(volumeBox);
|
||||
|
||||
QGridLayout *progressTime = new QGridLayout;
|
||||
QHBoxLayout *progressTime = new QHBoxLayout;
|
||||
m_progressTimeLabel = new QLabel;
|
||||
m_progressTimeLabel->setText(PROGRESS_TIME_LABEL);
|
||||
m_progressTime = new QTimeEdit;
|
||||
|
@ -68,19 +92,18 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name):
|
|||
m_progressTime->setDisplayFormat("h:mm:ss:zzz");
|
||||
m_progressTime->setReadOnly(true);
|
||||
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||
m_progressTime->setMaximumWidth(80);
|
||||
progressTime->addWidget(m_progressTimeLabel, 0 ,0);
|
||||
progressTime->addWidget(m_progressTime,0 ,1);
|
||||
|
||||
m_progressTime->setMaximumWidth(120);
|
||||
progressTime->addWidget(m_progressTimeLabel);
|
||||
progressTime->addWidget(m_progressTime);
|
||||
m_totalTimeLabel = new QLabel;
|
||||
m_totalTimeLabel->setText(TOTAL_TIME_LABEL);
|
||||
m_totalTimeValue = new QTimeEdit;
|
||||
m_totalTimeValue->setDisplayFormat("h:mm:ss:zzz");
|
||||
m_totalTimeValue->setReadOnly(true);
|
||||
m_totalTimeValue->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||
m_totalTimeValue->setMaximumWidth(80);
|
||||
progressTime->addWidget(m_totalTimeLabel,1 , 0);
|
||||
progressTime->addWidget(m_totalTimeValue, 1 ,1);
|
||||
m_totalTimeValue->setMaximumWidth(120);
|
||||
progressTime->addWidget(m_totalTimeLabel);
|
||||
progressTime->addWidget(m_totalTimeValue);
|
||||
layout->addLayout(progressTime);
|
||||
|
||||
QHBoxLayout *progressSlider = new QHBoxLayout;
|
||||
|
@ -100,7 +123,7 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name):
|
|||
|
||||
connect(m_watchDMX, SIGNAL(timeout()),
|
||||
this, SLOT(watchDMXExpired()));
|
||||
m_watchDMX->start(243);
|
||||
m_watchDMX->start(100);
|
||||
|
||||
m_music.setAttenuation(0);
|
||||
}
|
||||
|
@ -115,6 +138,21 @@ void AudioLayerWidget::volumeChanged(int value)
|
|||
m_music.setVolume(value);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::panChanged(int value)
|
||||
{
|
||||
m_music.setPosition((value - 128) / 32.0, 0, 0);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::pitchChanged(int value)
|
||||
{
|
||||
m_music.setPitch(qreal(value / 128.0 ));
|
||||
}
|
||||
|
||||
void AudioLayerWidget::loopChanged(int value)
|
||||
{
|
||||
m_music.setLoop(value);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::setVol(qreal vol)
|
||||
{
|
||||
m_music.setVolume(vol);
|
||||
|
@ -123,6 +161,22 @@ void AudioLayerWidget::setVol(qreal vol)
|
|||
m_volumeSlider->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::setPan(qreal pan)
|
||||
{
|
||||
m_music.setPosition(float((pan - 128) / 32.0), 0, 0);
|
||||
m_panSlider->blockSignals(true);
|
||||
m_panSlider->setValue(pan);
|
||||
m_panSlider->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::setPitch(qreal pitch)
|
||||
{
|
||||
m_music.setPitch(float(pitch / 128 ));
|
||||
m_pitchSlider->blockSignals(true);
|
||||
m_pitchSlider->setValue(pitch);
|
||||
m_pitchSlider->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::loadMedia(QString file)
|
||||
{
|
||||
if (m_currentMedia.compare(file) == 0 ) {
|
||||
|
@ -165,9 +219,13 @@ void AudioLayerWidget::durationChanged(qint64 dur)
|
|||
m_totalTimeValue->setTime(QTime::fromMSecsSinceStartOfDay(dur));
|
||||
}
|
||||
|
||||
void AudioLayerWidget::play()
|
||||
void AudioLayerWidget::play(bool loop)
|
||||
{
|
||||
m_music.play();
|
||||
m_music.setLoop(loop);
|
||||
m_loopCheck->blockSignals(true);
|
||||
m_loopCheck->setChecked(m_music.getLoop());
|
||||
m_loopCheck->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::pause()
|
||||
|
@ -202,6 +260,9 @@ void AudioLayerWidget::watchDMXExpired() {
|
|||
m_progressSlider->setValue(0);
|
||||
break;
|
||||
}
|
||||
//m_loopCheck->blockSignals(true);
|
||||
//m_loopCheck->setChecked(m_music.getLoop());
|
||||
//m_loopCheck->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::toggleSuspendResume()
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
/**
|
||||
* @brief play
|
||||
*/
|
||||
void play();
|
||||
void play(bool loop);
|
||||
|
||||
/**
|
||||
* @brief stop
|
||||
|
@ -58,6 +58,16 @@ public:
|
|||
*/
|
||||
void resume();
|
||||
|
||||
void setPan(qreal pan);
|
||||
|
||||
void setPitch(qreal pitch);
|
||||
|
||||
void setLoop(bool on);
|
||||
|
||||
//void setEntryPoint(qreal entry);
|
||||
|
||||
//void setEndPoint(qreal end);
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
|
@ -66,10 +76,13 @@ public slots:
|
|||
void toggleSuspendResume();
|
||||
|
||||
/**
|
||||
* @brief Conencted with the slider
|
||||
* @brief Connected with the slider
|
||||
* @param volume 0 -100 range
|
||||
*/
|
||||
void volumeChanged(int vol);
|
||||
void panChanged(int vol);
|
||||
void pitchChanged(int vol);
|
||||
void loopChanged(int vol);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -81,6 +94,15 @@ private:
|
|||
QLabel *m_volumeLabel;
|
||||
QSlider *m_volumeSlider;
|
||||
|
||||
QLabel *m_panLabel;
|
||||
QSlider *m_panSlider;
|
||||
|
||||
QLabel *m_pitchLabel;
|
||||
QSlider *m_pitchSlider;
|
||||
|
||||
QLabel *m_loopCheckLabel;
|
||||
QCheckBox *m_loopCheck;
|
||||
|
||||
QLabel * m_progressLabel;
|
||||
QSlider *m_progressSlider;
|
||||
|
||||
|
@ -96,7 +118,7 @@ private:
|
|||
QLabel * m_folderLabel;
|
||||
QLabel * m_folderValue;
|
||||
|
||||
QCheckBox *m_receiveDMX;
|
||||
//QCheckBox *m_receiveDMX;
|
||||
QTimer *m_watchDMX;
|
||||
|
||||
QString m_currentMedia;
|
||||
|
@ -125,6 +147,4 @@ private slots:
|
|||
void watchDMXExpired();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // AUDIOLAYERWIDGET_H
|
||||
|
|
|
@ -4,25 +4,24 @@
|
|||
|
||||
AudioMasterWidget::AudioMasterWidget(QWidget *parent) :
|
||||
QGroupBox(parent)
|
||||
, m_file(new QLabel)
|
||||
, m_folder(new QLabel)
|
||||
, m_vol(new QSlider)
|
||||
, m_mute(new QCheckBox)
|
||||
, m_status(new QLabel)
|
||||
//, m_file(new QLabel)
|
||||
//, m_folder(new QLabel)
|
||||
//, m_vol(new QSlider)
|
||||
//, m_mute(new QCheckBox)
|
||||
//, m_status(new QLabel)
|
||||
, m_receiveDMX(new QCheckBox)
|
||||
, m_watchDMX(new QTimer)
|
||||
{
|
||||
QVBoxLayout *vbox = new QVBoxLayout;
|
||||
// vbox->addWidget(status);
|
||||
// vbox->addWidget(vol);
|
||||
// vbox->addWidget(mute);
|
||||
//vbox->addWidget(m_status);
|
||||
//vbox->addWidget(m_vol);
|
||||
//vbox->addWidget(m_mute);
|
||||
m_receiveDMX->setText("Receiving DMX");
|
||||
vbox->addWidget(m_receiveDMX);
|
||||
this->setLayout(vbox);
|
||||
connect(m_watchDMX, SIGNAL(timeout()),
|
||||
this, SLOT(watchDMXExpired()));
|
||||
m_watchDMX->start(1000);
|
||||
|
||||
}
|
||||
|
||||
AudioMasterWidget::~AudioMasterWidget()
|
||||
|
|
|
@ -28,11 +28,11 @@ public slots:
|
|||
void updateWatchDMX();
|
||||
|
||||
private:
|
||||
QLabel *m_file;
|
||||
QLabel *m_folder;
|
||||
QSlider *m_vol;
|
||||
QCheckBox *m_mute;
|
||||
QLabel *m_status;
|
||||
//QLabel *m_file;
|
||||
//QLabel *m_folder;
|
||||
//QSlider *m_vol;
|
||||
//QCheckBox *m_mute;
|
||||
//QLabel *m_status;
|
||||
QCheckBox *m_receiveDMX;
|
||||
QTimer *m_watchDMX;
|
||||
|
||||
|
|
|
@ -37,12 +37,22 @@ void AudioWidget::volChanged(int layer, qreal vol) {
|
|||
|
||||
}
|
||||
|
||||
void AudioWidget::panChanged(int layer, qreal vol) {
|
||||
QLayoutItem * const item = layout->itemAt(layer);
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPan(vol);
|
||||
}
|
||||
|
||||
void AudioWidget::pitchChanged(int layer, qreal vol) {
|
||||
QLayoutItem * const item = layout->itemAt(layer);
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPitch(vol);
|
||||
}
|
||||
|
||||
void AudioWidget::playbackChanged(int layer, Status status)
|
||||
{
|
||||
QLayoutItem * const item = layout->itemAt(layer);
|
||||
switch (status) {
|
||||
case Playing:
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->play();
|
||||
case PlayingOnce:
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->play(false);
|
||||
break;
|
||||
case Stopped:
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->stop();
|
||||
|
@ -50,6 +60,9 @@ void AudioWidget::playbackChanged(int layer, Status status)
|
|||
case Paused:
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->pause();
|
||||
break;
|
||||
case PlayingLoop:
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->play(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -24,6 +24,8 @@ protected:
|
|||
static AudioWidget *getInstance();
|
||||
void mediaLoaded(int layer, QString media );
|
||||
void volChanged(int layer, qreal vol);
|
||||
void panChanged(int layer, qreal pan);
|
||||
void pitchChanged(int layer, qreal pitch);
|
||||
void playbackChanged(int layer, Status status);
|
||||
|
||||
private:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#define COPYRIGHT "(C) 2014-2024 Santi Norena lms@criptomart.net"
|
||||
#define LICENSE "GPL 3 License. See LICENSE.txt and credits.txt for details"
|
||||
|
||||
#define LAYERS_NUMBER 3
|
||||
#define LAYERS_NUMBER 4 // esto tiene que desaparecer
|
||||
|
||||
#define DEFAULT_FILE "lms-audio.xlm"
|
||||
|
||||
|
@ -59,9 +59,10 @@ struct MediaFolder {
|
|||
|
||||
enum Status
|
||||
{
|
||||
Stopped, ///< Sound is not playing
|
||||
Paused, ///< Sound is paused
|
||||
Playing ///< Sound is playing
|
||||
Stopped,
|
||||
Paused,
|
||||
PlayingOnce,
|
||||
PlayingLoop,
|
||||
};
|
||||
|
||||
#endif // DEFINES_H
|
||||
|
|
|
@ -9,13 +9,16 @@
|
|||
3 - Folder
|
||||
4 - File
|
||||
5 - Playback
|
||||
0-24 : Play. Reproduce desde el inicio del fichero.
|
||||
25-49: Stop.
|
||||
50-74: Resume. Reproduce desde el punto desde el que se paró, o desde el punto designado por Entry Point.
|
||||
0-24 : Play once.
|
||||
25-49: Stop. Returns to start of file.
|
||||
50-74: Pause. It keeps the time of reproductions.
|
||||
75-99: Play loop.
|
||||
6 - Control - Reservado, sin uso en este momento.
|
||||
7 - Volume Fine
|
||||
8 - Entry Point Coarse - Punto de entrada de reproducción.
|
||||
9 - Entry Point Fine - El valor de estos dos canales en centésimas de segundo.
|
||||
10 - Pan
|
||||
11 - Pitch
|
||||
*/
|
||||
|
||||
// ToDo: Tiene bastante sentido cambiar estos defines por un enum
|
||||
|
@ -30,7 +33,8 @@
|
|||
#define VOLUME_FINE 6
|
||||
#define ENTRY_POINT_COARSE 7
|
||||
#define ENTRY_POINT_FINE 8
|
||||
#define PITCH 9
|
||||
|
||||
#define LAYER_CHANNELS 4 // ToDo: esto tiene que desaparecer
|
||||
#define LAYER_CHANNELS 10
|
||||
|
||||
#endif // DMXPERSONALITY_H
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="address">
|
||||
<property name="geometry">
|
||||
|
@ -35,6 +38,35 @@
|
|||
<property name="accessibleDescription">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>497</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="universe_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>0</y>
|
||||
<width>67</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Universe</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="address_label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>0</y>
|
||||
<width>67</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Libre Media Server - A Media Server Sotfware for stage and performing
|
||||
|
||||
Copyright (C) 2012-2014 Santi Noreña libremediaserver@gmail.com
|
||||
Copyright (C) 2012-2024 Santi Noreña lms@criptomart.net
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -181,7 +181,10 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|||
AudioWidget::getInstance()->volChanged(layer, f / 655.35);
|
||||
break;
|
||||
case PAN:
|
||||
f = (float)value / 255;
|
||||
AudioWidget::getInstance()->panChanged(layer, value);
|
||||
break;
|
||||
case PITCH:
|
||||
AudioWidget::getInstance()->pitchChanged(layer, value);
|
||||
break;
|
||||
case PLAYBACK:
|
||||
if (value == 0)
|
||||
|
@ -189,7 +192,7 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|||
aux = value / 25;
|
||||
switch (aux) {
|
||||
case 0 :
|
||||
AudioWidget::getInstance()->playbackChanged(layer, Playing);
|
||||
AudioWidget::getInstance()->playbackChanged(layer, PlayingOnce);
|
||||
break;
|
||||
case 1 :
|
||||
AudioWidget::getInstance()->playbackChanged(layer, Stopped);
|
||||
|
@ -197,6 +200,9 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|||
case 2 :
|
||||
AudioWidget::getInstance()->playbackChanged(layer, Paused);
|
||||
break;
|
||||
case 3 :
|
||||
AudioWidget::getInstance()->playbackChanged(layer, PlayingLoop);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue