quelcom-0.4.0/ 40755 0 0 0 7245453630 11152 5 ustar root root quelcom-0.4.0/makefile 100644 0 0 2763 7245453630 12757 0 ustar root root
#
# makefile for quelcom 0.4.0
#
# all variables exported by default to sub-makefiles
export
PREFIX=/usr/local
BINDIR=$(PREFIX)/bin
LIBDIR=$(PREFIX)/lib
LOCALEDIR=$(PREFIX)/share/locale
INFODIR=$(PREFIX)/info
MANDIR=$(PREFIX)/man
PACKAGE=quelcom
VERSION=0.4.0
CXX=g++
DIRS=lib bin doc po
all:
for i in $(DIRS); \
do \
make -C $$i; \
done
clean:
for i in $(DIRS); \
do \
make -C $$i clean; \
done
# installs the deprecated man pages
installman:
make -C doc installman
install: all
for i in $(DIRS); \
do \
make -C $$i install; \
done
package:
# include generated doc un .mo files
make -C doc
make -C po
# clean package
rm -rf quelcom-$(VERSION)
mkdir -p quelcom-$(VERSION)
cp -f makefile ChangeLog INSTALL README TODO quelcom-$(VERSION)
# binary files
mkdir -p quelcom-$(VERSION)/bin
cp bin/*.cc bin/makefile quelcom-$(VERSION)/bin
# library files
mkdir -p quelcom-$(VERSION)/lib
cp lib/*.{cc,hh} lib/makefile quelcom-$(VERSION)/lib
# documentation files
mkdir -p quelcom-$(VERSION)/doc
cp -f doc/*.texinfo doc/quelcom.* doc/texinfo.tex doc/makefile quelcom-$(VERSION)/doc
cp -Rf doc/old.man.pages quelcom-$(VERSION)/doc
# po/mo files
mkdir -p quelcom-$(VERSION)/po
cp -f po/*.{po,mo} po/makefile quelcom-$(VERSION)/po
# build tar file
tar cvzf quelcom-$(VERSION).tar.gz quelcom-$(VERSION)
tgz:
tar cvzf quelcom-$(VERSION)-`date +%Y%m%d-%H%M.tgz` bin/*.cc bin/makefile makefile [A-Z]* doc/* tudú* bin/pendents/* Doxyfile lib/*.{cc,hh} lib/makefile po/*.{po,mo} po/makefile
quelcom-0.4.0/ChangeLog 100644 0 0 3240 7245453630 13020 0 ustar root root 20010326: version 0.4.0
splitted sources in directories
created shared libraries
added time specifiers for qwavsample, qwavsilence, q{mp3,wav}cut
corrected a bug that made qwavfade just fade the first of the given files to fade.
improved qmp3report (html output, split reports across subdirs)
added variable bit rate support for qmp3info, qmp3check, qmp3report, qmp3join (no vbr support in qmp3cut by now) (xing vbr headers are not read).
qwavheaderdump: added some capability to recover damaged headers.
adapted source code to compile with no modifications with cygwin tools. binary versions for windows available separately.
(near complete) .mo gettext translation files for catalan and spanish
deprecated man pages.
full documentation in texinfo, html and txt formats. postscript version available separately.
doxygen-ized part of the library code
20010123: version 0.3.0
added gettext support. no translations available yet
added qwavfade
added qmp3report
added qwavheaderdump
added long options support (getopt_long)
added ability to specify file points with millisecond resolution
added silence shrinking capability to qwavsilence
speeded up qwavsilence on non silent wav files
updated man pages
20001227: version 0.2.0
corrected some function signatures that caused egcs fail (almost
version 2.91.66)
corrected overflow bug that caused fail on search ops in big files
added qwavsilence and qmp3check
updated man pages
20001211: version 0.1.0
rewritten file access with mmap
renamed binaries and most of sources prepending with 'q'
code cleanup
added qmp3cut
20001031: version 0.0.0b
first public release: wavinfo, wavjoin, wavcut, mp3info, mp3join
quelcom-0.4.0/INSTALL 100644 0 0 2757 7245453630 12313 0 ustar root root installation instructions for quelcom 0.4.0
REQUIREMENTS
quelcom is being developed on an intel p133 with suse 6.3 linux. other
configurations may work also.
a c++ compiler is needed. i'm currently using gcc 2.95.2.
c++ libraries: libstdc++ is required.
BUILDING AND INSTALLATION
the sources may be found at http://www.etse.urv.es/~dmanye/quelcom/quelcom.html
unpack the package:
tar xzf quelcom-0.4.0.tar.gz
this should create a directory called quelcom-0.4.0 and expand there all the
files
get into the directory and build
cd quelcom-0.4.0
make
if you get any irrecoverable error, you can try to fix it by editing by hand
the makefile, or looking at the source files ;-). otherwise you can try to
contact with me and explain me what kind of error you get.
when everything is fine you can proceed with installation issuing the command:
make install
by default places of installation are:
- /usr/local/bin: executables
- /usr/local/lib: libraries
- /usr/local/share/locale: translation files
- /usr/local/info: info manual
you can change this by editing the root makefile and changing the predefined
values to your preferences.
the doc directory contains also the info manual in html and txt formats.
in addition, this release also contains the deprecated man pages for version
0.3.0. they will be installed under /usr/local/man if you issue the command
'make installman'.
gaudeix-ne, si pots.
dmanye@etse.urv.es
http://www.etse.urv.es/~dmanye/quelcom/quelcom.html
quelcom-0.4.0/README 100644 0 0 2154 7245453630 12131 0 ustar root root quelcom v0.4.0
quelcom is a set of tools to manage wav and mp3 files.
this release 0.4.0 is considered yet in beta state although works reasonably
well for his author.
currently the following applications are implemented:
qwavinfo: to get info from a wav file
qwavjoin: to join two or more wav files in one
qwavcut: to extract or delete a fragment of a wav file
qwavsilence: to detect silence sequences in wav files
qwavfade: to fade in/out wav files
qwavheaderdump: to dump and fix wav headers
qmp3info: to get info from a mp3 file
qmp3join: to join two or more mp3 files in one
qmp3cut: to extract or delete a fragment of a mp3 file
qmp3check: to check and clean mp3 streams
qmp3report: to get reports from mp3 directory hierarchies
an info manual can be found in the doc subdir (html version and source texinfo
is also available)
deprecated (version 0.3.0) man pages for each app are provided with the package
see INSTALL file for instructions about building and installing the software
enjoy it.
comments and suggestions are welcome.
dmanye@etse.urv.es
http://www.etse.urv.es/~dmanye/quelcom/quelcom.html
quelcom-0.4.0/TODO 100644 0 0 1027 7245453630 11737 0 ustar root root to-do wish list for quelcom 0.4.0
reading/writing from/to stdin/stdout
use autoconf/automake
implement a mp3 silence detecter
implement a wav volume normalizer
allow user-customizable info format for {mp3,wav}info
implement a kind of lightweight quelcom sound file editor
include frame-decoding capability to get more extensive checking of
frames (qmp3check)
translations for de,fr
implement a (hard) real-time sound recorder (implement wav::record)
write a port to other operating systems/architectures (solaris+sparc)
quelcom-0.4.0/bin/ 40755 0 0 0 7245453630 11722 5 ustar root root quelcom-0.4.0/bin/qmp3check.cc 100644 0 0 23456 7245453630 14236 0 ustar root root # include // getopt
# include // per esborrar...
# include "qmp3frameheader.hh"
# include "qmp3.hh"
# include "qfile.hh"
# include "qtag.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: check and clean mp3 streams\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" -D, --delete: delete invalid frames and garbage. use with care\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -q, --quiet: no output messages\n");
cerr << _(" -T, --delete-tag: delete tag (if exists). option -D must be set\n");
cerr << _(" -v, --verbose: show more detailed info\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
int option;
bool verbose=false, del=false, delTag=false, quiet=false;
static struct option long_options[] = {
{"delete",no_argument,0,'D'},
{"help",no_argument,0,'h'},
{"quiet",no_argument,0,'q'},
{"delete-tag",no_argument,0,'T'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.mp3 ...
if (argc==1) {
usage();
return 1;
}
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "DhqTvV",long_options,0)) != EOF)
switch (option) {
case 'D':
del=true;
break;
case 'h':
usage();
return 0;
break;
case 'q':
quiet=true; verbose=false;
break;
case 'T':
delTag=true;
break;
case 'v':
verbose=true; quiet=false;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (delTag && !del) {
cerr << APPNAME << _(": flag -T requires -D. ignoring -T") << endl;
delTag = false;
}
if (argc<=optind) {
// hauríem de fer *.mp3 ... ?
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
argv += optind;
u_int32_t error_files = 0;
u_int32_t frames, stream_length;
u_int32_t mode = del?qfile::READWRITE:qfile::READ;
caddr_t clean_offset, clean_block_begin, clean_block_end;
qmp3frameheader *frame;
u_int32_t skipped, total_skipped;
do {
total_skipped = 0;
try {
qfile file(*argv,mode);
bool hasTag;
qtag *tag;
if (file.getSize()isValid();
if (hasTag)
cerr << *argv << ": " << *tag << endl;
else
if (verbose)
cerr << *argv << _(": no tag") << endl;
}
frames = 0;
stream_length = file.getSize()-(hasTag?qtag::LENGTH:0);
try {
frame = new qmp3frameheader(file.getMap(),file.getSize());
}
catch (qexception e) {
cerr << file.getName() << ": " << e << endl;
error_files++;
continue; // sembla que no xuti...potser si: quan prova de desmapejar el qfile pq surt del seu àmbit, i crec que peta sempre que vol desmapejar un fitxer de mida zero. ok.
}
clean_offset = file.getMap()-1;
clean_block_begin = frame->getMap();
skipped = frame->getMap()-file.getMap();
if (skipped) {
if (!quiet)
cerr.form(_("%s: skipped %d bytes of garbage at the beginning\n"),
*argv,skipped);
total_skipped += skipped;
stream_length -= skipped;
}
if (stream_length >= frame->getLength()) {
stream_length -= frame->getLength();
clean_block_end = frame->getMap()+frame->getLength()-1;
frames++;
}
else
if (!quiet)
cerr.form(_("%s: first frame incomplete: %d of %d bytes\n"),
*argv,stream_length,frame->getLength());
while (stream_length) {
try {
skipped = frame->setNext(stream_length);
}
catch (qexception e) {
if (!quiet)
cerr.form(_("%s: %d bytes of garbage at the end"),
*argv,stream_length);
if (verbose)
cerr.form(" (%d..%d)",file.getSize()-stream_length,file.getSize());
if (!quiet)
cerr << endl;
total_skipped += stream_length;
stream_length = 0;
break;
}
if (skipped) {
if (!quiet)
cerr.form(_("%s: skipped %d bytes"),*argv,skipped);
if (verbose)
cerr.form(" (%d..%d)",
clean_block_end-file.getMap()+1,
frame->getMap()-file.getMap()-1);
if (!quiet)
cerr << endl;
if ( clean_block_begin!=clean_offset &&
(clean_offset!=file.getMap()-1)) {
if (del) {
if (!quiet)
cerr.form(_("%s: moving %d bytes"),
*argv,
clean_block_end-clean_block_begin+1);
if (verbose)
cerr.form(" (%d..%d) <-- (%d..%d)",
clean_offset-file.getMap()+1,
clean_offset-file.getMap()+1+clean_block_end-clean_block_begin,
clean_block_begin-file.getMap(),
clean_block_end-file.getMap());
if (!quiet)
cerr << endl;
file.move ((u_int32_t)(clean_block_begin-file.getMap()),
(u_int32_t)(clean_block_end-file.getMap()),
(u_int32_t)(clean_offset+1-file.getMap()));
}
clean_offset += clean_block_end-clean_block_begin+1;
}
else
clean_offset = clean_block_end;
clean_block_begin = frame->getMap();
total_skipped += skipped;
stream_length -= skipped;
}
if (stream_length >= frame->getLength()) {
stream_length -= frame->getLength();
clean_block_end = frame->getMap()+frame->getLength()-1;
frames++;
}
else {
if (!quiet)
cerr.form(_("%s: last frame (%d+1) truncated: %d of %d bytes\n"),
*argv,frames,stream_length,frame->getLength());
total_skipped += stream_length;
stream_length = 0;
break;
}
}
if (clean_block_end>clean_block_begin &&
clean_block_begin>clean_offset &&
(clean_offsetgetMap()-file.getMap()),
(u_int32_t)(tag->getMap()-file.getMap()+qtag::LENGTH-1),
(u_int32_t)(clean_offset+1-file.getMap()));
if (!quiet)
cerr.form(_("%s: moving tag (%d bytes)"),*argv,qtag::LENGTH);
if (verbose)
cerr.form(" (%d..%d) <-- (%d..%d)",
clean_offset-file.getMap()+1,
clean_offset-file.getMap()+1+qtag::LENGTH-1,
tag->getMap()-file.getMap(),
tag->getMap()-file.getMap()+qtag::LENGTH-1);
if (!quiet)
cerr << endl;
}
clean_offset += qtag::LENGTH;
}
}
else
clean_offset += qtag::LENGTH;
}
if (total_skipped) {
if (!quiet)
cerr.form(_("%s: %d of %d discardable bytes\n"),
*argv,total_skipped,file.getSize());
if (del) {
if (!quiet)
cerr.form(_("%s: truncating to %d bytes\n"),
*argv,file.getSize()-total_skipped);
file.truncate(file.getSize()-total_skipped);
}
}
if (verbose) {
if (del) {
qmp3 mp3(*argv);
cerr << mp3 << endl; // quedaria millor la versió 'verbose...'
}
else
cerr.form(_("%s: %d frames, %d bytes\n"),
*argv,frames,clean_offset-file.getMap()+1);
}
if (hasTag)
delete tag;
} catch (qexception e) {
cerr << *argv << ": " << e << endl;
error_files++;
}
if (total_skipped)
error_files++;
} while (*++argv);
if (error_files && verbose)
cerr.form(_("%d error files found\n"),error_files);
}
quelcom-0.4.0/bin/qmp3cut.cc 100644 0 0 10530 7245453630 13741 0 ustar root root # include // getopt
# include "qmp3.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: extract and/or delete parts of a mp3 file\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file\n"),APPNAME);
cerr << _(" options:\n");
cerr << _(" -B, --set-begin : set the first frame from the beginning of the file\n");
cerr << _(" -b, --set-begin-from-eof : set the first frame from the end of the file\n");
cerr << _(" -d, --delete: deletes the fragment\n");
cerr << _(" -E, --set-end : set the last frame from the beginning of the file\n");
cerr << _(" -e, --set-end-from-eof : set the last frame from the end of the file\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -o, --output : output file where the fragment is stored\n");
cerr << _(" -s, --size : specifies the size of the cut\n");
cerr << _(" -S, --slice -: set the cut as a time slice\n");
cerr << _(" -v, --verbose: verbose\n");
cerr << _(" -V, --version: show version and exit\n");
cerr << _(" = [j|s|m|b|k|M]\n");
cerr << _(" = [[h:]m:]s[.ms]\n");
cerr << _(" see info manual for more info about options and usage\n");
}
int main (int argc, char **argv) {
string outfile;
string infile;
bool del = false, verbose=false, slice_defined = false;
qvf vfbegin,vfSize,vfend,vfBegin,vfEnd;
static struct option long_options[] = {
{"set-begin",required_argument,0,'B'},
{"set-begin-from-eof",required_argument,0,'b'},
{"delete",no_argument,0,'d'},
{"set-end",required_argument,0,'E'},
{"set-end-from-eof",required_argument,0,'e'},
{"help",no_argument,0,'h'},
{"output",required_argument,0,'o'},
{"size",required_argument,0,'s'},
{"slice",required_argument,0,'S'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
int option;
qcuthandler h;
// supress getopt error messages:
opterr = 0;
while ((option = getopt_long(argc, argv, "b:B:de:E:ho:s:S:vV",long_options,0)) != EOF)
try {
switch (option) {
case 'b':
vfbegin = qvf(optarg);
break;
case 'B':
vfBegin = qvf(optarg);
break;
case 'd':
del=true;
break;
case 'e':
vfend = qvf(optarg);
break;
case 'E':
vfEnd = qvf(optarg);
break;
case 'h':
usage();
return 1;
break;
case 'o':
outfile=optarg;
break;
case 's':
vfSize = qvf(optarg);
break;
case 'S':
slice_defined = true;
h = qcuthandler(optarg);
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
}
catch (qexception e) {
cerr << e << endl;
}
if (argc-optind!=1) {
cerr << APPNAME << _(": only one file to cut must be specified") << endl;
usage();
return 1;
}
infile = argv[optind];
if (!slice_defined) {
h.setBegin(vfBegin);
h.setbegin(vfbegin);
h.setEnd(vfEnd);
h.setend(vfend);
}
h.setSize(vfSize);
h.setDel(del);
h.setOutfile(outfile);
try {
u_int32_t mode = del?qmp3::READWRITE:qmp3::READ;
qmp3 mp3 (infile,mode);
if (verbose)
cerr.form(_("scanning '%s'..."),infile.c_str());
mp3.scan();
if (verbose)
cerr << "ok." << endl;
mp3.scan();
if (mp3.isVbr()) {
cerr << APPNAME << _(": vbr format is not supported") << endl;
return 1;
}
mp3.cut(h);
if (verbose) {
cerr << mp3 << endl;
if (outfile!="") {
qmp3 mp3out(outfile);
cerr << mp3out << endl;
}
}
}
catch (qexception e) {
cerr << e << endl;
return 1;
}
return 0;
}
quelcom-0.4.0/bin/qmp3info.cc 100644 0 0 6535 7245453630 14073 0 ustar root root # include // getopt
# include "qmp3.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: show info from mp3 files\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" -c, --check: check the entire stream (slower but accurate)\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -s, --summary-only: show only the summary\n");
cerr << _(" -v, --verbose: verbose\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
int option;
bool verbose=false;
bool summarize=false;
bool check=false;
static struct option long_options[] = {
{"check",no_argument,0,'c'},
{"help",no_argument,0,'h'},
{"summary-only",no_argument,0,'s'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.mp3 ...
if (argc==1) {
usage();
return 1;
}
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "chsvV",long_options,0)) != EOF)
switch (option) {
case 'c':
check=true;
break;
case 'h':
usage();
return 0;
break;
case 's':
summarize=true;
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc<=optind) {
// hauríem de fer *.mp3 ...
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
u_int32_t files=0, errors=0;
u_int32_t msduration, total_msduration=0;
u_int32_t bytes, frames, total_bytes=0, total_frames=0;
while (argv[optind]) {
files++;
try {
qmp3 p(argv[optind]);
if (!check && p.isVbr()) {
if (verbose)
cerr << p.getName() << _(": vbr detected => automatic check") << endl;
check = true;
}
if (check)
p.scan();
msduration = p.getMsDuration();
total_msduration += msduration;
if (!summarize)
cout << p;
if (verbose) {
bytes = p.getSize();
frames = p.getFrames();
if (!summarize)
cout << " " << bytes << " bytes " << frames << " frames";
total_bytes += bytes;
total_frames += frames;
}
if (!summarize)
cout << endl;
}
catch (qexception e) {
cerr << argv[optind] << ": " << e << endl;
errors++;
}
optind++;
}
cout.form (_("%u file%c"),files,files>1?'s':0);
if (errors)
cout.form (" (%u error%c)",errors,errors>1?'s':0);
if (verbose)
cout.form (" => %d:%02d.%03d %u frames %u bytes\n",
total_msduration/60000,(total_msduration/1000)%60,
total_msduration%1000,total_frames,total_bytes);
else
cout.form (" => %d:%02d\n",
total_msduration/60000,(total_msduration/1000)%60);
}
quelcom-0.4.0/bin/qmp3join.cc 100644 0 0 6125 7245453630 14072 0 ustar root root # include // getopt
# include "qmp3.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: join mp3 files\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file1 file2...\n"),APPNAME);
cerr << _(" -f, --force: force join bypassing bit rate checks\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -o, --output : send output to . otherwise, append to \n");
cerr << _(" -v, --verbose: verbose\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
bool verbose=false, force=false;
string outfile;
static struct option long_options[] = {
{"force",no_argument,0,'f'},
{"help",no_argument,0,'h'},
{"output",required_argument,0,'o'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
if (argc==1) {
usage();
return 1;
}
int option;
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "fho:vV",long_options,0)) != EOF)
switch (option) {
case 'f':
force = true;
break;
case 'h':
usage();
return 0;
break;
case 'o':
outfile=optarg;
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc-optind<2) {
cerr << APPNAME << _(": at least two files to join must be specified\n");
usage();
return 1;
}
argv += optind;
qmp3 *mp3;
try {
// resolve which is the first file
if (outfile!="") {
mp3 = new qmp3(*argv);
if (verbose)
cerr.form(_("copying '%s' to '%s'..."),*argv,outfile.c_str());
mp3->dup(outfile);
if (verbose)
cerr << "ok." << endl;
delete mp3;
mp3 = new qmp3 (outfile,qmp3::READWRITE);
}
else
mp3 = new qmp3(*argv,qmp3::READWRITE);
if (verbose)
cerr.form(_("scanning '%s'..."),mp3->getName().c_str());
mp3->scan();
if (verbose)
cerr << "ok." << endl;
// append the rest of the files
while (*++argv) {
qmp3 mm(*argv);
if (verbose)
cerr.form(_("scanning '%s'..."),mm.getName().c_str());
mm.scan();
if (verbose)
cerr << "ok." << endl;
if (verbose)
cerr.form(_("appending '%s' to '%s'..."),
mm.getName().c_str(),mp3->getName().c_str());
mp3->append(mm,force);
if (verbose)
cerr << "ok." << endl;
}
}
catch (qexception e) {
cerr << *argv << ": " << e << endl;
return 1;
}
if (verbose)
cerr << *mp3 << endl;
delete mp3;
return 0;
}
quelcom-0.4.0/bin/qmp3report.cc 100644 0 0 22751 7245453630 14471 0 ustar root root # include
# include
# include // stat
# include // getopt
# include // scandir
# include // getcwd
# include // errno
# include "qmp3.hh"
# include "qfile.hh"
# include "qexception.hh"
# include "qreport.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
struct options {
bool all, html, recursive,
showall, showdirs, showfiles, showsummary,
split, verbose;
string outfilename;
ofstream *out;
};
void usage () {
cerr.form(_(" %s: generate reports from mp3 files and directories\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" options:\n");
cerr << _(" -a, --all-files: report all files, not just *.mp3\n");
cerr << _(" -A, --show-all: implies -d, -f, -s\n");
// cerr << _(" --all-mp3: consider files as mp3 streams"\n");
cerr << _(" -d, --dirs: show a report for every directory\n");
cerr << _(" -f, --files: show a report for every file\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -H, --html: output in html format (default is text)\n");
// cerr << _(" -o, --outfilename : output file (by default stdout)\n");
cerr << _(" -r, --recursive: scan directories\n");
// cerr << _(" -s: scan streams for validity (slower but more accurate)\n");
cerr << _(" -s, --summary: show a summary report\n");
cerr << _(" -S, --split: split report across visited directories\n");
cerr << _(" -v, --verbose: show more detailed info\n");
cerr << _(" -V, --version: show version and exit\n");
// allow user defined format for showing
// treure segons com i quan el temps que triga
}
qreport report_file (string filename, struct options &opts) {
try {
if (opts.all) {
qfile f(filename);
if (opts.verbose)
cerr.form (_("reporting file '%s'\n"),filename.c_str());
qreport r(f);
if (opts.showfiles) {
if (opts.html) {
r.html(opts.out);
*opts.out << " " << endl;
}
else
*opts.out << r << endl;
}
return r;
}
}
catch (qexception e) {
cerr << filename << ": " << e << endl;
}
return qreport();
}
qreport report_mp3 (string mp3name, struct options &opts) {
try {
qmp3 mp3(mp3name);
if (mp3.isVbr()) {
if (opts.verbose)
cerr << mp3.getName() << _(": vbr detected => automatic check") << endl;
mp3.scan();
}
if (opts.verbose)
cerr.form (_("reporting mp3 file '%s'\n"),mp3name.c_str());
qreport r(mp3);
if (opts.showfiles) {
if (opts.html) {
r.html(opts.out);
*opts.out << " " << endl;
}
else
*opts.out << r << endl;
}
return r;
}
catch (qexception e) {
cerr << mp3name << ": " << e << endl;
return qreport();
}
}
qreport report_directory (string dirname, struct options &opts) {
if (opts.verbose)
cerr.form (_("reporting directory '%s'\n"),dirname.c_str());
qreport dirreport(dirname);
if (!opts.recursive) {
if (opts.verbose)
cerr.form(_("%s: '%s' is a directory\n"),APPNAME,dirname.c_str());
return dirreport;
}
char previous_wd[1025],wd[1025];
ofstream *out;
if (opts.split) {
if (getcwd(previous_wd,sizeof(previous_wd))==NULL) {
cerr.form(_("cannot get current directory (%s): %s\n"),
dirname.c_str(),strerror(errno));
return dirreport;
}
if (chdir(dirname.c_str())) {
cerr.form(_("cannot move to dir %s: %s\n"),dirname.c_str(),strerror(errno));
return dirreport;
}
if (getcwd(wd,sizeof(wd))==NULL) {
cerr.form(_("cannot get current directory (%s): %s\n"),
dirname.c_str(),strerror(errno));
return dirreport;
}
char *index = strrchr(wd,'/');
string outfilename;
if (*index && index!=wd)
outfilename = string((index+1));
else
outfilename = string ("qmp3report");
if (opts.html)
outfilename += string(".html");
else
outfilename += string(".txt");
if (opts.verbose)
cerr.form(_("opening output file '%s'\n"),outfilename.c_str());
out = opts.out;
opts.out = new ofstream(outfilename.c_str());
dirname = string(".");
}
int n;
struct dirent **namelist;
if ((n = scandir(dirname.c_str(),&namelist,0,alphasort))<0) {
cerr.form(_("%s: cannot scan '%s'\n"),APPNAME,dirname.c_str());
return dirreport;
}
for (int i=0; id_name,".") ||
!strcmp(namelist[i]->d_name,".."))
continue;
struct stat filestat;
string filepathname;
if (dirname==".")
filepathname = string(namelist[i]->d_name);
else
filepathname = dirname + string("/") + string(namelist[i]->d_name);
if (stat(filepathname.c_str(),&filestat)) {
cerr.form(_("%s: error reading '%s' status: %s\n"),
APPNAME,dirname.c_str(),strerror(errno));
continue;
}
if (S_ISDIR(filestat.st_mode)) {
dirreport.add(report_directory(filepathname,opts));
continue;
}
if (S_ISREG(filestat.st_mode)) {
int length = filepathname.length();
if (length>4 && !strncasecmp((char*)(&(filepathname.c_str()[length-4])),".mp3",4))
dirreport.add(report_mp3(filepathname,opts));
else {
if (opts.all)
dirreport.add(report_file(filepathname,opts));
}
continue;
}
if (opts.verbose)
cerr << filepathname << _(" is a special file. skipping.") << endl;
}
if (opts.split) {
if (opts.html)
*opts.out << "  " << endl;
else
*opts.out << endl;
*opts.out << dirreport << endl;
opts.out->close();
opts.out = out;
chdir (previous_wd);
}
if (opts.showdirs && dirreport.getFiles()>0) {
if (opts.html) {
// if split fer que en lloc d'assenyalar al directori apunti al report
// que conté.
dirreport.html(opts.out,dirreport.getName()+string("/")+dirreport.getName()+string(".html"));
*opts.out << " " << endl;
}
else
*opts.out << dirreport << endl;
}
return dirreport;
}
int main (int argc, char **argv) {
int option;
struct options opts={false,false,false,false,false,false,false,false,false,""};
static struct option long_options[] = {
{"all-files",no_argument,0,'a'},
{"show-all",no_argument,0,'A'},
// {"all-mp3",no_argument,0,'Q'}, ??????
{"dirs",no_argument,0,'d'},
{"files",no_argument,0,'f'},
{"help",no_argument,0,'h'},
{"html",no_argument,0,'H'},
{"recursive",no_argument,0,'r'},
{"summary",no_argument,0,'s'},
{"split",no_argument,0,'S'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.mp3 ...
if (argc==1) {
usage();
return 1;
}
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "aAdfhHo:rsSvV",long_options,0)) != EOF)
switch (option) {
case 'a': opts.all = true; break;
case 'A': opts.showdirs=opts.showfiles=opts.showsummary = true; break;
case 'd': opts.showdirs = true; break;
case 'f': opts.showfiles = true; break;
case 'h': usage(); return 0; break;
case 'H': opts.html = true; break;
case 'r': opts.recursive = true; break;
case 's': opts.showsummary = true;break;
case 'S': opts.split = true; break;
case 'v': opts.verbose = true; break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc<=optind) {
// hauríem de fer *.mp3 ...
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
qreport base;
opts.out = new ofstream(1);
if (opts.split)
opts.out = new ofstream("/dev/null");
else {
opts.out = new ofstream(1);
if (opts.html)
*opts.out << "\nqmp3report \n\n\n\n";
}
for (; optind4 && !strncasecmp((char*)(&(argv[optind][length-4])),".mp3",4))
base.add(report_mp3(argv[optind],opts));
else {
if (opts.all)
base.add(report_file(argv[optind],opts));
}
continue;
}
if (opts.verbose)
cerr << argv[optind] << _(" is a special file. skipping.") << endl;
}
catch (qexception e) {
cerr << e << endl;
}
}
if (opts.showsummary) {
if (!opts.html || opts.split) {
cout << base << endl;
}
else {
base.html(new ofstream(1));
cout << " " << endl;
}
}
if (!opts.split) {
if (opts.html) {
*opts.out << "\n\n";
}
}
opts.out->close();
}
quelcom-0.4.0/bin/qwavcut.cc 100644 0 0 10122 7245453630 14034 0 ustar root root # include // getopt
# include "qwav.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: extract and/or delete parts of a wav file\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file\n"),APPNAME);
cerr << _(" options:\n");
cerr << _(" -B, --set-begin : set the first sample from the beginning of the file\n");
cerr << _(" -b, --set-begin-from-eof : set the first sample from the end of the file\n");
cerr << _(" -d, --delete: deletes the fragment\n");
cerr << _(" -E, --set-end : set the last sample from the beginning of the file\n");
cerr << _(" -e, --set-end-from-eof : set the last sample from the end of the file\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -o, --output : output file where the fragment is stored\n");
cerr << _(" -s, --size : specifies the size of the cut\n");
cerr << _(" -S, --slice -: set the cut as a time slice\n");
cerr << _(" -v, --verbose: verbose\n");
cerr << _(" -V, --version: show version and exit\n");
cerr << _(" = [j|s|m|b|k|M]\n");
cerr << _(" = [[h:]m:]s[.ms]\n");
cerr << _(" see info manual for more info about options and usage\n");
}
int main (int argc, char **argv) {
string outfile;
string infile;
bool del = false, verbose=false, slice_defined = false;
qvf vfbegin,vfSize,vfend,vfBegin,vfEnd;
static struct option long_options[] = {
{"set-begin",required_argument,0,'B'},
{"set-begin-from-eof",required_argument,0,'b'},
{"delete",no_argument,0,'d'},
{"set-end",required_argument,0,'E'},
{"set-end-from-eof",required_argument,0,'e'},
{"help",no_argument,0,'h'},
{"output",required_argument,0,'o'},
{"size",required_argument,0,'s'},
{"slice",required_argument,0,'S'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
int option;
qcuthandler h;
// supress getopt error messages:
opterr = 0;
while ((option = getopt_long(argc, argv, "b:B:de:E:ho:s:S:vV",long_options,0)) != EOF)
try {
switch (option) {
case 'b':
vfbegin = qvf(optarg);
break;
case 'B':
vfBegin = qvf(optarg);
break;
case 'd':
del=true;
break;
case 'e':
vfend = qvf(optarg);
break;
case 'E':
vfEnd = qvf(optarg);
break;
case 'h':
usage();
return 1;
break;
case 'o':
outfile=optarg;
break;
case 's':
vfSize = qvf(optarg);
break;
case 'S':
slice_defined = true;
h = qcuthandler(optarg);
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
}
catch (qexception e) {
cerr << e << endl;
}
if (argc-optind!=1) {
cerr << APPNAME << _(": only one file to cut must be specified") << endl;
usage();
return 1;
}
infile = argv[optind];
if (!slice_defined) {
h.setBegin(vfBegin);
h.setbegin(vfbegin);
h.setEnd(vfEnd);
h.setend(vfend);
}
h.setSize(vfSize);
h.setDel(del);
h.setOutfile(outfile);
try {
u_int32_t mode = del?qwav::READWRITE:qwav::READ;
qwav wav (infile,mode);
wav.cut(h);
if (verbose) {
cerr << wav << endl;
if (outfile!="") {
qwav wavout(outfile);
cerr << wavout << endl;
}
}
}
catch (qexception e) {
cerr << e << endl;
return 1;
}
return 0;
}
quelcom-0.4.0/bin/qwavfade.cc 100644 0 0 11623 7245453630 14147 0 ustar root root # include // getopt
# include "qwav.hh"
# include "qwavsample.hh"
# include "qexception.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: fade in/out wav files\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" -d, --duration [j|s|m|b|k|M]: set the fade duration\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -i, --in: just fade in\n");
cerr << _(" -l, --length [[h:]m:]s[.ms]: set the fade duration.\n");
// cerr << _(" -m, --mode : select the type of fade {linear,quadpos,quadneg} \n");
cerr << _(" -o, --out: just fade out\n");
cerr << _(" -t, --test: don't modify. create and fade a test file\n");
cerr << _(" -v, --verbose: show more detailed info\n");
cerr << _(" -V, --version: show version and exit\n");
cerr << _(" see info manual for more info about options and usage\n");
}
int main (int argc, char **argv) {
int option;
qvf duration(5,qvf::SECONDS);
bool in=true,out=true,verbose=false,test=false;
static struct option long_options[] = {
{"duration",required_argument,0,'d'},
{"help",no_argument,0,'h'},
{"in",no_argument,0,'i'},
{"length",required_argument,0,'l'},
// {"mode",required_argument,0,'m'},
{"out",no_argument,0,'o'},
{"test",no_argument,0,'t'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.wav ...
if (argc==1) {
usage();
return 1;
}
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "d:hil:otvV",long_options,0)) != EOF)
switch (option) {
case 'd':
try { duration = qvf(optarg); }
catch (qexception e) { cerr << e << endl; }
break;
case 'h':
usage();
return 0;
break;
case 'i':
in=true;
out=false;
break;
case 'l':
try {
duration = qvf(time2ms(optarg),qvf::MILLISECONDS);
}
catch (qexception e) { cerr << e << endl; }
break;
case 'o':
out=true;
in=false;
break;
case 't':
test = true;
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc<=optind) {
// hauríem de fer *.wav ...
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
u_int32_t wavmode = test?qwav::READ:qwav::READWRITE;
while (argv[optind]) {
if (verbose)
cerr.form(_("fading '%s'...\n"),argv[optind]);
qwav *wav = new qwav(argv[optind],wavmode);
u_int32_t nsamples = wav->getSample(duration); // dins del rang?
if (in && out && nsamples>wav->getSamples()/2) {
cerr << APPNAME << _(": both fades overlap. they'd be done separately\n");
optind++;
continue;
}
if (in) { // fade in:
if (test) {
string name(string("fadein.")+wav->getName());
qvf size(nsamples+5*wav->getSampleRate());
qcuthandler h;
h.setOutfile(name);
h.setSize(size);
wav->cut(h);
if (verbose)
cerr.form(_("created testfile '%s'\n"),name.c_str());
delete wav;
wav = new qwav(name,qwav::READWRITE);
}
qwavsample sample(wav);
double factor;
for (u_int32_t i=0; igetName().c_str());
}
delete wav;
wav = new qwav(argv[optind],wavmode);
if (out) { // fade out
if (test) {
string name(string("fadeout.")+wav->getName());
qvf begin(nsamples+5*wav->getSampleRate());
qcuthandler h;
h.setOutfile(name);
h.setbegin(begin);
wav->cut(h);
if (verbose)
cerr.form(_("created testfile '%s'\n"),name.c_str());
delete wav;
wav = new qwav(name,qwav::READWRITE);
}
qwavsample sample(wav,wav->getSamples()-nsamples+1);
double factor;
for (int i=nsamples; i>0; i--) {
factor = (double)i/(double)nsamples;
sample.prod(factor);
sample.setNext();
}
if (verbose)
cerr.form(_("faded out %d samples in '%s'\n"),nsamples,wav->getName().c_str());
}
optind++;
}
}
quelcom-0.4.0/bin/qwavheaderdump.cc 100644 0 0 15154 7245453630 15371 0 ustar root root # include // getopt
# include // u_int16_t, u_int32_t
# include "qfile.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
// see qwavheader.hh for more info about the wav header struct
struct header {
char riff[4];
u_int32_t rifflength;
char wave[4];
char fmt_[4];
u_int32_t fmtlength;
u_int16_t format;
u_int16_t channels;
u_int32_t samplerate;
u_int32_t bytespersec;
u_int16_t bytespersample;
u_int16_t bitspersample;
char data[4];
u_int32_t datalength;
};
const unsigned int HEADERSIZE = sizeof(struct header);
void usage () {
cerr.form(_(" %s: dump (and fix) wav header\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" -F, --fix: correct header. use with care\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -q, --quiet: no output messages\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
int option;
bool quiet=false, fix=false;
static struct option long_options[] = {
{"fix",no_argument,0,'F'},
{"help",no_argument,0,'h'},
{"quiet",no_argument,0,'q'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.wav ...
if (argc==1) {
usage();
return 1;
}
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "FhqV",long_options,0)) != EOF)
switch (option) {
case 'F':
fix=true;
break;
case 'h':
usage();
return 0;
break;
case 'q':
quiet=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc<=optind) {
// hauríem de fer *.wav ...
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
u_int32_t openmode = fix?qfile::READWRITE:qfile::READ;
while (argv[optind]) {
try {
qfile f(argv[optind],openmode);
if (f.getSize()riff);
if (strncmp(header->riff,"RIFF",4)) {
if (!quiet)
cerr.form(_("\t\triff field should be 'RIFF'\n"));
if (fix) {
strncpy(header->riff,"RIFF",4);
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form(_("\triff length: %d\n"),header->rifflength);
if (header->rifflength!=f.getSize()-8) {
if (!quiet)
cerr.form(_("\t\triff length field should be %d\n"),f.getSize()-8);
if (fix) {
header->rifflength = f.getSize()-8;
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form("\twave: '%.4s'\n",header->wave);
if (strncmp(header->wave,"WAVE",4)) {
if (!quiet)
cerr.form(_("\t\twave field should be 'WAVE'\n"));
if (fix) {
strncpy(header->wave,"WAVE",4);
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form("\tfmt: '%.4s'\n",header->fmt_);
if (strncmp(header->fmt_,"fmt ",4)) {
if (!quiet)
cerr.form(_("\t\tfmt field should be 'fmt '\n"));
if (fix) {
strncpy(header->fmt_,"fmt ",4);
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form(_("\tfmt length: %d\n"),header->fmtlength);
if (header->fmtlength!=16) {
if (!quiet)
cerr.form(_("\t\tfmt length field should be %d\n"),16);
if (fix) {
header->fmtlength = 16;
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form("\tformat: %d\n",header->format);
if (header->format!=1) {
if (!quiet)
cerr.form(_("\t\tformat field should 1 (pcm tag)\n"),16);
if (fix) {
header->format = 1;
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form(_("\tchannels: %d\n"),header->channels);
if (header->channels!=2 && header->channels!=1) {
if (!quiet)
cerr.form(_("\t\tchannels field should be 1 (mono) or 2 (stereo)\n"));
if (fix) {
cerr << _("\t\tdon't know which value must be set...\n") << endl;
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form(_("\tsample rate: %d\n"),header->samplerate);
if (header->samplerate>48000 || header->samplerate<8000) {
if (!quiet)
cerr.form(_("\t\tsample rate field should be between 8000 and 48000\n"));
if (fix)
cerr << _("\t\tdon't know which value must be set...\n") << endl;
}
cout.form(_("\tbytes/second: %d\n"),header->bytespersec);
cout.form(_("\tbytes/sample: %d\n"),header->bytespersample);
if (header->bytespersample!=1 &&
header->bytespersample!=2 &&
header->bytespersample!=4) {
if (!quiet)
cerr.form(_("\t\t bytes/sample field should be 1, 2 or 4\n"));
if (fix)
cerr << _("\t\tdon't know which value must be set...\n") << endl;
}
cout.form(_("\tbits/sample: %d\n"),header->bitspersample);
cout.form("\tdata: '%.4s'\n",header->data);
if (strncmp(header->data,"data",4)) {
if (!quiet)
cerr.form(_("\t\tdata field should be 'data'\n"));
if (fix) {
strncpy(header->data,"data",4);
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
cout.form(_("\tdata length: %d\n"),header->datalength);
if (header->datalength!=f.getSize()-44) {
if (!quiet)
cerr.form(_("\t\tdata length field should be %d\n"),f.getSize()-44);
if (fix) {
header->datalength = f.getSize()-44;
if (!quiet)
cerr << _("\t\tfixed\n");
}
}
}
catch (qexception e) {
cerr << argv[optind] << ": " << e << endl;
}
optind++;
}
}
quelcom-0.4.0/bin/qwavinfo.cc 100644 0 0 6002 7245453630 14156 0 ustar root root # include // getopt
# include
# include "qwav.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: show info from wav files\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -s, --summary-only: show only the summary\n");
cerr << _(" -v, --verbose: verbose\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
int option;
bool verbose=false;
bool summarize=false;
static struct option long_options[] = {
{"help",no_argument,0,'h'},
{"summary-only",no_argument,0,'s'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.wav ...
if (argc==1) {
usage();
return 1;
}
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "hsvV",long_options,0)) != EOF)
switch (option) {
case 'h':
usage();
return 0;
break;
case 's':
summarize=true;
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc<=optind) {
// hauríem de fer *.wav ...
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
u_int32_t files=0, errors=0;
u_int32_t msduration, bytes, samples;
u_int32_t total_bytes=0, total_samples=0, total_msduration=0;
while (argv[optind]) {
files++;
try {
qwav p(argv[optind]);
msduration = p.getMsDuration();
total_msduration += msduration;
if (!summarize)
cout << p;
if (verbose) {
bytes = p.getSize();
samples = p.getSamples();
if (!summarize)
cout << " " << bytes << " bytes " << samples << " samples";
total_bytes += bytes;
total_samples += samples;
}
if (!summarize)
cout << endl;
}
catch (qexception e) {
cerr << argv[optind] << ": " << e << endl;
errors++;
}
optind++;
}
cout.form (_("%u file%c"),files,files>1?'s':0);
if (errors)
cout.form (" (%u error%c)",errors,errors>1?'s':0);
if (verbose)
cout.form (_(" => %d:%02d.%03d %u samples %u bytes\n"),
total_msduration/60000,(total_msduration/1000)%60,
total_msduration%1000,total_samples,total_bytes);
else
cout.form (" => %d:%02d\n",
total_msduration/60000,(total_msduration/1000)%60);
}
quelcom-0.4.0/bin/qwavjoin.cc 100644 0 0 5177 7245453630 14176 0 ustar root root # include // getopt
# include "qwav.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: join wav files\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file1 file2...\n"),APPNAME);
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -o, --output : send output to . otherwise, append to \n");
cerr << _(" -v, --verbose: verbose\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
bool verbose=false;
string outfile;
static struct option long_options[] = {
{"help",no_argument,0,'h'},
{"output",required_argument,0,'o'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
if (argc==1) {
usage();
return 1;
}
int option;
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "ho:vV",long_options,0)) != EOF)
switch (option) {
case 'h':
usage();
return 0;
break;
case 'o':
outfile=optarg;
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc-optind<2) {
cerr << APPNAME << _(": at least two files to join must be specified\n");
usage();
return 1;
}
argv += optind;
qwav *wav;
try {
// resolve which is the first file
if (outfile!="") {
wav = new qwav(*argv);
if (verbose)
cerr.form(_("copying '%s' to '%s'..."),*argv,outfile.c_str());
wav->dup(outfile);
if (verbose)
cerr << "ok." << endl;
delete wav;
wav = new qwav (outfile,qwav::READWRITE);
}
else
wav = new qwav(*argv,qwav::READWRITE);
// append the rest of the files
while (*++argv) {
qwav ww(*argv);
if (verbose)
cerr.form(_("appending '%s' to '%s'..."),
ww.getName().c_str(),wav->getName().c_str());
wav->append(ww);
if (verbose)
cerr << "ok." << endl;
}
}
catch (qexception e) {
cerr << *argv << ": " << e << endl;
return 1;
}
if (verbose)
cerr << *wav << endl;
delete wav;
return 0;
}
quelcom-0.4.0/bin/qwavsilence.cc 100644 0 0 20350 7245453630 14667 0 ustar root root # include // getopt
# include "qwav.hh"
# include "qwavsample.hh"
# include "qexception.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
void usage () {
cerr.form(_(" %s: detect and shrink silence sequence in wav files\n"),APPNAME);
cerr.form(_(" syntax: %s [option]... file...\n"),APPNAME);
cerr << _(" -d, --duration [j|s|m|b|k|M]: set the minimum silence duration.\n");
cerr << _(" -h, --help: show this help and exit\n");
cerr << _(" -l, --length [[h:]m:]s[.ms]: set the minimum silence duration.\n");
cerr << _(" -S, --shrink: shrink silences greater than 'duration'. use with care.\n");
cerr << _(" -t, --threshold : set the maximum value (in %) for silent samples\n");
cerr << _(" -v, --verbose: show more detailed info\n");
cerr << _(" -V, --version: show version and exit\n");
}
int main (int argc, char **argv) {
int option;
u_int32_t threshold=0;
qvf duration(1,qvf::SECONDS);
bool shrink=false, verbose=false;
static struct option long_options[] = {
{"duration",required_argument,0,'d'},
{"help",no_argument,0,'h'},
{"length",required_argument,0,'l'},
{"shrink",no_argument,0,'S'},
{"threshold",required_argument,0,'t'},
{"verbose",no_argument,0,'v'},
{"version",no_argument,0,'V'},
{0,0,0,0}
};
#ifdef NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
// un altre dia, per defecte llegir *.wav ...
if (argc==1) {
usage();
return 1;
}
double temp;
// supress getopt error message
opterr = 0;
while ((option = getopt_long(argc, argv, "d:hl:St:vV",long_options,0)) != EOF)
switch (option) {
case 'd':
try { duration = qvf(optarg); }
catch (qexception e) { cerr << e << endl; }
break;
case 'h':
usage();
return 0;
break;
case 'l':
try {
duration = qvf(time2ms(optarg),qvf::MILLISECONDS);
}
catch (qexception e) { cerr << e << endl; }
break;
case 'S':
shrink=true;
break;
case 't':
temp = strtod(optarg,0);
if (temp<0 || temp>100) {
cerr.form(_("%s: threshold must be 0..100 (%d)\n"),APPNAME,temp);
return 1;
}
threshold = (u_int32_t)temp;
break;
case 'v':
verbose=true;
break;
case 'V':
cerr.form(_("%s - version %s - build %s\n"),APPNAME,VERSION,__DATE__);
return 0;
break;
case '?':
default:
cerr.form(_("%s: option '%s' is not recognized or bad used\n"),
APPNAME,argv[optind-1]);
usage();
return 1;
}
if (argc<=optind) {
// hauríem de fer *.wav ...
cerr << APPNAME << _(": no input file(s)") << endl;
usage();
return 1;
}
u_int32_t files=0, errors=0;
u_int32_t duration_samples, threshold_value;
u_int32_t total_silent_samples, sample_number, shrinked_samples;
while (argv[optind]) {
files++;
try {
qwav wav(argv[optind],shrink?qwav::READWRITE:qwav::READ);
duration_samples = wav.getSample(duration);
// the % value depends on bits/sample
threshold_value = threshold*(1<<(wav.getBitsPerSample()-1))/100;
sample_number = wav.getSamples();
if (sample_number<1) {
if (verbose)
cerr << *argv << _(": empty") << endl;
optind++;
continue;
}
if (sample_numberisSilence(threshold_value)) {
silent_samples++;
sample_index++;
sample->setNext();
}
if (silent_samples) {
if (silent_samples>=duration_samples) {
u_int32_t mssec_begin, mssec_end;
mssec_begin = 1000LL*(sample_index-silent_samples)/wav.getSampleRate();
mssec_end = (1000LL*silent_samples)/wav.getSampleRate();
if (!verbose)
cout.form(_("%s: %d:%02d of silence at %d:%02d\n"),
argv[optind],
mssec_end/60000,(mssec_end/1000)%60,
mssec_begin/60000,(mssec_begin/1000)%60);
else
cout.form(_("%s: %d:%02d.%03d (%d samples) at %d:%02d:%03d (sample %d)\n"),
argv[optind],
mssec_end/60000,(mssec_end/1000)%60,mssec_end%1000,
silent_samples,
mssec_begin/60000,(mssec_begin/1000)%60,mssec_begin%1000,
sample_index-silent_samples);
total_silent_samples+=silent_samples;
if (shrink) {
u_int32_t shrinkable_samples = silent_samples - duration_samples;
cerr.form(_("shrink %d samples at %d\n"),
shrinkable_samples,sample_index - shrinkable_samples - 1);
if (shrinked_samples) {
u_int32_t samples_moved = sample_index-shrinkable_samples-(first_shrinkable_sample+shrinked_samples+1);
cerr.form(_("move %d..%d (%d samples) to %d..%d\n"),
first_shrinkable_sample+shrinked_samples+1,
sample_index-shrinkable_samples-1,
samples_moved,
first_shrinkable_sample,
first_shrinkable_sample+samples_moved);
wav.move(first_shrinkable_sample+shrinked_samples+1,
sample_index-shrinkable_samples-1,
first_shrinkable_sample);
}
shrinked_samples += shrinkable_samples;
first_shrinkable_sample = sample_index - shrinked_samples - 1;
}
}
// else
// if very-very-verbose ...
}
// skip non silent region by looking for non silent samples ahead
u_int32_t test_index = duration_samples;
while (sample_index+duration_samples <= sample_number
&& test_index>=1) {
qwavsample test_sample(&wav,sample_index+test_index);
if (test_sample.isSilence(threshold_value))
test_index >>= 1;
else {
sample_index += test_index;
test_index = duration_samples;
}
}
if (test_index==0)
sample_index++;
else { // sortim del bucle pq s'ha acabat el fitxer...
if (shrink && shrinked_samples) {
u_int32_t samples_moved = sample_number-(first_shrinkable_sample+shrinked_samples+1);
cerr.form(_("move %d..%d (%d samples) to %d..%d\n"),
first_shrinkable_sample+shrinked_samples+1,
sample_number,
samples_moved,
first_shrinkable_sample,
first_shrinkable_sample+samples_moved);
wav.move(first_shrinkable_sample+shrinked_samples+1,
sample_number,
first_shrinkable_sample);
}
}
}
if (verbose) {
u_int32_t mssec = 1000LL*total_silent_samples/wav.getSampleRate();
cerr.form(_("%s: total silence reported: %d:%02d.%02d (%d samples)\n"),
argv[optind],mssec/60000,(mssec/1000)%60,(mssec%1000)/10,
total_silent_samples);
}
if (shrinked_samples) {
wav.truncate(sample_number-shrinked_samples);
if (verbose)
cerr << "truncating down to " << sample_number-shrinked_samples << " samples" << endl;
}
}
catch (qexception e) {
cerr << argv[optind] << ": " << e << endl;
errors++;
}
optind++;
}
if (errors)
cout.form ("%u error%c\n",errors,errors>1?'s':0);
}
quelcom-0.4.0/bin/makefile 100644 0 0 1560 7245453630 13521 0 ustar root root
MP3BIN=qmp3report qmp3check qmp3info qmp3join qmp3cut
MP3BINOBJ=$(addsuffix .o,$(MP3BIN))
WAVBIN=qwavheaderdump qwavfade qwavsilence qwavinfo qwavjoin qwavcut
WAVBINOBJ=$(addsuffix .o,$(WAVBIN))
BINTARGETS=$(MP3BIN) $(WAVBIN)
all: $(BINTARGETS)
#
# if you don't want to include native language support (=get quelcom messages
# in a different language than english) remove -DNLS and -DLOCALEDIR... below
#
CXXFLAGS=-DNLS -Wall -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" -DLOCALEDIR=\"$(LOCALEDIR)\" -I./../lib
LDFLAGS=-lm -L./../lib
$(MP3BINOBJ) $(WAVBINOBJ): %.o: %.cc
$(CXX) $(CXXFLAGS) -DAPPNAME=\"$*\" -o $@ -c $<
$(MP3BIN): %: %.o
$(CXX) -o $@ $< -L./../lib -lqextra -lqmp3
strip $@
$(WAVBIN): %: %.o
$(CXX) -o $@ $< -L./../lib -lqextra -lqwav
strip $@
install: all
mkdir -p $(BINDIR)
cp -f $(BINTARGETS) $(BINDIR)
clean:
rm -f *.o $(BINTARGETS)
quelcom-0.4.0/lib/ 40755 0 0 0 7245453630 11720 5 ustar root root quelcom-0.4.0/lib/qcuthandler.cc 100644 0 0 3134 7245453630 14637 0 ustar root root /*! \file
* implementation functions for class qcuthandler
*/
# include "qcuthandler.hh"
# include "qmisc.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
qcuthandler::qcuthandler():del(false) { }
qcuthandler::qcuthandler(char *str):del(false) {
char *left,*right;
left = str;
right = strchr(str,'-');
if (!right)
throw qexception(__PRETTY_FUNCTION__,_("no '-' found"));
else
*right++=0;
// if left or right time specifiers are empty, take default values:
// beginning and end of file respectively.
// notice that '-' is now 0.
if (*left)
Begin = qvf(time2ms(left),qvf::MILLISECONDS);
cerr << Begin << endl << flush;
if (*right)
End = qvf(time2ms(right),qvf::MILLISECONDS);
cerr << End << endl << flush;
// es pot comprovar ja ací que begin<=end...
// cerr << *this << endl << flush;
}
void qcuthandler::setBegin (qvf &B) { Begin = B; }
void qcuthandler::setEnd (qvf &E) { End = E; }
void qcuthandler::setbegin (qvf &b) { begin = b; }
void qcuthandler::setend (qvf &e) { end = e; }
void qcuthandler::setSize (qvf &s) { size = s; }
void qcuthandler::setOutfile (string o) { outfile = o; }
void qcuthandler::setDel (bool d) { del = d; }
qvf& qcuthandler::getBegin() { return Begin; }
qvf& qcuthandler::getEnd() { return End; }
qvf& qcuthandler::getbegin() { return begin; }
qvf& qcuthandler::getend() { return end; }
qvf& qcuthandler::getSize() { return size; }
string qcuthandler::getOutfile () { return outfile; }
bool qcuthandler::getDel() { return del; }
quelcom-0.4.0/lib/qexception.cc 100644 0 0 527 7245453630 14467 0 ustar root root /*! \file
* implementation functions for class qexception
*/
# include "qexception.hh"
string qexception::getInfo() {
return info;
}
void qexception::print (ostream *os) {
#ifdef QVERBOSE
*os << metode << ": " << info;
#else
*os << info;
#endif
}
ostream &operator<<(ostream &os, qexception &e) {
e.print(&os);
return os;
}
quelcom-0.4.0/lib/qfile.cc 100644 0 0 14344 7245453630 13452 0 ustar root root /*! \file
* implementation functions for class qfile
*/
# include // lseek
# include // mmap, munmap
# include // close, ftruncate, write
# include // strerror, memmove
# include // errno
# include // open
# include // string
// AFEGIR UN QVERBOSE AL FINAL DE CADA FUNCIO
# include "qfile.hh"
# include "qexception.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
// revisar l'umask. el millor seria fer l'open normal sense això i el creat, o bé passar-lo a un open+creat+trunc, o bé posar-hi un valor que no afecti a l'umask i així es passa la "culpa" a l'usuari...
# define CREATION_MASK (S_IRUSR|S_IWUSR)
const u_int32_t qfile::READ=O_RDONLY,
qfile::WRITE=O_WRONLY,
qfile::READWRITE=O_RDWR,
qfile::TRUNCATE=O_TRUNC;
const u_int32_t qfile::NEW = qfile::READWRITE|qfile::TRUNCATE|O_CREAT;
qfile::qfile(string filename, u_int32_t f) {
name = filename;
flags = f;
if (flags&WRITE || flags&TRUNCATE || flags&READWRITE)
mapflags=PROT_READ|PROT_WRITE;
else
mapflags=PROT_READ;
if ((fd=open(filename.c_str(),flags,CREATION_MASK))==-1)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
struct stat stat;
if (fstat(fd,&stat)) {
close(fd);
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
}
if (!S_ISREG(stat.st_mode)) {
close(fd);
throw qexception(__PRETTY_FUNCTION__,_("not a regular file"));
}
size = stat.st_size;
if ((map=(caddr_t)mmap((caddr_t)0,size,mapflags,MAP_SHARED,fd,0))==MAP_FAILED) {
close(fd);
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
}
#ifdef QVERBOSE
cerr << "file '" << *this << "' successfully mapped at address " << (void*)getMap() << endl;
#endif
}
qfile::~qfile() {
// munmap always gives an error when unmapping empty files...
if (size>0)
if (munmap(map,size))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (close(fd))
#ifdef QVERBOSE
cerr << getName() << ": altre cop el close" << endl;
#else
;
#endif
}
u_int32_t qfile::truncate (u_int32_t newsize) {
if (newsize>=size)
return size;
if (munmap(map,size))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (ftruncate(fd,newsize))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
size = newsize;
if ((map=(caddr_t)mmap(map,size,mapflags,MAP_SHARED,fd,0))==MAP_FAILED)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
return size;
}
u_int32_t qfile::move (u_int32_t start, u_int32_t end, u_int32_t dest) {
if (start>end)
throw qexception(__PRETTY_FUNCTION__,
string("move: end(")+uint2string(end)+string(")size)
throw qexception(__PRETTY_FUNCTION__,
string("move: start(")+uint2string(start)+
string(") is out of file"));
if (end>size)
end = size;
if (dest+end-start+1>size)
end = start+(size-dest)-1;
char *base = (char*)map;
memmove(base+dest,base+start,end-start+1);
return end-start+1;
}
u_int32_t qfile::cut (u_int32_t start, u_int32_t end) {
if (start>size)
return size;
if (end=size)
end = size-1;
memmove((char*)map+start,(char*)map+end+1,size-1-end);
truncate(size-(end-start+1));
return size;
}
u_int32_t qfile::append (qfile f) {
if (munmap(map,size))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (lseek(fd,0,SEEK_END)==-1)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (write(fd,f.getMap(),f.getSize())!=(int)f.getSize())
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
size += f.getSize();
if ((map=(caddr_t)mmap(map,size,mapflags,MAP_SHARED,fd,0))==MAP_FAILED)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
return size;
}
/*
u_int32_t qfile::append (qfile f, u_int32_t start, u_int32_t end) {
cerr << "this code is buggy. use another append!!" << endl;
if (start>end)
throw qexception(__PRETTY_FUNCTION__,
string("append: end(")+uint2string(end)+string(")=f.getSize())
return size;
if (end>=f.getSize())
end = f.getSize()-1;
if (munmap(map,size))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (lseek(fd,0,SEEK_END)==-1)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (write(fd,f.getMap()+start,end-start+1)!=(int)(end-start+1))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
size += end-start+1;
if ((map=(caddr_t)mmap(map,size,mapflags,MAP_SHARED,fd,0))==MAP_FAILED)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
return size;
}
*/
u_int32_t qfile::append (caddr_t pointer, u_int32_t appsize) {
if (size)
if (munmap(map,size))
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (lseek(fd,0,SEEK_END)==-1)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
if (write(fd,pointer,appsize)!=(int)appsize)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
size += appsize;
if ((map=(caddr_t)mmap(map,size,mapflags,MAP_SHARED,fd,0))==MAP_FAILED)
throw qexception(__PRETTY_FUNCTION__,strerror(errno));
return size;
}
qfile qfile::dup(string newname) {
int newfd;
if ((newfd=creat(newname.c_str(),CREATION_MASK))==-1)
throw qexception(__PRETTY_FUNCTION__,newname+string(strerror(errno)));
if (write(newfd,getMap(),getSize())!=(int)getSize())
throw qexception(__PRETTY_FUNCTION__,newname+string(strerror(errno)));
close (newfd);
return qfile(newname);
}
caddr_t qfile::getMap() { return map; }
u_int32_t qfile::getSize() { return size; }
string qfile::getName() { return name; }
void qfile::print (ostream *os) { *os << getName(); }
ostream& operator<<(ostream &os, qfile &f) {
f.print(&os);
return os;
}
quelcom-0.4.0/lib/qmisc.cc 100644 0 0 7730 7245453630 13447 0 ustar root root /*! \file
* miscellaneous functions
*/
# include
# include
# include
# include
# include "qexception.hh"
# include
# include
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
u_int32_t time2ms (char *str) {
// char a[]="7.7";
char *endptr = (char*)!0; // no-null
u_int32_t h=0,m=0,s=0,ms=0;
s = strtol(str,&endptr,10);
if (str==endptr)
throw qexception(__PRETTY_FUNCTION__,_("invalid time specification"));
str = endptr;
if (*str==':') {
str++;
m = s;
s = strtol(str,&endptr,10);
if (str==endptr)
throw qexception(__PRETTY_FUNCTION__,_("invalid time specification"));
str = endptr;
}
if (*str==':') {
str++;
h = m;
m = s;
s = strtol(str,&endptr,10);
if (str==endptr)
throw qexception(__PRETTY_FUNCTION__,_("invalid time specification"));
str = endptr;
}
// printf("%g\n",strtod(a,&endptr));
if (*str=='.') {
*--str='0';
// printf("%s\n",str);
// printf("%g %g %d\n",strtod(str,&endptr),1000*strtod(str,&endptr),(unsigned int)rint(strtod(str,&endptr)*1000LL));
ms = (u_int32_t)rint(strtod(str,&endptr)*1000LL);
// printf("%g %d\n",strtod(str,&endptr),ms);
if (str==endptr)
throw qexception(__PRETTY_FUNCTION__,_("invalid time specification"));
str=endptr;
}
if (*str)
throw qexception(__PRETTY_FUNCTION__,_("invalid time specification"));
else
return 3600000*h + 60000*m + 1000*s + ms;
}
u_int32_t time2msec (char *str) {
char *index;
char *secure;
u_int32_t milliseconds = 0;
// sure there aren't invalid chars
if (strlen(str)!=strspn(str,"0123456789:."))
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(str));
// look for milliseconds part
index = strrchr(str,'.');
if (index) {
*index=0;
milliseconds += (u_int32_t) strtod (index+1,&secure);
if (*secure!=0)
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(index+1));
}
if (!strlen(str))
return milliseconds;
// look for seconds part
index = strrchr(str,':');
if (index) {
*index=0;
milliseconds += 1000 * (u_int32_t) strtod (index+1,&secure);
if (*secure!=0)
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(index+1));
}
else {
milliseconds += 1000 * (u_int32_t) strtod (str,&secure);
if (*secure!=0)
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(index+1));
return milliseconds;
}
cerr << "time2sec: ms=" << milliseconds << endl;
// look for minutes part
index = strrchr(str,':');
if (index) {
*index=0;
milliseconds += 60 * 1000 * (u_int32_t) strtod (index+1,&secure);
if (*secure!=0)
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(index+1));
}
else {
milliseconds += 60 * 1000 * (u_int32_t) strtod (str,&secure);
if (*secure!=0)
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(index+1));
return milliseconds;
}
cerr << "time2sec: ms=" << milliseconds << endl;
// look for hours part
milliseconds += 60 * 60 * 1000 * (u_int32_t) strtod (str,&secure);
if (*secure!=0)
throw qexception(__PRETTY_FUNCTION__,
string("invalid char in ")+string(index+1));
return milliseconds;
}
string uint2string (u_int32_t ui) {
char buf[16];
sprintf(buf,"%u",ui);
return string(buf);
}
string char2string (char c) {
char buf[2];
sprintf(buf,"%c",c);
return string(buf);
}
bool strcmpn (char *str1, char *str2, u_int32_t n) {
while (n && (*str1==*str2)) {
str1++;
str2++;
n--;
}
return n==0;
}
string htmlize (string str) {
int pos;
while ((pos = str.find(" "))!=-1)
str.replace(pos,1,"%20");
return str;
}
quelcom-0.4.0/lib/qmp3.cc 100644 0 0 30222 7245453630 13223 0 ustar root root /*! \file
* implementation functions for class qmp3
*/
# include "qmp3.hh"
# include "qexception.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
u_int32_t qmp3::append (qmp3 &mp3, bool force) {
// compatible guarantees both files are scanned
if (!compatible(mp3,force))
throw qexception (__PRETTY_FUNCTION__,
getName() + string(": ") +
mp3.getName() + string(_(" is not compatible")));
if (hasTag) {
qfile::truncate(getStreamLength());
remap(qfile::getMap());
hasTag = false;
}
qfile::append(mp3.qfile::getMap(),mp3.getStreamLength());
remap(qfile::getMap());
if (force && mp3.isVbr())
vbr=true;
frames += mp3.getFrames();
msduration += mp3.getMsDuration();
return frames;
}
bool qmp3::compatible(qmp3 &mp3, bool force) {
if (!isScanned())
scan();
if (!mp3.isScanned())
mp3.scan();
if (force)
return true;
if (isVbr() && mp3.isVbr())
return true;
// i la resta de paràmetres...? actualitzar a la plana man/texinfo del qmp3join
return getBitRate()==mp3.getBitRate();
}
u_int32_t qmp3::getMsDuration() {
return (1000ULL * getFrames() * getSamplesPerFrame()) / getSampleRate();
}
qmp3::qmp3(string name, u_int32_t flags=READ)
: qfile (name,flags),
qmp3frameheader (qfile::getMap()),
qtag (qfile::getMap()+getSize()-qtag::LENGTH) {
hasTag = isValid();
// frames = scan(getStreamLength());
scanned = false;
vbr = isVbr();
frames = getStreamLength()/qmp3frameheader::getLength();
#ifdef QVERBOSE
cerr << "mp3 file " << *this << " successfully opened." << endl;
#endif
}
// a ugly chooped scan() to discover fastly vbr streams
bool qmp3::isVbr() {
if (scanned)
return vbr;
u_int32_t bufsize = getStreamLength();
qmp3frameheader *fh = new qmp3frameheader(*this);
// if the file is little, easier to do a normal scan
// otherwise, there should be room enough for (int i=5) frames...
if (bufsize<10*fh->getLength()) {
scan();
return vbr;
}
u_int32_t bitrate = fh->getBitRate();
bufsize -= fh->getLength();
for (int i=5; i>0; i--) {
fh->setNext();
if (fh->getBitRate()!=bitrate)
return true;
}
return false;
}
u_int32_t qmp3::scan (u_int32_t bufsize=0) {
if (!bufsize)
bufsize = getStreamLength();
frames = 0;
qmp3frameheader *fh = new qmp3frameheader(*this);
u_int32_t bitrate = fh->getBitRate();
msduration = fh->getMsDuration();
if (bufsizegetLength())
throw qexception(__PRETTY_FUNCTION__,_("first frame incomplete"));
bufsize -= fh->getLength();
frames++;
// char lluna[]={"OD)|(C"};
while (bufsize>qmp3frameheader::HEADERSIZE) {
fh->setNext();
if (bufsize>=fh->getLength()) {
bufsize -= fh->getLength();
frames++;
if (fh->getBitRate()!=bitrate)
bitrate = 0;
msduration += fh->getMsDuration();
// cout << lluna[frames%6] << "\r" << flush;
}
else
throw qexception(__PRETTY_FUNCTION__,
uint2string(bufsize)+string(_(" bytes of garbage at the end")));
}
#ifdef QVERBOSE
cerr << getName() << ": " << uint2string(frames) << " frames" << endl;
#endif
if (bufsize)
throw qexception(__PRETTY_FUNCTION__,
uint2string(bufsize)+string(_(" bytes of garbage at the end")));
scanned = true;
vbr = !bitrate;
return frames;
}
void qmp3::print (ostream *os) {
u_int32_t msduration;
*os << getName() << ": mpeg " << getVersion()
<< " layer " << getLayer() << " "
<< getSampleRate() << "Hz ";
if (!vbr)
*os << getBitRate() << "kbps";
else
*os << "[vbr]";
msduration = getMsDuration();
os->form(" %d:%02d.%03d ",
msduration/60000,(msduration/1000)%60,msduration%1000);
if (hasTag)
this->qtag::print(os);
else
*os << _("[no tag]");
}
ostream &operator<<(ostream &os, qmp3 &u) {
u.print(&os);
return os;
}
/*
void qmp3::truncate (u_int32_t frames) {
if (frames>=getFrames())
return;
qmp3frameheader fh(qfile::getMap()+getOffset(frames));
qfile::truncate(getOffset(frames)+fh.getLength());
remap(qfile::getMap());
}
*/
u_int32_t qmp3::cut (qcuthandler &h) {
if ((!h.getDel()) && (h.getOutfile()==""))
return 0;
if (!scanned) {
frames = scan();
scanned = true;
}
//
// an schema with the cut specifications and what will be done
// B => begin point, from the beginning of the file
// E => end point, from the beginning of the file
// b => begin point, from the end of the file
// e => end point, from the end of the file
// s => size of the fragment
//
// 0 means not specified 1 means specified
//
// B b E e s
// 0 0 0 0 0 throw
// 0 0 0 0 1 0 .. s
// 0 0 0 1 0 0 .. e
// 0 0 0 1 1 e-s .. e
// 0 0 1 0 0 0 .. E
// 0 0 1 0 1 E-s .. E
// 0 0 1 1 0 throw
// 0 0 1 1 1 throw
// 0 1 0 0 0 b .. EOF
// 0 1 0 0 1 b .. b+s
// 0 1 0 1 0 b .. e
// 0 1 0 1 1 throw
// 0 1 1 0 0 b .. E
// 0 1 1 0 1 throw
// 0 1 1 1 0 throw
// 0 1 1 1 1 throw
// 1 0 0 0 0 B .. EOF
// 1 0 0 0 1 B .. B+s
// 1 0 0 1 0 B .. e
// 1 0 0 1 1 throw
// 1 0 1 0 0 B .. E
// 1 0 1 0 1 throw
// 1 0 1 1 0 throw
// 1 0 1 1 1 throw
// 1 1 0 0 0 throw
// 1 1 0 0 1 throw
// 1 1 0 1 0 throw
// 1 1 0 1 1 throw
// 1 1 1 0 0 throw
// 1 1 1 0 1 throw
// 1 1 1 1 0 throw
// 1 1 1 1 1 throw
// it is ugly, actually, but the table above should make things clear
u_int32_t mode=0;
if (h.getBegin().getFormat()!=qvf::UNDEFINED)
mode+=16;
if (h.getbegin().getFormat()!=qvf::UNDEFINED)
mode+=8;
if (h.getEnd().getFormat()!=qvf::UNDEFINED)
mode+=4;
if (h.getend().getFormat()!=qvf::UNDEFINED)
mode+=2;
if (h.getSize().getFormat()!=qvf::UNDEFINED)
mode+=1;
u_int32_t first_frame, last_frame;
#ifdef QVERBOSE
cerr << "cut mode: " << mode << endl;
#endif
// comprovació de zeros: -s 3b => -s 0!!
switch (mode) {
case 0:
//cerr << "cut: you must specify where to cut" << endl;
return 0;
case 1: // 1 .. s (p)
first_frame = 1;
last_frame = getFrame(h.getSize());
break;
case 2: // 1 .. e (p)
first_frame = 1;
last_frame = getFrames()+1-getFrame(h.getend());
break;
case 3: // e-s .. e (p)
last_frame = getFrames()+1-getFrame(h.getend());
first_frame = last_frame-getFrame(h.getSize())+1;
break;
case 4: // 1 .. E (p)
first_frame = 1;
last_frame = getFrame(h.getEnd());
break;
case 5: // E-s .. E (p)
last_frame = getFrame(h.getEnd());
first_frame = last_frame-getFrame(h.getSize())+1;
break;
case 6: // E+e => throw (p)
case 7: // E+e+s => throw (p)
case 14: // b+E+e => throw (p)
case 15: // b+E+e+s => throw (p)
case 22: // B+E+e => throw (p)
case 23: // B+E+e+s => throw (p)
throw qexception(__PRETTY_FUNCTION__,
_("options -E and -e cannot be used together"));
case 8: // b .. EOF (p)
first_frame = getFrames()+1-getFrame(h.getbegin());
last_frame = getFrames();
break;
case 9: // b .. b+s (p)
first_frame = getFrames()+1-getFrame(h.getbegin());
last_frame = first_frame+getFrame(h.getSize())-1;
break;
case 10: // b .. e (p)
first_frame = getFrames()+1-getFrame(h.getbegin());
last_frame = getFrames()+1-getFrame(h.getend());
break;
case 11: // b+e+s
case 13: // b+E+s
case 19: // B+e+s
case 21: // B+E+s
throw qexception(__PRETTY_FUNCTION__,
_("options (-b or -B), (-e or -E) and -s cannot be used together"));
case 12: // b .. E (p)
first_frame = getFrames()+1-getFrame(h.getbegin());
last_frame = getFrame(h.getEnd());
break;
case 16: // B .. EOF (p)
first_frame = getFrame(h.getBegin());
last_frame = getFrames();
break;
case 17: // B .. B+s (p)
first_frame = getFrame(h.getBegin());
last_frame = first_frame+getFrame(h.getSize())-1;
break;
case 18: // B .. e (p)
first_frame = getFrame(h.getBegin());
last_frame = getFrames()+1-getFrame(h.getend());
break;
case 20: // B .. E
first_frame = getFrame(h.getBegin());
last_frame = getFrame(h.getEnd());
break;
case 24 ... 31: // B+b+...
throw qexception(__PRETTY_FUNCTION__,
_("options -B and -b cannot be used together"));
default: // this should never happen
cerr << "quelcom panic!" << endl;
return 0;
}
#ifdef QVERBOSE
cerr << "cut: " << last_frame-first_frame+1 << " frames(" << first_frame << ".." << last_frame << ") => ";
#endif
if (first_frame>last_frame)
throw qexception(__PRETTY_FUNCTION__,_("last frame > first frame"));
// especificar quines mostres són
if (last_frame>getFrames())
last_frame = getFrames();
if (h.getOutfile()!="")
getMp3(h.getOutfile(),first_frame,last_frame);
if (h.getDel())
cut(first_frame,last_frame);
return frames;
}
u_int32_t qmp3::getStreamLength () {
return getSize() - (hasTag?qtag::LENGTH:0);
}
u_int32_t qmp3::getFrames() { return frames; }
u_int32_t qmp3::getFrame (qvf &vf) {
u_int32_t frame;
switch (vf.getFormat()) {
case qvf::BYTES: frame = ((long long)vf.getValue()*getFrames())/getStreamLength(); break;
case qvf::KBYTES: frame = (vf.getValue()*getFrames()*1024ULL)/getStreamLength(); break;
case qvf::MBYTES: frame = (vf.getValue()*getFrames()*1024*1024ULL)/getStreamLength(); break;
case qvf::MILLISECONDS: frame = (vf.getValue()*getFrames()*1ULL)/getMsDuration(); break;
case qvf::SECONDS: frame = (vf.getValue()*getFrames()*1000ULL)/getMsDuration(); break;
case qvf::MINUTES: frame = (vf.getValue()*getFrames()*1000*60ULL)/getMsDuration(); break;
case qvf::SPECIFIC: frame = vf.getValue(); break;
default:
throw qexception(__PRETTY_FUNCTION__,
string(_("format not recognized: ")));
// hi ha una funció molt maca format2char
}
#ifdef QVERBOSE
cerr << "getFrame: " << vf << " => " << frame << endl;
#endif
if (frame<1 || frame>getFrames())
throw qexception(__PRETTY_FUNCTION__,
string(_("frame out of range: "))+uint2string(frame));
return frame;
}
u_int32_t qmp3::cut (u_int32_t firstframe, u_int32_t lastframe) {
u_int32_t offset_first = getOffset(firstframe);
u_int32_t offset_last = getOffset(lastframe);
qmp3frameheader fh(qfile::getMap()+offset_last);
u_int32_t length_last = fh.getLength();
qfile::cut(offset_first,offset_last+length_last-1);
remap(qfile::getMap());
}
// provar donant l'@ de memòria...
u_int32_t qmp3::getOffset(u_int32_t frame) {
if (frame<1 || frame>getFrames())
throw qexception(__PRETTY_FUNCTION__,
string(_("frame out of range: "))+uint2string(frame));
if (!isScanned())
scan();
if (frame==1)
return 0;
// let's look around there...
long long offset; // more than 32 bits are needed!!
caddr_t start, backward, forward;
offset = ((long long)frame-1)*getStreamLength()/getFrames();
start = (caddr_t)qfile::getMap()+offset;
forward = seek_header(start,getSize()-offset,getSignature());
backward = seek_header(start,offset,getSignature(),true);
if ((char*)forward-(char*)start<(char*)start-(char*)backward) {
// cerr << "forward way: skipped " << (char*)forward-(char*)start << " bytes" << endl;
start = forward;
}
else {
// cerr << "backward way: skipped " << (char*)start-(char*)backward << " bytes" << endl;
start = backward;
}
#ifdef QVERBOSE
cerr << "frame " << frame
<< " => offset " << (char*)start-(char*)qfile::getMap()
<< "(" << offset << ")" << endl;
#endif
return (u_int32_t)((char*)start-(char*)qfile::getMap());
}
qmp3& qmp3::getMp3(string name, u_int32_t startframe, u_int32_t endframe) {
qfile newmp3(name,NEW);
u_int32_t startoffset = getOffset(startframe);
qmp3frameheader fh(qfile::getMap()+getOffset(endframe));
u_int32_t endoffset = getOffset(endframe)+fh.getLength();
newmp3.append((char*)qfile::getMap()+startoffset,endoffset-startoffset);
// return ??
}
bool qmp3::isScanned() { return scanned; }
quelcom-0.4.0/lib/qmp3frameheader.cc 100644 0 0 16554 7245453630 15423 0 ustar root root /*! \file
* implementation functions for class qframeheader
*/
# include "qmp3frameheader.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
// tanta constant i dades estàtiques en una mena de qmp3ct.cc
const u_int32_t qmp3frameheader::HEADERSIZE=sizeof(struct header);
const u_int32_t qmp3frameheader::MASK = (u_int32_t)(0x0c30cfeff); // ff fe fc c3 // la 'f' entre la 'e' i la 'c' és el bitrate. posada a zero fa que no es tinguin en compte els canvis de bitrate i, pt, s'esdevé pseudosuport pels vbr.
const u_int32_t qmp3frameheader::LAYER3 = 1;
const u_int32_t qmp3frameheader::LAYER2 = 2;
const u_int32_t qmp3frameheader::LAYER1 = 3;
const u_int32_t qmp3frameheader::VERSION1 = 3;
const u_int32_t qmp3frameheader::VERSION2 = 2;
const u_int32_t qmp3frameheader::VERSION25 = 0;
const u_int32_t qmp3frameheader::UNDEFINED_VERSION = 1;
static const char *versions[] = { "2.5", "reserved", "2.0", "1.0" };
static const char *layers[] = { "reserved", "III", "II", "I" };
static const u_int32_t samplerates [4][4] = {
{ 11025, 12000, 8000, 0 },
{ 0, 0, 0, 0 },
{ 22050, 24000, 16000, 0 },
{ 44100, 48000, 32000, 0 }
};
// potser fer -1=>0 i fer-ho sense signe...
static const int layer3_bitrates[4][16] = {
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}, // version 2.5
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, // undefined
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}, // version 2
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} // version 1
};
static u_int32_t samplesPerFrame[4] = { 1152, 1152, 384, 0 };
string qmp3frameheader::getLayer() { return string(layers[header->layer]);}
u_int32_t qmp3frameheader::getSamplesPerFrame() { return samplesPerFrame[header->layer]; }
string qmp3frameheader::getVersion() { return string(versions[header->version]);}
caddr_t qmp3frameheader::getMap() {return (caddr_t)header;}
void qmp3frameheader::remap(caddr_t p) {
header = (struct header*)p;
}
u_int32_t qmp3frameheader::getSignature() {return (*(u_int32_t*)header)&MASK;}
u_int32_t qmp3frameheader::getSampleRate() {
return samplerates[header->version][header->samplerate];
}
bool qmp3frameheader::isSilence () {
// què xungo: pot ser que hi hagi crc o no, i el main data begin dins de la
// side information és de nou bits
// el problema és que és segur que existeix el capçal, però ningú no ens assegura que hi hagi alguna cosa més al darrere per tal de no fer un segfault. es podria mirar de fer una classe derivada on HEADERSIZE fos major.
return false;
}
bool qmp3frameheader::valid (caddr_t p) {
struct header *header = (struct header*)p;
return ( (header->sync1 == 0xff) &&
(header->sync2 == 0x7) &&
(header->version != UNDEFINED_VERSION) &&
(header->layer != 0) &&
(header->bitrate != 0x0f) &&
(header->samplerate != 0x03) &&
(header->emphasis != 0x02) );
}
bool qmp3frameheader::valid () {
return ! ( (header->sync1 != 0xff) ||
(header->sync2 != 0x7) ||
(header->version == UNDEFINED_VERSION) ||
(header->layer == 0) ||
(header->bitrate == 0x0f) ||
(header->samplerate == 0x03) ||
(header->emphasis == 0x02) );
}
//caddr_t qmp3frameheader::getMap() { return header; }
bool qmp3frameheader::compatible(caddr_t p, u_int32_t signature) {
return ((*(u_int32_t*)p)&(MASK)) == signature;
}
u_int32_t qmp3frameheader::setNext(u_int32_t bufsize) {
caddr_t supposed= (char*)header+getLength();
header = (struct header*) seek_header(supposed,bufsize,getSignature());
return (char*)header-(char*)supposed;
}
u_int32_t qmp3frameheader::setNext(caddr_t endstream) {
caddr_t previous = (caddr_t) header;
header = (struct header*) seek_header((char*)header+getLength(),(char*)endstream-(char*)header+1,getSignature());
return (char*)header-(char*)previous-getLength();
}
caddr_t qmp3frameheader::seek_header(caddr_t p, u_int32_t bufsize, u_int32_t signature, bool backwards) {
u_int32_t skipped = 0;
while ((bufsize>=HEADERSIZE) &&
(((signature && !compatible(p,signature)) || (!signature && !valid(p))))) {
bufsize--;
skipped++;
if (backwards)
p--;
else
p++;
}
if (bufsizesync1;
case SYNC2: return header->sync2;
case _VERSION: return header->version;
case LAYER: return header->layer;
case PROTECTION: return header->protection;
case BITRATE: return header->bitrate;
case SAMPLERATE: return header->samplerate;
case PADDING: return header->padding;
case PRIVAT: return header->privat;
case CHANNEL_MODE: return header->channel_mode;
case MODE_EXTENSION: return header->mode_extension;
case COPYRIGHT: return header->copyright;
case ORIGINAL: return header->original;
case EMPHASIS: return header->emphasis;
default:
throw qexception(__PRETTY_FUNCTION__,_("invalid field"));
// i pintar el valor...
}
}
void qmp3frameheader::setField (enum qmp3frameheaderfield f, u_int32_t v) {
switch (f) {
case SYNC1: header->sync1 = v; break;
case SYNC2: header->sync2 = v; break;
case _VERSION: header->version = v; break;
case LAYER: header->layer = v; break;
case PROTECTION: header->protection = v; break;
case BITRATE: header->bitrate = v; break;
case SAMPLERATE: header->samplerate = v; break;
case PADDING: header->padding = v; break;
case PRIVAT: header->privat = v; break;
case CHANNEL_MODE: header->channel_mode = v; break;
case MODE_EXTENSION: header->mode_extension = v; break;
case COPYRIGHT: header->copyright = v; break;
case ORIGINAL: header->original = v; break;
case EMPHASIS: header->emphasis = v; break;
default:
throw qexception(__PRETTY_FUNCTION__,_("invalid field"));
// i pintar el valor...
}
}
u_int32_t qmp3frameheader::getLength() {
if (header->layer!=LAYER3)
throw qexception (__PRETTY_FUNCTION__,_("layer not supported"));
// i dir quin valor...
return (144 * getBitRate() * 1000) / getSampleRate() + header->padding;
}
u_int32_t qmp3frameheader::getMsDuration() {
// this is just true for layer II and layer III
return (1152*1000)/getSampleRate();
}
void qmp3frameheader::print (ostream *os) {
*os << "mpeg " << getVersion() << " "
<< "layer " << getLayer() << " "
<< getSampleRate() << "Hz " << getBitRate() << "kbps";
}
u_int32_t qmp3frameheader::getBitRate() {
if (header->layer!=LAYER3)
throw qexception (__PRETTY_FUNCTION__,_("only layer III is supported"));
if (header->version==UNDEFINED_VERSION)
throw qexception (__PRETTY_FUNCTION__,_("undefined version"));
return layer3_bitrates[header->version][header->bitrate];
}
ostream &operator<<(ostream &os, qmp3frameheader &fh) {
fh.print(&os);
return os;
}
quelcom-0.4.0/lib/qreport.cc 100644 0 0 17100 7245453630 14037 0 ustar root root /*! \file
* implementation functions for class qreport
*/
# include // sprintf
# include
# include "qreport.hh"
# include "qexception.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
/*
qreportar directoris visitats i directoris amb mp3
qreportar fitxers visitats i fitxers mp3
*/
// create a base empty qreport
qreport::qreport () {
type = BASE;
files = directories = errors = 0;
msduration = size = 0;
bitrate = samplerate = 0;
}
// report a normal file
qreport::qreport (qfile &f) {
type = FILE;
samplerate = 0;
bitrate = 0;
msduration = 0;
size = f.getSize();
name = f.getName();
files = 1;
directories = 0;
}
// report an mp3 file
qreport::qreport (qmp3 &mp3) {
type = MP3;
samplerate = mp3.getSampleRate();
bitrate = mp3.getBitRate();
msduration = mp3.getMsDuration();
size = mp3.getSize();
name = mp3.getName();
if (vbr = mp3.isVbr())
bitrate=(u_int32_t)(-1);
files = 1;
directories = 0;
}
// report a directory
qreport::qreport (const string dir) {
type = DIR;
files = errors = 0;
directories = 1;
msduration = size = 0;
bitrate = samplerate = 0;
name = dir;
}
void qreport::add (qreport r) {
/*
provar:
if (type==file) throw
if (r.type==base) throw
sumar
i llavors implementar el '+='
*/
switch (type) {
case FILE:
case MP3:
type = BASE;
case DIR:
case BASE:
switch (r.type) {
case BASE:
return ; // do nothing
// throw qexception(__PRETTY_FUNCTION__,"a base qreport cannot be added anywhere");
case DIR:
case MP3:
if (bitrate==0)
bitrate = r.bitrate;
else
if (bitrate!=r.bitrate)
bitrate = -1;
if (samplerate==0)
samplerate = r.samplerate;
else
if (samplerate!=r.samplerate)
samplerate = -1;
msduration += r.msduration;
case FILE:
files += r.files;
directories+=r.directories;
size += r.size;
break;
default:
throw qexception(__PRETTY_FUNCTION__,"invalid qreport type");
}
break;
default:
throw qexception(__PRETTY_FUNCTION__,"invalid qreport type");
}
// report_list.push_back(r);
}
// add_error (string); // qreport an error
string qreport::parameter2string() {
char str_duration[15], str_bitrate[10], str_size[15], str_files[15];
if (msduration>0) {
int duration = (int)(msduration/1000);
sprintf(str_duration,"%3d:%02d:%02d",duration/3600,(duration%3600)/60,duration%60);
}
if (bitrate>0)
sprintf(str_bitrate,"%3d kbps",bitrate);
else
sprintf(str_bitrate," ");
if (size>0)
sprintf(str_size,"%4.2f Mb",(double)size/(1024*1024));
if (type==DIR)
sprintf(str_files,"%d files",files); // and dirs?
else
str_files[0]=0; // and dirs?
return string(str_duration) + string(" - ") + string(str_bitrate) + string(" - ") + string(str_size) + string(" - ") + string(str_files);
}
string qreport::getName() {
return name;
}
void qreport::html(ostream *os, string link) {
if (files==0 && directories==0) {
*os << "[empty report]";
return;
}
// if (msduration>0) {
// no ho deixis així!!!!
int dur = msduration;
os->form("%3d:%02d:%02d",dur/3600000,(dur%3600000)/60000,(dur%60000)/1000);
// }
// else
// *os << " ";
*os << " - ";
switch (bitrate) {
case 0: *os << " "; break;
case (u_int32_t)(-1): *os << " [vbr] "; break;
default:
os->form("%3d kbps",bitrate);
}
*os << " - ";
/*
si verbose...
if (samplerate>0)
os->form("%5d Hz ",samplerate);
else
*os << " ";
*/
// if (size>0)
os->form("%4.2f Mb",(double)size/(1024*1024));
// else
// *os << " ";
switch (type) {
case BASE:
*os << " - " << directories << " directories and " << files << " files";
break;
case FILE:
case MP3:
if (link=="")
*os << " - " << "" << name << " ";
else
*os << " - " << "" << name << " ";
break;
case DIR:
if (link=="")
*os << " - " << "" << name << " ";
else
*os << " - " << "" << name << " ";
if (directories>1)
*os << " - " << directories-1 << " directories and " << files << " files";
else
*os << " - " << files << " files";
break;
default:
*os << "quelcom internal error" << endl;
}
return;
switch (type) {
case BASE:
if (directories>0)
*os << directories << _(" directories ");
*os << files << _(" files ");
break;
case FILE:
/*
if (htmloutput)
*os << "" << name << " : ";
else
*/
os->form("%-64s",name.c_str());
break;
case MP3:
// *os << "bliblablo";
os->form("%-64s",name.c_str());
break;
case DIR:
/*
if (htmloutput)
*os << "" << name << " : ";
else
*/
os->form("%-64s ",name.c_str());
if (directories>1) // other than itself
*os << directories-1 << _(" directories ");
os->form("%3d file%c ",files,(files==1)?' ':'s');
break;
}
}
void qreport::print(ostream *os) {
if (files==0 && directories==0) {
*os << "[empty report]";
return;
}
// if (msduration>0) {
// no ho deixis així!!!!
int dur = msduration;
os->form("%3d:%02d:%02d",dur/3600000,(dur%3600000)/60000,(dur%60000)/1000);
// }
// else
// *os << " ";
*os << " - ";
// això s'hauria d'assegurar. pex: bitrate==(u_int32_t)(-1) => vbr
switch (bitrate) {
case 0: *os << " "; break;
case (u_int32_t)(-1): *os << " [vbr] "; break;
default:
os->form("%3d kbps",bitrate);
}
*os << " - ";
/*
si verbose...
if (samplerate>0)
os->form("%5d Hz ",samplerate);
else
*os << " ";
*/
// if (size>0)
os->form("%4.2f Mb",(double)size/(1024*1024));
// else
// *os << " ";
switch (type) {
case BASE:
*os << " - " << directories << " directories and " << files << " files";
break;
case FILE:
case MP3:
*os << " - " << name;
break;
case DIR:
*os << " - " << name;
if (directories>1)
*os << " - " << directories-1 << " directories and " << files << " files";
else
*os << " - " << files << " files";
break;
default:
*os << "quelcom internal error" << endl;
}
return;
switch (type) {
case BASE:
if (directories>0)
*os << directories << _(" directories ");
*os << files << _(" files ");
break;
case FILE:
/*
if (htmloutput)
*os << "" << name << " : ";
else
*/
os->form("%-64s",name.c_str());
break;
case MP3:
// *os << "bliblablo";
os->form("%-64s",name.c_str());
break;
case DIR:
/*
if (htmloutput)
*os << "" << name << " : ";
else
*/
os->form("%-64s ",name.c_str());
if (directories>1) // other than itself
*os << directories-1 << _(" directories ");
os->form("%3d file%c ",files,(files==1)?' ':'s');
break;
}
}
ostream &operator<<(ostream &os, qreport &r) {
r.print(&os);
return os;
}
quelcom-0.4.0/lib/qtag.cc 100644 0 0 5576 7245453630 13275 0 ustar root root /*! \file
* implementation functions for class qtag
*/
# include "qtag.hh"
# include "qmisc.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
const u_int32_t qtag::LENGTH = 128;
const u_int32_t qtag::fieldlengths[7] = { 3, 30, 30, 30, 4, 30, 1};
caddr_t qtag::getMap() { return (caddr_t) tag; }
bool qtag::isValid() {
return tag!=0;
}
void qtag::cleanFields() {
if (!tag)
throw qexception(__PRETTY_FUNCTION__,_("tag is invalid"));
int i;
char *p;
i = fieldlengths[ALBUM]-1;
p = tag->album;
while (i>=0 && (p[i]==' ')) p[i--]=0;
i = fieldlengths[ARTIST]-1;
p = tag->artist;
while (i>=0 && (p[i]==' ')) p[i--]=0;
i = fieldlengths[TITLE]-1;
p = tag->title;
while (i>=0 && (p[i]==' ')) p[i--]=0;
}
qtag::qtag (caddr_t p) {
if (strcmpn(p,"TAG",3))
tag = (struct tag*) p;
else
tag = 0;
#ifdef QVERBOSE
if (tag)
cerr << "tag found mapped at address " << p << endl;
#endif
}
qtag::qtag (qfile &f) {
caddr_t p = f.getMap()+f.getSize()-LENGTH;
if (strcmpn(p,"TAG",3))
tag = (struct tag*) p;
else
tag = 0;
#ifdef QVERBOSE
if (tag)
cerr << "tag found mapped at address " << p << endl;
#endif
}
void qtag::get (enum field f, char *str) {
if (!tag)
throw qexception(__PRETTY_FUNCTION__,_("tag is invalid"));
switch (f) {
case TAG: strncpy(str,tag->tagid, fieldlengths[f]); break;
case TITLE: strncpy(str,tag->title, fieldlengths[f]); break;
case ARTIST: strncpy(str,tag->artist, fieldlengths[f]); break;
case ALBUM: strncpy(str,tag->album, fieldlengths[f]); break;
case YEAR: strncpy(str,tag->year, fieldlengths[f]); break;
case COMMENT: strncpy(str,tag->comment,fieldlengths[f]); break;
case GENRE: strncpy(str,tag->genre, fieldlengths[f]); break;
default: // this should never happen...
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
}
void qtag::set (enum field f, char *str) {
if (!tag)
throw qexception(__PRETTY_FUNCTION__,_("tag is invalid"));
switch (f) {
case TAG: strncpy(tag->tagid, str,fieldlengths[f]); break;
case TITLE: strncpy(tag->title, str,fieldlengths[f]); break;
case ARTIST: strncpy(tag->artist, str,fieldlengths[f]); break;
case ALBUM: strncpy(tag->album, str,fieldlengths[f]); break;
case YEAR: strncpy(tag->year, str,fieldlengths[f]); break;
case COMMENT: strncpy(tag->comment,str,fieldlengths[f]); break;
case GENRE: strncpy(tag->genre, str,fieldlengths[f]); break;
default: // this should never happen...
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
}
void qtag::print (ostream *os) {
os->form ("%-0.30s - %-0.30s - %-0.30s",tag->artist,tag->album,tag->title);
}
ostream &operator<<(ostream &os, qtag &t) {
t.print(&os);
return os;
}
quelcom-0.4.0/lib/qvf.cc 100644 0 0 3534 7245453630 13125 0 ustar root root /*! \file
* implementation functions for class qvf
*/
# include // sscanf
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
# include "qvf.hh"
# include "qexception.hh"
# include "qmisc.hh"
char qvf::format2char(enum format f) {
switch (f) {
case BYTES: return 'b';
case KBYTES: return 'k';
case MBYTES: return 'M';
case MINUTES: return 'm';
case SECONDS: return 's';
case MILLISECONDS: return 'j';
case SPECIFIC: return ' ';
case UNDEFINED: return 'X';
}
return '?';
}
enum qvf::format qvf::char2format(char c) {
switch (c) {
case 'b': return BYTES;
case 'k': return KBYTES;
case 'M': return MBYTES;
case 'm': return MINUTES;
case 's': return SECONDS;
case 'j': return MILLISECONDS;
case ' ': return SPECIFIC;
}
throw qexception(__PRETTY_FUNCTION__,
string(_("invalid format specifier: "))+char2string(c));
}
qvf::qvf() {
format=UNDEFINED;
}
qvf::qvf(u_int32_t v, enum format f=SPECIFIC):value(v),format(f) { }
qvf::qvf(char *s) {
char c;
// valors <0 es llegeixen com a MAX-valor ...
switch (sscanf(s,"%u%c",&value,&c)) {
case 1:
c = ' ';
case 2:
format = char2format(c);
break;
default:
throw qexception(__PRETTY_FUNCTION__,
string(_("error reading: "))+string(s));
}
}
unsigned int qvf::getValue() {
if (format==UNDEFINED)
throw qexception(__PRETTY_FUNCTION__,_("format is undefined"));
return value;
}
enum qvf::format qvf::getFormat() { return format; }
void qvf::set(unsigned int v, enum format f=SPECIFIC) { value=v; format=f; }
void qvf::print (ostream *os) {
*os << "{" << value << "," << format2char(format) << "}";
}
ostream &operator<<(ostream &os, qvf &q) {
q.print(&os);
return os;
}
quelcom-0.4.0/lib/qwav.cc 100644 0 0 17301 7245453630 13324 0 ustar root root /*! \file
* implementation functions for class qwav
*/
# include "qwav.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
u_int32_t qwav::append (qwav w) {
if (!compatible(w))
throw qexception (__PRETTY_FUNCTION__,
getName() + string(": ") + w.getName() +
string(_(" is not compatible")));
qfile::append(w.getMap()+HEADERSIZE,w.getSize()-HEADERSIZE);
remap(getMap());
addSamples(w.getSamples());
return getSamples();
}
void qwav::print (ostream *os) {
u_int32_t msduration;
msduration = getMsDuration();
// cal posar les milèssimes?
os->form("%s: %u Hz %u bits %s %2u:%02u.%02u",
getName().c_str(),
getSampleRate(),getBitsPerSample(),
((getChannels()==1)?"mono":"stereo"),
msduration/60000,(msduration/1000)%60,(msduration%1000)/10);
}
qwav::qwav(string name, u_int32_t flags=READ)
: qfile (name,flags),
qwavheader(getMap(),getSize()) {
}
bool qwav::compatible (qwav &w) {
return (getStereo() == w.getStereo()) &&
(getChannels() == w.getChannels()) &&
(getSampleRate() == w.getSampleRate());
}
u_int32_t qwav::cut (u_int32_t firstsample, u_int32_t lastsample) {
// s'hauria de comprovar la consistència dels paràmetres...
qfile::cut(getOffset(firstsample),getOffset(lastsample)+getBytesPerSample()-1);
remap(getMap());
setSamples((getSize()-qwavheader::HEADERSIZE)/getBytesPerSample());
return getSamples();
}
void qwav::move (u_int32_t sample_start, u_int32_t sample_end, u_int32_t sample_dest) {
if (sample_endgetSamples()) {
return; // ...
}
if (sample_end>getSamples()) {
sample_end = getSamples(); // ...
}
// revisar d'ací en avall...
u_int32_t sample_number = sample_end-sample_start;
if (sample_number+sample_dest-1>getSamples()) {
return; // ...
}
qfile::move(getOffset(sample_start),
getOffset(sample_end)+getBytesPerSample()-1,
getOffset(sample_dest));
}
void qwav::truncate (u_int32_t samples) {
if (samples>=getSamples())
return;
qfile::truncate(HEADERSIZE+samples*getBytesPerSample());
remap(getMap());
setSamples(samples);
}
u_int32_t qwav::cut (qcuthandler &h) {
if ((!h.getDel()) && (h.getOutfile()==""))
return 0;
//
// an schema with the cut specifications and what will be done
// B => begin point, from the beginning of the file
// E => end point, from the beginning of the file
// b => begin point, from the end of the file
// e => end point, from the end of the file
// s => size of the fragment
//
// 0 means not specified 1 means specified
//
// B b E e s
// 0 0 0 0 0 throw
// 0 0 0 0 1 0 .. s
// 0 0 0 1 0 0 .. e
// 0 0 0 1 1 e-s .. e
// 0 0 1 0 0 0 .. E
// 0 0 1 0 1 E-s .. E
// 0 0 1 1 0 throw
// 0 0 1 1 1 throw
// 0 1 0 0 0 b .. EOF
// 0 1 0 0 1 b .. b+s
// 0 1 0 1 0 b .. e
// 0 1 0 1 1 throw
// 0 1 1 0 0 b .. E
// 0 1 1 0 1 throw
// 0 1 1 1 0 throw
// 0 1 1 1 1 throw
// 1 0 0 0 0 B .. EOF
// 1 0 0 0 1 B .. B+s
// 1 0 0 1 0 B .. e
// 1 0 0 1 1 throw
// 1 0 1 0 0 B .. E
// 1 0 1 0 1 throw
// 1 0 1 1 0 throw
// 1 0 1 1 1 throw
// 1 1 0 0 0 throw
// 1 1 0 0 1 throw
// 1 1 0 1 0 throw
// 1 1 0 1 1 throw
// 1 1 1 0 0 throw
// 1 1 1 0 1 throw
// 1 1 1 1 0 throw
// 1 1 1 1 1 throw
// it is ugly, actually, but the table above should make things clear
u_int32_t cutmode=0;
if ( h.getBegin().getFormat()!=qvf::UNDEFINED ) cutmode+=16;
if ( h.getbegin().getFormat()!=qvf::UNDEFINED ) cutmode+=8;
if ( h.getEnd().getFormat()!=qvf::UNDEFINED ) cutmode+=4;
if ( h.getend().getFormat()!=qvf::UNDEFINED ) cutmode+=2;
if ( h.getSize().getFormat()!=qvf::UNDEFINED ) cutmode+=1;
u_int32_t first_sample, last_sample;
#ifdef QVERBOSE
cerr << "cut mode: " << cutmode << endl;
#endif
// comprovació de zeros: -s 3b => -s 0!!
switch (cutmode) {
case 0:
//cerr << "cut: you must specify where to cut" << endl;
return 0;
case 1: // 1 .. s (p)
first_sample = 1;
last_sample = getSample(h.getSize());
break;
case 2: // 1 .. e (p)
first_sample = 1;
last_sample = getSamples()+1-getSample(h.getend());
break;
case 3: // e-s .. e (p)
last_sample = getSamples()+1-getSample(h.getend());
first_sample = last_sample-getSample(h.getSize())+1;
break;
case 4: // 1 .. E (p)
first_sample = 1;
last_sample = getSample(h.getEnd());
break;
case 5: // E-s .. E (p)
last_sample = getSample(h.getEnd());
first_sample = last_sample-getSample(h.getSize())+1;
break;
case 6: // E+e => throw (p)
case 7: // E+e+s => throw (p)
case 14: // b+E+e => throw (p)
case 15: // b+E+e+s => throw (p)
case 22: // B+E+e => throw (p)
case 23: // B+E+e+s => throw (p)
throw qexception(__PRETTY_FUNCTION__,string(_("options -E and -e cannot be used together")));
case 8: // b .. EOF (p)
first_sample = getSamples()+1-getSample(h.getbegin());
last_sample = getSamples();
break;
case 9: // b .. b+s (p)
first_sample = getSamples()+1-getSample(h.getbegin());
last_sample = first_sample+getSample(h.getSize())-1;
break;
case 10: // b .. e (p)
first_sample = getSamples()+1-getSample(h.getbegin());
last_sample = getSamples()+1-getSample(h.getend());
break;
case 11: // b+e+s
case 13: // b+E+s
case 19: // B+e+s
case 21: // B+E+s
throw qexception(__PRETTY_FUNCTION__,string(_("options (-b or -B), (-e or -E) and -s cannot be used together")));
case 12: // b .. E (p)
first_sample = getSamples()+1-getSample(h.getbegin());
last_sample = getSample(h.getEnd());
break;
case 16: // B .. EOF (p)
first_sample = getSample(h.getBegin());
last_sample = getSamples();
break;
case 17: // B .. B+s (p)
first_sample = getSample(h.getBegin());
last_sample = first_sample+getSample(h.getSize())-1;
break;
case 18: // B .. e (p)
first_sample = getSample(h.getBegin());
last_sample = getSamples()+1-getSample(h.getend());
break;
case 20: // B .. E
first_sample = getSample(h.getBegin());
last_sample = getSample(h.getEnd());
break;
case 24 ... 31: // B+b+...
throw qexception(__PRETTY_FUNCTION__,string(_("options -B and -b cannot be used together")));
default: // this should never happen
cerr << "quelcom panic!" << endl;
return 0;
}
#ifdef QVERBOSE
cerr << "cut: " << last_sample-first_sample+1 << " samples(" << first_sample << ".." << last_sample << ") => ";
#endif
if (first_sample>last_sample)
throw qexception(__PRETTY_FUNCTION__,
string(_("cut: last sample > first sample")));
// especificar quines mostres són
if (last_sample>getSamples())
last_sample = getSamples();
if (h.getOutfile()!="")
getWav(h.getOutfile(),first_sample,last_sample);
if (h.getDel())
cut(first_sample,last_sample);
return 1;
}
qwav& qwav::getWav(string name, u_int32_t startsample, u_int32_t endsample) {
// s'ha de poder resoldre més elegantment...: un constructor nul de wav (nom de fitxer + paràmetres i cap mostra) + un append
qfile newwav(name,NEW);
newwav.append(getMap(),qwavheader::HEADERSIZE);
newwav.append(getMap()+getOffset(startsample),(endsample-startsample+1)*getBytesPerSample());
qwavheader h(newwav.getMap());
h.setSamples(endsample-startsample+1);
// return ???
}
ostream &operator<<(ostream &os, qwav &u) {
u.print(&os);
return os;
}
quelcom-0.4.0/lib/qwavheader.cc 100644 0 0 7676 7245453630 14473 0 ustar root root /*! \file
* implementation functions for class qwavheader
*/
# include "qwavheader.hh"
# include "qexception.hh"
# include "qmisc.hh"
#ifdef NLS
# include
# include
# define _(s) gettext (s)
#else
# define _(s) (s)
#endif
const u_int32_t qwavheader::HEADERSIZE = sizeof(struct header);
qwavheader::qwavheader (caddr_t p, u_int32_t wavlength=0) {
header = (struct header *)p;
valid();
if (wavlength)
validLength(wavlength);
}
void qwavheader::remap(caddr_t p) {
header = (struct header*)p;
}
u_int32_t qwavheader::setSamples(u_int32_t n) {
// protegir-la d'abusos...
header->datalength = n*header->bytespersample;
header->rifflength = header->datalength+36;
#ifdef QVERBOSE
cerr << "sample number set to " << n << endl;
#endif
return getSamples();
}
u_int32_t qwavheader::addSamples(int increment) {
// protegir-la d'abusos...
setSamples(getSamples()+increment);
return getSamples();
}
u_int32_t qwavheader::getSamples() {
return header->datalength / header->bytespersample;
}
bool qwavheader::compatible (const qwavheader &other) {
return (header->channels == other.header->channels) &&
(header->samplerate == other.header->samplerate);
}
void qwavheader::write(caddr_t p) {
memmove(p,header,HEADERSIZE);
}
bool qwavheader::valid () {
if (!strcmpn(header->riff,"RIFF",4) ||
!strcmpn(header->wave,"WAVE",4) ||
!strcmpn(header->fmt_,"fmt ",4) ||
!strcmpn(header->data,"data",4) ||
(header->fmtlength!=16 ) ||
(header->format!=1 )) {
throw qexception(__PRETTY_FUNCTION__,_("header format error"));
}
if ( (header->channels!=2 && header->channels!=1) ||
(header->samplerate>48000 || header->samplerate<8000) ||
(header->bytespersample!=1 &&
header->bytespersample!=2 &&
header->bytespersample!=4) )
throw qexception(__PRETTY_FUNCTION__,_("header value error"));
// caldria comprovar que bitspersample=bytespersample*channels*8
// caldria comprovar que bytespersec=bytespersample*samplerate
return true;
}
bool qwavheader::validLength (u_int32_t length) {
if ((header->datalength != length-44) || (header->rifflength != length-8))
throw qexception(__PRETTY_FUNCTION__,_("length mismatch"));
return true;
}
u_int32_t qwavheader::getMsDuration() {
return 1000ULL*header->datalength/(header->bytespersample*header->samplerate);
}
u_int32_t qwavheader::getSampleRate() { return header->samplerate; }
u_int32_t qwavheader::getChannels() { return header->channels; }
u_int32_t qwavheader::getOffset (qvf &vf) {
return getSample(vf)*getBytesPerSample()+HEADERSIZE;
}
u_int32_t qwavheader::getOffset (u_int32_t sample) {
// assegurar que sample in (1..getSamples())
return HEADERSIZE+(sample-1)*header->bytespersample;
}
u_int32_t qwavheader::getSample (qvf &vf) {
u_int32_t sample;
switch (vf.getFormat()) {
case qvf::BYTES: sample = vf.getValue()/getBytesPerSample(); break;
case qvf::KBYTES: sample = (vf.getValue()*1024)/getBytesPerSample(); break;
case qvf::MBYTES: sample = (vf.getValue()*1024*1024)/getBytesPerSample(); break;
case qvf::MILLISECONDS: sample = (1ULL*vf.getValue()*getSampleRate())/1000; break;
case qvf::SECONDS: sample = vf.getValue()*getSampleRate(); break;
case qvf::MINUTES: sample = 60*vf.getValue()*getSampleRate(); break;
case qvf::SPECIFIC: sample = vf.getValue(); break;
default:
throw qexception(__PRETTY_FUNCTION__,
string(_("format not recognized: "))+char2string(vf.getFormat()));
}
if (sample<1 || sample>getSamples())
throw qexception(__PRETTY_FUNCTION__,string(_("sample out of range: "))+uint2string(sample));
// i si poséssim el qvf, millor
return sample;
}
u_int32_t qwavheader::getBitsPerSample() { return header->bitspersample; }
u_int32_t qwavheader::getBytesPerSample() { return header->bytespersample; }
bool qwavheader::getStereo() { return header->channels==2; }
quelcom-0.4.0/lib/qwavsample.cc 100644 0 0 11510 7245453630 14522 0 ustar root root /*! \file
* implementation functions for class qsample
*/
# include "qwavsample.hh"
# include "qexception.hh"
#ifdef NLS
# include
# include
/*! \def define _(s)
* \brief gettextize strings
*/
# define _(s) gettext(s)
#else
/*! \def define _(s)
* \brief bypass gettextization
*/
# define _(s) (s)
#endif
qwavsample::qwavsample (qwav *wav, u_int32_t s=1) {
sample = (union sample*) (wav->getMap()+wav->getOffset(s));
if (wav->getBitsPerSample()==16) {
if (wav->getChannels()==2) {
type = STEREO16;
}
else if (wav->getChannels()==1) {
type = MONO16;
}
else
throw qexception(__PRETTY_FUNCTION__,_("unsupported channel value"));
}
else if (wav->getBitsPerSample()==8) {
if (wav->getChannels()==2) {
type = STEREO8;
}
else if (wav->getChannels()==1) {
type = MONO8;
}
else
throw qexception(__PRETTY_FUNCTION__,_("unsupported channel value"));
}
else
throw qexception(__PRETTY_FUNCTION__,_("unsupported bits/sample value"));
#ifdef QVERBOSE
cerr << "sample type " << type << " mapped at address " << this->sample << endl;
#endif
}
qwavsample::qwavsample(caddr_t pointer, u_int32_t channels, u_int32_t bitspersample) {
sample = (union sample*) pointer;
if (bitspersample==16) {
if (channels==2) {
type = STEREO16;
return;
}
else if (channels==1) {
type = MONO16;
return;
}
else
throw qexception(__PRETTY_FUNCTION__,_("unsupported channel value"));
}
else if (bitspersample==8) {
if (channels==2) {
type = STEREO8;
return;
}
else if (channels==1) {
type = MONO8;
return;
}
else
throw qexception(__PRETTY_FUNCTION__,_("unsupported channel value"));
}
else
throw qexception(__PRETTY_FUNCTION__,_("unsupported bits/sample value"));
}
qwavsample::qwavsample(caddr_t pointer, enum type t=STEREO16) {
sample = (union sample*) pointer;
type = t;
}
int qwavsample::getLeft() {
switch (type) {
case MONO8: return sample->mono8;
case MONO16: return sample->mono16;
case STEREO8: return sample->stereo8.left;
case STEREO16: return sample->stereo16.left;
}
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
int qwavsample::getRight() {
switch (type) {
case MONO8: return sample->mono8;
case MONO16: return sample->mono16;
case STEREO8: return sample->stereo8.right;
case STEREO16: return sample->stereo16.right;
}
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
void qwavsample::set(int left, int right=0) {
switch (type) {
case MONO8: sample->mono8=left; break;
case MONO16: sample->mono16=left; break;
case STEREO8: sample->stereo8.left=left;sample->stereo8.right=right; break;
case STEREO16: sample->stereo16.left=left;sample->stereo16.right=right; break;
default:
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
}
bool qwavsample::isSilence(u_int32_t threshold=0) {
switch (type) {
case MONO8: return (u_int32_t)abs(sample->mono8)<=threshold;
case MONO16: return (u_int32_t)abs(sample->mono16)<=threshold;
case STEREO8:
return ((u_int32_t)abs(sample->stereo8.left)<=threshold) &&
((u_int32_t)abs(sample->stereo8.right)<=threshold);
case STEREO16:
return ((u_int32_t)abs(sample->stereo16.left)<=threshold) &&
((u_int32_t)abs(sample->stereo16.right)<=threshold);
}
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
void qwavsample::setNext() {
switch (type) {
case MONO8: ++(char*)sample; break;
case MONO16: ++(short*)sample; break;
case STEREO8: ++(struct stereo8*)sample; break;
case STEREO16: ++(struct stereo16*)sample; break;
default:
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
#ifdef QVERBOSE
cerr << "sample now is mapped at " << (void*) sample << endl;
#endif
}
ostream& operator<<(ostream &os, qwavsample &s) {
s.print(os);
return os;
}
void qwavsample::print(ostream &os) {
switch (type) {
case MONO8: os.form("(%d)",sample->mono8); break;
case MONO16: os.form("(%d)",sample->mono16); break;
case STEREO8: os.form("(%d,%d)",sample->stereo8.left,sample->stereo8.right); break;
case STEREO16: os.form("(%d,%d)",sample->stereo16.left,sample->stereo16.right); break;
default:
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
}
void qwavsample::prod(double d) {
switch (type) {
case MONO8: sample->mono8*=d; break;
case MONO16: sample->mono16*=d; break;
case STEREO8: sample->stereo8.left*=d; sample->stereo8.right*=d; break;
case STEREO16: sample->stereo16.left*=d; sample->stereo16.right*=d; break;
default:
throw qexception(__PRETTY_FUNCTION__,_("quelcom internal error"));
}
}
quelcom-0.4.0/lib/qcuthandler.hh 100644 0 0 6271 7245453630 14656 0 ustar root root /*! \file
* header functions for qcuthandler
*/
# ifndef _qcuthandler_hh_
# define _qcuthandler_hh_
# include
# include "qvf.hh"
/*!
* \brief class for file-cut specifications
*
* this class does nothing: it is used just for keeping together different parameters used to define a cut (a fragment) of a file. basically, where the cut starts, where it ends and, optionally, the filename where to copy the cut and whether it must be deleted. the class values are filled by applications (qmp3cut.cc, qwavcut.cc) and interpreted by the "library" (qwav::cut(), qmp3::cut())
*/
class qcuthandler {
private:
//! if specified, sets the begin of the cut using the beginning of the file as reference point
qvf Begin;
//! if specified, sets the begin of the cut using the end of the file as reference point
qvf begin;
//! if specified, sets the end of the cut using the beginning of teh file as reference point
qvf End;
//! if specified, sets the begin of the cut using the end of the file as reference point
qvf end;
//! if specified, sets the size of the cut
qvf size;
//! the filename where to put the cut
string outfile;
//! whether the cut must be deleted from the file
bool del;
public:
qcuthandler();
/*!
* initializes itself with a string formed by two time specifiers separated by a '-'
*
* the string must have the form: [[h:]m:]s[.ms]-[[h:]m:]s[.ms]
* example (one second): 0.4-1.4
* example (six minutes and half second): 54:32.210-1:0:32.710
*/
qcuthandler(char*);
/*!
* \brief sets the Begin member
* \param B qvf object
*/
void setBegin (qvf &B);
/*!
* \brief sets the End member
* \param E qvf object
*/
void setEnd (qvf &E);
/*!
* \brief sets the begin member
* \param b qvf object
*/
void setbegin (qvf &b);
/*!
* \brief sets the end member
* \param e qvf object
*/
void setend (qvf &e);
/*!
* \brief sets the size member
* \param s qvf object
*/
void setSize (qvf &s);
/*!
* \brief sets the file where the cut will be copied
* \param o the file name
*/
void setOutfile (string o);
/*!
* \brief sets whether the cut must be deleted
* \param d bool indicating whether the cut must be deleted
*/
void setDel (bool d);
/*!
* \brief gets the Begin member
* \return the Begin member
*/
qvf& getBegin();
/*!
* \brief gets the End member
* \return the End member
*/
qvf& getEnd();
/*!
* \brief gets the begin member
* \return the begin member
*/
qvf& getbegin();
/*!
* \brief gets the end member
* \return the end member
*/
qvf& getend();
/*!
* \brief gets the size of the cut
* \return the size of the cut
*/
qvf& getSize();
/*!
* \brief gets the file where the cut must be copied
* \return the name of the file where the cut must be copied
*/
string getOutfile();
/*!
* \brief gets whether the cut must be deleted
* \return whether the cut must be deleted
*/
bool getDel();
// i quedaria genial poder sumar i restar qvf per desplaçar el tall.
};
#endif
quelcom-0.4.0/lib/qexception.hh 100644 0 0 2200 7245453630 14507 0 ustar root root /*! \file
* header functions for qexception
*/
# ifndef _qexception_hh_
# define _qexception_hh_
#include
/*!
* \brief class for quelcom specific exceptions
*
* simple class for raising and catching quelcom specific exceptions. it includes info from the method which raised the exception for debugging purpouses.
*/
class qexception {
private:
//! the method where the exception is raised
string method;
//! info describing the cause of the exception raising
string info;
public:
/*!
* initializes itself with the given method and info
* \param m the method where the exception has been raised
* \param i info explaining the cause of the exception raising
*/
qexception (string m=string(), string i=string()):method(m),info(i) { }
/*!
* \brief gets the info of the exception
* \return a string containg the info of the exception
*/
string getInfo();
/*!
* \brief print the wav characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream *os);
};
ostream &operator<<(ostream &os, qexception &e);
# endif
quelcom-0.4.0/lib/qfile.hh 100644 0 0 6732 7245453630 13446 0 ustar root root /*! \file
* header functions for qfile
*/
# ifndef _qfile_hh_
# define _qfile_hh_
# include // string
# include // struct stat, fstat
# include // u_int32_t
/*!
* \brief class for mapped files.
*
* this class models a files mapped in memory allowing better performance and easier programmer use than no mapped files
*/
class qfile {
private:
//! file descriptor
int fd;
//! flags used to open the file
u_int32_t flags;
//! flags used to map the file in memory
u_int32_t mapflags;
//! name of the file
string name;
//! memory location where the file is mapped
caddr_t map;
//! size of the file
u_int32_t size;
public:
static const u_int32_t READ, WRITE, READWRITE, TRUNCATE;
static const u_int32_t NEW;
/*!
* initializes itself with the given name and flags
* \param name the name of the file to open
* \param flags the flags to select the opening mode
*/
qfile(string name, u_int32_t flags=READ);
/*!
* \brief destructor
*
* unmaps the file from memory flushing it to disk
*/
~qfile();
// synchronize (protected)
/*!
* \brief deletes part of the file
* \param start first byte to delete
* \param end last byte to delete
* \return the new size in bytes of the file
*/
u_int32_t cut (u_int32_t start, u_int32_t end);
/*!
* \brief truncates the file to the given number of bytes
* \param size the number of bytes to keep
* \return the new size in bytes of the file
*/
u_int32_t truncate (u_int32_t size);
/*!
* \brief move data in the file
* \param start offset of the first byte to move
* \param end offset of the last byte to move
* \param dest offset of the first byte to overwrite
* \return the number of bytes moved
*/
u_int32_t move (u_int32_t begin, u_int32_t end, u_int32_t dest);
// synchronize (protected)
/*!
* \brief append a file at the end
* \param f the file to append
* \return the new size in bytes of the file
*/
u_int32_t append (qfile f); // operador << ?
/* HAS BUGS!!!
* \brief append part of a file at the end
* \param f the file to append partially
* \param start the first byte of f to append
* \param end the last byte of f to append
* \return ???
*/
// u_int32_t append (qfile f, u_int32_t start, u_int32_t end);
/*!
* \brief append a block of data at the end
* \param pointer pointer to the start of the data to append
* \param size number of bytes to append
* \return the new size in bytes of the file
*/
u_int32_t append (caddr_t pointer, u_int32_t size);
/*!
* \brief gets where the file is mapped
* \return return the memory location where the file is mapped
*/
caddr_t getMap();
/*!
* \brief gets the size of the file
* \return the number of bytes in the file
*/
u_int32_t getSize();
/*!
* \brief gets the name of the file
* \return a string with the name of the file
*/
string getName();
/*!
* \brief print the wav characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream *os);
/*!
* \brief creates a copy of the file with the given name
* \param copyname the name of the file where to copy the file contents
* \return an instantiation of the newly created file
*/
qfile dup (string copyname);
};
ostream& operator<<(ostream&, qfile&);
# endif
quelcom-0.4.0/lib/qmisc.hh 100644 0 0 552 7245453630 13434 0 ustar root root /*! \file
* header functions for miscellaneous funcions
*/
# include
# include // u_int32_t
extern u_int32_t time2ms (char *str);
extern u_int32_t time2msec (char *str);
extern string uint2string (u_int32_t ui);
extern string char2string (char c);
extern bool strcmpn(char *str1, char *str2, u_int32_t n);
string htmlize (string str);
quelcom-0.4.0/lib/qmp3.hh 100644 0 0 11606 7245453630 13242 0 ustar root root /*! \file
* header functions for qmp3
*/
# ifndef _qmp3_hh_
# define _qmp3_hh_
# include
# include "qfile.hh"
# include "qtag.hh"
# include "qmp3frameheader.hh"
# include "qcuthandler.hh"
# include "qvf.hh"
/*! \class qmp3
* \brief class for mp3 files.
*
* this class models a mp3 file mapped in memory
*/
class qmp3 : public qfile, public qmp3frameheader, public qtag {
private:
//! whether the entire file has been scanned searching for errors
bool scanned;
/*!
* \brief the number of frames
* \warning this value is consistent only if scanned==true
*/
u_int32_t frames;
/*!
* \brief the duration time expressed in milliseconds
* \warning this value is consistent only if scanned==true
*/
u_int32_t msduration;
//! whether the mp3 is vbr
bool vbr;
//! whether the mp3 has tag
bool hasTag;
/*!
* \brief the tag of the mp3
* \warning this value is consistent only if hasTag==true
*/
qtag *tag;
// void remap (caddr_t);
public:
/*!
* initializes itself with the given filename and flags
* \param filename the file to initialize the mp3
* \param flags the file open mode
* \see qfile::qfile()
*/
qmp3 (string name, u_int32_t flags = READ);
// u_int32_t scan (void *p, u_int32_t bufsize, u_int32_t signature=0);
/*!
* \brief scan the file for validity
* \param bufsize the number of skippable bytes to find the first valid header. zero by default -> no garbage allowed
* \return the number of frames of the mp3
*/
u_int32_t scan (u_int32_t bufsize=0);
/*!
* \brief whether the stream has been scanned or not
* \return whether the stream has been scanned or not
*/
bool isScanned();
/*!
* \brief whether the stream has frames with different bit rate or not
* \return whether the stream has frames with different bit rate or not
*/
bool isVbr();
/*!
* \brief gets the duration of the stream
* \return the duration of the stream expressed in milliseconds
*/
u_int32_t getMsDuration();
/*!
* \brief print the mp3 characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream *os);
/*!
* \brief append the given mp3 at the end.
* \param mp3 the mp3 to append at the end
* \param force whether to force the appending if the parameters don't match
* \return the new number of frames of the mp3
*/
u_int32_t append (qmp3 &mp3, bool force=false);
/*!
* \brief perform a cut operation
* \param ch the cuthandler which specifies how to cut
* \return the new number of frames of the mp3
*/
u_int32_t cut (qcuthandler&);
/*!
* \brief deletes part of the frames
* \param first the first sample to delete
* \param last the last sample to delete
* \return the new number of frames of the mp3
*/
u_int32_t cut (u_int32_t firstframe, u_int32_t lastframe);
/*!
* \brief truncates the file to the given number of frames
* \param frames the number of samples to keep
*/
void truncate (u_int32_t frames);
/*!
* \brief move frams in the file
* \param start_sample first frames to move
* \param end_sample last frame to move
* \param dest_sample first frame to be overwritten
*/
void move (u_int32_t frame_start, u_int32_t frame_end, u_int32_t frame_dest);
/*!
* \brief gets the stream lenght (does not include the tag)
* \return the number of bytes in the stream
*/
u_int32_t getStreamLength ();
/*!
* \brief gets the number of frames in the stream
* \warning this value is an aproximation if the stream isn't scanned
* \return the number of frames in the stream
*/
u_int32_t getFrames();
/*!
* \brief get the frame number of the given frame in value-format format
* \param vf the frame in value-format format
* \return the number of frame in range 1..getFrames()
*/
u_int32_t getFrame(qvf &);
/*!
* \brief get the offset of the given frame
* \param frame the frame
* \return the offset of the given frame from the start of the file
*/
u_int32_t getOffset(u_int32_t frame);
/*!
* \brief copy some frames to the given filename
* \param filename the file where to put the given range of frames
* \param start_frame the first frame to copy
* \param end_frame the last frame to copy
* \return the newly created mp3
*/
qmp3& getMp3(string name, u_int32_t start_frame, u_int32_t end_frame);
/*!
* \brief compares the mp3 parameters whether they're compatible or not
* \param mp3 the mp3 to check for compatibility
* \param force whether to force the compatibility if the parameters don't match
* \return whether compatible or not
*/
bool compatible(qmp3 &mp3, bool force=false); // operador ==
// tag getTag();
};
ostream &operator<<(ostream &os, qmp3 &m);
# endif
quelcom-0.4.0/lib/qmp3frameheader.hh 100644 0 0 7646 7245453630 15417 0 ustar root root /*! \file
* header functions for qmp3frameheader
*/
# ifndef _qmp3frameheader_hh_
# define _qmp3frameheader_hh_
# include
# include
/*!
* \brief class for mp3 frame headers
*
* this class models a mp3 frame header mapped in memory
*/
class qmp3frameheader {
private:
/*!
* \brief struct for mp3 frame headers
*
* this struct is defined to match exactly with a mp3 frame header with no change on a little-endian machine
*/
struct header {
u_int32_t
sync1:8, /*!< syncro field. should be 0x0ff */
protection:1, /*!< whether or not the frame has crc */
layer:2, /*!< mpeg frame layer */
version:2, /*!< mpeg frame version */
sync2:3, /*!< syncro field. should be 0x7 */
privat:1, /*!< bit for private use */
padding:1, /*!< whether the frame is one byte larger */
samplerate:2, /*!< sample rate */
bitrate:4, /*!< bit rate */
emphasis:2, /*!< which type of pre-emphasis must be used */
original:1, /*!< original bit stream (1) or copy (0) */
copyright:1, /*!< whether or not is a copyrighted frame */
mode_extension:2, /*!< type of joint stereo coding */
channel_mode:2; /*!< mono or which type of stereo */
};
//! pointer to the header (memory location where it is located)
struct header *header;
public:
/*!
* \brief gets where the frame header is mapped
* \return the memory location where the frame header is mapped
*/
caddr_t getMap();
/*!
* \brief remaps (changes) the location of the header
* \param a the new address of the header
*/
void remap(caddr_t a);
//! length in bytes of a mp3 frame header
static const u_int32_t HEADERSIZE;
static const u_int32_t MASK;
/*!
* \brief looks for (and reuses itself with) the next frame
* \param bufsize the number of bytes where to find the header
* \return the number of (garbage) skipped bytes
*/
u_int32_t setNext(u_int32_t bufsize=HEADERSIZE);
/*!
* \brief looks for (and reuses itself with) the next frame
* \param endstream
* \return the number of (garbage) skipped bytes
*/
u_int32_t setNext(caddr_t endstream);
static const u_int32_t LAYER1, LAYER2, LAYER3;
static const u_int32_t VERSION1, VERSION2, VERSION25, UNDEFINED_VERSION;
/*!
* \brief look for a frame header
* \param a the start searching point
* \param bufsize the number of bytes where to find the header
* \param signature the header must be compatible with this signature
* \param backwards whether to search forwards (by default) or backwards
* \return the address where the header has been found
*/
static caddr_t seek_header(caddr_t a, u_int32_t bufsize=HEADERSIZE, u_int32_t signature=0, bool backwards=false);
static bool compatible(caddr_t p, u_int32_t signature);
bool compatible(qmp3frameheader &h);
bool compatible(u_int32_t);
void print (ostream *os);
bool valid();
static bool valid(caddr_t);
qmp3frameheader();
qmp3frameheader(caddr_t p, u_int32_t bufsize = HEADERSIZE, u_int32_t signature=0);
// direct access to the header
u_int32_t get();
void set(u_int32_t h);
// direct access to the header fields (without checking!!):
enum qmp3frameheaderfield {
SYNC1, SYNC2, _VERSION, LAYER, PROTECTION, BITRATE, SAMPLERATE,
PADDING, PRIVAT, CHANNEL_MODE, MODE_EXTENSION, COPYRIGHT,
ORIGINAL, EMPHASIS
};
u_int32_t getField (enum qmp3frameheaderfield f);
void setField (enum qmp3frameheaderfield f, u_int32_t v);
string getVersion();
string getLayer();
u_int32_t getSamplesPerFrame();
u_int32_t getLength();
u_int32_t getSampleRate();
u_int32_t getBitRate();
u_int32_t getMsDuration();
u_int32_t getSignature();
bool isSilence();
void write(int fd);
};
ostream &operator<<(ostream &os, qmp3frameheader &fh);
# endif
quelcom-0.4.0/lib/qreport.hh 100644 0 0 2026 7245453630 14032 0 ustar root root /*! \file
* header functions for qreport
*/
# ifndef _report_hh_
# define _report_hh_
# include
//# include
# include "qfile.hh"
# include "qmp3.hh"
class qreport {
private:
enum type { FILE, MP3, DIR, BASE };
u_int32_t files, directories, errors;
u_int32_t samplerate, bitrate;
long long msduration, size;
enum type type;
string name;
bool vbr;
// list report_list;
public:
qreport ();
qreport (qfile &f);
qreport (qmp3 &mp3);
qreport (const string str);
void add (qreport r);// adds a report. behaviour depends on report type
// void add_error (string); // report an error
void print (ostream *os);
void html (ostream *os, string link="");
u_int32_t getDuration();
u_int32_t getBitRate();
u_int32_t getSampleRate();
string getName();
u_int32_t getFiles() { return files; }
string parameter2string();
string print_html ();
// setOutputFormat(...);
};
ostream &operator<<(ostream &os, qreport &r);
# endif
quelcom-0.4.0/lib/qtag.hh 100644 0 0 3400 7245453630 13267 0 ustar root root /*! \file
* header functions for qtag
*/
# ifndef __qtag_hh__
# define __qtag_hh__
# include "qfile.hh"
# include
/*!
* \brief class for mp3 tags
*
* this class models (partially) a mp3 tag v1.0
*/
class qtag {
private:
static const u_int32_t fieldlengths[];
//! struct for mp3 tags
struct tag {
char tagid[3], /*!< 'TAG' */
title[30], /*!< title */
artist[30], /*!< artist */
album[30], /*!< album name */
year[4], /*!< year */
comment[30], /*!< free comment */
genre[1]; /*!< one byte music genre identifier */
};
//! memory location where the tag is mapped
struct tag *tag;
public:
//! length of the tag
static const u_int32_t LENGTH;
//! list of tag fields
enum field { TAG=0, TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE };
/*!
* initializes itself with a tag in memory
* \param a the address where the tag is found
*/
qtag (caddr_t a);
/*!
* initializes itself with a tag in a file
* \param f the file where to look for the tag
*/
qtag (qfile &f);
/*!
* \brief gets the location in memory where the tag is placed
* \return the memory address of the tag
*/
caddr_t getMap();
// treballar amb strings!!
void get (enum field f, char *);
void set (enum field f, char *);
/*
* \brief whether the tag is (found and) valid
* \return whether is a valid tag or not
*/
bool isValid();
u_int32_t fieldlength (enum field f) { return fieldlengths[f]; }
void cleanFields ();
/*!
* \brief print the wav characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream *os);
};
ostream &operator<<(ostream &os, qtag &t);
# endif
quelcom-0.4.0/lib/qvf.hh 100644 0 0 5512 7245453630 13135 0 ustar root root /*! \file
* header functions for qvf
*/
# ifndef _qvf_hh_
# define _qvf_hh_
# include // ostream
# include
/*! \class qvf
* \brief class for value-format pairs.
*
* this class is a general porpouse class for quelcom.
* it allows handling values together with differents formats (units).
*/
class qvf {
public:
/*! \enum format
* \brief enumeration for the different formats supported
*/
enum format {
BYTES, /*!< bytes */
KBYTES, /*!< kilobytes (1024 bytes) */
MBYTES, /*!< megabytes (1024 kilobytes) */
MINUTES, /*!< minutes */
SECONDS, /*!< seconds */
MILLISECONDS, /*!< milliseconds */
SPECIFIC, /*!< specific, depends on what's applied */
UNDEFINED /*!< no defined, error prone... */
};
private:
//! the current value
u_int32_t value;
//! the current format
enum format format;
// què fashoquí???
u_int32_t time2msec(char*);
public:
/*! \fn static char format2char(enum format f)
* \brief converts the given format to its equivalent char
* \param f the format to convert to a char
* \return the corresponding char
*/
static char format2char(enum format f);
/*! \fn static enum format char2format(char c)
* \brief converts the given char to its equivalent format
* \param c the char to convert to format
* \return the corresponding format
*/
static enum format char2format(char c);
//! default constructor
qvf();
/*!
* initializes itself with the given value and format
* \param value the initial value
* \param format the initial format (specific by default)
*/
qvf(u_int32_t value, enum format f=SPECIFIC);
/*!
* initializes itself reading from a char string
*
* the format for the char string must be [M|k|b|m|s|j]: a unsigned int followed optionally by a char.
* if there's no char, the typed is initialized as specific, otherwise it should be M (for megabytes), k (for kilobytes), b (for bytes), m (for minutes), s (for seconds) or j (for milliseconds).
* \param str the char string containig the value and the format
*/
qvf(char *str);
/*! \fn u_int32_t getValue()
* \brief gets the value
* \return the value
*/
u_int32_t getValue();
/*! \fn enum format getFormat()
* \brief gets the format
* \return the format
*/
enum format getFormat();
/*! \fn void set (unsigned int v, enum format f=SPECIFIC)
* \brief sets the value and the format
* \param v the value
* \param f the format
*/
void set (unsigned int v, enum format f=SPECIFIC);
/*! \fn void print (ostream *os)
* \brief print the vf characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream *os);
};
ostream &operator<<(ostream &os, qvf &vf);
#endif
quelcom-0.4.0/lib/qwav.hh 100644 0 0 4420 7245453630 13314 0 ustar root root /*! \file
* header functions for qwav
*/
# ifndef _qwav_hh_
# define _qwav_hh_
# include "qfile.hh"
# include "qwavheader.hh"
# include "qcuthandler.hh"
# include
/*! \class qwav
* \brief class for wav files.
*
* this class models a wav file mapped in memory
*/
class qwav : public qfile, public qwavheader {
public:
/*!
* initializes itself with the given filename and flags
* \param filename the file to initialize the wav
* \param flags the file open mode (see ...)
*/
qwav (string filename, u_int32_t flags = READ);
/*!
* \brief compares both wavs whether they're compatible or not
* \param wav the wav to check for compatibility
* \return whether compatible or not
*/
bool compatible(qwav &wav);
/*!
* \brief print the wav characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream *os);
/*!
* \brief append the given wav at the end
* \param wav the wav to append at the end
*/
u_int32_t append (qwav wav);
/*!
* \brief perform a cut operation
* \param ch the cuthandler which specifies how to cut
* \return ???
*/
u_int32_t cut (qcuthandler &ch);
/*!
* \brief deletes part of the samples
* \param first the first sample to delete
* \param last the last sample to delete
* \return ??? check this!
*/
u_int32_t cut (u_int32_t first, u_int32_t last);
/*!
* \brief truncates the file to the given number of samples
* \param samples the number of samples to keep
*/
void truncate (u_int32_t samples);
/*!
* \brief move samples in the file
* \param start_sample first sample to move
* \param end_sample last sample to move
* \param dest_sample first sample to be overwritten
*/
void move (u_int32_t sample_start, u_int32_t sample_end, u_int32_t sample_dest);
/*!
* \brief copy some samples to the given filename
* \param filename the file where to put the given range of samples
* \param start_sample the first sample to copy
* \param end_sample the last sample to copy
* \return the newly created wav
*/
qwav& getWav(string filename, u_int32_t startsample, u_int32_t endsample);
};
ostream &operator<<(ostream &os, qwav &w);
# endif
quelcom-0.4.0/lib/qwavheader.hh 100644 0 0 11031 7245453630 14501 0 ustar root root /*! \file
* header functions for qwavheader
*/
#ifndef _qwavheader_hh_
#define _qwavheader_hh_
# include
# include "qvf.hh"
/*!
* \brief class for wav headers.
*
* this class models a 'canonical' wav header mapped in memory
*/
class qwavheader {
private:
/*!
* \brief struct for wav headers
*
* this struct is defined to match exactly with a 'canonical' wav header with no change on a little-endian machine
*/
struct header {
// riff chunk
char riff[4]; /*!< should be 'RIFF' */
u_int32_t rifflength; /*!< should be file size - 8 */
char wave[4]; /*!< should be 'WAVE' */
// fmt chunk
char fmt_[4]; /*!< should be 'fmt ' */
u_int32_t fmtlength; /*!< should be 16 (length of the fmt data) */
u_int16_t format; /*!< should be 1 (pcm) */
u_int16_t channels; /*!< stereo (1) or mono (0) */
u_int32_t samplerate; /*!< samples per second */
u_int32_t bytespersec; /*!< bytes per second: block align * sample rate */
u_int16_t bytespersample; /*!< bytes per sample (block align) */
u_int16_t bitspersample; /*!< bits per sample: 8 or 16 */
char data[4]; /*!< should be 'data' */
u_int32_t datalength; /*!< data block length (file size - 44) */
};
//! pointer to the header (memory location where it is located)
struct header *header;
public:
//! length in bytes of the wav header
static const u_int32_t HEADERSIZE;
/*!
* initializes itself with a memory address and validates with the given wav length
* \param p the memory address where the header is located
* \param length length of the wav file or zero to ignore
*/
qwavheader (caddr_t p, u_int32_t length=0);
/*!
* \brief gets the number of samples
* \return the number of samples
*/
u_int32_t getSamples();
/*!
* \brief modify the number of samples by adding a positive or negative increment
* \param increment the value to be added to the current number of samples
* \return the new number of samples
*/
u_int32_t addSamples(int increment);
/*!
* \brief set the number of samples
* \param number the new number of samples
* \return the new number of samples
*/
u_int32_t setSamples(u_int32_t number);
/*!
* \brief get the offset of the given sample in value-format format
* \param vf the sample in value-format format
* \return the offset of the given sample from the start of the file
*/
u_int32_t getOffset (qvf &vf);
/*!
* \brief get the offset of the given sample
* \param sample the sample
* \return the offset of the given sample from the start of the file
*/
u_int32_t getOffset (u_int32_t sample);
/*!
* \brief get the sample number of the given sample in value-format format
* \param vf the sample in value-format format
* \return the number of sample in range 1..getSamples()
*/
u_int32_t getSample (qvf &vf);
/*!
* \brief get the bits per sample (bps) value
* \return the bits per sample value
*/
u_int32_t getBitsPerSample();
/*!
* \brief get the bytes per sample value
* \return the bytes per sample value
*/
u_int32_t getBytesPerSample();
/*!
* \brief gets the number of channels
* \return the number of channels
*/
u_int32_t getChannels();
/*!
* \brief get whether is stereo or not
* \return whether is stereo or not
*/
bool getStereo();
/*!
* \brief gets the sample rate
* \return the sample rate
*/
u_int32_t getSampleRate();
/*!
* \brief get the duration in milliseconds
* \return the duration in milliseconds
*/
u_int32_t getMsDuration();
/*!
* \brief remaps (changes) the location of the header
* \param a the new address of the header
*/
void remap(caddr_t);
/*!
* \brief compares both headers whether they're compatible or not
* \param h the header to check for compatibility
* \return whether compatible or not
*/
bool compatible(const qwavheader&);
/*!
* \brief checks the validity of the header.
* \return whether is valid or not
*/
bool valid();
/*!
* \brief checks the validity of the header for a wav file of the given length
* \param length the length to check for validity
* \return whether is valid or not
*/
bool validLength(u_int32_t length);
/*!
* \brief write (copy) the header to the given address
* \param a the memory address where to write the header
*/
void write(caddr_t );
};
# endif
quelcom-0.4.0/lib/qwavsample.hh 100644 0 0 6661 7245453630 14527 0 ustar root root /*! \file
* header functions for qwavsample
*/
#ifndef _qwavsample_hh
#define _qwavsample_hh_
# include "qwav.hh"
# include
/*! \class qwavsample
* \brief class for wav samples.
*
* this class models a wav sample: mono or stereo, 8 or 16 bit
*/
class qwavsample {
private:
//! struct for 8 bit mono wav samples
struct mono8 { char m8; };
//! struct for 16 bit mono wav samples
struct mono16 { short m16; };
//! struct for 8 bit stereo wav samples
struct stereo8 { char left; char right; };
//! struct for 16 bit stereo wav samples
struct stereo16 { short left; short right; };
//! enum to define the type of sample
enum type {
MONO8, /*!< 8 bit mono wav sample */
MONO16, /*!< 16 bit mono wav sample */
STEREO8, /*!< 8 bit stereo wav sample */
STEREO16 /*!< 16 bit stereo wav sample */
};
//! the type of sample
enum type type;
//! union for wav samples
union sample {
char mono8;
short mono16;
struct stereo8 stereo8;
struct stereo16 stereo16;
};
//! pointer to the sample (memory location where it is mapped)
union sample *sample;
public:
/*!
* initializes itself with the given sample of the given wav
* \param wav pointer to a wav file to initialize the sample
* \param sample the sample to read (the first one by default)
*/
qwavsample(qwav *wav, u_int32_t sample=1);
/*!
* initializes itself with a memory address and the given sample type
* \param a the memory address where the sample is located
* \param type the type of sample (16 bit stereo by default)
*/
qwavsample(caddr_t a, enum type=STEREO16);
/*!
* initializes itself with a memory address and the given sample info
* from which the sample type is deduced
* \param a the memory address where the sample is located
* \param channels the number of channels of the sample (1/2)
* \param bps the number of bits per sample (8/16)
*/
qwavsample(caddr_t a, u_int32_t channels, u_int32_t bps);
/*!
* \fn int getLeft()
* \brief gets the left channel value
* \return the left channel value or simply the sample if mono
*/
int getLeft();
/*! \fn int getRight()
* \brief gets the right channel value
* \return the left channel value or simply the sample if mono
*/
int getRight();
/*! \fn void setNext()
* \brief sets the sample to the next contiguous sample in memory
*/
void setNext();
/*! \fn bool isSilence(u_int32_t threshold=0)
* \brief returns whether the sample value is under the threshold or not
* \param threshold (zero by default=>absolute silence)
* \return whether the sample value is under the threshold
*/
bool isSilence(u_int32_t threshold=0);
/*! \fn void print (ostream &os)
* \brief print the sample characteristics on the given output stream
* \param os the given output stream
*/
void print (ostream &os);
/*! \fn void prod(double f)
* \brief multiplies the sample value with the given factor
* \param f the factor to multiply the sample value with
*/
void prod(double d);
/*! \fn void set (int l, int r=0)
* \brief sets a new value for the sample
* \param l the left channel value, or the sample value if mono
* \param r the right channel value. omit if mono
*/
void set (int l, int r=0);
};
ostream& operator<<(ostream &os,qwavsample &s);
#endif
quelcom-0.4.0/lib/makefile 100644 0 0 2425 7245453630 13520 0 ustar root root
LIBTARGETS=libqextra.so libqmp3.so libqwav.so
all: $(LIBTARGETS)
#
# if you don't want to include native language support (=get quelcom messages
# in a different language than english) remove -DNLS below
#
CXXFLAGS=-DNLS -Wall
LDFLAGS=-lm
MP3LIB=qmp3 qmp3frameheader qtag qreport
MP3LIBSOURCES=$(addsuffix .cc,$(MP3LIB))
MP3LIBHEADERS=$(addsuffix .hh,$(MP3LIB))
MP3LIBOBJECTS=$(addsuffix .o,$(MP3LIB))
WAVLIB=qwav qwavheader qwavsample
WAVLIBSOURCES=$(addsuffix .cc,$(WAVLIB))
WAVLIBHEADERS=$(addsuffix .hh,$(WAVLIB))
WAVLIBOBJECTS=$(addsuffix .o,$(WAVLIB))
EXTRA=qexception qvf qcuthandler qfile qmisc
EXTRASOURCES=$(addsuffix .cc,$(EXTRA))
EXTRAHEADERS=$(addsuffix .hh,$(EXTRA))
EXTRAOBJECTS=$(addsuffix .o,$(EXTRA))
$(EXTRAOBJECTS) $(MP3LIBOBJECTS) $(WAVLIBOBJECTS): %.o: %.cc %.hh
$(CXX) $(CXXFLAGS) -o $@ -c $<
libqextra.so: $(EXTRAHEADERS) $(EXTRASOURCES) $(EXTRAOBJECTS)
$(CXX) $(CXXFLAGS) -o $@ -shared $(EXTRAOBJECTS)
strip $@
libqwav.so: $(WAVLIBSOURCES) $(WAVLIBHEADERS) $(WAVLIBOBJECTS)
$(CXX) $(CXXFLAGS) -o $@ -shared $(WAVLIBOBJECTS)
strip $@
libqmp3.so: $(MP3LIBSOURCES) $(MP3LIBHEADERS) $(MP3LIBOBJECTS)
$(CXX) $(CXXLIBFLAGS) -o $@ -shared $(MP3LIBOBJECTS)
strip $@
install: all
mkdir -p $(LIBDIR)
cp -f $(LIBTARGETS) $(LIBDIR)
clean:
rm -f *.o $(LIBTARGETS)
quelcom-0.4.0/doc/ 40755 0 0 0 7245453630 11717 5 ustar root root quelcom-0.4.0/doc/gpl.texinfo 100644 0 0 43651 7245453630 14225 0 ustar root root @setfilename gpl.info
@unnumbered GNU GENERAL PUBLIC LICENSE
@center Version 2, June 1991
@display
Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@end display
@unnumberedsec Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software---to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
@iftex
@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@end iftex
@ifinfo
@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@end ifinfo
@enumerate
@item
This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The ``Program'', below,
refers to any such program or work, and a ``work based on the Program''
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term ``modification''.) Each licensee is addressed as ``you''.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
@item
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
@item
You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
@enumerate a
@item
You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
@item
You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
@item
If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
@end enumerate
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
@item
You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
@enumerate a
@item
Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
@item
Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
@item
Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
@end enumerate
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
@item
You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
@item
You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
@item
Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
@item
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
@item
If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
@item
The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and ``any
later version'', you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
@item
If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
@iftex
@heading NO WARRANTY
@end iftex
@ifinfo
@center NO WARRANTY
@end ifinfo
@item
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
@item
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
@end enumerate
@iftex
@heading END OF TERMS AND CONDITIONS
@end iftex
@ifinfo
@center END OF TERMS AND CONDITIONS
@end ifinfo
@page
@unnumberedsec How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the ``copyright'' line and a pointer to where the full notice is found.
@smallexample
@var{one line to give the program's name and an idea of what it does.}
Copyright (C) 19@var{yy} @var{name of author}
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 2
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.
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.
@end smallexample
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
@smallexample
Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
@end smallexample
The hypothetical commands @samp{show w} and @samp{show c} should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than @samp{show w} and
@samp{show c}; they could even be mouse-clicks or menu items---whatever
suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a ``copyright disclaimer'' for the program, if
necessary. Here is a sample; alter the names:
@smallexample
@group
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
@var{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
@end group
@end smallexample
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
quelcom-0.4.0/doc/quelcom.texinfo 100644 0 0 75675 7245453630 15123 0 ustar root root \input texinfo.tex @c -*-texinfo-*-
@c %**start of header
@include version.texinfo
@setfilename quelcom.info
@settitle quelcom tools @value{VERSION}
@finalout
@setchapternewpage odd
@c %**end of header
@ifinfo
this file documents the @code{quelcom tools}: a set of commands to handle @file{.wav} and @file{.mp3} files@.
permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@ignore
permission is granted to process this file through tex and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
(this paragraph not being relevant to the printed manual).
@end ignore
permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
@end ifinfo
@titlepage
@title quelcom tools
@subtitle command line tools to handle @file{.wav} and @file{.mp3} files
@subtitle @value{UPDATED}
@author by david many@'e
@c això seria la cara del darrera de la portada
@page
@vskip 0pt plus 1filll
permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
@end titlepage
@node top
@include version.texinfo
@ifinfo
this file documents the @code{quelcom tools v@value{VERSION}}: a set of command line tools to handle @file{.wav} and @file{.mp3} files.
@end ifinfo
@c all the menus can be updated with the emacs command
@c texinfo-all-menus-update, which is normally bound to c-c c-u c-a.
@menu
* license:: what you can do with quelcom
* introduction:: introductory information.
* installation:: installation instructions
* wav tools:: tools to manipulate wav files
* mp3 tools:: tools to manipulate mp3 files
* cut points:: how to specify points in files
* specifying time:: how to specify time in arguments
@end menu
@contents
@node license, introduction, top, top
@include gpl.texinfo
@node introduction, installation, license, top
@chapter introduction
@code{quelcom tools} is a set of command line tools to manipulate @file{.wav} and @file{.mp3} files.
with these tools you can do a set of operations (get info, join, cut, delete fragments, detect silence, check, fade, ...) on maybe the most popular sound file formats (wave and mpeg layer 3) without the need of a grafical interface (xwindow) nor these or those grafical libraries.
since they are build as command line apps, they can be easily included in scripts to do automatically some job.
the @code{quelcom tools} package is written by @email{dmanye@@etse.urv.es,david many@'e} and you may find the package sources in @uref{http://www.etse.urv.es/~dmanye/quelcom/quelcom.html}.
@node installation, requirements, introduction, top
@chapter installation
@menu
* requirements::
* configuring building and installing::
* problems::
@end menu
@node requirements, configuring building and installing, installation, installation
@section requirements
the @code{quelcom tools} package is being developed on an old intel p133 with suse linux 6.3. other configurations may work also.
a c++ compiler is needed. currently are used gcc-2.95.2 and egcs-2.91.66. you can get the compiler name and version issuing the command @code{gcc@w{ }--version}.
and of course, you also need que @code{quelcom tools} package. you may find it at @w{http://www.etse.urv.es/~dmanye/quelcom/quelcom.html}. using the latest available version is recommended.
@node configuring building and installing, problems, requirements, installation
@section configuring and building
@enumerate
@item
unpack the package with the command @code{tar@w{ }xzf@w{ }quelcom-@value{VERSION}.tar.gz}. this creates a directory named @file{quelcom-@value{VERSION}} and expands there all the files.
@item
get into the directory with @code{@w{cd quelcom-@value{VERSION}}}
@item
if you want, you can take a look at the makefiles. then type @code{make} to build the sources. some compiler messages may appear, but it should compile successfully.
@item
once the package is successfully build, you can proceed to install it with @code{make install}.
by default, the executables are installed under @file{/usr/local/bin}, the libraries under @file{/usr/local/lib}, the translation @file{.mo} files under @file{/usr/local/share/locale} and the info manual file under @file{/usr/local/info}.
@end enumerate
to activate the automatic translation to catalan or to spanish (the only languages supported at this moment), it should be enough (if there haven't been no problem until now), setting the environment variable @env{LANG} this way (with @command{bash} shell): @command{export LANG=ca} or @command{export LANG=es} respectively. otherwise, the messages will appear in english.
@node problems, wav tools, configuring building and installing, installation
@section problems
if you have problems configuring or building the package, or if you find a bug in any of the tools, please update to the latest release. if the problem remains, please send electronic mail to @w{@samp{dmanye@@etse.urv.es}} including the version number and a detailed description of the problem.
@node wav tools, qwavcut, problems, top
@chapter wav tools
tests has been done only with 44100 Hz 16 bit stereo files, though it may work with mono/stereo 8/16 bits files.
the tools to handle wav files are the following:
@menu
* qwavcut:: extract and/or delete parts of a wav file@.
* qwavfade:: fade in/out wav files@.
* qwavheaderdump:: dump (and fix) wav headers@.
* qwavinfo:: show info from wav files@.
* qwavjoin:: join multiple wav files in one@.
* qwavsilence:: detect and shrink silence sequences in wav files@.
@end menu
@iftex
@ifnothtml
@itemize @bullet
@item @command{qwavcut}
to extract and/or delete parts of a wav file@.
@item @command{qwavfade}
to fade in/out wav files@.
@item @command{qwavheaderdump}
to dump (and fix) wav headers@.
@item @command{qwavinfo}
to show info from wav files@.
@item @command{qwavjoin}
to join multiple wav files in one@.
@item @command{qwavsilence}
to detect and shrink silence sequences in wav files@.
@end itemize
@end ifnothtml
@end iftex
@page
@node qwavcut, qwavfade, wav tools, wav tools
@section qwavcut
@command{qwavcut} extracts and/or deletes parts of a wav file
@subsection synopsis
@samp{qwavcut @var{option}@dots{} @var{file}}
@subsection description
@command{qwavcut} allows to extract and/or delete a fragment of a wav file. some parameters must be supplied in order to define the start/size/end cut points and what to do then: either the fragment must be copied to another file or erased from the file (or both)
@subsection general options
@table @samp
@item -d
@itemx --delete
deletes the fragment from the file. if option @option{--delete} is used, deletion is always done after fragment extraction.
@item -h
@itemx --help
show a brief help and exit.
@item -o @var{outfile}
@itemx --output=@var{outfile}
@var{outfile} is the name of the file where all the samples in the given fragment will be copied.
@c @item -v
@c @itemx --verbose
@c show which operations are done.
@item -V
@itemx --version
show version and exit.
@end table
@subsection cut options
cut options are used to specify where the fragment begins and ends. there are two ways to do it: with time slices (easier) and with cut points (more complex but also more powerful). cut options are mandatory (which way is used is matter of your choice).
if time slices are used, cut points options are automatically ignored.
@subsubsection cut with time slices
there is only one option:
@table @samp
@item -S @var{timeslice}
@itemx --slice @var{timeslice}
@var{timeslice} (@pxref{specifying time}) specifies, in terms of time, where the cut begins and ends.
@end table
@subsubsection cut with cut points
there are several options with cut points. cut points are used to specify at which sample the fragment begins (@option{--begin} and @option{--Begin}), ends (@option{--end} and @option{--End}), or which size it has (@option{--size}). at least, one cut option must be specified (non specified options take its default values). neither the options @option{--begin} and @option{--Begin}, and the options @option{--end} and @option{--End} can be used together; also, a begin, end and size option cannot be used at the same time.
by default, the fragment begins at the first sample and ends at the last sample; there's no default value for size.
@table @samp
@item -b @var{cutpoint}
@itemx --set-begin-from-eof=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the first sample of the file that belongs to the cut counting from the end of the file.
@item -B @var{cutpoint}
@itemx --set-begin=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the first sample of the file that belongs to the cut counting from the beginning of the file.
@item -e @var{cutpoint}
@itemx --set-end-from-eof=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the last sample of the file that belongs to the cut counting from the end of the file.
@item -E @var{cutpoint}
@itemx --set-end=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the last sample of the file that belongs to the cut counting from the beginning of the file.
@item -s @var{cutpoint}
@itemx --size=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the number of samples contained in the cut.
@end table
@subsection examples
@enumerate
@item
to get the last ten seconds of a file
@example
qwavcut -b 10s -o outfile.wav infile.wav
@end example
@item
four different ways to get the first minute of a file:
@example
qwavcut -S -1:0 -o outfile.wav infile.wav
qwavcut -S -60 -o outfile.wav infile.wav
qwavcut -E 1m -o outfile.wav infile.wav
qwavcut -s 1m -o outfile.wav infile.wav
@end example
@item
four ways of getting the second quarter of a file:
@example
qwavcut -S 15:0-30:0 -o outfile.wav infile.wav
qwavcut -B 15m -E 30m -o outfile.wav infile.wav
qwavcut -s 15m -E 30m -o outfile.wav infile.wav
qwavcut -B 15m -s 15m -o outfile.wav infile.wav
@end example
@end enumerate
@page
@node qwavfade, qwavheaderdump, qwavcut, wav tools
@section qwavfade
@command{qwavfade} fade in/out wav files
@subsection synopsis
@samp{qwavfade @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qwavfade} modifies a wav file applying on it a fade in or a fade out or both.
a fade consists in modifying progressively the level of the wav as if you were slowly increasing or decreasing the volume. a fade in consists in increasing the volume starting from a low level at the beginning of the wav. a fade out consists in decreasing the volume to a low level at the end of the wav.
@subsection option list
@table @samp
@item -d @var{cutpoint}
@itemx --duration=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the duration of the fade. the default value is five seconds. this option overrides the @option{--length} option explained below.
@item -h
@itemx --help
show a brief help and exit.
@item -i
@itemx --in
just fade in. don't fade out. by default, fade in and fade out.
@item -l @var{time}
@itemx --length=@var{time}
@var{time} (@pxref{specifying time}) specifies the length(=duration) of the fade. this option is quite similar to the @option{--duration} option above. it's easier to use though not as powerful than the previous one. the default value is five seconds. this option overrides @option{--duration} option explained above.
@item -o
@itemx --out
just fade out. don't fade in. by default, fade in and fade out.
@item -t
@itemx --test
this option can be used to create and fade test files instead of modifying the original file. a test file will be created for each type of selected fade (in or out). the name of the test file will be @file{fadein.@var{file}} or @file{fadeout.@var{file}}. the duration of the test files is the fade duration plus five seconds.
@item -v
@itemx --verbose
show more detailed info.
@item -V
@itemx --version
show version and exit.
@end table
@subsection example
suppose you want to fade in and out the fantastic song @file{live.in.concert.wav} using a fade duration of 3.5 seconds:
first we are going to test:
@example
qwavfade --test --length 3.5 live.in.concert.wav
@end example
hear the test fades:
@example
my-wav-player fadein.live.in.concert.wav fadeout.live.in.concert.wav
@end example
if you want to try with another duration, jump to the first step and change the @option{length}(or @option{--duration}) argument.
if you're happy with the tests (omit @option{--test}):
@example
qwavfade --length 3.5 live.in.concert.wav
@end example
@subsection notes
@command{qwavfade} doesn't allow both types of fades (in and out) to overlap. if you want to fade in and out a wav file, and the two regions to fade overlap, then probably you made a mistake (maybe you selected a too large fade). in any case, you'll have to fade separately.
@page
@node qwavheaderdump, qwavinfo, qwavfade, wav tools
@section qwavheaderdump
@command{qwavheaderdump} dumps (and fixes) wav headers
@subsection synopsis
@samp{qwavheaderdump @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qwavheaderdump} reads a list of wav files and prints on standard output all its header values in text (no binary) form. also, it has ability to fix some of the headers in case they'd be incorrect.
@subsection option list
@table @samp
@item -F
@itemx --fix
correct the header if there's any incorrect value. not all the fields are recoverable.
@item -h
@itemx --help
show a brief help and exit.
@item -q
@itemx --quiet
no output messages. don't show detected (and corrected) errors.
@item -V
@itemx --version
show version and exit.
@end table
@page
@node qwavinfo, qwavjoin, qwavheaderdump, wav tools
@section qwavinfo
@command{qwavinfo} show info from wav files.
@subsection synopsis
@samp{qwavinfo @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qwavinfo} reads a list of wav files and prints on standard output some of its parameters: sample rate, bits per sample, mono/stereo and duration. a duration summary is appended at the end of the list.
@subsection option list
@table @samp
@item -h
@itemx --help
show a brief help and exit.
@item -s
@itemx --summary-only
show only the summary. do not show info from every file.
@item -v
@itemx --verbose
show also the number of bytes and samples.
@item -V
@itemx --version
show version and exit.
@end table
@c exemple...
@page
@node qwavjoin, qwavsilence, qwavinfo, wav tools
@section qwavjoin
@command{qwavjoin} joins wav files
@subsection synopsis
@samp{qwavjoin @var{option}@dots{} @var{file1} @var{file2}@dots{}}
@subsection description
@command{qwavjoin} reads a list of wav files and joins them in the specified order in one wav file. the files must have the same parameters (i.e. sampling rate, bytes per sample, @dots{}) in order that the joining can be done.
@subsection option list
@table @samp
@item -h
@itemx --help
show a brief help and exit.
@item -o @var{outfile}
@itemx --output=@var{outfile}
@var{outfile} is the name of the file where all the samples will be copied. if this option is not used, the samples from the second to the last file of the list will be appended to @var{file1}.
@item -v
@itemx --verbose
show which operations are done.
@item -V
@itemx --version
show version and exit.
@end table
@c exemple...
@page
@node qwavsilence, mp3 tools, qwavjoin, wav tools
@section qwavsilence
@command{qwavsilence} detects and shrinks silence sequences in wav files
@subsection synopsis
@samp{qwavsilence @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qwavsilence} reads a list of wav files looking for silence sequences longer than a given value, possibly shrinking them.
@subsection option list
@table @samp
@item -d @var{cutpoint}
@itemx --duration=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the minimum duration of a silent sequence in a file to be reported. the default value is one second. this option overrides the option @option{--length} explained below.
@item -h
@itemx --help
show a brief help and exit.
@item -l @var{time}
@itemx --length=@var{time}
@var{time} (@pxref{specifying time}) specifies the minimum length(=duration) of a silent sequence in a file to be reported. this option is quite similar to the @option{--duration} option above. it's easier to use though not as powerful than the previous one. the default value is one second. this option overrides the @option{--duration} option explained above.
@item -S
@itemx --shrink
when this option is set, all the silent sequences greater than the value of the @option{--duration} option will be shrinked down to @var{duration} and the file size truncated accordingly.
@item -t @var{threshold}
@itemx --threshold=@var{threshold}
@var{threshold} is a percentage value respect the maximum (absolute) sample value. samples whose value is under the given @var{threshold} are considered silent. for example, a value of 2 means that all samples with absolute value under the 2% will be treated as silent samples. the default value is 0.
@item -v
@itemx --verbose
show also sample information.
@item -V
@itemx --version
show version and exit.
@end table
@c @subsection example
@node mp3 tools, qmp3check, qwavsilence, top
@chapter mp3 tools
tests have been done only with mpeg version 1 layer iii streams, though it may (or not) work with other versions or layers.
the tools to handle mp3 files are the following:
@menu
* qmp3check:: check and clean mp3 files@.
* qmp3cut:: extract and/or delete fragments from a mp3 file@.
* qmp3info:: show info from mp3 files@.
* qmp3join:: join multiple mp3 files in one@.
* qmp3report:: generate simple reports for mp3 files and directories
@end menu
@iftex
@ifnothtml
@itemize @bullet
@item @command{qmp3check}
to check and clean mp3 files@.
@item @command{qmp3cut}
to extract and/or delete parts of a mp3 file@.
@item @command{qmp3info}
to show info from mp3 files@.
@item @command{qmp3join}
to join multiple mp3 files in one@.
@item @command{qmp3report}
to generate simple reports for mp3 files and directories
@end itemize
@end ifnothtml
@end iftex
@page
@node qmp3check, qmp3cut, mp3 tools, mp3 tools
@section qmp3check
@command{qmp3check} checks and cleans mp3 streams
@subsection synopsis
@samp{qmp3check @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qmp3check} reads mp3 streams looking for invalid frames or, simply, garbage. it can be used as a mp3 file checker but also as a mp3 file cleaner because it is able to strip garbage bits from the streams.
@subsection option list
@table @samp
@item -D
@itemx --delete
delete invalid frames and garbage. use with care
@item -h
@itemx --help
show a brief help and exit.
@item -q
@itemx --quiet
no output messages
@item -T
@itemx --delete-tag
delete tag (if exists). option @option{--delete} must be set.
@item -v
@itemx --verbose
show more detailed info
@item -V
@itemx --version
show version and exit.
@end table
@page
@node qmp3cut, qmp3info, qmp3check, mp3 tools
@section qmp3cut
@command{qmp3cut} extracts and/or deletes parts of a mp3 file
@subsection synopsis
@samp{qmp3cut @var{option}@dots{} @var{file}}
@subsection description
@command{qmp3cut} allows to extract and/or delete a fragment of a mp3 file. some parameters must be supplied in order to define the start/size/end cut points and what to do then: either the fragment must be copied to another file or erased from the file (or both)
@subsection general options
@table @samp
@item -d
@itemx --delete
deletes the fragment from the file. if option @option{--output} is used, deletion is always done after fragment extraction.
@item -h
@itemx --help
show a brief help and exit.
@item -o @var{outfile}
@itemx --output=@var{outfile}
@var{outfile} is the name of the file where all the frames in the given fragment will be copied.
@item -v
@itemx --verbose
verbose
@item -V
@itemx --version
show version and exit.
@end table
@subsection cut options
cut options are used to specify where the fragment begins and ends. there are two ways to do it: with time slices (easier) and with cut points (more complex but also more powerful). cut options are mandatory (which way is used is matter of your choice).
if time slices are used, cut points options are automatically ignored.
@subsubsection cut with time slices
there is only one option:
@table @samp
@item -S @var{timeslice}
@itemx --slice @var{timeslice}
@var{timeslice} (@pxref{specifying time}) specifies, in terms of time, where the cut begins and ends.
@end table
@subsubsection cut with cut points
there are several options with cut points. cut points are used to specify at which frame the fragment begins (@option{--begin} and @option{--Begin}), ends (@option{--end} and @option{--End}), or which size it has (@option{--size}). at least, one cut option must be specified (non specified options take its default values). neither the options @option{--begin} and @option{--Begin}, and the options @option{--end} and @option{--End} can be used together; also, a begin, end and size option cannot be used at the same time.
by default, the fragment begins at the first frame and ends at the last frame; there's no default value for size.
@table @samp
@item -b @var{cutpoint}
@itemx --set-begin-from-eof=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the first frame of the file that belongs to the cut counting from the end of the file.
@item -B @var{cutpoint}
@itemx --set-begin=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the first frame of the file that belongs to the cut counting from the beginning of the file.
@item -e @var{cutpoint}
@itemx --set-end-from-eof=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the last frame of the file that belongs to the cut counting from the end of the file.
@item -E @var{cutpoint}
@itemx --set-end=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the last frame of the file that belongs to the cut counting from the beginning of the file.
@item -s @var{cutpoint}
@itemx --size=@var{cutpoint}
@var{cutpoint} (@pxref{cut points}) specifies the number of frames contained in the cut.
@end table
@subsection examples
@enumerate
@item
to get the last ten seconds of a file
@example
qmp3cut -b 10s -o outfile.mp3 infile.mp3
@end example
@item
four different ways to get the first minute of a file:
@example
qmp3cut -S -1:0 -o outfile.mp3 infile.mp3
qmp3cut -S -60 -o outfile.mp3 infile.mp3
qmp3cut -E 1m -o outfile.mp3 infile.mp3
qmp3cut -s 1m -o outfile.mp3 infile.mp3
@end example
@item
four ways of getting the second quarter of a file:
@example
qmp3cut -S 15:0-30:0 -o outfile.mp3 infile.mp3
qmp3cut -B 15m -E 30m -o outfile.mp3 infile.mp3
qmp3cut -s 15m -E 30m -o outfile.mp3 infile.mp3
qmp3cut -B 15m -s 15m -o outfile.mp3 infile.mp3
@end example
@end enumerate
@page
@node qmp3info, qmp3join, qmp3cut, mp3 tools
@section qmp3info
@command{qmp3info} show info from mp3 files.
@subsection synopsis
@samp{qmp3info @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qmp3info} reads a list of mp3 files and prints on standard output some of its parameters: version, layer, sample rate, bit rate, duration and tag. a duration summary is appended at the end of the list.
@subsection option list
@table @samp
@item -c
@itemx --check
check the entire stream (slower but accurate). all the frames of the stream are read and the total duration is exactly computed. this option is automatically activated if the stream appears to be vbr (have different bit rate frames).
@item -h
@itemx --help
show a brief help and exit.
@item -s
@itemx --summary-only
show only the summary. do not show info from every file.
@item -v
@itemx --verbose
show also the number of bytes and frames.
@item -V
@itemx --version
show version and exit.
@end table
@c exemple...
@subsection bugs
variable bit rate (vbr) streams are detected by reading the initial 5 frames in the stream. if their bit rate field differs, the @option{--check} option is activated automatically.
if vbr is not detected, @command{qmp3info} reads only the first frame in the stream and calculates the duration supposing that (1) the entire stream is composed by valid frames and (2) all the frames have the same bit rate. this is a fast way to compute the duration of the stream, but it is not exact: there's an error of 0.3% aprox. if you want to be accurate, or @command{qmp3info} is unable to detect a vbr stream, use @option{--check}.
@page
@node qmp3join, qmp3report, qmp3info, mp3 tools
@section qmp3join
@command{qmp3join} joins mp3 files
@subsection synopsis
@samp{qmp3join @var{option}@dots{} @var{file1} @var{file2}@dots{}}
@subsection description
@command{qmp3join} reads a list of mp3 files and joins them in one mp3 file in the specified order. some conditions must be met for the parameters of each of the files (see the notes subsection below).
@subsection option list
@table @samp
@item -f
@itemx --force
force join bypassing bit rate checks. by default, to join two files they must be both vbr (have variable bit rate) or have the same bit rate. using this option you can skip this check.
@item -h
@itemx --help
show a brief help and exit.
@item -o @var{outfile}
@itemx --output=@var{outfile}
@var{outfile} is the name of the file where all the frames will be copied. if this option is not used, the frames from the second to the last file of the list will be appended to @var{file1}.
@item -v
@itemx --verbose
show which operations are done.
@item -V
@itemx --version
show version and exit.
@end table
@c exemple...
@subsection notes
both mp3 must have the same bit rate or (both) must have a variable bit rate. this restriction can be by-passed with the @option{--force} flag.
before joining, all the streams are tested for validity. this is a time consuming operation. if the streams are not found clean, the join operation is aborted, so if you want to join @i{dirty} streams or simply qmp3join detects a clean stream as dirty, please report this as a bug and/or use @command{cat}.
due to the mp3 file format characteristics, @command{qmp3join} can be viewed like a @i{better but restrictive} @command{cat} for mp3 files.
@page
@node qmp3report, cut points, qmp3join, mp3 tools
@section qmp3report
@command{qmp3report} reports mp3 files and directories
@subsection synopsis
@samp{qmp3report @var{option}@dots{} @var{file}@dots{}}
@subsection description
@command{qmp3report} reads mp3 files or directories containing mp3 files and gives information about them. @command{qmp3report} can output the reports with plain text or in html format. using the latter format, you can @i{navigate} your mp3 directories with a web browser.
@subsection option list
@table @samp
@item -a
@itemx --all-files
report all files, not just files with suffix @file{.mp3}.
@item -A
@itemx --show-all
implies @option{--dirs}, @option{--files} and @option{--summary}. show report for files and directories and a summary report.
@item -d
@itemx --dirs
show a report for every directory containing reported files/directories. note that if option @option{--all-files} is not set, only will be reported those directories containing mp3 files.
@item -f
@itemx --files
show a report for every reportable file (see also @option{--all-files}).
@item -h
@itemx --help
show a brief help and exit.
@item -H
@itemx --html
output in html format (default is plain text).
@item -r
@itemx --recursive
scan directories.
@item -s
@itemx --summary
show a summary report.
@item -S
@itemx --split
split report across visited directories. @command{qmp3report} leaves in each visited directory a file with the report for that directory, independently of the output format. the name of the report file is the name of the directory with extension @file{.txt} or @file{.html} depending on the selected output format.
@item -v
@itemx --verbose
show more detailed info.
@item -V
@itemx --version
show version and exit.
@end table
@c exemple... qmp3report -rA .
@c exemple... qmp3report -rAHS .
@subsection bugs
variable bit rate (vbr) streams are detected by reading the initial 5 frames in the stream. if their bit rate field differs, the entire stream is read to compute the duration time with accuracy (@pxref{qmp3info}).
if vbr is not detected, @command{qmp3report} reads only the first frame in the stream and calculates the duration supposing that (1) the entire stream is composed by valid frames and (2) all the frames have the same bit rate. this is a fast way to compute the duration of the stream, but it is not exact: there's an error of 0.3% aprox.
the @i{htmlize} function, which converts file names in a suitable form for html format (ie. replacing blanks with '@i{%20}'), is not bulletproof.
@node cut points, specifying time, qmp3report, top
@appendix cut points
cut points are used to specify point in a sound file. they can also be used to speciy a size or a time duration using the beginning of the file as start reference. a cut point has the following form:
@var{value}[@var{format}]
@c farcir tot això d'exemples!!!
@c some of the commands have options referring to a point (a begin or an end of a fragment for qwavcut and qmp3cut) or a part of a file (a duration for qwavfade or qwavsilence, a size for qwavcut or qmp3cut).
in all cases, a positive integer @var{value} is required. the wav tools treat this number as a number of samples, whereas the mp3 tools treat this number as a number of frames. since most of the times is hard to specify a point (or size, or duration) in a file in terms of samples or frames, some modifiers are accepted. these modifiers consist in a single letter that must be written behind the number without leaving any blank.
@appendixsec cut points modifiers
these are the valid modifiers and how they modify the interpretation of @var{value}:
@table @code
@item j
milliseconds
@item s
seconds
@item m
minutes
@item b
bytes
@item k
kbytes (1024 bytes)
@item M
megabytes (1024 kbytes)
@end table
in either case, the given values will be rounded to an integer number of samples/frames.
@node specifying time, , cut points, top
@appendix specifying time
time specifiers are a easier (more @i{human}) way than cut options to specify points in a file.
a time specifier has the following form:
[[@var{h}:]@var{m}:]@var{s}[.@var{ms}]
where:
@table @code
@item @var{h}
hours
@item @var{m}
minutes
@item @var{s}
seconds
@item @var{ms}
milliseconds
@end table
as you can see, time specifiers are easier to use but less powerful than cut options (which can also specify a point in a file in terms of bytes or frames/samples).
@c posar-hi exemples
@appendixsec time slices
time slices are composed by two time specifiers designing a range (slice) of time:
@var{begin}-@var{end}
where @var{begin} and @var{end} are time specifiers. they can be not specified, meaning, respectively, the beginning and the end of the file.
@c més exemples
@bye
quelcom-0.4.0/doc/version.texinfo 100644 0 0 52 7245453630 15034 0 ustar root root
@set VERSION 0.4.0
@set UPDATED feb 2001
quelcom-0.4.0/doc/quelcom.html 100644 0 0 153625 7245453630 14423 0 ustar root root
[ Next:introduction
| Previous:Top
| Up:Top
]
Version 2, June 1991
Copyright © 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does.
Copyright (C) 19yy name of author
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 2
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.
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
The hypothetical commands show w
and show c
should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than show w
and
show c
; they could even be mouse-clicks or menu items--whatever
suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon , 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
[ Next:installation
| Previous:license
| Up:Top
]
quelcom tools
is a set of command line tools to manipulate .wav
and .mp3
files.
with these tools you can do a set of operations (get info, join, cut, delete fragments, detect silence, check, fade, ...) on maybe the most popular sound file formats (wave and mpeg layer 3) without the need of a grafical interface (xwindow) nor these or those grafical libraries.
since they are build as command line apps, they can be easily included in scripts to do automatically some job.
the quelcom tools
package is written by david manyé and you may find the package sources in http://www.etse.urv.es/~dmanye/quelcom/quelcom.html .
[ Next:requirements
| Previous:introduction
| Up:Top
]
[ Next:configuring building and installing
| Previous:installation
| Up:installation
]
the quelcom tools
package is being developed on an old intel p133 with suse linux 6.3. other configurations may work also.
a c++ compiler is needed. currently are used gcc-2.95.2 and egcs-2.91.66. you can get the compiler name and version issuing the command gcc --version
.
and of course, you also need que quelcom tools
package. you may find it at http://www.etse.urv.es/~dmanye/quelcom/quelcom.html. using the latest available version is recommended.
[ Next:problems
| Previous:requirements
| Up:installation
]
unpack the package with the command tar xzf quelcom-0.4.0.tar.gz
. this creates a directory named quelcom-0.4.0
and expands there all the files.
get into the directory with cd quelcom-0.4.0
if you want, you can take a look at the makefiles. then type make
to build the sources. some compiler messages may appear, but it should compile successfully.
once the package is successfully build, you can proceed to install it with make install
.
by default, the executables are installed under /usr/local/bin
, the libraries under /usr/local/lib
, the translation .mo
files under /usr/local/share/locale
and the info manual file under /usr/local/info
.
to activate the automatic translation to catalan or to spanish (the only languages supported at this moment), it should be enough (if there haven't been no problem until now), setting the environment variable LANG
this way (with bash
shell): export LANG=ca
or export LANG=es
respectively. otherwise, the messages will appear in english.
[ Next:wav tools
| Previous:configuring building and installing
| Up:installation
]
if you have problems configuring or building the package, or if you find a bug in any of the tools, please update to the latest release. if the problem remains, please send electronic mail to dmanye@etse.urv.es
including the version number and a detailed description of the problem.
[ Next:qwavcut
| Previous:problems
| Up:Top
]
tests has been done only with 44100 Hz 16 bit stereo files, though it may work with mono/stereo 8/16 bits files.
the tools to handle wav files are the following:
qwavcut : : extract and/or delete parts of a wav file.
qwavfade : : fade in/out wav files.
qwavheaderdump : : dump (and fix) wav headers.
qwavinfo : : show info from wav files.
qwavjoin : : join multiple wav files in one.
qwavsilence : : detect and shrink silence sequences in wav files.
[ Next:qwavfade
| Previous:wav tools
| Up:wav tools
]
qwavcut
extracts and/or deletes parts of a wav file
qwavcut option ... file
qwavcut
allows to extract and/or delete a fragment of a wav file. some parameters must be supplied in order to define the start/size/end cut points and what to do then: either the fragment must be copied to another file or erased from the file (or both)
-d
--delete
deletes the fragment from the file. if option --delete
is used, deletion is always done after fragment extraction.
-h
--help
show a brief help and exit.
-o outfile
--output=outfile
outfile is the name of the file where all the samples in the given fragment will be copied.
-V
--version
show version and exit.
cut options are used to specify where the fragment begins and ends. there are two ways to do it: with time slices (easier) and with cut points (more complex but also more powerful). cut options are mandatory (which way is used is matter of your choice).
if time slices are used, cut points options are automatically ignored.
there is only one option:
-S timeslice
--slice timeslice
timeslice (see specifying time ) specifies, in terms of time, where the cut begins and ends.
there are several options with cut points. cut points are used to specify at which sample the fragment begins (--begin
and --Begin
), ends (--end
and --End
), or which size it has (--size
). at least, one cut option must be specified (non specified options take its default values). neither the options --begin
and --Begin
, and the options --end
and --End
can be used together; also, a begin, end and size option cannot be used at the same time.
by default, the fragment begins at the first sample and ends at the last sample; there's no default value for size.
-b cutpoint
--set-begin-from-eof=cutpoint
cutpoint (see cut points ) specifies the first sample of the file that belongs to the cut counting from the end of the file.
-B cutpoint
--set-begin=cutpoint
cutpoint (see cut points ) specifies the first sample of the file that belongs to the cut counting from the beginning of the file.
-e cutpoint
--set-end-from-eof=cutpoint
cutpoint (see cut points ) specifies the last sample of the file that belongs to the cut counting from the end of the file.
-E cutpoint
--set-end=cutpoint
cutpoint (see cut points ) specifies the last sample of the file that belongs to the cut counting from the beginning of the file.
-s cutpoint
--size=cutpoint
cutpoint (see cut points ) specifies the number of samples contained in the cut.
to get the last ten seconds of a file
qwavcut -b 10s -o outfile.wav infile.wav
four different ways to get the first minute of a file:
qwavcut -S -1:0 -o outfile.wav infile.wav
qwavcut -S -60 -o outfile.wav infile.wav
qwavcut -E 1m -o outfile.wav infile.wav
qwavcut -s 1m -o outfile.wav infile.wav
four ways of getting the second quarter of a file:
qwavcut -S 15:0-30:0 -o outfile.wav infile.wav
qwavcut -B 15m -E 30m -o outfile.wav infile.wav
qwavcut -s 15m -E 30m -o outfile.wav infile.wav
qwavcut -B 15m -s 15m -o outfile.wav infile.wav
[ Next:qwavheaderdump
| Previous:qwavcut
| Up:wav tools
]
qwavfade
fade in/out wav files
qwavfade option ... file ...
qwavfade
modifies a wav file applying on it a fade in or a fade out or both.
a fade consists in modifying progressively the level of the wav as if you were slowly increasing or decreasing the volume. a fade in consists in increasing the volume starting from a low level at the beginning of the wav. a fade out consists in decreasing the volume to a low level at the end of the wav.
-d cutpoint
--duration=cutpoint
cutpoint (see cut points ) specifies the duration of the fade. the default value is five seconds. this option overrides the --length
option explained below.
-h
--help
show a brief help and exit.
-i
--in
just fade in. don't fade out. by default, fade in and fade out.
-l time
--length=time
time (see specifying time ) specifies the length(=duration) of the fade. this option is quite similar to the --duration
option above. it's easier to use though not as powerful than the previous one. the default value is five seconds. this option overrides --duration
option explained above.
-o
--out
just fade out. don't fade in. by default, fade in and fade out.
-t
--test
this option can be used to create and fade test files instead of modifying the original file. a test file will be created for each type of selected fade (in or out). the name of the test file will be fadein.file
or fadeout.file
. the duration of the test files is the fade duration plus five seconds.
-v
--verbose
show more detailed info.
-V
--version
show version and exit.
suppose you want to fade in and out the fantastic song live.in.concert.wav
using a fade duration of 3.5 seconds:
first we are going to test:
qwavfade --test --length 3.5 live.in.concert.wav
hear the test fades:
my-wav-player fadein.live.in.concert.wav fadeout.live.in.concert.wav
if you want to try with another duration, jump to the first step and change the length
(or --duration
) argument.
if you're happy with the tests (omit --test
):
qwavfade --length 3.5 live.in.concert.wav
qwavfade
doesn't allow both types of fades (in and out) to overlap. if you want to fade in and out a wav file, and the two regions to fade overlap, then probably you made a mistake (maybe you selected a too large fade). in any case, you'll have to fade separately.
[ Next:qwavinfo
| Previous:qwavfade
| Up:wav tools
]
qwavheaderdump
dumps (and fixes) wav headers
qwavheaderdump option ... file ...
qwavheaderdump
reads a list of wav files and prints on standard output all its header values in text (no binary) form. also, it has ability to fix some of the headers in case they'd be incorrect.
-F
--fix
correct the header if there's any incorrect value. not all the fields are recoverable.
-h
--help
show a brief help and exit.
-q
--quiet
no output messages. don't show detected (and corrected) errors.
-V
--version
show version and exit.
[ Next:qwavjoin
| Previous:qwavheaderdump
| Up:wav tools
]
qwavinfo
show info from wav files.
qwavinfo option ... file ...
qwavinfo
reads a list of wav files and prints on standard output some of its parameters: sample rate, bits per sample, mono/stereo and duration. a duration summary is appended at the end of the list.
-h
--help
show a brief help and exit.
-s
--summary-only
show only the summary. do not show info from every file.
-v
--verbose
show also the number of bytes and samples.
-V
--version
show version and exit.
[ Next:qwavsilence
| Previous:qwavinfo
| Up:wav tools
]
qwavjoin
joins wav files
qwavjoin option ... file1 file2 ...
qwavjoin
reads a list of wav files and joins them in the specified order in one wav file. the files must have the same parameters (i.e. sampling rate, bytes per sample, ... ) in order that the joining can be done.
-h
--help
show a brief help and exit.
-o outfile
--output=outfile
outfile is the name of the file where all the samples will be copied. if this option is not used, the samples from the second to the last file of the list will be appended to file1 .
-v
--verbose
show which operations are done.
-V
--version
show version and exit.
[ Next:mp3 tools
| Previous:qwavjoin
| Up:wav tools
]
qwavsilence
detects and shrinks silence sequences in wav files
qwavsilence option ... file ...
qwavsilence
reads a list of wav files looking for silence sequences longer than a given value, possibly shrinking them.
-d cutpoint
--duration=cutpoint
cutpoint (see cut points ) specifies the minimum duration of a silent sequence in a file to be reported. the default value is one second. this option overrides the option --length
explained below.
-h
--help
show a brief help and exit.
-l time
--length=time
time (see specifying time ) specifies the minimum length(=duration) of a silent sequence in a file to be reported. this option is quite similar to the --duration
option above. it's easier to use though not as powerful than the previous one. the default value is one second. this option overrides the --duration
option explained above.
-S
--shrink
when this option is set, all the silent sequences greater than the value of the --duration
option will be shrinked down to duration and the file size truncated accordingly.
-t threshold
--threshold=threshold
threshold is a percentage value respect the maximum (absolute) sample value. samples whose value is under the given threshold are considered silent. for example, a value of 2 means that all samples with absolute value under the 2% will be treated as silent samples. the default value is 0.
-v
--verbose
show also sample information.
-V
--version
show version and exit.
[ Next:qmp3check
| Previous:qwavsilence
| Up:Top
]
tests have been done only with mpeg version 1 layer iii streams, though it may (or not) work with other versions or layers.
the tools to handle mp3 files are the following:
qmp3check : : check and clean mp3 files.
qmp3cut : : extract and/or delete fragments from a mp3 file.
qmp3info : : show info from mp3 files.
qmp3join : : join multiple mp3 files in one.
qmp3report : : generate simple reports for mp3 files and directories
[ Next:qmp3cut
| Previous:mp3 tools
| Up:mp3 tools
]
qmp3check
checks and cleans mp3 streams
qmp3check option ... file ...
qmp3check
reads mp3 streams looking for invalid frames or, simply, garbage. it can be used as a mp3 file checker but also as a mp3 file cleaner because it is able to strip garbage bits from the streams.
-D
--delete
delete invalid frames and garbage. use with care
-h
--help
show a brief help and exit.
-q
--quiet
no output messages
-T
--delete-tag
delete tag (if exists). option --delete
must be set.
-v
--verbose
show more detailed info
-V
--version
show version and exit.
[ Next:qmp3info
| Previous:qmp3check
| Up:mp3 tools
]
qmp3cut
extracts and/or deletes parts of a mp3 file
qmp3cut option ... file
qmp3cut
allows to extract and/or delete a fragment of a mp3 file. some parameters must be supplied in order to define the start/size/end cut points and what to do then: either the fragment must be copied to another file or erased from the file (or both)
-d
--delete
deletes the fragment from the file. if option --output
is used, deletion is always done after fragment extraction.
-h
--help
show a brief help and exit.
-o outfile
--output=outfile
outfile is the name of the file where all the frames in the given fragment will be copied.
-v
--verbose
verbose
-V
--version
show version and exit.
cut options are used to specify where the fragment begins and ends. there are two ways to do it: with time slices (easier) and with cut points (more complex but also more powerful). cut options are mandatory (which way is used is matter of your choice).
if time slices are used, cut points options are automatically ignored.
there is only one option:
-S timeslice
--slice timeslice
timeslice (see specifying time ) specifies, in terms of time, where the cut begins and ends.
there are several options with cut points. cut points are used to specify at which frame the fragment begins (--begin
and --Begin
), ends (--end
and --End
), or which size it has (--size
). at least, one cut option must be specified (non specified options take its default values). neither the options --begin
and --Begin
, and the options --end
and --End
can be used together; also, a begin, end and size option cannot be used at the same time.
by default, the fragment begins at the first frame and ends at the last frame; there's no default value for size.
-b cutpoint
--set-begin-from-eof=cutpoint
cutpoint (see cut points ) specifies the first frame of the file that belongs to the cut counting from the end of the file.
-B cutpoint
--set-begin=cutpoint
cutpoint (see cut points ) specifies the first frame of the file that belongs to the cut counting from the beginning of the file.
-e cutpoint
--set-end-from-eof=cutpoint
cutpoint (see cut points ) specifies the last frame of the file that belongs to the cut counting from the end of the file.
-E cutpoint
--set-end=cutpoint
cutpoint (see cut points ) specifies the last frame of the file that belongs to the cut counting from the beginning of the file.
-s cutpoint
--size=cutpoint
cutpoint (see cut points ) specifies the number of frames contained in the cut.
to get the last ten seconds of a file
qmp3cut -b 10s -o outfile.mp3 infile.mp3
four different ways to get the first minute of a file:
qmp3cut -S -1:0 -o outfile.mp3 infile.mp3
qmp3cut -S -60 -o outfile.mp3 infile.mp3
qmp3cut -E 1m -o outfile.mp3 infile.mp3
qmp3cut -s 1m -o outfile.mp3 infile.mp3
four ways of getting the second quarter of a file:
qmp3cut -S 15:0-30:0 -o outfile.mp3 infile.mp3
qmp3cut -B 15m -E 30m -o outfile.mp3 infile.mp3
qmp3cut -s 15m -E 30m -o outfile.mp3 infile.mp3
qmp3cut -B 15m -s 15m -o outfile.mp3 infile.mp3
[ Next:qmp3join
| Previous:qmp3cut
| Up:mp3 tools
]
qmp3info
show info from mp3 files.
qmp3info option ... file ...
qmp3info
reads a list of mp3 files and prints on standard output some of its parameters: version, layer, sample rate, bit rate, duration and tag. a duration summary is appended at the end of the list.
-c
--check
check the entire stream (slower but accurate). all the frames of the stream are read and the total duration is exactly computed. this option is automatically activated if the stream appears to be vbr (have different bit rate frames).
-h
--help
show a brief help and exit.
-s
--summary-only
show only the summary. do not show info from every file.
-v
--verbose
show also the number of bytes and frames.
-V
--version
show version and exit.
variable bit rate (vbr) streams are detected by reading the initial 5 frames in the stream. if their bit rate field differs, the --check
option is activated automatically.
if vbr is not detected, qmp3info
reads only the first frame in the stream and calculates the duration supposing that (1) the entire stream is composed by valid frames and (2) all the frames have the same bit rate. this is a fast way to compute the duration of the stream, but it is not exact: there's an error of 0.3% aprox. if you want to be accurate, or qmp3info
is unable to detect a vbr stream, use --check
.
[ Next:qmp3report
| Previous:qmp3info
| Up:mp3 tools
]
qmp3join
joins mp3 files
qmp3join option ... file1 file2 ...
qmp3join
reads a list of mp3 files and joins them in one mp3 file in the specified order. some conditions must be met for the parameters of each of the files (see the notes subsection below).
-f
--force
force join bypassing bit rate checks. by default, to join two files they must be both vbr (have variable bit rate) or have the same bit rate. using this option you can skip this check.
-h
--help
show a brief help and exit.
-o outfile
--output=outfile
outfile is the name of the file where all the frames will be copied. if this option is not used, the frames from the second to the last file of the list will be appended to file1 .
-v
--verbose
show which operations are done.
-V
--version
show version and exit.
both mp3 must have the same bit rate or (both) must have a variable bit rate. this restriction can be by-passed with the --force
flag.
before joining, all the streams are tested for validity. this is a time consuming operation. if the streams are not found clean, the join operation is aborted, so if you want to join dirty streams or simply qmp3join detects a clean stream as dirty, please report this as a bug and/or use cat
.
due to the mp3 file format characteristics, qmp3join
can be viewed like a better but restrictive cat
for mp3 files.
[ Next:cut points
| Previous:qmp3join
| Up:mp3 tools
]
qmp3report
reports mp3 files and directories
qmp3report option ... file ...
qmp3report
reads mp3 files or directories containing mp3 files and gives information about them. qmp3report
can output the reports with plain text or in html format. using the latter format, you can navigate your mp3 directories with a web browser.
-a
--all-files
report all files, not just files with suffix .mp3
.
-A
--show-all
implies --dirs
, --files
and --summary
. show report for files and directories and a summary report.
-d
--dirs
show a report for every directory containing reported files/directories. note that if option --all-files
is not set, only will be reported those directories containing mp3 files.
-f
--files
show a report for every reportable file (see also --all-files
).
-h
--help
show a brief help and exit.
-H
--html
output in html format (default is plain text).
-r
--recursive
scan directories.
-s
--summary
show a summary report.
-S
--split
split report across visited directories. qmp3report
leaves in each visited directory a file with the report for that directory, independently of the output format. the name of the report file is the name of the directory with extension .txt
or .html
depending on the selected output format.
-v
--verbose
show more detailed info.
-V
--version
show version and exit.
variable bit rate (vbr) streams are detected by reading the initial 5 frames in the stream. if their bit rate field differs, the entire stream is read to compute the duration time with accuracy (see qmp3info ).
if vbr is not detected, qmp3report
reads only the first frame in the stream and calculates the duration supposing that (1) the entire stream is composed by valid frames and (2) all the frames have the same bit rate. this is a fast way to compute the duration of the stream, but it is not exact: there's an error of 0.3% aprox.
the htmlize function, which converts file names in a suitable form for html format (ie. replacing blanks with '%20 '), is not bulletproof.
[ Next:specifying time
| Previous:qmp3report
| Up:Top
]
cut points are used to specify point in a sound file. they can also be used to speciy a size or a time duration using the beginning of the file as start reference. a cut point has the following form:
value [format ]
in all cases, a positive integer value is required. the wav tools treat this number as a number of samples, whereas the mp3 tools treat this number as a number of frames. since most of the times is hard to specify a point (or size, or duration) in a file in terms of samples or frames, some modifiers are accepted. these modifiers consist in a single letter that must be written behind the number without leaving any blank.
these are the valid modifiers and how they modify the interpretation of value :
j
milliseconds
s
seconds
m
minutes
b
bytes
k
kbytes (1024 bytes)
M
megabytes (1024 kbytes)
in either case, the given values will be rounded to an integer number of samples/frames.
[ Previous:cut points
| Up:Top
]
time specifiers are a easier (more human ) way than cut options to specify points in a file.
a time specifier has the following form:
[[h :]m :]s [.ms ]
where:
h
hours
m
minutes
s
seconds
ms
milliseconds
as you can see, time specifiers are easier to use but less powerful than cut options (which can also specify a point in a file in terms of bytes or frames/samples).
time slices are composed by two time specifiers designing a range (slice) of time:
begin -end
where begin and end are time specifiers. they can be not specified, meaning, respectively, the beginning and the end of the file.