blob: 62b6761dad8fce540f3b5fef5dc366f770ff8a1a [file] [log] [blame]
Benny Prijonobc797312006-03-24 20:44:27 +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#include <pjmedia.h>
20#include <pjlib-util.h>
21#include <pjlib.h>
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include "util.h"
27
28/* For logging purpose. */
29#define THIS_FILE "resampleplay.c"
30
31
32static const char *desc =
33" FILE \n"
34" \n"
35" resampleplay.c \n"
36" \n"
37" PURPOSE \n"
38" \n"
39" Demonstrate how use resample port to play a WAV file to sound \n"
40" device using different sampling rate. \n"
41" \n"
42" USAGE \n"
43" \n"
44" resampleplay [options] FILE.WAV \n"
45" \n"
46" where options: \n"
47SND_USAGE
48" \n"
49" The WAV file could have mono or stereo channels with arbitrary \n"
50" sampling rate, but MUST contain uncompressed (i.e. 16bit) PCM. \n";
51
52
53int main(int argc, char *argv[])
54{
55 pj_caching_pool cp;
56 pjmedia_endpt *med_endpt;
57 pj_pool_t *pool;
58 pjmedia_port *file_port;
59 pjmedia_port *resample_port;
60 pjmedia_snd_port *snd_port;
61 char tmp[10];
62 pj_status_t status;
63
64 int dev_id = -1;
65 int sampling_rate = CLOCK_RATE;
66 int channel_count = NCHANNELS;
67 int samples_per_frame = NSAMPLES;
68 int bits_per_sample = NBITS;
69 //int ptime;
70 //int down_samples;
71
72 /* Must init PJLIB first: */
73 status = pj_init();
74 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
75
76
77 /* Get options */
78 if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &sampling_rate,
79 &channel_count, &samples_per_frame, &bits_per_sample))
80 {
81 puts("");
82 puts(desc);
83 return 1;
84 }
85
86 if (!argv[pj_optind]) {
87 puts("Error: no file is specified");
88 puts(desc);
89 return 1;
90 }
91
92 /* Must create a pool factory before we can allocate any memory. */
93 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
94
95 /*
96 * Initialize media endpoint.
97 * This will implicitly initialize PJMEDIA too.
98 */
99 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
100 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
101
102 /* Create memory pool for our file player */
103 pool = pj_pool_create( &cp.factory, /* pool factory */
104 "app", /* pool name. */
105 4000, /* init size */
106 4000, /* increment size */
107 NULL /* callback on error */
108 );
109
110 /* Create the file port. */
111 status = pjmedia_file_player_port_create( pool, argv[pj_optind], 0,
112 0, 0, &file_port);
113 if (status != PJ_SUCCESS) {
114 app_perror(THIS_FILE, "Unable to open file", status);
115 return 1;
116 }
117
118 /* File must have same number of channels. */
119 if (file_port->info.channel_count != (unsigned)channel_count) {
120 PJ_LOG(3,(THIS_FILE, "Error: file has different number of channels. "
121 "Perhaps you'd need -c option?"));
122 pjmedia_port_destroy(file_port);
123 return 1;
124 }
125
126 /* Calculate number of samples per frame to be taken from file port */
127 //ptime = samples_per_frame * 1000 / sampling_rate;
128
129 /* Create the resample port. */
130 status = pjmedia_resample_port_create( pool, 1, 1,
131 file_port->info.sample_rate,
132 sampling_rate,
133 channel_count,
134 (unsigned)(
135 samples_per_frame * 1.0 *
136 file_port->info.sample_rate /
137 sampling_rate),
138 &resample_port);
139 if (status != PJ_SUCCESS) {
140 app_perror(THIS_FILE, "Unable to create resample port", status);
141 return 1;
142 }
143
144 /* Connect resample port to file port */
145 status = pjmedia_port_connect( pool, resample_port, file_port);
146 if (status != PJ_SUCCESS) {
147 app_perror(THIS_FILE, "Error connecting ports", status);
148 return 1;
149 }
150
151 /* Create sound player port. */
152 status = pjmedia_snd_port_create(
153 pool, /* pool */
154 dev_id, /* device */
155 dev_id, /* device */
156 sampling_rate, /* clock rate. */
157 channel_count, /* # of channels. */
158 samples_per_frame, /* samples per frame. */
159 bits_per_sample, /* bits per sample. */
160 0, /* options */
161 &snd_port /* returned port */
162 );
163 if (status != PJ_SUCCESS) {
164 app_perror(THIS_FILE, "Unable to open sound device", status);
165 return 1;
166 }
167
168 /* Connect resample port to sound device */
169 status = pjmedia_snd_port_connect( snd_port, resample_port);
170 if (status != PJ_SUCCESS) {
171 app_perror(THIS_FILE, "Error connecting sound ports", status);
172 return 1;
173 }
174
175
176 /* Dump memory usage */
177 dump_pool_usage(THIS_FILE, &cp);
178
179 /*
180 * File should be playing and looping now, using sound device's thread.
181 */
182
183
184 /* Sleep to allow log messages to flush */
185 pj_thread_sleep(100);
186
187
188 printf("Playing %s at sampling rate %d (original file sampling rate=%d)\n",
189 argv[pj_optind], sampling_rate, file_port->info.sample_rate);
190 puts("");
191 puts("Press <ENTER> to stop playing and quit");
192
193 fgets(tmp, sizeof(tmp), stdin);
194
195
196 /* Start deinitialization: */
197
198
199 /* Destroy sound device */
200 status = pjmedia_snd_port_destroy( snd_port );
201 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
202
203
204 /* Destroy resample port.
205 * This will destroy all downstream ports (e.g. the file port)
206 */
207 status = pjmedia_port_destroy( resample_port );
208 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
209
210
211 /* Release application pool */
212 pj_pool_release( pool );
213
214 /* Destroy media endpoint. */
215 pjmedia_endpt_destroy( med_endpt );
216
217 /* Destroy pool factory */
218 pj_caching_pool_destroy( &cp );
219
220
221 /* Done. */
222 return 0;
223
224}
225
226
227