PyQa40x-i2c 0.2.0__tar.gz → 0.2.2__tar.gz

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 (65) hide show
  1. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/PKG-INFO +1 -1
  2. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/RELEASE_NOTES.md +8 -0
  3. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/_version.py +3 -3
  4. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/analyzer.py +128 -4
  5. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/control.py +1 -1
  6. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/stream.py +24 -3
  7. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/wave.py +1 -1
  8. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x_i2c.egg-info/PKG-INFO +1 -1
  9. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x_i2c.egg-info/scm_file_list.json +32 -32
  10. pyqa40x_i2c-0.2.2/src/PyQa40x_i2c.egg-info/scm_version.json +8 -0
  11. pyqa40x_i2c-0.2.0/src/PyQa40x_i2c.egg-info/scm_version.json +0 -8
  12. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/.github/workflows/code_checker.yml +0 -0
  13. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/.github/workflows/publish_package.yml +0 -0
  14. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/.github/workflows/unit_tests.yml +0 -0
  15. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/.gitignore +0 -0
  16. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/.pylint_ignore +0 -0
  17. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LICENSE +0 -0
  18. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/FirstPrinciples.py +0 -0
  19. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_acoustic_chirp_spl_bt.py +0 -0
  20. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_acoustic_dbspl.py +0 -0
  21. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_acoustic_energy_decay_bt.py +0 -0
  22. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_coherent_averaging.py +0 -0
  23. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_cross_correlation.py +0 -0
  24. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_freq_response_with_mask.py +0 -0
  25. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_pinknoise.py +0 -0
  26. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/PyQa40x_thdn.py +0 -0
  27. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/mask_freq.txt +0 -0
  28. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/LibTest/mask_phase.txt +0 -0
  29. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/MANIFEST.in +0 -0
  30. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/README.md +0 -0
  31. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/_ci/is_dev_version.sh +0 -0
  32. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/pyproject.toml +0 -0
  33. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/requirements-dev.txt +0 -0
  34. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/requirements-test.txt +0 -0
  35. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/requirements.txt +0 -0
  36. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/setup.cfg +0 -0
  37. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/__init__.py +0 -0
  38. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/analyzer_params.py +0 -0
  39. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/bluetooth.py +0 -0
  40. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/cross_correlation.py +0 -0
  41. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/fft_processor.py +0 -0
  42. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/freq_series_plotter.py +0 -0
  43. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/helpers.py +0 -0
  44. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/math_chirp.py +0 -0
  45. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/math_energy.py +0 -0
  46. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/math_general.py +0 -0
  47. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/math_sines.py +0 -0
  48. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/math_windows.py +0 -0
  49. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/registers.py +0 -0
  50. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/series_plotter.py +0 -0
  51. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/sig_proc.py +0 -0
  52. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/wave_chirp.py +0 -0
  53. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x/wave_sine.py +0 -0
  54. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x.egg-info/PKG-INFO +0 -0
  55. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x.egg-info/SOURCES.txt +0 -0
  56. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x.egg-info/dependency_links.txt +0 -0
  57. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x.egg-info/requires.txt +0 -0
  58. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x.egg-info/top_level.txt +0 -0
  59. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x_i2c.egg-info/SOURCES.txt +0 -0
  60. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x_i2c.egg-info/dependency_links.txt +0 -0
  61. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x_i2c.egg-info/requires.txt +0 -0
  62. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/src/PyQa40x_i2c.egg-info/top_level.txt +0 -0
  63. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/tests/__init__.py +0 -0
  64. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/tests/test_template.py +0 -0
  65. {pyqa40x_i2c-0.2.0 → pyqa40x_i2c-0.2.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyQa40x-i2c
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: A Python library for the QA40x audio analyser (int2code fork)
5
5
  Maintainer-email: Hubert Stepniewski <hubert.stepniewski@int2code.com>
6
6
  License: MIT License
@@ -1,3 +1,11 @@
1
+ ### 0.2.2
2
+
3
+ [PATCH] Allow reliable streaming for higher sample rates (`96kHz`, `192kHz`).
4
+
5
+ ### 0.2.1
6
+
7
+ [PATCH] Restore removed `Analyzer.send_receive` functionality.
8
+
1
9
  ### 0.2.0
2
10
 
3
11
  [MINOR] Add endless audio capturing
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.0'
22
- __version_tuple__ = version_tuple = (0, 2, 0)
21
+ __version__ = version = '0.2.2'
22
+ __version_tuple__ = version_tuple = (0, 2, 2)
23
23
 
24
- __commit_id__ = commit_id = 'g6a5ba3357'
24
+ __commit_id__ = commit_id = 'gf75dc49b9'
@@ -1,5 +1,6 @@
1
1
  import threading
2
2
  import logging
3
+ import struct
3
4
 
4
5
  import numpy as np
5
6
  import usb1 # pip install libusb1
@@ -11,13 +12,20 @@ from PyQa40x.stream import Stream
11
12
  from PyQa40x.helpers import *
12
13
  from PyQa40x.analyzer_params import AnalyzerParams
13
14
  from PyQa40x.bluetooth import BluetoothAudioDevice
15
+ from PyQa40x.wave_sine import Wave
14
16
 
15
17
  logger = logging.getLogger(__name__)
16
18
 
19
+ # Sample rate Hz vs bytes per USB transfer
20
+ TRANSFER_BYTES_MAP = {
21
+ 44100: Stream.DEFAULT_TRANSFER_BYTES,
22
+ 48000: Stream.DEFAULT_TRANSFER_BYTES,
23
+ 96000: 32768,
24
+ 192000: 65536,
25
+ }
17
26
 
18
- class Analyzer:
19
27
 
20
- CAPTURE_CHUNK_BYTES = Stream.TRANSFER_BYTES # bytes per USB transfer
28
+ class Analyzer:
21
29
 
22
30
  def __init__(self):
23
31
  """
@@ -25,6 +33,7 @@ class Analyzer:
25
33
  """
26
34
  self.params: AnalyzerParams | None = None
27
35
  self.context: usb1.USBContext | None = None
36
+ self.chunk_size: int | None = None
28
37
  self.device: usb1.USBDeviceHandle | None = None
29
38
  self.registers: Registers | None = None
30
39
  self.control: Control | None = None
@@ -78,6 +87,7 @@ class Analyzer:
78
87
  )
