mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-04-18 03:47:29 +08:00
ggwave-gui : add spectrum + other UI stuff
This commit is contained in:
@@ -94,9 +94,54 @@ int main(int argc, char** argv) {
|
|||||||
float volume;
|
float volume;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GGWaveStats {
|
||||||
|
bool isReceiving;
|
||||||
|
bool isAnalyzing;
|
||||||
|
int framesToRecord;
|
||||||
|
int framesLeftToRecord;
|
||||||
|
int framesToAnalyze;
|
||||||
|
int framesLeftToAnalyze;
|
||||||
|
};
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
|
||||||
|
struct Flags {
|
||||||
|
bool newMessage = false;
|
||||||
|
bool newSpectrum = false;
|
||||||
|
bool newStats = false;
|
||||||
|
|
||||||
|
void clear() { memset(this, 0, sizeof(Flags)); }
|
||||||
|
} flags;
|
||||||
|
|
||||||
|
void apply(State & dst) {
|
||||||
|
if (update == false) return;
|
||||||
|
|
||||||
|
if (this->flags.newMessage) {
|
||||||
|
dst.update = true;
|
||||||
|
dst.flags.newMessage = true;
|
||||||
|
dst.message = std::move(this->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->flags.newSpectrum) {
|
||||||
|
dst.update = true;
|
||||||
|
dst.flags.newSpectrum = true;
|
||||||
|
dst.spectrum = std::move(this->spectrum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->flags.newStats) {
|
||||||
|
dst.update = true;
|
||||||
|
dst.flags.newStats = true;
|
||||||
|
dst.stats = std::move(this->stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.clear();
|
||||||
|
update = false;
|
||||||
|
}
|
||||||
|
|
||||||
Message message;
|
Message message;
|
||||||
|
GGWave::SpectrumData spectrum;
|
||||||
|
GGWaveStats stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Input {
|
struct Input {
|
||||||
@@ -146,6 +191,7 @@ int main(int argc, char** argv) {
|
|||||||
lastRxDataLength = ggWave->takeRxData(lastRxData);
|
lastRxDataLength = ggWave->takeRxData(lastRxData);
|
||||||
if (lastRxDataLength > 0) {
|
if (lastRxDataLength > 0) {
|
||||||
buffer.stateCore.update = true;
|
buffer.stateCore.update = true;
|
||||||
|
buffer.stateCore.flags.newMessage = true;
|
||||||
buffer.stateCore.message = {
|
buffer.stateCore.message = {
|
||||||
true,
|
true,
|
||||||
std::time(nullptr),
|
std::time(nullptr),
|
||||||
@@ -155,15 +201,28 @@ int main(int argc, char** argv) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (ggWave->takeSpectrum(buffer.stateCore.spectrum)) {
|
||||||
std::lock_guard<std::mutex> lock(buffer.mutex);
|
buffer.stateCore.update = true;
|
||||||
if (buffer.stateCore.update) {
|
buffer.stateCore.flags.newSpectrum = true;
|
||||||
buffer.stateUI = std::move(buffer.stateCore);
|
|
||||||
buffer.stateCore.update = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
if (true) {
|
||||||
|
buffer.stateCore.update = true;
|
||||||
|
buffer.stateCore.flags.newStats = true;
|
||||||
|
buffer.stateCore.stats.isReceiving = ggWave->isReceiving();
|
||||||
|
buffer.stateCore.stats.isAnalyzing = ggWave->isAnalyzing();
|
||||||
|
buffer.stateCore.stats.framesToRecord = ggWave->getFramesToRecord();
|
||||||
|
buffer.stateCore.stats.framesLeftToRecord = ggWave->getFramesLeftToRecord();
|
||||||
|
buffer.stateCore.stats.framesToAnalyze = ggWave->getFramesToAnalyze();
|
||||||
|
buffer.stateCore.stats.framesLeftToAnalyze = ggWave->getFramesLeftToAnalyze();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(buffer.mutex);
|
||||||
|
buffer.stateCore.apply(buffer.stateUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -176,16 +235,13 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(buffer.mutex);
|
std::lock_guard<std::mutex> lock(buffer.mutex);
|
||||||
if (buffer.stateUI.update) {
|
buffer.stateUI.apply(stateCurrent);
|
||||||
stateCurrent = std::move(buffer.stateUI);
|
|
||||||
buffer.stateUI.update = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WindowId {
|
enum class WindowId {
|
||||||
Settings,
|
Settings,
|
||||||
Messages,
|
Messages,
|
||||||
Commands,
|
Spectrum,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
@@ -206,10 +262,22 @@ int main(int argc, char** argv) {
|
|||||||
static double tStartInput = 0.0f;
|
static double tStartInput = 0.0f;
|
||||||
static double tEndInput = -100.0f;
|
static double tEndInput = -100.0f;
|
||||||
|
|
||||||
|
static GGWaveStats statsCurrent;
|
||||||
|
static GGWave::SpectrumData spectrumCurrent;
|
||||||
static std::vector<Message> messageHistory;
|
static std::vector<Message> messageHistory;
|
||||||
|
|
||||||
if (stateCurrent.update) {
|
if (stateCurrent.update) {
|
||||||
messageHistory.push_back(std::move(stateCurrent.message));
|
if (stateCurrent.flags.newMessage) {
|
||||||
|
scrollMessagesToBottom = true;
|
||||||
|
messageHistory.push_back(std::move(stateCurrent.message));
|
||||||
|
}
|
||||||
|
if (stateCurrent.flags.newSpectrum) {
|
||||||
|
spectrumCurrent = std::move(stateCurrent.spectrum);
|
||||||
|
}
|
||||||
|
if (stateCurrent.flags.newStats) {
|
||||||
|
statsCurrent = std::move(stateCurrent.stats);
|
||||||
|
}
|
||||||
|
stateCurrent.flags.clear();
|
||||||
stateCurrent.update = false;
|
stateCurrent.update = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,12 +319,14 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_LIST_UL " Commands", { 1.0f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
if (ImGui::Button(ICON_FA_LIST_UL " Spectrum", { 1.0f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
||||||
windowId = WindowId::Commands;
|
windowId = WindowId::Spectrum;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowId == WindowId::Settings) {
|
if (windowId == WindowId::Settings) {
|
||||||
ImGui::BeginChild("Settings:main", ImGui::GetContentRegionAvail(), true);
|
ImGui::BeginChild("Settings:main", ImGui::GetContentRegionAvail(), true);
|
||||||
|
ImGui::Text("%s", "");
|
||||||
|
ImGui::Text("%s", "");
|
||||||
ImGui::Text("Waver v0.1");
|
ImGui::Text("Waver v0.1");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
@@ -264,7 +334,7 @@ int main(int argc, char** argv) {
|
|||||||
ImGui::Text("Sample rate (capture): %g, %d B/sample", ggWave->getSampleRateIn(), ggWave->getSampleSizeBytesIn());
|
ImGui::Text("Sample rate (capture): %g, %d B/sample", ggWave->getSampleRateIn(), ggWave->getSampleSizeBytesIn());
|
||||||
ImGui::Text("Sample rate (playback): %g, %d B/sample", ggWave->getSampleRateOut(), ggWave->getSampleSizeBytesOut());
|
ImGui::Text("Sample rate (playback): %g, %d B/sample", ggWave->getSampleRateOut(), ggWave->getSampleSizeBytesOut());
|
||||||
|
|
||||||
static float kLabelWidth = 100.0f;
|
const float kLabelWidth = 100.0f;
|
||||||
|
|
||||||
// volume
|
// volume
|
||||||
ImGui::Text("%s", "");
|
ImGui::Text("%s", "");
|
||||||
@@ -282,7 +352,6 @@ int main(int argc, char** argv) {
|
|||||||
ImGui::Text("Tx Protocol: ");
|
ImGui::Text("Tx Protocol: ");
|
||||||
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
|
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::BeginCombo("##protocol", ggWave->getTxProtocols()[settings.protocolId].name)) {
|
if (ImGui::BeginCombo("##protocol", ggWave->getTxProtocols()[settings.protocolId].name)) {
|
||||||
for (int i = 0; i < (int) ggWave->getTxProtocols().size(); ++i) {
|
for (int i = 0; i < (int) ggWave->getTxProtocols().size(); ++i) {
|
||||||
const bool isSelected = (settings.protocolId == i);
|
const bool isSelected = (settings.protocolId == i);
|
||||||
@@ -301,7 +370,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (windowId == WindowId::Messages) {
|
if (windowId == WindowId::Messages) {
|
||||||
const float messagesInputHeight = ImGui::GetTextLineHeightWithSpacing();
|
const float messagesInputHeight = 2*ImGui::GetTextLineHeightWithSpacing();
|
||||||
const float messagesHistoryHeigthMax = ImGui::GetContentRegionAvail().y - messagesInputHeight - 2.0f*style.ItemSpacing.x;
|
const float messagesHistoryHeigthMax = ImGui::GetContentRegionAvail().y - messagesInputHeight - 2.0f*style.ItemSpacing.x;
|
||||||
float messagesHistoryHeigth = messagesHistoryHeigthMax;
|
float messagesHistoryHeigth = messagesHistoryHeigthMax;
|
||||||
|
|
||||||
@@ -324,6 +393,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
ImGui::BeginChild("Messages:history", { ImGui::GetContentRegionAvailWidth(), messagesHistoryHeigth }, true);
|
ImGui::BeginChild("Messages:history", { ImGui::GetContentRegionAvailWidth(), messagesHistoryHeigth }, true);
|
||||||
|
|
||||||
|
ImGui::PushTextWrapPos();
|
||||||
for (int i = 0; i < (int) messageHistory.size(); ++i) {
|
for (int i = 0; i < (int) messageHistory.size(); ++i) {
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
const auto & message = messageHistory[i];
|
const auto & message = messageHistory[i];
|
||||||
@@ -351,6 +421,7 @@ int main(int argc, char** argv) {
|
|||||||
ImGui::Text("%s", "");
|
ImGui::Text("%s", "");
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
if (scrollMessagesToBottom) {
|
if (scrollMessagesToBottom) {
|
||||||
ImGui::SetScrollHereY();
|
ImGui::SetScrollHereY();
|
||||||
@@ -361,6 +432,22 @@ int main(int argc, char** argv) {
|
|||||||
ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Left);
|
ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Left);
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
if (statsCurrent.isReceiving) {
|
||||||
|
if (statsCurrent.isAnalyzing) {
|
||||||
|
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Analyzing ...");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::ProgressBar(1.0f - float(statsCurrent.framesLeftToAnalyze)/statsCurrent.framesToAnalyze,
|
||||||
|
{ ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() });
|
||||||
|
} else {
|
||||||
|
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Receiving ...");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::ProgressBar(1.0f - float(statsCurrent.framesLeftToRecord)/statsCurrent.framesToRecord,
|
||||||
|
{ ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::TextDisabled("Listening for waves ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (doInputFocus) {
|
if (doInputFocus) {
|
||||||
ImGui::SetKeyboardFocusHere();
|
ImGui::SetKeyboardFocusHere();
|
||||||
doInputFocus = false;
|
doInputFocus = false;
|
||||||
@@ -394,9 +481,24 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowId == WindowId::Commands) {
|
if (windowId == WindowId::Spectrum) {
|
||||||
ImGui::BeginChild("Commands:main", ImGui::GetContentRegionAvail(), true);
|
ImGui::BeginChild("Spectrum:main", ImGui::GetContentRegionAvail(), true);
|
||||||
ImGui::Text("Todo");
|
ImGui::Text("FPS: %g\n", ImGui::GetIO().Framerate);
|
||||||
|
if (spectrumCurrent.empty() == false) {
|
||||||
|
auto wSize = ImGui::GetContentRegionAvail();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0.3f, 0.3f, 0.3f, 0.3f });
|
||||||
|
if (statsCurrent.isReceiving) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, { 1.0f, 0.0f, 0.0f, 1.0f });
|
||||||
|
} else {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, { 0.0f, 1.0f, 0.0f, 1.0f });
|
||||||
|
}
|
||||||
|
ImGui::PlotHistogram("##plotSpectrumCurrent",
|
||||||
|
spectrumCurrent.data() + 30,
|
||||||
|
ggWave->getSamplesPerFrame()/2 - 30, 0,
|
||||||
|
(std::string("Current Spectrum")).c_str(),
|
||||||
|
0.0f, FLT_MAX, wSize);
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ public:
|
|||||||
void receive(const CBDequeueAudio & CBDequeueAudio);
|
void receive(const CBDequeueAudio & CBDequeueAudio);
|
||||||
|
|
||||||
const bool & hasTxData() const { return m_hasNewTxData; }
|
const bool & hasTxData() const { return m_hasNewTxData; }
|
||||||
|
const bool & isReceiving() const { return m_receivingData; }
|
||||||
|
const bool & isAnalyzing() const { return m_analyzingData; }
|
||||||
|
|
||||||
const int & getFramesToRecord() const { return m_framesToRecord; }
|
const int & getFramesToRecord() const { return m_framesToRecord; }
|
||||||
const int & getFramesLeftToRecord() const { return m_framesLeftToRecord; }
|
const int & getFramesLeftToRecord() const { return m_framesLeftToRecord; }
|
||||||
@@ -74,7 +76,9 @@ public:
|
|||||||
const TxRxData & getRxData() const { return m_rxData; }
|
const TxRxData & getRxData() const { return m_rxData; }
|
||||||
const TxProtocol & getRxProtocol() const { return m_rxProtocol; }
|
const TxProtocol & getRxProtocol() const { return m_rxProtocol; }
|
||||||
const int & getRxProtocolId() const { return m_rxProtocolId; }
|
const int & getRxProtocolId() const { return m_rxProtocolId; }
|
||||||
|
|
||||||
int takeRxData(TxRxData & dst);
|
int takeRxData(TxRxData & dst);
|
||||||
|
bool takeSpectrum(SpectrumData & dst);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int maxFramesPerTx() const;
|
int maxFramesPerTx() const;
|
||||||
@@ -117,6 +121,7 @@ private:
|
|||||||
std::vector<float> m_fftIn; // real
|
std::vector<float> m_fftIn; // real
|
||||||
std::vector<float> m_fftOut; // complex
|
std::vector<float> m_fftOut; // complex
|
||||||
|
|
||||||
|
bool m_hasNewSpectrum;
|
||||||
SpectrumData m_sampleSpectrum;
|
SpectrumData m_sampleSpectrum;
|
||||||
AmplitudeData m_sampleAmplitude;
|
AmplitudeData m_sampleAmplitude;
|
||||||
|
|
||||||
|
|||||||
@@ -149,8 +149,11 @@ GGWave::GGWave(
|
|||||||
m_encodedDataOffset(3),
|
m_encodedDataOffset(3),
|
||||||
m_fftIn(kMaxSamplesPerFrame),
|
m_fftIn(kMaxSamplesPerFrame),
|
||||||
m_fftOut(2*kMaxSamplesPerFrame),
|
m_fftOut(2*kMaxSamplesPerFrame),
|
||||||
|
m_hasNewSpectrum(false),
|
||||||
m_sampleSpectrum(kMaxSamplesPerFrame),
|
m_sampleSpectrum(kMaxSamplesPerFrame),
|
||||||
m_sampleAmplitude(kMaxSamplesPerFrame),
|
m_sampleAmplitude(kMaxSamplesPerFrame),
|
||||||
|
m_hasNewRxData(false),
|
||||||
|
m_lastRxDataLength(0),
|
||||||
m_rxData(kMaxDataSize),
|
m_rxData(kMaxDataSize),
|
||||||
m_sampleAmplitudeAverage(kMaxSamplesPerFrame),
|
m_sampleAmplitudeAverage(kMaxSamplesPerFrame),
|
||||||
m_sampleAmplitudeHistory(kMaxSpectrumHistory),
|
m_sampleAmplitudeHistory(kMaxSpectrumHistory),
|
||||||
@@ -385,48 +388,47 @@ void GGWave::receive(const CBDequeueAudio & CBDequeueAudio) {
|
|||||||
auto nBytesRecorded = CBDequeueAudio(m_sampleAmplitude.data(), m_samplesPerFrame*m_sampleSizeBytesIn);
|
auto nBytesRecorded = CBDequeueAudio(m_sampleAmplitude.data(), m_samplesPerFrame*m_sampleSizeBytesIn);
|
||||||
|
|
||||||
if (nBytesRecorded != 0) {
|
if (nBytesRecorded != 0) {
|
||||||
{
|
m_sampleAmplitudeHistory[m_historyId] = m_sampleAmplitude;
|
||||||
m_sampleAmplitudeHistory[m_historyId] = m_sampleAmplitude;
|
|
||||||
|
|
||||||
if (++m_historyId >= kMaxSpectrumHistory) {
|
if (++m_historyId >= kMaxSpectrumHistory) {
|
||||||
m_historyId = 0;
|
m_historyId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_historyId == 0 && (m_receivingData == false || m_receivingData)) {
|
if (m_historyId == 0 || m_receivingData) {
|
||||||
std::fill(m_sampleAmplitudeAverage.begin(), m_sampleAmplitudeAverage.end(), 0.0f);
|
m_hasNewSpectrum = true;
|
||||||
for (auto & s : m_sampleAmplitudeHistory) {
|
|
||||||
for (int i = 0; i < m_samplesPerFrame; ++i) {
|
std::fill(m_sampleAmplitudeAverage.begin(), m_sampleAmplitudeAverage.end(), 0.0f);
|
||||||
m_sampleAmplitudeAverage[i] += s[i];
|
for (auto & s : m_sampleAmplitudeHistory) {
|
||||||
}
|
|
||||||
}
|
|
||||||
float norm = 1.0f/kMaxSpectrumHistory;
|
|
||||||
for (int i = 0; i < m_samplesPerFrame; ++i) {
|
for (int i = 0; i < m_samplesPerFrame; ++i) {
|
||||||
m_sampleAmplitudeAverage[i] *= norm;
|
m_sampleAmplitudeAverage[i] += s[i];
|
||||||
}
|
|
||||||
|
|
||||||
// calculate spectrum
|
|
||||||
std::copy(m_sampleAmplitudeAverage.begin(), m_sampleAmplitudeAverage.begin() + m_samplesPerFrame, m_fftIn.data());
|
|
||||||
|
|
||||||
FFT(m_fftIn.data(), m_fftOut.data(), m_samplesPerFrame, 1.0);
|
|
||||||
|
|
||||||
double fsum = 0.0;
|
|
||||||
for (int i = 0; i < m_samplesPerFrame; ++i) {
|
|
||||||
m_sampleSpectrum[i] = (m_fftOut[2*i + 0]*m_fftOut[2*i + 0] + m_fftOut[2*i + 1]*m_fftOut[2*i + 1]);
|
|
||||||
fsum += m_sampleSpectrum[i];
|
|
||||||
}
|
|
||||||
for (int i = 1; i < m_samplesPerFrame/2; ++i) {
|
|
||||||
m_sampleSpectrum[i] += m_sampleSpectrum[m_samplesPerFrame - i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_framesLeftToRecord > 0) {
|
float norm = 1.0f/kMaxSpectrumHistory;
|
||||||
std::copy(m_sampleAmplitude.begin(),
|
for (int i = 0; i < m_samplesPerFrame; ++i) {
|
||||||
m_sampleAmplitude.begin() + m_samplesPerFrame,
|
m_sampleAmplitudeAverage[i] *= norm;
|
||||||
m_recordedAmplitude.data() + (m_framesToRecord - m_framesLeftToRecord)*m_samplesPerFrame);
|
}
|
||||||
|
|
||||||
if (--m_framesLeftToRecord <= 0) {
|
// calculate spectrum
|
||||||
m_analyzingData = true;
|
std::copy(m_sampleAmplitudeAverage.begin(), m_sampleAmplitudeAverage.begin() + m_samplesPerFrame, m_fftIn.data());
|
||||||
}
|
|
||||||
|
FFT(m_fftIn.data(), m_fftOut.data(), m_samplesPerFrame, 1.0);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_samplesPerFrame; ++i) {
|
||||||
|
m_sampleSpectrum[i] = (m_fftOut[2*i + 0]*m_fftOut[2*i + 0] + m_fftOut[2*i + 1]*m_fftOut[2*i + 1]);
|
||||||
|
}
|
||||||
|
for (int i = 1; i < m_samplesPerFrame/2; ++i) {
|
||||||
|
m_sampleSpectrum[i] += m_sampleSpectrum[m_samplesPerFrame - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_framesLeftToRecord > 0) {
|
||||||
|
std::copy(m_sampleAmplitude.begin(),
|
||||||
|
m_sampleAmplitude.begin() + m_samplesPerFrame,
|
||||||
|
m_recordedAmplitude.data() + (m_framesToRecord - m_framesLeftToRecord)*m_samplesPerFrame);
|
||||||
|
|
||||||
|
if (--m_framesLeftToRecord <= 0) {
|
||||||
|
m_analyzingData = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,6 +653,15 @@ int GGWave::takeRxData(TxRxData & dst) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GGWave::takeSpectrum(SpectrumData & dst) {
|
||||||
|
if (m_hasNewSpectrum == false) return false;
|
||||||
|
|
||||||
|
m_hasNewSpectrum = false;
|
||||||
|
dst = m_sampleSpectrum;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int GGWave::maxFramesPerTx() const {
|
int GGWave::maxFramesPerTx() const {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
for (const auto & protocol : kTxProtocols) {
|
for (const auto & protocol : kTxProtocols) {
|
||||||
|
|||||||
Reference in New Issue
Block a user