BIQUAD.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import os.path
  2. import numpy as np
  3. import itertools
  4. import Tools
  5. from scipy import signal
  6. #from pylab import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show,semilogx, semilogy
  7. import math
  8. # Those patterns are used for tests and benchmarks.
  9. # For tests, there is the need to add tests for saturation
  10. def cartesian(*somelists):
  11. r=[]
  12. for element in itertools.product(*somelists):
  13. r.append(element)
  14. return(r)
  15. def writeBenchmarks(config):
  16. NBSAMPLES=512 # 512 for stereo
  17. NUMSTAGES = 4
  18. samples=np.random.randn(NBSAMPLES)
  19. coefs=np.random.randn(NUMSTAGES*5)
  20. samples = Tools.normalize(samples)
  21. coefs = Tools.normalize(coefs)
  22. # Used for benchmarks
  23. config.writeInput(1, samples,"Samples")
  24. config.writeInput(1, coefs,"Coefs")
  25. def getCoefs(n,sos,format):
  26. if format==15:
  27. coefs=np.reshape(np.hstack((np.insert(sos[:,:3],1,0.0,axis=1),-sos[:,4:])),n*6)
  28. else:
  29. coefs=np.reshape(np.hstack((sos[:,:3],-sos[:,4:])),n*5)
  30. if format==31:
  31. # Postshift must be 2 in the tests
  32. coefs = coefs / 4.0
  33. if format==15:
  34. # Postshift must be 2 in the tests
  35. coefs = coefs / 4.0
  36. return(coefs)
  37. def genSos(numTaps):
  38. zeros=[]
  39. poles=[]
  40. for i in range(0,numTaps):
  41. phase = np.random.rand()*2.0 * math.pi
  42. z = np.exp(1j*phase)
  43. phase = np.random.rand()*2.0 * math.pi
  44. amplitude = np.random.rand()*0.7
  45. p = np.exp(1j*phase) * amplitude
  46. zeros += [z,np.conj(z)]
  47. poles += [p,np.conj(p)]
  48. g = 0.02
  49. sos = signal.zpk2sos(zeros,poles,g)
  50. return(sos)
  51. def writeTests(config,format):
  52. # Write test with fixed and known patterns
  53. NB = 100
  54. t = np.linspace(0, 1,NB)
  55. sig = Tools.normalize(np.sin(2*np.pi*5*t)+np.random.randn(len(t)) * 0.2 + 0.4*np.sin(2*np.pi*20*t))
  56. if format==31:
  57. sig = 1.0*sig / (1 << 2)
  58. #if format==15:
  59. # sig = 1.0*sig / 2.0
  60. p0 = np.exp(1j*0.05) * 0.98
  61. p1 = np.exp(1j*0.25) * 0.9
  62. p2 = np.exp(1j*0.45) * 0.97
  63. z0 = np.exp(1j*0.02)
  64. z1 = np.exp(1j*0.65)
  65. z2 = np.exp(1j*1.0)
  66. g = 0.02
  67. sos = signal.zpk2sos(
  68. [z0,np.conj(z0),z1,np.conj(z1),z2,np.conj(z2)]
  69. ,[p0, np.conj(p0),p1, np.conj(p1),p2, np.conj(p2)]
  70. ,g)
  71. coefs=getCoefs(3,sos,format)
  72. res=signal.sosfilt(sos,sig)
  73. config.writeInput(1, sig,"BiquadInput")
  74. config.writeInput(1, res,"BiquadOutput")
  75. config.writeInput(1, coefs,"BiquadCoefs")
  76. #if format==0:
  77. # figure()
  78. # plot(sig)
  79. # figure()
  80. # plot(res)
  81. # show()
  82. # Now random patterns to test different tail sizes
  83. # and number of loops
  84. numStages = [Tools.loopnb(format,Tools.TAILONLY),
  85. Tools.loopnb(format,Tools.BODYONLY),
  86. Tools.loopnb(format,Tools.BODYANDTAIL)
  87. ]
  88. blockSize=[Tools.loopnb(format,Tools.TAILONLY),
  89. Tools.loopnb(format,Tools.BODYONLY),
  90. Tools.loopnb(format,Tools.BODYANDTAIL)
  91. ]
  92. allConfigs = cartesian(numStages, blockSize)
  93. allconf=[]
  94. allcoefs=[]
  95. allsamples=[]
  96. allStereo=[]
  97. alloutputs=[]
  98. allStereoOutputs=[]
  99. for (n,b) in allConfigs:
  100. samples=np.random.randn(b)
  101. samples = Tools.normalize(samples)
  102. samplesB=np.random.randn(b)
  103. samplesB = Tools.normalize(samplesB)
  104. stereo = np.empty((samples.size + samplesB.size,), dtype=samples.dtype)
  105. stereo[0::2] = samples
  106. stereo[1::2] = samplesB
  107. sos = genSos(n)
  108. coefs=getCoefs(n,sos,format)
  109. output=signal.sosfilt(sos,samples)
  110. outputB=signal.sosfilt(sos,samplesB)
  111. stereoOutput = np.empty((output.size + outputB.size,), dtype=output.dtype)
  112. stereoOutput[0::2] = output
  113. stereoOutput[1::2] = outputB
  114. allStereoOutputs += list(stereoOutput)
  115. alloutputs += list(output)
  116. allconf += [n,b]
  117. allcoefs += list(coefs)
  118. allsamples += list(samples)
  119. allStereo += list(stereo)
  120. config.writeReferenceS16(2,allconf,"AllBiquadConfigs")
  121. config.writeInput(2,allsamples,"AllBiquadInputs")
  122. config.writeInput(2,allcoefs,"AllBiquadCoefs")
  123. config.writeReference(2,alloutputs,"AllBiquadRefs")
  124. # Stereo version only for floats
  125. if format==0 or format==16:
  126. config.writeInput(2,allStereo,"AllBiquadStereoInputs")
  127. config.writeReference(2,allStereoOutputs,"AllBiquadStereoRefs")
  128. def generatePatterns():
  129. PATTERNDIR = os.path.join("Patterns","DSP","Filtering","BIQUAD","BIQUAD")
  130. PARAMDIR = os.path.join("Parameters","DSP","Filtering","BIQUAD","BIQUAD")
  131. configf64=Tools.Config(PATTERNDIR,PARAMDIR,"f64")
  132. configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
  133. configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16")
  134. configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31")
  135. configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15")
  136. #configq7=Tools.Config(PATTERNDIR,PARAMDIR,"q7")
  137. writeBenchmarks(configf32)
  138. writeBenchmarks(configf16)
  139. writeBenchmarks(configq31)
  140. writeBenchmarks(configq15)
  141. writeBenchmarks(configf64)
  142. writeTests(configf32,0)
  143. writeTests(configf16,16)
  144. writeTests(configq31,31)
  145. writeTests(configq15,15)
  146. writeTests(configf64,64)
  147. #writeTests(configq7)
  148. if __name__ == '__main__':
  149. generatePatterns()