79
88
  self.context = usb1.USBContext()
80
89
  self.context.open()
90
+ self.chunk_size = TRANSFER_BYTES_MAP.get(sample_rate, Stream.DEFAULT_TRANSFER_BYTES)
81
91
 
82
92
  # Attempt to open QA402 or QA403 device
83
93
  self.device = self.context.openByVendorIDAndProductID(0x16C0, 0x4E37) # QA402
@@ -92,7 +102,7 @@ class Analyzer:
92
102
 
93
103
  self.registers = Registers(self.device)
94
104
  self.control = Control(self.registers)
95
- self.stream = Stream(self.context, self.device, self.registers)
105
+ self.stream = Stream(self.context, self.device, self.registers, self.chunk_size)
96
106
 
97
107
  # Load calibration data
98
108
  self.cal_data = self.control.load_calibration()
@@ -212,7 +222,7 @@ class Analyzer:
212
222
  """Continuously submit zero-DAC / ADC-read transfer pairs while capturing."""
213
223
  while self._capturing and self.stream.running:
214
224
  try:
215
- self.stream.write_zeros(self.CAPTURE_CHUNK_BYTES)
225
+ self.stream.write_zeros(self.chunk_size)
216
226
  except Exception as exc: # pylint: disable=broad-except
217
227
  # Racing with stop() is expected; a real failure while we still
218
228
  # expect to run is recorded in the post-loop reconciliation below.
@@ -277,6 +287,120 @@ class Analyzer:
277
287
  if self._dac_writer is not None:
