├── .gitignore ├── .idea ├── hackrf.iml ├── misc.xml └── modules.xml ├── CMakeLists.txt ├── cmake └── modules │ └── FindLIBHACKRF.cmake ├── input.wav ├── readme.md ├── receiver.cpp ├── rxSrc └── hackrfTool.cpp ├── transfer.cpp └── txSrc ├── CMakeLists.txt ├── algorithm.cpp ├── fmMod.cpp ├── fmMod.h └── waveRead.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | ### JetBrains template 2 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 3 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 4 | 5 | # User-specific stuff: 6 | .idea/workspace.xml 7 | .idea/tasks.xml 8 | .idea/dictionaries 9 | .idea/vcs.xml 10 | .idea/jsLibraryMappings.xml 11 | 12 | # Sensitive or high-churn files: 13 | .idea/dataSources.ids 14 | .idea/dataSources.xml 15 | .idea/dataSources.local.xml 16 | .idea/sqlDataSources.xml 17 | .idea/dynamic.xml 18 | .idea/uiDesigner.xml 19 | 20 | # Gradle: 21 | .idea/gradle.xml 22 | .idea/libraries 23 | 24 | # Mongo Explorer plugin: 25 | .idea/mongoSettings.xml 26 | 27 | ## File-based project format: 28 | *.iws 29 | 30 | ## Plugin-specific files: 31 | 32 | # IntelliJ 33 | /out/ 34 | 35 | # mpeltonen/sbt-idea plugin 36 | .idea_modules/ 37 | 38 | # JIRA plugin 39 | atlassian-ide-plugin.xml 40 | 41 | # Crashlytics plugin (for Android Studio and IntelliJ) 42 | com_crashlytics_export_strings.xml 43 | crashlytics.properties 44 | crashlytics-build.properties 45 | fabric.properties 46 | ### OSX template 47 | .DS_Store 48 | .AppleDouble 49 | .LSOverride 50 | 51 | # Icon must end with two \r 52 | Icon 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # Files that might appear in the root of a volume 58 | .DocumentRevisions-V100 59 | .fseventsd 60 | .Spotlight-V100 61 | .TemporaryItems 62 | .Trashes 63 | .VolumeIcon.icns 64 | 65 | # Directories potentially created on remote AFP share 66 | .AppleDB 67 | .AppleDesktop 68 | Network Trash Folder 69 | Temporary Items 70 | .apdisk 71 | ### C++ template 72 | # Compiled Object files 73 | *.slo 74 | *.lo 75 | *.o 76 | *.obj 77 | 78 | # Precompiled Headers 79 | *.gch 80 | *.pch 81 | 82 | # Compiled Dynamic libraries 83 | *.so 84 | *.dylib 85 | *.dll 86 | 87 | # Fortran module files 88 | *.mod 89 | 90 | # Compiled Static libraries 91 | *.lai 92 | *.la 93 | *.a 94 | *.lib 95 | 96 | # Executables 97 | *.exe 98 | *.out 99 | *.app 100 | 101 | -------------------------------------------------------------------------------- /.idea/hackrf.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(hackrfMultiTransfer) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fopenmp") 5 | set(CMAKE_MODULE_PATH ${CMAKE_ROOT}/modules ${CMAKE_SOURCE_DIR}/cmake/modules) 6 | find_package(LIBHACKRF REQUIRED) 7 | add_subdirectory(txSrc) 8 | aux_source_directory(. DIR_SRCS) 9 | add_executable(main ${DIR_SRCS}) 10 | target_link_libraries(main Mod ${LIBHACKRF_LIBRARIES}) 11 | 12 | 13 | -------------------------------------------------------------------------------- /cmake/modules/FindLIBHACKRF.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the libhackrf library 2 | # Once done this defines 3 | # 4 | # LIBHACKRF_FOUND - system has libhackrf 5 | # LIBHACKRF_INCLUDE_DIR - the libhackrf include directory 6 | # LIBHACKRF_LIBRARIES - Link these to use libhackrf 7 | 8 | # Copyright (c) 2013 Benjamin Vernoux 9 | # 10 | 11 | 12 | if (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES) 13 | 14 | # in cache already 15 | set(LIBHACKRF_FOUND TRUE) 16 | 17 | else (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES) 18 | IF (NOT WIN32) 19 | # use pkg-config to get the directories and then use these values 20 | # in the FIND_PATH() and FIND_LIBRARY() calls 21 | find_package(PkgConfig) 22 | pkg_check_modules(PC_LIBHACKRF QUIET libhackrf) 23 | ENDIF(NOT WIN32) 24 | 25 | FIND_PATH(LIBHACKRF_INCLUDE_DIR 26 | NAMES hackrf.h 27 | HINTS $ENV{LIBHACKRF_DIR}/include ${PC_LIBHACKRF_INCLUDEDIR} 28 | PATHS /usr/local/include/libhackrf /usr/include/libhackrf /usr/local/include 29 | /usr/include ${CMAKE_SOURCE_DIR}/../libhackrf/src 30 | /opt/local/include/libhackrf 31 | ${LIBHACKRF_INCLUDE_DIR} 32 | ) 33 | 34 | set(libhackrf_library_names hackrf) 35 | 36 | FIND_LIBRARY(LIBHACKRF_LIBRARIES 37 | NAMES ${libhackrf_library_names} 38 | HINTS $ENV{LIBHACKRF_DIR}/lib ${PC_LIBHACKRF_LIBDIR} 39 | PATHS /usr/local/lib /usr/lib /usr/lib/arm-linux-gnueabihf /opt/local/lib ${PC_LIBHACKRF_LIBDIR} ${PC_LIBHACKRF_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../libhackrf/src 40 | ) 41 | 42 | if(LIBHACKRF_INCLUDE_DIR) 43 | set(CMAKE_REQUIRED_INCLUDES ${LIBHACKRF_INCLUDE_DIR}) 44 | endif() 45 | 46 | if(LIBHACKRF_LIBRARIES) 47 | set(CMAKE_REQUIRED_LIBRARIES ${LIBHACKRF_LIBRARIES}) 48 | endif() 49 | 50 | include(FindPackageHandleStandardArgs) 51 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBHACKRF DEFAULT_MSG LIBHACKRF_LIBRARIES LIBHACKRF_INCLUDE_DIR) 52 | 53 | MARK_AS_ADVANCED(LIBHACKRF_INCLUDE_DIR LIBHACKRF_LIBRARIES) 54 | 55 | endif (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES) -------------------------------------------------------------------------------- /input.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TW-OY/hackrfMultiTransfer/37081f758370e76a08e98468efdd07fb868e27d8/input.wav -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ##Introduction 2 | This is a hackrf fm/am transreceiver(only transfer part finish for now) 3 | 4 | Transfer part is inspired by . 5 | 6 | Receiver part is inspired by and . 7 | 8 | And on branch static, i've made a simple multi-core optimizing. 9 | 10 | ##usage 11 | 1. clone this repo 12 | 2. cd hackrfMultiTransfer 13 | 3. mkdir build 14 | 4. cd build 15 | 5. cmake .. 16 | 6. make 17 | 7. run main 18 | 19 | -------------------------------------------------------------------------------- /receiver.cpp: -------------------------------------------------------------------------------- 1 | #include "rxSrc/hackrfTool.cpp" 2 | 3 | 4 | int main(int argc,char* argv[]) { 5 | 6 | hackrfInit(); 7 | captureData(); 8 | 9 | doSomeThing(hackrf_rx_buf); 10 | 11 | 12 | while(true){ 13 | sleep(1); 14 | 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /rxSrc/hackrfTool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int8 hackrf_rx_buf[CAPLENGTH*2]; 4 | int hackrf_rx_count; 5 | 6 | void hackrfInit() { 7 | 8 | hackrf_init(); 9 | 10 | hackrf_open(&device); 11 | 12 | hackrf_set_sample_rate(device, sampleRate, 1); 13 | 14 | hackrf_set_baseband_filter_bandwidth(device, bandWidth); 15 | 16 | hackrf_set_vga_gain(device, vga_gain); 17 | 18 | hackrf_set_lna_gain(device, lna_gain); 19 | 20 | hackrf_set_freq(device, freq); 21 | } 22 | 23 | 24 | void captureData() { 25 | hackrf_stop_rx(hackrf_dev); //中止接收,因为可能之前处于接收使能状态。 26 | 27 | hackrf_rx_count = 0; 28 | // 接收数据长度清零,这是一个全局变量, 29 | // 回调函数会用此变量来告诉前台程序现在接收到多少数据了, 30 | // 前台程序应该在每次接收前把此变量清零,这样回调函数下一次被驱动调用时, 31 | // 才会认为用户buffer是空的,从而把驱动收到的数据搬进用户buffer(其实是个全局数组) 32 | 33 | hackrf_start_rx(hackrf_dev, capbuf_hackrf_callback, NULL); 34 | // 启动接收,并且告诉驱动回调函数为capbuf_hackrf_callback 35 | 36 | while(hackrf_is_streaming(hackrf_dev) == HACKRF_TRUE) { 37 | //不断检测HackRF设备是否处于正常streaming状态 38 | if( hackrf_rx_count == (CAPLENGTH*2) ) 39 | //如果接收数据长度达到了我们预订长度CAPLENGTH即退出, 40 | //*2是因为每个样点有I和Q两个数据 41 | break; 42 | } 43 | hackrf_is_streaming(hackrf_dev); //再次调用此函数 44 | 45 | } 46 | 47 | static int capbuf_hackrf_callback(hackrf_transfer* transfer) { 48 | size_t bytes_to_write; //本次调用向全局数组hackrf_rx_buf写入的长度 49 | size_t hackrf_rx_count_new = hackrf_rx_count + transfer->valid_length; 50 | //初步计算本次接收后数据总长度。 51 | 52 | int count_left = (CAPLENGTH*2) - hackrf_rx_count_new; 53 | //计算期望接收总长度与本次接收后总长度的差值。 54 | 55 | if ( count_left <= 0 ) { //如果本次接收后,总长度超出期望接收总长度 56 | bytes_to_write = transfer->valid_length + count_left; 57 | //则要减去超出的长度,否则待会儿hackrf_rx_buf装不下这么多数据会越界。 58 | } else { //如果不超 59 | bytes_to_write = transfer->valid_length; 60 | //则本次收到的数据可以全写入hackrf_rx_buf 61 | } 62 | 63 | if (bytes_to_write!=0) 64 | //如果需要把数据写入hackrf_rx_buf,即hackrf_rx_buf还没满 65 | { 66 | memcpy( hackrf_rx_buf+hackrf_rx_count, transfer->buffer, bytes_to_write ); 67 | //把数据从驱动的buffer中搬到用户全局数组hackrf_rx_buf中(附加在之前的数据之后) 68 | 69 | hackrf_rx_count = hackrf_rx_count + bytes_to_write; 70 | //更新当前接收数据总长度。 71 | //这个回调函数具有“自锁”能力, 72 | //即接收数据总长度达到期望的CAPLENGTH*2后, 73 | //即使被驱动调用,也不会再往用户全局数组hackrf_rx_buf中写了,因为已经满了。 74 | } 75 | 76 | return(0); 77 | } 78 | -------------------------------------------------------------------------------- /transfer.cpp: -------------------------------------------------------------------------------- 1 | #include "txSrc/fmMod.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(int argc,char* argv[]) { 8 | 9 | 10 | // getPcmData(argv[1]); 11 | 12 | char * path="/Users/MakeitBetter/input.wav"; 13 | // char * path="input.wav"; 14 | 15 | getPcmData(path); 16 | makeCache(); 17 | cout<<"cache finish"< 3 | 4 | float _last_in_samples[4] = { 0.0, 0.0, 0.0, 0.0 }; 5 | 6 | void interpolation(float * in_buf, uint32_t in_samples, float * out_buf, uint32_t out_samples) { 7 | 8 | uint32_t i; /* Input buffer index + 1. */ 9 | uint32_t j = 0; /* Output buffer index. */ 10 | float pos; /* Position relative to the input buffer 11 | * + 1.0. */ 12 | 13 | /* We always "stay one sample behind", so what would be our first sample 14 | * should be the last one wrote by the previous call. */ 15 | pos = (float)in_samples / (float)out_samples; 16 | while (pos < 1.0) 17 | { 18 | out_buf[j] = _last_in_samples[3] + (in_buf[0] - _last_in_samples[3]) * pos; 19 | j++; 20 | pos = (float)(j + 1)* (float)in_samples / (float)out_samples; 21 | } 22 | 23 | /* Interpolation cycle. */ 24 | i = (uint32_t)pos; 25 | while (j < (out_samples - 1)) 26 | { 27 | 28 | out_buf[j] = in_buf[i - 1] + (in_buf[i] - in_buf[i - 1]) * (pos - (float)i); 29 | j++; 30 | pos = (float)(j + 1)* (float)in_samples / (float)out_samples; 31 | i = (uint32_t)pos; 32 | } 33 | 34 | /* The last sample is always the same in input and output buffers. */ 35 | out_buf[j] = in_buf[in_samples - 1]; 36 | 37 | /* Copy last samples to _last_in_samples (reusing i and j). */ 38 | for (i = in_samples - 4, j = 0; j < 4; i++, j++) 39 | _last_in_samples[j] = in_buf[i]; 40 | } 41 | 42 | 43 | void modulation(float * input, int8_t * output, uint32_t mode) { 44 | double fm_deviation = 0.0; 45 | float gain = 0.9; 46 | 47 | double fm_phase = 0.0; 48 | 49 | int hackrf_sample = 2000000; 50 | 51 | if (mode == 0) { 52 | fm_deviation = 2.0 * M_PI * 75.0e3 / hackrf_sample; // 75 kHz max deviation WBFM 53 | } 54 | else if (mode == 1) 55 | { 56 | fm_deviation = 2.0 * M_PI * 5.0e3 / hackrf_sample; // 5 kHz max deviation NBFM 57 | } 58 | 59 | //AM mode 60 | if (mode == 2) { 61 | for (uint32_t i = 0; i < BUF_LEN; i++) { 62 | double audio_amp = input[i] * gain; 63 | 64 | if (fabs(audio_amp) > 1.0) { 65 | audio_amp = (audio_amp > 0.0) ? 1.0 : -1.0; 66 | } 67 | 68 | output[i * BYTES_PER_SAMPLE] = (int8_t)(audio_amp*127.0); 69 | output[i * BYTES_PER_SAMPLE + 1] = 0; 70 | } 71 | } 72 | //FM mode 73 | else { 74 | 75 | for (uint32_t i = 0; i < BUF_LEN / 2; i++) { 76 | 77 | double audio_amp = input[i] * gain; 78 | 79 | if (fabs(audio_amp) > 1.0) { 80 | audio_amp = (audio_amp > 0.0) ? 1.0 : -1.0; 81 | } 82 | fm_phase += fm_deviation * audio_amp; 83 | while (fm_phase > (float)(M_PI)) 84 | fm_phase -= (float)(2.0 * M_PI); 85 | while (fm_phase < (float)(-M_PI)) 86 | fm_phase += (float)(2.0 * M_PI); 87 | 88 | output[i * BYTES_PER_SAMPLE] = (int8_t)(sin(fm_phase)*127.0); 89 | output[i * BYTES_PER_SAMPLE + 1] =(int8_t)(cos(fm_phase)*127.0); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /txSrc/fmMod.cpp: -------------------------------------------------------------------------------- 1 | #include "fmMod.h" 2 | #include 3 | #include 4 | #include 5 | #include "waveRead.cpp" 6 | #include "algorithm.cpp" 7 | 8 | using namespace std; 9 | 10 | //_ means global variable 11 | 12 | int _audioSampleRate=0; 13 | float * _audioSampleBuf=NULL; 14 | float * _new_audio_buf=NULL; 15 | float * _new_audio_buf1=NULL; 16 | float * _new_audio_buf2=NULL; 17 | float * _new_audio_buf3=NULL; 18 | unsigned int offset=0; 19 | int _hackrfSampleRate=2000000; 20 | int32_t _numSampleCount; 21 | int8_t ** _iqCache; 22 | int _buffCount = 0; 23 | 24 | 25 | void getPcmData(char *path){ 26 | 27 | WaveData *wave = wavRead(path, strlen(path)); 28 | int nch = wave->header.numChannels; 29 | _audioSampleRate=wave->sampleRate; 30 | _numSampleCount = wave->size / wave->header.blockAlign; 31 | 32 | cout<<_numSampleCount<samples[i]; 44 | } 45 | 46 | }else if(nch==2){ 47 | 48 | for(int i=0;i<_numSampleCount;i++){ 49 | 50 | _audioSampleBuf[i] = (wave->samples[i * 2] + wave->samples[i * 2 + 1]) / (float)2.0; 51 | } 52 | } 53 | 54 | } 55 | 56 | void makeCache() { 57 | int _nsample = (float) _audioSampleRate * (float) BUF_LEN / (float) _hackrfSampleRate / 2.0; 58 | 59 | 60 | _iqCache = new int8_t *[_numSampleCount / _nsample](); 61 | for (int i = 0; i < _numSampleCount / _nsample; i++) { 62 | _iqCache[i] = new int8_t[BUF_LEN](); 63 | } 64 | 65 | #pragma omp parallel for 66 | for (int i = 0; i < _numSampleCount / _nsample; i++) { 67 | if (i < _numSampleCount / _nsample / 4) { 68 | interpolation(_audioSampleBuf + (_nsample * i), _nsample, _new_audio_buf, BUF_LEN / 2); 69 | modulation(_new_audio_buf, _iqCache[i], 0); 70 | } 71 | else if (i < _numSampleCount / _nsample / 4 * 2) { 72 | interpolation(_audioSampleBuf + (_nsample * i), _nsample, _new_audio_buf1, BUF_LEN / 2); 73 | modulation(_new_audio_buf1, _iqCache[i], 0); 74 | } 75 | else if (i < _numSampleCount / _nsample / 4 * 3) { 76 | interpolation(_audioSampleBuf + (_nsample * i), _nsample, _new_audio_buf2, BUF_LEN / 2); 77 | modulation(_new_audio_buf2, _iqCache[i], 0); 78 | } 79 | else if (i < _numSampleCount / _nsample) { 80 | interpolation(_audioSampleBuf + (_nsample * i), _nsample, _new_audio_buf3, BUF_LEN / 2); 81 | modulation(_new_audio_buf3, _iqCache[i], 0); 82 | } 83 | 84 | } 85 | } 86 | 87 | 88 | int hackrf_tx_callback(int8_t *buffer, uint32_t length) { 89 | int _nsample = (float)_audioSampleRate * (float)BUF_LEN / (float)_hackrfSampleRate / 2.0; 90 | if(_buffCount <= (_numSampleCount / _nsample)) { 91 | memcpy(buffer, _iqCache[_buffCount], length); 92 | _buffCount++; 93 | } 94 | return 0; 95 | } 96 | 97 | 98 | int _hackrf_tx_callback(hackrf_transfer *transfer) { 99 | return hackrf_tx_callback((int8_t *)transfer->buffer, transfer->valid_length); 100 | } 101 | 102 | 103 | void hackrfWork() { 104 | double freq = 433.00 * 1000000; 105 | uint32_t gain = 90 / 100.0; 106 | uint32_t tx_vga = 40; 107 | uint32_t enableamp = 1; 108 | hackrf_init(); 109 | hackrf_device * _dev = NULL; 110 | int ret = hackrf_open(&_dev); 111 | 112 | if (ret != HACKRF_SUCCESS) { 113 | hackrf_close(_dev); 114 | cout<<"hackrf open error"< 5 | #include 6 | 7 | #define BUF_LEN 262144 //hackrf tx buf 8 | #define BUF_NUM 63 9 | #define BYTES_PER_SAMPLE 2 10 | #define M_PI 3.14159265358979323846 11 | 12 | 13 | void interpolation(float * in_buf, uint32_t in_samples, float * out_buf, uint32_t out_samples); 14 | void modulation(float * input, int8_t * output, uint32_t mode); 15 | int hackrf_tx_callback(int8_t *buffer, uint32_t length, int count); 16 | void hackrfWork(); 17 | int _hackrf_tx_callback(hackrf_transfer *transfer); 18 | void getPcmData(char *path); 19 | void makeCache(); 20 | 21 | #endif //HACKRFMULTITRANSFER_WAVOPERATOR_H 22 | -------------------------------------------------------------------------------- /txSrc/waveRead.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * wavread.c 3 | * 4 | * Copyright 2013 Sachin Mousli 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef WAV_READ 24 | #define WAV_READ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #define DEBUG 1 31 | 32 | /* 33 | * A basic implementation of the 16-bit pcm wave file header. 34 | * Links explaining the RIFF-WAVE standard: 35 | * http://www.topherlee.com/software/pcm-tut-wavformat.html 36 | * https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 37 | */ 38 | typedef struct _WaveHeader_t 39 | { 40 | char chunkID[4]; // 1-4 "RIFF" 41 | int32_t chunkSize; // 5-8 42 | char format[4]; // 9-12 "WAVE" 43 | char subchunkID[4]; // 13-16 "fmt\0" 44 | int32_t subchunkSize; // 17-20 45 | uint16_t audioFormat; // 21-22 PCM = 1 46 | uint16_t numChannels; // 23-24 47 | int32_t sampleRate; // 25-28 48 | int32_t bytesPerSecond; // 29-32 49 | uint16_t blockAlign; // 33-34 50 | uint16_t bitDepth; // 35-36 16bit support only 51 | char dataID[4]; // 37-40 "data" 52 | int32_t dataSize; // 41-44 53 | } WaveHeader; 54 | 55 | typedef struct _WaveData_t 56 | { 57 | _WaveHeader_t header; 58 | int16_t *samples; 59 | int32_t size; 60 | int32_t sampleRate; 61 | uint16_t bitDepth; 62 | } WaveData; 63 | 64 | /* 65 | * Prototypes 66 | */ 67 | void printHeaderInfo(WaveHeader); 68 | WaveData* wavRead(char[],size_t); 69 | void dumpDataToFile(WaveData); 70 | 71 | 72 | WaveData* wavRead(char fileName[],size_t fileNameSize) 73 | { 74 | // 75 | if (fileName[fileNameSize] != '\0') 76 | { 77 | fprintf(stderr,"wavRead: Invalid string format.\n"); 78 | } else 79 | { 80 | FILE* filePtr = fopen(fileName, "r"); 81 | if (filePtr == NULL) 82 | { 83 | perror("Unable to open file"); 84 | } 85 | else 86 | { 87 | // Read header. 88 | WaveHeader header; 89 | fread(&header, sizeof(header), 1, filePtr); 90 | 91 | if (DEBUG) 92 | printHeaderInfo(header); 93 | 94 | // Check if the file is of supported format. 95 | if ( strncmp(header.chunkID, "RIFF", 4) || 96 | strncmp(header.format, "WAVE", 4) || 97 | strncmp(header.subchunkID, "fmt" , 3) || 98 | strncmp(header.dataID, "data", 4) || 99 | header.audioFormat != 1 || 100 | header.bitDepth != 16) 101 | { 102 | fprintf(stderr, "Unsupported file type.\n"); 103 | } 104 | else 105 | { 106 | // Initialize the data struct. 107 | WaveData *data = (WaveData*) malloc(sizeof(WaveData)); 108 | data->header = header; 109 | data->sampleRate = header.sampleRate; 110 | data->bitDepth = header.bitDepth; 111 | data->size = header.dataSize; 112 | 113 | // Read data. 114 | // ToDo: Add support for 24-32bit files. 115 | // 24bit samples are best converted to 32bits 116 | data->samples = (int16_t*) malloc(header.dataSize * sizeof(int16_t)); 117 | fread(data->samples, sizeof(float), header.dataSize, filePtr); 118 | fclose(filePtr); 119 | return data; 120 | } 121 | } 122 | } 123 | return NULL; 124 | } 125 | 126 | 127 | void dumpDataToFile(WaveData waveData) 128 | { 129 | // Dump data into a text file. 130 | FILE* outputFilePtr = fopen("output.txt","w"); 131 | if (outputFilePtr == NULL) 132 | { 133 | perror(""); 134 | } 135 | else 136 | { 137 | int i; 138 | for (i = 0; i < waveData.size; ++i) 139 | { 140 | fprintf(outputFilePtr,"%d\n",waveData.samples[i]); 141 | } 142 | fclose(outputFilePtr); 143 | } 144 | } 145 | 146 | /* 147 | * Prints the wave header 148 | */ 149 | void printHeaderInfo(WaveHeader hdr) 150 | { 151 | char buf[5]; 152 | printf("Header Info:\n"); 153 | strncpy(buf, hdr.chunkID, 4); 154 | buf[4] = '\0'; 155 | printf(" Chunk ID: %s\n",buf); 156 | printf(" Chunk Size: %d\n", hdr.chunkSize); 157 | strncpy(buf,hdr.format,4); 158 | buf[4] = '\0'; 159 | printf(" Format: %s\n", buf); 160 | strncpy(buf,hdr.subchunkID,4); 161 | buf[4] = '\0'; 162 | printf(" Sub-chunk ID: %s\n", buf); 163 | printf(" Sub-chunk Size: %d\n", hdr.subchunkSize); 164 | printf(" Audio Format: %d\n", hdr.audioFormat); 165 | printf(" Channel Count: %d\n", hdr.numChannels); 166 | printf(" Sample Rate: %d\n", hdr.sampleRate); 167 | printf(" Bytes per Second: %d\n", hdr.bytesPerSecond); 168 | printf(" Block alignment: %d\n", hdr.blockAlign); 169 | printf(" Bit depth: %d\n", hdr.bitDepth); 170 | strncpy(buf,hdr.dataID, 4); 171 | buf[4] = '\0'; 172 | printf(" Data ID: %s\n", buf); 173 | printf(" Data Size: %d\n", hdr.dataSize); 174 | } 175 | 176 | #endif 177 | 178 | --------------------------------------------------------------------------------