acoular 24.3__py3-none-any.whl → 24.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. acoular/__init__.py +119 -54
  2. acoular/calib.py +29 -38
  3. acoular/configuration.py +132 -82
  4. acoular/demo/__init__.py +10 -4
  5. acoular/demo/acoular_demo.py +73 -55
  6. acoular/environments.py +270 -264
  7. acoular/fastFuncs.py +366 -196
  8. acoular/fbeamform.py +1797 -1934
  9. acoular/grids.py +504 -548
  10. acoular/h5cache.py +74 -83
  11. acoular/h5files.py +159 -142
  12. acoular/internal.py +13 -14
  13. acoular/microphones.py +57 -53
  14. acoular/sdinput.py +57 -53
  15. acoular/signals.py +180 -178
  16. acoular/sources.py +920 -724
  17. acoular/spectra.py +353 -363
  18. acoular/tbeamform.py +416 -416
  19. acoular/tfastfuncs.py +180 -104
  20. acoular/tools/__init__.py +25 -0
  21. acoular/tools/aiaa.py +185 -0
  22. acoular/tools/helpers.py +189 -0
  23. acoular/tools/metrics.py +165 -0
  24. acoular/tprocess.py +1240 -1182
  25. acoular/traitsviews.py +513 -501
  26. acoular/trajectory.py +50 -52
  27. acoular/version.py +5 -6
  28. acoular/xml/minidsp_uma-16.xml +20 -0
  29. acoular/xml/{minidsp_uma16.xml → minidsp_uma-16_mirrored.xml} +3 -0
  30. {acoular-24.3.dist-info → acoular-24.7.dist-info}/METADATA +58 -39
  31. acoular-24.7.dist-info/RECORD +50 -0
  32. {acoular-24.3.dist-info → acoular-24.7.dist-info}/WHEEL +1 -1
  33. acoular-24.7.dist-info/licenses/LICENSE +28 -0
  34. acoular/fileimport.py +0 -380
  35. acoular/nidaqimport.py +0 -273
  36. acoular/tests/reference_data/BeamformerBase.npy +0 -0
  37. acoular/tests/reference_data/BeamformerBaseFalse1.npy +0 -0
  38. acoular/tests/reference_data/BeamformerBaseFalse2.npy +0 -0
  39. acoular/tests/reference_data/BeamformerBaseFalse3.npy +0 -0
  40. acoular/tests/reference_data/BeamformerBaseFalse4.npy +0 -0
  41. acoular/tests/reference_data/BeamformerBaseTrue1.npy +0 -0
  42. acoular/tests/reference_data/BeamformerBaseTrue2.npy +0 -0
  43. acoular/tests/reference_data/BeamformerBaseTrue3.npy +0 -0
  44. acoular/tests/reference_data/BeamformerBaseTrue4.npy +0 -0
  45. acoular/tests/reference_data/BeamformerCMFLassoLarsBIC.npy +0 -0
  46. acoular/tests/reference_data/BeamformerCMFNNLS.npy +0 -0
  47. acoular/tests/reference_data/BeamformerCapon.npy +0 -0
  48. acoular/tests/reference_data/BeamformerClean.npy +0 -0
  49. acoular/tests/reference_data/BeamformerCleansc.npy +0 -0
  50. acoular/tests/reference_data/BeamformerCleant.npy +0 -0
  51. acoular/tests/reference_data/BeamformerCleantSq.npy +0 -0
  52. acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
  53. acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
  54. acoular/tests/reference_data/BeamformerDamas.npy +0 -0
  55. acoular/tests/reference_data/BeamformerDamasPlus.npy +0 -0
  56. acoular/tests/reference_data/BeamformerEig.npy +0 -0
  57. acoular/tests/reference_data/BeamformerEigFalse1.npy +0 -0
  58. acoular/tests/reference_data/BeamformerEigFalse2.npy +0 -0
  59. acoular/tests/reference_data/BeamformerEigFalse3.npy +0 -0
  60. acoular/tests/reference_data/BeamformerEigFalse4.npy +0 -0
  61. acoular/tests/reference_data/BeamformerEigTrue1.npy +0 -0
  62. acoular/tests/reference_data/BeamformerEigTrue2.npy +0 -0
  63. acoular/tests/reference_data/BeamformerEigTrue3.npy +0 -0
  64. acoular/tests/reference_data/BeamformerEigTrue4.npy +0 -0
  65. acoular/tests/reference_data/BeamformerFunctional.npy +0 -0
  66. acoular/tests/reference_data/BeamformerGIB.npy +0 -0
  67. acoular/tests/reference_data/BeamformerGridlessOrth.npy +0 -0
  68. acoular/tests/reference_data/BeamformerMusic.npy +0 -0
  69. acoular/tests/reference_data/BeamformerOrth.npy +0 -0
  70. acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
  71. acoular/tests/reference_data/BeamformerTime.npy +0 -0
  72. acoular/tests/reference_data/BeamformerTimeSq.npy +0 -0
  73. acoular/tests/reference_data/BeamformerTimeSqTraj.npy +0 -0
  74. acoular/tests/reference_data/BeamformerTimeTraj.npy +0 -0
  75. acoular/tests/reference_data/Environment.npy +0 -0
  76. acoular/tests/reference_data/Example1_numerical_values_testsum.h5 +0 -0
  77. acoular/tests/reference_data/FiltFiltOctave__.npy +0 -0
  78. acoular/tests/reference_data/FiltFiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
  79. acoular/tests/reference_data/FiltFreqWeight_weight_A_.npy +0 -0
  80. acoular/tests/reference_data/FiltFreqWeight_weight_C_.npy +0 -0
  81. acoular/tests/reference_data/FiltFreqWeight_weight_Z_.npy +0 -0
  82. acoular/tests/reference_data/FiltOctave__.npy +0 -0
  83. acoular/tests/reference_data/FiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
  84. acoular/tests/reference_data/Filter__.npy +0 -0
  85. acoular/tests/reference_data/GeneralFlowEnvironment.npy +0 -0
  86. acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
  87. acoular/tests/reference_data/OpenJet.npy +0 -0
  88. acoular/tests/reference_data/PointSource.npy +0 -0
  89. acoular/tests/reference_data/PowerSpectra_csm.npy +0 -0
  90. acoular/tests/reference_data/PowerSpectra_ev.npy +0 -0
  91. acoular/tests/reference_data/RotatingFlow.npy +0 -0
  92. acoular/tests/reference_data/SlotJet.npy +0 -0
  93. acoular/tests/reference_data/TimeAverage__.npy +0 -0
  94. acoular/tests/reference_data/TimeCumAverage__.npy +0 -0
  95. acoular/tests/reference_data/TimeExpAverage_weight_F_.npy +0 -0
  96. acoular/tests/reference_data/TimeExpAverage_weight_I_.npy +0 -0
  97. acoular/tests/reference_data/TimeExpAverage_weight_S_.npy +0 -0
  98. acoular/tests/reference_data/TimeInOut__.npy +0 -0
  99. acoular/tests/reference_data/TimePower__.npy +0 -0
  100. acoular/tests/reference_data/TimeReverse__.npy +0 -0
  101. acoular/tests/reference_data/UniformFlowEnvironment.npy +0 -0
  102. acoular/tests/reference_data/beamformer_traj_time_data.h5 +0 -0
  103. acoular/tests/run_tests.sh +0 -18
  104. acoular/tests/run_tests_osx.sh +0 -16
  105. acoular/tests/test.npy +0 -0
  106. acoular/tests/test_beamformer_results.py +0 -213
  107. acoular/tests/test_classes.py +0 -60
  108. acoular/tests/test_digest.py +0 -125
  109. acoular/tests/test_environments.py +0 -73
  110. acoular/tests/test_example1.py +0 -124
  111. acoular/tests/test_grid.py +0 -92
  112. acoular/tests/test_integrate.py +0 -102
  113. acoular/tests/test_signals.py +0 -60
  114. acoular/tests/test_sources.py +0 -65
  115. acoular/tests/test_spectra.py +0 -38
  116. acoular/tests/test_timecache.py +0 -35
  117. acoular/tests/test_tprocess.py +0 -90
  118. acoular/tests/test_traj_beamformer_results.py +0 -164
  119. acoular/tests/unsupported/SpeedComparison/OvernightTestcasesBeamformer_nMics32_nGridPoints100_nFreqs4_nTrials10.png +0 -0
  120. acoular/tests/unsupported/SpeedComparison/cythonBeamformer.pyx +0 -237
  121. acoular/tests/unsupported/SpeedComparison/mainForCython.py +0 -103
  122. acoular/tests/unsupported/SpeedComparison/mainForParallelJit.py +0 -143
  123. acoular/tests/unsupported/SpeedComparison/setupCythonOpenMP.py +0 -63
  124. acoular/tests/unsupported/SpeedComparison/sharedFunctions.py +0 -153
  125. acoular/tests/unsupported/SpeedComparison/timeOverNMics_AllImportantMethods.png +0 -0
  126. acoular/tests/unsupported/SpeedComparison/timeOverNMics_faverage.png +0 -0
  127. acoular/tests/unsupported/SpeedComparison/vglOptimierungFAverage.py +0 -204
  128. acoular/tests/unsupported/SpeedComparison/vglOptimierungGaussSeidel.py +0 -182
  129. acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAMFULL_INVERSE.py +0 -764
  130. acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAM_OS.py +0 -231
  131. acoular/tests/unsupported/SpeedComparison/whatsFastestWayFor_absASquared.py +0 -48
  132. acoular/tests/unsupported/functionalBeamformer.py +0 -123
  133. acoular/tests/unsupported/precisionTest.py +0 -153
  134. acoular/tests/unsupported/validationOfBeamformerFuncsPOSTAcoularIntegration.py +0 -254
  135. acoular/tests/unsupported/validationOfBeamformerFuncsPREeAcoularIntegration.py +0 -531
  136. acoular/tools.py +0 -422
  137. acoular-24.3.dist-info/RECORD +0 -148
  138. acoular-24.3.dist-info/licenses/LICENSE +0 -29
  139. {acoular-24.3.dist-info → acoular-24.7.dist-info}/licenses/AUTHORS.rst +0 -0
