@@ -236,6 +236,7 @@ struct Input {
236236 dst.update = true ;
237237 dst.flags .needReinit = true ;
238238 dst.sampleRateOffset = std::move (this ->sampleRateOffset );
239+ dst.freqStartShift = std::move (this ->freqStartShift );
239240 dst.payloadLength = std::move (this ->payloadLength );
240241 dst.directSequenceSpread = std::move (this ->directSequenceSpread );
241242 }
@@ -266,6 +267,7 @@ struct Input {
266267
267268 // reinit
268269 float sampleRateOffset = 0 ;
270+ int freqStartShift = 0 ;
269271 int payloadLength = -1 ;
270272
271273 // spectrum
@@ -636,10 +638,19 @@ void updateCore() {
636638 if (inputCurrent.flags .needReinit ) {
637639 static auto sampleRateInpOld = ggWave->sampleRateInp ();
638640 static auto sampleRateOutOld = ggWave->sampleRateOut ();
641+ static auto freqStartShiftOld = 0 ;
642+
639643 auto sampleFormatInpOld = ggWave->sampleFormatInp ();
640644 auto sampleFormatOutOld = ggWave->sampleFormatOut ();
641645 auto rxProtocolsOld = ggWave->rxProtocols ();
642646
647+ for (int i = 0 ; i < GGWAVE_PROTOCOL_COUNT; ++i) {
648+ GGWave::Protocols::tx ()[i].freqStart = std::max (1 , GGWave::Protocols::tx ()[i].freqStart + inputCurrent.freqStartShift - freqStartShiftOld);
649+ rxProtocolsOld[i].freqStart = std::max (1 , rxProtocolsOld[i].freqStart + inputCurrent.freqStartShift - freqStartShiftOld);
650+ }
651+
652+ freqStartShiftOld = inputCurrent.freqStartShift ;
653+
643654 GGWave::OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
644655 if (inputCurrent.directSequenceSpread ) mode |= GGWAVE_OPERATING_MODE_USE_DSS;
645656
@@ -853,6 +864,8 @@ void renderMain() {
853864 int protocolId = GGWAVE_PROTOCOL_AUDIBLE_FAST;
854865 bool isSampleRateOffset = false ;
855866 float sampleRateOffset = -512 .0f ;
867+ bool isFreqStartShift = false ;
868+ int freqStartShift = 48 ;
856869 bool isFixedLength = false ;
857870 bool directSequenceSpread = false ;
858871 int payloadLength = 16 ;
@@ -1055,7 +1068,7 @@ void renderMain() {
10551068
10561069 if (windowId == WindowId::Settings) {
10571070 ImGui::BeginChild (" Settings:main" , ImGui::GetContentRegionAvail (), true , ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
1058- ImGui::Text (" Waver v1.5.1 " );
1071+ ImGui::Text (" Waver v1.5.2 " );
10591072 ImGui::Separator ();
10601073
10611074 ImGui::Text (" %s" , " " );
@@ -1177,7 +1190,10 @@ void renderMain() {
11771190 {
11781191 const float df = statsCurrent.sampleRate /statsCurrent.samplesPerFrame ;
11791192 const auto & protocol = settings.txProtocols [settings.protocolId ];
1180- ImGui::Text (" %6.2f Hz - %6.2f Hz" , df*protocol.freqStart , df*(protocol.freqStart + float (2 *16 *protocol.bytesPerTx )/protocol.extra ));
1193+ const auto freqStart = std::max (1 , protocol.freqStart + (settings.isFreqStartShift ? settings.freqStartShift : 0 ));
1194+ const float f0 = df*freqStart;
1195+ const float f1 = df*(freqStart + float (2 *16 *protocol.bytesPerTx )/protocol.extra );
1196+ ImGui::Text (" %6.2f Hz - %6.2f Hz" , f0, f1);
11811197 }
11821198
11831199 // fixed-length
@@ -1204,65 +1220,107 @@ void renderMain() {
12041220 if (settings.isFixedLength ) {
12051221 ImGui::SameLine ();
12061222 ImGui::PushItemWidth (0.5 *ImGui::GetContentRegionAvailWidth ());
1207- if (ImGui::SliderInt (" Bytes" , &settings.payloadLength , 1 , GGWave::kMaxLengthFixed )) {
1223+ if (ImGui::DragInt (" Bytes" , &settings.payloadLength , 1 , 1 , GGWave::kMaxLengthFixed )) {
12081224 g_buffer.inputUI .update = true ;
12091225 g_buffer.inputUI .flags .needReinit = true ;
12101226 g_buffer.inputUI .payloadLength = settings.isFixedLength ? settings.payloadLength : -1 ;
12111227 }
12121228 ImGui::PopItemWidth ();
12131229 }
12141230
1215- // Output sample-rate offset
1216- ImGui::Text (" %s" , " " );
1231+ // Direct-sequence spread
1232+ // ImGui::Text("%s", "");
12171233 {
12181234 auto posSave = ImGui::GetCursorScreenPos ();
12191235 ImGui::Text (" %s" , " " );
12201236 ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
12211237 ImGui::PushTextWrapPos ();
1222- ImGui::TextDisabled (" Modify the output Sampling Rate " );
1238+ ImGui::TextDisabled (" Direct-sequence spread " );
12231239 ImGui::PopTextWrapPos ();
12241240 }
12251241 {
12261242 auto posSave = ImGui::GetCursorScreenPos ();
1227- ImGui::Text (" Pitch shift : " );
1243+ ImGui::Text (" Use DSS : " );
12281244 ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
12291245 }
1230- if (ImGui::Checkbox (" ##output-sample-rate-offset " , &settings.isSampleRateOffset )) {
1246+ if (ImGui::Checkbox (" ##direct-sequence-spread " , &settings.directSequenceSpread )) {
12311247 g_buffer.inputUI .update = true ;
12321248 g_buffer.inputUI .flags .needReinit = true ;
1233- g_buffer.inputUI .sampleRateOffset = settings.isSampleRateOffset ? settings. sampleRateOffset : 0 ;
1249+ g_buffer.inputUI .directSequenceSpread = settings.directSequenceSpread ;
12341250 }
12351251
1236- if (settings.isSampleRateOffset ) {
1252+ // FreqStart offset
1253+ // ImGui::Text("%s", "");
1254+ {
1255+ auto posSave = ImGui::GetCursorScreenPos ();
1256+ ImGui::Text (" %s" , " " );
1257+ ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
1258+ ImGui::PushTextWrapPos ();
1259+ ImGui::TextDisabled (" Apply tx/rx frequency shift" );
1260+ ImGui::PopTextWrapPos ();
1261+ }
1262+ {
1263+ auto posSave = ImGui::GetCursorScreenPos ();
1264+ ImGui::Text (" Freq shift: " );
1265+ ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
1266+ }
1267+ if (ImGui::Checkbox (" ##freq-start-offset" , &settings.isFreqStartShift )) {
1268+ g_buffer.inputUI .update = true ;
1269+ g_buffer.inputUI .flags .needReinit = true ;
1270+ g_buffer.inputUI .freqStartShift = settings.isFreqStartShift ? settings.freqStartShift : 0 ;
1271+ }
1272+
1273+ if (settings.isFreqStartShift ) {
12371274 ImGui::SameLine ();
12381275 ImGui::PushItemWidth (0.5 *ImGui::GetContentRegionAvailWidth ());
1239- if (ImGui::SliderFloat ( " Samples " , &settings.sampleRateOffset , - 1000 , 1000 , " %.0f " )) {
1276+ if (ImGui::DragInt ( " bins " , &settings.freqStartShift , 1 , - 64 , 64 , " %d " )) {
12401277 g_buffer.inputUI .update = true ;
12411278 g_buffer.inputUI .flags .needReinit = true ;
1242- g_buffer.inputUI .sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0 ;
1279+ g_buffer.inputUI .freqStartShift = settings.isFreqStartShift ? settings.freqStartShift : 0 ;
12431280 }
12441281 ImGui::PopItemWidth ();
1282+
1283+ {
1284+ auto posSave = ImGui::GetCursorScreenPos ();
1285+ ImGui::Text (" " );
1286+ ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
1287+ }
1288+ {
1289+ const float df = statsCurrent.sampleRate /statsCurrent.samplesPerFrame ;
1290+ ImGui::Text (" %6.2f Hz" , df*settings.freqStartShift );
1291+ }
12451292 }
12461293
1247- // Direct-sequence spread
1248- ImGui::Text (" %s" , " " );
1294+ // Output sample-rate offset
1295+ // ImGui::Text("%s", "");
12491296 {
12501297 auto posSave = ImGui::GetCursorScreenPos ();
12511298 ImGui::Text (" %s" , " " );
12521299 ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
12531300 ImGui::PushTextWrapPos ();
1254- ImGui::TextDisabled (" Direct-sequence spread " );
1301+ ImGui::TextDisabled (" Modify the output Sampling Rate " );
12551302 ImGui::PopTextWrapPos ();
12561303 }
12571304 {
12581305 auto posSave = ImGui::GetCursorScreenPos ();
1259- ImGui::Text (" Use DSS : " );
1306+ ImGui::Text (" Pitch shift : " );
12601307 ImGui::SetCursorScreenPos ({ posSave.x + kLabelWidth , posSave.y });
12611308 }
1262- if (ImGui::Checkbox (" ##direct-sequence-spread " , &settings.directSequenceSpread )) {
1309+ if (ImGui::Checkbox (" ##output-sample-rate-offset " , &settings.isSampleRateOffset )) {
12631310 g_buffer.inputUI .update = true ;
12641311 g_buffer.inputUI .flags .needReinit = true ;
1265- g_buffer.inputUI .directSequenceSpread = settings.directSequenceSpread ;
1312+ g_buffer.inputUI .sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0 ;
1313+ }
1314+
1315+ if (settings.isSampleRateOffset ) {
1316+ ImGui::SameLine ();
1317+ ImGui::PushItemWidth (0.5 *ImGui::GetContentRegionAvailWidth ());
1318+ if (ImGui::SliderFloat (" Samples" , &settings.sampleRateOffset , -1000 , 1000 , " %.0f" )) {
1319+ g_buffer.inputUI .update = true ;
1320+ g_buffer.inputUI .flags .needReinit = true ;
1321+ g_buffer.inputUI .sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0 ;
1322+ }
1323+ ImGui::PopItemWidth ();
12661324 }
12671325
12681326 // rx protocols
0 commit comments