mirror of
				https://github.com/bytequill/radio-sdr.git
				synced 2025-11-04 14:49:18 +01:00 
			
		
		
		
	early skeleton
This commit is contained in:
		
							parent
							
								
									dbfddda58a
								
							
						
					
					
						commit
						ecd259f629
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					dev/*
 | 
				
			||||||
 | 
					build/*
 | 
				
			||||||
 | 
					# Temporary ignore!!
 | 
				
			||||||
 | 
					docs/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(radio-sdr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					file(GLOB_RECURSE SOURCES "src/*.cpp")
 | 
				
			||||||
 | 
					file(GLOB_RECURSE HEADERS "src/*.hpp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(main ${SOURCES} ${HEADERS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_FLAGS_DEBUG "-g -Og -ggdb")
 | 
				
			||||||
 | 
					set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#==============================
 | 
				
			||||||
 | 
					# CPM - Cmake Package Manager |
 | 
				
			||||||
 | 
					#==============================
 | 
				
			||||||
 | 
					include(src/get_CPM.cmake)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CPMAddPackage("gh:libsdl-org/SDL#release-3.2.10")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CPMAddPackage(gh:ocornut/imgui@1.91.9b)
 | 
				
			||||||
 | 
					add_library(imgui STATIC
 | 
				
			||||||
 | 
					    ${imgui_SOURCE_DIR}/imgui.cpp
 | 
				
			||||||
 | 
					    ${imgui_SOURCE_DIR}/imgui_demo.cpp # optionally comment this out
 | 
				
			||||||
 | 
					    ${imgui_SOURCE_DIR}/imgui_draw.cpp
 | 
				
			||||||
 | 
					    ${imgui_SOURCE_DIR}/imgui_widgets.cpp
 | 
				
			||||||
 | 
					    ${imgui_SOURCE_DIR}/imgui_tables.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					message(STATUS "imgui_SOURCE_DIR: ${imgui_SOURCE_DIR}")
 | 
				
			||||||
 | 
					target_include_directories(imgui INTERFACE ${imgui_SOURCE_DIR})
 | 
				
			||||||
 | 
					target_compile_definitions(imgui PUBLIC -DIMGUI_DISABLE_OBSOLETE_FUNCTIONS) # optional imgui setting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(main SDL3 imgui)
 | 
				
			||||||
@ -1 +1,3 @@
 | 
				
			|||||||
# radio
 | 
					# radio-sdr - An exploration of low-level radio modulation, raw filetype parsing and displaying data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# FOREWORD
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										31
									
								
								src/fft.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/fft.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					#include "fft.hpp"
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void fft(vector<cd> &a, bool invert) {
 | 
				
			||||||
 | 
						assert(a.size() > 0 && (a.size() & (a.size() - 1)) == 0); // Check power of 2
 | 
				
			||||||
 | 
						int n = a.size();
 | 
				
			||||||
 | 
						if (n == 1)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vector<cd> a0(n / 2), a1(n / 2);
 | 
				
			||||||
 | 
						for (int i = 0; 2 * i < n; i++) {
 | 
				
			||||||
 | 
							a0[i] = a[2*i];
 | 
				
			||||||
 | 
							a1[i] = a[2*i+1];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fft(a0, invert);
 | 
				
			||||||
 | 
						fft(a1, invert);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double ang = 2 * PI / n * (invert ? -1 : 1);
 | 
				
			||||||
 | 
						cd w(1), wn(cos(ang), sin(ang));
 | 
				
			||||||
 | 
						for (int i = 0; 2 * i < n; i++) {
 | 
				
			||||||
 | 
							a[i] = a0[i] + w * a1[i];
 | 
				
			||||||
 | 
							a[i + n/2] = a0[i] - w * a1[i];
 | 
				
			||||||
 | 
							if (invert) {
 | 
				
			||||||
 | 
								a[i] /= 2;
 | 
				
			||||||
 | 
								a[i + n/2] /= 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							w *= wn;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								src/fft.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/fft.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					#include <complex>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using cd = std::complex<double>;
 | 
				
			||||||
 | 
					const double PI = acos(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void fft(std::vector<cd> &a, bool invert);
 | 
				
			||||||
							
								
								
									
										24
									
								
								src/get_CPM.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/get_CPM.cmake
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					# SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CPM_DOWNLOAD_VERSION 0.42.0)
 | 
				
			||||||
 | 
					set(CPM_HASH_SUM "2020b4fc42dba44817983e06342e682ecfc3d2f484a581f11cc5731fbe4dce8a")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(CPM_SOURCE_CACHE)
 | 
				
			||||||
 | 
					  set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
 | 
				
			||||||
 | 
					elseif(DEFINED ENV{CPM_SOURCE_CACHE})
 | 
				
			||||||
 | 
					  set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
					  set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Expand relative path. This is important if the provided path contains a tilde (~)
 | 
				
			||||||
 | 
					get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					file(DOWNLOAD
 | 
				
			||||||
 | 
					     https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
 | 
				
			||||||
 | 
					     ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(${CPM_DOWNLOAD_LOCATION})
 | 
				
			||||||
							
								
								
									
										67
									
								
								src/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/main.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					#include "sources/wav-baseband.hpp"
 | 
				
			||||||
 | 
					#include "fft.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//GUI
 | 
				
			||||||
 | 
					#include <SDL3/SDL.h>
 | 
				
			||||||
 | 
					#include <imgui.h>
 | 
				
			||||||
 | 
					#include <backends/imgui_impl_sdl3.h>
 | 
				
			||||||
 | 
					#include <backends/imgui_impl_sdlrenderer3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int GUIMain() {
 | 
				
			||||||
 | 
						if(!SDL_Init(SDL_INIT_VIDEO)) {
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
 | 
				
			||||||
 | 
						SDL_Window *window = SDL_CreateWindow("Title", 1280, 720, window_flags);
 | 
				
			||||||
 | 
						if(window == NULL) {
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						SDL_Renderer *renderer = SDL_CreateRenderer(window, NULL);
 | 
				
			||||||
 | 
						if(renderer == NULL) {
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						SDL_SetRenderVSync(renderer, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						IMGUI_CHECKVERSION();
 | 
				
			||||||
 | 
						ImGui::CreateContext();
 | 
				
			||||||
 | 
						ImGuiIO& io = ImGui::GetIO(); (void)io;
 | 
				
			||||||
 | 
						io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						ImGui::StyleColorsDark();
 | 
				
			||||||
 | 
						ImGui_ImplSDL3_InitForSDLRenderer(window, renderer);
 | 
				
			||||||
 | 
					    ImGui_ImplSDLRenderer3_Init(renderer);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() {
 | 
				
			||||||
 | 
						int res2 = GUIMain();
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return res2;
 | 
				
			||||||
 | 
						RFSourceWAV src;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						bool res = src.Load("./dev/test2.wav");
 | 
				
			||||||
 | 
						std::vector<cd> samples;
 | 
				
			||||||
 | 
						for (int i = 0; i != 10000 * 2; i++) {
 | 
				
			||||||
 | 
							std::vector<cd> sampleFrame = src.GetSamples(i * pow(2,11), pow(2,11));
 | 
				
			||||||
 | 
							fft(sampleFrame, false);
 | 
				
			||||||
 | 
							samples.insert(samples.end(), sampleFrame.begin(), sampleFrame.end());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						std::ofstream out;
 | 
				
			||||||
 | 
						out.open("dev/out1.csv");
 | 
				
			||||||
 | 
						out << "Magnitude\n";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < samples.size(); i++) {
 | 
				
			||||||
 | 
					        int mag = static_cast<int>(std::abs(samples[i]));
 | 
				
			||||||
 | 
					        out << mag << "\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    out.close();
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/sources/base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/sources/base.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <complex>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using cd = std::complex<double>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RFSourceBase {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
						bool live; // TRUE - Live RF stream FALSE - Recorded file
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// Fundamental metadata. In Hz
 | 
				
			||||||
 | 
						long bandwidth;
 | 
				
			||||||
 | 
						long samplerate;
 | 
				
			||||||
 | 
						long centerFreq;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						bool Load(std::string sourceID);
 | 
				
			||||||
 | 
						std::vector<cd> GetSamples(uintmax_t indx, int n);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										106
									
								
								src/sources/wav-baseband.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/sources/wav-baseband.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					#include "wav-baseband.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RFSourceWAV::Load(std::string filename) {
 | 
				
			||||||
 | 
						file.open(filename.c_str(), std::ios::in | std::ios::binary);
 | 
				
			||||||
 | 
						if (!file || !file.is_open()) {return false;}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						std::cout << header.samplerate << std::endl;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						char buff[sizeof(header)];
 | 
				
			||||||
 | 
						file.read(buff, sizeof(header));
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						memcpy(&header, buff, sizeof(header));
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// Assumptions about the format which if not true require refactoring of the code
 | 
				
			||||||
 | 
						if (std::strncmp(header.Magic, "RIFF", 4) != 0 ||
 | 
				
			||||||
 | 
							std::strncmp(header.RIFFType, "WAV", 4) != 0 ||
 | 
				
			||||||
 | 
							std::strncmp(header.FMTMARK, "fmt ", 4) != 0 ||
 | 
				
			||||||
 | 
							std::strncmp(header.DATAMARK, "data", 4) != 0 ||
 | 
				
			||||||
 | 
							header.fmtType != 1 ||
 | 
				
			||||||
 | 
							header.chnNum != 2)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// TODO: figure out a DEBUG/ERROR system for more precise data than just the failure
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						this->samplerate = header.samplerate;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// converts the `char`(1byte) raw sampleData into correct bitsPerSample based values
 | 
				
			||||||
 | 
					int64_t convertSample(const char *sampleData, uint_fast16_t bitsPerSample) {
 | 
				
			||||||
 | 
						assert(bitsPerSample > 0 && (bitsPerSample & (bitsPerSample - 1)) == 0); // Check power of 2
 | 
				
			||||||
 | 
						assert(bitsPerSample <= 64);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (bitsPerSample == 8) {
 | 
				
			||||||
 | 
							// 8-bit WAV audio is typically stored as unsigned values.
 | 
				
			||||||
 | 
							// Convert to signed: 0-255 (unsigned) -> -128 to 127.
 | 
				
			||||||
 | 
							uint8_t raw = *(reinterpret_cast<const uint8_t*>(sampleData));
 | 
				
			||||||
 | 
							return static_cast<int64_t>(static_cast<int16_t>(raw) - 128);
 | 
				
			||||||
 | 
						} else if (bitsPerSample == 16) {
 | 
				
			||||||
 | 
							int16_t sample = static_cast<int16_t>(
 | 
				
			||||||
 | 
								(static_cast<uint16_t>(static_cast<uint8_t>(sampleData[1])) << 8) |
 | 
				
			||||||
 | 
								 static_cast<uint8_t>(sampleData[0])
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							return static_cast<int64_t>(sample);
 | 
				
			||||||
 | 
						} else if (bitsPerSample == 32) {
 | 
				
			||||||
 | 
							int32_t sample = static_cast<int32_t>(
 | 
				
			||||||
 | 
								(static_cast<uint32_t>(static_cast<uint8_t>(sampleData[3])) << 24) |
 | 
				
			||||||
 | 
								(static_cast<uint32_t>(static_cast<uint8_t>(sampleData[2])) << 16) |
 | 
				
			||||||
 | 
								(static_cast<uint32_t>(static_cast<uint8_t>(sampleData[1])) <<  8) |
 | 
				
			||||||
 | 
								 static_cast<uint8_t>(sampleData[0])
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							return static_cast<int64_t>(sample);
 | 
				
			||||||
 | 
						} else if (bitsPerSample == 64 && sizeof(size_t) >= 8) {
 | 
				
			||||||
 | 
							int64_t sample = static_cast<int64_t>(
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[7])) << 56) |
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[6])) << 48) |
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[5])) << 40) |
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[4])) << 32) |
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[3])) << 24) |
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[2])) << 16) |
 | 
				
			||||||
 | 
								(static_cast<uint64_t>(static_cast<uint8_t>(sampleData[1])) <<  8) |
 | 
				
			||||||
 | 
								 static_cast<uint8_t>(sampleData[0])
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							return static_cast<int64_t>(sample);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<cd> RFSourceWAV::GetSamples(uintmax_t indx, int n) {
 | 
				
			||||||
 | 
						// an I/Q PCM stream MUST have 2 channels but setting value here for readability
 | 
				
			||||||
 | 
						int8_t chnNum = 2; 
 | 
				
			||||||
 | 
						assert (chnNum == header.chnNum);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						std::vector<cd> samples;
 | 
				
			||||||
 | 
						if (!file || !file.is_open()) {return samples;}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						std::vector<char> buf((header.bitsPerSample / 8) * chnNum * n);
 | 
				
			||||||
 | 
						uintmax_t offset = sizeof(header) + indx * header.blockAlign;
 | 
				
			||||||
 | 
						if (offset + buf.size() > header.dataLen + sizeof(header)) {return samples;}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						file.seekg(offset);
 | 
				
			||||||
 | 
						if (!file) {return samples;}
 | 
				
			||||||
 | 
						file.read(buf.data(), buf.size());
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						for (size_t i = 0; i < buf.size(); i += header.blockAlign) {
 | 
				
			||||||
 | 
							int sampleI = convertSample(&buf.data()[i], header.bitsPerSample);
 | 
				
			||||||
 | 
							int sampleQ = convertSample(&buf.data()[i + (header.bitsPerSample / 8)],
 | 
				
			||||||
 | 
														header.bitsPerSample);
 | 
				
			||||||
 | 
							samples.push_back(cd(sampleI, sampleQ));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return samples;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RFSourceWAV::~RFSourceWAV() {
 | 
				
			||||||
 | 
						if(file){
 | 
				
			||||||
 | 
							if(file.is_open()) {file.close();}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/sources/wav-baseband.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/sources/wav-baseband.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#include "base.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma pack(push, 1)
 | 
				
			||||||
 | 
					struct WAVHeader {
 | 
				
			||||||
 | 
					    char Magic[4];            // Always "RIFF". Magic value for all RIFF-Based formats!
 | 
				
			||||||
 | 
					    uint32_t Size;
 | 
				
			||||||
 | 
					    char RIFFType[4];         // Always "WAV"
 | 
				
			||||||
 | 
					    char FMTMARK[4];
 | 
				
			||||||
 | 
					    uint32_t fmtChunkLen;     // Always 16
 | 
				
			||||||
 | 
					    uint16_t fmtType;         // 1 - PCM
 | 
				
			||||||
 | 
					    uint16_t chnNum;
 | 
				
			||||||
 | 
					    uint32_t samplerate;
 | 
				
			||||||
 | 
					    uint32_t byteRate;        // samplerate * bitsPerSample * chnNum / 8
 | 
				
			||||||
 | 
					    uint16_t blockAlign;      // bitsPerSample * chnNum / 8
 | 
				
			||||||
 | 
					    uint16_t bitsPerSample;
 | 
				
			||||||
 | 
					    char DATAMARK[4];
 | 
				
			||||||
 | 
					    uint32_t dataLen;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#pragma pack(pop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RFSourceWAV : RFSourceBase {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							bool Load(std::string filename);
 | 
				
			||||||
 | 
							// Get `n` samples at index `indx` for both I and Q channels from the WAV file and return an
 | 
				
			||||||
 | 
							// FFT-friendly vector
 | 
				
			||||||
 | 
							std::vector<cd> GetSamples(uintmax_t indx, int n);
 | 
				
			||||||
 | 
							~RFSourceWAV();
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::ifstream file;
 | 
				
			||||||
 | 
							WAVHeader header;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user