mirror of https://github.com/asterisk/asterisk
Add stereoize (bug #3142), faster than soxmix
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4859 65c4cc65-6c06-0410-ace0-fbb531ad65f31.2-netsec
parent
9fc931366e
commit
2184f91230
@ -1,3 +1,4 @@
|
||||
.depend
|
||||
astman
|
||||
smsq
|
||||
stereoize
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,300 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Programs for processing sound files in raw- or WAV-format.
|
||||
* -- Useful functions for parsing command line options and
|
||||
* issuing errors, warnings, and chit chat.
|
||||
*
|
||||
* Name: frame.h
|
||||
* Version: see frame.c
|
||||
* Author: Mark Roberts <mark@manumark.de>
|
||||
*
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* These are useful functions that all DSP programs might find handy
|
||||
****************************************************************************/
|
||||
|
||||
/* fileswitch for parseargs:
|
||||
|
||||
The following are masks for several different ways of opening files.
|
||||
--------------------------------------------------------------------
|
||||
Bit 0: Open infile?
|
||||
Bit 1: Open infile as binary (as opposed to text)
|
||||
Bit 2: Open outfile?
|
||||
Bit 3: Open outfile as binary (as opposed to text)
|
||||
Bit 4: Do not complain about too many file arguments
|
||||
Bit 5: Open one file for input AND output, binary.
|
||||
*/
|
||||
#define INTEXT (1+0)
|
||||
#define INBIN (1+2)
|
||||
#define OUTTEXT (4)
|
||||
#define OUTBIN (4+8)
|
||||
#define NOFILES (0)
|
||||
#define NOCOMPLAIN (16)
|
||||
#define IOBIN (32)
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0==1)
|
||||
#define TRUE (0==0)
|
||||
#endif
|
||||
|
||||
extern unsigned int samplefrequency;
|
||||
extern unsigned short samplewidth;
|
||||
extern unsigned short channels;
|
||||
extern int wavout; /* TRUE iff out file is .WAV file */
|
||||
extern int iswav; /* TRUE iff in file was found to be a .WAV file */
|
||||
extern FILE *in, *out;
|
||||
extern char *infilename, *outfilename;
|
||||
extern int verboselevel;
|
||||
extern char *version; /* String to be issued as version string. Should
|
||||
be set by application. */
|
||||
extern char *usage; /* String to be issued as usage string. Should be
|
||||
set by application. */
|
||||
|
||||
#define DEFAULTFREQ 44100
|
||||
#define BUFFSIZE 50000 /* How many samples to read in one go (preferred) */
|
||||
#define MINBUFFSIZE 5000 /* How many samples to read in one go (minimum) */
|
||||
|
||||
/*************************************************
|
||||
* Types of errors handled by argerrornum() *
|
||||
*************************************************/
|
||||
typedef enum
|
||||
{
|
||||
ME_NOINT,
|
||||
ME_NODOUBLE,
|
||||
ME_NOTIME,
|
||||
ME_NOVOL,
|
||||
ME_NOSWITCH,
|
||||
ME_TOOMANYFILES,
|
||||
ME_HEADERONTEXTFILE,
|
||||
ME_NOINFILE,
|
||||
ME_NOOUTFILE,
|
||||
ME_NOIOFILE,
|
||||
ME_NOSTDIN,
|
||||
ME_NOSTDOUT,
|
||||
ME_NOSTDIO,
|
||||
ME_NOTENOUGHFILES,
|
||||
ME_THISCANTHAPPEN
|
||||
} Errornum;
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Create memory and copy 'string', returning a pointer to the copy.
|
||||
NULL is returned if malloc fails.
|
||||
-----------------------------------------------------------------------*/
|
||||
extern char *malloccopy( char *string);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Start the stopwatch and make sure the user is informed at end of program.
|
||||
-----------------------------------------------------------------------*/
|
||||
extern void startstopwatch(void);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Writes the number of samples to result that are yet to be read from anyin.
|
||||
I.e. the number of remaining bytes is divided by the number of bytes per
|
||||
sample value, but not by the number of channels.
|
||||
Return values are TRUE on success, FALSE on failure.
|
||||
-----------------------------------------------------------------------*/
|
||||
extern int getremainingfilelength( FILE *anyin, long *result);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Read a .pk-header from 'anyin' and printf the entries.
|
||||
-----------------------------------------------------------------------*/
|
||||
void readpkheader( FILE *anyin);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Read a .WAV header from 'anyin'.
|
||||
If it is recognised, the data is used.
|
||||
Otherwise, we assume it's PCM-data and ignore the header.
|
||||
The global variable 'iswav' is set on success, otherwise cleared.
|
||||
-----------------------------------------------------------------------*/
|
||||
extern void readwavheader( FILE *anyin);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Write a .WAV header to 'out'.
|
||||
The filepointer is placed at the end of 'out' before operation.
|
||||
This should be called before any data is
|
||||
written, and again, when ALL the data has been written.
|
||||
First time, this positions the file pointer correctly; second time, the
|
||||
missing data can be inserted that wasn't known the first time round.
|
||||
-----------------------------------------------------------------------*/
|
||||
extern void makewavheader( void);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Tests the character 'coal' for being a command line option character,
|
||||
momentarrily '/' or '-'.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int isoptionchar (char coal);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for an option starting
|
||||
with 'string'. The rest of the option is read as a time and passed
|
||||
to *result, where the result is meant to mean 'number of samples' in
|
||||
that time.
|
||||
On failure, *result is unchanged.
|
||||
return value is TRUE on success, FALSE otherwise.
|
||||
-----------------------------------------------------------------------*/
|
||||
extern int parsetimearg( int argcount, char *args[], char *string,
|
||||
int *result);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
The string argument is read as a time and passed to *result, where
|
||||
the result is meant to mean 'number of samples' in that time. On
|
||||
failure, *result is unchanged.
|
||||
return value is TRUE on success, FALSE otherwise.
|
||||
-----------------------------------------------------------------------*/
|
||||
int parsetime(char *string, int *result);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
The string argument is read as a frequency and passed
|
||||
to *result, where the result is meant to mean 'number of samples' in
|
||||
one cycle of that frequency.
|
||||
On failure, *result is unchanged.
|
||||
return value is TRUE on success, FALSE otherwise.
|
||||
-----------------------------------------------------------------------*/
|
||||
int parsefreq(char *string, double *result);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for a switch -'string'.
|
||||
return value is TRUE if one exists, FALSE otherwise.
|
||||
If characters remain after the switch, a fatal error is issued.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int parseswitcharg( int argcount, char *args[], char *string);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for an option starting
|
||||
with 'string'. The rest of the option is read as an integer and
|
||||
passed to &result.
|
||||
On failure, &result is unchanged.
|
||||
return value is TRUE on success, FALSE otherwise.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int parseintarg( int argcount, char *args[], char *string,
|
||||
int *result);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for a filename, i.e. anything
|
||||
that does not start with the optionchar. The filename is copied to
|
||||
newly allocated memory, a pointer to which is returned.
|
||||
The argument is marked as used. Therefore repeated use of this function
|
||||
will yield a complete list of filenames on the commandline.
|
||||
If malloc() fails, the function does not return.
|
||||
-------------------------------------------------------------------- */
|
||||
extern char *parsefilearg( int argcount, char *args[]);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for an option starting
|
||||
with 'string'. The rest of the option is read as a double and
|
||||
passed to *result.
|
||||
On failure, *result is unchanged.
|
||||
return value is TRUE on success, FALSE otherwise.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int parsedoublearg( int argcount, char *args[], char *string,
|
||||
double *result);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for an option starting
|
||||
with 'string'. The rest of the option is read as a volume, i.e.
|
||||
absolute, percent or db. The result is passed to *result.
|
||||
On failure, *result is unchanged.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int parsevolarg( int argcount, char *args[], char *string,
|
||||
double *result);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads the specified string and interprets it as a volume. The string
|
||||
would be of the form 1.8 or 180% or 5db.
|
||||
On success, the return value is the relative volume, i.e. 1.8
|
||||
On failure, -1 is returned.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int parsevolume(char *s, double *result);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads through the arguments on the lookout for a switch -'string'.
|
||||
return value is TRUE if one exists, FALSE otherwise.
|
||||
If characters remain after the switch, a fatal error is issued.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int parseswitch( char *found, char *wanted);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reports an error due to parsing the string 's' encountered on the
|
||||
command line.
|
||||
-------------------------------------------------------------------- */
|
||||
extern void argerror(char *s);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reports an error due to parsing the string 's' encountered on the
|
||||
command line. 'code' indicates the type of error.
|
||||
-------------------------------------------------------------------- */
|
||||
extern void argerrornum(char *s, Errornum code);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reports an error due to parsing the string 's' encountered on the
|
||||
command line. 'message' explains the type of error.
|
||||
-------------------------------------------------------------------- */
|
||||
extern void argerrortxt(char *s, char *message);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Check for any remaining arguments and complain about their existence.
|
||||
If arguments are found, this function does not return.
|
||||
-------------------------------------------------------------------- */
|
||||
extern void checknoargs( int argcount, char *args[]);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Parses the command line arguments as represented by the function
|
||||
arguments. Sets the global variables 'in', 'out', 'samplefrequency'
|
||||
and 'samplewidth' accordingly.
|
||||
According to 'fileswitch', in and out files are opened or not. See
|
||||
above for an explanation of 'fileswitch'.
|
||||
-------------------------------------------------------------------- */
|
||||
extern void parseargs( int argcount, char *args[], int fileswitch);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Returns the index 'i' of the first argument that IS an option, and
|
||||
which begins with the label 's'. If there is none, -1.
|
||||
We also mark that option as done with, i.e. we cross it out.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int findoption( int argcount, char *args[], char *s);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Finishes off the .WAV header (if any) and exits correctly and formerly.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int myexit (int value);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Reads the stated input file bufferwise, calls the function 'work'
|
||||
with the proper values, and writes the result to the stated output file.
|
||||
Return value: TRUE on success, FALSE otherwise.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int workloop( FILE *theinfile, FILE *theoutfile,
|
||||
int (*work)( short *buffer, int length) );
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Five functions for printing to stderr. Depending on the level of verbose,
|
||||
output may be supressed. fatalerror() is like error() but does not return.
|
||||
fatalperror() is like the standard function perror() but does not return.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int chat( const char *format, ...);
|
||||
extern int inform( const char *format, ...);
|
||||
extern int error( const char *format, ...);
|
||||
extern void fatalerror( const char *format, ...);
|
||||
extern void fatalperror( const char *string);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
And one functions for printing to stdout.
|
||||
-------------------------------------------------------------------- */
|
||||
extern int say( const char *format, ...);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Allocate memory for it and return a pointer to a string made up of
|
||||
the two argument strings.
|
||||
-------------------------------------------------------------------- */
|
||||
extern char *mallocconcat( char *one, char *two);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Convert a sample value to decibel.
|
||||
-------------------------------------------------------------------- */
|
||||
extern double double2db( double value);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Read 'size' samples from file 'in' and lose them.
|
||||
-------------------------------------------------------------------- */
|
||||
extern void readawaysamples( FILE *in, size_t size);
|
@ -0,0 +1,159 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Programs for processing sound files in raw- or WAV-format.
|
||||
* -- Merge two mono WAV-files to one stereo WAV-file.
|
||||
*
|
||||
* Name: stereorize.c
|
||||
* Version: 1.1
|
||||
* Author: Mark Roberts <mark@manumark.de>
|
||||
* Michael Labuschke <michael@labuschke.de>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "frame.h"
|
||||
|
||||
static char *Version = "stereorize 1.1, November 5th 2000";
|
||||
static char *Usage =
|
||||
"Usage: stereorize [options] infile-left infile-right outfile\n\n"
|
||||
|
||||
"Example:\n"
|
||||
" stereorize left.wav right.wav stereo.wav -h\n\n"
|
||||
|
||||
"Creates stereo.wav (with WAV-header, option -h) from data in mono files\n"
|
||||
"left.wav and right.wav.\n"
|
||||
;
|
||||
|
||||
int main( int argcount, char *args[])
|
||||
{
|
||||
int i, k[2], maxk, stdin_in_use=FALSE;
|
||||
short *leftsample, *rightsample, *stereosample;
|
||||
FILE *channel[2];
|
||||
char *filename[2], *tempname;
|
||||
|
||||
version = Version;
|
||||
usage = Usage;
|
||||
|
||||
channel[0] = NULL;
|
||||
channel[1] = NULL;
|
||||
|
||||
parseargs( argcount, args, NOFILES | NOCOMPLAIN);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
filename[i] = parsefilearg( argcount, args);
|
||||
if (filename[i] == NULL)
|
||||
argerrornum( NULL, ME_NOTENOUGHFILES);
|
||||
if (strcmp (filename[i], "-") == 0)
|
||||
{
|
||||
if (stdin_in_use)
|
||||
argerrortxt( filename[i] + 1,
|
||||
"Cannot use <stdin> for both input files");
|
||||
filename[i] = "<stdin>";
|
||||
channel[i] = stdin;
|
||||
stdin_in_use = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
channel[i] = fopen(filename[i], "rb");
|
||||
}
|
||||
if (channel[i] == NULL)
|
||||
fatalerror( "Error opening input file '%s': %s\n", filename[i],strerror(errno));
|
||||
else
|
||||
inform("Using file '%s' as input\n", filename[i]);
|
||||
}
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
assert ( channel[i] != NULL);
|
||||
readwavheader( channel[i]);
|
||||
if (iswav && channels != 1)
|
||||
inform("Warning: '%s' is no mono file\n", filename[i]);
|
||||
}
|
||||
|
||||
outfilename = parsefilearg( argcount, args);
|
||||
if (outfilename == NULL) argerrornum( NULL, ME_NOOUTFILE);
|
||||
if (strcmp (outfilename, "-") == 0)
|
||||
{
|
||||
outfilename = "<stdout>";
|
||||
out = stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = fopen(outfilename, "wb");
|
||||
}
|
||||
if (out == NULL)
|
||||
fatalerror( "Error opening output file '%s': %s\n", outfilename,strerror(errno));
|
||||
else
|
||||
inform("Using file '%s' as output\n", outfilename);
|
||||
|
||||
if ((tempname = parsefilearg( argcount, args)) != NULL)
|
||||
argerrornum( tempname, ME_TOOMANYFILES);
|
||||
|
||||
checknoargs(argcount, args); /* Check that no arguments are left */
|
||||
|
||||
leftsample = malloc( sizeof(*leftsample) * BUFFSIZE);
|
||||
rightsample = malloc( sizeof(*leftsample) * BUFFSIZE);
|
||||
stereosample = malloc( sizeof(*leftsample) * 2 * BUFFSIZE);
|
||||
if (leftsample == NULL || rightsample == NULL || stereosample == NULL)
|
||||
fatalperror ("");
|
||||
|
||||
channels = 2; /* Output files are stereo */
|
||||
if (wavout)
|
||||
{
|
||||
if ((strcmp(outfilename,"<stdout>")!=0) && (fseek( out, 0, SEEK_SET) != 0))
|
||||
fatalerror("Couldn't navigate output file '%s': %s\n",outfilename, strerror(errno));
|
||||
makewavheader();
|
||||
}
|
||||
|
||||
startstopwatch();
|
||||
while (TRUE)
|
||||
{
|
||||
maxk = 0;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
k[i] = fread(i==0? leftsample : rightsample,
|
||||
sizeof(*leftsample),
|
||||
BUFFSIZE,
|
||||
channel[i]);
|
||||
if (k[i] == -1)
|
||||
fatalerror("Error reading file '%s': %s\n", filename[i],strerror(errno));
|
||||
if (k[i] > maxk)
|
||||
maxk = k[i];
|
||||
}
|
||||
if (maxk == 0)
|
||||
myexit (0);
|
||||
|
||||
/*-------------------------------------------------*
|
||||
* First the left channel as far as it goes ... *
|
||||
*-------------------------------------------------*/
|
||||
for (i = 0; i < k[0]; i++)
|
||||
stereosample[2 * i] = leftsample[i];
|
||||
/*-------------------------------------------------*
|
||||
* ... and fill up till the end of this buffer. *
|
||||
*-------------------------------------------------*/
|
||||
for (; i < maxk; i++)
|
||||
stereosample[2 * i] = 0;
|
||||
|
||||
/*-------------------------------------------------*
|
||||
* Next the right channel as far as it goes ... *
|
||||
*-------------------------------------------------*/
|
||||
for (i = 0; i < k[1]; i++)
|
||||
stereosample[2 * i + 1] = rightsample[i];
|
||||
/*-------------------------------------------------*
|
||||
* ... and fill up till the end of this buffer. *
|
||||
*-------------------------------------------------*/
|
||||
for (; i < maxk; i++)
|
||||
stereosample[2 * i + 1] = 0;
|
||||
|
||||
fwrite(stereosample, sizeof(*leftsample), 2 * maxk, out);
|
||||
if (ferror( out) != 0)
|
||||
fatalerror("Error writing to file '%s': %s\n",
|
||||
outfilename, strerror(errno));
|
||||
}
|
||||
/* That was an endless loop. This point is never reached. */
|
||||
}
|
Loading…
Reference in new issue