#!/usr/local/bin/python3 ### Convert SPKR Buffer to WAV -- (c) by Tamas Rudnai 2022 ### ### This utility convert SPKR buffer output to an uncompressed WAV file ### ### Purpose is that sound generation can be analyzed by audio editor - Audacity for example ### import os import sys import struct # binpath = '/Users/trudnai/Library/Containers/com.trudnai.steveii/Data/' # binfilename = binpath + 'steve2_audio_debug.bin' def convert_bin_to_audio(filename): data_size = os.path.getsize(filename) channels = 2 sample_rate = 1023000 # 192000 # must be the same as in speaker.c : spkr_sample_rate bits_per_sample = 16 header_size = 44 with open( filename, 'rb') as binfile: wavfilename = os.path.splitext( os.path.basename(filename) )[0] + '.wav' with open( wavfilename, 'wb+') as wavfile: # WAV HEADER wavfile.write( 'RIFF'.encode() ) # Marks the file as a riff file. Characters are each 1 byte long wavfile.write( struct.pack('I', data_size + header_size ) ) # Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically you’d fill this in after creation wavfile.write( 'WAVE'.encode() ) # File Type Header. For our purposes, it always equals “WAVE” # FMT HEADER wavfile.write( 'fmt '.encode() ) # Format chunk marker. Includes trailing null (tr: Space works, null don't) wavfile.write( struct.pack('I', 16 ) ) # Length of format data as listed above # FMT DATA wavfile.write( struct.pack('H', 1 ) ) # Type of format (1 is PCM) - 2 byte integer wavfile.write( struct.pack('H', channels ) ) # Number of Channels - 2 byte integer wavfile.write( struct.pack('I', sample_rate ) ) # Sample Rate - 32 byte integer. Common values are 44100 (CD), 48000 (DAT). Sample Rate = Number of Samples per second, or Hertz wavfile.write( struct.pack('I', int(sample_rate * bits_per_sample * channels / 8) ) ) # (Sample Rate * BitsPerSample * Channels) / 8 wavfile.write( struct.pack('H', 4 ) ) # 0: (BitsPerSample * Channels) / 8 # 1: 8 bit mono2 # 2: 8 bit stereo # 3: 16 bit mono # 4: 16 bit stereo wavfile.write( struct.pack('H', bits_per_sample ) ) # Bits per sample # DATA HEADER wavfile.write( 'data'.encode() ) # “data” chunk header. Marks the beginning of the data section wavfile.write( struct.pack('I', data_size ) ) # Size of the data section # // WAV DATA wavfile.write( binfile.read() ) for filename in sys.argv: convert_bin_to_audio(filename)