~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjsip-apps/src/samples/playsine.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: playsine.c 3664 2011-07-19 03:42:28Z nanang $ */
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
 
 
21
 
 
22
 
/**
23
 
 * \page page_pjmedia_samples_playsine_c Samples: Using Custom Ports (Sine Wave Generator)
24
 
 *
25
 
 * This example demonstrate how to create a custom media port (in this case, a
26
 
 * sine wave generator) and connect it to the sound device.
27
 
 *
28
 
 * This file is pjsip-apps/src/samples/playsine.c
29
 
 *
30
 
 * \includelineno playsine.c
31
 
 */
32
 
 
33
 
/*
34
 
 * playsine.c
35
 
 *
36
 
 * PURPOSE:
37
 
 *  Demonstrate how to create and use custom media port which
38
 
 *  simply feed a sine wav to the sound player.
39
 
 *
40
 
 * USAGE:
41
 
 *  playsine [nchannel]
42
 
 *
43
 
 * where:
44
 
 *  nchannel is 1 for mono (this is the default) or 2 for stereo.
45
 
 */
46
 
 
47
 
#include <pjmedia.h>
48
 
#include <pjlib.h>
49
 
 
50
 
#include <stdlib.h>     /* atoi() */
51
 
#include <stdio.h>
52
 
#include <math.h>       /* sin()  */
53
 
 
54
 
/* For logging purpose. */
55
 
#define THIS_FILE   "playsine.c"
56
 
 
57
 
 
58
 
/* Util to display the error message for the specified error code  */
59
 
static int app_perror( const char *sender, const char *title,
60
 
                       pj_status_t status)
61
 
{
62
 
    char errmsg[PJ_ERR_MSG_SIZE];
63
 
 
64
 
    PJ_UNUSED_ARG(sender);
65
 
 
66
 
    pj_strerror(status, errmsg, sizeof(errmsg));
67
 
 
68
 
    printf("%s: %s [code=%d]\n", title, errmsg, status);
69
 
    return 1;
70
 
}
71
 
 
72
 
 
73
 
/* Struct attached to sine generator */
74
 
typedef struct
75
 
{
76
 
    pj_int16_t  *samples;       /* Sine samples.    */
77
 
} port_data;
78
 
 
79
 
 
80
 
/* This callback is called to feed more samples */
81
 
static pj_status_t sine_get_frame( pjmedia_port *port,
82
 
                                   pjmedia_frame *frame)
83
 
{
84
 
    port_data *sine = port->port_data.pdata;
85
 
    pj_int16_t *samples = frame->buf;
86
 
    unsigned i, count, left, right;
87
 
 
88
 
    /* Get number of samples */
89
 
    count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info);
90
 
 
91
 
    left = 0;
92
 
    right = 0;
93
 
 
94
 
    for (i=0; i<count; ++i) {
95
 
        *samples++ = sine->samples[left];
96
 
        ++left;
97
 
 
98
 
        if (PJMEDIA_PIA_CCNT(&port->info) == 2) {
99
 
            *samples++ = sine->samples[right];
100
 
            right += 2; /* higher pitch so we can distinguish left and right. */
101
 
            if (right >= count)
102
 
                right = 0;
103
 
        }
104
 
    }
105
 
 
106
 
    /* Must set frame->type correctly, otherwise the sound device
107
 
     * will refuse to play.
108
 
     */
109
 
    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
110
 
 
111
 
    return PJ_SUCCESS;
112
 
}
113
 
 
114
 
#ifndef M_PI
115
 
#define M_PI  (3.14159265)
116
 
#endif
117
 
 
118
 
/*
119
 
 * Create a media port to generate sine wave samples.
120
 
 */
121
 
static pj_status_t create_sine_port(pj_pool_t *pool,
122
 
                                    unsigned sampling_rate,
123
 
                                    unsigned channel_count,
124
 
                                    pjmedia_port **p_port)
125
 
{
126
 
    pjmedia_port *port;
127
 
    unsigned i;
128
 
    unsigned count;
129
 
    pj_str_t name;
130
 
    port_data *sine;
131
 
 
132
 
    PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2,
133
 
                     PJ_EINVAL);
134
 
 
135
 
    port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
136
 
    PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);
137
 
 
138
 
    /* Fill in port info. */
139
 
    name = pj_str("sine generator");
140
 
    pjmedia_port_info_init(&port->info, &name,
141
 
                           PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'),
142
 
                           sampling_rate,
143
 
                           channel_count,
144
 
                           16, sampling_rate * 20 / 1000 * channel_count);
145
 
 
146
 
    /* Set the function to feed frame */
147
 
    port->get_frame = &sine_get_frame;
148
 
 
149
 
    /* Create sine port data */
150
 
    port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));
151
 
 
152
 
    /* Create samples */
153
 
    count = PJMEDIA_PIA_SPF(&port->info) / channel_count;
154
 
    sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));
155
 
    PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);
156
 
 
157
 
    /* initialise sinusoidal wavetable */
158
 
    for( i=0; i<count; i++ )
159
 
    {
160
 
        sine->samples[i] = (pj_int16_t) (10000.0 *
161
 
                sin(((double)i/(double)count) * M_PI * 8.) );
162
 
    }
163
 
 
164
 
    *p_port = port;
165
 
 
166
 
    return PJ_SUCCESS;
167
 
}
168
 
 
169
 
 
170
 
