audio-validation 0.3.2__tar.gz → 0.3.3__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 (45) hide show
  1. {audio_validation-0.3.2 → audio_validation-0.3.3}/PKG-INFO +1 -1
  2. {audio_validation-0.3.2 → audio_validation-0.3.3}/RELEASE_NOTES.md +4 -0
  3. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/_version.py +3 -3
  4. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/continous_validation/models.py +24 -1
  5. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/continous_validation/validator.py +22 -1
  6. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation.egg-info/PKG-INFO +1 -1
  7. audio_validation-0.3.3/src/audio_validation.egg-info/scm_version.json +8 -0
  8. audio_validation-0.3.2/src/audio_validation.egg-info/scm_version.json +0 -8
  9. {audio_validation-0.3.2 → audio_validation-0.3.3}/.github/workflows/code_checker.yml +0 -0
  10. {audio_validation-0.3.2 → audio_validation-0.3.3}/.github/workflows/publish_to_pypi.yml +0 -0
  11. {audio_validation-0.3.2 → audio_validation-0.3.3}/.github/workflows/unit_tests.yml +0 -0
  12. {audio_validation-0.3.2 → audio_validation-0.3.3}/.gitignore +0 -0
  13. {audio_validation-0.3.2 → audio_validation-0.3.3}/.pylint_ignore +0 -0
  14. {audio_validation-0.3.2 → audio_validation-0.3.3}/LICENSE +0 -0
  15. {audio_validation-0.3.2 → audio_validation-0.3.3}/README.md +0 -0
  16. {audio_validation-0.3.2 → audio_validation-0.3.3}/_ci/is_dev_version.sh +0 -0
  17. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/Makefile +0 -0
  18. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/conf.py +0 -0
  19. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/contribute.rst +0 -0
  20. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/index.rst +0 -0
  21. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/installation.rst +0 -0
  22. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/release_notes.rst +0 -0
  23. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/requirements.txt +0 -0
  24. {audio_validation-0.3.2 → audio_validation-0.3.3}/docs/tutorials/index.rst +0 -0
  25. {audio_validation-0.3.2 → audio_validation-0.3.3}/pyproject.toml +0 -0
  26. {audio_validation-0.3.2 → audio_validation-0.3.3}/requirements-dev.txt +0 -0
  27. {audio_validation-0.3.2 → audio_validation-0.3.3}/requirements-test.txt +0 -0
  28. {audio_validation-0.3.2 → audio_validation-0.3.3}/requirements.txt +0 -0
  29. {audio_validation-0.3.2 → audio_validation-0.3.3}/setup.cfg +0 -0
  30. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/__init__.py +0 -0
  31. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/audio_features.py +0 -0
  32. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/audio_verification.py +0 -0
  33. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/continous_validation/criteria.py +0 -0
  34. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/continous_validation/plots.py +0 -0
  35. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/continous_validation/recorder.py +0 -0
  36. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/continous_validation/retention.py +0 -0
  37. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation/utils/audio_generation.py +0 -0
  38. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation.egg-info/SOURCES.txt +0 -0
  39. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation.egg-info/dependency_links.txt +0 -0
  40. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation.egg-info/requires.txt +0 -0
  41. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation.egg-info/scm_file_list.json +0 -0
  42. {audio_validation-0.3.2 → audio_validation-0.3.3}/src/audio_validation.egg-info/top_level.txt +0 -0
  43. {audio_validation-0.3.2 → audio_validation-0.3.3}/tests/__init__.py +0 -0
  44. {audio_validation-0.3.2 → audio_validation-0.3.3}/tests/test_template.py +0 -0
  45. {audio_validation-0.3.2 → audio_validation-0.3.3}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audio_validation
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: Tools for validating audio data, including feature extraction and visualization.
5
5
  Maintainer-email: Hubert Stepniewski <hubert.stepniewski@int2code.com>, Marcin Tomiczek <marcin.tomiczek@int2code.com>, Piotr Sznapka <piotr.sznapka@int2code.com>
6
6
  License: MIT License
@@ -1,3 +1,7 @@
1
+ ### 0.3.3
2
+
3
+ [PATCH] Add absolute timestamps in audio chunks.
4
+
1
5
  ### 0.3.2
