forked from Mirrors/freeswitch
32fce49ba3
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2880 d0543943-73ff-0310-b7d9-9358b9ac24b2
214 lines
5.4 KiB
C
214 lines
5.4 KiB
C
/**********************************************************************
|
|
|
|
resample-sndfile.c
|
|
|
|
Written by Dominic Mazzoni
|
|
|
|
Based on resample-1.7:
|
|
http://www-ccrma.stanford.edu/~jos/resample/
|
|
|
|
License: LGPL - see the file LICENSE.txt for more information
|
|
|
|
**********************************************************************/
|
|
|
|
#include "../include/libresample.h"
|
|
|
|
#include <sndfile.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#define MIN(A, B) (A) < (B)? (A) : (B)
|
|
|
|
void usage(char *progname)
|
|
{
|
|
fprintf(stderr, "Usage: %s -by <ratio> <input> <output>\n", progname);
|
|
fprintf(stderr, " %s -to <rate> <input> <output>\n", progname);
|
|
fprintf(stderr, "\n");
|
|
exit(-1);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
SNDFILE *srcfile, *dstfile;
|
|
SF_INFO srcinfo, dstinfo;
|
|
SF_FORMAT_INFO formatinfo;
|
|
char *extension;
|
|
void **handle;
|
|
int channels;
|
|
int srclen, dstlen;
|
|
float *src, *srci;
|
|
float *dst, *dsti;
|
|
double ratio = 0.0;
|
|
double srcrate;
|
|
double dstrate = 0.0;
|
|
struct timeval tv0, tv1;
|
|
double deltat;
|
|
int numformats;
|
|
int pos, bufferpos, outcount;
|
|
int i, c;
|
|
|
|
if (argc != 5)
|
|
usage(argv[0]);
|
|
|
|
if (!strcmp(argv[1], "-by")) {
|
|
ratio = atof(argv[2]);
|
|
if (ratio <= 0.0) {
|
|
fprintf(stderr, "Ratio of %f is illegal\n", ratio);
|
|
usage(argv[0]);
|
|
}
|
|
}
|
|
else if (!strcmp(argv[1], "-to")) {
|
|
dstrate = atof(argv[2]);
|
|
if (dstrate < 10.0 || dstrate > 100000.0) {
|
|
fprintf(stderr, "Sample rate of %f is illegal\n", dstrate);
|
|
usage(argv[0]);
|
|
}
|
|
}
|
|
else
|
|
usage(argv[0]);
|
|
|
|
memset(&srcinfo, 0, sizeof(srcinfo));
|
|
memset(&dstinfo, 0, sizeof(dstinfo));
|
|
srcfile = sf_open(argv[3], SFM_READ, &srcinfo);
|
|
if (!srcfile) {
|
|
fprintf(stderr, "%s", sf_strerror(NULL));
|
|
exit(-1);
|
|
}
|
|
|
|
srcrate = srcinfo.samplerate;
|
|
if (dstrate == 0.0)
|
|
dstrate = srcrate * ratio;
|
|
else
|
|
ratio = dstrate / srcrate;
|
|
|
|
channels = srcinfo.channels;
|
|
|
|
/* figure out format of destination file */
|
|
|
|
extension = strstr(argv[4], ".");
|
|
if (extension) {
|
|
extension++;
|
|
sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT,
|
|
&numformats, sizeof(numformats));
|
|
for(i=0; i<numformats; i++) {
|
|
memset(&formatinfo, 0, sizeof(formatinfo));
|
|
formatinfo.format = i;
|
|
sf_command(NULL, SFC_GET_FORMAT_MAJOR,
|
|
&formatinfo, sizeof(formatinfo));
|
|
if (!strcmp(formatinfo.extension, extension)) {
|
|
printf("Using %s for output format.\n", formatinfo.name);
|
|
dstinfo.format = formatinfo.format |
|
|
(srcinfo.format & SF_FORMAT_SUBMASK);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!dstinfo.format) {
|
|
if (extension)
|
|
printf("Warning: output format (%s) not recognized, "
|
|
"using same as input format.\n",
|
|
extension);
|
|
dstinfo.format = srcinfo.format;
|
|
}
|
|
|
|
dstinfo.samplerate = (int)(dstrate + 0.5);
|
|
dstinfo.channels = channels;
|
|
|
|
dstfile = sf_open(argv[4], SFM_WRITE, &dstinfo);
|
|
if (!dstfile) {
|
|
fprintf(stderr, "%s", sf_strerror(NULL));
|
|
exit(-1);
|
|
}
|
|
|
|
printf("Source: %s (%d frames, %.2f Hz)\n",
|
|
argv[3], (int)srcinfo.frames, srcrate);
|
|
printf("Destination: %s (%.2f Hz, ratio=%.5f)\n", argv[4],
|
|
dstrate, ratio);
|
|
|
|
srclen = 4096;
|
|
dstlen = (srclen * ratio + 1000);
|
|
srci = (float *)malloc(srclen * channels * sizeof(float));
|
|
dsti = (float *)malloc(dstlen * channels * sizeof(float));
|
|
src = (float *)malloc(srclen * sizeof(float));
|
|
dst = (float *)malloc(dstlen * sizeof(float));
|
|
|
|
handle = (void **)malloc(channels * sizeof(void *));
|
|
for(c=0; c<channels; c++)
|
|
handle[c] = resample_open(1, ratio, ratio);
|
|
|
|
gettimeofday(&tv0, NULL);
|
|
|
|
pos = 0;
|
|
bufferpos = 0;
|
|
outcount = 0;
|
|
while(pos < srcinfo.frames) {
|
|
int block = MIN(srclen-bufferpos, srcinfo.frames-pos);
|
|
int lastFlag = (pos+block == srcinfo.frames);
|
|
int inUsed, inUsed2=0, out=0, out2=0;
|
|
|
|
sf_readf_float(srcfile, &srci[bufferpos*channels], block);
|
|
block += bufferpos;
|
|
|
|
for(c=0; c<channels; c++) {
|
|
for(i=0; i<block; i++)
|
|
src[i] = srci[i*channels+c];
|
|
|
|
inUsed = 0;
|
|
out = resample_process(handle[c], ratio, src, block, lastFlag,
|
|
&inUsed, dst, dstlen);
|
|
if (c==0) {
|
|
inUsed2 = inUsed;
|
|
out2 = out;
|
|
}
|
|
else {
|
|
if (inUsed2 != inUsed || out2 != out) {
|
|
fprintf(stderr, "Fatal error: channels out of sync!\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
for(i=0; i<out; i++)
|
|
{
|
|
if(dst[i] <= -1)
|
|
dsti[i*channels+c] = -1;
|
|
else if(dst[i] >= 1)
|
|
dsti[i*channels+c] = 1;
|
|
else
|
|
dsti[i*channels+c] = dst[i];
|
|
}
|
|
}
|
|
|
|
sf_writef_float(dstfile, dsti, out);
|
|
|
|
bufferpos = block - inUsed;
|
|
for(i=0; i<bufferpos*channels; i++)
|
|
srci[i] = srci[i+(inUsed*channels)];
|
|
pos += inUsed;
|
|
outcount += out;
|
|
}
|
|
|
|
sf_close(srcfile);
|
|
sf_close(dstfile);
|
|
|
|
gettimeofday(&tv1, NULL);
|
|
deltat =
|
|
(tv1.tv_sec + tv1.tv_usec * 0.000001) -
|
|
(tv0.tv_sec + tv0.tv_usec * 0.000001);
|
|
|
|
printf("Elapsed time: %.3f seconds\n", deltat);
|
|
printf("%d frames written to output file\n", outcount);
|
|
|
|
free(src);
|
|
free(srci);
|
|
free(dst);
|
|
free(dsti);
|
|
|
|
exit(0);
|
|
}
|