import sys
import threading
import pyaudio
import numpy as np
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QPushButton, QSlider, QComboBox)
class VoiceChanger:
def __init__(self, input_device_index, output_device_index, pitch_factor):
self.pitch_factor = pitch_factor
self.input_device_index = input_device_index
self.output_device_index = output_device_index
self.p = pyaudio.PyAudio()
self.stream = self.p.open(
input_device_index=self.input_device_index,
output_device_index=self.output_device_index,
format=pyaudio.paInt16,
channels=1,
rate=44100,
input=True,
output=True,
frames_per_buffer=1024
)
def change_pitch(self):
data = self.stream.read(1024)
data = np.fromstring(data, dtype=np.int16)
data = np.interp(np.arange(0, len(data), self.pitch_factor), np.arange(0, len(data)), data)
data = data.astype(np.int16)
self.stream.write(data.tostring())
def close(self):
self.stream.stop_stream()
self.stream.close()
self.p.terminate()
def get_device_names(device_type):
p = pyaudio.PyAudio()
device_names = []
for i in range(p.get_device_count()):
device_info = p.get_device_info_by_index(i)
if device_info['maxInputChannels'] > 0 and device_type == pyaudio.PyAudio.paInput:
device_names.append(device_info['name'])
elif device_info['maxOutputChannels'] > 0 and device_type == pyaudio.PyAudio.paOutput:
device_names.append(device_info['name'])
p.terminate()
return device_names
class MainPage(QWidget):
def __init__(self):
super().__init__()
self.vc = None
self.inputCombo = QComboBox() # Add this line to define the inputCombo attribute
self.initUI()
def initUI(self):
# Create the "On" button
onButton = QPushButton("On", self)
onButton.clicked.connect(self.onButtonClicked)
# Create the "Off" button
offButton = QPushButton("Off", self)
offButton.clicked.connect(self.offButtonClicked)
# Create the "Next" button
nextButton = QPushButton("Next", self)
nextButton.clicked.connect(self.nextButtonClicked)
# Create the "Listen" button
listenButton = QPushButton("Listen", self)
listenButton.clicked.connect(self.listenButtonClicked)
# Create the slider
self.slider = QSlider(Qt.Horizontal, self)
self.slider.valueChanged.connect(self.sliderChanged)
# Add items to the input and output combo boxes
self.inputCombo.addItems(get_device_names(pyaudio.PyAudio.paInput))
self.outputCombo.addItems(get_device_names(pyaudio.PyAudio.paOutput))
# Create a layout and add the buttons and slider
layout = QVBoxLayout()
layout.addWidget(onButton)
layout.addWidget(self.slider)
self.setLayout(layout)
def onButtonClicked(self):
# Turn the voice changer on
input_device_index = self.inputCombo.currentIndex()
output_device_index = self.outputCombo.currentIndex()
pitch_factor = self.slider.value() / 100
self.vc = VoiceChanger(input_device_index, output_device_index, pitch_factor)
self.vc_thread = threading.Thread(target=self.vc_callback)
self.vc_thread.start()
def offButtonClicked(self):
# Turn the voice changer off
if self.vc is not None:
self.vc.close()
self.vc_thread.stop()
self.vc = None
def nextButtonClicked(self):
# Open the next page
self.nextPage = NextPage(self)
self.nextPage.show()
def vc_callback(self):
while self.vc_thread.is_alive():
self.vc.change_pitch()
def sliderChanged(self, value):
if self.vc is not None: # Check if vc is defined
self.vc.pitch_factor = value / 100
def listenButtonClicked(self):
# Listen to your own voice
self.vc.change_pitch()
class NextPage(QWidget):
def __init__(self, main_page):
super().__init__()
self.main_page = main_page
self.outputCombo = QComboBox() # Add this line to define the outputCombo attribute
self.initUI()
def initUI(self):
# Create the "Back" button
backButton = QPushButton("Back", self)
backButton.clicked.connect(self.backButtonClicked)
# Create the "Listen" button
listenButton = QPushButton("Listen", self)
listenButton.clicked.connect(self.listenButtonClicked)
self.outputCombo.addItems(get_device_names(pyaudio.PyAudio.paOutput)) # Add this line to populate the outputCombo
# Create a layout and add the buttons
layout = QVBoxLayout()
layout.addWidget(backButton)
layout.addWidget(listenButton)
layout.addWidget(self.outputCombo) # Add this line to add the outputCombo to the layout
self.setLayout(layout)
def backButtonClicked(self):
# Go back to the main page
self.main_page.show()
self.close()
def listenButtonClicked(self):
# Listen to the output audio
self.main_page.vc.output_device_index = self.outputCombo.currentIndex()
if __name__ == '__main__':
app = QApplication(sys.argv)
main_page = MainPage()
main_page.show()
sys.exit(app.exec_())
1 Like
If anyone can help me it would be much appreciated
my discord is ************
if you would rather message me there
so I can send screenshots etc
Hi @littleethan12 welcome to the community.
Can you please share a link to the Repl and upload screenshots of the error messages you are seeing.