/* Show usage */
171
 
static void usage(void)
172
 
{
173
 
    puts("");
174
 
    puts("Usage: playsine [nchannel]");
175
 
    puts("");
176
 
    puts("where");
177
 
    puts(" nchannel is number of audio channels (1 for mono, or 2 for stereo).");
178
 
    puts(" Default is 1 (mono).");
179
 
    puts("");
180
 
}
181
 
 
182
 
 
183
 
/*
184
 
 * main()
185
 
 */
186
 
int main(int argc, char *argv[])
187
 
{
188
 
    pj_caching_pool cp;
189
 
    pjmedia_endpt *med_endpt;
190
 
    pj_pool_t *pool;
191
 
    pjmedia_port *sine_port;
192
 
    pjmedia_snd_port *snd_port;
193
 
    char tmp[10];
194
 
    int channel_count = 1;
195
 
    pj_status_t status;
196
 
 
197
 
    if (argc == 2) {
198
 
        channel_count = atoi(argv[1]);
199
 
        if (channel_count < 1 || channel_count > 2) {
200
 
            puts("Error: invalid arguments");
201
 
            usage();
202
 
            return 1;
203
 
        }
204
 
    }
205
 
 
206
 
    /* Must init PJLIB first: */
207
 
    status = pj_init();
208
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
209
 
 
210
 
    /* Must create a pool factory before we can allocate any memory. */
211
 
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
212
 
 
213
 
    /*
214
 
     * Initialize media endpoint.
215
 
     * This will implicitly initialize PJMEDIA too.
216
 
     */
217
 
    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
218
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
219
 
 
220
 
    /* Create memory pool for our sine generator */
221
 
    pool = pj_pool_create( &cp.factory,     /* pool factory         */
222
 
                           "wav",           /* pool name.           */
223
 
                           4000,            /* init size            */
224
 
                           4000,            /* increment size       */
225
 
                           NULL             /* callback on error    */
226
 
                           );
227
 
 
228
 
    /* Create a media port to generate sine wave samples. */
229
 
    status = create_sine_port( pool,        /* memory pool          */
230
 
                               11025,       /* sampling rate        */
231
 
                               channel_count,/* # of channels       */
232
 
                               &sine_port   /* returned port        */
233
 
                             );
234
 
    if (status != PJ_SUCCESS) {
235
 
        app_perror(THIS_FILE, "Unable to create sine port", status);
236
 
        return 1;
237
 
    }
238
 
 
239
 
    /* Create sound player port. */
240
 
    status = pjmedia_snd_port_create_player(
241
 
                 pool,                              /* pool                 */
242
 
                 -1,                                /* use default dev.     */
243
 
                 PJMEDIA_PIA_SRATE(&sine_port->info),/* clock rate.         */
244
 
                 PJMEDIA_PIA_CCNT(&sine_port->info),/* # of channels.       */
245
 
                 PJMEDIA_PIA_SPF(&sine_port->info), /* samples per frame.   */
246
 
                 PJMEDIA_PIA_BITS(&sine_port->info),/* bits per sample.     */
247
 
                 0,                                 /* options              */
248
 
                 &snd_port                          /* returned port        */
249
 
                 );
250
 
    if (status != PJ_SUCCESS) {
251
 
        app_perror(THIS_FILE, "Unable to open sound device", status);
252
 
        return 1;
253
 
    }
254
 
 
255
 
    /* Connect sine generator port to the sound player
256
 
     * Stream playing will commence immediately.
257
 
     */
258
 
    status = pjmedia_snd_port_connect( snd_port, sine_port);
259
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
260
 
 
261
 
 
262
 
 
263
 
    /*
264
 
     * Audio should be playing in a loop now, using sound device's thread.
265
 
     */
266
 
 
267
 
 
268
 
    /* Sleep to allow log messages to flush */
269
 
    pj_thread_sleep(100);
270
 
 
271
 
 
272
 
    puts("Playing sine wave..");
273
 
    puts("");
274
 
    puts("Press <ENTER> to stop playing and quit");
275
 
 
276
 
    if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
277
 
        puts("EOF while reading stdin, will quit now..");
278
 
    }
279
 
 
280
 
 
281
 
    /* Start deinitialization: */
282
 
 
283
 
    /* Disconnect sound port from file port */
284
 
    status = pjmedia_snd_port_disconnect(snd_port);
285
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
286
 
 
287
 
    /* Without this sleep, Windows/DirectSound will repeteadly
288
 
     * play the last frame during destroy.
289
 
     */
290
 
    pj_thread_sleep(100);
291
 
 
292
 
    /* Destroy sound device */
293
 
    status = pjmedia_snd_port_destroy( snd_port );
294
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
295
 
 
296
 
 
297
 
    /* Destroy sine generator */
298
 
    status = pjmedia_port_destroy( sine_port );
299
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
300
 
 
301
 
 
302
 
    /* Release application pool */
303
 
    pj_pool_release( pool );
304
 
 
305
 
    /* Destroy media endpoint. */
306
 
    pjmedia_endpt_destroy( med_endpt );
307
 
 
308
 
    /* Destroy pool factory */
309
 
    pj_caching_pool_destroy( &cp );
310
 
 
311
 
    /* Shutdown PJLIB */
312
 
    pj_shutdown();
313
 
 
314
 
 
315
 
    /* Done. */
316
 
    return 0;
317
 
}