高进度计时,精确到0.001秒,且不受任何干扰!

 

'在Project中加入一个Module,然后在其中加入以下代码:
Option Explicit

Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

Public Declare Function QueryPerformanceCounter Lib "kernel32" _
        (lpPerformanceCount As LARGE_INTEGER) As Long
Public Declare Function QueryPerformanceFrequency Lib "kernel32" _
        (lpFrequency As LARGE_INTEGER) As Long
Public Declare Function timeSetEvent Lib "winmm.dll" (ByVal uDelay As Long, ByVal _
        uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, _
        ByVal uFlags As Long) As Long
Public Declare Function timeKillEvent Lib "winmm.dll" (ByVal uID As Long) As Long
Public Declare Function GetTickCount Lib "kernel32" () As Long

Public lMSFreq As Long
Public TimerCount As Single
Public lmmCount As Single
Public lTimeID As Long
Public actTime1 As Long
Public actTime2 As Long
Public iCountStart As Single

Dim iCount As Single

'注释: timeSetEvent的回调函数
Sub TimeProc(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, _
    ByVal dw1 As Long, ByVal dw2 As Long)
   
    Form1.Text2.Text = Format$(lmmCount, "00.00")
    lmmCount = lmmCount - 0.01
    If lmmCount <= 0 Then
        iCountStart = 60
        lmmCount = 60
        TimerCount = 60
        EndCount
    End If
End Sub
Sub EndCount()
    iCount = iCountStart
    iCountStart = 0
    timeKillEvent lTimeID
    actTime2 = GetTickCount - actTime1
    With Form1
        .Command1.Enabled = True
        .Command2.Enabled = False
        .Timer1.Enabled = False
       
        .Text1 = "计数器记时" + Format$((60 - iCount), "00.00") + "  " _
                + "实际经过时间" + Format$((actTime2 / 1000), "00.00")
        .Text2 = "计数器记时" + Format$((60 - lmmCount), "00.00") + "  " _
                + "实际经过时间" + Format$((actTime2 / 1000), "00.00")
        .Text3 = "计数器记时" + Format$((60 - TimerCount), "00.00") + "  " _
                + "实际经过时间" + Format$((actTime2 / 1000), "00.00")
    End With
End Sub

