""" ################################################################################ This file is p398dlp_sp2022_read_binary.py. Read an audio binary file written by an Adalogger using my program piano_tests3.ino. Data format: each ADC digitization lives in two bytes, with the low byte holding the least signiificant bits and the high byte holding the most significiant bits. George Gollin, University of Illinois, February 7, 2022 ################################################################################ """ ############################## initialize stuff ################################ # time and clock routines import time # numerical routines import numpy as np # operating system routines import os import matplotlib import matplotlib.pyplot as plt # import matplotlib.mlab as mlab ############################################################## # change the file name to suit your needs. # Here's the name of the audio file. filename = 'ADCTST00.TXT' ############################################################## # sample rate (Hz) reported by the Arduino code that generated the binaries ADC_sample_rate = 16439 # close already-open graphics windows matplotlib.pyplot.close("all") ############################## read the file ############################## # away we go! print time information. print("\nstart reading file ", filename, " at ", time.ctime()) # keep track of running time start_time = time.time() # open the file for reading as a binary file ("rb") myfile = open(filename, "rb") # get file size information file_size_bytes = os.path.getsize(filename) file_size_words = int(file_size_bytes / 2) print("File holds ", file_size_words, " ADC samples") # read the whole file into a list: an array holding all the bytes in the file, # one byte per list element. data_bytes = list(myfile.read(file_size_bytes)) # preallocate space for the arrays by creating them, but initially filled # with zeroes. ADC_word = np.zeros(file_size_words, dtype = int) ADC_bin_number = np.zeros(file_size_words, dtype = int) # time bin size time_bin_width = 1.0 / float(ADC_sample_rate) # now load arrays. for iword in range(0, file_size_words): ADC_word[iword] = data_bytes[2 * iword] + 256 * data_bytes[2 * iword + 1] ADC_bin_number[iword] = iword print("finish reading file at ", time.ctime()) # now subtract the mean. ADC_word = ADC_word - np.mean(ADC_word) # also make an array of times for each ADC digitization. #unites: milliseconds. time_bin_value = ADC_bin_number * time_bin_width # make a plot! fig = plt.figure() ax = fig.gca() ax.set_xlabel("time (milliseconds)") ax.set_ylabel("ADC counts") ax.set_title("ADC counts vs time") # "k" is color black in ax.plot parameter. ax.plot(1000 * time_bin_value[0:200], ADC_word[0:200], '.', c = 'k', markersize = 2) # duration of the recording recording_duration = time_bin_value[file_size_words - 1] # now do an FFT. # frequency bin width is 1 / duration of the recording, and is in Hz. frequency_bin_width = 1. / float(recording_duration) # array holding frequencies... frequency = np.arange(file_size_words) * frequency_bin_width # take the Fourier transform FT = np.fft.fft(ADC_word) # since the FFT is complex, take its magnitude. FT_magnitude = abs(FT) # make another plot! upper_lim = 4000 fig = plt.figure() ax = fig.gca() ax.set_xlabel("frequency (Hz)") ax.set_ylabel("ADC amplitude") ax.set_title("ADC amplitude vs frequency") # "k" is color black in ax.plot parameter. ax.plot(frequency[0:upper_lim], FT_magnitude[0:upper_lim], '.', c = 'k', markersize = 2) ax.set_yscale('log') ax.set_ylim(bottom=1.)