acoular/microphones.py CHANGED
@@ -1,9 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
- #pylint: disable-msg=E0611, E1103, C0103, R0901, R0902, R0903, R0904, W0232
3
- #------------------------------------------------------------------------------
1
+ # ------------------------------------------------------------------------------
4
2
  # Copyright (c) Acoular Development Team.
5
- #------------------------------------------------------------------------------
6
- """Implements support for array microphone arrangements
3
+ # ------------------------------------------------------------------------------
4
+ """Implements support for array microphone arrangements.
7
5
 
8
6
  .. autosummary::
9
7
  :toctree: generated/
@@ -13,108 +11,97 @@
13
11
  """
14
12
 
15
13
  # imports from other packages
16
- from numpy import array, average
17
- from scipy.spatial.distance import cdist
18
- from traits.api import HasPrivateTraits, Property, File, \
19
- CArray, cached_property, on_trait_change, ListInt , Bool
20
- from os import path, strerror
21
14
  import errno
15
+ from os import path, strerror
16
+
17
+ from numpy import array, average
18
+ from scipy.spatial.distance import cdist
19
+ from traits.api import Bool, CArray, File, HasPrivateTraits, ListInt, Property, cached_property, on_trait_change
22
20
 
23
21
  from .internal import digest
24
22
 
25
23
 
26
- class MicGeom( HasPrivateTraits ):
27
- """
28
- Provides the geometric arrangement of microphones in the array.
29
-
30
- The geometric arrangement of microphones is read in from an
31
- xml-source with element tag names `pos` and attributes Name, `x`, `y` and `z`.
24
+ class MicGeom(HasPrivateTraits):
25
+ """Provides the geometric arrangement of microphones in the array.
26
+
27
+ The geometric arrangement of microphones is read in from an
28
+ xml-source with element tag names `pos` and attributes Name, `x`, `y` and `z`.
32
29
  Can also be used with programmatically generated arrangements.
33
30
  """
34
31
 
35
32
  #: Name of the .xml-file from wich to read the data.
36
- from_file = File(filter=['*.xml'],
37
- desc="name of the xml file to import")
33
+ from_file = File(filter=['*.xml'], desc='name of the xml file to import')
38
34
 
39
35
  #: Validate mic geom from file
40
- validate_file = Bool(True,
41
- desc="Validate mic geom from file")
36
+ validate_file = Bool(True, desc='Validate mic geom from file')
42
37
 
43
38
  #: Basename of the .xml-file, without the extension; is set automatically / readonly.
44
- basename = Property( depends_on = 'from_file',
45
- desc="basename of xml file")
39
+ basename = Property(depends_on='from_file', desc='basename of xml file')
46
40
 
47
41
  #: List that gives the indices of channels that should not be considered.
48
42
  #: Defaults to a blank list.
49
- invalid_channels = ListInt(
50
- desc="list of invalid channels")
43
+ invalid_channels = ListInt(desc='list of invalid channels')
51
44
 
52
45
  #: Number of microphones in the array; readonly.
53
- num_mics = Property( depends_on = ['mpos', ],
54
- desc="number of microphones in the geometry")
46
+ num_mics = Property(depends_on=['mpos'], desc='number of microphones in the geometry')
55
47
 
