forked from charlie-foxtrot/RTLSDR-Airband
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrtl_airband.h
397 lines (358 loc) · 10.1 KB
/
rtl_airband.h
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
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
/*
* rtl_airband.h
* Global declarations
*
* Copyright (c) 2015-2021 Tomasz Lemiech <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _RTL_AIRBAND_H
#define _RTL_AIRBAND_H 1
#include <cstdio>
#include <complex>
#include <stdint.h> // uint32_t
#include <pthread.h>
#include <sys/time.h>
#include <shout/shout.h>
#include <lame/lame.h>
#include <libconfig.h++>
#include <netinet/in.h> // sockaddr_in
#include "config.h"
#ifdef WITH_BCM_VC
#include "hello_fft/gpu_fft.h"
#else
#include <fftw3.h>
#endif
#ifdef WITH_PULSEAUDIO
#include <pulse/context.h>
#include <pulse/stream.h>
#endif
#include "input-common.h" // input_t
#include "squelch.h"
#include "filters.h"
#include "logging.h"
#define ALIGNED32 __attribute__((aligned(32)))
#define SLEEP(x) usleep(x * 1000)
#define THREAD pthread_t
#define GOTOXY(x, y) printf("%c[%d;%df",0x1B,y,x)
#ifndef SYSCONFDIR
#define SYSCONFDIR "/usr/local/etc"
#endif
#define CFGFILE SYSCONFDIR "/rtl_airband.conf"
#define PIDFILE "/run/rtl_airband.pid"
#define MIN_BUF_SIZE 2560000
#define DEFAULT_SAMPLE_RATE 2560000
#ifdef NFM
#define WAVE_RATE 16000
#else
#define WAVE_RATE 8000
#endif
#define WAVE_BATCH WAVE_RATE / 8
#define AGC_EXTRA 100
#define WAVE_LEN 2 * WAVE_BATCH + AGC_EXTRA
#define MP3_RATE 8000
#define MAX_SHOUT_QUEUELEN 32768
#define TAG_QUEUE_LEN 16
#define MAX_MIXINPUTS 32
#define MIN_FFT_SIZE_LOG 8
#define DEFAULT_FFT_SIZE_LOG 9
#define MAX_FFT_SIZE_LOG 13
#define LAMEBUF_SIZE 22000 //todo: calculate
#define MIX_DIVISOR 2
#define ONES(x) ~(~0U << (x))
#define SET_BIT(a, x) (a) |= (1 << (x))
#define RESET_BIT(a, x) (a) &= ~(1 << (x))
#define IS_SET(a, x) (a) & (1 << (x))
#if defined WITH_BCM_VC
struct sample_fft_arg
{
size_t fft_size_by4;
GPU_FFT_COMPLEX* dest;
};
extern "C" void samplefft(sample_fft_arg *a, unsigned char* buffer, float* window, float* levels);
# define FFT_BATCH 250
#else
# define FFT_BATCH 1
#endif
//#define AFC_LOGGING
enum status {NO_SIGNAL = ' ', SIGNAL = '*', AFC_UP = '<', AFC_DOWN = '>' };
enum ch_states { CH_DIRTY, CH_WORKING, CH_READY };
enum mix_modes { MM_MONO, MM_STEREO };
enum output_type {
O_ICECAST,
O_FILE,
O_RAWFILE,
O_MIXER,
O_UDP_STREAM
#ifdef WITH_PULSEAUDIO
, O_PULSE
#endif
};
struct icecast_data {
const char *hostname;
int port;
#ifdef LIBSHOUT_HAS_TLS
int tls_mode;
#endif
const char *username;
const char *password;
const char *mountpoint;
const char *name;
const char *genre;
const char *description;
bool send_scan_freq_tags;
shout_t *shout;
};
struct file_data {
char *basename;
char *suffix;
char *file_path;
char *file_path_tmp;
bool continuous;
bool append;
bool split_on_transmission;
bool include_freq;
timeval open_time;
timeval last_write_time;
FILE *f;
enum output_type type;
};
struct udp_stream_data {
float *stereo_buffer;
size_t stereo_buffer_len;
bool continuous;
const char *dest_address;
const char *dest_port;
int send_socket;
struct sockaddr dest_sockaddr;
socklen_t dest_sockaddr_len;
};
#ifdef WITH_PULSEAUDIO
struct pulse_data {
const char *server;
const char *name;
const char *sink;
const char *stream_name;
pa_context *context;
pa_stream *left, *right;
pa_channel_map lmap, rmap;
mix_modes mode;
bool continuous;
};
#endif
struct mixer_data {
struct mixer_t *mixer;
int input;
};
struct output_t {
enum output_type type;
bool enabled;
bool active;
void *data;
};
struct freq_tag {
int freq;
struct timeval tv;
};
enum modulations {
MOD_AM
#ifdef NFM
, MOD_NFM
#endif
};
class Signal {
public:
Signal(void) {
pthread_cond_init(&cond_, NULL);
pthread_mutex_init(&mutex_, NULL);
}
void send(void) {
pthread_mutex_lock(&mutex_);
pthread_cond_signal(&cond_);
pthread_mutex_unlock(&mutex_);
}
void wait(void) {
pthread_mutex_lock(&mutex_);
pthread_cond_wait(&cond_, &mutex_);
pthread_mutex_unlock(&mutex_);
}
private:
pthread_cond_t cond_;
pthread_mutex_t mutex_;
};
struct freq_t {
int frequency; // scan frequency
char *label; // frequency label
float agcavgfast; // average power, for AGC
float ampfactor; // multiplier to increase / decrease volume
Squelch squelch;
size_t active_counter; // count of loops where channel has signal
NotchFilter notch_filter; // notch filter - good to remove CTCSS tones
LowpassFilter lowpass_filter; // lowpass filter, applied to I/Q after derotation, set at bandwidth/2 to remove out of band noise
enum modulations modulation;
};
struct channel_t {
float wavein[WAVE_LEN]; // FFT output waveform
float waveout[WAVE_LEN]; // waveform after squelch + AGC (left/center channel mixer output)
float waveout_r[WAVE_LEN]; // right channel mixer output
float iq_in[2*WAVE_LEN]; // raw input samples for I/Q outputs and NFM demod
float iq_out[2*WAVE_LEN]; // raw output samples for I/Q outputs (FIXME: allocate only if required)
#ifdef NFM
float pr; // previous sample - real part
float pj; // previous sample - imaginary part
float prev_waveout; // previous sample - waveout before notch / ampfactor
float alpha;
#endif
uint32_t dm_dphi, dm_phi; // derotation frequency and current phase value
enum mix_modes mode; // mono or stereo
status axcindicate;
unsigned char afc; //0 - AFC disabled; 1 - minimal AFC; 2 - more aggressive AFC and so on to 255
struct freq_t *freqlist;
int freq_count;
int freq_idx;
int output_count;
int need_mp3;
int needs_raw_iq;
int has_iq_outputs;
enum ch_states state; // mixer channel state flag
output_t *outputs;
int highpass; // highpass filter cutoff
int lowpass; // lowpass filter cutoff
lame_t lame; // Context for LAME MP3 encoding if needed
unsigned char *lamebuf; // Buffer used by each lame encode
};
enum rec_modes { R_MULTICHANNEL, R_SCAN };
struct device_t {
input_t *input;
#ifdef NFM
float alpha;
#endif
int channel_count;
size_t *base_bins, *bins;
channel_t *channels;
// FIXME: size_t
int waveend;
int waveavail;
THREAD controller_thread;
struct freq_tag tag_queue[TAG_QUEUE_LEN];
int tq_head, tq_tail;
int last_frequency;
pthread_mutex_t tag_queue_lock;
int row;
int failed;
enum rec_modes mode;
size_t output_overrun_count;
};
struct mixinput_t {
float *wavein;
float ampfactor;
float ampl, ampr;
bool ready;
bool has_signal;
pthread_mutex_t mutex;
size_t input_overrun_count;
};
struct mixer_t {
const char *name;
bool enabled;
int input_count;
int interval;
unsigned int inputs_todo;
unsigned int input_mask;
channel_t channel;
mixinput_t inputs[MAX_MIXINPUTS];
size_t output_overrun_count;
};
struct demod_params_t {
Signal *mp3_signal;
int device_start;
int device_end;
#ifndef WITH_BCM_VC
fftwf_plan fft;
fftwf_complex* fftin;
fftwf_complex* fftout;
#endif
};
struct output_params_t {
Signal *mp3_signal;
int device_start;
int device_end;
int mixer_start;
int mixer_end;
};
// version.cpp
extern char const *RTL_AIRBAND_VERSION;
// output.cpp
lame_t airlame_init(mix_modes mixmode, int highpass, int lowpass);
void shout_setup(icecast_data *icecast, mix_modes mixmode);
void disable_device_outputs(device_t *dev);
void disable_channel_outputs(channel_t *channel);
void *output_check_thread(void* params);
void *output_thread(void* params);
// rtl_airband.cpp
extern bool use_localtime;
extern bool multiple_demod_threads;
extern bool multiple_output_threads;
extern char *stats_filepath;
extern size_t fft_size, fft_size_log;
extern int device_count, mixer_count;
extern int shout_metadata_delay;
extern volatile int do_exit, device_opened;
extern float alpha;
extern device_t *devices;
extern mixer_t *mixers;
// util.cpp
int atomic_inc(volatile int *pv);
int atomic_dec(volatile int *pv);
int atomic_get(volatile int *pv);
double atofs(char *s);
double delta_sec(const timeval *start, const timeval *stop);
void log(int priority, const char *format, ...);
void tag_queue_put(device_t *dev, int freq, struct timeval tv);
void tag_queue_get(device_t *dev, struct freq_tag *tag);
void tag_queue_advance(device_t *dev);
void sincosf_lut_init();
void sincosf_lut(uint32_t phi, float *sine, float *cosine);
void *xcalloc(size_t nmemb, size_t size, const char *file, const int line, const char *func);
void *xrealloc(void *ptr, size_t size, const char *file, const int line, const char *func);
#define XCALLOC(nmemb, size) xcalloc((nmemb), (size), __FILE__, __LINE__, __func__)
#define XREALLOC(ptr, size) xrealloc((ptr), (size), __FILE__, __LINE__, __func__)
float dBFS_to_level(const float &dBFS);
float level_to_dBFS(const float &level);
// mixer.cpp
mixer_t *getmixerbyname(const char *name);
int mixer_connect_input(mixer_t *mixer, float ampfactor, float balance);
void mixer_disable_input(mixer_t *mixer, int input_idx);
void mixer_put_samples(mixer_t *mixer, int input_idx, const float *samples, bool has_signal, unsigned int len);
void *mixer_thread(void *params);
const char *mixer_get_error();
// config.cpp
int parse_devices(libconfig::Setting &devs);
int parse_mixers(libconfig::Setting &mx);
// udp_stream.cpp
bool udp_stream_init(udp_stream_data *sdata, mix_modes mode, size_t len);
void udp_stream_write(udp_stream_data *sdata, const float *data, size_t len);
void udp_stream_write(udp_stream_data *sdata, const float *data_left, const float *data_right, size_t len);
void udp_stream_shutdown(udp_stream_data *sdata);
#ifdef WITH_PULSEAUDIO
#define PULSE_STREAM_LATENCY_LIMIT 10000000UL
// pulse.cpp
void pulse_init();
int pulse_setup(pulse_data *pdata, mix_modes mixmode);
void pulse_start();
void pulse_shutdown(pulse_data *pdata);
void pulse_write_stream(pulse_data *pdata, mix_modes mode, const float *data_left, const float *data_right, size_t len);
#endif
#endif /* _RTL_AIRBAND_H */
// vim: ts=4