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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/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
}