- sudo apt install python3-pyaudio
$ sudo apt install python3-pyaudio
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成
有一些软件包无法被安装。如果您用的是 unstable 发行版,这也许是
因为系统无法达到您要求的状态造成的。该版本中可能会有一些您需要的软件
包尚未被创建或是它们已被从新到(Incoming)目录移出。
下列信息可能会对解决问题有所帮助:
下列软件包有未满足的依赖关系:
python3-pyaudio : 依赖: python3 (< 3.6) 但是 3.10.6-1~22.04 正要被安装
E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。
$ conda install PyAudio #这个并不需要python3 (< 3.6)
Collecting package metadata (current_repodata.json): done
Solving environment: done
## Package Plan ##
environment location: /home/pdd/anaconda3/envs/myaudio
added / updated specs:
- pyaudio
The following packages will be downloaded:
package | build
---------------------------|-----------------
portaudio-19.6.0 | h7b6447c_4 114 KB defaults
pyaudio-0.2.11 | py35h14c3975_1 64 KB defaults
------------------------------------------------------------
Total: 178 KB
The following NEW packages will be INSTALLED:
portaudio anaconda/pkgs/main/linux-64::portaudio-19.6.0-h7b6447c_4 None
pyaudio anaconda/pkgs/main/linux-64::pyaudio-0.2.11-py35h14c3975_1 None
Proceed ([y]/n)? y
Downloading and Extracting Packages
portaudio-19.6.0 | 114 KB | ####################################################################################################### | 100%
pyaudio-0.2.11 | 64 KB | ####################################################################################################### | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
Retrieving notices: ...working... done
使用pyaudio
保存音频到wav文件
import pyaudio
import wave
def record_and_save_wav(filename, duration=5, sample_rate=44100, channels=2, format=pyaudio.paInt16):
p = pyaudio.PyAudio()
stream = p.open(format=format,
channels=channels,
rate=sample_rate,
input=True,
frames_per_buffer=1024)
print("Recording...")
frames = []
for i in range(0, int(sample_rate / 1024 * duration)):
data = stream.read(1024)
frames.append(data)
print("Finished recording.")
stream.stop_stream()
stream.close()
p.terminate()
with wave.open(filename, 'wb') as wf:
wf.setnchannels(channels)
wf.setsampwidth(p.get_sample_size(format))
wf.setframerate(sample_rate)
wf.writeframes(b''.join(frames))
filename = "output.wav"
record_and_save_wav(filename, duration=5)
使用pyaudio
绘制频谱
# 代码来自https://github.com/sbarratt/spectrum-analyzer/blob/master/sa.py,略有修改
import pyaudio
import struct
import math
import sys
import numpy as np
import IPython as ipy
import pyqtgraph as pg
from PyQt5 import QtWidgets
from pyqtgraph.Qt import QtGui, QtCore
# Audio Format (check Audio MIDI Setup if on Mac)
FORMAT = pyaudio.paInt16
RATE = 44100
CHANNELS = 2
# Set Plot Range [-RANGE,RANGE], default is nyquist/2
RANGE = None
if not RANGE:
RANGE = RATE/2
# Set these parameters (How much data to plot per FFT)
INPUT_BLOCK_TIME = 0.05
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME)
# Which Channel? (L or R)
LR = "l"
class SpectrumAnalyzer():
def __init__(self):
self.pa = pyaudio.PyAudio()
self.initMicrophone()
self.initUI()
def find_input_device(self):
device_index = None
for i in range(self.pa.get_device_count()):
devinfo = self.pa.get_device_info_by_index(i)
if devinfo["name"].lower() in ["mic","input"]:
device_index = i
return device_index
def initMicrophone(self):
device_index = self.find_input_device()
self.stream = self.pa.open( format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
input_device_index = device_index,
frames_per_buffer = INPUT_FRAMES_PER_BLOCK)
def readData(self):
block = self.stream.read(INPUT_FRAMES_PER_BLOCK)
count = len(block)/2
format = "%dh"%(count)
shorts = struct.unpack( format, block )
if CHANNELS == 1:
return np.array(shorts)
else:
l = shorts[::2]
r = shorts[1::2]
if LR == 'l':
return np.array(l)
else:
return np.array(r)
def initUI(self):
self.app = QtWidgets.QApplication([]) # self.app = QtGui.QApplication([])
self.app.quitOnLastWindowClosed()
self.mainWindow = QtWidgets.QMainWindow()
self.mainWindow.setWindowTitle("Spectrum Analyzer")
self.mainWindow.resize(800,300)
self.centralWid = QtWidgets.QWidget()
self.mainWindow.setCentralWidget(self.centralWid)
self.lay = QtWidgets.QVBoxLayout()
self.centralWid.setLayout(self.lay)
self.specWid = pg.PlotWidget(name="spectrum")
self.specItem = self.specWid.getPlotItem()
self.specItem.setMouseEnabled(y=False)
self.specItem.setYRange(0,1000)
self.specItem.setXRange(-RANGE,RANGE, padding=0)
self.specAxis = self.specItem.getAxis("bottom")
self.specAxis.setLabel("Frequency [Hz]")
self.lay.addWidget(self.specWid)
self.mainWindow.show()
self.app.aboutToQuit.connect(self.close)
def close(self):
self.stream.close()
sys.exit()
def get_spectrum(self, data):
T = 1.0/RATE
N = data.shape[0]
Pxx = (1./N)*np.fft.fft(data)
f = np.fft.fftfreq(N,T)
Pxx = np.fft.fftshift(Pxx)
f = np.fft.fftshift(f)
return f.tolist(), (np.absolute(Pxx)).tolist()
def mainLoop(self):
while 1:
# Sometimes Input overflowed because of mouse events, ignore this
try:
data = self.readData()
except IOError:
continue
f, Pxx = self.get_spectrum(data)
self.specItem.plot(x=f,y=Pxx, clear=True)
QtWidgets.QApplication.processEvents()
if __name__ == '__main__':
sa = SpectrumAnalyzer()
sa.mainLoop()
使用pyaudio
绘制频谱+悬浮窗口
- 添加到
setWindowFlags
中的标志,确保窗口保持在其他窗口之上。这样,即使焦点切换到其他窗口,悬浮窗口仍然会保持在顶部。
import pyaudio
import struct
import math
import sys
import numpy as np
import IPython as ipy
import pyqtgraph as pg
from PyQt5 import QtWidgets
from pyqtgraph.Qt import QtGui, QtCore
from PyQt5.QtCore import Qt
# Audio Format (check Audio MIDI Setup if on Mac)
FORMAT = pyaudio.paInt16
RATE = 44100
CHANNELS = 2
# Set Plot Range [-RANGE,RANGE], default is nyquist/2
RANGE = None
if not RANGE:
RANGE = RATE/2
# Set these parameters (How much data to plot per FFT)
INPUT_BLOCK_TIME = 0.05
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME)
# Which Channel? (L or R)
LR = "l"
class SpectrumAnalyzer():
def __init__(self):
self.pa = pyaudio.PyAudio()
self.initMicrophone()
self.initUI()
def find_input_device(self):
device_index = None
for i in range(self.pa.get_device_count()):
devinfo = self.pa.get_device_info_by_index(i)
if devinfo["name"].lower() in ["mic","input"]:
device_index = i
return device_index
def initMicrophone(self):
device_index = self.find_input_device()
self.stream = self.pa.open( format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
input_device_index = device_index,
frames_per_buffer = INPUT_FRAMES_PER_BLOCK)
def readData(self):
block = self.stream.read(INPUT_FRAMES_PER_BLOCK)
count = len(block)/2
format = "%dh"%(count)
shorts = struct.unpack( format, block )
if CHANNELS == 1:
return np.array(shorts)
else:
l = shorts[::2]
r = shorts[1::2]
if LR == 'l':
return np.array(l)
else:
return np.array(r)
def initUI(self):
self.app = QtWidgets.QApplication([]) # self.app = QtGui.QApplication([])
self.app.quitOnLastWindowClosed()
self.mainWindow = QtWidgets.QMainWindow()
self.mainWindow.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.mainWindow.setWindowTitle("Spectrum Analyzer")
self.mainWindow.setGeometry(100, 100, 300, 200)#self.mainWindow.resize(800,300)
self.centralWid = QtWidgets.QWidget()
self.mainWindow.setCentralWidget(self.centralWid)
self.lay = QtWidgets.QVBoxLayout()
self.centralWid.setLayout(self.lay)
self.specWid = pg.PlotWidget(name="spectrum")
self.specItem = self.specWid.getPlotItem()
self.specItem.setMouseEnabled(y=False)
self.specItem.setYRange(0,1000)
self.specItem.setXRange(-RANGE,RANGE, padding=0)
self.specAxis = self.specItem.getAxis("bottom")
self.specAxis.setLabel("Frequency [Hz]")
self.lay.addWidget(self.specWid)
self.mainWindow.show()
self.app.aboutToQuit.connect(self.close)
def close(self):
self.stream.close()
sys.exit()
def get_spectrum(self, data):
T = 1.0/RATE
N = data.shape[0]
Pxx = (1./N)*np.fft.fft(data)
f = np.fft.fftfreq(N,T)
Pxx = np.fft.fftshift(Pxx)
f = np.fft.fftshift(f)
return f.tolist(), (np.absolute(Pxx)).tolist()
def mainLoop(self):
while 1:
# Sometimes Input overflowed because of mouse events, ignore this
try:
data = self.readData()
except IOError:
continue
f, Pxx = self.get_spectrum(data)
self.specItem.plot(x=f,y=Pxx, clear=True)
QtWidgets.QApplication.processEvents()
if __name__ == '__main__':
sa = SpectrumAnalyzer()
sa.mainLoop()
CG