├── .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 |
--------------------------------------------------------------------------------