278
288
  self._dac_writer.join(timeout=5.0)
279
289
 
290
+ def send_receive(self, left_wave: Wave, right_wave: Wave) -> tuple[Wave, Wave]:
291
+ """
292
+ Sends DAC data to the device and receives ADC data.
293
+
294
+ Args:
295
+ left_wave (Wave): Wave instance with left channel DAC data.
296
+ right_wave (Wave): Wave instance with right channel DAC data.
297
+
298
+ Returns:
299
+ tuple[Wave, Wave]: Tuple containing Wave instances with left and right channel ADC data.
300
+ """
301
+ left_dac_data = left_wave.get_buffer()
302
+ right_dac_data = right_wave.get_buffer()
303
+
304
+ # On QA402 and QA403, outputs need to be swapped
305
+ left_dac_data, right_dac_data = right_dac_data, left_dac_data
306
+
307
+ left_peak = np.max(left_dac_data)
308
+
309
+ # Get calibration factors for outgoing data
310
+ cal_dac_left, cal_dac_right = self.control.get_dac_cal(
311
+ self.cal_data, self.params.max_output_level
312
+ )
313
+
314
+ # Convert to dBFS. Note the 3 dB adjustment--dBFS is peak, while dBV is RMS
315
+ dac_dbfs_adjustment = 10 ** -((self.params.max_output_level + 3) / 20)
316
+
317
+ # Apply calibration and dBFS scaling
318
+ left_dac_data = left_dac_data * dac_dbfs_adjustment * cal_dac_left
319
+ right_dac_data = right_dac_data * dac_dbfs_adjustment * cal_dac_right
320
+
321
+ # Convert incoming doubles to float
322
+ left_dac_data_float = left_dac_data.astype(np.float32)
323
+ right_dac_data_float = right_dac_data.astype(np.float32)
324
+
325
+ # Interleave the left and right channels
326
+ interleaved_dac_data = np.empty(
327
+ (left_dac_data_float.size + right_dac_data_float.size,), dtype=np.float32
328
+ )
329
+ interleaved_dac_data[0::2] = left_dac_data_float
330
+ interleaved_dac_data[1::2] = right_dac_data_float
331
+
332
+ # Convert to bytes, multiplying by max int value
333
+ max_int_value = 2 ** 31 - 1
334
+ interleaved_dac_data = (interleaved_dac_data * max_int_value).astype(np.int32)
335
+
336
+ num_ints_per_chunk = self.chunk_size // 4 # 32-bit ints, so 4 bytes per int
337
+ total_chunks = len(interleaved_dac_data) // num_ints_per_chunk
338
+
339
+ self.stream.start()
340
+
341
+ # Play wave on Bluetooth if available
342
+ bt_thread = None
343
+ if self.bt_device:
344
+ # Play both left and right waves on Bluetooth
345
+ bt_thread = self.bt_device.play_wave_background(left_wave, right_wave)
346
+
347
+ try:
348
+ for i in range(total_chunks):
349
+ chunk = interleaved_dac_data[
350
+ i * num_ints_per_chunk: (i + 1) * num_ints_per_chunk
351
+ ]
352
+ buffer = struct.pack("<%di" % len(chunk), *chunk)
353
+ self.stream.write(buffer)
354
+ finally:
355
+ self.stream.stop()
356
+
357
+ # Collect ADC data. This is bytes
358
+ interleaved_adc_data = self.stream.collect_remaining_adc_data()
359
+
360
+ # Wait for the Bluetooth thread to finish after processing
361
+ if bt_thread:
362
+ bt_thread.join()
363
+
364
+ # Convert collected ADC data back to int
365
+ interleaved_adc_data = np.frombuffer(interleaved_adc_data, dtype=np.int32)
366
+
367
+ # Separate interleaved ADC data into left and right channels. This is int
368
+ left_adc_data_int = interleaved_adc_data[0::2]
369
+ right_adc_data_int = interleaved_adc_data[1::2]
370
+
371
+ # Convert left and right channels back to double
372
+ left_adc_data = left_adc_data_int.astype(np.float64) / max_int_value
373
+ right_adc_data = right_adc_data_int.astype(np.float64) / max_int_value
374
+
375
+ # Get calibration factors for incoming data
376
+ cal_adc_left, cal_adc_right = self.control.get_adc_cal(
377
+ self.cal_data, self.params.max_input_level
378
+ )
379
+
380
+ # Convert from dBFS to dBV. Note the 6 dB factor--the ADC is differential
381
+ adc_dbfs_correction = 10 ** ((self.params.max_input_level - 6) / 20)
382
+
383
+ # Apply calibration and dBFS scaling
384
+ left_adc_data = left_adc_data * cal_adc_left * adc_dbfs_correction
385
+ right_adc_data = right_adc_data * cal_adc_right * adc_dbfs_correction
386
+
387
+ # Ensure the buffer matches the expected shape. Is this needed?
388
+ expected_shape = (
389
+ self.params.pre_buf + self.params.fft_size + self.params.post_buf,
390
+ )
391
+ if left_adc_data.shape[0] != expected_shape[0]:
392
+ left_adc_data = np.resize(left_adc_data, expected_shape)
393
+ if right_adc_data.shape[0] != expected_shape[0]:
394
+ right_adc_data = np.resize(right_adc_data, expected_shape)
395
+
396
+ # Create instances of Wave with the full buffers
397
+ left_wave = Wave(self.params)
398
+ right_wave = Wave(self.params)
399
+ left_wave.set_buffer(left_adc_data)
400
+ right_wave.set_buffer(right_adc_data)
401
+
402
+ return left_wave, right_wave
403
+
280
404
  def capture(self, total_samples: int) -> tuple[np.ndarray, np.ndarray]:
