/********************************************************************** 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); }