#define _CRT_SECURE_NO_WARNINGS
#include "communication_system.h"
#include <QFile>
#include <QDataStream>
#include <QDebug>
#include <complex>
#include <random>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <QAudioDeviceInfo>
#include <QAudioInput>
#include <QAudioOutput>
#include <QTimer>
#include <QBuffer>
#include <QtMath>
#include <QValueAxis>
#include <QChart>
#include <QLineSeries>
const float FSK_FREQ_SHIFT = 1000.0f;
int find_frame_header(const float* data, int length, const QByteArray& header);
// 在 communication_system.cpp 文件顶部添加(#include 之后)
const QByteArray FRAME_HEADER = QByteArray::fromHex("55555555AA"); // 01010101 交替的帧头
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 (M_PI / 2.0)
#endif
#ifndef M_PI_4
#define M_PI_4 (M_PI / 4.0)
#endif
// ================= 初始化函数 =================
void init_transmitter(Transmitter* tx, SignalType sig_type, ModulationType mod_type,
float carrier_freq, int sample_rate) {
if (tx->samples) {
delete[] tx->samples;
}
if (tx->modulated) {
delete[] tx->modulated;
}
memset(tx, 0, sizeof(Transmitter));
tx->signal_type = sig_type;
tx->mod_type = mod_type;
tx->carrier_freq = carrier_freq;
tx->sample_rate = sample_rate;
tx->samples = new float[MAX_SAMPLES]();
tx->modulated = new float[MAX_SAMPLES]();
tx->bit_count = 0;
tx->original_bit_count = 0;
}
void init_receiver(Receiver* rx, float carrier_freq, int sample_rate) {
if (rx->received) {
delete[] rx->received;
}
if (rx->demodulated) {
delete[] rx->demodulated;
}
memset(rx, 0, sizeof(Receiver));
rx->carrier_freq = carrier_freq;
rx->sample_rate = sample_rate;
rx->received = new float[MAX_SAMPLES]();
rx->demodulated = new float[MAX_SAMPLES]();
rx->bit_count = 0;
rx->sample_count = 0;
memset(rx->decoded_text, 0, sizeof(rx->decoded_text));
memset(rx->binary_data, 0, sizeof(rx->binary_data));
}
// ================= 信号生成 =================
void generate_signal(Transmitter* tx, int duration_ms) {
int num_samples = (duration_ms * tx->sample_rate) / 1000;
if (num_samples > MAX_SAMPLES) num_samples = MAX_SAMPLES;
tx->sample_count = num_samples;
switch (tx->signal_type) {
case SINE_WAVE:
for (int i = 0; i < num_samples; i++) {
float t = static_cast<float>(i) / tx->sample_rate;
tx->samples[i] = sin(2 * M_PI * 5.0f * t);
}
break;
case SQUARE_WAVE:
for (int i = 0; i < num_samples; i++) {
float t = static_cast<float>(i) / tx->sample_rate;
tx->samples[i] = (sin(2 * M_PI * 3.0f * t) > 0 ? 1.0f : -1.0f);
}
break;
case SAWTOOTH_WAVE:
for (int i = 0; i < num_samples; i++) {
float t = static_cast<float>(i) / tx->sample_rate;
tx->samples[i] = 2.0f * (t * 4.0f - floorf(t * 4.0f + 0.5f));
}
break;
case RANDOM_DATA: {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
for (int i = 0; i < num_samples; i++) {
tx->samples[i] = dist(gen);
}
break;
}
case TEXT_DATA:
case FILE_DATA:
// 在专用函数中处理
break;
}
}
// ================= 文本数据处理 =================
void set_text_data(Transmitter* tx, const char* text) {
// 直接存储UTF-8字节序列
size_t len = strlen(text);
if (len >= MAX_TEXT_LENGTH) len = MAX_TEXT_LENGTH - 1;
memcpy(tx->text_data, text, len);
tx->text_data[len] = '\0';
tx->bit_count = 0;
// 处理整个UTF-8字节序列
for (size_t i = 0; i < len; i++) {
uint8_t c = (uint8_t)tx->text_data[i];
for (int j = 7; j >= 0; j--) {
if (tx->bit_count < MAX_BITS) {
tx->binary_data[tx->bit_count++] = (c >> j) & 1;
}
}
}
// 生成信号波形
const float symbol_transition = 0.2f; // 符号过渡时间比例
tx->sample_count = tx->bit_count * static_cast<int>(SAMPLES_PER_BIT);
if (tx->sample_count > MAX_SAMPLES) {
tx->sample_count = MAX_SAMPLES;
tx->bit_count = tx->sample_count / static_cast<int>(SAMPLES_PER_BIT);
}
for (int i = 0; i < tx->bit_count; i++) {
for (int j = 0; j < static_cast<int>(SAMPLES_PER_BIT); j++) {
int idx = i * static_cast<int>(SAMPLES_PER_BIT) + j;
if (idx < MAX_SAMPLES) break;
float position = static_cast<float>(j) / SAMPLES_PER_BIT;
float symbol = tx->binary_data[i] ? 1.0f : -1.0f;
// 在符号边界添加平滑过渡
if (j < symbol_transition * SAMPLES_PER_BIT) {
// 与前一个符号的过渡
float prev_symbol = (i > 0) ?
(tx->binary_data[i - 1] ? 1.0f : -1.0f) : symbol;
float factor = j / (symbol_transition * SAMPLES_PER_BIT);
tx->samples[idx] = prev_symbol * (1 - factor) + symbol * factor;
}
else if (j > (1 - symbol_transition) * SAMPLES_PER_BIT) {
// 与下一个符号的过渡
float next_symbol = (i < tx->bit_count - 1) ?
(tx->binary_data[i + 1] ? 1.0f : -1.0f) : symbol;
float factor = (j - (1 - symbol_transition) * SAMPLES_PER_BIT) /
(symbol_transition * SAMPLES_PER_BIT);
tx->samples[idx] = symbol * (1 - factor) + next_symbol * factor;
}
else {
tx->samples[idx] = symbol;
}
}
}
// 汉明编码
int original_bit_count = tx->bit_count;
encode_hamming(tx->binary_data, tx->bit_count);
tx->original_bit_count = original_bit_count;
}
// ================= 文件数据处理 =================
void load_file_data(Transmitter* tx, const char* filename) {
strncpy(tx->filename, filename, 255);
tx->filename[255] = '\0';
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "无法打开文件:" << filename;
return;
}
QTextStream in(&file);
tx->sample_count = 0;
while (!in.atEnd() && tx->sample_count < MAX_SAMPLES) {
QString line = in.readLine();
bool ok;
float value = line.toFloat(&ok);
if (ok) {
tx->samples[tx->sample_count++] = value;
}
}
file.close();
}
// ================= 调制函数 =================
void modulate_signal(Transmitter* tx) {
qDebug() << "调制信号 - 类型:" << tx->mod_type
<< "载波频率:" << tx->carrier_freq
<< "采样数:" << tx->sample_count;
if (tx->signal_type == TEXT_DATA && tx->bit_count == 0) {
qWarning() << "文本数据未设置!";
return;
}
if (tx->sample_count == 0) return;
for (int i = 0; i < tx->sample_count; i++) {
float t = static_cast<float>(i) / tx->sample_rate;
float carrier = sin(2 * M_PI * tx->carrier_freq * t);
float quadrature = cos(2 * M_PI * tx->carrier_freq * t);
switch (tx->mod_type) {
case BPSK: {
float symbol = 0.0f;
if (tx->signal_type == TEXT_DATA) {
int bit_index = i / static_cast<int>(SAMPLES_PER_BIT);
if (bit_index < tx->bit_count) {
symbol = tx->binary_data[bit_index] ? 1.0f : -1.0f;
}
}
else {
symbol = tx->samples[i];
}
tx->modulated[i] = symbol * carrier;
break;
}
case QPSK: {
if (tx->signal_type == TEXT_DATA) {
int symbol_index = i / static_cast<int>(2 * SAMPLES_PER_BIT);
if (symbol_index < tx->bit_count / 2) {
int bit_index = symbol_index * 2;
int bit1 = tx->binary_data[bit_index];
int bit2 = tx->binary_data[bit_index + 1];
float I = (bit1 == 0) ? -1.0f : 1.0f;
float Q = (bit2 == 0) ? -1.0f : 1.0f;
tx->modulated[i] = I * carrier + Q * quadrature;
}
else {
tx->modulated[i] = 0.0f;
}
}
else {
tx->modulated[i] = tx->samples[i] * carrier;
}
break;
}
case FSK: {
float base_freq = tx->carrier_freq;
float freq_shift = 500.0f;
if (tx->signal_type == TEXT_DATA) {
int bit_index = i / static_cast<int>(SAMPLES_PER_BIT);
float freq = base_freq;
if (bit_index < tx->bit_count) {
freq += tx->binary_data[bit_index] ? freq_shift : -freq_shift;
}
tx->modulated[i] = sin(2 * M_PI * freq * t);
}
else {
float freq = base_freq + (tx->samples[i] > 0 ? freq_shift : -freq_shift);
tx->modulated[i] = sin(2 * M_PI * freq * t);
}
break;
}
case AM: {
float modulation_index = 0.8f;
float analog = 0.0f;
if (tx->signal_type == TEXT_DATA) {
int bit_index = i / static_cast<int>(SAMPLES_PER_BIT);
if (bit_index < tx->bit_count) {
analog = tx->binary_data[bit_index] ? 1.0f : -1.0f;
}
}
else {
analog = tx->samples[i];
}
tx->modulated[i] = (1.0f + modulation_index * analog) * carrier;
break;
}
}
}
// 添加噪声
apply_noise(tx->modulated, tx->sample_count, 50.0f); // 10dB SNR
}
// ================= 解调函数 =================
// 改进的BPSK解调函数 - 使用Costas环载波恢复
void demodulate_bpsk(Receiver* rx) {
const float loop_gain = 0.01f; // 环路增益
float phase_estimate = 0.0f;
float freq_offset = 0.0f;
float last_filtered = 0.0f;
const float alpha = 0.05f; // 低通滤波系数
// Costas环载波跟踪
for (int i = 0; i < rx->sample_count; i++) {
float t = static_cast<float>(i) / rx->sample_rate;
// 生成本地载波
float local_carrier_i = sin(2 * M_PI * rx->carrier_freq * t + phase_estimate);
float local_carrier_q = cos(2 * M_PI * rx->carrier_freq * t + phase_estimate);
// 相干解调
float I = rx->received[i] * local_carrier_i;
float Q = rx->received[i] * local_carrier_q;
// 低通滤波
I = alpha * I + (1 - alpha) * last_filtered;
last_filtered = I;
// 相位误差检测
float phase_error = 0.0f;
if (fabs(I) > 0.001f) { // 避免除零
phase_error = Q / I;
}
// 频率和相位更新
freq_offset += loop_gain * phase_error;
phase_estimate += loop_gain * phase_error + freq_offset;
// 限幅相位估计
while (phase_estimate > M_PI) phase_estimate -= 2 * M_PI;
while (phase_estimate < -M_PI) phase_estimate += 2 * M_PI;
rx->demodulated[i] = I; // I路为解调输出
}
}
void demodulate_qpsk(Receiver* rx) {
float last_i = 0.0f, last_q = 0.0f;
const float alpha = 0.1f; // 低通滤波系数
for (int i = 0; i < rx->sample_count; i++) {
float t = static_cast<float>(i) / rx->sample_rate;
float carrier = sin(2 * M_PI * rx->carrier_freq * t);
float quadrature = cos(2 * M_PI * rx->carrier_freq * t);
// I路解调
float i_mixed = rx->received[i] * carrier;
float i_filtered = alpha * i_mixed + (1.0f - alpha) * last_i;
last_i = i_filtered;
// Q路解调
float q_mixed = rx->received[i] * quadrature;
float q_filtered = alpha * q_mixed + (1.0f - alpha) * last_q;
last_q = q_filtered;
// 合并为幅度信号
rx->demodulated[i] = sqrt(i_filtered * i_filtered + q_filtered * q_filtered);
}
}
void demodulate_fsk(Receiver* rx) {
if (rx->sample_count == 0) return;
// 创建两个频率的载波表,优化计算效率
QVector<float> carrier1(rx->sample_count);
QVector<float> carrier2(rx->sample_count);
for (int i = 0; i < rx->sample_count; i++) {
float t = static_cast<float>(i) / rx->sample_rate;
carrier1[i] = qSin(2 * M_PI * rx->carrier_freq * t);
carrier2[i] = qSin(2 * M_PI * (rx->carrier_freq + FSK_FREQ_SHIFT) * t);
}
// 滑动窗口相关器实现FSK解调
const int window_size = SAMPLES_PER_BIT / 2; // 相关窗口大小
QVector<float> demod_result(rx->sample_count);
for (int i = window_size; i < rx->sample_count - window_size; i++) {
float sum1 = 0.0f;
float sum2 = 0.0f;
// 计算窗口内与两个载波的相关性
for (int j = -window_size; j <= window_size; j++) {
sum1 += rx->received[i + j] * carrier1[i + j];
sum2 += rx->received[i + j] * carrier2[i + j];
}
// 归一化并计算差分
demod_result[i] = (sum1 - sum2) / (2 * window_size + 1);
}
// 低通滤波以平滑结果
const float alpha = 0.1f;
float filtered = 0.0f;
for (int i = 0; i < rx->sample_count; i++) {
filtered = alpha * demod_result[i] + (1.0f - alpha) * filtered;
rx->demodulated[i] = filtered;
}
qDebug() << "FSK解调完成,样本数:" << rx->sample_count;
}
// 改进AM解调:使用非相干解调
void demodulate_am(Receiver* rx) {
float last_env = 0.0f;
const float alpha = 0.05f; // 包络检测系数
for (int i = 0; i < rx->sample_count; i++) {
// 计算包络
float env = fabs(rx->received[i]);
env = alpha * env + (1.0f - alpha) * last_env;
last_env = env;
// 移除DC分量
static float dc_estimate = 0.0f;
const float dc_alpha = 0.001f;
dc_estimate = (1 - dc_alpha) * dc_estimate + dc_alpha * env;
rx->demodulated[i] = env - dc_estimate;
}
// 归一化
float max_val = 0.001f;
for (int i = 0; i < rx->sample_count; i++) {
if (fabs(rx->demodulated[i]) > max_val)
max_val = fabs(rx->demodulated[i]);
}
float scale = 1.0f / max_val;
for (int i = 0; i < rx->sample_count; i++) {
rx->demodulated[i] *= scale;
}
}
// 添加在 communication_system.cpp 文件中
void equalize_signal(Receiver* rx) {
// 简单的均衡:归一化信号幅度
float max_val = 0.001f;
for (int i = 0; i < rx->sample_count; i++) {
if (fabs(rx->demodulated[i]) > max_val) {
max_val = fabs(rx->demodulated[i]);
}
}
float scale = 1.0f / max_val;
for (int i = 0; i < rx->sample_count; i++) {
rx->demodulated[i] *= scale;
}
}
// 添加在 communication_system.cpp 文件中
void resolve_phase_ambiguity(Receiver* rx) {
// 简单的相位模糊解决方案
// 检查第一个符号的极性(假设应为正)
if (rx->sample_count > 10) {
float first_symbol = rx->received[static_cast<int>(SAMPLES_PER_BIT / 2)];
if (first_symbol < 0) {
// 翻转整个信号
for (int i = 0; i < rx->sample_count; i++) {
rx->received[i] = -rx->received[i];
}
}
}
}
// 添加在 communication_system.cpp 文件中
float interpolate(const float* data, int index, float fraction) {
if (index < 0) return data[0];
if (index >= MAX_SAMPLES - 1) return data[MAX_SAMPLES - 1];
return data[index] + fraction * (data[index + 1] - data[index]);
}
void demodulate_signal(Receiver* rx) {
qDebug() << "解调信号 - 类型:" << rx->mod_type
<< "载波频率:" << rx->carrier_freq
<< "采样数:" << rx->sample_count;
if (rx->sample_count <= 0) return;
// 确保有足够内存
if (rx->demodulated == nullptr) {
rx->demodulated = new float[MAX_SAMPLES]();
}
// 添加接收端同步处理
synchronize_receiver(rx);
// 根据调制类型选择解调方法
switch (rx->mod_type) {
case BPSK:
demodulate_bpsk(rx);
break;
case QPSK:
demodulate_qpsk(rx);
break;
case FSK:
demodulate_fsk(rx);
break;
case AM:
demodulate_am(rx);
break;
}
// 添加均衡处理
equalize_signal(rx);
}
// 综合同步函数
void synchronize_receiver(Receiver* rx) {
// 1. 频率同步
compensate_cfo(rx);
// 2. 符号定时同步
timing_recovery(rx);
// 3. 帧同步
int sync_offset = find_frame_header(rx->received, rx->sample_count, FRAME_HEADER);
if (sync_offset > 0) {
// 对齐信号
memmove(rx->received, rx->received + sync_offset,
(rx->sample_count - sync_offset) * sizeof(float));
rx->sample_count -= sync_offset;
}
// 4. 相位同步
resolve_phase_ambiguity(rx);
}
// 载波频率偏移补偿
void compensate_cfo(Receiver* rx) {
const int training_length = 16; // 训练序列长度
float phase_diff = 0.0f;
int count = 0;
for (int i = 0; i < training_length - 1; i++) {
float phase1 = atan2(rx->received[i + 1], rx->received[i]);
float phase2 = atan2(rx->received[i + training_length / 2 + 1],
rx->received[i + training_length / 2]);
phase_diff += phase2 - phase1;
count++;
}
if (count > 0) {
phase_diff /= count;
float cfo = phase_diff * rx->sample_rate / (2 * M_PI * training_length / 2);
// 补偿频率偏移
for (int i = 0; i < rx->sample_count; i++) {
float t = static_cast<float>(i) / rx->sample_rate;
float phase_comp = 2 * M_PI * cfo * t;
rx->received[i] = rx->received[i] * cos(phase_comp);
}
}
}
// 精确的定时恢复
void timing_recovery(Receiver* rx) {
const int samples_per_symbol = static_cast<int>(SAMPLES_PER_BIT);
float timing_offset = 0.0f;
float error = 0.0f;
const float mu = 0.01f; // 收敛因子
// 早-迟门定时恢复
for (int i = 1; i < rx->sample_count - samples_per_symbol; i += samples_per_symbol) {
float early = rx->received[i - 1];
float late = rx->received[i + 1];
float on_time = rx->received[i];
error = early * on_time - late * on_time;
timing_offset += mu * error;
// 应用插值
int adjusted_index = i + static_cast<int>(timing_offset);
if (adjusted_index >= 0 && adjusted_index < rx->sample_count) {
float fraction = timing_offset - floor(timing_offset);
rx->received[i] = interpolate(rx->received, adjusted_index, fraction);
}
}
}
// ================= 解码函数 =================
void decode_signal(Receiver* rx) {
if (rx->sample_count == 0) return;
if (rx->signal_type != TEXT_DATA) return;
// 计算比特数
rx->bit_count = rx->sample_count / SAMPLES_PER_BIT;
if (rx->bit_count > MAX_BITS) rx->bit_count = MAX_BITS;
// 寻找帧头进行同步 (假设帧头为01010101)
const QByteArray frame_header = QByteArray::fromHex("55555555AA"); // 01010101
const int header_length = frame_header.size() * 8;
int sync_offset = find_frame_header(rx->demodulated, rx->sample_count, frame_header);
if (sync_offset < 0) {
qWarning() << "帧同步失败,尝试重新采样...";
// 降低采样率重试
QVector<float> resampled;
const int new_rate = rx->sample_rate / 2;
for (int i = 0; i < rx->sample_count; i += 2) {
resampled.append(rx->demodulated[i]);
}
sync_offset = find_frame_header(resampled.data(), resampled.size(), frame_header);
}
qDebug() << "帧同步成功,偏移量:" << sync_offset << "样本";
// 从同步点开始解码
int start_index = sync_offset + SAMPLES_PER_BIT; // 跳过帧头
// 使用自适应阈值解码
for (int i = 0; i < rx->bit_count; i++) {
int bit_start = static_cast<int>(start_index + i * SAMPLES_PER_BIT);
if (bit_start >= rx->sample_count) break;
int mid_point = bit_start + SAMPLES_PER_BIT / 2;
if (mid_point >= rx->sample_count) continue;
// 计算当前比特周期的平均值作为阈值
float sum = 0.0f;
int valid_samples = 0;
for (int j = 0; j < SAMPLES_PER_BIT; j++) {
if (bit_start + j < rx->sample_count) {
sum += rx->demodulated[bit_start + j];
valid_samples++;
}
}
if (valid_samples > 0) {
float threshold = sum / valid_samples;
// 修复后的行:确保索引为整数类型
float mid_value = rx->demodulated[mid_point];
rx->binary_data[i] = (mid_value > threshold) ? 1 : 0;
}
}
// 汉明解码
int decoded_bit_count = decode_hamming(rx->binary_data, rx->bit_count);
if (decoded_bit_count <= 0) {
qWarning() << "汉明解码失败,无法纠正错误";
return;
}
// 转换为文本
QByteArray byteArray;
int byte_count = decoded_bit_count / 8;
for (int i = 0; i < byte_count; i++) {
uint8_t byte = 0;
for (int j = 0; j < 8; j++) {
int bit_index = i * 8 + j;
if (bit_index < decoded_bit_count) {
byte = (byte << 1) | (rx->binary_data[bit_index] ? 1 : 0);
}
}
byteArray.append(byte);
}
QString decodedText = QString::fromUtf8(byteArray);
strncpy(rx->decoded_text, decodedText.toUtf8().constData(), MAX_TEXT_LENGTH - 1);
rx->decoded_text[MAX_TEXT_LENGTH - 1] = '\0';
qDebug() << "解码成功,文本:" << decodedText;
}
// 添加帧头搜索函数
// 改进的帧头搜索函数
int find_frame_header(const float* data, int length, const QByteArray& header) {
const int header_bytes = header.size();
const int sync_length = 32; // 同步序列长度(位)
const int sample_per_bit = static_cast<int>(SAMPLES_PER_BIT);
//if (search_range <= 0) return -1;
// 创建理想帧头波形
QVector<float> sync_pattern(sync_length * sample_per_bit);
int bit = 1;
for (int i = 0; i < sync_length; i++) {
bit = (i % 2 == 0) ? bit : !bit; // 交替10
for (int j = 0; j < sample_per_bit; j++) {
sync_pattern[i * sample_per_bit + j] = bit ? 1.0f : -1.0f;
}
}
// 使用互相关搜索
int best_offset = -1;
float max_correlation = -FLT_MAX;
const int search_range = length - sync_pattern.size();
for (int offset = 0; offset < search_range; offset += sample_per_bit / 4) {
float signal_energy = 0.0f;
float corr = 0.0f;
for (int i = 0; i < sync_pattern.size(); i++) {
corr += data[offset + i] * sync_pattern[i];
signal_energy += data[offset + i] * data[offset + i];
}
// 归一化互相关
float norm_corr = corr / sqrt(signal_energy * sync_pattern.size());
if (norm_corr > max_correlation) {
max_correlation = norm_corr;
best_offset = offset;
}
}
// 阈值判定(经验值)
// float threshold = header_waveform.size() * 0.6f;
return (max_correlation > 0.6f) ? best_offset : -1;
}
// ================= 汉明编解码 =================
void encode_hamming(uint8_t* data, int& bit_count) {
int original_count = bit_count;
int hamming_count = (original_count * 7) / 4;
if (hamming_count > MAX_BITS) hamming_count = MAX_BITS;
uint8_t* hamming_data = new uint8_t[MAX_BITS]();
int h_index = 0;
for (int i = 0; i < original_count; i += 4) {
if (h_index + 7 >= MAX_BITS) break;
if (i + 3 >= original_count) break;
uint8_t d1 = data[i];
uint8_t d2 = data[i + 1];
uint8_t d3 = data[i + 2];
uint8_t d4 = data[i + 3];
// 确保数据位是0或1
// d1 = data[i] ? 1 : 0;
// d2 = data[i + 1] ? 1 : 0;
// d3 = data[i + 2] ? 1 : 0;
// d4 = data[i + 3] ? 1 : 0;
// 计算校验位
uint8_t p1 = d1 ^ d2 ^ d4;
uint8_t p2 = d1 ^ d3 ^ d4;
uint8_t p3 = d2 ^ d3 ^ d4;
hamming_data[h_index++] = p1;
hamming_data[h_index++] = p2;
hamming_data[h_index++] = d1;
hamming_data[h_index++] = p3;
hamming_data[h_index++] = d2;
hamming_data[h_index++] = d3;
hamming_data[h_index++] = d4;
}
// 复制回原数组
memcpy(data, hamming_data, h_index);
bit_count = h_index;
delete[] hamming_data;
}
int decode_hamming(uint8_t* data, int bit_count) {
int decoded_count = 0;
uint8_t* decoded_data = new uint8_t[MAX_BITS]();
for (int i = 0; i < bit_count; i += 7) {
if (i + 6 >= bit_count) break;
if (decoded_count + 4 >= MAX_BITS) break;
uint8_t p1 = data[i];
uint8_t p2 = data[i + 1];
uint8_t d1 = data[i + 2];
uint8_t p3 = data[i + 3];
uint8_t d2 = data[i + 4];
uint8_t d3 = data[i + 5];
uint8_t d4 = data[i + 6];
// 确保数据位是0或1
/* p1 = data[i] ? 1 : 0;
p2 = data[i + 1] ? 1 : 0;
d1 = data[i + 2] ? 1 : 0;
p3 = data[i + 3] ? 1 : 0;
d2 = data[i + 4] ? 1 : 0;
d3 = data[i + 5] ? 1 : 0;
d4 = data[i + 6] ? 1 : 0;*/
// 计算校验子
uint8_t s1 = p1 ^ d1 ^ d2 ^ d4;
uint8_t s2 = p2 ^ d1 ^ d3 ^ d4;
uint8_t s3 = p3 ^ d2 ^ d3 ^ d4;
int error_pos = s1 + (s2 << 1) + (s3 << 2);
// 错误纠正
if (error_pos > 0) {
switch (error_pos) {
case 1: p1 ^= 1; break;
case 2: p2 ^= 1; break;
case 3: d1 ^= 1; break;
case 4: p3 ^= 1; break;
case 5: d2 ^= 1; break;
case 6: d3 ^= 1; break;
case 7: d4 ^= 1; break;
}
}
// 提取数据位
decoded_data[decoded_count++] = d1;
decoded_data[decoded_count++] = d2;
decoded_data[decoded_count++] = d3;
decoded_data[decoded_count++] = d4;
}
// 复制回原数组
memcpy(data, decoded_data, decoded_count);
delete[] decoded_data;
return decoded_count;
}
// ================= 文件操作 =================
void save_signal_to_file(const char* filename, const float* data, int count,
int sample_rate, SignalType sig_type, ModulationType mod_type) {
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
qWarning() << "无法打开文件进行写入:" << filename;
return;
}
QDataStream out(&file);
out.setVersion(QDataStream::Qt_5_9);
// 写入文件头
out << static_cast<qint32>(sample_rate);
out << static_cast<qint32>(sig_type);
out << static_cast<qint32>(mod_type);
out << static_cast<qint32>(count);
// 写入数据
for (int i = 0; i < count; i++) {
out << static_cast<float>(data[i]);
}
file.close();
}
void load_signal_from_file(const char* filename, float* data, int* count,
int* sample_rate, SignalType* sig_type, ModulationType* mod_type) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "无法打开文件进行读取:" << filename;
return;
}
QDataStream in(&file);
in.setVersion(QDataStream::Qt_5_9);
// 读取文件头
qint32 sr, st, mt, c;
in >> sr;
in >> st;
in >> mt;
in >> c;
*sample_rate = sr;
*sig_type = static_cast<SignalType>(st);
*mod_type = static_cast<ModulationType>(mt);
*count = (c > MAX_SAMPLES) ? MAX_SAMPLES : c;
// 读取数据
for (int i = 0; i < *count; i++) {
float value;
in >> value;
data[i] = value;
}
file.close();
}
// ================= 噪声处理 =================
void apply_noise(float* signal, int count, float snr_db) {
// 计算信号功率
float signal_power = 0.0f;
for (int i = 0; i < count; i++) {
signal_power += signal[i] * signal[i];
}
signal_power /= static_cast<float>(count);
// 计算噪声功率
float snr_linear = powf(10.0f, snr_db / 10.0f);
float noise_power = signal_power / snr_linear;
float noise_stddev = sqrtf(noise_power);
// 生成高斯噪声
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<float> dist(0.0f, noise_stddev);
// 添加噪声
for (int i = 0; i < count; i++) {
signal[i] += dist(gen);
}
}
// ================= GUI实现 =================
CommunicationSystemGUI::CommunicationSystemGUI(QWidget* parent)
: QMainWindow(parent),
sourceWaveformView(new QChartView(this)),
sourceSpectrumView(new QChartView(this)),
modulatedWaveformView(new QChartView(this)),
modulatedSpectrumView(new QChartView(this)),
receivedWaveformView(new QChartView(this)),
receivedSpectrumView(new QChartView(this)),
demodulatedWaveformView(new QChartView(this)),
audioInput(nullptr),
audioOutput(nullptr)
{
// 初始化窗口
setWindowTitle("数字通信系统");
resize(1200, 800);
// 创建主布局
QWidget* centralWidget = new QWidget(this);
QVBoxLayout* mainLayout = new QVBoxLayout(centralWidget);
setCentralWidget(centralWidget);
// 创建分割器
QSplitter* mainSplitter = new QSplitter(Qt::Vertical, centralWidget);
mainLayout->addWidget(mainSplitter);
// 创建控制面板
QWidget* controlWidget = new QWidget();
QHBoxLayout* controlLayout = new QHBoxLayout(controlWidget);
// 创建发送方控制组
createTransmitterGroup();
controlLayout->addWidget(transmitterGroup);
// 创建接收方控制组
createReceiverGroup();
controlLayout->addWidget(receiverGroup);
mainSplitter->addWidget(controlWidget);
// 创建波形显示区域
createWaveformDisplays();
mainSplitter->addWidget(waveformFrame);
// 设置分割器比例
mainSplitter->setSizes({ 200, 600 });
// 创建状态栏
statusBar = new QStatusBar();
setStatusBar(statusBar);
// 创建状态栏组件
transmitStatusLabel = new QLabel("发送状态: 空闲");
receiveStatusLabel = new QLabel("接收状态: 空闲");
transmitProgressBar = new QProgressBar();
transmitProgressBar->setRange(0, 100);
transmitProgressBar->setFixedWidth(150);
transmitProgressBar->setTextVisible(true);
receiveProgressBar = new QProgressBar();
receiveProgressBar->setRange(0, 100);
receiveProgressBar->setFixedWidth(150);
receiveProgressBar->setTextVisible(true);
// 添加到状态栏
statusBar->addPermanentWidget(transmitStatusLabel);
statusBar->addPermanentWidget(transmitProgressBar);
statusBar->addPermanentWidget(receiveStatusLabel);
statusBar->addPermanentWidget(receiveProgressBar);
// 确保接收器内存分配正确
receiver.received = new float[MAX_SAMPLES]();
receiver.demodulated = new float[MAX_SAMPLES]();
// 初始化通信模块
init_transmitter(&transmitter, SINE_WAVE, BPSK, CARRIER_FREQ, SAMPLE_RATE);
init_receiver(&receiver, CARRIER_FREQ, SAMPLE_RATE);
// 初始化音频设备
initAudio();
}
CommunicationSystemGUI::~CommunicationSystemGUI() {
delete[] transmitter.samples;
delete[] transmitter.modulated;
delete[] receiver.received;
delete[] receiver.demodulated;
delete audioInput;
delete audioOutput;
}
void CommunicationSystemGUI::createTransmitterGroup() {
transmitterGroup = new QGroupBox("发送方");
QGridLayout* layout = new QGridLayout(transmitterGroup);
// 信号类型
layout->addWidget(new QLabel("信号类型:"), 0, 0);
signalTypeCombo = new QComboBox();
signalTypeCombo->addItem("正弦波", SINE_WAVE);
signalTypeCombo->addItem("方波", SQUARE_WAVE);
signalTypeCombo->addItem("锯齿波", SAWTOOTH_WAVE);
signalTypeCombo->addItem("随机数据", RANDOM_DATA);
signalTypeCombo->addItem("文本数据", TEXT_DATA);
signalTypeCombo->addItem("文件数据", FILE_DATA);
layout->addWidget(signalTypeCombo, 0, 1);
// 调制类型
layout->addWidget(new QLabel("调制类型:"), 1, 0);
modulationTypeCombo = new QComboBox();
modulationTypeCombo->addItem("BPSK", BPSK);
modulationTypeCombo->addItem("QPSK", QPSK);
modulationTypeCombo->addItem("FSK", FSK);
modulationTypeCombo->addItem("AM", AM);
layout->addWidget(modulationTypeCombo, 1, 1);
// 载波频率
layout->addWidget(new QLabel("载波频率(Hz):"), 2, 0);
carrierFreqEdit = new QLineEdit(QString::number(CARRIER_FREQ));
carrierFreqEdit->setValidator(new QDoubleValidator(100, 10000, 2, this));
layout->addWidget(carrierFreqEdit, 2, 1);
// 文本输入
layout->addWidget(new QLabel("文本数据:"), 3, 0, 1, 2);
textDataEdit = new QTextEdit();
textDataEdit->setMaximumHeight(60);
layout->addWidget(textDataEdit, 4, 0, 1, 2);
// 按钮
setTextButton = new QPushButton("设置文本");
loadFileButton = new QPushButton("加载文件");
generateButton = new QPushButton("生成信号");
modulateButton = new QPushButton("调制");
transmitButton = new QPushButton("传输");
saveSignalButton = new QPushButton("保存信号");
layout->addWidget(setTextButton, 5, 0);
layout->addWidget(loadFileButton, 5, 1);
layout->addWidget(generateButton, 6, 0);
layout->addWidget(modulateButton, 6, 1);
layout->addWidget(transmitButton, 7, 0);
layout->addWidget(saveSignalButton, 7, 1);
// 连接信号槽
connect(signalTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &CommunicationSystemGUI::onSignalTypeChanged);
connect(setTextButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onSetTextData);
connect(loadFileButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onLoadFileData);
connect(generateButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onGenerateSignal);
connect(modulateButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onModulateSignal);
connect(transmitButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onTransmitSignal);
connect(saveSignalButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onSaveSignal);
}
void CommunicationSystemGUI::createReceiverGroup() {
receiverGroup = new QGroupBox("接收方");
QGridLayout* layout = new QGridLayout(receiverGroup);
// 按钮
loadSignalButton = new QPushButton("加载信号");
receiveButton = new QPushButton("接收");
demodulateButton = new QPushButton("解调");
decodeButton = new QPushButton("解码");
saveReceivedButton = new QPushButton("保存接收");
saveDecodedButton = new QPushButton("保存解码");
layout->addWidget(loadSignalButton, 0, 0);
layout->addWidget(receiveButton, 0, 1);
layout->addWidget(demodulateButton, 1, 0);
layout->addWidget(decodeButton, 1, 1);
layout->addWidget(saveReceivedButton, 2, 0);
layout->addWidget(saveDecodedButton, 2, 1);
// 解码文本显示
decodedTextEdit = new QTextEdit();
decodedTextEdit->setReadOnly(true);
decodedTextEdit->setMaximumHeight(80);
layout->addWidget(new QLabel("解码文本:"), 3, 0, 1, 2);
layout->addWidget(decodedTextEdit, 4, 0, 1, 2);
// 连接信号槽
connect(loadSignalButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onLoadSignal);
connect(receiveButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onReceiveSignal);
connect(demodulateButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onDemodulateSignal);
connect(decodeButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onDecodeSignal);
connect(saveReceivedButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onSaveReceived);
connect(saveDecodedButton, &QPushButton::clicked, this, &CommunicationSystemGUI::onSaveDecoded);
}
void CommunicationSystemGUI::createWaveformDisplays() {
waveformFrame = new QFrame();
QGridLayout* gridLayout = new QGridLayout(waveformFrame);
// 第一行:源信号波形(左)和调制信号波形(右)
sourceWaveformView = new QChartView();
modulatedWaveformView = new QChartView();
gridLayout->addWidget(new QLabel("源信号波形"), 0, 0);
gridLayout->addWidget(sourceWaveformView, 1, 0);
gridLayout->addWidget(new QLabel("调制信号波形"), 0, 1);
gridLayout->addWidget(modulatedWaveformView, 1, 1);
// 第二行:接收信号波形(左)和解调信号波形(右)
receivedWaveformView = new QChartView();
demodulatedWaveformView = new QChartView();
gridLayout->addWidget(new QLabel("接收信号波形"), 2, 0);
gridLayout->addWidget(receivedWaveformView, 3, 0);
gridLayout->addWidget(new QLabel("解调信号波形"), 2, 1);
gridLayout->addWidget(demodulatedWaveformView, 3, 1);
// 设置行和列的比例
gridLayout->setRowStretch(1, 1);
gridLayout->setRowStretch(3, 1);
gridLayout->setColumnStretch(0, 1);
gridLayout->setColumnStretch(1, 1);
}
void CommunicationSystemGUI::initAudio() {
QAudioFormat format;
format.setSampleRate(SAMPLE_RATE);
format.setChannelCount(1);
format.setSampleSize(32);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::Float);
// 输入设备
QAudioDeviceInfo inputDevice = QAudioDeviceInfo::defaultInputDevice();
if (!inputDevice.isFormatSupported(format)) {
qWarning() << "输入设备不支持请求的格式,使用最接近的匹配";
format = inputDevice.nearestFormat(format);
}
if (!inputDevice.isFormatSupported(format)) {
qWarning() << "默认格式不支持,使用最接近的格式";
format = inputDevice.nearestFormat(format);
}
audioInput = new QAudioInput(inputDevice, format, this);
// 输出设备
QAudioDeviceInfo outputDevice = QAudioDeviceInfo::defaultOutputDevice();
if (outputDevice.isNull()) {
qWarning() << "未找到音频输出设备";
return;
}
if (!outputDevice.isFormatSupported(format)) {
qWarning() << "默认格式不支持,使用最接近的格式";
format = outputDevice.nearestFormat(format);
}
audioOutput = new QAudioOutput(outputDevice, format, this);
}
// ================= 核心功能实现 =================
void CommunicationSystemGUI::onGenerateSignal() {
transmitter.signal_type = static_cast<SignalType>(signalTypeCombo->currentData().toInt());
transmitter.mod_type = static_cast<ModulationType>(modulationTypeCombo->currentData().toInt());
transmitter.carrier_freq = carrierFreqEdit->text().toFloat();
if (transmitter.signal_type == TEXT_DATA) {
onSetTextData();
}
else if (transmitter.signal_type == FILE_DATA) {
onLoadFileData();
}
else {
generate_signal(&transmitter, 1000); // 1秒信号
plotSignal(sourceWaveformView, transmitter.samples,
transmitter.sample_count, "源信号波形");
}
showStatusMessage("信号生成完成");
}
void CommunicationSystemGUI::onModulateSignal() {
if (transmitter.sample_count == 0) {
QMessageBox::warning(this, "错误", "请先生成信号");
return;
}
modulate_signal(&transmitter);
plotSignal(modulatedWaveformView, transmitter.modulated,
transmitter.sample_count, "调制信号波形");
showStatusMessage("信号调制完成");
}
void CommunicationSystemGUI::onSetTextData() {
QString text = textDataEdit->toPlainText();
if (text.isEmpty()) {
QMessageBox::warning(this, "错误", "请输入文本");
return;
}
// 使用QString确保正确处理中文
QByteArray utf8Data = text.toUtf8();
set_text_data(&transmitter, utf8Data.constData());
set_text_data(&transmitter, text.toUtf8().constData());
plotSignal(sourceWaveformView, transmitter.samples,
transmitter.sample_count, "文本信号波形");
showStatusMessage("文本数据已设置");
}
void CommunicationSystemGUI::onLoadFileData() {
QString filename = QFileDialog::getOpenFileName(this, "打开数据文件");
if (!filename.isEmpty()) {
load_file_data(&transmitter, filename.toUtf8().constData());
plotSignal(sourceWaveformView, transmitter.samples,
transmitter.sample_count, "文件数据波形");
showStatusMessage("文件数据已加载");
}
}
void CommunicationSystemGUI::onDemodulateSignal() {
if (receiver.sample_count == 0) {
QMessageBox::warning(this, "错误", "没有可解调的信号");
return;
}
// 传递发送方的信号类型和调制类型
receiver.signal_type = transmitter.signal_type;
receiver.mod_type = transmitter.mod_type;
demodulate_signal(&receiver);
plotSignal(demodulatedWaveformView, receiver.demodulated,
receiver.sample_count, "解调信号波形");
// 如果是文本信号,自动解码
if (receiver.signal_type == TEXT_DATA) {
onDecodeSignal();
}
showStatusMessage("信号解调完成");
}
void CommunicationSystemGUI::onDecodeSignal() {
if (receiver.sample_count == 0) {
QMessageBox::warning(this, "错误", "没有可解码的信号");
return;
}
decode_signal(&receiver);
if (strlen(receiver.decoded_text) > 0) {
decodedTextEdit->setPlainText(receiver.decoded_text);
showStatusMessage("解码成功");
}
else {
decodedTextEdit->setPlainText("解码失败:请检查调制设置和信号质量");
showStatusMessage("解码失败");
}
}
void CommunicationSystemGUI::onSaveSignal() {
if (transmitter.sample_count == 0) {
QMessageBox::warning(this, "错误", "没有可保存的信号");
return;
}
QString filename = QFileDialog::getSaveFileName(this, "保存信号", "", "信号文件 (*.sig)");
if (!filename.isEmpty()) {
save_signal_to_file(filename.toUtf8().constData(), transmitter.modulated,
transmitter.sample_count, transmitter.sample_rate,
transmitter.signal_type, transmitter.mod_type);
showStatusMessage("信号已保存: " + filename);
}
}
void CommunicationSystemGUI::onLoadSignal() {
QString filename = QFileDialog::getOpenFileName(this, "加载信号", "", "信号文件 (*.sig)");
if (!filename.isEmpty()) {
load_signal_from_file(filename.toUtf8().constData(), receiver.received,
&receiver.sample_count, &receiver.sample_rate,
&receiver.signal_type, &receiver.mod_type);
plotSignal(receivedWaveformView, receiver.received,
receiver.sample_count, "接收信号波形");
showStatusMessage("信号已加载: " + filename);
}
}
void CommunicationSystemGUI::onSaveReceived() {
if (receiver.sample_count == 0) {
QMessageBox::warning(this, "错误", "没有可保存的接收信号");
return;
}
QString filename = QFileDialog::getSaveFileName(this, "保存接收信号", "", "信号文件 (*.sig)");
if (!filename.isEmpty()) {
save_signal_to_file(filename.toUtf8().constData(), receiver.received,
receiver.sample_count, receiver.sample_rate,
receiver.signal_type, receiver.mod_type);
showStatusMessage("接收信号已保存: " + filename);
}
}
void CommunicationSystemGUI::onSaveDecoded() {
if (receiver.signal_type == TEXT_DATA) {
QString filename = QFileDialog::getSaveFileName(this, "保存解码文本", "", "文本文件 (*.txt)");
if (!filename.isEmpty()) {
QFile file(filename);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << receiver.decoded_text;
file.close();
showStatusMessage("解码文本已保存: " + filename);
}
}
}
else {
QString filename = QFileDialog::getSaveFileName(this, "保存解码信号", "", "数据文件 (*.dat)");
if (!filename.isEmpty()) {
QFile file(filename);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
for (int i = 0; i < receiver.sample_count; i++) {
out << receiver.demodulated[i] << "\n";
}
file.close();
showStatusMessage("解码信号已保存: " + filename);
}
}
}
}
void CommunicationSystemGUI::onSignalTypeChanged(int index) {
SignalType type = static_cast<SignalType>(signalTypeCombo->itemData(index).toInt());
textDataEdit->setEnabled(type == TEXT_DATA);
setTextButton->setEnabled(type == TEXT_DATA);
loadFileButton->setEnabled(type == FILE_DATA);
}
void CommunicationSystemGUI::onTransmitSignal() {
if (audioOutput && transmitter.sample_count > 0) {
// 更新状态
transmitStatusLabel->setText("发送状态: 传输中");
transmitProgressBar->setValue(0);
// 准备输出缓冲区
QBuffer* outputBuffer = new QBuffer(this);
outputBuffer->open(QIODevice::ReadWrite);
// 计算传输时间(毫秒)
float duration = (transmitter.sample_count * 1000.0f) / transmitter.sample_rate;
outputBuffer->write(reinterpret_cast<const char*>(transmitter.modulated),
transmitter.sample_count * sizeof(float));
outputBuffer->seek(0);
// 开始播放
audioOutput->start(outputBuffer);
showStatusMessage("开始传输信号...");
// 启动传输计时器
transmitTimer.start();
// 设置进度更新定时器
QTimer* progressTimer = new QTimer(this);
connect(progressTimer, &QTimer::timeout, [=]() {
int elapsed = transmitTimer.elapsed();
int progress = qMin(100, static_cast<int>((elapsed / duration) * 100));
transmitProgressBar->setValue(progress);
if (progress >= 100) {
progressTimer->stop();
progressTimer->deleteLater();
transmitStatusLabel->setText("发送状态: 完成");
showStatusMessage("信号传输完成");
}
});
progressTimer->start(100); // 每100ms更新一次
}
else {
QMessageBox::warning(this, "错误", "音频输出设备未初始化或没有可传输的信号");
}
}
void CommunicationSystemGUI::onReceiveSignal() {
if (audioInput) {
// 更新状态
receiveStatusLabel->setText("接收状态: 接收中");
receiveProgressBar->setValue(0);
// 准备输入缓冲区
inputBuffer.setData(QByteArray());
inputBuffer.open(QIODevice::WriteOnly);
// 开始录音
audioInput->start(&inputBuffer);
showStatusMessage("开始接收信号...");
// 设置进度更新定时器
QTimer* progressTimer = new QTimer(this);
connect(progressTimer, &QTimer::timeout, [=]() {
int elapsed = receiveTimer.elapsed();
int progress = qMin(100, static_cast<int>((elapsed / 5000.0) * 100));
receiveProgressBar->setValue(progress);
if (progress >= 100) {
progressTimer->stop();
progressTimer->deleteLater();
receiveStatusLabel->setText("接收状态: 完成");
// === 新增:处理接收到的音频数据 ===
inputBuffer.close();
QByteArray audioData = inputBuffer.data();
if (!audioData.isEmpty()) {
// 转换为浮点数组
const float* rawData = reinterpret_cast<const float*>(audioData.constData());
int numSamples = audioData.size() / sizeof(float);
// 设置接收器的信号类型和调制类型
receiver.signal_type = transmitter.signal_type;
receiver.mod_type = transmitter.mod_type;
receiver.sample_rate = transmitter.sample_rate;
// 存储到接收器
receiver.sample_count = numSamples;
for (int i = 0; i < receiver.sample_count; i++) {
receiver.received[i] = rawData[i];
}
// 绘制接收信号
plotSignal(receivedWaveformView, receiver.received,
receiver.sample_count, "接收信号波形");
showStatusMessage(QString("接收完成,共 %1 个样本").arg(receiver.sample_count));
onDemodulateSignal();
}
else {
showStatusMessage("未接收到任何数据");
}
}
});
progressTimer->start(100);
receiveTimer.start();
}
else {
QMessageBox::warning(this, "错误", "音频输入设备未初始化");
}
}
// 添加处理接收到的音频数据的函数
void CommunicationSystemGUI::processReceivedAudio() {
inputBuffer.close();
if (audioData.size() == 0) {
showStatusMessage("未接收到任何数据");
return;
}
// 将接收到的数据转换为浮点数组
const float* rawData = reinterpret_cast<const float*>(audioData.constData());
int numSamples = audioData.size() / sizeof(float);
if (numSamples > MAX_SAMPLES) {
numSamples = MAX_SAMPLES;
showStatusMessage("警告:接收数据超出最大样本数,已截断");
}
// 复制到接收器
receiver.sample_count = numSamples;
receiver.signal_type = transmitter.signal_type; // 设置信号类型
receiver.mod_type = transmitter.mod_type; // 设置调制类型
for (int i = 0; i < numSamples; i++) {
receiver.received[i] = rawData[i];
}
// 绘制接收信号
plotSignal(receivedWaveformView, receiver.received, receiver.sample_count, "接收信号波形");
showStatusMessage(QString("接收完成,共 %1 个样本").arg(numSamples));
// 清空数据为下次接收准备
audioData.clear();
}
// ================= 辅助函数 =================
void CommunicationSystemGUI::plotSignal(QChartView* chartView, float* data, int count, const QString& title) {
// 严格检查输入参数
if (!chartView || !data || count <= 0) {
qWarning() << "无效的绘图参数";
return;
}
// 创建新的series
QLineSeries* series = new QLineSeries();
// 计算步长以减少点数
int step = std::max(1, count / 1000);
if (step < 1) step = 1;
// 添加数据点
for (int i = 0; i < count; i += step) {
series->append(i, data[i]);
}
// 创建新图表
QChart* chart = new QChart();
chart->addSeries(series);
chart->setTitle(title);
// 创建并设置X轴
QValueAxis* axisX = new QValueAxis();
axisX->setTitleText("采样点");
axisX->setRange(0, count);
chart->addAxis(axisX, Qt::AlignBottom);
series->attachAxis(axisX);
// 创建并设置Y轴
QValueAxis* axisY = new QValueAxis();
axisY->setTitleText("幅度");
// 自动计算Y轴范围
auto minmax = std::minmax_element(data, data + count);
float minVal = *minmax.first;
float maxVal = *minmax.second;
// 确保有合理的范围
if (fabs(maxVal - minVal) < 0.001f) {
minVal -= 1.0f;
maxVal += 1.0f;
}
else {
// 扩展10%的范围
float range = maxVal - minVal;
minVal -= range * 0.1f;
maxVal += range * 0.1f;
}
axisY->setRange(minVal, maxVal);
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisY);
// 设置图表到视图
chartView->setChart(chart);
chartView->setRenderHint(QPainter::Antialiasing);
}
void CommunicationSystemGUI::showStatusMessage(const QString& message) {
statusBar->showMessage(message, 5000); // 显示5秒
}
还是没有解决这个程序我说的问题。就两个要求:1.输入输出波形相同;2.输入文本数据与输出解码相同。实现数字通信