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_stop.c @ 162:d43aab368df9

History | View | Annotate | Download (10.5 KB)

1
/** @file patest_stop.c
2
        @ingroup test_src
3
        @brief Test different ways of stopping audio.
4

5
        Test the three ways of stopping audio:
6
                - calling Pa_StopStream(),
7
                - calling Pa_AbortStream(),
8
                - and returning a 1 from the callback function.
9

10
        A long latency is set up so that you can hear the difference.
11
        Then a simple 8 note sequence is repeated twice.
12
        The program will print what you should hear.
13

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

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

    
57
#define OUTPUT_DEVICE       (Pa_GetDefaultOutputDevice())
58
#define SLEEP_DUR           (200)
59
#define SAMPLE_RATE         (44100)
60
#define FRAMES_PER_BUFFER   (256)
61
#define LATENCY_SECONDS     (3.f)
62
#define FRAMES_PER_NOTE     (SAMPLE_RATE/2)
63
#define MAX_REPEATS         (2)
64
#define FUNDAMENTAL         (400.0f / SAMPLE_RATE)
65
#define NOTE_0              (FUNDAMENTAL * 1.0f / 1.0f)
66
#define NOTE_1              (FUNDAMENTAL * 5.0f / 4.0f)
67
#define NOTE_2              (FUNDAMENTAL * 4.0f / 3.0f)
68
#define NOTE_3              (FUNDAMENTAL * 3.0f / 2.0f)
69
#define NOTE_4              (FUNDAMENTAL * 2.0f / 1.0f)
70
#define MODE_FINISH    (0)
71
#define MODE_STOP      (1)
72
#define MODE_ABORT     (2)
73
#ifndef M_PI
74
#define M_PI  (3.14159265)
75
#endif
76
#define TABLE_SIZE   (400)
77

    
78
typedef struct
79
{
80
    float  waveform[TABLE_SIZE + 1]; /* Add one for guard point for interpolation. */
81
    float  phase_increment;
82
    float  phase;
83
    float *tune;
84
    int    notesPerTune;
85
    int    frameCounter;
86
    int    noteCounter;
87
    int    repeatCounter;
88
    PaTime outTime;
89
    int    stopMode;
90
    int    done;
91
}
92
paTestData;
93

    
94
/************* Prototypes *****************************/
95
int TestStopMode( paTestData *data );
96
float LookupWaveform( paTestData *data, float phase );
97

    
98
/******************************************************
99
 * Convert phase between 0.0 and 1.0 to waveform value 
100
 * using linear interpolation.
101
 */
102
float LookupWaveform( paTestData *data, float phase )
103
{
104
    float fIndex = phase*TABLE_SIZE;
105
    int   index = (int) fIndex;
106
    float fract = fIndex - index;
107
    float lo = data->waveform[index];
108
    float hi = data->waveform[index+1];
109
    float val = lo + fract*(hi-lo);
110
    return val;
111
}
112

    
113
/* This routine will be called by the PortAudio engine when audio is needed.
114
** It may called at interrupt level on some machines so don't do anything
115
** that could mess up the system like calling malloc() or free().
116
*/
117
static int patestCallback( const void *inputBuffer, void *outputBuffer,
118
                            unsigned long framesPerBuffer,
119
                            const PaStreamCallbackTimeInfo* timeInfo,
120
                            PaStreamCallbackFlags statusFlags,
121
                            void *userData )
122
{
123
    paTestData *data = (paTestData*)userData;
124
    float *out = (float*)outputBuffer;
125
    float value;
126
    unsigned int i = 0;
127
    int finished = paContinue;
128

    
129
    (void) inputBuffer;     /* Prevent unused variable warnings. */
130
    (void) timeInfo;
131
    (void) statusFlags;
132

    
133

    
134
    /* data->outTime = outTime; */
135
    
136
    if( !data->done )
137
    {
138
        for( i=0; i<framesPerBuffer; i++ )
139
        {
140
            /* Are we done with this note? */
141
            if( data->frameCounter >= FRAMES_PER_NOTE )
142
            {
143
                data->noteCounter += 1;
144
                data->frameCounter = 0;
145
                /* Are we done with this tune? */
146
                if( data->noteCounter >= data->notesPerTune )
147
                {
148
                    data->noteCounter = 0;
149
                    data->repeatCounter += 1;
150
                    /* Are we totally done? */
151
                    if( data->repeatCounter >= MAX_REPEATS )
152
                    {
153
                        data->done = 1;
154
                        if( data->stopMode == MODE_FINISH )
155
                        {
156
                            finished = paComplete;
157
                            break;
158
                        }
159
                    }
160
                }
161
                data->phase_increment = data->tune[data->noteCounter];
162
            }
163
            value = LookupWaveform(data, data->phase);
164
            *out++ = value;  /* left */
165
            *out++ = value;  /* right */
166
            data->phase += data->phase_increment;
167
            if( data->phase >= 1.0f ) data->phase -= 1.0f;
168

    
169
            data->frameCounter += 1;
170
        }
171
    }
172
    /* zero remainder of final buffer */
173
    for( ; i<framesPerBuffer; i++ )
174
    {
175
        *out++ = 0; /* left */
176
        *out++ = 0; /* right */
177
    }
178
    return finished;
179
}
180
/*******************************************************************/
181
int main(void);
182
int main(void)
183
{
184
    paTestData data;
185
    int i;
186
    float simpleTune[] = { NOTE_0, NOTE_1, NOTE_2, NOTE_3, NOTE_4, NOTE_3, NOTE_2, NOTE_1 };
187
    
188
    printf("PortAudio Test: play song and test stopping. ask for %f seconds latency\n", LATENCY_SECONDS );
189
    /* initialise sinusoidal wavetable */
190
    for( i=0; i<TABLE_SIZE; i++ )
191
    {
192
        data.waveform[i] = (float) (
193
                               (0.2 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. )) +
194
                               (0.2 * sin( ((double)(3*i)/(double)TABLE_SIZE) * M_PI * 2. )) +
195
                               (0.1 * sin( ((double)(5*i)/(double)TABLE_SIZE) * M_PI * 2. ))
196
                           );
197
    }
