1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <pjmedia/wsola.h>
21 #include <pj/log.h>
22 #include <pj/pool.h>
23 #include <pj/os.h>
24 #include <stdio.h>
25 #include <assert.h>
26
27 #define CLOCK_RATE 16000
28 #define SAMPLES_PER_FRAME (10 * CLOCK_RATE / 1000)
29
30 #define RESET() memset(buf1, 0, sizeof(buf1)), \
31 memset(buf2, 0, sizeof(buf2)), \
32 memset(frm1, 0, sizeof(frm1)), \
33 memset(frm2, 0, sizeof(frm2))
34
35 #if 0
36 void test_find_pitch(void)
37 {
38 enum { ON = 111, FRM_PART_LEN=20 };
39 short buf2[SAMPLES_PER_FRAME*2], buf1[SAMPLES_PER_FRAME*2],
40 frm2[SAMPLES_PER_FRAME], frm1[SAMPLES_PER_FRAME];
41 short *ref, *pos;
42
43 /* Case 1. all contiguous */
44 RESET();
45 ref = buf1 + 10;
46 *ref = ON;
47 frm1[0] = ON;
48
49 pos = pjmedia_wsola_find_pitch(frm1, SAMPLES_PER_FRAME, NULL, 0,
50 buf1, SAMPLES_PER_FRAME*2, NULL, 0, PJ_TRUE);
51 assert(pos == ref);
52
53 /* Case 2: contiguous buffer, non-contiguous frame */
54 RESET();
55 ref = buf1 + 17;
56 *ref = ON;
57 *(ref+FRM_PART_LEN) = ON;
58 frm1[0] = ON;
59 frm2[0] = ON;
60
61 /* Noise */
62 buf1[0] = ON;
63
64 pos = pjmedia_wsola_find_pitch(frm1, FRM_PART_LEN, frm2, SAMPLES_PER_FRAME - FRM_PART_LEN,
65 buf1, SAMPLES_PER_FRAME*2, NULL, 0, PJ_TRUE);
66 assert(pos == ref);
67
68 /* Case 3: non-contiguous buffer, contiguous frame, found in buf1 */
69 RESET();
70 ref = buf1 + 17;
71 *ref = ON;
72 buf2[17] = ON;
73 frm1[0] = ON;
74 frm1[FRM_PART_LEN] = ON;
75
76 /* Noise */
77 buf1[0] = ON;
78
79 pos = pjmedia_wsola_find_pitch(frm1, SAMPLES_PER_FRAME, NULL, 0,
80 buf1, FRM_PART_LEN,
81 buf2, SAMPLES_PER_FRAME,
82 PJ_TRUE);
83
84 assert(pos == ref);
85 }
86 #endif
87
expand(pj_pool_t * pool,const char * filein,const char * fileout,int expansion_rate100,int lost_rate10,int lost_burst)88 int expand(pj_pool_t *pool, const char *filein, const char *fileout,
89 int expansion_rate100, int lost_rate10, int lost_burst)
90 {
91 enum { LOST_RATE = 10 };
92 FILE *in, *out;
93 short frame[SAMPLES_PER_FRAME];
94 pjmedia_wsola *wsola;
95 pj_timestamp elapsed, zero;
96 unsigned samples;
97 int last_lost = 0;
98
99 /* Lost burst must be > 0 */
100 assert(lost_rate10==0 || lost_burst > 0);
101
102 in = fopen(filein, "rb");
103 if (!in) return 1;
104 out = fopen(fileout, "wb");
105 if (!out) return 1;
106
107 pjmedia_wsola_create(pool, CLOCK_RATE, SAMPLES_PER_FRAME, 1, 0, &wsola);
108
109 samples = 0;
110 elapsed.u64 = 0;
111
112 while (fread(frame, SAMPLES_PER_FRAME*2, 1, in) == 1) {
113 pj_timestamp t1, t2;
114
115 if (lost_rate10 == 0) {
116
117 /* Expansion */
118 pj_get_timestamp(&t1);
119 pjmedia_wsola_save(wsola, frame, 0);
120 pj_get_timestamp(&t2);
121
122 pj_sub_timestamp(&t2, &t1);
123 pj_add_timestamp(&elapsed, &t2);
124
125 fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
126
127 samples += SAMPLES_PER_FRAME;
128
129 if ((rand() % 100) < expansion_rate100) {
130
131 pj_get_timestamp(&t1);
132 pjmedia_wsola_generate(wsola, frame);
133 pj_get_timestamp(&t2);
134
135 pj_sub_timestamp(&t2, &t1);
136 pj_add_timestamp(&elapsed, &t2);
137
138 samples += SAMPLES_PER_FRAME;
139
140 fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
141 }
142
143 } else {
144 /* Lost */
145
146 if ((rand() % 10) < lost_rate10) {
147 int burst;
148
149 for (burst=0; burst<lost_burst; ++burst) {
150 pj_get_timestamp(&t1);
151 pjmedia_wsola_generate(wsola, frame);
152 pj_get_timestamp(&t2);
153
154 pj_sub_timestamp(&t2, &t1);
155 pj_add_timestamp(&elapsed, &t2);
156
157 samples += SAMPLES_PER_FRAME;
158
159 fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
160 }
161 last_lost = 1;
162 } else {
163 pj_get_timestamp(&t1);
164 pjmedia_wsola_save(wsola, frame, last_lost);
165 pj_get_timestamp(&t2);
166
167 pj_sub_timestamp(&t2, &t1);
168 pj_add_timestamp(&elapsed, &t2);
169
170 samples += SAMPLES_PER_FRAME;
171
172 fwrite(frame, SAMPLES_PER_FRAME*2, 1, out);
173 last_lost = 0;
174 }
175
176 }
177
178 }
179
180 zero.u64 = 0;
181 zero.u64 = pj_elapsed_usec(&zero, &elapsed);
182
183 zero.u64 = samples * PJ_INT64(1000000) / zero.u64;
184 assert(zero.u32.hi == 0);
185
186 PJ_LOG(3,("test.c", "Processing: %f Msamples per second",
187 zero.u32.lo/1000000.0));
188 PJ_LOG(3,("test.c", "CPU load for current settings: %f%%",
189 CLOCK_RATE * 100.0 / zero.u32.lo));
190
191 pjmedia_wsola_destroy(wsola);
192 fclose(in);
193 fclose(out);
194
195 return 0;
196 }
197
save_file(const char * file,short frame[],unsigned count)198 static void save_file(const char *file,
199 short frame[], unsigned count)
200 {
201 FILE *f = fopen(file, "wb");
202 fwrite(frame, count, 2, f);
203 fclose(f);
204 }
205
compress(pj_pool_t * pool,const char * filein,const char * fileout,int rate10)206 int compress(pj_pool_t *pool,
207 const char *filein, const char *fileout,
208 int rate10)
209 {
210 enum { BUF_CNT = SAMPLES_PER_FRAME * 10 };
211 FILE *in, *out;
212 pjmedia_wsola *wsola;
213 short buf[BUF_CNT];
214 pj_timestamp elapsed, zero;
215 unsigned samples = 0;
216
217 in = fopen(filein, "rb");
218 if (!in) return 1;
219 out = fopen(fileout, "wb");
220 if (!out) return 1;
221
222 pjmedia_wsola_create(pool, CLOCK_RATE, SAMPLES_PER_FRAME, 1, 0, &wsola);
223
224 elapsed.u64 = 0;
225
226 for (;;) {
227 unsigned size_del, count;
228 pj_timestamp t1, t2;
229 int i;
230
231 if (fread(buf, sizeof(buf), 1, in) != 1)
232 break;
233
234 count = BUF_CNT;
235 size_del = 0;
236 pj_get_timestamp(&t1);
237
238 for (i=0; i<rate10; ++i) {
239 unsigned to_del = SAMPLES_PER_FRAME;
240 #if 0
241 /* Method 1: buf1 contiguous */
242 pjmedia_wsola_discard(wsola, buf, count, NULL, 0, &to_del);
243 #elif 0
244 /* Method 2: split, majority in buf1 */
245 assert(count > SAMPLES_PER_FRAME);
246 pjmedia_wsola_discard(wsola, buf, count-SAMPLES_PER_FRAME,
247 buf+count-SAMPLES_PER_FRAME, SAMPLES_PER_FRAME,
248 &to_del);
249 #elif 0
250 /* Method 3: split, majority in buf2 */
251 assert(count > SAMPLES_PER_FRAME);
252 pjmedia_wsola_discard(wsola, buf, SAMPLES_PER_FRAME,
253 buf+SAMPLES_PER_FRAME, count-SAMPLES_PER_FRAME,
254 &to_del);
255 #elif 1
256 /* Method 4: split, each with small length */
257 enum { TOT_LEN = 3 * SAMPLES_PER_FRAME };
258 unsigned buf1_len = (rand() % TOT_LEN);
259 short *ptr = buf + count - TOT_LEN;
260 assert(count > TOT_LEN);
261 if (buf1_len==0) buf1_len=SAMPLES_PER_FRAME*2;
262 pjmedia_wsola_discard(wsola, ptr, buf1_len,
263 ptr+buf1_len, TOT_LEN-buf1_len,
264 &to_del);
265 #endif
266 count -= to_del;
267 size_del += to_del;
268 }
269 pj_get_timestamp(&t2);
270
271 samples += BUF_CNT;
272
273 pj_sub_timestamp(&t2, &t1);
274 pj_add_timestamp(&elapsed, &t2);
275
276 assert(size_del >= SAMPLES_PER_FRAME);
277
278 fwrite(buf, count, 2, out);
279 }
280
281 pjmedia_wsola_destroy(wsola);
282 fclose(in);
283 fclose(out);
284
285 zero.u64 = 0;
286 zero.u64 = pj_elapsed_usec(&zero, &elapsed);
287
288 zero.u64 = samples * PJ_INT64(1000000) / zero.u64;
289 assert(zero.u32.hi == 0);
290
291 PJ_LOG(3,("test.c", "Processing: %f Msamples per second",
292 zero.u32.lo/1000000.0));
293 PJ_LOG(3,("test.c", "CPU load for current settings: %f%%",
294 CLOCK_RATE * 100.0 / zero.u32.lo));
295
296 return 0;
297 }
298
299
mem_test(pj_pool_t * pool)300 static void mem_test(pj_pool_t *pool)
301 {
302 char unused[1024];
303 short *frame = pj_pool_alloc(pool, 240+4*160);
304 pj_timestamp elapsed, zero, t1, t2;
305 unsigned samples = 0;
306
307 elapsed.u64 = 0;
308 while (samples < 50000000) {
309
310 pj_get_timestamp(&t1);
311 pjmedia_move_samples(frame, frame+160, 240+2*160);
312 pj_get_timestamp(&t2);
313 pj_sub_timestamp(&t2, &t1);
314
315 elapsed.u64 += t2.u64;
316
317 memset(unused, 0, sizeof(unused));
318 samples += 160;
319 }
320
321
322
323
324 zero.u64 = 0;
325 zero.u64 = pj_elapsed_usec(&zero, &elapsed);
326
327 zero.u64 = samples * PJ_INT64(1000000) / zero.u64;
328 assert(zero.u32.hi == 0);
329
330 PJ_LOG(3,("test.c", "Processing: %f Msamples per second",
331 zero.u32.lo/1000000.0));
332 PJ_LOG(3,("test.c", "CPU load for current settings: %f%%",
333 CLOCK_RATE * 100.0 / zero.u32.lo));
334
335 }
336
main()337 int main()
338 {
339 pj_caching_pool cp;
340 pj_pool_t *pool;
341 int i, rc;
342
343 //test_find_pitch();
344
345 pj_init();
346 pj_caching_pool_init(&cp, NULL, 0);
347 pool = pj_pool_create(&cp.factory, "", 1000, 1000, NULL);
348
349 srand(2);
350
351 rc = expand(pool, "galileo16.pcm", "temp1.pcm", 20, 0, 0);
352 rc = compress(pool, "temp1.pcm", "output.pcm", 1);
353
354 for (i=0; i<2; ++i) {
355 rc = expand(pool, "output.pcm", "temp1.pcm", 20, 0, 0);
356 rc = compress(pool, "temp1.pcm", "output.pcm", 1);
357 }
358
359 if (rc != 0) {
360 puts("Error");
361 return 1;
362 }
363
364 #if 0
365 {
366 char s[10];
367 puts("Press ENTER to quit");
368 fgets(s, sizeof(s), stdin);
369 }
370 #endif
371
372 return 0;
373 }
374