Rivendellaudio/lib/rdwavewidget.cpp
Fred Gleason 0892892407 2021-04-12 Fred Gleason <fredg@paravelsystems.com>
* Added a 'DISTRO-SPECIFIC NOTES' section to 'INSTALL'.

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
2021-04-12 16:12:52 -04:00

315 lines
6.6 KiB
C++

// rdwavewidget.cpp
//
// Widget for displaying audio waveforms
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <math.h>
#include "rdapplication.h"
#include "rdcut.h"
#include "rdpeaksexport.h"
#include "rdwavewidget.h"
RDWaveWidget::RDWaveWidget(RDWaveWidget::TrackMode mode,int height,
QWidget *parent)
: QWidget(parent)
{
d_channels=0;
d_audio_gain=0.0;
d_x_shrink=1;
d_track_mode=mode;
d_height=(qreal)height;
d_view=new QGraphicsView(this);
d_scene=NULL;
}
RDWaveWidget::~RDWaveWidget()
{
delete d_view;
if(d_scene!=NULL) {
delete d_scene;
}
}
QSize RDWaveWidget::sizeHint() const
{
return QSize(1000,d_height+20);
// return QSize(1000,d_height+42);
}
QSizePolicy RDWaveWidget::sizePolicy() const
{
return QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Fixed);
}
QGraphicsScene *RDWaveWidget::scene() const
{
return d_scene;
}
qreal RDWaveWidget::audioGain() const
{
return d_audio_gain;
}
int RDWaveWidget::shrinkFactor() const
{
return d_x_shrink;
}
void RDWaveWidget::setAudioGain(qreal gain)
{
if(gain!=d_audio_gain) {
d_audio_gain=gain;
WriteWave();
}
}
void RDWaveWidget::setShrinkFactor(int sf)
{
if(sf!=d_x_shrink) {
d_x_shrink=sf;
WriteWave();
}
}
bool RDWaveWidget::setCut(QString *err_msg,unsigned cartnum,int cutnum)
{
clear();
//
// Get Cut Info
//
RDCut *cut=new RDCut(cartnum,cutnum);
if(!cut->exists()) {
*err_msg=tr("No such cart/cut!");
delete cut;
return false;
}
d_channels=cut->channels();
delete cut;
//
// Get Cut Energy Data
//
RDPeaksExport::ErrorCode err_code;
RDPeaksExport *conv=new RDPeaksExport(this);
conv->setCartNumber(cartnum);
conv->setCutNumber(cutnum);
if((err_code=conv->runExport(rda->user()->name(),rda->user()->password()))!=
RDPeaksExport::ErrorOk) {
*err_msg=tr("Energy export failed")+": "+RDPeaksExport::errorText(err_code);
delete conv;
return false;
}
if((d_track_mode==RDWaveWidget::SingleTrack)&&(d_channels==2)) { // Mix-down
for(unsigned i=0;i<conv->energySize();i+=2) {
uint32_t frame=
((uint32_t)conv->energy(i)+(uint32_t)conv->energy(i+1))/2;
d_energy_data.push_back(frame);
}
}
else { // Pass-through
for(unsigned i=0;i<conv->energySize();i++) {
d_energy_data.push_back(conv->energy(i));
}
}
delete conv;
return loadCut();
}
void RDWaveWidget::clear()
{
d_view->setScene(NULL);
delete d_scene;
d_scene=NULL;
d_energy_data.clear();
d_x_shrink=1;
}
QList<uint16_t> RDWaveWidget::energyData() const
{
return d_energy_data;
}
bool RDWaveWidget::loadCut()
{
/*
switch(d_track_mode) {
case RDWaveWidget::SingleTrack:
d_scene=new RDWaveScene(d_energy_data,d_x_shrink,0.0,d_height,this);
break;
case RDWaveWidget::MultiTrack:
switch(d_channels) {
case 1:
d_scene=new RDWaveScene(d_energy_data,d_x_shrink,0.0,d_height,this);
break;
case 2:
d_scenes.push_back(new RDWaveScene(d_energy_datas.front(),d_x_shrink,0.0,
d_height/2,this));
d_views.front()->setScene(d_scenes.back());
d_scenes.push_back(new RDWaveScene(d_energy_datas.back(),d_x_shrink,0.0,
d_height/2,this));
d_views.back()->setScene(d_scenes.back());
d_views.front()->show();
d_views.back()->show();
break;
}
break;
}
d_view->setScene(d_scene);
*/
WriteWave();
return true;
}
void RDWaveWidget::resizeEvent(QResizeEvent *e)
{
int w=size().width();
int h=size().height();
d_view->setGeometry(0,0,w,h);
}
void RDWaveWidget::WriteWave()
{
//
// Calculate Effective Channels
//
int chans=d_channels;
if(d_track_mode==RDWaveWidget::SingleTrack) {
chans=1;
}
//
// Get New Scene
if(d_scene!=NULL) {
delete d_scene;
}
d_scene=new QGraphicsScene(0,0,d_energy_data.size()/d_x_shrink,d_height,this);
//
// Gain Ratio
//
qreal ratio=exp10(d_audio_gain/20.0);
//
// Waveform
//
for(int i=0;i<chans;i++) {
for(int j=i;j<d_energy_data.size();j+=(chans*d_x_shrink)) {
uint16_t lvl=d_energy_data.at(j);
for(int k=1;k<d_x_shrink;k++) {
if(((j+k)<d_energy_data.size())&&(d_energy_data.at(j+k))>lvl) {
lvl=d_energy_data.at(j+k);
}
}
qreal rlvl=ratio*(qreal)lvl*d_height/(65534.0*(qreal)chans);
// Bottom half
d_scene->addRect((qreal)(j/d_x_shrink),
d_height/((qreal)chans*2.0)+i*d_height/((qreal)chans),
(qreal)1,
rlvl,
QPen(Qt::black),QBrush(Qt::black));
// Top half
d_scene->addRect((qreal)(j/d_x_shrink),
d_height/((qreal)chans*2.0)+i*d_height/((qreal)chans),
(qreal)1,
-rlvl,
QPen(Qt::black),QBrush(Qt::black));
}
}
for(int i=1;i<chans;i++) {
// Track Divider
d_scene->addLine(0.0,i*d_height/((qreal)chans),
d_energy_data.size()/d_x_shrink,i*d_height/((qreal)chans),
QPen(Qt::gray));
}
d_view->setScene(d_scene);
}
/*
void RDWaveWidget::WriteWave()
{
//
// Calculate Effective Channels
//
int chans=d_channels;
if(d_track_mode==RDWaveWidget::SingleTrack) {
chans=1;
}
//
// Get New Scene
if(d_scene!=NULL) {
delete d_scene;
}
d_scene=new QGraphicsScene(0,0,d_energy_data.size()/d_x_shrink,d_height,this);
//
// Gain Ratio
//
qreal ratio=exp10(d_audio_gain/20.0);
//
// Waveform
//
for(int j=0;j<d_energy_data.size();j+=d_x_shrink) {
uint16_t lvl=d_energy_data.at(j);
for(int k=1;k<d_x_shrink;k++) {
if(((j+k)<d_energy_data.size())&&(d_energy_data.at(j+k))>lvl) {
lvl=d_energy_data.at(j+k);
}
}
qreal rlvl=ratio*(qreal)lvl*d_height/65534.0;
// Bottom half
d_scene->addRect((qreal)(j/d_x_shrink),d_height/2.0,
(qreal)1,rlvl,
QPen(Qt::black),QBrush(Qt::black));
// Top half
d_scene->addRect((qreal)(j/d_x_shrink),d_height/2.0,
(qreal)1,-rlvl,
QPen(Qt::black),QBrush(Qt::black));
}
d_view->setScene(d_scene);
}
*/