99import os
1010import tempfile
1111import unittest
12+ import wave
1213from pathlib import Path
1314
1415import numpy as np
1516
16- try :
17- from scipy .io import wavfile
18-
19- SCIPY_AVAILABLE = True
20- except ImportError :
21- SCIPY_AVAILABLE = False
22-
2317import sigmf
24- from sigmf .apps . convert_blue import convert_blue
25- from sigmf .apps . convert_wav import convert_wav
18+ from sigmf .convert . blue import blue_to_sigmf
19+ from sigmf .convert . wav import wav_to_sigmf
2620
2721BLUE_ENV_VAR = "NONSIGMF_RECORDINGS_PATH"
2822
@@ -32,8 +26,6 @@ class TestWAVConverter(unittest.TestCase):
3226
3327 def setUp (self ) -> None :
3428 """create temp wav file for testing"""
35- if not SCIPY_AVAILABLE :
36- self .skipTest ("scipy is required for WAV file tests" )
3729 self .tmp_dir = tempfile .TemporaryDirectory ()
3830 self .tmp_path = Path (self .tmp_dir .name )
3931 self .wav_path = self .tmp_path / "foo.wav"
@@ -42,19 +34,28 @@ def setUp(self) -> None:
4234 ttt = np .linspace (0 , duration_s , int (samp_rate * duration_s ), endpoint = False )
4335 freq = 440 # A4 note
4436 self .audio_data = 0.5 * np .sin (2 * np .pi * freq * ttt )
45- wavfile .write (self .wav_path , samp_rate , self .audio_data .astype (np .float32 ))
37+ # note scipy could write float wav files directly,
38+ # but to avoid adding scipy as a dependency for sigmf-python,
39+ # convert float audio to 16-bit PCM integer format
40+ audio_int16 = (self .audio_data * 32767 ).astype (np .int16 )
41+
42+ # write wav file using built-in wave module
43+ with wave .open (str (self .wav_path ), "wb" ) as wav_file :
44+ wav_file .setnchannels (1 ) # mono
45+ wav_file .setsampwidth (2 ) # 16-bit = 2 bytes
46+ wav_file .setframerate (samp_rate )
47+ wav_file .writeframes (audio_int16 .tobytes ())
4648
4749 def tearDown (self ) -> None :
4850 """clean up temporary directory"""
4951 self .tmp_dir .cleanup ()
5052
5153 def test_wav_to_sigmf (self ):
5254 sigmf_path = self .tmp_path / "bar"
53- _ = convert_wav (wav_path = self .wav_path , out_path = sigmf_path )
54- meta = sigmf .fromfile (sigmf_path )
55+ meta = wav_to_sigmf (wav_path = self .wav_path , out_path = sigmf_path )
5556 data = meta .read_samples ()
56- # allow small numerical differences due to data type conversions
57- self .assertTrue (np .allclose (self .audio_data , data , atol = 1e-8 ))
57+ # allow numerical differences due to PCM conversion
58+ self .assertTrue (np .allclose (self .audio_data , data , atol = 1e-4 ))
5859
5960
6061class TestBlueConverter (unittest .TestCase ):
@@ -79,18 +80,24 @@ def tearDown(self) -> None:
7980
8081 def test_blue_to_sigmf (self ):
8182 for bdx , bluefile in enumerate (self .bluefiles ):
82- sigmf_path = self .tmp_path / f"converted_{ bdx } "
83- _ = convert_blue (blue_path = bluefile , out_path = sigmf_path )
84- meta = sigmf .fromfile (sigmf_path )
83+ sigmf_path = self .tmp_path / bluefile .stem
84+ meta = blue_to_sigmf (blue_path = bluefile , out_path = sigmf_path )
8585
8686 ### EVERYTHING BELOW HERE IS FOR DEBUGGING ONLY _ REMOVE LATER ###
8787 # plot stft of RF data for visual inspection
88+ import matplotlib .pyplot as plt
8889 from scipy .signal import spectrogram
90+ from swiftfox import summary
8991
9092 samples = meta .read_samples ()
93+ plt .figure (figsize = (10 , 10 ))
94+ summary (samples , detail = 0.1 , samp_rate = meta .get_global_field ("core:sample_rate" ))
95+ plt .figure ()
96+ plt .plot (samples .real )
97+ plt .plot (samples .imag )
98+
9199 freqs , times , spec = spectrogram (samples , fs = meta .get_global_field ("core:sample_rate" ), nperseg = 1024 )
92100 # use imshow to plot spectrogram
93- import matplotlib .pyplot as plt
94101
95102 plt .figure ()
96103 plt .imshow (
0 commit comments