I have made a short python program to loop through around 9000 audio files, trim off the edges to make them around 2.5 seconds long, convert them into spectrograms, and save them as PNGs in their appropriate folders. It gets the paths of the audio (.wav) files from a .csv file.
The problem is the program starts out very quickly, taking around 0.5 seconds for each spectrogram, but begins slowing down quickly. I don't think this is caused by my computer thermal throttling, because it's constantly slowing down; it doesn't settle in at a certain amount of time per spectrogram. Each spectrogram takes longer than the last. Additionally, if I stop the program and then start it very quickly, it resets to around 0.5 seconds per spectrogram.
Here is my code:
import csv
import time
import wave
import matplotlib.pyplot as plt
import numpy as np
# Function to make a spectrogram from a given wav file, and save it as a png to a given location
def makeSpectrogram(soundFilePath, fileSavePath, counter, station, species):
soundFile = wave.open(soundFilePath, "r")
# Get frame rate and number of frames
frameRate = soundFile.getframerate()
numFrames = soundFile.getnframes()
# Extract the raw audio data
rawAudio = soundFile.readframes(numFrames)
# Convert the raw audio data to a NumPy array
audio = np.frombuffer(rawAudio, dtype=np.int16)
# Trim the audio
reductionFactor = int((len(audio) - 500000) / 2)
audio = audio[reductionFactor:-reductionFactor]
# Create the spectrogram
spectrogram = plt.specgram(audio, Fs=frameRate, NFFT=4096, noverlap=2048, cmap="Greys", )
# Limit the y-axis to certain frequencies
plt.ylim([15000, 90000])
# Save the spectrogram as an image
plt.savefig(f"{fileSavePath}spectrogram_station{station}_{species}_{counter}.png", dpi=250)
# Close the file
soundFile.close()
# Open CSV
csvFile = open("/Users/myname/Desktop/spreadsheet.csv", "r")
csv = csv.reader(csvFile)
# List from CSV
csvList = list(csv)
# Start timer
start = time.time()
# Loop through files in CSV, make spectrogram for each
for i in range(510, len(csvList)):
row = csvList\[i\]
wavPath = row\[0\]
station = row\[4\]
species = row\[1\]
try:
start2 = time.time()
makeSpectrogram(wavPath, f"/Users/myname/Desktop/Spectrograms/Station {station}/uncropped/", i, station, species)
print(f"Spectrogram complete: {wavPath}")
end = time.time()
print(f"Time Elapsed: {end - start} s")
end2 = time.time()
print(f"Render Time: {end2 - start2}")
print(f"Estimated Time Remaining: {((end2 - start2) \* (len(csvList) - i)) / 3600} hrs")
print(f"Spectrograms Completed: {i}\\n")
except:
print(f"File not found: {wavPath}")
end = time.time()
print(f"Time Elapsed: {end - start} s")
print(f"Spectrograms Completed: {i}\\n")
csvFile.close()
I was initially missing soundFile.close() at the end of the makeSpectrogram function, so I though Python was leaving every file open and the program was slowing down due to a buildup of open files (I'm not actually sure if this is how Python handles files), but upon adding that line nothing changed. After making around 500 spectrograms, it's taking 10.8 seconds each, and still increasing.
Edit: I solved the root problem (see my answer), but I now have a memory leak of some sort. It takes a while, but eventually after rendering around 5500 spectrograms my computer warns me that I'm running out of memory. It's not a huge issue, but it's annoying.