cannam@89: #!/usr/bin/env python cannam@89: """ cannam@89: cannam@89: Run and graph the results of patest_suggested_vs_streaminfo_latency.c cannam@89: cannam@89: Requires matplotlib for plotting: http://matplotlib.sourceforge.net/ cannam@89: cannam@89: """ cannam@89: import os cannam@89: from pylab import * cannam@89: import numpy cannam@89: from matplotlib.backends.backend_pdf import PdfPages cannam@89: cannam@89: testExeName = "PATest.exe" # rename to whatever the compiled patest_suggested_vs_streaminfo_latency.c binary is cannam@89: dataFileName = "patest_suggested_vs_streaminfo_latency.csv" # code below calls the exe to generate this file cannam@89: cannam@89: inputDeviceIndex = -1 # -1 means default cannam@89: outputDeviceIndex = -1 # -1 means default cannam@89: sampleRate = 44100 cannam@89: pdfFilenameSuffix = "_wmme" cannam@89: cannam@89: pdfFile = PdfPages("patest_suggested_vs_streaminfo_latency_" + str(sampleRate) + pdfFilenameSuffix +".pdf") #output this pdf file cannam@89: cannam@89: cannam@89: def loadCsvData( dataFileName ): cannam@89: params= "" cannam@89: inputDevice = "" cannam@89: outputDevice = "" cannam@89: cannam@89: startLines = file(dataFileName).readlines(1024) cannam@89: for line in startLines: cannam@89: if "output device" in line: cannam@89: outputDevice = line.strip(" \t\n\r#") cannam@89: if "input device" in line: cannam@89: inputDevice = line.strip(" \t\n\r#") cannam@89: params = startLines[0].strip(" \t\n\r#") cannam@89: cannam@89: data = numpy.loadtxt(dataFileName, delimiter=",", skiprows=4).transpose() cannam@89: cannam@89: class R(object): pass cannam@89: result = R() cannam@89: result.params = params cannam@89: for s in params.split(','): cannam@89: if "sample rate" in s: cannam@89: result.sampleRate = s cannam@89: cannam@89: result.inputDevice = inputDevice cannam@89: result.outputDevice = outputDevice cannam@89: result.suggestedLatency = data[0] cannam@89: result.halfDuplexOutputLatency = data[1] cannam@89: result.halfDuplexInputLatency = data[2] cannam@89: result.fullDuplexOutputLatency = data[3] cannam@89: result.fullDuplexInputLatency = data[4] cannam@89: return result; cannam@89: cannam@89: cannam@89: def setFigureTitleAndAxisLabels( framesPerBufferString ): cannam@89: title("PortAudio suggested (requested) vs. resulting (reported) stream latency\n" + framesPerBufferString) cannam@89: ylabel("PaStreamInfo::{input,output}Latency (s)") cannam@89: xlabel("Pa_OpenStream suggestedLatency (s)") cannam@89: grid(True) cannam@89: legend(loc="upper left") cannam@89: cannam@89: def setDisplayRangeSeconds( maxSeconds ): cannam@89: xlim(0, maxSeconds) cannam@89: ylim(0, maxSeconds) cannam@89: cannam@89: cannam@89: # run the test with different frames per buffer values: cannam@89: cannam@89: compositeTestFramesPerBufferValues = [0] cannam@89: # powers of two cannam@89: for i in range (1,11): cannam@89: compositeTestFramesPerBufferValues.append( pow(2,i) ) cannam@89: cannam@89: # multiples of 50 cannam@89: for i in range (1,20): cannam@89: compositeTestFramesPerBufferValues.append( i * 50 ) cannam@89: cannam@89: # 10ms buffer sizes cannam@89: compositeTestFramesPerBufferValues.append( 441 ) cannam@89: compositeTestFramesPerBufferValues.append( 882 ) cannam@89: cannam@89: # large primes cannam@89: #compositeTestFramesPerBufferValues.append( 39209 ) cannam@89: #compositeTestFramesPerBufferValues.append( 37537 ) cannam@89: #compositeTestFramesPerBufferValues.append( 26437 ) cannam@89: cannam@89: individualPlotFramesPerBufferValues = [0,64,128,256,512] #output separate plots for these cannam@89: cannam@89: isFirst = True cannam@89: cannam@89: for framesPerBuffer in compositeTestFramesPerBufferValues: cannam@89: commandString = testExeName + " " + str(inputDeviceIndex) + " " + str(outputDeviceIndex) + " " + str(sampleRate) + " " + str(framesPerBuffer) + ' > ' + dataFileName cannam@89: print commandString cannam@89: os.system(commandString) cannam@89: cannam@89: d = loadCsvData(dataFileName) cannam@89: cannam@89: if isFirst: cannam@89: figure(1) # title sheet cannam@89: gcf().text(0.1, 0.0, cannam@89: "patest_suggested_vs_streaminfo_latency\n%s\n%s\n%s\n"%(d.inputDevice,d.outputDevice,d.sampleRate)) cannam@89: pdfFile.savefig() cannam@89: cannam@89: cannam@89: figure(2) # composite plot, includes all compositeTestFramesPerBufferValues cannam@89: cannam@89: if isFirst: cannam@89: plot( d.suggestedLatency, d.suggestedLatency, label="Suggested latency" ) cannam@89: cannam@89: plot( d.suggestedLatency, d.halfDuplexOutputLatency ) cannam@89: plot( d.suggestedLatency, d.halfDuplexInputLatency ) cannam@89: plot( d.suggestedLatency, d.fullDuplexOutputLatency ) cannam@89: plot( d.suggestedLatency, d.fullDuplexInputLatency ) cannam@89: cannam@89: if framesPerBuffer in individualPlotFramesPerBufferValues: # individual plots cannam@89: figure( 3 + individualPlotFramesPerBufferValues.index(framesPerBuffer) ) cannam@89: cannam@89: plot( d.suggestedLatency, d.suggestedLatency, label="Suggested latency" ) cannam@89: plot( d.suggestedLatency, d.halfDuplexOutputLatency, label="Half-duplex output latency" ) cannam@89: plot( d.suggestedLatency, d.halfDuplexInputLatency, label="Half-duplex input latency" ) cannam@89: plot( d.suggestedLatency, d.fullDuplexOutputLatency, label="Full-duplex output latency" ) cannam@89: plot( d.suggestedLatency, d.fullDuplexInputLatency, label="Full-duplex input latency" ) cannam@89: cannam@89: if framesPerBuffer == 0: cannam@89: framesPerBufferText = "paFramesPerBufferUnspecified" cannam@89: else: cannam@89: framesPerBufferText = str(framesPerBuffer) cannam@89: setFigureTitleAndAxisLabels( "user frames per buffer: "+str(framesPerBufferText) ) cannam@89: setDisplayRangeSeconds(2.2) cannam@89: pdfFile.savefig() cannam@89: setDisplayRangeSeconds(0.1) cannam@89: setFigureTitleAndAxisLabels( "user frames per buffer: "+str(framesPerBufferText)+" (detail)" ) cannam@89: pdfFile.savefig() cannam@89: cannam@89: isFirst = False cannam@89: cannam@89: figure(2) cannam@89: setFigureTitleAndAxisLabels( "composite of frames per buffer values:\n"+str(compositeTestFramesPerBufferValues) ) cannam@89: setDisplayRangeSeconds(2.2) cannam@89: pdfFile.savefig() cannam@89: setDisplayRangeSeconds(0.1) cannam@89: setFigureTitleAndAxisLabels( "composite of frames per buffer values:\n"+str(compositeTestFramesPerBufferValues)+" (detail)" ) cannam@89: pdfFile.savefig() cannam@89: cannam@89: pdfFile.close() cannam@89: cannam@89: #uncomment this to display interactively, otherwise we just output a pdf cannam@89: #show()