#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.输入文本数据与输出解码相同。实现数字通信
最新发布
06-10
#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) { // 创建预定义的帧头和帧尾 const QByteArray frame_header = QByteArray::fromHex("55AA55AA55AA"); // 预定义帧头 const QByteArray frame_footer = QByteArray::fromHex("AA55AA55AA55"); // 预定义帧尾 QByteArray data; data.append(frame_header); data.append(text); data.append(frame_footer); // 设置数据 size_t len = data.size(); if (len >= MAX_TEXT_LENGTH) len = MAX_TEXT_LENGTH - 1; memcpy(tx->text_data, data.constData(), len); tx->text_data[len] = '\0'; tx->bit_count = 0; // 转换为二进制 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; } } } // 汉明编码 int original_bit_count = tx->bit_count; encode_hamming(tx->binary_data, tx->bit_count); tx->original_bit_count = original_bit_count; // 生成信号波形 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); } // 使用升余弦滤波器生成更平滑的基带信号 static const float rc_alpha = 0.35f; // 滚降因子 static const int rc_span = 6; // 符号跨度 for (int i = 0; i < tx->sample_count; i++) { float t = (i % static_cast<int>(SAMPLES_PER_BIT)) * 1.0f / SAMPLES_PER_BIT - 0.5f; float rc_value = 0.0f; for (int k = -rc_span; k <= rc_span; k++) { int bit_idx = i / SAMPLES_PER_BIT + k; if (bit_idx < 0 || bit_idx >= tx->bit_count) continue; float bit_value = tx->binary_data[bit_idx] ? 1.0f : -1.0f; float t_shift = t - k; if (fabs(t_shift) < 1e-5) { // 避免除以0 rc_value += bit_value; } else { float sinc = sin(M_PI * t_shift) / (M_PI * t_shift); float rolloff = cos(M_PI * rc_alpha * t_shift) / (1 - 4 * pow(rc_alpha * t_shift, 2)); rc_value += bit_value * sinc * rolloff; } } tx->samples[i] = rc_value; } } // ================= 文件数据处理 ================= 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* tx) { for (int i = 0; i < tx->sample_count; i++) { float t = i * 1.0f / tx->sample_rate; // 使用判决点值而不是所有采样点 int bit_idx = i / SAMPLES_PER_BIT; if (bit_idx >= tx->bit_count) { tx->demodulated[i] = 0.0f; } else { float symbol = tx->binary_data[bit_idx] ? 1.0f : -1.0f; tx->demodulated[i] = symbol * sin(2 * M_PI * tx->carrier_freq * t); } } } 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](); } // 深度同步接收信号 deep_synchronization(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 deep_synchronization(Receiver* rx) { // 1. 幅度归一化 float max_amp = 0.01f; for (int i = 0; i < rx->sample_count; i++) { if (fabs(rx->received[i]) > max_amp) { max_amp = fabs(rx->received[i]); } } float scale = 1.0f / max_amp; for (int i = 0; i < rx->sample_count; i++) { rx->received[i] *= scale; } // 2. 载波同步 const int frame_length = 64; // 训练序列长度 if (rx->sample_count > frame_length * 2) { // 寻找最大相关点进行载波同步 int max_corr_index = 0; float max_corr = -1.0f; for (int i = 0; i < frame_length; i++) { float corr = 0.0f; for (int j = 0; j < frame_length; j++) { float ref = sin(2 * M_PI * rx->carrier_freq * (j + i) / rx->sample_rate); corr += rx->received[j] * ref; } if (fabs(corr) > max_corr) { max_corr = fabs(corr); max_corr_index = i; } } // 调整接收信号的相位 memmove(rx->received, rx->received + max_corr_index, (rx->sample_count - max_corr_index) * sizeof(float)); rx->sample_count -= max_corr_index; } // 3. 符号定时恢复 const int spb = SAMPLES_PER_BIT; // 每个符号的样本数 const int window_size = spb / 4; // 定时误差检测窗口 float epsilon = 0.0f; // 定时偏移估计 float mu = 0.01f; // 步长因子 // 改进的Gardner定时恢复算法 for (int i = window_size; i < rx->sample_count - spb - window_size; i += spb) { float late = rx->received[i + spb / 2 + 1]; float early = rx->received[i + spb / 2 - 1]; float center = rx->received[i + spb / 2]; // 计算定时误差 float error = (late - early) * center; // 更新定时偏移估计 epsilon += mu * error; // 应用插值重采样 float fractional = epsilon - floor(epsilon); rx->received[i] = interpolate(rx->received, i + (int)epsilon, fractional); } } // 综合同步函数 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_bits = header.size() * 8; const int spb = SAMPLES_PER_BIT; // 创建理想的帧头模板 std::vector<float> template_signal(header_bits * spb); for (int i = 0; i < header_bits; i++) { int byte_idx = i / 8; int bit_idx = i % 8; int bit = (header[byte_idx] >> (7 - bit_idx)) & 1; float symbol = bit ? 1.0f : -1.0f; // 升余弦整形 for (int j = 0; j < spb; j++) { float t = j * 1.0f / spb; template_signal[i * spb + j] = symbol * sin(M_PI * t); } } // 使用归一化互相关寻找最佳位置 int best_offset = -1; float max_corr = -FLT_MAX; for (int offset = 0; offset < length - template_signal.size(); offset++) { float signal_energy = 0.0f; float template_energy = 0.0f; float correlation = 0.0f; for (int i = 0; i < template_signal.size(); i++) { float s = data[offset + i]; float t = template_signal[i]; signal_energy += s * s; template_energy += t * t; correlation += s * t; } // 归一化互相关 float norm_corr = correlation / sqrt(signal_energy * template_energy + 1e-5); if (norm_corr > max_corr) { max_corr = norm_corr; best_offset = offset; } } // 应用阈值(需要根据实际情况调整) const float threshold = 0.75f; return (max_corr > threshold) ? 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 } 还是不行,波形不一致,解码失败
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值