int ConstRateResample::Process(double factor, float *inBuffer, int inBufferLen, bool lastFlag, int *inBufferUsed, float *outBuffer, int outBufferLen) { return resample_process(mHandle, factor, inBuffer, inBufferLen, (int)lastFlag, inBufferUsed, outBuffer, outBufferLen); }
static int resample_frame(struct ast_trans_pvt *pvt, void *resampler, float resample_factor, struct ast_frame *f) { int total_in_buf_used = 0; int total_out_buf_used = 0; int16_t *in_buf = (int16_t *) f->data; int16_t *out_buf = (int16_t *) pvt->outbuf + pvt->samples; float in_buf_f[f->samples]; float out_buf_f[2048]; int res = 0; int i; for (i = 0; i < f->samples; i++) in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX); while (total_in_buf_used < f->samples) { int in_buf_used, out_buf_used; out_buf_used = resample_process(resampler, resample_factor, &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used, 0, &in_buf_used, &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used); if (out_buf_used < 0) break; total_out_buf_used += out_buf_used; total_in_buf_used += in_buf_used; if (total_out_buf_used == ARRAY_LEN(out_buf_f)) { ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n"); res = -1; break; } } for (i = 0; i < total_out_buf_used; i++) out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX); pvt->samples += total_out_buf_used; pvt->datalen += (total_out_buf_used * sizeof(int16_t)); return res; }
void runtest(int srclen, double freq, double factor, int srcblocksize, int dstblocksize) { int expectedlen = (int)(srclen * factor); int dstlen = expectedlen + 1000; float *src = (float *)malloc((srclen+100) * sizeof(float)); float *dst = (float *)malloc((dstlen+100) * sizeof(float)); void *handle; double sum, sumsq, err, rmserr; int i, out, o, srcused, errcount, rangecount; int statlen, srcpos, lendiff; int fwidth; printf("-- srclen: %d sin freq: %.1f factor: %.3f srcblk: %d dstblk: %d\n", srclen, freq, factor, srcblocksize, dstblocksize); for(i=0; i<srclen; i++) src[i] = sin(i/freq); for(i=srclen; i<srclen+100; i++) src[i] = -99.0; for(i=0; i<dstlen+100; i++) dst[i] = -99.0; handle = resample_open(1, factor, factor); fwidth = resample_get_filter_width(handle); out = 0; srcpos = 0; for(;;) { int srcBlock = MIN(srclen-srcpos, srcblocksize); int lastFlag = (srcBlock == srclen-srcpos); o = resample_process(handle, factor, &src[srcpos], srcBlock, lastFlag, &srcused, &dst[out], MIN(dstlen-out, dstblocksize)); srcpos += srcused; if (o >= 0) out += o; if (o < 0 || (o == 0 && srcpos == srclen)) break; } resample_close(handle); if (o < 0) { printf("Error: resample_process returned an error: %d\n", o); } if (out <= 0) { printf("Error: resample_process returned %d samples\n", out); free(src); free(dst); return; } lendiff = abs(out - expectedlen); if (lendiff > (int)(2*factor + 1.0)) { printf(" Expected ~%d, got %d samples out\n", expectedlen, out); } sum = 0.0; sumsq = 0.0; errcount = 0.0; /* Don't compute statistics on all output values; the last few are guaranteed to be off because it's based on far less interpolation. */ statlen = out - fwidth; for(i=0; i<statlen; i++) { double diff = sin((i/freq)/factor) - dst[i]; if (fabs(diff) > 0.05) { if (errcount == 0) printf(" First error at i=%d: expected %.3f, got %.3f\n", i, sin((i/freq)/factor), dst[i]); errcount++; } sum += fabs(diff); sumsq += diff * diff; } rangecount = 0; for(i=0; i<statlen; i++) { if (dst[i] < -1.01 || dst[i] > 1.01) { if (rangecount == 0) printf(" Error at i=%d: value is %.3f\n", i, dst[i]); rangecount++; } } if (rangecount > 1) printf(" At least %d samples were out of range\n", rangecount); if (errcount > 0) { i = out - 1; printf(" i=%d: expected %.3f, got %.3f\n", i, sin((i/freq)/factor), dst[i]); printf(" At least %d samples had significant error.\n", errcount); } err = sum / statlen; rmserr = sqrt(sumsq / statlen); printf(" Out: %d samples Avg err: %f RMS err: %f\n", out, err, rmserr); free(src); free(dst); }
FOOIDAPI int fp_feed_float(t_fooid * fid, float *data, int len) { int pos; int c; float accum; int inpos; int res_out; int in_used; /* check input validity */ if (len % fid->channels != 0) { return -1; } len = len / fid->channels; /* cut the invalid data at start of music, only do once. */ // printf("[fp_feed_float] len = %d \n ", len); const float min_float = 1.0f / 32768.0f - EPSILON; if (!fid->soundfound) { pos = 0; //delete the zero part at the head of song's data. while (!fid->soundfound && pos < len) { for (c = 0; c < fid->channels; c++) { if (fabs(data[(pos * fid->channels) + c]) >= min_float ) { //if (fabs(data[(pos * fid->channels) + c]) >= (1.0f/32768.0f - EPSILON)) { fid->soundfound = TRUE; } } if (!fid->soundfound) { pos++; //the usable data start point store in poinger pos. } } /* end without sound? */ if (pos >= len && !fid->soundfound) { return TRUE; } /* adjust start */ len = len - pos; // printf(" [fp_feed_float] pos =%d, adjust len: %d\n",pos, len); data = data + (pos * fid->channels); //cut the data. } /* silly user feeding us more than we need? */ if (fid->outpos >= SSIZE) { return FALSE; //if 8000hz data (resample data) more than 100s, then return 0. } //printf("fp_feed_float] fid->outpos=%d\n", fid->outpos ); /* now we have music data queued up process it at most IN_LEN at a time */ do { /* read samples */ for (pos = 0; pos < len && pos < IN_LEN; pos++) { /* downmix sample */ // add 2 or more channels data, and avrage to a nono channel data // input to resample function. accum = 0; for (c = 0; c < fid->channels; c++) { accum += data[(pos * fid->channels) + c]; } accum /= (float)fid->channels; fid->sbuffer[pos] = accum; } inpos = 0; /* feed to resampler */ do { // return out sample count. res_out = resample_process(fid->resample_h, fid->resample_ratio, &(fid->sbuffer[inpos]), min(IN_LEN - inpos, len), FALSE, &in_used, &(fid->samples[fid->outpos]), SSIZE - fid->outpos); //fid->outpos is a pointer at the t_fooid's samples array. //fid->outpos dislay the calculate data is enough?(8000*10) fid->outpos += res_out; inpos += in_used; } while (in_used < min(IN_LEN, len) && fid->outpos < SSIZE); /* are we done yet? */ if (fid->outpos >= SSIZE) { return FALSE; } /* check if there's still input left */ len = len - in_used; data = data + (in_used * fid->channels); } while (len > 0); return TRUE; }
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++) 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); }