source: portaudio/branches/V18.1/pa_tests/debug_record_reuse.c @ 165

Revision 165, 10.7 KB checked in by philburk, 8 years ago (diff)

Demonstrate bug with Terratect where stream sample rates change!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * $Id$
3 * debug_record_reuse.c
4 * Record input into an array.
5 * Save array to a file.
6 * Based on patest_record.c but with various ugly debug hacks thrown in.
7 * Loop twice and reuse same streams.
8 *
9 * Author: Phil Burk  http://www.softsynth.com
10 *
11 * This program uses the PortAudio Portable Audio Library.
12 * For more information see: http://www.portaudio.com
13 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files
17 * (the "Software"), to deal in the Software without restriction,
18 * including without limitation the rights to use, copy, modify, merge,
19 * publish, distribute, sublicense, and/or sell copies of the Software,
20 * and to permit persons to whom the Software is furnished to do so,
21 * subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * Any person wishing to distribute modifications to the Software is
27 * requested to send the modifications to the original developer so that
28 * they can be incorporated into the canonical version.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
34 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
35 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 *
38 */
39#include <stdio.h>
40#include <stdlib.h>
41#include <memory.h>
42#include "portaudio.h"
43#define SAMPLE_RATE     (22050)
44#define NUM_SECONDS     (4)
45#define SLEEP_DUR_MSEC  (200)
46#define FRAMES_PER_BUFFER  (256)
47#define NUM_REC_BUFS    (0)
48
49#if 1
50#define PA_SAMPLE_TYPE  paFloat32
51typedef float SAMPLE;
52#else
53#define PA_SAMPLE_TYPE  paInt16
54typedef short SAMPLE;
55#endif
56
57typedef struct
58{
59    long         frameIndex;  /* Index into sample array. */
60    long         maxFrameIndex;
61    long         samplesPerFrame;
62    long         numSamples;
63    PortAudioStream *outputStream;
64    PortAudioStream *inputStream;
65    SAMPLE      *recordedSamples;
66}
67paTestData;
68
69/* This routine will be called by the PortAudio engine when audio is needed.
70** It may be called at interrupt level on some machines so don't do anything
71** that could mess up the system like calling malloc() or free().
72*/
73static int recordCallback( void *inputBuffer, void *outputBuffer,
74                           unsigned long framesPerBuffer,
75                           PaTimestamp outTime, void *userData )
76{
77    paTestData *data = (paTestData*)userData;
78    SAMPLE *rptr = (SAMPLE*)inputBuffer;
79    SAMPLE *wptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
80    long framesToCalc;
81    unsigned long i;
82    int finished;
83    unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
84
85    (void) outputBuffer; /* Prevent unused variable warnings. */
86    (void) outTime;
87
88    if( framesLeft < framesPerBuffer )
89    {
90        framesToCalc = framesLeft;
91        finished = 1;
92    }
93    else
94    {
95        framesToCalc = framesPerBuffer;
96        finished = 0;
97    }
98    if( inputBuffer == NULL )
99    {
100        for( i=0; i<framesToCalc; i++ )
101        {
102            *wptr++ = 0;  /* left */
103            *wptr++ = 0;  /* right */
104        }
105    }
106    else
107    {
108        for( i=0; i<framesToCalc; i++ )
109        {
110            *wptr++ = *rptr++;  /* left */
111            *wptr++ = *rptr++;  /* right */
112        }
113    }
114    data->frameIndex += framesToCalc;
115    return finished;
116}
117
118/* This routine will be called by the PortAudio engine when audio is needed.
119** It may be called at interrupt level on some machines so don't do anything
120** that could mess up the system like calling malloc() or free().
121*/
122static int playCallback( void *inputBuffer, void *outputBuffer,
123                         unsigned long framesPerBuffer,
124                         PaTimestamp outTime, void *userData )
125{
126    paTestData *data = (paTestData*)userData;
127    SAMPLE *rptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
128    SAMPLE *wptr = (SAMPLE*)outputBuffer;
129    unsigned long i;
130    int finished;
131    unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
132    if( outputBuffer == NULL ) return 0;
133    (void) inputBuffer; /* Prevent unused variable warnings. */
134    (void) outTime;
135
136    if( framesLeft < framesPerBuffer )
137    {
138        /* final buffer... */
139        for( i=0; i<framesLeft; i++ )
140        {
141            *wptr++ = *rptr++;  /* left */
142            *wptr++ = *rptr++;  /* right */
143        }
144        for( ; i<framesPerBuffer; i++ )
145        {
146            *wptr++ = 0;  /* left */
147            *wptr++ = 0;  /* right */
148        }
149        data->frameIndex += framesLeft;
150        finished = 1;
151    }
152    else
153    {
154        for( i=0; i<framesPerBuffer; i++ )
155        {
156            *wptr++ = *rptr++;  /* left */
157            *wptr++ = *rptr++;  /* right */
158        }
159        data->frameIndex += framesPerBuffer;
160        finished = 0;
161    }
162    return finished;
163}
164
165/****************************************************************/
166PaError TestRecording( paTestData *dataPtr )
167{
168    PaError    err;
169    int        i;
170    int        lastIndex = 0;
171
172/* Open input stream if not already open. */
173    if( dataPtr->inputStream == NULL )
174    {
175        /* Record some audio. */
176        err = Pa_OpenStream(
177                  &dataPtr->inputStream,
178                  Pa_GetDefaultInputDeviceID(),
179                  dataPtr->samplesPerFrame,               /* stereo input */
180                  PA_SAMPLE_TYPE,
181                  NULL,
182                  paNoDevice,
183                  0,
184                  PA_SAMPLE_TYPE,
185                  NULL,
186                  SAMPLE_RATE,
187                  FRAMES_PER_BUFFER,            /* frames per buffer */
188                  NUM_REC_BUFS,               /* number of buffers, if zero then use default minimum */
189                  paClipOff,       /* we won't output out of range samples so don't bother clipping them */
190                  recordCallback,
191                  dataPtr );
192        if( err != paNoError ) goto error;
193    }
194
195    dataPtr->frameIndex = 0;
196
197    err = Pa_StartStream( dataPtr->inputStream );
198    if( err != paNoError ) goto error;
199
200    printf("Now recording!\n"); fflush(stdout);
201    for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
202    {
203        int frameIndex, delta;
204        Pa_Sleep(SLEEP_DUR_MSEC);
205
206        frameIndex = dataPtr->frameIndex;
207        if( Pa_StreamActive( dataPtr->inputStream ) <= 0)
208        {
209            printf("Stream inactive!\n");
210            break;
211        }
212        if( dataPtr->maxFrameIndex <= frameIndex )
213        {
214            printf("Buffer recording complete.\n");
215            break;
216        }
217
218        delta = frameIndex - lastIndex;
219        lastIndex = frameIndex;
220        printf("index = %d, delta = %d\n", frameIndex, delta ); fflush(stdout);
221    }
222
223    err = Pa_StopStream( dataPtr->inputStream );
224    if( err != paNoError ) goto error;
225
226    printf("Done.\n"); fflush(stdout);
227
228error:
229    return err;
230}
231
232/****************************************************************/
233PaError TestPlayback( paTestData *dataPtr )
234{
235    PaError    err;
236    int        i;
237    int        lastIndex = 0;
238
239    /* Playback recorded data. */
240    dataPtr->frameIndex = 0;
241    printf("Begin playback.\n"); fflush(stdout);
242
243/* Open output stream if not already open. */
244    if( dataPtr->outputStream == NULL )
245    {
246        err = Pa_OpenStream(
247                  &dataPtr->outputStream,
248                  paNoDevice,
249                  0,               /* NO input */
250                  PA_SAMPLE_TYPE,
251                  NULL,
252                  Pa_GetDefaultOutputDeviceID(),
253                  dataPtr->samplesPerFrame,               /* stereo output */
254                  PA_SAMPLE_TYPE,
255                  NULL,
256                  SAMPLE_RATE,
257                  FRAMES_PER_BUFFER,            /* frames per buffer */
258                  0,               /* number of buffers, if zero then use default minimum */
259                  paClipOff,       /* we won't output out of range samples so don't bother clipping them */
260                  playCallback,
261                  dataPtr );
262        if( err != paNoError ) goto error;
263    }
264
265    err = Pa_StartStream( dataPtr->outputStream );
266    if( err != paNoError ) goto error;
267
268    printf("Waiting for playback to finish.\n"); fflush(stdout);
269    for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
270    {
271        int frameIndex, delta;
272        Pa_Sleep(SLEEP_DUR_MSEC);
273        frameIndex = dataPtr->frameIndex;
274        delta = frameIndex - lastIndex;
275        lastIndex = frameIndex;
276        printf("index = %d, delta = %d\n", frameIndex, delta ); fflush(stdout);
277    }
278
279    err = Pa_StopStream( dataPtr->outputStream );
280    if( err != paNoError ) goto error;
281   
282error:
283    return err;
284}
285/*******************************************************************/
286int main(void);
287int main(void)
288{
289    PaError    err;
290    paTestData data = { 0 };
291    long       totalFrames;
292    long       numBytes;
293    long       i;
294    printf("patest_record.c\n"); fflush(stdout);
295
296/* Set up test data structure and sample array. */
297    data.frameIndex = 0;
298    data.samplesPerFrame = 2;
299    data.maxFrameIndex = totalFrames = NUM_SECONDS*SAMPLE_RATE;
300
301    printf("totalFrames = %d\n", totalFrames ); fflush(stdout);
302    data.numSamples = totalFrames * data.samplesPerFrame;
303
304    numBytes = data.numSamples * sizeof(SAMPLE);
305    data.recordedSamples = (SAMPLE *) malloc( numBytes );
306    if( data.recordedSamples == NULL )
307    {
308        printf("Could not allocate record array.\n");
309        exit(1);
310    }
311    for( i=0; i<data.numSamples; i++ ) data.recordedSamples[i] = 0;
312
313    err = Pa_Initialize();
314    if( err != paNoError ) goto error;
315
316/* Record and playback multiple times. */
317    for( i=0; i<2; i++ )
318    {
319        err = TestRecording( &data );
320        if( err != paNoError ) goto error;
321
322        err = TestPlayback( &data );
323        if( err != paNoError ) goto error;
324    }
325
326/* Clean up. */
327    err = Pa_CloseStream( data.inputStream );
328    if( err != paNoError ) goto error;
329
330    err = Pa_CloseStream( data.outputStream );
331    if( err != paNoError ) goto error;
332
333    if( err != paNoError ) goto error;
334
335    free( data.recordedSamples );
336    Pa_Terminate();
337   
338    printf("Test complete.\n"); fflush(stdout);
339    return 0;
340
341error:
342    Pa_Terminate();
343    fprintf( stderr, "An error occured while using the portaudio stream\n" );
344    fprintf( stderr, "Error number: %d\n", err );
345    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
346    if( err == paHostError )
347    {
348        fprintf( stderr, "Host Error number: %d\n", Pa_GetHostError() );
349    }
350    return -1;
351}
Note: See TracBrowser for help on using the repository browser.