diff options
Diffstat (limited to 'res/libresample/tests/resample-sndfile.c')
-rw-r--r-- | res/libresample/tests/resample-sndfile.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/res/libresample/tests/resample-sndfile.c b/res/libresample/tests/resample-sndfile.c new file mode 100644 index 000000000..e780228c1 --- /dev/null +++ b/res/libresample/tests/resample-sndfile.c @@ -0,0 +1,213 @@ +/********************************************************************** + + 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); +} |