0
|
1 /******************************************/
|
|
2 /*
|
|
3 audiodelay.cpp
|
|
4 by Peter Meerwald, pmeerw@pmeerw.net, 2009.
|
|
5
|
|
6 This program tests the delay between audio output and input.
|
|
7 */
|
|
8 /******************************************/
|
|
9
|
|
10 #include "RtAudio.h"
|
|
11 #include <stdlib.h>
|
|
12 #include <stdio.h>
|
|
13 #include <math.h>
|
|
14 #include <string.h>
|
|
15 #include <sys/time.h>
|
|
16 #include <time.h>
|
|
17
|
|
18 const char *progname = "audiodelay";
|
|
19
|
|
20 typedef signed short AUDIOSAMPLE_TYPE;
|
|
21 #define FORMAT RTAUDIO_SINT16
|
|
22
|
|
23 static volatile unsigned int nmeasurements = 0;
|
|
24 static float accum_measurements = 0.0f;
|
|
25
|
|
26 static int inout(void *out_buf, void *in_buf, unsigned int nbuf_frames,
|
|
27 double stream_time, RtAudioStreamStatus status, void *data) {
|
|
28 if (status)
|
|
29 printf("%s: stream over/underflow detected\n", progname);
|
|
30
|
|
31 static unsigned int count_inout = 0;
|
|
32 static struct timeval tv_start;
|
|
33 static struct timeval tv_stop;
|
|
34
|
|
35 AUDIOSAMPLE_TYPE *pout = (AUDIOSAMPLE_TYPE *)out_buf, *pin = (AUDIOSAMPLE_TYPE *)in_buf;
|
|
36
|
|
37 memset(out_buf, 0, nbuf_frames*sizeof(AUDIOSAMPLE_TYPE) * 2);
|
|
38 if ((count_inout % (512*128/nbuf_frames)) == 0) {
|
|
39 for (unsigned int i = nbuf_frames/2-4; i < nbuf_frames/2+4; i++) {
|
|
40 pout[2*i] = 32000;
|
|
41 pout[2*i+1] = 32000;
|
|
42 }
|
|
43
|
|
44 gettimeofday(&tv_start, 0);
|
|
45 }
|
|
46
|
|
47 if (1) {
|
|
48 for (unsigned int i = 0; i < nbuf_frames; i++) {
|
|
49 if (pin[2*i] > 15000 || pin[2*i+1] > 15000) {
|
|
50
|
|
51 gettimeofday(&tv_stop, 0);
|
|
52
|
|
53 unsigned int msec = (tv_stop.tv_sec - tv_start.tv_sec) * 1000;
|
|
54 if (tv_stop.tv_usec < tv_start.tv_usec)
|
|
55 msec -= (tv_start.tv_usec - tv_stop.tv_usec) / 1000;
|
|
56 else
|
|
57 msec += (tv_stop.tv_usec - tv_start.tv_usec) / 1000;
|
|
58
|
|
59 accum_measurements += msec;
|
|
60 nmeasurements++;
|
|
61 printf("%s: measured delay %u ms, offset %u, average %.2f\n", progname, msec, i, accum_measurements / nmeasurements);
|
|
62
|
|
63 break;
|
|
64 }
|
|
65 }
|
|
66 }
|
|
67
|
|
68 count_inout++;
|
|
69
|
|
70 return 0;
|
|
71 }
|
|
72
|
|
73 int main(int argc, char *argv[]) {
|
|
74 unsigned int channels = 2, sample_rate = 44100, buf_bytes, odevice = 0, idevice = 0, ioffset = 0, ooffset = 0;
|
|
75
|
|
76 RtAudio adac;
|
|
77 if (adac.getDeviceCount() < 1) {
|
|
78 std::cout << "\nNo audio devices found!\n";
|
|
79 exit(EXIT_FAILURE);
|
|
80 }
|
|
81
|
|
82 // Let RtAudio print messages to stderr.
|
|
83 adac.showWarnings(true);
|
|
84
|
|
85 // Set the same number of channels for both input and output.
|
|
86 unsigned int buf_frames = 128;
|
|
87 RtAudio::StreamParameters iparams, oparams;
|
|
88 iparams.deviceId = idevice;
|
|
89 iparams.nChannels = channels;
|
|
90 iparams.firstChannel = ioffset;
|
|
91 oparams.deviceId = odevice;
|
|
92 oparams.nChannels = channels;
|
|
93 oparams.firstChannel = ooffset;
|
|
94
|
|
95 RtAudio::StreamOptions options;
|
|
96 options.flags = 0; // RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_SCHEDULE_REALTIME
|
|
97 options.numberOfBuffers = 2;
|
|
98 options.priority = 0; // for RTAUDIO_SCHEDULE_REALTIME
|
|
99
|
|
100 try {
|
|
101 adac.openStream(&oparams, &iparams, FORMAT, sample_rate, &buf_frames, &inout, (void *)&buf_bytes, &options);
|
|
102 }
|
|
103 catch (RtError& e) {
|
|
104 printf("%s: %s\n", progname, e.getMessage().c_str());
|
|
105 exit(EXIT_FAILURE);
|
|
106 }
|
|
107
|
|
108 buf_bytes = buf_frames * channels * sizeof(AUDIOSAMPLE_TYPE);
|
|
109
|
|
110 try {
|
|
111 adac.startStream();
|
|
112
|
|
113 printf("%s: stream latency %ld frames, %d sample rate\n", progname, adac.getStreamLatency(), adac.getStreamSampleRate());
|
|
114
|
|
115 printf("%s: running ... press <enter> to quit (%d buffer frames)\n", progname, buf_frames);
|
|
116 getchar();
|
|
117
|
|
118 // Stop the stream.
|
|
119 adac.stopStream();
|
|
120 }
|
|
121 catch (RtError& e) {
|
|
122 printf("%s: %s\n", progname, e.getMessage().c_str());
|
|
123 goto cleanup;
|
|
124 }
|
|
125
|
|
126 cleanup:
|
|
127 if (adac.isStreamOpen())
|
|
128 adac.closeStream();
|
|
129
|
|
130 return 0;
|
|
131 }
|