Untitled
unknown
python
a year ago
11 kB
5
Indexable
import sys import PyQt5.QtWidgets import pyqtgraph as pg import numpy as np from scipy.io import wavfile from scipy.fft import fft import csv class SignalGenerator: def __init__(self, sampling_rate, duration): self.sampling_rate = sampling_rate self.duration = duration def generate_sine(self, frequency, amplitude): t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False) signal = amplitude * np.sin(2 * np.pi * frequency * t) return t, signal def generate_square(self, frequency, amplitude): t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False) signal = amplitude * np.sign(np.sin(2 * np.pi * frequency * t)) return t, signal def generate_sawtooth(self, frequency, amplitude): t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False) signal = amplitude * (2 * (frequency * t - np.floor(0.5 + frequency * t))) return t, signal def generate_triangle(self, frequency, amplitude): t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False) signal = amplitude * np.abs((2 * (frequency * t - np.floor(0.5 + frequency * t))) - 1) return t, signal def generate_white_noise(self, amplitude): signal = amplitude * np.random.uniform(-1, 1, int(self.sampling_rate * self.duration)) t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False) return t, signal def plot_fourier_transform(self, signal, title, plot_widget): N = len(signal) T = 1 / self.sampling_rate yf = fft(signal) xf = np.fft.fftfreq(N, T)[:N // 2] plot_widget.plot(xf, 2.0 / N * np.abs(yf[0:N // 2])) plot_widget.setTitle(title) plot_widget.setLabel('bottom', 'Częstotliwość (Hz)') plot_widget.setLabel('left', 'Amplituda') plot_widget.setXRange(0, 3000) plot_widget.setYRange(0, 0.0125) plot_widget.getAxis('bottom').setTicks([[(i, str(i)) for i in range(0, 3001, 500)]]) plot_widget.getAxis('left').setTicks([[(i, str(i)) for i in np.arange(0, 0.0126, 0.0025)]]) plot_widget.show() def save_fourier_to_csv(self, signal, filename): N = len(signal) T = 1 / self.sampling_rate yf = fft(signal) xf = np.fft.fftfreq(N, T)[:N // 2] with open(filename, 'w', newline='') as csvfile: csvwriter = csv.writer(csvfile) csvwriter.writerow(['Częstotliwość', 'Amplituda']) for freq, amp in zip(xf, 2.0 / N * np.abs(yf[0:N // 2])): csvwriter.writerow([freq, amp]) def save_to_wav(self, t, signal, filename): scaled_data = np.int16(signal / np.max(np.abs(signal)) * 32767) wavfile.write(filename, self.sampling_rate, scaled_data) class SignalGeneratorGUI(PyQt5.QtWidgets.QMainWindow): def __init__(self): super().__init__() self.generator = SignalGenerator(44100, 5) self.central_widget = PyQt5.QtWidgets.QWidget() self.setCentralWidget(self.central_widget) self.init_ui() def init_ui(self): # Layouts main_layout = PyQt5.QtWidgets.QHBoxLayout() # Left-side layout for signal options options_layout = PyQt5.QtWidgets.QVBoxLayout() # Signal Type signal_type_label = PyQt5.QtWidgets.QLabel("Typ sygnału:") self.signal_type_combo = PyQt5.QtWidgets.QComboBox() self.signal_type_combo.addItems(['Sine', 'Square', 'Triangle', 'Sawtooth', 'White Noise']) options_layout.addWidget(signal_type_label) options_layout.addWidget(self.signal_type_combo) # Sampling Rate sampling_rate_label = PyQt5.QtWidgets.QLabel("Częstotliwość próbkowania:") self.sampling_rate_spin = PyQt5.QtWidgets.QSpinBox() self.sampling_rate_spin.setValue(44100) options_layout.addWidget(sampling_rate_label) options_layout.addWidget(self.sampling_rate_spin) # Duration duration_label = PyQt5.QtWidgets.QLabel("Długość trwania:") self.duration_spin = PyQt5.QtWidgets.QSpinBox() self.duration_spin.setValue(5) options_layout.addWidget(duration_label) options_layout.addWidget(self.duration_spin) # Frequency frequency_label = PyQt5.QtWidgets.QLabel("Częstotliwość:") self.frequency_double_spin = PyQt5.QtWidgets.QDoubleSpinBox() self.frequency_double_spin.setValue(440) options_layout.addWidget(frequency_label) options_layout.addWidget(self.frequency_double_spin) # Amplitude amplitude_label = PyQt5.QtWidgets.QLabel("Amplituda:") self.amplitude_double_spin = PyQt5.QtWidgets.QDoubleSpinBox() self.amplitude_double_spin.setValue(1.0) options_layout.addWidget(amplitude_label) options_layout.addWidget(self.amplitude_double_spin) # Generate Button generate_button = PyQt5.QtWidgets.QPushButton("Generuj sygnał") generate_button.clicked.connect(self.generate_signal) options_layout.addWidget(generate_button) # Right-side layout for plots and tables plots_layout = PyQt5.QtWidgets.QVBoxLayout() # Table for time domain self.table = PyQt5.QtWidgets.QTableWidget() self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(['Czas', 'Amplituda']) plots_layout.addWidget(self.table) # Middle layout for plots middle_layout = PyQt5.QtWidgets.QVBoxLayout() # Plot self.plot_widget = pg.PlotWidget() self.plot_widget.setLabel('bottom', 'Czas (s)') self.plot_widget.setLabel('left', 'Amplituda') middle_layout.addWidget(self.plot_widget) # Fourier Transform Plot self.fourier_plot_widget = pg.PlotWidget() self.fourier_plot_widget.setLabel('bottom', 'Częstotliwość (Hz)') self.fourier_plot_widget.setLabel('left', 'Amplituda') middle_layout.addWidget(self.fourier_plot_widget) plots_layout.addLayout(middle_layout) main_layout.addLayout(options_layout) main_layout.addLayout(plots_layout) # Menu Bar menubar = self.menuBar() file_menu = menubar.addMenu('Plik') # Save to WAV save_wav_action = PyQt5.QtWidgets.QAction('Zapisz do WAV', self) save_wav_action.triggered.connect(self.save_to_wav) file_menu.addAction(save_wav_action) # Save to CSV save_csv_action = PyQt5.QtWidgets.QAction('Zapisz do CSV', self) save_csv_action.triggered.connect(self.save_to_csv) file_menu.addAction(save_csv_action) self.central_widget.setLayout(main_layout) self.setWindowTitle("Generator Sygnałów") self.show() def generate_signal(self): signal_type = self.signal_type_combo.currentText() frequency = self.frequency_double_spin.value() amplitude = self.amplitude_double_spin.value() duration = self.duration_spin.value() sampling_rate = self.sampling_rate_spin.value() t, signal = self.generator.generate_sine(frequency, amplitude) # Default to sine for simplicity # Update Table self.table.setRowCount(len(t)) for i in range(len(t)): self.table.setItem(i, 0, PyQt5.QtWidgets.QTableWidgetItem(str(t[i]))) self.table.setItem(i, 1, PyQt5.QtWidgets.QTableWidgetItem(str(signal[i]))) # Update Plot self.plot_widget.clear() self.plot_widget.plot(t, signal, pen='b') # Update Fourier Transform Plot self.fourier_plot_widget.clear() self.generator.plot_fourier_transform(signal, 'Fourier Transform', self.fourier_plot_widget) def save_to_wav(self): filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku WAV', '', 'Wave Files (*.wav);;All Files (*)') if filename: self.generator.save_to_wav(self.table, filename) def save_to_csv(self): filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku CSV', '', 'CSV Files (*.csv);;All Files (*)') if filename: self.generator.save_fourier_to_csv(self.table, filename) if __name__ == '__main__': app = PyQt5.QtWidgets.QApplication(sys.argv) window = SignalGeneratorGUI() sys.exit(app.exec_()) def generate_signal(self): signal_type = self.signal_type_combo.currentText() frequency = self.frequency_double_spin.value() amplitude = self.amplitude_double_spin.value() duration = self.duration_spin.value() sampling_rate = self.sampling_rate_spin.value() t, signal = self.generator.generate_sine(frequency, amplitude) # Default to sine for simplicity # Update Table self.table.setRowCount(len(t)) for i in range(len(t)): self.table.setItem(i, 0, PyQt5.QtWidgets.QTableWidgetItem(str(t[i]))) self.table.setItem(i, 1, PyQt5.QtWidgets.QTableWidgetItem(str(signal[i]))) # Update Plot self.plot_widget.clear() self.plot_widget.plot(t, signal, pen='b') # Update Fourier Transform Plot self.fourier_plot_widget.clear() self.generator.plot_fourier_transform(signal, 'Fourier Transform', self.fourier_plot_widget) def save_to_wav(self): filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku WAV', '', 'Wave Files (*.wav);;All Files (*)') if filename: self.generator.save_to_wav(self.table, filename) def save_to_csv(self): filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku CSV', '', 'CSV Files (*.csv);;All Files (*)') if filename: self.generator.save_fourier_to_csv(self.table, filename) if __name__ == '__main__': app = PyQt5.QtWidgets.QApplication(sys.argv) window = SignalGeneratorGUI() sys.exit(app.exec_())
Editor is loading...
Leave a Comment