To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / portaudio_20161030_catalina_patch / test / patest_sync.c @ 162:d43aab368df9

History | View | Annotate | Download (9.56 KB)

1
/** @file patest_sync.c
2
        @ingroup test_src
3
        @brief Test time stamping and synchronization of audio and video.
4

5
        A high latency is used so we can hear the difference in time.
6
        Random durations are used so we know we are hearing the right beep
7
        and not the one before or after.
8

9
        Sequence of events:
10
                -# Foreground requests a beep.
11
                -# Background randomly schedules a beep.
12
                -# Foreground waits for the beep to be heard based on PaUtil_GetTime().
13
                -# Foreground outputs video (printf) in sync with audio.
14
                -# Repeat.
15
        
16
        @author Phil Burk  http://www.softsynth.com
17
*/
18
/*
19
 * $Id$
20
 *
21
 * This program uses the PortAudio Portable Audio Library.
22
 * For more information see: http://www.portaudio.com
23
 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
24
 *
25
 * Permission is hereby granted, free of charge, to any person obtaining
26
 * a copy of this software and associated documentation files
27
 * (the "Software"), to deal in the Software without restriction,
28
 * including without limitation the rights to use, copy, modify, merge,
29
 * publish, distribute, sublicense, and/or sell copies of the Software,
30
 * and to permit persons to whom the Software is furnished to do so,
31
 * subject to the following conditions:
32
 *
33
 * The above copyright notice and this permission notice shall be
34
 * included in all copies or substantial portions of the Software.
35
 *
36
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
37
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
38
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
39
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
40
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
41
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
42
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43
 */
44

    
45
/*
46
 * The text above constitutes the entire PortAudio license; however, 
47
 * the PortAudio community also makes the following non-binding requests:
48
 *
49
 * Any person wishing to distribute modifications to the Software is
50
 * requested to send the modifications to the original developer so that
51
 * they can be incorporated into the canonical version. It is also 
52
 * requested that these non-binding requests be included along with the 
53
 * license above.
54
 */
55

    
56
#include <stdio.h>
57
#include <math.h>
58
#include "portaudio.h"
59
#include "pa_util.h"
60
#define NUM_BEEPS           (6)
61
#define SAMPLE_RATE         (44100)
62
#define SAMPLE_PERIOD       (1.0/44100.0)
63
#define FRAMES_PER_BUFFER   (256)
64
#define BEEP_DURATION       (400)
65
#define LATENCY_MSEC        (2000)
66
#define SLEEP_MSEC          (10)
67
#define TIMEOUT_MSEC        (15000)
68

    
69
#define STATE_BKG_IDLE      (0)
70
#define STATE_BKG_PENDING   (1)
71
#define STATE_BKG_BEEPING   (2)
72
typedef struct
73
{
74
    float        left_phase;
75
    float        right_phase;
76
    int          state;
77
    volatile int requestBeep;  /* Set by foreground, cleared by background. */
78
    PaTime       beepTime;
79
    int          beepCount;
80
    double       latency;    /* For debugging. */
81
}
82
paTestData;
83

    
84
static unsigned long GenerateRandomNumber( void );
85
/************************************************************/
86
/* Calculate pseudo-random 32 bit number based on linear congruential method. */
87
static unsigned long GenerateRandomNumber( void )
88
{
89
    static unsigned long randSeed = 99887766;  /* Change this for different random sequences. */
90
    randSeed = (randSeed * 196314165) + 907633515;
91
    return randSeed;
92
}
93

    
94
/* This routine will be called by the PortAudio engine when audio is needed.
95
** It may called at interrupt level on some machines so don't do anything
96
** that could mess up the system like calling malloc() or free().
97
*/
98
static int patestCallback( const void *inputBuffer, void *outputBuffer,
99
                           unsigned long framesPerBuffer,
100
                           const PaStreamCallbackTimeInfo *timeInfo,
101
                           PaStreamCallbackFlags statusFlags, void *userData )
