Index: pjproject/trunk/pjmedia/src/test/wsola_test.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/wsola_test.c	(revision 1832)
+++ pjproject/trunk/pjmedia/src/test/wsola_test.c	(revision 1832)
@@ -0,0 +1,352 @@
+#include <pjmedia/wsola.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/os.h>
+#include <stdio.h>
+#include <assert.h>
+
+#define CLOCK_RATE	    44100
+#define SAMPLES_PER_FRAME   (10 * CLOCK_RATE / 1000)
+
+#define RESET()	    memset(buf1, 0, sizeof(buf1)), \
+		    memset(buf2, 0, sizeof(buf2)), \
+		    memset(frm1, 0, sizeof(frm1)), \
+		    memset(frm2, 0, sizeof(frm2))
+
+#if 0
+void test_find_pitch(void)
+{
+    enum { ON = 111, FRM_PART_LEN=20 };
+    short buf2[SAMPLES_PER_FRAME*2], buf1[SAMPLES_PER_FRAME*2],
+	  frm2[SAMPLES_PER_FRAME], frm1[SAMPLES_PER_FRAME];
+    short *ref, *pos;
+
+    /* Case 1. all contiguous */
+    RESET();
+    ref = buf1 + 10;
+    *ref = ON;
+    frm1[0] = ON;
+
+    pos = pjmedia_wsola_find_pitch(frm1, SAMPLES_PER_FRAME, NULL, 0,
+				   buf1, SAMPLES_PER_FRAME*2, NULL, 0, PJ_TRUE);
+    assert(pos == ref);
+
+    /* Case 2: contiguous buffer, non-contiguous frame */
+    RESET();
+    ref = buf1 + 17;
+    *ref = ON;
+    *(ref+FRM_PART_LEN) = ON;
+    frm1[0] = ON;
+    frm2[0] = ON;
+
+    /* Noise */
+    buf1[0] = ON;
+
+    pos = pjmedia_wsola_find_pitch(frm1, FRM_PART_LEN, frm2, SAMPLES_PER_FRAME - FRM_PART_LEN,
+				   buf1, SAMPLES_PER_FRAME*2, NULL, 0, PJ_TRUE);
+    assert(pos == ref);
+
+    /* Case 3: non-contiguous buffer, contiguous frame, found in buf1 */
+    RESET();
+    ref = buf1 + 17;
+    *ref = ON;
+    buf2[17] = ON;
+    frm1[0] = ON;
+    frm1[FRM_PART_LEN] = ON;
+
+    /* Noise */
+    buf1[0] = ON;
+
+    pos = pjmedia_wsola_find_pitch(frm1, SAMPLES_PER_FRAME, NULL, 0,
+				   buf1, FRM_PART_LEN,
+				   buf2, SAMPLES_PER_FRAME,
+				   PJ_TRUE);
+
+    assert(pos == ref);
+}
+#endif
+
+int expand(pj_pool_t *pool, const char *filein, const char *fileout,
+	   int expansion_rate100, int lost_rate10, int lost_burst)
+{
+    enum { LOST_RATE = 10 };
+    FILE *in, *out;
+    short frame[SAMPLES_PER_FRAME];
+    pjmedia_wsola *wsola;
+    pj_timestamp elapsed, zero;
+    unsigned samples;
+    int last_lost = 0;
+
+    /* Lost burst must be > 0 */
+    assert(lost_rate10==0 || lost_burst > 0);
+
+    in = fopen(filein, "rb");
+    if (!in) return 1;
+    out = fopen(fileout, "wb");
+    if (!out) return 1;
+
+    pjmedia_wsola_create(pool, CLOCK_RATE, SAMPLES_PER_FRAME, 0, &wsola);
+
+    samples = 0;
+    elapsed.u64 = 0;
+
+    while (fread(frame, SAMPLES_PER_FRAME*2, 1, in) == 1) {
+	pj_timestamp t1, t2;
+
+	if (lost_rate10 == 0) {
+
+	    /* Expansion */
+	    pj_get_timestamp(&t1);
+	    pjmedia_wsola_save(wsola, frame, 0);
+	    pj_get_timestamp(&t2);
+
+	    pj_sub_timestamp(&t2, &t1);
+	    pj_add_timestamp(&elapsed, &t2);
+
+	    fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
+
+	    samples += SAMPLES_PER_FRAME;
+
+	    if ((rand() % 100) < expansion_rate100) {
+
+		pj_get_timestamp(&t1);
+		pjmedia_wsola_generate(wsola, frame);
+		pj_get_timestamp(&t2);
+
+		pj_sub_timestamp(&t2, &t1);
+		pj_add_timestamp(&elapsed, &t2);
+    
+		samples += SAMPLES_PER_FRAME;
+
+		fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
+	    } 
+
+	} else {
+	    /* Lost */
+
+	    if ((rand() % 10) < lost_rate10) {
+		int burst;
+
+		for (burst=0; burst<lost_burst; ++burst) {
+		    pj_get_timestamp(&t1);
+		    pjmedia_wsola_generate(wsola, frame);
+		    pj_get_timestamp(&t2);
+
+		    pj_sub_timestamp(&t2, &t1);
+		    pj_add_timestamp(&elapsed, &t2);
+
+		    samples += SAMPLES_PER_FRAME;
+
+		    fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
+		}
+		last_lost = 1;
+	    } else {
+		pj_get_timestamp(&t1);
+		pjmedia_wsola_save(wsola, frame, last_lost);
+		pj_get_timestamp(&t2);
+
+		pj_sub_timestamp(&t2, &t1);
+		pj_add_timestamp(&elapsed, &t2);
+
+		samples += SAMPLES_PER_FRAME;
+
+		fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
+		last_lost = 0;
+	    }
+
+	}
+
+    }
+
+    zero.u64 = 0;
+    zero.u64 = pj_elapsed_usec(&zero, &elapsed);
+    
+    zero.u64 = samples * PJ_INT64(1000000) / zero.u64;
+    assert(zero.u32.hi == 0);
+
+    PJ_LOG(3,("test.c", "Processing: %f Msamples per second", 
+	      zero.u32.lo/1000000.0));
+    PJ_LOG(3,("test.c", "CPU load for current settings: %f%%",
+	      CLOCK_RATE * 100.0 / zero.u32.lo));
+
+    pjmedia_wsola_destroy(wsola);
+    fclose(in);
+    fclose(out);
+
+    return 0;
+}
+
+static void save_file(const char *file, 
+		      short frame[], unsigned count)
+{
+    FILE *f = fopen(file, "wb");
+    fwrite(frame, count, 2, f);
+    fclose(f);
+}
+
+int compress(pj_pool_t *pool, 
+	     const char *filein, const char *fileout, 
+	     int rate10)
+{
+    enum { BUF_CNT = SAMPLES_PER_FRAME * 10 };
+    FILE *in, *out;
+    pjmedia_wsola *wsola;
+    short buf[BUF_CNT];
+    pj_timestamp elapsed, zero;
+    unsigned samples = 0;
+    
+    in = fopen(filein, "rb");
+    if (!in) return 1;
+    out = fopen(fileout, "wb");
+    if (!out) return 1;
+
+    pjmedia_wsola_create(pool, CLOCK_RATE, SAMPLES_PER_FRAME, 0, &wsola);
+
+    elapsed.u64 = 0;
+
+    for (;;) {
+	unsigned size_del, count;
+	pj_timestamp t1, t2;
+	int i;
+
+	if (fread(buf, sizeof(buf), 1, in) != 1)
+	    break;
+
+	count = BUF_CNT;
+	size_del = 0;
+	pj_get_timestamp(&t1);
+
+	for (i=0; i<rate10; ++i) {
+	    unsigned to_del = SAMPLES_PER_FRAME;
+#if 0
+	    /* Method 1: buf1 contiguous */
+	    pjmedia_wsola_discard(wsola, buf, count, NULL, 0, &to_del);
+#elif 0
+	    /* Method 2: split, majority in buf1 */
+	    assert(count > SAMPLES_PER_FRAME);
+	    pjmedia_wsola_discard(wsola, buf, count-SAMPLES_PER_FRAME, 
+				  buf+count-SAMPLES_PER_FRAME, SAMPLES_PER_FRAME, 
+				  &to_del);
+#elif 0
+	    /* Method 3: split, majority in buf2 */
+	    assert(count > SAMPLES_PER_FRAME);
+	    pjmedia_wsola_discard(wsola, buf, SAMPLES_PER_FRAME, 
+				  buf+SAMPLES_PER_FRAME, count-SAMPLES_PER_FRAME, 
+				  &to_del);
+#elif 1
+	    /* Method 4: split, each with small length */
+	    enum { TOT_LEN = 3 * SAMPLES_PER_FRAME };
+	    unsigned buf1_len = (rand() % TOT_LEN);
+	    short *ptr = buf + count - TOT_LEN;
+	    assert(count > TOT_LEN);
+	    if (buf1_len==0) buf1_len=SAMPLES_PER_FRAME*2;
+	    pjmedia_wsola_discard(wsola, ptr, buf1_len, 
+				  ptr+buf1_len, TOT_LEN-buf1_len, 
+				  &to_del);
+#endif
+	    count -= to_del;
+	    size_del += to_del;
+	}
+	pj_get_timestamp(&t2);
+	
+	samples += BUF_CNT;
+
+	pj_sub_timestamp(&t2, &t1);
+	pj_add_timestamp(&elapsed, &t2);
+
+	assert(size_del >= SAMPLES_PER_FRAME);
+
+	fwrite(buf, count, 2, out);
+    }
+
+    pjmedia_wsola_destroy(wsola);
+    fclose(in);
+    fclose(out);
+
+    zero.u64 = 0;
+    zero.u64 = pj_elapsed_usec(&zero, &elapsed);
+    
+    zero.u64 = samples * PJ_INT64(1000000) / zero.u64;
+    assert(zero.u32.hi == 0);
+
+    PJ_LOG(3,("test.c", "Processing: %f Msamples per second", 
+	      zero.u32.lo/1000000.0));
+    PJ_LOG(3,("test.c", "CPU load for current settings: %f%%",
+	      CLOCK_RATE * 100.0 / zero.u32.lo));
+
+    return 0;
+}
+
+
+static void mem_test(pj_pool_t *pool)
+{
+    char unused[1024];
+    short   *frame = pj_pool_alloc(pool, 240+4*160);
+    pj_timestamp elapsed, zero, t1, t2;
+    unsigned samples = 0;
+
+    elapsed.u64 = 0;
+    while (samples < 50000000) {
+
+	pj_get_timestamp(&t1);
+	pjmedia_move_samples(frame, frame+160, 240+2*160);
+	pj_get_timestamp(&t2);
+	pj_sub_timestamp(&t2, &t1);
+
+	elapsed.u64 += t2.u64;
+
+	memset(unused, 0, sizeof(unused));
+	samples += 160;
+    }
+    
+
+    
+
+    zero.u64 = 0;
+    zero.u64 = pj_elapsed_usec(&zero, &elapsed);
+    
+    zero.u64 = samples * PJ_INT64(1000000) / zero.u64;
+    assert(zero.u32.hi == 0);
+
+    PJ_LOG(3,("test.c", "Processing: %f Msamples per second", 
+	      zero.u32.lo/1000000.0));
+    PJ_LOG(3,("test.c", "CPU load for current settings: %f%%",
+	      CLOCK_RATE * 100.0 / zero.u32.lo));
+
+}
+
+int main()
+{
+    pj_caching_pool cp;
+    pj_pool_t *pool;
+    int rc;
+
+    //test_find_pitch();
+
+    pj_init();
+    pj_caching_pool_init(&cp, NULL, 0);
+    pool = pj_pool_create(&cp.factory, "", 1000, 1000, NULL);
+
+    mem_test(pool);
+    return 0;
+
+    srand(2);
+
+    rc = expand(pool, "beet44.pcm", "output.pcm", 1, 0, 0);
+    //rc = compress(pool, "beet44.pcm", "output.pcm", 2);
+
+    if (rc != 0) {
+	puts("Error");
+	return 1;
+    }
+
+#if 0
+    {
+	char s[10];
+	puts("Press ENTER to quit");
+	fgets(s, sizeof(s), stdin);
+    }
+#endif
+
+    return 0;
+}
