#ifndef MockBackEnd #include "BackEnd.h" #include "./MainWidget.h" #include "../component/FrequentShower.h" #include "../component/ProgressBar.h" #include "IntermediateFrequencyWidget.h" #include "RadioWidget.h" #include "SweepFrequencyWidget.h" #include "am_fm_cw_modem.hpp" #include "device_uhd.h" #include // 用于音频文件写入 #include // 用于音频播放 #include // Qt 的 QVector #include #include #include #define BUFFER_SIZE 512 // 缓冲区大小 Device_UHD* mYsRadio; AM_Demod am_demod; snd_pcm_t *handle; int err; void BackEnd::play(const QString& fileName){ // mYsRadio->YsSetFreq(value); } BackEnd *BackEnd::instance() { static BackEnd temp; return &temp; } bool BackEnd::match(QKeyEvent *e, const QString &function) { bool ok = mFunctionMap.contains(function); if(!ok){ qDebug() << "error Global::match 失败! 功能" << function << "不存在!" << e; } return e->key() == mFunctionMap[function]; } void BackEnd::YsSetFreq(quint64 value) { mYsRadio->setDevParam("RX0",UHD_ParamType::CenterFreq,value); mYsRadio->setDevZDParam("RX0",0,value,150000,300000); } qint64 BackEnd::YsGetFreq() { return (qint64)mYsRadio->getDevParam("RX0",UHD_ParamType::CenterFreq); } // 获取到频率 void BackEnd::YsReceiveFreq(quint64 freq) { qDebug() << "接收到频率:" << freq; MainWidget::instance()->mRadioWidget->mSelectValueWidget->set_frequent(freq); } // 音量设置 void BackEnd::YsSetAfGain(int value) { std::string command = "amixer sset Master " + std::to_string(value) + "%"; int result = system(command.c_str()); if (result != 0) { std::cerr << "Failed to set volume: " << result << std::endl; } } int BackEnd::YsGetAfGain() { FILE *pipe = popen("amixer sget Master | grep 'Left:' | awk -F'[][]' '{ print $2 }'", "r"); if (!pipe) { std::cerr << "Failed to run command" << std::endl; return -1; } char buffer[128]; std::string result = ""; while (!feof(pipe)) { if (fgets(buffer, 128, pipe) != NULL) result += buffer; } pclose(pipe); // Remove newline character if present result.erase(std::remove(result.begin(), result.end(), '\n'), result.end()); // Convert string to integer int volume = std::stoi(result); return volume; } int BackEnd::YsGetRfGain() { return 60; } // 增益设置 void BackEnd::YsSetRfGain(int value) { mYsRadio->setDevParam("RX0",UHD_ParamType::Gain,value); qDebug()<<"增益设置"<DataLen; //绘图用 if(pUHDData->DataType == UHD_Enum_DataType::kd_fft ) { QVector data; data.clear(); for(int i = 0; i < 1024; i++) { unsigned short ts = *((unsigned short *)pUHDData+32+i); //qDebug()<<(double) (ts/256); data.push_back((double) (ts/256)); // if(i==512) // {qDebug()<mRadioWidget; auto iw = mw->mIntermediateFrequencyWidget; int tick = rw->mWaterFall->time_axis()->give_data(QTime::currentTime()); rw->mWaterFall->give_data(tick, data); // 中频瀑布图 rw->mSpectrogramLine->give_data(data); // 中频频谱图 iw->mAfterglow->give_data(data); // 余晖图 iw->mSpectrogramLine->give_data(data); // 瀑布图 // auto sl = MainWidget::instance()->mSweepFrequencyWidget->mSweepFrequencyLine; // int n = sl->block_frequent_point_size(); // sl->give_data(data); } if(pUHDData->DataType == UHD_Enum_DataType::zd_ddc) { // qDebug()<<"收到zd_ddc数据包大小"<DataLen; short rbuf[512]; std::complex* cbuf_ptr = reinterpret_cast*>((char*)pData + 64); am_demod.step(cbuf_ptr, rbuf, 512); // 解调数据 //MainWidget::instance()->mRadioWidget->giv QVector data(512); for(int i = 0; i < 512; ++i){ data[i] = rbuf[i]; } auto main = MainWidget::instance(); auto radio = main->mRadioWidget; //qDebug() << data; radio->mAudioSpectrogramPlot->give_data(data); //std::cout << "audio == " << rbuf[256] << std::endl; int tick = radio->mTimePower->time_axis()->give_data(QTime::currentTime()); radio->mTimePower->give_data(tick, rbuf[256]); // 保存音频流 // ofstream fp_dst; // fp_dst.open("FM_DeMod.dat", ios::out | ios::binary | ios::app); // fp_dst.write((char *)rbuf, 512 * 2ll); // fp_dst.close(); // snd_pcm_writei 是ALSA库提供的函数,用于将音频数据写入PCM设备。 // handle:指向已打开的PCM设备句柄。 // buffer:指向包含音频数据的缓冲区。 // BUFFER_SIZE:要写入的数据帧数。 // err:存储 snd_pcm_writei 函数的返回值。 // == -EPIPE:检查返回值是否为 -EPIPE,这表示发生了XRUN(欠载)错误。XRUN发生在音频缓冲区为空时,即音频设备没有足够的数据进行播放。 // 播放数据 if ((err = snd_pcm_writei(handle, rbuf, BUFFER_SIZE)) == -EPIPE) { fprintf(stderr, "XRUN occurred\n"); // 重新准备PCM设备 if ((err = snd_pcm_prepare(handle)) < 0) { fprintf(stderr, "无法重新准备PCM设备: %s\n", snd_strerror(err)); } } else if (err < 0) { fprintf(stderr, "无法写入音频数据: %s\n", snd_strerror(err)); } // // 关闭音频设备 // snd_pcm_close(handle); } } BackEnd::BackEnd() { mFunctionMap["主菜单"] = Qt::Key_F9; mFunctionMap["属性菜单"] = Qt::Key_F11; mFunctionMap["顶部菜单"] = Qt::Key_F10; mFunctionMap["退出"] = Qt::Key_Escape; mFunctionMap["确定"] = Qt::Key_F2; mFunctionMap["左移"] = Qt::Key_Left; mFunctionMap["右移"] = Qt::Key_Right; mFunctionMap["增加"] = Qt::Key_Up; mFunctionMap["减小"] = Qt::Key_Down; mFunctionMap["切换音量/RF Gain"] = Qt::Key_F1; mFunctionMap["特别增加"] = Qt::Key_PageUp; mFunctionMap["特别减小"] = Qt::Key_PageDown; mYsRadio = new Device_UHD(); uhd::device_addrs_t tmp_add = mYsRadio->findDevices(); while(mYsRadio->openDevice(tmp_add[0]) != true) { qDebug()<<"9002连接失败,重试中..."; sleep(1); mYsRadio->openDevice(tmp_add[0]); } qDebug()<<"9002设备连接成功"; quint64 value = 10125000; mYsRadio->setDevParam("RX0",UHD_ParamType::CenterFreq,value); // 宽带设置 mYsRadio->setDevParam("RX0",UHD_ParamType::BandWidth,100000); // 改带宽,频谱带宽不变 mYsRadio->setDevParam("RX0",UHD_ParamType::SampleFreq,480000); // 改采样率,频谱带宽变化 mYsRadio->setDevParam("RX0",UHD_ParamType::Gain,33); // mYsRadio->setDevDataSwitch("RX0",KDDCSwitch,0,true); mYsRadio->setDevFFTParam(UHD_FFTWin::blkmc,_1024,10); // FFT设置 mYsRadio->setDevDataSwitch("RX0",KFFTSwitch,0,true); mYsRadio->setDevZDParam("RX0",0,value,15000,30000); // 窄带设置 mYsRadio->setDevDataSwitch("RX0",ZDDCSwitch,0, true); mYsRadio->startDevRecv(0); //mYsRadio->stopDevRecv(0); mYsRadio->callBackData = std::bind(&BackEnd::callBackData_Func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); // mYsRadio->hide(); // connect(mYsRadio, &YsRadio::YsGetFreq, this, &BackEnd::YsReceiveFreq); // connect(mYsRadio,&YsRadio::YsReceiveSpectrumData,this, &BackEnd::YsReceiveSpectrumData); // 打开音频设备 if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "无法打开音频设备: %s\n", snd_strerror(err)); exit(1); } else{ qDebug()<<"打开音频设备成功"; } // 设置音频参数 snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); // 初始化硬件参数结构 if ((err = snd_pcm_hw_params_any(handle, params)) < 0) { fprintf(stderr, "无法初始化硬件参数结构: %s\n", snd_strerror(err)); // goto close_device; }else{ qDebug()<<"初始化硬件参数结构成功"; } // 设置访问类型 if ((err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "无法设置访问类型: %s\n", snd_strerror(err)); // goto close_device; }else{ qDebug()<<"设置访问类型"; } // 设置样本格式 if ((err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf(stderr, "无法设置样本格式: %s\n", snd_strerror(err)); // goto close_device; }else{ qDebug()<<"设置样本格式"; } // 设置采样率 unsigned int rate = 30000;//44100 if ((err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0)) < 0) { fprintf(stderr, "无法设置采样率: %s\n", snd_strerror(err)); // goto close_device; }else{ qDebug()<<"设置采样率"; } // 设置声道数 if ((err = snd_pcm_hw_params_set_channels(handle, params, 1)) < 0) { fprintf(stderr, "无法设置声道数: %s\n", snd_strerror(err)); // goto close_device; }else{ qDebug()<<"设置声道数"; } // 应用硬件参数 if ((err = snd_pcm_hw_params(handle, params)) < 0) { fprintf(stderr, "无法应用硬件参数: %s\n", snd_strerror(err)); // goto close_device; }else{ qDebug()<<"应用硬件参数"; } // 准备播放 if ((err = snd_pcm_prepare(handle)) < 0) { fprintf(stderr, "无法准备播放: %s\n", snd_strerror(err)); // goto close_device; } else{ qDebug()<<"准备播放"; } //close_device: // // 关闭音频设备 // snd_pcm_close(handle); } QString BackEnd::getAudioFileLocation() { return "./"; } QString BackEnd::get_screenshot_save_file_name() { QDateTime currentDateTime = QDateTime::currentDateTime(); return "截屏_" + currentDateTime.toString() .replace(":", "_") .replace("/", "_") + ".png"; } QString BackEnd::get_screenshot_save_dir_path() { return "/media/sdcard1/"; } #endif