151 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			151 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								#!/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()
							 |