blob: 1258ff77ae6c84f9efe70f15b593c82ca6c60401 [file] [log] [blame]
#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);
srand(2);
rc = expand(pool, "beet44.pcm", "output.pcm", 0, 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;
}