281
405
  """
282
406
  Captures ``total_samples`` samples from both ADC input channels without
@@ -46,7 +46,7 @@ class Control:
46
46
  """
47
47
  val = self.samplerate2reg[rate]
48
48
  self.registers.write(9, val)
49
- time.sleep(0.1) # A small delay to ensure the sample rate is set
49
+ time.sleep(0.2) # A small delay to ensure the sample rate is set
50
50
 
51
51
  def load_calibration(self):
52
52
  """
@@ -1,5 +1,7 @@
1
1
  import threading
2
2
  import queue
3
+ import time
4
+
3
5
  import usb1
4
6
  import logging
5
7
  from typing import Callable
@@ -27,7 +29,7 @@ class Stream:
27
29
  """
28
30
 
29
31
  TRANSFER_TIMEOUT_MS = 1000 # Timeout for USB transfers in milliseconds
30
- TRANSFER_BYTES = 16384 # 16 kB per USB bulk transfer (hardware chunk size)
32
+ DEFAULT_TRANSFER_BYTES = 16384 # 16 kB per USB bulk transfer (hardware chunk size)
31
33
  # cap on unread ADC data before overflow
32
34
  MAX_BUFFERED_BYTES = 256 * 1024 * 1024
33
35
 
@@ -36,6 +38,7 @@ class Stream:
36
38
  context: usb1.USBContext,
37
39
  device: usb1.USBDeviceHandle,
38
40
  registers: Registers,
41
+ transfer_bytes_size: int = DEFAULT_TRANSFER_BYTES
39
42
  ) -> None:
40
43
  """
41
44
  Initialize the Stream.
@@ -44,10 +47,12 @@ class Stream:
44
47
  context (usb1.USBContext): The USB context.
45
48
  device (usb1.USBDeviceHandle): The USB device handle.
46
49
  registers (Registers): The Registers instance for control writes.
50
+ transfer_bytes_size (int):
47
51
  """
48
52
  self.context = context
49
53
  self.device = device
50
54
  self.registers = registers
55
+ self.transfer_bytes_size = transfer_bytes_size # USB bulk transfer (hardware chunk size)
51
56
  self.endpoint_read = usb1.ENDPOINT_IN | 0x02 # EP2 in
