process double channels only once in each frame
This commit is contained in:
parent
63f25e8209
commit
32a1e5cb0c
11 changed files with 70 additions and 46 deletions
|
@ -16,6 +16,7 @@ v 0.2.0 Antigona (24/04/2024)
|
|||
+ Refactor AudioMasterWidget to AudioDMXReceptionWidget.
|
||||
+ mp3, flac, wav (mp3 has given some errors seeking cursor...).
|
||||
+ settings dialog not working, only read the conf file at startup.
|
||||
+ variable number of layers.
|
||||
|
||||
v 0.1.3 Unreleased (19/04/2024)
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ v 0.2.1
|
|||
- Play all medias found in folder consecutevily or random, with loop.
|
||||
- Play all medias, consecutevily and random, with loop.
|
||||
- mute/panic on layer.
|
||||
- number of layers configured in conf file, up to 256.
|
||||
- Master Bus Layer:
|
||||
- each layer will have one "Gain" prefader that acts in source, "Vol" in v 1.3.
|
||||
- each layer will have one volume dmx channel for each bus layer. One aux "Send" prefader.
|
||||
|
@ -44,11 +43,14 @@ v 0.2.1
|
|||
- dmx address + universe settings.
|
||||
- Keyboards strokes, load media files from ui.
|
||||
- Dar la opción clickeando en el widget de tiempo de poner una cuenta atrás en vez de hacia delante.
|
||||
- LOGs y entrada de comandos.
|
||||
- Logs, verbosity, timestamp.
|
||||
- Bufgix: depurar errores cuando no carga la librería de medias, cambia el númmero de capas, cambia el universo, etc.
|
||||
- New control mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH
|
||||
- Vumeter or indicator about audio output in layer and master.
|
||||
- SettingsDialog.
|
||||
- Load/save conf file.
|
||||
- ¿stop offset? is it needed?
|
||||
- decouple MiniAudioEngine from AudioWidget, starts whith no gui or with gui in a dedicated thread.
|
||||
- decouple MiniAudioEngine from AudioWidget, starts whith no gui or with audio in a dedicated thread.
|
||||
- olathread, send double channels only once for each dmx frame buffer.
|
||||
- New Status "Iddle" in playbacks if is not loaded.
|
||||
- check return errors, we are too happy....
|
||||
|
|
|
@ -106,21 +106,21 @@ void AudioLayerWidget::toggleSuspendResume()
|
|||
}
|
||||
|
||||
// from DMX signals
|
||||
void AudioLayerWidget::setVol(qreal vol)
|
||||
void AudioLayerWidget::setVol(int vol)
|
||||
{
|
||||
m_volume->blockSignals(true);
|
||||
m_volume->setValue(vol);
|
||||
m_volume->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::setPan(qreal pan)
|
||||
void AudioLayerWidget::setPan(int pan)
|
||||
{
|
||||
m_pan->blockSignals(true);
|
||||
m_pan->setValue(pan);
|
||||
m_pan->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::setPitch(qreal pitch)
|
||||
void AudioLayerWidget::setPitch(int pitch)
|
||||
{
|
||||
m_pitch->blockSignals(true);
|
||||
m_pitch->setValue(pitch);
|
||||
|
@ -144,33 +144,25 @@ void AudioLayerWidget::setPlaybackStatus(Status status)
|
|||
m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(0));
|
||||
m_statusValue->blockSignals(true);
|
||||
m_suspendResumeButton->blockSignals(true);
|
||||
m_statusValue->setText(StatusStr[status]);
|
||||
m_suspendResumeButton->setText(StatusStr[status]);
|
||||
switch (m_status) {
|
||||
case Status::Paused:
|
||||
m_statusValue->setText("Pause");
|
||||
m_statusValue->setStyleSheet("QLabel { color : red; }");
|
||||
m_suspendResumeButton->setText("Pause");
|
||||
break;
|
||||
case Status::PlayingLoop:
|
||||
m_statusValue->setText("Play Loop");
|
||||
m_statusValue->setStyleSheet("QLabel { color : green; }");
|
||||
m_suspendResumeButton->setText("Play Loop");
|
||||
break;
|
||||
case Status::PlayingOnce:
|
||||
m_statusValue->setText("Play One");
|
||||
m_statusValue->setStyleSheet("QLabel { color : green; }");
|
||||
m_suspendResumeButton->setText("Play One");
|
||||
break;
|
||||
case Status::Stopped:
|
||||
m_statusValue->setText("Stop");
|
||||
m_statusValue->setStyleSheet("QLabel { color : red; }");
|
||||
m_suspendResumeButton->setText("Stop");
|
||||
break;
|
||||
}
|
||||
m_statusValue->blockSignals(false);
|
||||
m_suspendResumeButton->blockSignals(false);
|
||||
}
|
||||
|
||||
void AudioLayerWidget::durationChanged(qint64 dur)
|
||||
void AudioLayerWidget::durationChanged(float dur)
|
||||
{
|
||||
dur *= 1000;
|
||||
m_progressSlider->setMaximum(dur);
|
||||
|
|
|
@ -26,10 +26,10 @@ class AudioLayerWidget : public QGroupBox
|
|||
public:
|
||||
explicit AudioLayerWidget(QWidget *parent = 0, QString name = "Layer", int layer = 0);
|
||||
~AudioLayerWidget();
|
||||
void setVol(qreal vol);
|
||||
void setVol(int vol);
|
||||
void resume();
|
||||
void setPan(qreal pan);
|
||||
void setPitch(qreal pitch);
|
||||
void setPan(int pan);
|
||||
void setPitch(int pitch);
|
||||
void setLoop(bool on);
|
||||
void setPlaybackStatus(Status status);
|
||||
inline Status getPlaybackStatus() { return m_status; }
|
||||
|
@ -60,7 +60,7 @@ public slots:
|
|||
void panChanged(int vol);
|
||||
void pitchChanged(int vol);
|
||||
void fileLoaded(QString file);
|
||||
void durationChanged(qint64 dur);
|
||||
void durationChanged(float dur);
|
||||
void refreshUi(float progress);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -56,19 +56,19 @@ void AudioWidget::mediaLoaded(int layer, QString file)
|
|||
dynamic_cast<AudioLayerWidget *>(item->widget())->durationChanged(pLength);
|
||||
}
|
||||
|
||||
void AudioWidget::volChanged(int layer, qreal vol) {
|
||||
void AudioWidget::volChanged(int layer, int vol) {
|
||||
m_mae.volChanged(layer, vol);
|
||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setVol(vol);
|
||||
}
|
||||
|
||||
void AudioWidget::panChanged(int layer, qreal pan) {
|
||||
void AudioWidget::panChanged(int layer, int pan) {
|
||||
m_mae.panChanged(layer, pan);
|
||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPan(pan);
|
||||
}
|
||||
|
||||
void AudioWidget::pitchChanged(int layer, qreal pitch) {
|
||||
void AudioWidget::pitchChanged(int layer, int pitch) {
|
||||
m_mae.pitchChanged(layer, pitch);
|
||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPitch(pitch);
|
||||
|
|
|
@ -27,9 +27,9 @@ public:
|
|||
|
||||
protected:
|
||||
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 volChanged(int layer, int vol);
|
||||
void panChanged(int layer, int pan);
|
||||
void pitchChanged(int layer, int pitch);
|
||||
void playbackChanged(int layer, Status status);
|
||||
void entryPointChanged(int layer, int cursor);
|
||||
|
||||
|
|
|
@ -58,6 +58,14 @@ enum Status
|
|||
PlayingLoop,
|
||||
};
|
||||
|
||||
static const char* StatusStr[] =
|
||||
{
|
||||
"Stop",
|
||||
"Pause",
|
||||
"Playing One",
|
||||
"Playing Loop",
|
||||
};
|
||||
|
||||
enum Slider
|
||||
{
|
||||
Volume,
|
||||
|
|
|
@ -48,12 +48,12 @@ libreMediaServerAudio::libreMediaServerAudio(QStringList args, QWidget *parent)
|
|||
connect(set, SIGNAL(registerUniverse(int)), ola, SLOT(registerUniverse(int)));
|
||||
connect(ola, SIGNAL (universeReceived(int)), m_dmxWidget, SLOT(updateWatchDMX(int)));
|
||||
connect(ola, SIGNAL(dmxOutput(int, int, int)), this, SLOT(dmxInput(int, int, int)));
|
||||
connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
|
||||
ola->registerUniverse();
|
||||
ola->start(QThread::TimeCriticalPriority );
|
||||
connect(ui.actionOpen_conf, SIGNAL(triggered()), this, SLOT(openFile()));
|
||||
connect(ui.actionSave_conf, SIGNAL(triggered()), this, SLOT(saveFile()));
|
||||
connect(ui.action_Settings, SIGNAL(triggered()), this, SLOT(settings()));
|
||||
connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
|
||||
aw->startEngine();
|
||||
qDebug("Init Complete.");
|
||||
ola->blockSignals(false);
|
||||
|
@ -107,8 +107,6 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|||
return;
|
||||
QString mediaFile = NULL;
|
||||
int aux;
|
||||
qreal f;
|
||||
int r;
|
||||
switch(channel){
|
||||
case DMX_FOLDER:
|
||||
aux = ola->getValue(layer, DMX_FILE);
|
||||
|
@ -123,12 +121,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|||
aw->mediaLoaded(layer, mediaFile);
|
||||
break;
|
||||
case VOLUME_COARSE:
|
||||
f = ( value * 0x100 ) + ola->getValue(layer, VOLUME_FINE);
|
||||
aw->volChanged(layer, (f / 655.35));
|
||||
break;
|
||||
case VOLUME_FINE:
|
||||
f = ( ola->getValue(layer, VOLUME_COARSE) * 0x100 ) + value;
|
||||
aw->volChanged(layer, (f / 655.35));
|
||||
aw->volChanged(layer, (value / 650.25));
|
||||
break;
|
||||
case PAN:
|
||||
aw->panChanged(layer, value);
|
||||
|
@ -137,12 +131,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|||
aw->pitchChanged(layer, value);
|
||||
break;
|
||||
case ENTRY_POINT_COARSE:
|
||||
r = ( value * 0x100 ) + ola->getValue(layer, ENTRY_POINT_FINE);
|
||||
aw->entryPointChanged(layer, r);
|
||||
break;
|
||||
case ENTRY_POINT_FINE:
|
||||
r = ( ola->getValue(layer, ENTRY_POINT_COARSE) * 0x100 ) + value;
|
||||
aw->entryPointChanged(layer, r);
|
||||
aw->entryPointChanged(layer, value);
|
||||
break;
|
||||
case PLAYBACK:
|
||||
if (value == 0)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "miniaudio.h"
|
||||
|
||||
#include "defines.h" //MAX_LAYERS
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
|
@ -18,7 +17,6 @@ public:
|
|||
static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
|
||||
|
||||
protected:
|
||||
// slots for DMX input
|
||||
ma_result loadMedia(int layer, char *media );
|
||||
void volChanged(int layer, float vol);
|
||||
void panChanged(int layer, float pan);
|
||||
|
|
|
@ -38,6 +38,7 @@ void olaThread::init()
|
|||
m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx));
|
||||
m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss));
|
||||
m_client->SetCloseHandler(ola::NewSingleCallback(this, &olaThread::socketClosed));
|
||||
m_dmxSettings = Settings::getInstance()->getDmxSettings();
|
||||
}
|
||||
|
||||
void olaThread::run()
|
||||
|
@ -62,19 +63,50 @@ void olaThread::stop()
|
|||
void olaThread::NewDmx(const ola::client::DMXMetadata &data,
|
||||
const ola::DmxBuffer &buffer)
|
||||
{
|
||||
m_counter++;
|
||||
gettimeofday(&m_last_data, NULL);
|
||||
foreach (const dmxSetting &i, Settings::getInstance()->getDmxSettings()) {
|
||||
bool volSent = false;
|
||||
bool entrySent = false;
|
||||
|
||||
foreach (const dmxSetting &i, m_dmxSettings) {
|
||||
if(i.universe == data.universe && i.address > -1) {
|
||||
for (int j = 0; j < LAYER_CHANNELS; j++){
|
||||
int value = buffer.Get((i.address) + j);
|
||||
if (m_dmx[i.layer][j] != value) {
|
||||
m_dmx[i.layer][j] = value;
|
||||
switch (j) {
|
||||
case 0:
|
||||
value = (value * 0x100) + buffer.Get(i.address + 6);
|
||||
emit dmxOutput(i.layer,j,value);
|
||||
volSent = true;
|
||||
break;
|
||||
case 7:
|
||||
value = (value * 0x100) + buffer.Get(i.address + 8);
|
||||
emit dmxOutput(i.layer,j,value);
|
||||
entrySent = true;
|
||||
break;
|
||||
case 6:
|
||||
if (volSent == false)
|
||||
{
|
||||
value = (buffer.Get(i.address) * 0x100) + value;
|
||||
emit dmxOutput(i.layer,j,value);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (entrySent == false)
|
||||
{
|
||||
value = (buffer.Get(i.address + 7) * 0x100) + value;
|
||||
emit dmxOutput(i.layer,j,value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
emit dmxOutput(i.layer,j,value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_counter++;
|
||||
gettimeofday(&m_last_data, NULL);
|
||||
emit universeReceived(data.universe);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ private:
|
|||
struct timeval m_last_data; // Last DMX frame received
|
||||
int m_layers;
|
||||
int m_dmx[MAX_LAYERS][LAYER_CHANNELS];
|
||||
QList<dmxSetting> m_dmxSettings;
|
||||
|
||||
/**
|
||||
* @brief Callback from ola. Control de errores en el registro de Universos en OLA
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue