@@ -322,7 +322,7 @@ def read_extended_header(file_path, h_fixed):
322322 return entries
323323
324324
325- def write_data (blue_path : Path , out_path : Path , h_fixed : dict ) -> np .ndarray :
325+ def data_loopback (blue_path : Path , out_path : Path , h_fixed : dict ) -> np .ndarray :
326326 """
327327 Write SigMF data file from BLUE file samples.
328328
@@ -342,12 +342,17 @@ def write_data(blue_path: Path, out_path: Path, h_fixed: dict) -> np.ndarray:
342342 """
343343 log .debug ("parsing BLUE file data values" )
344344
345- file_size_bytes = os . path . getsize ( blue_path )
346- extended_header_data_size = h_fixed .get ("ext_size" )
345+ # use header data_size field instead of file size calculation
346+ data_size_bytes = int ( h_fixed .get ("data_size" , 0 ) )
347347 fmt = h_fixed .get ("format" )
348348
349+ log .debug (f"format: { fmt } , data_size from header: { data_size_bytes } bytes" )
350+
349351 # Determine destination path for SigMF data file
350352 dest_path = out_path .with_suffix (".sigmf-data" )
353+ print ("#" * 80 )
354+ print ("Writing SigMF data to:" , dest_path )
355+ print ("#" * 80 )
351356
352357 config = DATA_TYPE_CONFIGS [fmt ]
353358 np_dtype = config ["dtype" ]
@@ -356,7 +361,9 @@ def write_data(blue_path: Path, out_path: Path, h_fixed: dict) -> np.ndarray:
356361
357362 # calculate element size and count
358363 elem_size = np .dtype (np_dtype ).itemsize
359- elem_count = (file_size_bytes - extended_header_data_size ) // elem_size
364+ elem_count = data_size_bytes // elem_size
365+
366+ log .debug (f"elem_size: { elem_size } , elem_count: { elem_count } , is_complex: { is_complex } " )
360367
361368 # read raw samples
362369 raw_samples = np .fromfile (blue_path , dtype = np_dtype , offset = HEADER_SIZE_BYTES , count = elem_count )
@@ -369,6 +376,7 @@ def write_data(blue_path: Path, out_path: Path, h_fixed: dict) -> np.ndarray:
369376 else :
370377 # reassemble interleaved IQ samples
371378 samples = raw_samples [::2 ] + 1j * raw_samples [1 ::2 ]
379+ log .debug (f"Deinterleaved { len (raw_samples )} samples into { len (samples )} complex samples" )
372380 else :
373381 # scalar data
374382 samples = raw_samples
@@ -470,21 +478,27 @@ def get_tag(tag):
470478 blue_start_time = float (h_fixed .get ("timecode" , 0 ))
471479 blue_start_time += h_adjunct .get ("xstart" , 0 )
472480 blue_start_time += float (h_keywords .get ("TC_PREC" , 0 ))
473- # timecode uses 1950-01-01 as epoch, datetime uses 1970-01-01
474- blue_epoch = blue_start_time - 631152000 # seconds between 1950 and 1970
475- # FIXME: I am unsure if the timezone is always UTC in these files
476- blue_datetime = datetime .fromtimestamp (blue_epoch , tz = timezone .utc )
477481
478- capture_info = {
479- SigMFFile .DATETIME_KEY : blue_datetime .strftime (SIGMF_DATETIME_ISO8601_FMT ),
480- }
482+ if blue_start_time == 0 :
483+ log .warning ("BLUE timecode is zero or missing; datetime metadata will be absent." )
484+ capture_info = {}
485+ else :
486+ # timecode uses 1950-01-01 as epoch, datetime uses 1970-01-01
487+ blue_epoch = blue_start_time - 631152000 # seconds between 1950 and 1970
488+ # FIXME: I am unsure if the timezone is always UTC in these files
489+ blue_datetime = datetime .fromtimestamp (blue_epoch , tz = timezone .utc )
490+
491+ capture_info = {
492+ SigMFFile .DATETIME_KEY : blue_datetime .strftime (SIGMF_DATETIME_ISO8601_FMT ),
493+ }
481494
482495 if get_tag ("RF_FREQ" ) is not None :
483496 # FIXME: I believe there are many possible keys related to tune frequency
484497 capture_info [SigMFFile .FREQUENCY_KEY ] = float (get_tag ("RF_FREQ" ))
485498
486499 # actually write to SigMF
487- filenames = get_sigmf_filenames (out_path )
500+ filenames = get_sigmf_filenames (out_path .stem )
501+ print ("dbug" , filenames )
488502
489503 meta = SigMFFile (
490504 data_file = filenames ["data_fn" ],
@@ -582,12 +596,12 @@ def validate_extended_header(entries: list) -> None:
582596 raise SigMFConversionError (f"Invalid SAMPLE_RATE in extended header: { sample_rate } " )
583597
584598
585- def convert_blue (
599+ def blue_to_sigmf (
586600 blue_path : str ,
587601 out_path : Optional [str ] = None ,
588- ) -> np . ndarray :
602+ ) -> SigMFFile :
589603 """
590- Convert a MIDIS Bluefile to SigMF metadata and data .
604+ Read a MIDAS Bluefile, write to SigMF, return SigMFFile object .
591605
592606 Parameters
593607 ----------
@@ -625,7 +639,7 @@ def convert_blue(
625639 h_extended = read_extended_header (blue_path , h_fixed )
626640
627641 # write to SigMF data file
628- _ = write_data (blue_path , out_path , h_fixed )
642+ _ = data_loopback (blue_path , out_path , h_fixed )
629643
630644 log .debug (">>>>>>>>> Fixed Header" )
631645 for key , _ , _ , _ , desc in FIXED_LAYOUT :
@@ -652,7 +666,8 @@ def main() -> None:
652666 Entry-point for sigmf_convert_blue
653667 """
654668 parser = argparse .ArgumentParser (description = __doc__ )
655- parser .add_argument ("input" , type = str , help = "Blue (cdif) file path" )
669+ parser .add_argument ("-i" , "--input" , type = str , required = True , help = "BLUE file path" )
670+ parser .add_argument ("-o" , "--output" , type = str , default = None , help = "SigMF path" )
656671 parser .add_argument ("-v" , "--verbose" , action = "count" , default = 0 )
657672 parser .add_argument ("--version" , action = "version" , version = f"%(prog)s v{ toolversion } " )
658673 args = parser .parse_args ()
@@ -664,4 +679,8 @@ def main() -> None:
664679 }
665680 logging .basicConfig (level = level_lut [min (args .verbose , 2 )])
666681
667- convert_blue (args .input )
682+ _ = blue_to_sigmf (blue_path = args .input , out_path = args .output )
683+
684+
685+ if __name__ == "__main__" :
686+ main ()
0 commit comments