198
    data.waveform[TABLE_SIZE] = data.waveform[0]; /* Set guard point. */
199
    data.tune = &simpleTune[0];
200
    data.notesPerTune = sizeof(simpleTune) / sizeof(float);
201

    
202
    printf("Test MODE_FINISH - callback returns 1.\n");
203
    printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
204
    data.stopMode = MODE_FINISH;
205
    if( TestStopMode( &data ) != paNoError )
206
    {
207
        printf("Test of MODE_FINISH failed!\n");
208
        goto error;
209
    }
210

    
211
    printf("Test MODE_STOP - stop when song is done.\n");
212
    printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
213
    data.stopMode = MODE_STOP;
214
    if( TestStopMode( &data ) != paNoError )
215
    {
216
        printf("Test of MODE_STOP failed!\n");
217
        goto error;
218
    }
219

    
220
    printf("Test MODE_ABORT - abort immediately.\n");
221
    printf("Should hear last repetition cut short by %f seconds.\n", LATENCY_SECONDS);
222
    data.stopMode = MODE_ABORT;
223
    if( TestStopMode( &data ) != paNoError )
224
    {
225
        printf("Test of MODE_ABORT failed!\n");
226
        goto error;
227
    }
228

    
229
    return 0;
230

    
231
error:
232
    return 1;
233
}
234

    
235
int TestStopMode( paTestData *data )
236
{
237
    PaStreamParameters outputParameters;
238
    PaStream *stream;
239
    PaError err;
240
    
241
    data->done = 0;
242
    data->phase = 0.0;
243
    data->frameCounter = 0;
244
    data->noteCounter = 0;
245
    data->repeatCounter = 0;
246
    data->phase_increment = data->tune[data->noteCounter];
247
    
248
    err = Pa_Initialize();
249
    if( err != paNoError ) goto error;
250

    
251
    outputParameters.device = OUTPUT_DEVICE;
252
    if (outputParameters.device == paNoDevice) {
253
        fprintf(stderr,"Error: No default output device.\n");
254
        goto error;
255
    }
256
    outputParameters.channelCount = 2;          /* stereo output */
257
    outputParameters.sampleFormat = paFloat32;  /* 32 bit floating point output */
258
    outputParameters.suggestedLatency = LATENCY_SECONDS;
259
    outputParameters.hostApiSpecificStreamInfo = NULL;
260
    
261
    err = Pa_OpenStream(
262
              &stream,
263
              NULL, /* no input */
264
              &outputParameters,
265
              SAMPLE_RATE,
266
              FRAMES_PER_BUFFER,            /* frames per buffer */
267
              paClipOff,      /* we won't output out of range samples so don't bother clipping them */
268
              patestCallback,
269
              data );
270
    if( err != paNoError ) goto error;
271

    
272
    err = Pa_StartStream( stream );
273
    if( err != paNoError ) goto error;
274

    
275
    if( data->stopMode == MODE_FINISH )
276
    {
277
        while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
278
        {
279
            /*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
280
             data->noteCounter, data->repeatCounter  );
281
            fflush(stdout); */
282
            Pa_Sleep( SLEEP_DUR );
283
        }
284
        if( err < 0 ) goto error;
285
    }
286
    else
287
    {
288
        while( data->repeatCounter < MAX_REPEATS )
289
        {
290
            /*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
291
             data->noteCounter, data->repeatCounter  );
292
            fflush(stdout); */
293
            Pa_Sleep( SLEEP_DUR );
294
        }
295
    }
296

    
297
    if( data->stopMode == MODE_ABORT )
298
    {
299
        printf("Call Pa_AbortStream()\n");
300
        err = Pa_AbortStream( stream );
301
    }
302
    else
303
    {
304
        printf("Call Pa_StopStream()\n");
305
        err = Pa_StopStream( stream );
306
    }
307
    if( err != paNoError ) goto error;
308

    
309
    printf("Call Pa_CloseStream()\n"); fflush(stdout);
310
    err = Pa_CloseStream( stream );
311
    if( err != paNoError ) goto error;
312

    
313
    Pa_Terminate();
314
    printf("Test finished.\n");
315

    
316
    return err;
317

    
318
error:
319
    Pa_Terminate();
320
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
321
    fprintf( stderr, "Error number: %d\n", err );
322
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
323
    return err;
324
}