forked from charlie-foxtrot/RTLSDR-Airband
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rtl_airband.h
269 lines (246 loc) · 6.92 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
/*
* rtl_airband.h
* Global declarations
*
* Copyright (c) 2015-2016 Tomasz Lemiech <szpajder@gmail.com>
*
* 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/>.
*/
#include <cstdio>
#include <pthread.h>
#include <sys/time.h>
#include <shout/shout.h>
#include <lame/lame.h>
#include <libconfig.h++>
#include <rtl-sdr.h>
#ifdef USE_BCM_VC
#include "hello_fft/gpu_fft.h"
#endif
#define RTL_AIRBAND_VERSION "2.3.0"
#define ALIGN
#define ALIGN2 __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"
#if DEBUG
#define DEBUG_PATH "rtl_airband_debug.log"
#endif
#define BUF_SIZE 2560000
#define SOURCE_RATE 2560000
#ifdef NFM
#define WAVE_RATE 16000
#else
#define WAVE_RATE 8000
#endif
#define WAVE_BATCH WAVE_RATE / 8
#define AGC_EXTRA WAVE_RATE / 160
#define WAVE_LEN 2 * WAVE_BATCH + AGC_EXTRA
#define MP3_RATE 8000
#define MAX_SHOUT_QUEUELEN 32768
#define TAG_QUEUE_LEN 16
#define CHANNELS 8
#define MAX_MIXINPUTS 32
#define FFT_SIZE_LOG 9
#define LAMEBUF_SIZE 22000 //todo: calculate
#define MIX_DIVISOR 2
#define ONES(x) ~(~0 << (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 USE_BCM_VC
struct sample_fft_arg
{
int 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 FFT_SIZE (2<<(FFT_SIZE_LOG - 1))
//#define AFC_LOGGING
struct icecast_data {
const char *hostname;
int port;
const char *username;
const char *password;
const char *mountpoint;
const char *name;
const char *genre;
bool send_scan_freq_tags;
shout_t *shout;
};
struct file_data {
const char *dir;
const char *prefix;
char *suffix;
bool continuous;
bool append;
FILE *f;
};
struct mixer_data {
struct mixer_t *mixer;
int input;
};
enum output_type { O_ICECAST, O_FILE, O_MIXER };
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
};
enum ch_states { CH_DIRTY, CH_WORKING, CH_READY };
enum mix_modes { MM_MONO, MM_STEREO };
struct channel_t {
float wavein[WAVE_LEN]; // FFT output waveform
float waveref[WAVE_LEN]; // for power level calculation
float waveout[WAVE_LEN]; // waveform after squelch + AGC (left/center channel mixer output)
float waveout_r[WAVE_LEN]; // right channel mixer output
#ifdef NFM
float complex_samples[2*WAVE_LEN]; // raw samples for NFM demod
float timeref_nsin[WAVE_RATE];
float timeref_cos[WAVE_RATE];
int wavecnt; // sample counter for timeref shift
// FIXME: get this from complex_samples?
float pr; // previous sample - real part
float pj; // previous sample - imaginary part
float alpha;
#endif
enum modulations modulation;
enum mix_modes mode; // mono or stereo
int agcsq; // squelch status, 0 = signal, 1 = suppressed
float agcavgfast; // average power, for AGC
float agcavgslow; // average power, for squelch level detection
float agcmin; // noise level
int sqlevel; // manually configured squelch level
int agclow; // low level sample count
char axcindicate; // squelch/AFC status indicator: ' ' - no signal; '*' - has signal; '>', '<' - signal tuned by AFC
unsigned char afc; //0 - AFC disabled; 1 - minimal AFC; 2 - more aggressive AFC and so on to 255
int frequency;
int freq_count;
int *freqlist;
char **labels;
int output_count;
int need_mp3;
enum ch_states state; // mixer channel state flag
output_t *outputs;
lame_t lame;
};
enum rec_modes { R_MULTICHANNEL, R_SCAN };
struct device_t {
unsigned char buffer[BUF_SIZE + FFT_SIZE * 2 + 48];
int bufs;
int bufe;
rtlsdr_dev_t* rtlsdr;
int device;
int centerfreq;
int correction;
int gain;
#ifdef NFM
float alpha;
#endif
int channel_count;
int base_bins[CHANNELS];
int bins[CHANNELS];
channel_t channels[CHANNELS];
int waveend;
int waveavail;
THREAD rtl_thread;
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;
pthread_mutex_t buffer_lock;
int row;
int failed;
enum rec_modes mode;
};
struct mixinput_t {
float *wavein;
float ampfactor;
float ampl, ampr;
bool ready;
pthread_mutex_t mutex;
};
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];
};
// output.cpp
lame_t airlame_init(mix_modes mixmode);
void shout_setup(icecast_data *icecast, mix_modes mixmode);
void disable_device_outputs(device_t *dev);
void disable_channel_outputs(channel_t *channel);
void *icecast_check(void* params);
void *output_thread(void* params);
// rtl_airband.cpp
extern bool use_localtime;
extern int device_count, mixer_count;
extern int shout_metadata_delay, do_syslog, foreground;
extern volatile int do_exit;
extern float alpha;
extern device_t *devices;
extern mixer_t *mixers;
extern pthread_cond_t mp3_cond;
extern pthread_mutex_t mp3_mutex;
// util.cpp
void error();
int atomic_inc(volatile int *pv);
int atomic_dec(volatile int *pv);
int atomic_get(volatile int *pv);
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 init_debug (char *file);
void close_debug();
extern FILE *debugf;
#define debug_print(fmt, ...) \
do { if (DEBUG) fprintf(debugf, "%s(): " fmt, __func__, __VA_ARGS__); fflush(debugf); } while (0)
#define debug_bulk_print(fmt, ...) \
do { if (DEBUG) fprintf(debugf, "%s(): " fmt, __func__, __VA_ARGS__); } while (0)
// 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, float *samples, 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);
// vim: ts=4