blob: a2770728f4540d9cdf1d2176ad394b7ad5b235b7 [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
38
39static const char *desc =
40" FILE \n"
41" \n"
42" aectest.c \n"
43" \n"
44" PURPOSE \n"
45" \n"
46" Test the AEC effectiveness. \n"
47" \n"
48" USAGE \n"
49" \n"
50" aectest INPUT.WAV OUTPUT.WAV \n"
51" \n"
52" INPUT.WAV is the file to be played to the speaker. \n"
53" OUTPUT.WAV is the output file containing recorded signal from the\n"
54" microphone.";
55
56
57static void app_perror(const char *sender, const char *title, pj_status_t st)
58{
59 char errmsg[PJ_ERR_MSG_SIZE];
60
61 pj_strerror(st, errmsg, sizeof(errmsg));
62 PJ_LOG(3,(sender, "%s: %s", title, errmsg));
63}
64
65
66/*
67 * main()
68 */
69int main(int argc, char *argv[])
70{
71 pj_caching_pool cp;
72 pjmedia_endpt *med_endpt;
73 pj_pool_t *pool;
74 pjmedia_port *play_port;
75 pjmedia_port *rec_port;
76 pjmedia_port *bidir_port;
77 pjmedia_snd_port *snd;
78 char tmp[10];
79 pj_status_t status;
80
81
82 if (argc != 3) {
83 puts("Error: arguments required");
84 puts(desc);
85 return 1;
86 }
87
88
89 /* Must init PJLIB first: */
90 status = pj_init();
91 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
92
93 /* Must create a pool factory before we can allocate any memory. */
94 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
95
96 /*
97 * Initialize media endpoint.
98 * This will implicitly initialize PJMEDIA too.
99 */
100 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
101 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
102
103 /* Create memory pool for our file player */
104 pool = pj_pool_create( &cp.factory, /* pool factory */
105 "wav", /* pool name. */
106 4000, /* init size */
107 4000, /* increment size */
108 NULL /* callback on error */
109 );
110
111 /* Create file media port from the WAV file */
112 status = pjmedia_wav_player_port_create( pool, /* memory pool */
113 argv[1], /* file to play */
114 PTIME, /* ptime. */
115 0, /* flags */
116 0, /* default buffer */
117 &play_port);
118 if (status != PJ_SUCCESS) {
119 app_perror(THIS_FILE, "Unable to open input WAV file", status);
120 return 1;
121 }
122
123 if (play_port->info.channel_count != 1) {
124 puts("Error: input WAV must have 1 channel audio");
125 return 1;
126 }
127 if (play_port->info.bits_per_sample != 16) {
128 puts("Error: input WAV must be encoded as 16bit PCM");
129 return 1;
130 }
131
132#ifdef PJ_DARWINOS
133 /* Need to force clock rate on MacOS */
134 if (play_port->info.clock_rate != 44100) {
135 pjmedia_port *resample_port;
136
137 status = pjmedia_resample_port_create(pool, play_port, 44100, 0,
138 &resample_port);
139 if (status != PJ_SUCCESS) {
140 app_perror(THIS_FILE, "Unable to create resampling port", status);
141 return 1;
142 }
143
144 data.play_port = resample_port;
145 }
146#endif
147
148 /* Create WAV output file port */
149 status = pjmedia_wav_writer_port_create(pool, argv[2],
150 play_port->info.clock_rate,
151 play_port->info.channel_count,
152 play_port->info.samples_per_frame,
153 play_port->info.bits_per_sample,
154 0, 0, &rec_port);
155 if (status != PJ_SUCCESS) {
156 app_perror(THIS_FILE, "Unable to open output file", status);
157 return 1;
158 }
159
160 /* Create bidirectional port from the WAV ports */
161 pjmedia_bidirectional_port_create(pool, play_port, rec_port, &bidir_port);
162
163 /* Create AEC port */
164 if (0) {
165 pjmedia_aec_port_create(pool, bidir_port,
166 bidir_port->info.clock_rate * 200 / 1000,
167 &bidir_port);
168 }
169
170 /* Create sound device. */
171 status = pjmedia_snd_port_create(pool, -1, -1,
172 play_port->info.clock_rate,
173 play_port->info.channel_count,
174 play_port->info.samples_per_frame,
175 play_port->info.bits_per_sample,
176 0, &snd);
177 if (status != PJ_SUCCESS) {
178 app_perror(THIS_FILE, "Unable to open sound device", status);
179 return 1;
180 }
181
182
183 /* Connect sound to the port */
184 pjmedia_snd_port_connect(snd, bidir_port);
185
186
187 puts("");
188 printf("Playing %s and recording to %s\n", argv[1], argv[2]);
189 puts("Press <ENTER> to quit");
190
191 fgets(tmp, sizeof(tmp), stdin);
192
193
194 /* Start deinitialization: */
195
196 /* Destroy sound device */
197 status = pjmedia_snd_port_destroy( snd );
198 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
199
200
201 /* Destroy file port(s) */
202 status = pjmedia_port_destroy( play_port );
203 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
204 status = pjmedia_port_destroy( rec_port );
205 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
206
207
208 /* Release application pool */
209 pj_pool_release( pool );
210
211 /* Destroy media endpoint. */
212 pjmedia_endpt_destroy( med_endpt );
213
214 /* Destroy pool factory */
215 pj_caching_pool_destroy( &cp );
216
217
218 /* Done. */
219 return 0;
220}
221