2
6
 
3
7
  [PATCH] Add warmup chunks, improve failure reporting.
@@ -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.3.2'
22
- __version_tuple__ = version_tuple = (0, 3, 2)
21
+ __version__ = version = '0.3.3'
22
+ __version_tuple__ = version_tuple = (0, 3, 3)
23
23
 
24
- __commit_id__ = commit_id = 'ge32c5a61b'
24
+ __commit_id__ = commit_id = 'g1aaee7507'
@@ -5,12 +5,15 @@ short-lived (only referenced by the bounded retention buffer).
5
5
  """
6
6
 
7
7
  from dataclasses import dataclass, field
8
+ from datetime import datetime
8
9
  from textwrap import indent
9
10
  from typing import List, Optional
10
11
 
11
12
  import numpy as np
12
13
  import pandas as pd
13
14
 
15
+ WALL_CLOCK_UNKNOWN = "-"
16
+
14
17
 
15
18
  def format_timestamp(seconds: float) -> str:
16
19
  """Render *seconds* since capture start as ``HH:MM:SS.mmm``.
@@ -28,6 +31,18 @@ def format_timestamp(seconds: float) -> str:
28
31
  return f"{hours:02d}:{minutes:02d}:{secs:02d}.{millis:03d}"
29
32
 
30
33
 
34
+ def format_wall_clock(timestamp: Optional[datetime]) -> str:
35
+ """Render an absolute chunk timestamp as ``YYYY-MM-DD HH:MM:SS.mmm``.
36
+
37
+ :param timestamp: Absolute chunk time, or ``None`` when not recorded.
38
+ :return: Millisecond-precision timestamp, or ``"-"`` when *timestamp* is
39
+ ``None``.
40
+ """
41
+ if timestamp is None:
42
+ return WALL_CLOCK_UNKNOWN
43
+ return timestamp.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
44
+
45
+
31
46
  @dataclass
32
47
  class RawChunk:
33
48
  """One contiguous captured block, tagged with its position in the run.
@@ -36,12 +51,15 @@ class RawChunk:
36
51
  :ivar start_s: Start time in seconds relative to capture start.
37
52
  :ivar end_s: End time in seconds relative to capture start.
38
53
  :ivar samples: 2-D array ``(n_samples, channels)``.
54
+ :ivar start_timestamp: Absolute wall-clock time of the chunk's first sample,
55
+ or ``None`` when the capture start time is unknown.
39
56
  """
40
57
 
41
58
  index: int
42
59
  start_s: float
43
60
  end_s: float
44
61
  samples: np.ndarray
62
+ start_timestamp: Optional[datetime] = None
45
63
 
46
64
 
47
65
  @dataclass
@@ -63,6 +81,8 @@ class ChunkMetrics:
63
81
  :ivar reason: Single-line failure summary, suited to a table column.
64
82
  :ivar detail: Multiline failure report with the per-check channel tables;
65
83
  never put this in a DataFrame cell, log it separately.
84
+ :ivar start_timestamp: Absolute wall-clock time of the chunk's first sample,
85
+ or ``None`` when the capture start time is unknown.
66
86
  """
67
87
 
68
88
  index: int
@@ -72,6 +92,7 @@ class ChunkMetrics:
72
92
  reason: str
73
93
  detail: str = ""
74
94
  channels: List[ChannelMetric] = field(default_factory=list)
95
+ start_timestamp: Optional[datetime] = None
75
96
 
76
97
 
77
98
  @dataclass
@@ -124,7 +145,8 @@ class ValidationResult: # pylint: disable=too-many-instance-attributes
124
145
  multiline table crammed into one cell wrecks the table layout.
125
146
 
126
147
  ``start``/``end`` are rendered as ``HH:MM:SS.mmm`` offsets from capture
127
- start rather than raw seconds.
148
+ start rather than raw seconds; ``timestamp`` is the absolute wall-clock
149
+ time of the chunk's first sample, for lining chunks up with DUT logs.
128
150
  """
129
151
  rows = []
130
152
  for metric in self.metrics:
@@ -132,6 +154,7 @@ class ValidationResult: # pylint: disable=too-many-instance-attributes
132
154
  rows.append(
133
155
  {
134
156
  "index": metric.index,
157
+ "timestamp": format_wall_clock(metric.start_timestamp),
135
158
  "start": format_timestamp(metric.start_s),
136
159
  "end": format_timestamp(metric.end_s),
137
160
  "ch": ch_idx,
@@ -19,6 +19,7 @@ import threading
19
19
  from concurrent.futures import CancelledError, Future, ThreadPoolExecutor
20
20
  from concurrent.futures import wait as futures_wait
21
21
  from dataclasses import dataclass, replace
22
+ from datetime import datetime, timedelta
22
23
  import time
23
24
  from typing import Callable, List, Optional
24
25
 
@@ -149,6 +150,7 @@ class ContinuousAudioValidator: # pylint: disable=too-many-instance-attributes
149
150
  self._error: Optional[str] = None
150
151
 
151
152
  self._captured_time_s = 0.0
153
+ self._capture_started_at: Optional[datetime] = None
152
154
  self._consec_fail = 0
153
155
  self._stop_requested = False
154
156
  self._play_stopped = False
@@ -258,6 +260,17 @@ class ContinuousAudioValidator: # pylint: disable=too-many-instance-attributes
258
260
  except Exception: # pylint: disable=broad-except
259
261
  logger.exception("recorder.stop_capture() raised")
260
262
 
263
+ def _chunk_timestamp(self, chunk_start_s: float) -> Optional[datetime]:
264
+ """Return the absolute time of a chunk starting *chunk_start_s* into the run.
265
+ Chunk timestamps are derived from capture start plus the sample-count offset,
266
+
267
+ :param chunk_start_s: Chunk start offset from capture start, in seconds.
268
+ :return: Wall-clock chunk start, or ``None`` before capture started.
269
+ """
270
+ if self._capture_started_at is None:
271
+ return None
272
+ return self._capture_started_at + timedelta(seconds=chunk_start_s)
273
+
261
274
  def _read_chunks(self) -> None:
262
275
  """
263
276
  Read chunks from the recorder and put them into the queue.
@@ -266,6 +279,7 @@ class ContinuousAudioValidator: # pylint: disable=too-many-instance-attributes
266
279
  total_samples = 0
267
280
  try:
268
281
  self._recorder.start_capture()
282
+ self._capture_started_at = datetime.now()
269
283
  while not self._stop.is_set() and not self._abort.is_set():
270
284
 
271
285
  if (
@@ -293,7 +307,13 @@ class ContinuousAudioValidator: # pylint: disable=too-many-instance-attributes
293
307
  chunk_end_s = total_samples / self._sample_rate
294
308
  self._captured_time_s = chunk_end_s
295
309
  self._enqueue_chunk(
296
- RawChunk(chunk_idx, chunk_start_s, chunk_end_s, chunk)
310
+ RawChunk(
311
+ chunk_idx,
312
+ chunk_start_s,
313
+ chunk_end_s,
314
+ chunk,
315
+ self._chunk_timestamp(chunk_start_s),
316
+ )
297
317
  )
298
318
  chunk_idx += 1
299
319
  except Exception as exc: # pylint: disable=broad-except
@@ -357,6 +377,7 @@ class ContinuousAudioValidator: # pylint: disable=too-many-instance-attributes
357
377
  index=chunk.index,
358
378
  start_s=chunk.start_s,
359
379
  end_s=chunk.end_s,
380
+ start_timestamp=chunk.start_timestamp,
360
381
  ok=verdict.ok,
361
382
  reason="warm-up (not evaluated)" if warmup else verdict.summary,
362
383
  detail=verdict.detail,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audio_validation
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: Tools for validating audio data, including feature extraction and visualization.
5
5
  Maintainer-email: Hubert Stepniewski <hubert.stepniewski@int2code.com>, Marcin Tomiczek <marcin.tomiczek@int2code.com>, Piotr Sznapka <piotr.sznapka@int2code.com>
6
6
  License: MIT License
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.3.3",
3
+ "distance": 0,
4
+ "node": "g1aaee750785afc79b6f331c4bd0e497c7e4b11a5",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-08-07"
8
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.3.2",
3
- "distance": 0,
4
- "node": "ge32c5a61ba2f0d187518620dd508fd43f8e2e24f",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-08-06"
8
- }