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