简体   繁体   中英

How do I get the frequency and amplitude of audio that's being recorded in Python 3.x?

I'm trying to record audio and get the average frequency and amplitude of the audio in 1 second intervals without writing to a file. There are plenty of examples on how this can be done if you read from a file using pyaudio, although anything that could be usable for this specific situation uses Python 2.7 libraries that don't seem to exist for Python 3.x.

Any help would be appreciated!

Getting the Audio

I'm not exactly sure what library you are using to record the audio but the normal go-to for realtime recording / playback (in my opinion) is PyAudio (you only mentioned it for reading from a file).

They have an example for blocking and non-blocking audio I/O for realtime processing. For example, using blocking mode example, you can carry out your DSP processing everytime you receive a new block of audio.

"""PyAudio Example: Play a wave file."""

import pyaudio
import wave
import sys

CHUNK = 1024

if len(sys.argv) < 2:
    print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
    sys.exit(-1)

wf = wave.open(sys.argv[1], 'rb')

# instantiate PyAudio (1)
p = pyaudio.PyAudio()

# open stream (2)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                output=True)

# read data
data = wf.readframes(CHUNK)

# play stream (3)
while len(data) > 0:
    stream.write(data)
    data = wf.readframes(CHUNK)
    # Do all of your DSP processing here i.e. function call or whatever

# stop stream (4)
stream.stop_stream()
stream.close()

# close PyAudio (5)
p.terminate()

Finding the amplitude

If you want the amplitude of the signal at any given point, then all you have to do is take the absolute value of one sample in the array of samples, ie to get the amplitude of the 3rd sample from your audio block data.

ampSample3 = abs(data[2])

Obviously this isn't that useful generally for individual sample amplitudes, but rather it's better to look at the whole block. So you can calculate the absolute for each value, sum up all of the array and divide by the block size (average).

blockAmplitudeMean = sum(numpy.absolute(x))/len(x)

But when working with audio we usually want the RMS value of the block.

blockLinearRms= numpy.sqrt(numpy.mean(data**2)) # Linear value between 0 -> 1
blockLogRms = 20 * math.log10(blockLinearRms) # Decibel (dB value) between 0 dB -> -inf dB

Getting the frequency

In your question you just specified getting the frequency of the audio which could mean one of two things.

Determining the frequency spectrum

Commonly used in DSP, the frequency spectrum can be analyzed using the DFT (Discrete Fourier Transform). You will usually see this under the name FFT (Fast Fourier Transform), since this is the most popular implementation of the DFT. There are already Python libraries that implement the FFT for you and are simple to use.

Please note that this will give you an array the length of your block size that contains complex information (real signal + phase information) ie the frequency information. This does not mean you can necessarily identify the pitch of incoming audio (you can't directly tell that someone is playing an A1 note on the piano, unless the signal is really high quality and you still have some basic DSP processing as well as the FFT).

For reference:

  • Here is a link to the scipy.fft and how to get started
  • And here is the link for numpy.fft with a couple of examples

You can call this function in your processing loop if you wanted to do something with the frequency information.

Determining the pitch (/musical note)

This is a non-trivial task that many people try to accomplish. Most algorithm's usually involve the FFT (as discussed before), but have another layer of complicated processing on top. I would recommend using a library unless you fancy developing your own algorithm:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM