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