From 2c1f1c6a5915ae1ce6a71b4c160cff9a604df900 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 26 May 2017 08:55:29 -0400 Subject: [PATCH] 2017-05-26 Fred Gleason * Added rdconvert(1). --- .gitignore | 1 + ChangeLog | 2 + configure.ac | 1 + docs/docbook/Makefile.am | 4 + docs/docbook/rdconvert.xml | 261 ++++++++++++++++++++++++++++++++++ docs/docbook/rdexport.xml | 4 + docs/docbook/rdimport.xml | 4 + lib/rdsettings.cpp | 35 +++++ lib/rdsettings.h | 1 + rivendell.spec.in | 4 +- utils/Makefile.am | 1 + utils/rdconvert/Makefile.am | 50 +++++++ utils/rdconvert/rdconvert.cpp | 209 +++++++++++++++++++++++++++ utils/rdconvert/rdconvert.h | 56 ++++++++ 14 files changed, 632 insertions(+), 1 deletion(-) create mode 100644 docs/docbook/rdconvert.xml create mode 100644 utils/rdconvert/Makefile.am create mode 100644 utils/rdconvert/rdconvert.cpp create mode 100644 utils/rdconvert/rdconvert.h diff --git a/.gitignore b/.gitignore index 1df989de..b4ea7d6b 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ tests/timer_test tests/upload_test tests/wav_chunk_test utils/rdauth/rdauth +utils/rdconvert/rdconvert utils/rdhpiinfo/rdhpiinfo utils/rddgimport/rddgimport utils/rddiscimport/rddiscimport diff --git a/ChangeLog b/ChangeLog index f4921fc5..3781880a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15812,3 +15812,5 @@ configuration but was beyond the number of active GPIOS set. 2017-05-25 Fred Gleason * Incremented the package version to 2.15.3int08. +2017-05-26 Fred Gleason + * Added rdconvert(1). diff --git a/configure.ac b/configure.ac index add73a63..f534f974 100644 --- a/configure.ac +++ b/configure.ac @@ -473,6 +473,7 @@ AC_CONFIG_FILES([rivendell.spec \ utils/rdcleandirs/Makefile \ utils/rdclilogedit/Makefile \ utils/rdcollect/Makefile \ + utils/rdconvert/Makefile \ utils/rddbcheck/Makefile \ utils/rddelete/Makefile \ utils/rddgimport/Makefile \ diff --git a/docs/docbook/Makefile.am b/docs/docbook/Makefile.am index 0a09ff4c..c2f0298c 100644 --- a/docs/docbook/Makefile.am +++ b/docs/docbook/Makefile.am @@ -34,6 +34,7 @@ all-local: cae.html\ cae.pdf\ rdclilogedit.1\ + rdconvert.1\ rddbcheck.8\ rdmarkerset.8\ rdrevert.8\ @@ -45,6 +46,7 @@ all-local: cae.html\ web_api.pdf man_MANS = rdclilogedit.1\ + rdconvert.1\ rddbcheck.8\ rdexport.1\ rdimport.1\ @@ -56,6 +58,8 @@ EXTRA_DIST = cae.html\ cae.xml\ rdclilogedit.1\ rdclilogedit.xml\ + rdconvert.1\ + rdconvert.xml\ rddbcheck.8\ rddbcheck.xml\ rdmarkerset.8\ diff --git a/docs/docbook/rdconvert.xml b/docs/docbook/rdconvert.xml new file mode 100644 index 00000000..ee7bb6e3 --- /dev/null +++ b/docs/docbook/rdconvert.xml @@ -0,0 +1,261 @@ + + + + + rdconvert + 1 + May 2017 + Linux Audio Manual + + + rdconvert + Convert an audio file to a different format + + + + + Fred + Gleason + fredg@paravelsystems.com + + Application Author + + + + + + + rdconvert + OPTIONS + src-file + + + + + Description + + rdconvert1 can be used to convert + audio files between different formats. + + + + Options + + + + bit-rate + + + + Use a bit rate of bit-rate bits per + second. This option is ignored for PCM and FLAC formats, and is + mutually exclusive with the + option. The default value is 0. + + + + + + + chans + + + + Use chans channels. Supported values + are 1 and 2. The + default value is 2. + + + + + + + filename + + + + Write the converted data to filename. + If not specified, the data will be written to the name of the + input file with the default extension of the destination format + appended. + + + + + + + format + + + + Write the converted data to the specified format. + format can be one of the following: + + + + 0 + + + PCM16 WAV + + + + + 2 + + + MPEG Layer 2 (Raw) + + + + + 3 + + + MPEG Layer 3 (Raw) + + + + + 4 + + + Free Lossless Audio Codec (FLAC) + + + + + 5 + + + OggVorbis + + + + + 6 + + + MPEG Layer 2 (BWF WAV Container) + + + + + 7 + + + PCM24 WAV + + + + + + + + + + qual + + + + Use a variable bitrate with a quality of + chans. Supported values + are -1 through 10. + This parameter is used only with a format of 5 + (OggVorbis). The default value is 0. + + + + + + + rate + + + + Use a sample rate of rate samples per + second. Not all sample rates are supported for all formats; see + the relevant MPEG specifications for details. The default value is + 48000. + + + + + + + msec + + + + Stop converting the audio data at the point + msec mS from the start of the source + file. A value of -1 means to continue + conversion to the end of the source file, which is the default. + + + + + + + lvl + + + + Peak-normalize the audio to lvl dBFS. + A value of 0 disables normalization, which + is the default. + + + + + + + ratio + + + + Alter the tempo of the audio by ratio. + A value of 1.0 specifies no tempo alteration, + which is the default. + + + + + + + msec + + + + Start converting the audio data at the point + msec mS into the source file. The + default value is 0. + + + + + + + +See Also + + + rdexport1 + + , + + rdimport1 + + , + + rdmarkerset8 + + + + + + diff --git a/docs/docbook/rdexport.xml b/docs/docbook/rdexport.xml index caa92cf7..697e10ec 100644 --- a/docs/docbook/rdexport.xml +++ b/docs/docbook/rdexport.xml @@ -397,6 +397,10 @@ See Also + + rdconvert1 + + , rdimport1 diff --git a/docs/docbook/rdimport.xml b/docs/docbook/rdimport.xml index 942e8642..63c1f664 100644 --- a/docs/docbook/rdimport.xml +++ b/docs/docbook/rdimport.xml @@ -815,6 +815,10 @@ See Also + + rdimport1 + + , rdexport1 diff --git a/lib/rdsettings.cpp b/lib/rdsettings.cpp index e23e23a3..febf7173 100644 --- a/lib/rdsettings.cpp +++ b/lib/rdsettings.cpp @@ -276,6 +276,41 @@ QString RDSettings::pathName(const QString &stationname,QString pathname, } +QString RDSettings::defaultExtension(RDSettings::Format fmt) +{ + QString ret="dat"; + + switch(fmt) { + case RDSettings::Pcm16: + case RDSettings::Pcm24: + case RDSettings::MpegL2Wav: + ret="wav"; + break; + + case RDSettings::MpegL1: + ret="mp1"; + break; + + case RDSettings::MpegL2: + ret="mp2"; + break; + + case RDSettings::MpegL3: + ret="mp3"; + break; + + case RDSettings::Flac: + ret="flac"; + break; + + case RDSettings::OggVorbis: + ret="ogg"; + break; + } + return ret; +} + + QString RDSettings::defaultExtension(const QString &stationname, RDSettings::Format fmt) { diff --git a/lib/rdsettings.h b/lib/rdsettings.h index 412cdc22..aedb68c4 100644 --- a/lib/rdsettings.h +++ b/lib/rdsettings.h @@ -53,6 +53,7 @@ class RDSettings QString resolvedCustomCommandLine(const QString &destfile); static QString pathName(const QString &stationname,QString pathname, RDSettings::Format fmt); + static QString defaultExtension(RDSettings::Format fmt); static QString defaultExtension(const QString &stationname, RDSettings::Format fmt); static unsigned bytesPerSec(const QString &stationname, diff --git a/rivendell.spec.in b/rivendell.spec.in index b6f45e92..88a24452 100644 --- a/rivendell.spec.in +++ b/rivendell.spec.in @@ -237,6 +237,7 @@ rm -rf $RPM_BUILD_ROOT @LOCAL_PREFIX@/bin/rdpurgecasts @LOCAL_PREFIX@/bin/rdmaint @LOCAL_PREFIX@/bin/rdcollect +@LOCAL_PREFIX@/bin/rdconvert @LOCAL_PREFIX@/bin/rdcheckcuts @LOCAL_PREFIX@/bin/rd_audio_sync @LOCAL_PREFIX@/bin/rd_config @@ -289,9 +290,10 @@ rm -rf $RPM_BUILD_ROOT /etc/pam.d/rivendell /etc/pam.d/rdalsaconfig-root /etc/security/console.apps/rdalsaconfig-root +%{_mandir}/man1/rdclilogedit.1.gz +%{_mandir}/man1/rdconvert.1.gz %{_mandir}/man1/rdexport.1.gz %{_mandir}/man1/rdimport.1.gz -%{_mandir}/man1/rdclilogedit.1.gz %{_mandir}/man8/rddbcheck.8.gz %{_mandir}/man8/rdmarkerset.8.gz %{_mandir}/man8/rdrevert.8.gz diff --git a/utils/Makefile.am b/utils/Makefile.am index 29008e5b..9cb9a543 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -36,6 +36,7 @@ SUBDIRS = $(ALSACONFIG_RD_OPT)\ rdcleandirs\ rdclilogedit\ rdcollect\ + rdconvert\ rddelete\ rddiscimport\ rdexport\ diff --git a/utils/rdconvert/Makefile.am b/utils/rdconvert/Makefile.am new file mode 100644 index 00000000..e04ebd7d --- /dev/null +++ b/utils/rdconvert/Makefile.am @@ -0,0 +1,50 @@ +## automake.am +## +## Automake.am for rivendell/utils/rdconvert +## +## (C) Copyright 2017 Fred Gleason +## +## 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. +## +## Use automake to process this into a Makefile.in + +AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib +LIBS = @QT_LIBS@ -L$(top_srcdir)/lib +MOC = @QT_MOC@ + +# The dependency for qt's Meta Object Compiler (moc) +moc_%.cpp: %.h + $(MOC) $< -o $@ + +bin_PROGRAMS = rdconvert + +dist_rdconvert_SOURCES = rdconvert.cpp rdconvert.h + +rdconvert_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ + +CLEANFILES = *~\ + *.exe\ + *.idb\ + *ilk\ + *.obj\ + *.pdb\ + *.qm\ + moc_* + +MAINTAINERCLEANFILES = *~\ + *.tar.gz\ + aclocal.m4\ + configure\ + Makefile.in\ + moc_* diff --git a/utils/rdconvert/rdconvert.cpp b/utils/rdconvert/rdconvert.cpp new file mode 100644 index 00000000..5f012391 --- /dev/null +++ b/utils/rdconvert/rdconvert.cpp @@ -0,0 +1,209 @@ +// rdconvert.cpp +// +// Rivendell file format converter. +// +// (C) Copyright 2017 Fred Gleason +// +// 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 + +#include +#include +#include + +#include "rdconvert.h" + +MainObject::MainObject(QObject *parent) + :QObject(parent) +{ + unsigned schema=0; + + destination_settings=new RDSettings(); + start_point=-1; + end_point=-1; + speed_ratio=1.0; + bool ok=false; + RDAudioConvert::ErrorCode conv_err; + + // + // Read Command Options + // + RDCmdSwitch *cmd= + new RDCmdSwitch(qApp->argc(),qApp->argv(),"rdconvert", + RDCONVERT_USAGE); + if(cmd->keys()<1) { + fprintf(stderr,"rdconvert: missing argument\n"); + exit(256); + } + source_filename=cmd->key(cmd->keys()-1); + for(unsigned i=0;ikeys()-1;i++) { + /* + if(cmd->key(i)=="--source-file") { + source_filename=cmd->value(i); + cmd->setProcessed(i,true); + } + */ + if(cmd->key(i)=="--destination-file") { + destination_filename=cmd->value(i); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--start-point") { + start_point=cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid start point\n"); + exit(256); + } + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--end-point") { + end_point=cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid end point\n"); + exit(256); + } + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--destination-format") { + RDSettings::Format format=(RDSettings::Format)cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid destination format\n"); + exit(256); + } + switch(format) { + case RDSettings::Pcm16: + case RDSettings::Pcm24: + case RDSettings::MpegL2: + case RDSettings::MpegL2Wav: + case RDSettings::MpegL3: + case RDSettings::Flac: + case RDSettings::OggVorbis: + destination_settings->setFormat(format); + cmd->setProcessed(i,true); + break; + + default: + fprintf(stderr,"rdconvert: invalid destination format\n"); + exit(256); + } + destination_settings->setFormat(format); + } + if(cmd->key(i)=="--destination-channels") { + unsigned channels=cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid destination channels\n"); + exit(256); + } + destination_settings->setChannels(channels); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--destination-sample-rate") { + unsigned sample_rate=cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid destination sample rate\n"); + exit(256); + } + destination_settings->setSampleRate(sample_rate); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--destination-bit-rate") { + unsigned bit_rate=cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid destination bit rate\n"); + exit(256); + } + destination_settings->setBitRate(bit_rate); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--quality") { + unsigned quality=cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdconvert: invalid destination quality\n"); + exit(256); + } + destination_settings->setQuality(quality); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--normalization-level") { + int normalization_level=cmd->value(i).toInt(&ok); + if((!ok)||(normalization_level>0)) { + fprintf(stderr,"rdconvert: invalid normalization level\n"); + exit(256); + } + destination_settings->setNormalizationLevel(normalization_level); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--speed-ratio") { + speed_ratio=cmd->value(i).toFloat(&ok); + if((!ok)||(speed_ratio<=0)) { + fprintf(stderr,"rdconvert: invalid speed-ratio\n"); + exit(256); + } + cmd->setProcessed(i,true); + } + } + if(source_filename.isEmpty()) { + fprintf(stderr,"rdconvert: missing source-file\n"); + exit(256); + } + if(destination_filename.isEmpty()) { + destination_filename=source_filename+"."+ + RDSettings::defaultExtension(destination_settings->format()); + } + if((destination_settings->bitRate()!=0)&& + (destination_settings->quality()!=0)) { + fprintf(stderr,"rdconvert: --destination-bit-rate and --destination-quality are mutually exclusive\n"); + exit(256); + } + + // + // Read Configuration + // + rdconfig=new RDConfig(); + rdconfig->load(); + + // + // Open Database + // + QString err (tr("rdconvert: ")); + QSqlDatabase *db=RDInitDb(&schema,&err); + if(!db) { + fprintf(stderr,err.ascii()); + delete cmd; + exit(256); + } + + RDAudioConvert *conv=new RDAudioConvert(rdconfig->stationName(),this); + conv->setSourceFile(source_filename); + conv->setDestinationFile(destination_filename); + conv->setDestinationSettings(destination_settings); + conv->setRange(start_point,end_point); + conv->setSpeedRatio(speed_ratio); + conv_err=conv->convert(); + if(conv_err!=RDAudioConvert::ErrorOk) { + fprintf(stderr,"%s\n",(const char *)RDAudioConvert::errorText(conv_err)); + exit(256); + } + + exit(0); +} + + +int main(int argc,char *argv[]) +{ + QApplication a(argc,argv,false); + new MainObject(); + return a.exec(); +} diff --git a/utils/rdconvert/rdconvert.h b/utils/rdconvert/rdconvert.h new file mode 100644 index 00000000..8edd62e7 --- /dev/null +++ b/utils/rdconvert/rdconvert.h @@ -0,0 +1,56 @@ +// rdconvert.h +// +// Rivendell file format converter. +// +// (C) Copyright 2010-2016 Fred Gleason +// +// 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. +// + +#ifndef RDCONVERT_H +#define RDCONVERT_H + +#include + +#include +#include + +#include +#include +#include + +#define RDCONVERT_USAGE "[options] \n\nTest the Rivendell audio converter routines\n\nOptions are:\n--destination-file=\n\n--start-point=\n\n--end-point=\n\n--destination-format=\n Supported formats are:\n 0 - PCM16 WAV\n 2 - MPEG Layer 2\n 3 - MPEG Layer 3\n 4 - FLAC\n 5 - OggVorbis\n 6 - MPEG Layer 2 WAV\n 7 - PCM24 WAV\n\n--destination-channels=\n\n--destination-sample-rate=\n\n--destination-bit-rate=\n\n--destination-quality=\n\n--normalization-level=\n\n--speed-ratio=\n\n" + +// +// Global Variables +// +RDConfig *rdconfig; + + +class MainObject : public QObject +{ + public: + MainObject(QObject *parent=0); + + private: + QString source_filename; + QString destination_filename; + int start_point; + int end_point; + float speed_ratio; + RDSettings *destination_settings; +}; + + +#endif // RDCONVERT_H