102
{
103
    /* Cast data passed through stream to our structure. */
104
    paTestData *data = (paTestData*)userData;
105
    float *out = (float*)outputBuffer;
106
    unsigned int i;
107
    (void) inputBuffer;
108

    
109
    data->latency = timeInfo->outputBufferDacTime - timeInfo->currentTime;
110

    
111
    for( i=0; i<framesPerBuffer; i++ )
112
    {
113
        switch( data->state )
114
        {
115
        case STATE_BKG_IDLE:
116
            /* Schedule beep at some random time in the future. */
117
            if( data->requestBeep )
118
            {
119
                int random = GenerateRandomNumber() >> 14;
120
                data->beepTime = timeInfo->outputBufferDacTime + (( (double)(random + SAMPLE_RATE)) * SAMPLE_PERIOD );
121
                data->state = STATE_BKG_PENDING;
122
            }
123
            *out++ = 0.0;  /* left */
124
            *out++ = 0.0;  /* right */
125
            break;
126

    
127
        case STATE_BKG_PENDING:
128
            if( (timeInfo->outputBufferDacTime + (i*SAMPLE_PERIOD)) >= data->beepTime )
129
            {
130
                data->state = STATE_BKG_BEEPING;
131
                data->beepCount = BEEP_DURATION;
132
                data->left_phase = data->right_phase = 0.0;
133
            }
134
            *out++ = 0.0;  /* left */
135
            *out++ = 0.0;  /* right */
136
            break;
137

    
138
        case STATE_BKG_BEEPING:
139
            if( data->beepCount <= 0 )
140
            {
141
                data->state = STATE_BKG_IDLE;
142
                data->requestBeep = 0;
143
                *out++ = 0.0;  /* left */
144
                *out++ = 0.0;  /* right */
145
            }
146
            else
147
            {
148
                /* Play sawtooth wave. */
149
                *out++ = data->left_phase;  /* left */
150
                *out++ = data->right_phase;  /* right */
151
                /* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
152
                data->left_phase += 0.01f;
153
                /* When signal reaches top, drop back down. */
154
                if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;
155
                /* higher pitch so we can distinguish left and right. */
156
                data->right_phase += 0.03f;
157
                if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
158
            }
159
            data->beepCount -= 1;
160
            break;
161

    
162
        default:
163
            data->state = STATE_BKG_IDLE;
164
            break;
165
        }
166
    }
167
    return 0;
168
}
169
/*******************************************************************/
170
int main(void);
171
int main(void)
172
{
173
    PaStream *stream;
174
    PaError    err;
175
    paTestData DATA;
176
    int        i, timeout;
177
    PaTime     previousTime;
178
    PaStreamParameters outputParameters;
179
    printf("PortAudio Test: you should see BEEP at the same time you hear it.\n");
180
    printf("Wait for a few seconds random delay between BEEPs.\n");
181
    printf("BEEP %d times.\n", NUM_BEEPS );
182
    /* Initialize our DATA for use by callback. */
183
    DATA.left_phase = DATA.right_phase = 0.0;
184
    DATA.state = STATE_BKG_IDLE;
185
    DATA.requestBeep = 0;
186
    /* Initialize library before making any other calls. */
187
    err = Pa_Initialize();
188
    if( err != paNoError ) goto error;
189
    
190
    outputParameters.device = Pa_GetDefaultOutputDevice();
191
    if (outputParameters.device == paNoDevice) {
192
        fprintf(stderr,"Error: No default output device.\n");
193
        goto error;
194
    }
195
    outputParameters.channelCount = 2;
196
    outputParameters.hostApiSpecificStreamInfo = NULL;
197
    outputParameters.sampleFormat = paFloat32;
198
    outputParameters.suggestedLatency = (double)LATENCY_MSEC / 1000;
199

    
200
    /* Open an audio I/O stream. */
201
     err = Pa_OpenStream(
202
              &stream,
203
              NULL,                         /* no input */
204
              &outputParameters,
205
              SAMPLE_RATE,
206
              FRAMES_PER_BUFFER,            /* frames per buffer */
207
              paClipOff,      /* we won't output out of range samples so don't bother clipping them */
208
              patestCallback,
209
              &DATA );
210
   if( err != paNoError ) goto error;
211

    
212
    err = Pa_StartStream( stream );
213
    if( err != paNoError ) goto error;
214

    
215
    printf("started\n");
216
    fflush(stdout);
217

    
218
    previousTime = Pa_GetStreamTime( stream );
219
    for( i=0; i<NUM_BEEPS; i++ )
220
    {
221
        /* Request a beep from background. */
222
        DATA.requestBeep = 1;
223

    
224
        /* Wait for background to acknowledge request. */
225
        timeout = TIMEOUT_MSEC;
226
        while( (DATA.requestBeep == 1) && (timeout-- > 0 ) ) Pa_Sleep(SLEEP_MSEC);
227
        if( timeout <= 0 )
228
        {
229
            fprintf( stderr, "Timed out waiting for background to acknowledge request.\n" );
230
            goto error;
231
        }
232
        printf("calc beep for %9.3f, latency = %6.3f\n", DATA.beepTime, DATA.latency );
233
        fflush(stdout);
234

    
235
        /* Wait for scheduled beep time. */
236
        timeout =  TIMEOUT_MSEC + (10000/SLEEP_MSEC);
237
        while( (Pa_GetStreamTime( stream ) < DATA.beepTime) && (timeout-- > 0 ) )
238
        {
239
            Pa_Sleep(SLEEP_MSEC);
240
        }
241
        if( timeout <= 0 )
242
        {
243
            fprintf( stderr, "Timed out waiting for time. Now = %9.3f, Beep for %9.3f.\n",
244
                     PaUtil_GetTime(), DATA.beepTime );
245
            goto error;
246
        }
247

    
248
        /* Beep should be sounding now so print synchronized BEEP. */
249
        printf("hear \"BEEP\" at %9.3f, delta = %9.3f\n",
250
               Pa_GetStreamTime( stream ), (DATA.beepTime - previousTime) );
251
        fflush(stdout);
252

    
253
        previousTime = DATA.beepTime;
254
    }
255

    
256
    err = Pa_StopStream( stream );
257
    if( err != paNoError ) goto error;
258

    
259
    err = Pa_CloseStream( stream );
260
    if( err != paNoError ) goto error;
261

    
262
    Pa_Terminate();
263
    printf("Test finished.\n");
264
    return err;
265
error:
266
    Pa_Terminate();
267
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
268
    fprintf( stderr, "Error number: %d\n", err );
269
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
270
    return err;
271
}