Here is some code that will get you started.
Having a one second long window is not going to get you satisfactory results in most audio files. Your example pic, if the horizontal pixel represent seconds, has simple tones of very long duration.
Anyway, this code will give you the syntax you need. It may be handy for others as well.
Hope this helps.
Ced
from PIL import Image
from pydub import AudioSegment
import numpy as np
#=======================================================================
def main():
#---- Read in the Sound File
theSound = AudioSegment.from_file( "test.mp3" )
#---- Get the Channel Count
theTrackCount = theSound.channels
#---- Get the Raw Audio Data as an Array
if theTrackCount == 2:
theCombined = theSound.split_to_mono()
theSound = theCombined[0]
print "Using left channel only"
elif theTrackCount > 2:
print "Invalid Track Count"
theSamples = theSound.get_array_of_samples()
theSamplesCount = len( theSamples )
#---- Get the Frame Rate
theSamplesPerSecond = float( theSound.frame_rate )
#---- Print the File Characteristics
print theSamplesPerSecond, theTrackCount, len( theSamples )
#---- Get the File Size in Seconds
theSecondsCount = int( len( theSamples ) / theSamplesPerSecond )
print "Seconds:", theSecondsCount
#---- Create the Image
theImage = Image.new( "RGB", (500,22000), "black" )
thePixels = theImage.load()
#---- Loop Through the File
theSegmentSpot = 0
theSegmentSize = int( theSamplesPerSecond )
theVonHannWindow = np.hanning( theSegmentSize )
for s in range( 0, theSecondsCount ):
theNextSpot = theSegmentSpot + theSegmentSize
theSegment = theSamples[theSegmentSpot:theNextSpot]
ProcessSegment( s, theSegment, theVonHannWindow, thePixels )
theSegmentSpot = theNextSpot
print s, s / theSecondsCount
#---- Write the Image to a File
theImage.save( "test.jpg" )
#=======================================================================
def ProcessSegment( argSecond, argSegment, argVonHannWindow, argPixels ):
#---- Apply a Von Hann Window and take the DFT
theWindowedSegment = argSegment * argVonHannWindow
theDft = np.fft.rfft( theWindowedSegment )
theAbsDft = np.abs( theDft )
#---- Plot the Peaks
theThreshold = 1000
theFactor = 128.0 / 5000.0
for b in range( 2, 22000 ):
v = theAbsDft[b]
if v > theThreshold:
if v > theAbsDft[b-1]:
if v > theAbsDft[b-2]:
if v > theAbsDft[b+1]:
if v > theAbsDft[b+2]:
theI = int( 128.0 + v * theFactor )
if theI > 255: theI = 255
theShade = ( theI << 16 ) \
+ ( theI << 8 ) + theI
argPixels[argSecond,22000-b] = theShade
#=======================================================================
main()