blob: 286abcbf1e81617c24fc1f5baebd82c64d5a9c72 [file] [log] [blame]
Benny Prijono69f73122006-08-04 11:08:00 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21/**
22 * \page page_pjmedia_samples_aectest_c Samples: AEC Test (aectest.c)
23 *
24 * Play a file to speaker, run AEC, and record the microphone input
25 * to see if echo is coming.
26 *
27 * This file is pjsip-apps/src/samples/aectest.c
28 *
29 * \includelineno aectest.c
30 */
31#include <pjmedia.h>
32#include <pjlib-util.h> /* pj_getopt */
33#include <pjlib.h>
34
35/* For logging purpose. */
36#define THIS_FILE "playfile.c"
37#define PTIME 20
Benny Prijono12a669c2006-11-23 07:32:13 +000038#define TAIL_LENGTH 800
Benny Prijono69f73122006-08-04 11:08:00 +000039
40static const char *desc =
41" FILE \n"
42" \n"
43" aectest.c \n"
44" \n"
45" PURPOSE \n"
46" \n"
47" Test the AEC effectiveness. \n"
48" \n"
49" USAGE \n"
50" \n"
51" aectest INPUT.WAV OUTPUT.WAV \n"
52" \n"
53" INPUT.WAV is the file to be played to the speaker. \n"
54" OUTPUT.WAV is the output file containing recorded signal from the\n"
55" microphone.";
56
57
58static void app_perror(const char *sender, const char *title, pj_status_t st)
59{
60 char errmsg[PJ_ERR_MSG_SIZE];
61
62 pj_strerror(st, errmsg, sizeof(errmsg));
63 PJ_LOG(3,(sender, "%s: %s", title, errmsg));
64}
65
66
67/*
68 * main()
69 */
70int main(int argc, char *argv[])
71{
72 pj_caching_pool cp;
73 pjmedia_endpt *med_endpt;
74 pj_pool_t *pool;
75 pjmedia_port *play_port;
76 pjmedia_port *rec_port;
77 pjmedia_port *bidir_port;
78 pjmedia_snd_port *snd;
79 char tmp[10];
80 pj_status_t status;
81
82
83 if (argc != 3) {
84 puts("Error: arguments required");
85 puts(desc);
86 return 1;
87 }
88
89
90 /* Must init PJLIB first: */
91 status = pj_init();
92 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
93
94 /* Must create a pool factory before we can allocate any memory. */
95 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
96
97 /*
98 * Initialize media endpoint.
99 * This will implicitly initialize PJMEDIA too.
100 */
101 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
102 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
103
104 /* Create memory pool for our file player */
105 pool = pj_pool_create( &cp.factory, /* pool factory */
106 "wav", /* pool name. */
107 4000, /* init size */
108 4000, /* increment size */
109 NULL /* callback on error */
110 );
111
112 /* Create file media port from the WAV file */
113 status = pjmedia_wav_player_port_create( pool, /* memory pool */
114 argv[1], /* file to play */
115 PTIME, /* ptime. */
116 0, /* flags */
117 0, /* default buffer */
118 &play_port);
119 if (status != PJ_SUCCESS) {
120 app_perror(THIS_FILE, "Unable to open input WAV file", status);
121 return 1;
122 }
123
124 if (play_port->info.channel_count != 1) {
125 puts("Error: input WAV must have 1 channel audio");
126 return 1;
127 }
128 if (play_port->info.bits_per_sample != 16) {
129 puts("Error: input WAV must be encoded as 16bit PCM");
130 return 1;
131 }
132
133#ifdef PJ_DARWINOS
134 /* Need to force clock rate on MacOS */
135 if (play_port->info.clock_rate != 44100) {
136 pjmedia_port *resample_port;
137
138 status = pjmedia_resample_port_create(pool, play_port, 44100, 0,
139 &resample_port);
140 if (status != PJ_SUCCESS) {
141 app_perror(THIS_FILE, "Unable to create resampling port", status);
142 return 1;
143 }
144
145 data.play_port = resample_port;
146 }
147#endif
148
149 /* Create WAV output file port */
150 status = pjmedia_wav_writer_port_create(pool, argv[2],
151 play_port->info.clock_rate,
152 play_port->info.channel_count,
153 play_port->info.samples_per_frame,
154 play_port->info.bits_per_sample,
155 0, 0, &rec_port);
156 if (status != PJ_SUCCESS) {
157 app_perror(THIS_FILE, "Unable to open output file", status);
158 return 1;
159 }
160
161 /* Create bidirectional port from the WAV ports */
162 pjmedia_bidirectional_port_create(pool, play_port, rec_port, &bidir_port);
163
Benny Prijono69f73122006-08-04 11:08:00 +0000164 /* Create sound device. */
165 status = pjmedia_snd_port_create(pool, -1, -1,
166 play_port->info.clock_rate,
167 play_port->info.channel_count,
168 play_port->info.samples_per_frame,
169 play_port->info.bits_per_sample,
170 0, &snd);
171 if (status != PJ_SUCCESS) {
172 app_perror(THIS_FILE, "Unable to open sound device", status);
173 return 1;
174 }
175
176
Benny Prijonof20687a2006-08-04 18:27:19 +0000177 /* Customize AEC */
Benny Prijono12a669c2006-11-23 07:32:13 +0000178 pjmedia_snd_port_set_ec(snd, pool, TAIL_LENGTH, 0);
Benny Prijonof20687a2006-08-04 18:27:19 +0000179
Benny Prijono69f73122006-08-04 11:08:00 +0000180 /* Connect sound to the port */
181 pjmedia_snd_port_connect(snd, bidir_port);
182
183
184 puts("");
185 printf("Playing %s and recording to %s\n", argv[1], argv[2]);
186 puts("Press <ENTER> to quit");
187
188 fgets(tmp, sizeof(tmp), stdin);
189
190
191 /* Start deinitialization: */
192
193 /* Destroy sound device */
194 status = pjmedia_snd_port_destroy( snd );
195 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
196
197
198 /* Destroy file port(s) */
199 status = pjmedia_port_destroy( play_port );
200 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
201 status = pjmedia_port_destroy( rec_port );
202 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
203
204
205 /* Release application pool */
206 pj_pool_release( pool );
207
208 /* Destroy media endpoint. */
209 pjmedia_endpt_destroy( med_endpt );
210
211 /* Destroy pool factory */
212 pj_caching_pool_destroy( &cp );
213
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +0000214 /* Shutdown PJLIB */
215 pj_shutdown();
Benny Prijono69f73122006-08-04 11:08:00 +0000216
217 /* Done. */
218 return 0;
219}
220