# una2csv.py extracts a comma-separated-valye (csv) record # from a *una.txt file in stdin as generated by waveformAnalyzer.ck # (from a .wav file) for csc558 assignment 1, spring 2018, D. Parson # reads stdin, writes stdout` # Updated 1/28/2018 to put the random serial number out as 1st attribute. import sys import re __hdr_re__ = re.compile(r'^lazy1_([A-Za-z]+)_([0-9]+)_([01]\.[0-9]+)_([01]\.[0-9]+)_([0-9]+).wav.una.txt ([0-9]\.[0-9]+) ([0-9]\.[0-9]+) ([0-9]\.[0-9]+) ([0-9]\.[0-9]+) ([0-9]\.[0-9]+)$') __bin_re__ = re.compile(r'^([0-9]\.[0-9]+) :\(float\)') __fftbins__ = 512 _reducedbins__ = 20 # (osc) (freq) (oscgain) (noisegain) (rnd) (centroid) (rms) (25th) (50th) (75th) if __name__ == '__main__': hdr = '' m = None line = sys.stdin.readline() lineno = 1 while line: line = line.strip() m = __hdr_re__.match(line) if m: hdr = line break line = sys.stdin.readline() lineno += 1 if not m: sys.stderr.write("ERROR: No header line in input file.\n") sys.exit(1) osc = m.group(1).strip() freq = float(m.group(2).strip()) oscgain = float(m.group(3).strip()) noisegain = float(m.group(4).strip()) rnd = int(m.group(5).strip()) centroid = float(m.group(6).strip()) rms = float(m.group(7).strip()) roll25 = float(m.group(8).strip()) roll50 = float(m.group(9).strip()) roll75 = float(m.group(10).strip()) line = sys.stdin.readline() lineno += 1 histogram = [] sys.stdout.write(str(rnd) + ",'" + osc + "'," + str(freq) + "," + str(oscgain) + "," + str(noisegain) + "," + str(centroid) + "," + str(rms) + "," + str(roll25) + "," + str(roll50) + "," + str(roll75)) while line: line = line.strip() m = __bin_re__.match(line) if not m: sys.stderr.write("ERROR: Line " + str(lineno) + " is not a valid line: " + line + '\n') sys.stderr.write("ERROR file: " + hdr + '\n') sys.exit(1) histogram.append(float(m.group(1).strip())) line = sys.stdin.readline() lineno += 1 if len(histogram) != __fftbins__: sys.stderr.write("ERROR: Line count " + str(lineno-1) + " does not have " + str(__fftbins__) + " bins: " + str(len(histogram)) + '\n') sys.stderr.write("ERROR file: " + hdr + '\n') sys.exit(1) # Skip first two bins as out-of-band data, lower than the frequency range # [100,2000] used by the generator, then try to find the fundamental as # the highest level. hibin = 2 hival = histogram[2] for i in range(2,len(histogram)): if histogram[i] > hival: hival = histogram[i] hibin = i # Store the fundamental freq amplitude, then look at its harmonics. def __findnearest__(histogram, lookat): # Look for the nearest peak. ix = lookat - 3 if ix >= len(histogram): return(-1, 0.0) bigix = ix bigval = histogram[ix] while ix < len(histogram) and ix <= (lookat + 3): if histogram[ix] >= bigval: bigval = histogram[ix] bigix = ix ix += 1 return(bigix, bigval) scalebins = [hival] debugbins = [hibin] # Number of bins and actual bin offset of fundamental for freq extraction. sys.stdout.write(",44100," + str(__fftbins__) + "," + str(_reducedbins__) + "," + str(hibin)) jumpbin = hibin if (hibin >= 4) else 4 # Needed to add jumpbin for debugging because if fundamental # frequency is too close to bottom, __findnearest__'s +/- 3 # gets stuck at a single location. Seems to be a problem only # for 100 hz sine wave. nearbin, nextval = __findnearest__(histogram, 2*jumpbin) while nearbin > 0 and nearbin < len(histogram): scalebins.append(nextval) debugbins.append(nearbin) nearbin, nextval = __findnearest__(histogram, nearbin+jumpbin) # sys.stderr.write("DEBUG NEARBIN: " + str(nearbin) + "," + str(jumpbin) + '\n') biggest = 0.0 for i in range(0, len(scalebins)): # scalebins[i] = 10.0 ** scalebins[i] NO! # convert from log to linear if scalebins[i] > biggest: biggest = scalebins[i] for i in range(0, len(scalebins)): # normalize to 1.0 scalebins[i] = scalebins[i] / biggest if len(scalebins) > _reducedbins__: scalebins = scalebins[:_reducedbins__] # normalize to _reducedbins__ bins else: while len(scalebins) < _reducedbins__: scalebins.append(0.0) sys.stdout.write("," + ("%1.12f" % (1.0 / biggest))) # amplitude scale for sc in scalebins: # sys.stdout.write("," + str(sc)) sys.stdout.write("," + ("%1.12f" % sc)) sys.stdout.write("\n") sys.stderr.write("DEBUG BINS: " + str(debugbins) + " IN " + hdr + "\n")