Skip to content

Commit 7fbe176

Browse files
author
Kyle A Logue
committed
unified detect_converter function & better signalhound conversion
1 parent 520007a commit 7fbe176

File tree

9 files changed

+213
-125
lines changed

9 files changed

+213
-125
lines changed

docs/source/converters.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ Examples
207207
center_freq = meta.get_captures()[0]["core:frequency"]
208208
209209
# access Signal Hound-specific metadata in spike: namespace
210-
reference_level = meta.get_global_field("spike:reference_level")
211-
if_bandwidth = meta.get_global_field("spike:if_bandwidth")
212-
decimation = meta.get_global_field("spike:decimation")
210+
reference_level_dbm = meta.get_global_field("spike:reference_level_dbm")
211+
scale_factor_mw = meta.get_global_field("spike:scale_factor_mw")
212+
if_bandwidth_hz = meta.get_global_field("spike:if_bandwidth_hz")
213+
iq_filename = meta.get_global_field("spike:iq_filename") # original IQ file name
214+
preview_trace = meta.get_global_field("spike:preview_trace") # max-hold trace

sigmf/convert/__init__.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Copyright: Multiple Authors
2+
#
3+
# This file is part of sigmf-python. https://github.com/sigmf/sigmf-python
4+
#
5+
# SPDX-License-Identifier: LGPL-3.0-or-later
6+
7+
"""Convert non-SigMF recordings to SigMF format"""
8+
9+
from pathlib import Path
10+
11+
from ..error import SigMFConversionError
12+
13+
14+
def get_magic_bytes(file_path: Path, count: int = 4, offset: int = 0) -> bytes:
15+
"""
16+
Get magic bytes from a file to help identify file type.
17+
18+
Parameters
19+
----------
20+
file_path : Path
21+
Path to the file to read magic bytes from.
22+
count : int, optional
23+
Number of bytes to read. Default is 4.
24+
offset : int, optional
25+
Byte offset to start reading from. Default is 0.
26+
27+
Returns
28+
-------
29+
bytes
30+
Magic bytes from the file.
31+
32+
Raises
33+
------
34+
SigMFConversionError
35+
If file cannot be read or is too small.
36+
"""
37+
try:
38+
with open(file_path, "rb") as handle:
39+
handle.seek(offset)
40+
magic_bytes = handle.read(count)
41+
if len(magic_bytes) < count:
42+
raise SigMFConversionError(f"File {file_path} too small to read {count} magic bytes at offset {offset}")
43+
return magic_bytes
44+
except OSError as err:
45+
raise SigMFConversionError(f"Failed to read magic bytes from {file_path}: {err}") from err
46+
47+
48+
def detect_converter(file_path: Path):
49+
"""
50+
Detect the appropriate converter for a non-SigMF file.
51+
52+
Parameters
53+
----------
54+
file_path : Path
55+
Path to the file to detect.
56+
57+
Returns
58+
-------
59+
str
60+
The converter name: "wav", "blue", or "signalhound"
61+
62+
Raises
63+
------
64+
SigMFConversionError
65+
If the file format is not supported or cannot be detected.
66+
"""
67+
magic_bytes = get_magic_bytes(file_path, count=4, offset=0)
68+
69+
if magic_bytes == b"RIFF":
70+
return "wav"
71+
72+
elif magic_bytes == b"BLUE":
73+
return "blue"
74+
75+
elif magic_bytes == b"<?xm": # <?xml version="1.0" encoding="UTF-8"?>
76+
# Check if it's a Signal Hound Spike file
77+
# Skip XML declaration (40 bytes) and check for SignalHoundIQFile root element
78+
expanded_magic_bytes = get_magic_bytes(file_path, count=17, offset=40)
79+
if expanded_magic_bytes == b"SignalHoundIQFile":
80+
return "signalhound"
81+
else:
82+
raise SigMFConversionError(
83+
f"Unsupported XML file format. Root element: {expanded_magic_bytes}. "
84+
f"Expected SignalHoundIQFile for Signal Hound Spike files."
85+
)
86+
87+
else:
88+
raise SigMFConversionError(
89+
f"Unsupported file format. Magic bytes: {magic_bytes}. "
90+
f"Supported formats for conversion are WAV, BLUE/Platinum, and Signal Hound Spike."
91+
)

sigmf/convert/__main__.py

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@
1313

1414
from .. import __version__ as toolversion
1515
from ..error import SigMFConversionError
16-
from ..utils import get_magic_bytes
16+
from . import detect_converter
1717
from .blue import blue_to_sigmf
18-
from .wav import wav_to_sigmf
1918
from .signalhound import signalhound_to_sigmf
20-
19+
from .wav import wav_to_sigmf
2120

2221

2322
def main() -> None:
@@ -87,33 +86,16 @@ def main() -> None:
8786
if output_path.is_dir():
8887
raise SigMFConversionError(f"Output path must be a filename, not a directory: {output_path}")
8988

90-
# detect file type using magic bytes (same logic as fromfile())
91-
magic_bytes = get_magic_bytes(input_path, count=4, offset=0)
89+
# detect file type using magic bytes
90+
converter_type = detect_converter(input_path)
9291

93-
if magic_bytes == b"RIFF":
94-
# WAV file
92+
if converter_type == "wav":
9593
_ = wav_to_sigmf(wav_path=input_path, out_path=output_path, create_archive=args.archive, create_ncd=args.ncd)
96-
97-
elif magic_bytes == b"BLUE":
98-
# BLUE file
94+
elif converter_type == "blue":
9995
_ = blue_to_sigmf(blue_path=input_path, out_path=output_path, create_archive=args.archive, create_ncd=args.ncd)
100-
101-
elif magic_bytes == b"<?xm": # <?xml version="1.0" encoding="UTF-8"?> <SignalHoundIQFile Version="1.0">
102-
# Signal Hound Spike 1.0 file
103-
# Of the 66 Byte string move 43 bytes in to skip the XML declaration
104-
# and get to the root element and take 18 chars for a more specific detection of Signal Hound Spike files
105-
expanded_magic_bytes = get_magic_bytes(input_path, count=17, offset=40)
106-
if expanded_magic_bytes == b"SignalHoundIQFile":
107-
_ = signalhound_to_sigmf(signalhound_path=input_path, out_path=output_path, create_archive=args.archive, create_ncd=args.ncd)
108-
else:
109-
raise SigMFConversionError(
110-
f"Unsupported XML file format. Expanded Magic bytes: {expanded_magic_bytes}. "
111-
f"Supported formats for conversion are WAV, BLUE/Platinum, and Signal Hound Spike."
112-
)
113-
else:
114-
raise SigMFConversionError(
115-
f"Unsupported file format. Magic bytes: {magic_bytes}. "
116-
f"Supported formats for conversion are WAV, BLUE/Platinum, and Signal Hound Spike."
96+
elif converter_type == "signalhound":
97+
_ = signalhound_to_sigmf(
98+
signalhound_path=input_path, out_path=output_path, create_archive=args.archive, create_ncd=args.ncd
11799
)
118100

119101

0 commit comments

Comments
 (0)