0

I have a code here that displays the waveform of an audio file in PyQT Graph, unfortunately the graph seems so big.

I can't attached an image yet so I'll provide a link of the screenshot of the graph that I made.

enter image description here

And here is my code:

 self.waveFile = wave.open(audio,'rb')
 self.format = pyaudio.paInt16
 channel = self.waveFile.getnchannels()
 self.rate = self.waveFile.getframerate()
 self.frame = self.waveFile.getnframes()
 self.stream = p.open(format=self.format, 
                         channels=channel,
                         rate=self.rate,
                         output=True)

 durationF = self.frame / float(self.rate)
 self.data_int = self.waveFile.readframes(self.frame)
 self.data_plot = np.fromstring(self.data_int, 'Int16')
 self.data_plot.shape = -1, 2
 self.data_plot = self.data_plot.T
 self.time = np.arange(0, self.frame) * (1.0 / self.rate)

 w = pg.plot()
 w.plot(self.time, self.data_plot[0])

Should I need to adjust X and Y range limits? Should I adjust the Y peak? As you can see the X(time) matches from the audio file that I used with 8 seconds duration. But the Y isn't(?). I am not sure how to adjust the data of the waveform so that it can be fit inside the window. Any response and suggestions will be of great help!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Patrick
  • 5
  • 4

1 Answers1

0

I think there are a couple of options depending on what you want to show.

1: Adjust the Y-limit

The simplest solution is to scale the Y axis.

# See docs for function setYrange
# setYRange(min, max, padding=None, update=True)
w.setRange(YRange=[min,max])

You can check the docs here.

That is if you want to keep all of the audio values the same as they are currently, although do you really need the audio data in terms of those values? Normally audio data is displayed as a float between -1 and +1 for scientific purposes at least.

2: Adjust your data

As said before audio data tends to be most useful when its scaled between -1 and +1; it's just easier for us to glance at it and instantly get a feeling for if the amplitude is correct (if we were testing a gain program for example). There are plenty of other Python libraries other than the built in wave module, which will handle this much easier for you like PySoundFile or many others (see this other SO post for other methods of reading .wav files in Python).

Otherwise you can convert the data received from the wave module to floating point data using something like this (props to yeeking for the code):

import wave
import struct
import sys

def wav_to_floats(wave_file):
    w = wave.open(wave_file)
    astr = w.readframes(w.getnframes())
    # convert binary chunks to short 
    a = struct.unpack("%ih" % (w.getnframes()* w.getnchannels()), astr)
    a = [float(val) / pow(2, 15) for val in a]
    return a

# read the wav file specified as first command line arg
signal = wav_to_floats(sys.argv[1])
print "read "+str(len(signal))+" frames"
print  "in the range "+str(min(signal))+" to "+str(min(signal))

If possible using a library is always better in this case, because the wave module as it stands doesn't support many audio use cases (as far as I was aware, only mono 16 bit audio).

Note: If you do convert it to -1 to +1 data probably still worthwhile adjusting the Y-Limit like explained in part 1. Just to avoid weird scaling when loading different .wav files.

WoodyDev
  • 1,386
  • 1
  • 9
  • 19
  • Thank you so much for answering both of the options that I thought were possible, and it worked! I adjusted the Y range to -30000 and 30000 to which is that frequency possible peaks. I have to do further audio analysis functions and I think adjusting the data inside would be useful too. So thank you for both of your answers. It really helped me a lot which were on my blind spot. Thank you. :) – Patrick Jun 30 '18 at 05:50