|
HOME
SIP/media Features
High Performance SIP
Small Footprint SIP
Symbian Port
FAQ
Documentation
Licensing
Download
Development (Trac)
Projects using pjsip
Mailing List
Open Source Links
About: PJLIB, PJLIB-UTIL, PJSIP, and PJMEDIA are created by: Benny Prijono <bennylp pjsip.org>
|
|
Home --> Documentations --> PJMEDIA Reference
Play a file to speaker, run AEC, and record the microphone input to see if echo is coming.
This file is pjsip-apps/src/samples/aectest.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00031 #include <pjmedia.h>
00032 #include <pjlib-util.h>
00033 #include <pjlib.h>
00034
00035 #define THIS_FILE "aectest.c"
00036 #define PTIME 20
00037 #define TAIL_LENGTH 200
00038
00039 static const char *desc =
00040 " FILE \n"
00041 " \n"
00042 " aectest.c \n"
00043 " \n"
00044 " PURPOSE \n"
00045 " \n"
00046 " Test the AEC effectiveness. \n"
00047 " \n"
00048 " USAGE \n"
00049 " \n"
00050 " aectest [options] <PLAY.WAV> <REC.WAV> <OUTPUT.WAV> \n"
00051 " \n"
00052 " <PLAY.WAV> is the signal played to the speaker. \n"
00053 " <REC.WAV> is the signal captured from the microphone. \n"
00054 " <OUTPUT.WAV> is the output file to store the test result \n"
00055 "\n"
00056 " options:\n"
00057 " -d The delay between playback and capture in ms. Default is zero.\n"
00058 " -l Set the echo tail length in ms. Default is 200 ms \n"
00059 " -r Set repeat count (default=1) \n"
00060 " -a Algorithm: 0=default, 1=speex, 3=echo suppress \n"
00061 " -i Interactive \n";
00062
00063
00064
00065
00066
00067
00068
00069 static void app_perror(const char *sender, const char *title, pj_status_t st)
00070 {
00071 char errmsg[PJ_ERR_MSG_SIZE];
00072
00073 pj_strerror(st, errmsg, sizeof(errmsg));
00074 PJ_LOG(3,(sender, "%s: %s", title, errmsg));
00075 }
00076
00077
00078
00079
00080
00081 int main(int argc, char *argv[])
00082 {
00083 pj_caching_pool cp;
00084 pjmedia_endpt *med_endpt;
00085 pj_pool_t *pool;
00086 pjmedia_port *wav_play;
00087 pjmedia_port *wav_rec;
00088 pjmedia_port *wav_out;
00089 pj_status_t status;
00090 pjmedia_echo_state *ec;
00091 pjmedia_frame play_frame, rec_frame;
00092 unsigned opt = 0;
00093 unsigned latency_ms = 0;
00094 unsigned tail_ms = TAIL_LENGTH;
00095 pj_timestamp t0, t1;
00096 int i, repeat=1, interactive=0, c;
00097
00098 pj_optind = 0;
00099 while ((c=pj_getopt(argc, argv, "d:l:a:r:i")) !=-1) {
00100 switch (c) {
00101 case 'd':
00102 latency_ms = atoi(pj_optarg);
00103 break;
00104 case 'l':
00105 tail_ms = atoi(pj_optarg);
00106 break;
00107 case 'a':
00108 {
00109 int alg = atoi(pj_optarg);
00110 switch (alg) {
00111 case 0:
00112 opt = 0;
00113 case 1:
00114 opt = PJMEDIA_ECHO_SPEEX;
00115 break;
00116 case 3:
00117 opt = PJMEDIA_ECHO_SIMPLE;
00118 break;
00119 default:
00120 puts("Invalid algorithm");
00121 puts(desc);
00122 return 1;
00123 }
00124 }
00125 break;
00126 case 'r':
00127 repeat = atoi(pj_optarg);
00128 if (repeat < 1) {
00129 puts("Invalid algorithm");
00130 puts(desc);
00131 return 1;
00132 }
00133 break;
00134 case 'i':
00135 interactive = 1;
00136 break;
00137 }
00138 }
00139
00140 if (argc - pj_optind != 3) {
00141 puts("Error: missing argument(s)");
00142 puts(desc);
00143 return 1;
00144 }
00145
00146
00147 status = pj_init();
00148 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00149
00150
00151 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
00152
00153
00154
00155
00156
00157 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
00158 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00159
00160
00161 pool = pj_pool_create( &cp.factory,
00162 "wav",
00163 4000,
00164 4000,
00165 NULL
00166 );
00167
00168
00169 status = pjmedia_wav_player_port_create(pool, argv[pj_optind], PTIME,
00170 PJMEDIA_FILE_NO_LOOP, 0,
00171 &wav_play);
00172 if (status != PJ_SUCCESS) {
00173 app_perror(THIS_FILE, "Error opening playback WAV file", status);
00174 return 1;
00175 }
00176
00177
00178 status = pjmedia_wav_player_port_create(pool, argv[pj_optind+1], PTIME,
00179 PJMEDIA_FILE_NO_LOOP, 0,
00180 &wav_rec);
00181 if (status != PJ_SUCCESS) {
00182 app_perror(THIS_FILE, "Error opening recorded WAV file", status);
00183 return 1;
00184 }
00185
00186
00187 if (wav_play->info.clock_rate != wav_rec->info.clock_rate) {
00188 puts("Error: clock rate mismatch in the WAV files");
00189 return 1;
00190 }
00191
00192
00193 if (wav_play->info.channel_count != wav_rec->info.channel_count) {
00194 puts("Error: clock rate mismatch in the WAV files");
00195 return 1;
00196 }
00197
00198
00199 status = pjmedia_wav_writer_port_create(pool, argv[pj_optind+2],
00200 wav_play->info.clock_rate,
00201 wav_play->info.channel_count,
00202 wav_play->info.samples_per_frame,
00203 wav_play->info.bits_per_sample,
00204 0, 0, &wav_out);
00205 if (status != PJ_SUCCESS) {
00206 app_perror(THIS_FILE, "Error opening output WAV file", status);
00207 return 1;
00208 }
00209
00210
00211 status = pjmedia_echo_create2(pool, wav_play->info.clock_rate,
00212 wav_play->info.channel_count,
00213 wav_play->info.samples_per_frame,
00214 tail_ms, latency_ms,
00215 opt, &ec);
00216 if (status != PJ_SUCCESS) {
00217 app_perror(THIS_FILE, "Error creating EC", status);
00218 return 1;
00219 }
00220
00221
00222
00223 play_frame.buf = pj_pool_alloc(pool, wav_play->info.samples_per_frame<<1);
00224 rec_frame.buf = pj_pool_alloc(pool, wav_play->info.samples_per_frame<<1);
00225 pj_get_timestamp(&t0);
00226 for (i=0; i < repeat; ++i) {
00227 for (;;) {
00228 play_frame.size = wav_play->info.samples_per_frame << 1;
00229 status = pjmedia_port_get_frame(wav_play, &play_frame);
00230 if (status != PJ_SUCCESS)
00231 break;
00232
00233 status = pjmedia_echo_playback(ec, (short*)play_frame.buf);
00234
00235 rec_frame.size = wav_play->info.samples_per_frame << 1;
00236 status = pjmedia_port_get_frame(wav_rec, &rec_frame);
00237 if (status != PJ_SUCCESS)
00238 break;
00239
00240 status = pjmedia_echo_capture(ec, (short*)rec_frame.buf, 0);
00241
00242
00243
00244
00245 pjmedia_port_put_frame(wav_out, &rec_frame);
00246 }
00247
00248 pjmedia_wav_player_port_set_pos(wav_play, 0);
00249 pjmedia_wav_player_port_set_pos(wav_rec, 0);
00250 }
00251 pj_get_timestamp(&t1);
00252
00253 i = pjmedia_wav_writer_port_get_pos(wav_out) * 1000 /
00254 (wav_out->info.clock_rate * wav_out->info.channel_count);
00255 PJ_LOG(3,(THIS_FILE, "Processed %3d.%03ds audio",
00256 i / 1000, i % 1000));
00257 PJ_LOG(3,(THIS_FILE, "Completed in %u msec\n", pj_elapsed_msec(&t0, &t1)));
00258
00259
00260 status = pjmedia_port_destroy( wav_play );
00261 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00262 status = pjmedia_port_destroy( wav_rec );
00263 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00264 status = pjmedia_port_destroy( wav_out );
00265 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00266
00267
00268 pjmedia_echo_destroy(ec);
00269
00270
00271 pj_pool_release( pool );
00272
00273
00274 pjmedia_endpt_destroy( med_endpt );
00275
00276
00277 pj_caching_pool_destroy( &cp );
00278
00279
00280 pj_shutdown();
00281
00282 if (interactive) {
00283 char s[10];
00284 puts("ENTER to quit");
00285 fgets(s, sizeof(s), stdin);
00286 }
00287
00288
00289 return 0;
00290 }
00291
PJMEDIA small footprint Open Source media stack
(C)2003-2008 Benny Prijono
|
|