56
48
  #: Center of the array (arithmetic mean of all used array positions); readonly.
57
- center = Property( depends_on = ['mpos', ],
58
- desc="array center")
49
+ center = Property(depends_on=['mpos'], desc='array center')
59
50
 
60
51
  #: Aperture of the array (greatest extent between two microphones); readonly.
61
- aperture = Property( depends_on = ['mpos', ],
62
- desc="array aperture")
52
+ aperture = Property(depends_on=['mpos'], desc='array aperture')
63
53
 
64
54
  #: Positions as (3, :attr:`num_mics`) array of floats, may include also invalid
65
55
  #: microphones (if any). Set either automatically on change of the
66
56
  #: :attr:`from_file` argument or explicitely by assigning an array of floats.
67
- mpos_tot = CArray(dtype=float,
68
- desc="x, y, z position of all microphones")
57
+ mpos_tot = CArray(dtype=float, desc='x, y, z position of all microphones')
69
58
 
70
59
  #: Positions as (3, :attr:`num_mics`) array of floats, without invalid
71
60
  #: microphones; readonly.
72
- mpos = Property( depends_on = ['mpos_tot', 'invalid_channels'],
73
- desc="x, y, z position of microphones")
61
+ mpos = Property(depends_on=['mpos_tot', 'invalid_channels'], desc='x, y, z position of microphones')
74
62
 
75
63
  # internal identifier
76
- digest = Property( depends_on = ['mpos', ])
64
+ digest = Property(depends_on=['mpos'])
77
65
 
78
66
  @cached_property
79
- def _get_digest( self ):
67
+ def _get_digest(self):
80
68
  return digest(self)
81
69
 
82
70
  @cached_property
83
- def _get_basename( self ):
71
+ def _get_basename(self):
84
72
  return path.splitext(path.basename(self.from_file))[0]
85
73
 
86
74
  @cached_property
87
- def _get_mpos( self ):
75
+ def _get_mpos(self):
88
76
  if self.validate_file:
89
- if len(self.invalid_channels)==0:
77
+ if len(self.invalid_channels) == 0:
90
78
  return self.mpos_tot
91
- allr=[i for i in range(self.mpos_tot.shape[-1]) if i not in self.invalid_channels]
79
+ allr = [i for i in range(self.mpos_tot.shape[-1]) if i not in self.invalid_channels]
92
80
  return self.mpos_tot[:, array(allr)]
93
- else:
94
- raise FileNotFoundError(
95
- errno.ENOENT, strerror(errno.ENOENT), self.from_file)
81
+ raise FileNotFoundError(errno.ENOENT, strerror(errno.ENOENT), self.from_file)
96
82
 
97
83
  @cached_property
98
- def _get_num_mics( self ):
84
+ def _get_num_mics(self):
99
85
  return self.mpos.shape[-1]
100
86
 
101
87
  @cached_property
102
- def _get_center( self ):
88
+ def _get_center(self):
103
89
  if self.mpos.any():
104
- center = average(self.mpos,axis=1)
90
+ center = average(self.mpos, axis=1)
105
91
  # set very small values to zero
106
- center[abs(center) < 1e-16] = 0.
92
+ center[abs(center) < 1e-16] = 0.0
107
93
  return center
94
+ return None
108
95
 
109
96
  @cached_property
110
- def _get_aperture( self ):
97
+ def _get_aperture(self):
111
98
  if self.mpos.any():
112
- return cdist(self.mpos.T,self.mpos.T).max()
99
+ return cdist(self.mpos.T, self.mpos.T).max()
100
+ return None
113
101
 
114
102
  @on_trait_change('basename')
115
- def import_mpos( self ):
116
- """
117
- Import the microphone positions from .xml file.
103
+ def import_mpos(self):
104
+ """Import the microphone positions from .xml file.
118
105
  Called when :attr:`basename` changes.