52
57
  self.endpoint_write = usb1.ENDPOINT_OUT | 0x02 # EP2 out
53
58
  self.dacQueue = queue.Queue(
@@ -79,7 +84,7 @@ class Stream:
79
84
  self._adc_data_carry = bytearray() # leftover ADC bytes between consume_adc calls
80
85
  # latched, raised by consume_adc
81
86
  self._overflow_error: AdcOverflowError | None = None
82
- self._max_queued_chunks = self.MAX_BUFFERED_BYTES // self.TRANSFER_BYTES
87
+ self._max_queued_chunks = self.MAX_BUFFERED_BYTES // self.transfer_bytes_size
83
88
 
84
89
  @property
85
90
  def overflow_error(self) -> "AdcOverflowError | None":
@@ -205,10 +210,26 @@ class Stream:
205
210
  self.dacQueue.put(dac)
206
211
  self.adcQueue.put(read)
207
212
 
208
- def write_zeros(self, chunk_bytes: int = TRANSFER_BYTES) -> None:
213
+ def write_zeros(self, chunk_bytes: int = DEFAULT_TRANSFER_BYTES) -> None:
209
214
  """Feed the ADC pipeline with a zero DAC buffer (continuous capture)."""
210
215
  self.write(bytes(chunk_bytes))
211
216
 
217
+ def collect_remaining_adc_data(self):
218
+ """
219
+ Waits for all remaining ADC transfers to complete and returns the collected data.
220
+
221
+ Returns:
222
+ bytearray: The collected ADC data.
223
+ """
224
+ while not self.adcQueue.empty():
225
+ time.sleep(0.01)
226
+
227
+ while not self._adc_data.empty():
228
+ chunk = self._adc_data.get()
229
+ self._adc_data_carry.extend(chunk)
230
+
231
+ return self._adc_data_carry
232
+
212
233
  def consume_adc(
213
234
  self,
214
235
  need_bytes: int,
@@ -26,7 +26,7 @@ class Wave:
26
26
 
27
27
  self.amplitude_unit: str = amplitude_unit # Lowercase. Use dbv or dbu
28
28
  self.distortion_unit: str = distortion_unit # Lowercase. Use db or pct
29
- self.energy_unit: str = energy_unit # Lowercase. Use dbv, dbu, V, or V�
29
+ self.energy_unit: str = energy_unit # Lowercase. Use dbv, dbu, V or V^2
30
30
 
31
31
 
32
32
  def set_buffer(self, buffer: np.ndarray):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyQa40x-i2c
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: A Python library for the QA40x audio analyser (int2code fork)
5
5
  Maintainer-email: Hubert Stepniewski <hubert.stepniewski@int2code.com>
6
6
  License: MIT License
@@ -1,58 +1,58 @@
1
1
  {
2
2
  "files": [
3
- ".gitignore",
4
- "README.md",
5
- ".pylint_ignore",
6
- "requirements-test.txt",
3
+ "tox.ini",
7
4
  "requirements.txt",
5
+ "requirements-test.txt",
8
6
  "requirements-dev.txt",
9
- "tox.ini",
10
- "pyproject.toml",
11
7
  "MANIFEST.in",
12
- "RELEASE_NOTES.md",
8
+ "pyproject.toml",
9
+ ".pylint_ignore",
13
10
  "LICENSE",
11
+ "RELEASE_NOTES.md",
12
+ "README.md",
13
+ ".gitignore",
14
+ ".github/workflows/code_checker.yml",
15
+ ".github/workflows/unit_tests.yml",
16
+ ".github/workflows/publish_package.yml",
17
+ "tests/__init__.py",
18
+ "tests/test_template.py",
19
+ "src/PyQa40x/sig_proc.py",
14
20
  "src/PyQa40x/wave.py",
15
- "src/PyQa40x/math_general.py",
16
- "src/PyQa40x/fft_processor.py",
17
- "src/PyQa40x/wave_sine.py",
21
+ "src/PyQa40x/helpers.py",
18
22
  "src/PyQa40x/freq_series_plotter.py",
19
- "src/PyQa40x/analyzer_params.py",
20
- "src/PyQa40x/sig_proc.py",
21
- "src/PyQa40x/control.py",
22
23
  "src/PyQa40x/math_sines.py",
23
- "src/PyQa40x/analyzer.py",
24
- "src/PyQa40x/helpers.py",
24
+ "src/PyQa40x/wave_sine.py",
25
25
  "src/PyQa40x/registers.py",
26
- "src/PyQa40x/cross_correlation.py",
27
- "src/PyQa40x/series_plotter.py",
28
26
  "src/PyQa40x/math_windows.py",
29
- "src/PyQa40x/bluetooth.py",
30
27
  "src/PyQa40x/math_energy.py",
31
28
  "src/PyQa40x/math_chirp.py",
32
- "src/PyQa40x/wave_chirp.py",
29
+ "src/PyQa40x/analyzer.py",
30
+ "src/PyQa40x/analyzer_params.py",
33
31
  "src/PyQa40x/__init__.py",
32
+ "src/PyQa40x/math_general.py",
33
+ "src/PyQa40x/control.py",
34
+ "src/PyQa40x/wave_chirp.py",
35
+ "src/PyQa40x/series_plotter.py",
36
+ "src/PyQa40x/fft_processor.py",
34
37
  "src/PyQa40x/stream.py",
35
- "src/PyQa40x.egg-info/requires.txt",
38
+ "src/PyQa40x/cross_correlation.py",
39
+ "src/PyQa40x/bluetooth.py",
36
40
  "src/PyQa40x.egg-info/SOURCES.txt",
37
- "src/PyQa40x.egg-info/top_level.txt",
38
41
  "src/PyQa40x.egg-info/dependency_links.txt",
42
+ "src/PyQa40x.egg-info/requires.txt",
39
43
  "src/PyQa40x.egg-info/PKG-INFO",
40
- ".github/workflows/unit_tests.yml",
41
- ".github/workflows/code_checker.yml",
42
- ".github/workflows/publish_package.yml",
44
+ "src/PyQa40x.egg-info/top_level.txt",
43
45
  "_ci/is_dev_version.sh",
44
- "LibTest/PyQa40x_cross_correlation.py",
45
- "LibTest/PyQa40x_acoustic_chirp_spl_bt.py",
46
- "LibTest/PyQa40x_acoustic_dbspl.py",
46
+ "LibTest/PyQa40x_thdn.py",
47
47
  "LibTest/PyQa40x_freq_response_with_mask.py",
48
- "LibTest/PyQa40x_pinknoise.py",
49
- "LibTest/PyQa40x_acoustic_energy_decay_bt.py",
50
48
  "LibTest/mask_phase.txt",
51
49
  "LibTest/PyQa40x_coherent_averaging.py",
52
- "LibTest/PyQa40x_thdn.py",
53
50
  "LibTest/FirstPrinciples.py",
51
+ "LibTest/PyQa40x_cross_correlation.py",
52
+ "LibTest/PyQa40x_pinknoise.py",
54
53
  "LibTest/mask_freq.txt",
55
- "tests/test_template.py",
56
- "tests/__init__.py"
54
+ "LibTest/PyQa40x_acoustic_energy_decay_bt.py",
55
+ "LibTest/PyQa40x_acoustic_dbspl.py",
56
+ "LibTest/PyQa40x_acoustic_chirp_spl_bt.py"
57
57
  ]
58
58
  }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.2.2",
3
+ "distance": 0,
4
+ "node": "gf75dc49b93b52857fb5f1d4ae3825e1a36fc7a30",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-08-06"
8
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.2.0",
3
- "distance": 0,
4
- "node": "g6a5ba3357cf07c1d160ef5f122265823f2560ec9",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-07-16"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes