summaryrefslogtreecommitdiff
path: root/3rdparty/portaudio/test/patest_suggested_vs_streaminfo_latency.py
blob: 80267877a2491017f4f7844e4dadf8f6ecbf3437 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python
"""

Run and graph the results of patest_suggested_vs_streaminfo_latency.c

Requires matplotlib for plotting: http://matplotlib.sourceforge.net/

"""
import os
from pylab import *
import numpy
from matplotlib.backends.backend_pdf import PdfPages

testExeName = "PATest.exe" # rename to whatever the compiled patest_suggested_vs_streaminfo_latency.c binary is
dataFileName = "patest_suggested_vs_streaminfo_latency.csv" # code below calls the exe to generate this file

inputDeviceIndex = -1 # -1 means default
outputDeviceIndex = -1 # -1 means default
sampleRate = 44100
pdfFilenameSuffix = "_wmme"

pdfFile = PdfPages("patest_suggested_vs_streaminfo_latency_" + str(sampleRate) + pdfFilenameSuffix +".pdf") #output this pdf file


def loadCsvData( dataFileName ):
    params= ""
    inputDevice = ""
    outputDevice = ""

    startLines = file(dataFileName).readlines(1024)
    for line in startLines:
        if "output device" in line:
            outputDevice = line.strip(" \t\n\r#")
        if "input device" in line:
            inputDevice = line.strip(" \t\n\r#")
    params = startLines[0].strip(" \t\n\r#")

    data = numpy.loadtxt(dataFileName, delimiter=",", skiprows=4).transpose()

    class R(object): pass
    result = R()
    result.params = params
    for s in params.split(','):
        if "sample rate" in s:
            result.sampleRate = s

    result.inputDevice = inputDevice
    result.outputDevice = outputDevice
    result.suggestedLatency = data[0]
    result.halfDuplexOutputLatency = data[1]
    result.halfDuplexInputLatency = data[2]
    result.fullDuplexOutputLatency = data[3]
    result.fullDuplexInputLatency = data[4]
    return result;


def setFigureTitleAndAxisLabels( framesPerBufferString ):
    title("PortAudio suggested (requested) vs. resulting (reported) stream latency\n" + framesPerBufferString)
    ylabel("PaStreamInfo::{input,output}Latency (s)")
    xlabel("Pa_OpenStream suggestedLatency (s)")
    grid(True)
    legend(loc="upper left")

def setDisplayRangeSeconds( maxSeconds ):
    xlim(0, maxSeconds)
    ylim(0, maxSeconds)


# run the test with different frames per buffer values:

compositeTestFramesPerBufferValues = [0]
# powers of two
for i in range (1,11):
    compositeTestFramesPerBufferValues.append( pow(2,i) )

# multiples of 50
for i in range (1,20):
    compositeTestFramesPerBufferValues.append( i * 50 )

# 10ms buffer sizes
compositeTestFramesPerBufferValues.append( 441 )
compositeTestFramesPerBufferValues.append( 882 )

# large primes
#compositeTestFramesPerBufferValues.append( 39209 )
#compositeTestFramesPerBufferValues.append( 37537 )
#compositeTestFramesPerBufferValues.append( 26437 )

individualPlotFramesPerBufferValues = [0,64,128,256,512] #output separate plots for these

isFirst = True

for framesPerBuffer in compositeTestFramesPerBufferValues:
    commandString = testExeName + " " + str(inputDeviceIndex) + " " + str(outputDeviceIndex) + " " + str(sampleRate) + " " + str(framesPerBuffer) + ' > ' + dataFileName
    print commandString
    os.system(commandString)

    d = loadCsvData(dataFileName)

    if isFirst:
        figure(1) # title sheet
        gcf().text(0.1, 0.0,
           "patest_suggested_vs_streaminfo_latency\n%s\n%s\n%s\n"%(d.inputDevice,d.outputDevice,d.sampleRate))
        pdfFile.savefig()


    figure(2) # composite plot, includes all compositeTestFramesPerBufferValues

    if isFirst:
        plot( d.suggestedLatency, d.suggestedLatency, label="Suggested latency" )

    plot( d.suggestedLatency, d.halfDuplexOutputLatency )
    plot( d.suggestedLatency, d.halfDuplexInputLatency )
    plot( d.suggestedLatency, d.fullDuplexOutputLatency )
    plot( d.suggestedLatency, d.fullDuplexInputLatency )

    if framesPerBuffer in individualPlotFramesPerBufferValues: # individual plots
        figure( 3 + individualPlotFramesPerBufferValues.index(framesPerBuffer) )

        plot( d.suggestedLatency, d.suggestedLatency, label="Suggested latency" )
        plot( d.suggestedLatency, d.halfDuplexOutputLatency, label="Half-duplex output latency" )
        plot( d.suggestedLatency, d.halfDuplexInputLatency, label="Half-duplex input latency" )
        plot( d.suggestedLatency, d.fullDuplexOutputLatency, label="Full-duplex output latency" )
        plot( d.suggestedLatency, d.fullDuplexInputLatency, label="Full-duplex input latency" )

        if framesPerBuffer == 0:
            framesPerBufferText = "paFramesPerBufferUnspecified"
        else:
            framesPerBufferText = str(framesPerBuffer)
        setFigureTitleAndAxisLabels( "user frames per buffer: "+str(framesPerBufferText) )
        setDisplayRangeSeconds(2.2)
        pdfFile.savefig()
        setDisplayRangeSeconds(0.1)
        setFigureTitleAndAxisLabels( "user frames per buffer: "+str(framesPerBufferText)+" (detail)" )
        pdfFile.savefig()

    isFirst = False

figure(2)
setFigureTitleAndAxisLabels( "composite of frames per buffer values:\n"+str(compositeTestFramesPerBufferValues) )
setDisplayRangeSeconds(2.2)
pdfFile.savefig()
setDisplayRangeSeconds(0.1)
setFigureTitleAndAxisLabels( "composite of frames per buffer values:\n"+str(compositeTestFramesPerBufferValues)+" (detail)" )
pdfFile.savefig()

pdfFile.close()

#uncomment this to display interactively, otherwise we just output a pdf
#show()