119
106
  """
120
107
  if not path.isfile(self.from_file):
@@ -124,12 +111,29 @@ class MicGeom( HasPrivateTraits ):
124
111
  self.validate_file = False
125
112
 
126
113
  import xml.dom.minidom
114
+
127
115
  doc = xml.dom.minidom.parse(self.from_file)
128
116
  names = []
129
117
  xyz = []
130
118
  for el in doc.getElementsByTagName('pos'):
131
119
  names.append(el.getAttribute('Name'))
132
- xyz.append(list(map(lambda a : float(el.getAttribute(a)), 'xyz')))
120
+ xyz.append([float(el.getAttribute(a)) for a in 'xyz'])
133
121
  self.mpos_tot = array(xyz, 'd').swapaxes(0, 1)
134
122
  self.validate_file = True
135
123
 
124
+ def export_mpos(self, filename):
125
+ """Export the microphone positions to .xml file.
126
+
127
+ Parameters
128
+ ----------
129
+ filename : str
130
+ Name of the file to which the microphone positions are written.
131
+ """
132
+ basename = path.splitext(path.basename(filename))[0]
133
+ with open(filename, 'w') as f:
134
+ f.write(f'<?xml version="1.1" encoding="utf-8"?><MicArray name="{basename}">\n')
135
+ for i in range(self.mpos.shape[-1]):
136
+ f.write(
137
+ f' <pos Name="Point {i+1}" x="{self.mpos[0, i]}" y="{self.mpos[1, i]}" z="{self.mpos[2, i]}"/>\n',
138
+ )
139
+ f.write('</MicArray>')
acoular/sdinput.py CHANGED
@@ -1,118 +1,122 @@
1
- # -*- coding: utf-8 -*-
2
- #pylint: disable-msg=E0611, E1101, C0103, R0901, R0902, R0903, R0904, W0232
3
- #------------------------------------------------------------------------------
1
+ # ------------------------------------------------------------------------------
4
2
  # Copyright (c) Acoular Development Team.
5
- #------------------------------------------------------------------------------
6
- """ Input from soundcard hardware using the SoundDevice library
3
+ # ------------------------------------------------------------------------------
4
+ """Input from soundcard hardware using the SoundDevice library.
7
5
 
8
6
  .. autosummary::
9
7
  :toctree: generated/
10
8
 
11
9
  SoundDeviceSamplesGenerator
12
10
  """
13
- import sounddevice as sd
14
- from traits.api import Int, Long, Bool, Property, Any, observe, cached_property
15
- from .tprocess import SamplesGenerator
11
+
12
+ from traits.api import Any, Bool, Int, Long, Property, cached_property, observe
13
+
14
+ from .configuration import config
16
15
  from .internal import digest
16
+ from .tprocess import SamplesGenerator
17
17
 
18
- class SoundDeviceSamplesGenerator(SamplesGenerator):
18
+ if config.have_sounddevice:
19
+ import sounddevice as sd
19
20
 
20
- """
21
- Controller for sound card hardware using sounddevice library
21
+
22
+ class SoundDeviceSamplesGenerator(SamplesGenerator):
23
+ """Controller for sound card hardware using sounddevice library.
22
24
 
23
25
  Uses the device with index :attr:`device` to read samples
24
26
  from input stream, generates output stream via the generator
25
27
  :meth:`result`.
26
28
  """
27
29
 
30
+ def __init__(self, *args, **kwargs):
31
+ super().__init__(*args, **kwargs)
32
+ if config.have_sounddevice is False:
33
+ msg = 'SoundDevice library not found but is required for using the SoundDeviceSamplesGenerator class.'
34
+ raise ImportError(msg)
35
+
28
36
  #: input device index, refers to sounddevice list
29
- device = Int(0, desc="input device index")
37
+ device = Int(0, desc='input device index')
30
38
 
31
39
  #: Number of input channels, maximum depends on device
32
- numchannels = Long(1,
33
- desc="number of analog input channels that collects data")
40
+ numchannels = Long(1, desc='number of analog input channels that collects data')
34
41
 
35
42
  #: Number of samples to collect; defaults to -1.
36
43
  # If is set to -1 device collects till user breaks streaming by setting Trait: collectsamples = False
37
- numsamples = Long(-1,
38
- desc="number of samples to collect")
44
+ numsamples = Long(-1, desc='number of samples to collect')
39
45
 
40
46
  #: Indicates if samples are collected, helper trait to break result loop
41
- collectsamples = Bool(True,
42
- desc="Indicates if samples are collected")
47
+ collectsamples = Bool(True, desc='Indicates if samples are collected')
43
48
 
44
49
  #: Sampling frequency of the signal, changes with sinusdevices
45
- sample_freq = Property(
46
- desc="sampling frequency")
50
+ sample_freq = Property(desc='sampling frequency')
47
51
 
48
52
  #: Indicates that the sounddevice buffer has overflown
49
- overflow = Bool(False,
50
- desc="Indicates if sounddevice buffer overflow")
53
+ overflow = Bool(False, desc='Indicates if sounddevice buffer overflow')
51
54
 
52
55
  #: Indicates that the stream is collecting samples
53
- running = Bool(False,
54
- desc="Indicates that the stream is collecting samples")
56
+ running = Bool(False, desc='Indicates that the stream is collecting samples')
55
57
 
56
58
  #: The sounddevice InputStream object for inspection
57
59
  stream = Any
58
60
 
59
61
  # internal identifier
60
- digest = Property( depends_on=['device', 'numchannels', 'numsamples'])
61
-
62
+ digest = Property(depends_on=['device', 'numchannels', 'numsamples'])
63
+
62
64
  @cached_property
63
- def _get_digest( self ):
65
+ def _get_digest(self):
64
66
  return digest(self)
65
67
 
66
68
  # checks that numchannels are not more than device can provide
67
69
  @observe('device,numchannels')
68
- def _get_numchannels( self, change ):
69
- self.numchannels = min(self.numchannels,sd.query_devices(self.device)['max_input_channels'])
70
+ def _get_numchannels(self, event): # noqa ARG002
71
+ self.numchannels = min(self.numchannels, sd.query_devices(self.device)['max_input_channels'])
70
72
 
71
- def _get_sample_freq( self ):
73
+ def _get_sample_freq(self):
72
74
  return sd.query_devices(self.device)['default_samplerate']
73
75
 
74
- def device_properties( self ):
75
- """
76
- Returns
76
+ def device_properties(self):
77
+ """Returns
77
78
  -------
78
79
  Dictionary of device properties according to sounddevice
79
80
  """
80
81
  return sd.query_devices(self.device)
81
82
 
82
83
  def result(self, num):
83
- """
84
- Python generator that yields the output block-wise. Use at least a
85
- block-size of one ring cache block.
86
-
84
+ """Python generator that yields the output block-wise. Use at least a
85
+ block-size of one ring cache block.
86
+
87
87
  Parameters
88
88
  ----------
89
89
  num : integer
90
90
  This parameter defines the size of the blocks to be yielded
91
91
  (i.e. the number of samples per block).
92
-
92
+
93
93
  Returns
94
94
  -------
95
- Samples in blocks of shape (num, :attr:`numchannels`).
95
+ Samples in blocks of shape (num, :attr:`numchannels`).
96
96
  The last block may be shorter than num.
97
+
97
98
  """
98
- print(self.device_properties(),self.sample_freq)
99
+ print(self.device_properties(), self.sample_freq)
99
100
  self.stream = stream_obj = sd.InputStream(
100
- device=self.device, channels=self.numchannels,
101
- clip_off=True, samplerate=self.sample_freq)
101
+ device=self.device,
102
+ channels=self.numchannels,
103
+ clip_off=True,
104
+ samplerate=self.sample_freq,
105
+ )
102
106
 
103
107
  with stream_obj as stream:
104
108
  self.running = True
105
- if self.numsamples == -1:
106
- while self.collectsamples: # yield data as long as collectsamples is True
107
- data,self.overflow = stream.read(num)
108
- yield data[:num]
109
-
110
- elif self.numsamples > 0: # amount of samples to collect is specified by user
111
- samples_count = 0 # numsamples counter
112
- while samples_count < self.numsamples:
113
- anz = min(num, self.numsamples-samples_count)
109
+ if self.numsamples == -1:
110
+ while self.collectsamples: # yield data as long as collectsamples is True
111
+ data, self.overflow = stream.read(num)
112
+ yield data[:num]
113
+
114
+ elif self.numsamples > 0: # amount of samples to collect is specified by user
115
+ samples_count = 0 # numsamples counter
116
+ while samples_count < self.numsamples:
117
+ anz = min(num, self.numsamples - samples_count)
114
118
  data, self.overflow = stream.read(num)
115
- yield data[:anz]
119
+ yield data[:anz]
116
120
  samples_count += anz
117
121
  self.running = False
118
- return
122
+ return