1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22
23
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27
28
29 #include "globdef.h"
30 #include "uidef.h"
31 #include "fft1def.h"
32 #include "fft2def.h"
33 #include "fft3def.h"
34 #include "screendef.h"
35 #include "sigdef.h"
36 #include "seldef.h"
37 #include "rusage.h"
38 #include "thrdef.h"
39 #include "txdef.h"
40 #include "options.h"
41 #include "conf.h"
42
43 #if BUFBARS == TRUE
44 #define RX_INDICATOR_MAXNUM 8
45 extern int rx_indicator_maxpos[RX_INDICATOR_MAXNUM];
46 extern int rx_indicator_minpos[RX_INDICATOR_MAXNUM];
47 void show_bufbar(int i, int k);
48 #endif
49
50 float iir3_gain[9]={6.0,
51 31.55634919,
52 188.6646578,
53 1274.138623,
54 9304.588559,
55 70996.86308,
56 554452.4788,
57 4382011.796,
58 34842632.96};
59
60 float iir3_c0[9]={0.0,
61 0.1978251873,
62 0.4535459334,
63 0.6748018873,
64 0.8216600080,
65 0.9064815219,
66 0.9520967536,
67 0.9757549044,
68 0.9878031267};
69
70 float iir3_c1[9]={ -0.3333333333,
71 -0.9103690003,
72 -1.7151178300,
73 -2.2889939150,
74 -2.6262484669,
75 -2.8084292678,
76 -2.9030250284,
77 -2.9512131915,
78 -2.9755315293};
79
80 float iir3_c2[9]={ 0.0,
81 1.4590290622,
82 2.2191686183,
83 2.6079132760,
84 2.8037286680,
85 2.9018350649,
86 2.9509138462,
87 2.9754564614,
88 2.9877281729};
89
90
blocking_rxout(void)91 void blocking_rxout(void)
92 {
93 #if RUSAGE_OLD == TRUE
94 int local_workload_counter;
95 #endif
96 int k, initial_n, sleep_cnt;
97 int local_workload_reset;
98 char s[80];
99 char cc;
100 float sleep_time, short_sleep_time;
101 float t1;
102 #if OSNUM == OSNUM_LINUX
103 clear_thread_times(THREAD_BLOCKING_RXOUT);
104 #endif
105 #if RUSAGE_OLD == TRUE
106 local_workload_counter=workload_counter;
107 #endif
108 local_workload_reset=workload_reset_flag;
109 sleep_time=2000000./snd[RXDA].interrupt_rate;
110 if(sleep_time < 1010)sleep_time=1010;
111 if(sleep_time > 100000)sleep_time=100000;
112 short_sleep_time=0.2*sleep_time;
113 if(short_sleep_time > 10000)short_sleep_time=10000;
114 if(short_sleep_time < 1010)short_sleep_time=1010;
115 if(rx_daout_bytes == 1)
116 {
117 cc=0x80;
118 }
119 else
120 {
121 cc=0;
122 }
123 lir_await_event(EVENT_BLOCKING_RXOUT);
124 daout_px=(daout_px-snd[RXDA].block_bytes+daout_size)&daout_bufmask;
125 memset(&daout[daout_px],cc,snd[RXDA].block_bytes);
126 // It may take a long time to return from the first write.
127 // 4Front OSS may require 0.1 second to set up the output
128 // Write data that will fill the soundcard with data for about
129 // 20 milliseconds (or more).
130 lir_rx_dawrite();
131 t1=0.5+.02*genparm[DA_OUTPUT_SPEED]/snd[RXDA].block_frames;
132 k=t1-1;
133 while(k>0)
134 {
135 daout_px=(daout_px-snd[RXDA].block_bytes+daout_size)&daout_bufmask;
136 lir_rx_dawrite();
137 k--;
138 }
139 update_snd(RXDA);
140 thread_status_flag[THREAD_BLOCKING_RXOUT]=THRFLAG_ACTIVE;
141 sleep_cnt=0;
142 initial_n=2;
143 while(!kill_all_flag &&
144 thread_command_flag[THREAD_BLOCKING_RXOUT]==THRFLAG_ACTIVE)
145 {
146 // *******************************************************
147 #if RUSAGE_OLD == TRUE
148 if(local_workload_counter != workload_counter)
149 {
150 local_workload_counter=workload_counter;
151 update_snd(RXDA);
152 if(snd[RXDA].valid_bytes > snd[RXDA].block_bytes)
153 {
154 make_thread_times(THREAD_BLOCKING_RXOUT);
155 update_snd(RXDA);
156 }
157 }
158 #endif
159 if(local_workload_reset!=workload_reset_flag)
160 {
161 update_snd(RXDA);
162 snd[RXDA].min_valid_frames=snd[RXDA].tot_frames;
163 local_workload_reset=workload_reset_flag;
164 }
165 if( ((daout_pa-daout_px+daout_size)&daout_bufmask) >
166 initial_n*snd[RXDA].block_bytes)
167 {
168 sleep_cnt=0;
169 if(audio_dump_flag==0 && rx_audio_out != -1)
170 {
171 while(initial_n > 1)
172 {
173 lir_rx_dawrite();
174 initial_n--;
175 }
176 lir_sched_yield();
177 if( ((daout_pa-daout_px+daout_size)&daout_bufmask) >
178 snd[RXDA].block_bytes)
179 {
180 lir_rx_dawrite();
181 lir_sched_yield();
182 if( ((daout_pa-daout_px+daout_size)&daout_bufmask) >
183 snd[RXDA].block_bytes)
184 {
185 lir_rx_dawrite();
186 }
187 }
188 }
189 else
190 {
191 daout_px=(daout_px+snd[RXDA].block_bytes)&daout_bufmask;
192 }
193 }
194 else
195 {
196 if(audio_dump_flag == 1 || rx_audio_out == -1)
197 {
198 lir_sleep(sleep_time);
199 }
200 else
201 {
202 update_snd(RXDA);
203 if(snd[RXDA].valid_bytes > 8*snd[RXDA].block_bytes)
204 {
205 lir_sleep(sleep_time);
206 goto loop_end;;
207 }
208 if(snd[RXDA].valid_bytes < snd[RXDA].block_bytes/4)
209 {
210 if(count_rx_underrun_flag)
211 {
212 no_of_rx_underrun_errors++;
213 sprintf(s,"RX%s%d",underrun_error_msg,no_of_rx_underrun_errors);
214 wg_error(s,WGERR_RXOUT);
215 }
216 // clear the buffer
217 daout_px=(daout_px-snd[RXDA].block_bytes+daout_size)&daout_bufmask;
218 memset(&daout[daout_px],cc,snd[RXDA].block_bytes);
219 lir_rx_dawrite();
220 lir_sleep(short_sleep_time);
221 }
222 else
223 {
224 sleep_cnt++;
225 if(sleep_cnt > 2)lir_sleep(short_sleep_time);
226 }
227 }
228 }
229 loop_end:;
230 }
231 thread_status_flag[THREAD_BLOCKING_RXOUT]=THRFLAG_RETURNED;
232 while(!kill_all_flag &&
233 thread_command_flag[THREAD_BLOCKING_RXOUT] != THRFLAG_NOT_ACTIVE)
234 {
235 lir_sleep(1000);
236 }
237 }
238
239 #define MAXMAIL 5
240
rx_output(void)241 void rx_output(void)
242 {
243 #if RUSAGE_OLD == TRUE
244 int local_workload_counter;
245 #endif
246 char delay_margin_flag;
247 char cc, blocking;
248 float dasync_time_interval;
249 int da_start_bytes;
250 int dasync_errors;
251 int daout_py;
252 int i, k;
253 int speed_cnt_maxval;
254 char s[80];
255 double dt1;
256 int local_channels, local_bytes;
257 int local_workload_reset;
258 int speed_cnt;
259 float local_fft3_blocktime;
260 float t1, t2;
261 float sleep_time;
262 double total_time2;
263 double daspeed_time;
264 #if OSNUM == OSNUM_LINUX
265 clear_thread_times(THREAD_RX_OUTPUT);
266 #endif
267 #if RUSAGE_OLD == TRUE
268 local_workload_counter=workload_counter;
269 #endif
270 blocking=TRUE;
271 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
272 {
273 blocking=FALSE;
274 }
275 thread_status_flag[THREAD_RX_OUTPUT]=THRFLAG_ACTIVE;
276 local_channels=rx_daout_channels;
277 local_bytes=rx_daout_bytes;
278 local_fft3_blocktime=fft3_blocktime;
279 daout_pa=0;
280 daout_px=0;
281 count_rx_underrun_flag=FALSE;
282 sys_func(THRFLAG_OPEN_RX_SNDOUT);
283 if(rx_audio_out == -1)blocking=FALSE;
284 if(kill_all_flag)goto da_output_error;
285 if(blocking && audio_dump_flag == 0 && rx_audio_out >= 0)
286 {
287 lir_rx_dawrite();
288 daout_pa=0;
289 daout_px=0;
290 }
291 dasync_errors=0;
292 baseb_output_block=128;
293 da_start_bytes=-1;
294 thread_command_flag[THREAD_BLOCKING_RXOUT]=THRFLAG_NOT_ACTIVE;
295 if(blocking)
296 {
297 lir_init_event(EVENT_BLOCKING_RXOUT);
298 lir_sched_yield();
299 linrad_thread_create(THREAD_BLOCKING_RXOUT);
300 }
301 while(!kill_all_flag &&
302 thread_command_flag[THREAD_RX_OUTPUT]==THRFLAG_ACTIVE)
303 {
304 lir_sleep(3000);
305 }
306 speed_cnt_maxval=0.2*snd[RXDA].interrupt_rate;
307 goto stop_output;
308 resume:;
309 if(blocking)
310 {
311 lir_init_event(EVENT_BLOCKING_RXOUT);
312 lir_sched_yield();
313 linrad_thread_create(THREAD_BLOCKING_RXOUT);
314 }
315 if(lir_rxout_status != LIR_OK)
316 {
317 wg_error("Output soundcard disabled",WGERR_SOUNDCARD);
318 }
319 thread_status_flag[THREAD_RX_OUTPUT]=THRFLAG_ACTIVE;
320 count_rx_underrun_flag=FALSE;
321 lir_sched_yield();
322 sleep_time=1000000./snd[RXDA].interrupt_rate;
323 if(sleep_time < 1010)sleep_time=1010;
324 if(sleep_time > 100000)sleep_time=100000;
325 dasync_time_interval=(float)(7*fft3_size)/timf3_sampling_speed;
326 if(dasync_time_interval < (float)(7*fft1_size)/timf1_sampling_speed)
327 dasync_time_interval = (float)(7*fft1_size)/timf1_sampling_speed;
328 if(genparm[SECOND_FFT_ENABLE]!=0)
329 {
330 if(dasync_time_interval < (float)(7*fft2_size)/timf1_sampling_speed)
331 dasync_time_interval = (float)(7*fft2_size)/timf1_sampling_speed;
332 }
333 if(dasync_time_interval < 0.5)dasync_time_interval=0.5;
334 local_workload_reset=workload_reset_flag;
335 speed_cnt=snd[RXDA].interrupt_rate;
336 baseb_output_block=snd[RXDA].block_bytes/(2*da_resample_ratio);
337 if(baseb_output_block < 16)baseb_output_block=16;
338 baseb_min_block=1+1/da_resample_ratio;
339 if(baseb_min_block < baseb_output_block/16)
340 {
341 baseb_min_block=baseb_output_block/16;
342 }
343 k=0;
344 dasync_time=current_time();
345 daspeed_time=dasync_time;
346 await_narrowband_processing:;
347 if(kill_all_flag) goto da_output_error;
348 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
349 lir_sleep(2000);
350 update_snd(RXDA);
351 make_timing_info();
352 if(kill_all_flag) goto da_output_error;
353 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
354 t1=total_wttim-da_wait_time;
355 if(t1 < 0)
356 {
357 goto await_narrowband_processing;
358 }
359 if(k == 0 && blocking)
360 {
361 lir_set_event(EVENT_BLOCKING_RXOUT);
362 lir_sched_yield();
363 update_snd(RXDA);
364 make_timing_info();
365 }
366 k++;
367 if(t1*baseband_sampling_speed > 3*baseb_output_block)
368 {
369 i=t1*baseband_sampling_speed;
370 if(i > baseb_wts)i=baseb_wts;
371 baseb_py=(baseb_py+i+baseband_size)&baseband_mask;
372 baseb_wts-=i;
373 }
374 lir_sched_yield();
375 update_snd(RXDA);
376 make_timing_info();
377 if(kill_all_flag) goto da_output_error;
378 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
379 t1=total_wttim-da_wait_time;
380 if(t1*baseband_sampling_speed > 3*baseb_output_block )//|| k<2)
381 {
382 if(recent_time-dasync_time > 2)
383 {
384 lirerr(1199);
385 goto da_output_error;
386 }
387 goto await_narrowband_processing;
388 }
389 if(blocking && thread_status_flag[THREAD_BLOCKING_RXOUT] != THRFLAG_ACTIVE)
390 {
391 goto await_narrowband_processing;
392 }
393 baseb_fx=(baseb_py-2+baseband_size)&baseband_mask;
394 if(da_start_bytes == -1)
395 {
396 dasync_counter=0;
397 dasync_sum=0;
398 dasync_avg1=-1.5;
399 dasync_avg2=-1.5;
400 dasync_avg3=-1.5;
401 dasync_time=current_time();
402 dasync_avgtime=dasync_time;
403 daspeed_time=dasync_time+1;
404 }
405 daout_pa=0;
406 daout_px=0;
407 daout_py=0;
408 snd[RXDA].min_valid_frames=snd[RXDA].tot_frames;
409 min_daout_samps=baseband_size;
410 delay_margin_flag=TRUE;
411 lir_sleep(1000);
412 make_timing_info();
413 update_snd(RXDA);
414 if(kill_all_flag) goto da_output_error;
415 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
416 t1=total_wttim-da_wait_time;
417 if(t1*baseband_sampling_speed > 3*baseb_output_block )//|| k<2)
418 {
419 goto await_narrowband_processing;
420 }
421 while(!kill_all_flag &&
422 thread_command_flag[THREAD_RX_OUTPUT] == THRFLAG_ACTIVE)
423 {
424 #if RUSAGE_OLD == TRUE
425 if(local_workload_counter != workload_counter)
426 {
427 local_workload_counter=workload_counter;
428 make_thread_times(THREAD_RX_OUTPUT);
429 }
430 #endif
431 // We use speed_cnt to avoid using a lot of CPU time on this code section.
432 if(audio_dump_flag==0)speed_cnt--;
433 if(speed_cnt==0)
434 {
435 if(delay_margin_flag)
436 {
437 snd[RXDA].min_valid_frames=snd[RXDA].tot_frames;
438 min_daout_samps=baseband_size;
439 delay_margin_flag=FALSE;
440 }
441 if(local_workload_reset!=workload_reset_flag)
442 {
443 snd[RXDA].min_valid_frames=snd[RXDA].tot_frames;
444 local_workload_reset=workload_reset_flag;
445 }
446 speed_cnt=speed_cnt_maxval;
447 total_time2=recent_time;
448 if(recent_time-daspeed_time > 0)
449 {
450 // Compute the D/A speed and once every second.
451 if(audio_dump_flag==0)
452 {
453 daspeed_time=recent_time+1;
454 lir_sched_yield();
455 if(da_start_bytes == -1)
456 {
457 da_start_time=total_time2;
458 da_block_counter=0;
459 da_start_bytes=snd[RXDA].empty_bytes;
460 snd[RXDA].min_valid_frames=snd[RXDA].tot_frames;
461 count_rx_underrun_flag=TRUE;
462 }
463 else
464 {
465 measured_da_speed=(da_block_counter*snd[RXDA].block_bytes+
466 snd[RXDA].empty_bytes-da_start_bytes)/
467 (snd[RXDA].framesize*(total_time2-da_start_time));
468 }
469 }
470 // Keep track of the error in the frequency ratio between input and output.
471 // Average the total processing delay and adjust resampling rate to
472 // keep it constant.
473 #define DASYNC_MAXCOUNT 15 //Number of seconds used to form average
474 dt1=current_time();
475 if( diskread_flag == 0 &&
476 new_baseb_flag == 0 &&
477 dt1-dasync_avgtime > dasync_time_interval &&
478 rx_audio_out != -1)
479 {
480 dasync_avgtime=dt1;
481 lir_sched_yield();
482 make_timing_info();
483 if(kill_all_flag) goto da_output_error;
484 if(timinfo_flag != 0)
485 {
486 sprintf(s,"sync:%f ",total_wttim-dasync_avg3);
487 lir_text(26,screen_last_line-8,s);
488 }
489 if(dasync_avg3 >= 0 && fabs(total_wttim-dasync_avg3)>0.5)
490 {
491 dasync_errors++;
492 sprintf(s,"DA SYNC ERRORS %d",dasync_errors);
493 wg_error(s,WGERR_DASYNC);
494 baseb_reset_counter++;
495 da_start_bytes=-1;
496 dasync_counter=0;
497 }
498 dasync_counter++;
499 dasync_sum+=total_wttim;
500 if(dasync_counter >= DASYNC_MAXCOUNT)
501 {
502 dasync_avg1=dasync_sum/dasync_counter;
503 dasync_counter=0;
504 dasync_sum=0;
505 t2=dt1-dasync_time;
506 dasync_time=dt1;
507 if(dasync_avg2 > 0)
508 {
509 // The drift between input and output after t2 seconds is
510 // the difference between the two averages.
511 // Convert to frequency ratio, but use half the error only
512 // to avoid oscillations.
513 // Correct for the deviation from the first average, but only 20%
514 // so we drift slowy towards it if we are off.
515 // also add 5% of the time deviation from the ideal time.
516 t1= (t2+0.5*(dasync_avg2-dasync_avg1)+
517 0.2*(dasync_avg3-dasync_avg1))/t2;
518 // dasync_avg3=0.9*dasync_avg3+0.1*da_wait_time;
519 new_da_resample_ratio=da_resample_ratio*t1;
520 dasync_avg2=dasync_avg1;
521 }
522 else
523 {
524 if(dasync_avg3 <0)
525 {
526 dasync_avg3=dasync_avg1;
527 }
528 else
529 {
530 dasync_avg2=dasync_avg1;
531 }
532 }
533 }
534 }
535 if(thread_command_flag[THREAD_RX_OUTPUT] !=
536 THRFLAG_ACTIVE)goto stop_output;
537 }
538 }
539 // ***********************************************************
540 lir_sched_yield();
541 if( ((baseb_pa-baseb_py+baseband_size)&baseband_mask) > baseb_output_block )
542 {
543 if( ((daout_px-snd[RXDA].block_bytes-daout_pa+daout_size)&daout_bufmask) > (daout_size>>1) )
544 {
545 make_audio_signal();
546 }
547 else
548 {
549 if(audio_dump_flag==0)lir_sleep(sleep_time);
550 }
551 }
552 lir_sched_yield();
553 if( ((baseb_pa-baseb_py+baseband_size)&baseband_mask) <= baseb_output_block )
554 {
555 lir_await_event(EVENT_BASEB);
556 }
557 if( (ui.network_flag&NET_RXOUT_BASEBRAW) != 0)
558 {
559 #if NET_BASEBRAW_MODE == WFM_FM_FIRST_LOWPASS || \
560 NET_BASEBRAW_MODE == WFM_FM_FIRST_LOWPASS_UPSAMP || \
561 NET_BASEBRAW_MODE == WFM_STEREO_LOW || \
562 NET_BASEBRAW_MODE == WFM_STEREO_HIGH
563 int *ntbuf;
564 while(baseb_pn != baseb_pa &&
565 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
566 {
567 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
568 ntbuf[0]=floor(1000000000.*baseb_fm_demod_low[baseb_pn]);
569 baseb_pn=(baseb_pn+1)&baseband_mask;
570 basebrawnet_pa=(basebrawnet_pa+4)&basebrawnet_mask;
571 }
572 #endif
573 #if NET_BASEBRAW_MODE == WFM_FM_FULL_BANDWIDTH
574 int *ntbuf;
575 while(baseb_pn != baseb_pa &&
576 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
577 {
578 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
579 ntbuf[0]=floor(300000000.*baseb_fm_demod[baseb_pn]);
580 baseb_pn=(baseb_pn+1)&baseband_mask;
581 basebrawnet_pa=(basebrawnet_pa+4)&basebrawnet_mask;
582 }
583 #endif
584 #if NET_BASEBRAW_MODE == WFM_AM_FIRST_LOWPASS
585 int *ntbuf;
586 while(baseb_pn != baseb_pa &&
587 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
588 {
589 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
590 ntbuf[0]=floor(0.2*sqrt(baseb_carrier_ampl[baseb_pn]));
591 baseb_pn=(baseb_pn+1)&baseband_mask;
592 basebrawnet_pa=(basebrawnet_pa+4)&basebrawnet_mask;
593 }
594 #endif
595 #if NET_BASEBRAW_MODE == WFM_FM_FIRST_LOWPASS_RESAMP
596 int *ntbuf;
597 while(fm1_px != fm1_pa &&
598 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
599 {
600 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
601 ntbuf[0]=floor(fm1_all[fm1_px]);
602 // baseb_pn=(baseb_pn+1)&baseband_mask;
603 fm1_px=(fm1_px+1)&fm1_mask;
604 basebrawnet_pa=(basebrawnet_pa+4)&basebrawnet_mask;
605 }
606 #endif
607 #if NET_BASEBRAW_MODE == BASEBAND_IQ
608 int *ntbuf;
609 if(ui.rx_rf_channels == 1)
610 {
611 while(baseb_pn != baseb_pa &&
612 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
613 {
614 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
615 ntbuf[0]=floor(0.05*baseb_raw[2*baseb_pn ]);
616 ntbuf[1]=floor(0.05*baseb_raw[2*baseb_pn+1]);
617 baseb_pn=(baseb_pn+1)&baseband_mask;
618 basebrawnet_pa=(basebrawnet_pa+8)&basebrawnet_mask;
619 }
620 }
621 else
622 {
623 while(baseb_pn != baseb_pa &&
624 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
625 {
626 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
627 ntbuf[0]=floor(0.05*baseb_raw[2*baseb_pn ]);
628 ntbuf[1]=floor(0.05*baseb_raw[2*baseb_pn+1]);
629 ntbuf[2]=floor(0.05*baseb_raw_orthog[2*baseb_pn ]);
630 ntbuf[3]=floor(0.05*baseb_raw_orthog[2*baseb_pn+1]);
631 baseb_pn=(baseb_pn+1)&baseband_mask;
632 basebrawnet_pa=(basebrawnet_pa+16)&basebrawnet_mask;
633 }
634 }
635 #endif
636 #if NET_BASEBRAW_MODE == WFM_SYNTHETIZED_FROM_FIRST_LOWPASS || \
637 NET_BASEBRAW_MODE == WFM_SUBTRACT_FROM_FIRST_LOWPASS
638 int *ntbuf;
639 while(baseb_pn != baseb_pa &&
640 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
641 {
642 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
643 for(i=0; i<basebraw_ad_channels; i++)
644 {
645 ntbuf[i]=floor(0.05*baseb_carrier[basebraw_ad_channels*baseb_pn+i]);
646 }
647 baseb_pn=(baseb_pn+1)&baseband_mask;
648 basebrawnet_pa=(basebrawnet_pa+4*basebraw_ad_channels)&basebrawnet_mask;
649 }
650 #endif
651 #if NET_BASEBRAW_MODE == WFM_AM_FULL_BANDWIDTH
652 int *ntbuf;
653 while(baseb_pn != baseb_pa &&
654 ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
655 {
656 ntbuf=(int*)&basebraw_netsend_buffer[basebrawnet_pa];
657 ntbuf[0]=0.1*floor(sqrt(baseb_totpwr[baseb_pn]));
658 baseb_pn=(baseb_pn+1)&baseband_mask;
659 basebrawnet_pa=(basebrawnet_pa+4)&basebrawnet_mask;
660 }
661 #endif
662 }
663 if(kill_all_flag) goto da_output_error;
664 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
665 if(audio_dump_flag == 1 || rx_audio_out == -1)
666 {
667 while( ((daout_pa-daout_px+daout_size)&daout_bufmask) >
668 snd[RXDA].block_bytes)
669 {
670 daout_px=(daout_px+snd[RXDA].block_bytes)&daout_bufmask;
671 if(kill_all_flag) goto da_output_error;
672 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
673 }
674 lir_sched_yield();
675 if(kill_all_flag) goto da_output_error;
676 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
677 }
678 while(daout_px != daout_py)
679 {
680 if(wav_write_flag != 0)
681 {
682 if(fwrite(&daout[daout_py],snd[RXDA].block_bytes,1,wav_file)!=1)
683 wavsave_start_stop(0);
684 }
685 da_block_counter+=1;
686 daout_py=(daout_py+snd[RXDA].block_bytes)&daout_bufmask;
687 if(kill_all_flag) goto da_output_error;
688 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)goto stop_output;
689 }
690 #if BUFBARS == TRUE
691 if(baseband_handle != NULL && timinfo_flag!=0)
692 {
693 i=(daout_pa+2-daout_px+daout_bufmask+1)&daout_bufmask;
694 i/=daout_indicator_block;
695 show_bufbar(7,i);
696 }
697 #endif
698 }
699 stop_output:;
700 if(blocking)
701 {
702 lir_set_event(EVENT_BLOCKING_RXOUT);
703 linrad_thread_stop_and_join(THREAD_BLOCKING_RXOUT);
704 lir_close_event(EVENT_BLOCKING_RXOUT);
705 }
706 //stop_output_2:;
707 daout_px=0;
708 daout_pa=0;
709 daout_py=0;
710 if(thread_command_flag[THREAD_RX_OUTPUT] == THRFLAG_IDLE)
711 {
712 if(rx_audio_out >= 0)lir_empty_da_device_buffer();
713 thread_status_flag[THREAD_RX_OUTPUT] = THRFLAG_IDLE;
714 lir_sleep(10000);
715 while(thread_command_flag[THREAD_RX_OUTPUT] == THRFLAG_IDLE)
716 {
717 lir_sleep(5000);
718 if(kill_all_flag) goto da_output_error;
719 }
720 daout_px=0;
721 daout_pa=0;
722 while(thread_command_flag[THREAD_RX_OUTPUT] == THRFLAG_SEMCLEAR)
723 {
724 thread_status_flag[THREAD_RX_OUTPUT] = THRFLAG_SEMCLEAR;
725 lir_await_event(EVENT_RX_START_DA);
726 if(kill_all_flag) goto da_output_error;
727 }
728 if(thread_command_flag[THREAD_RX_OUTPUT] == THRFLAG_ACTIVE)
729 {
730 if( rx_audio_out != -1 && (local_channels != rx_daout_channels ||
731 local_bytes != rx_daout_bytes ||
732 local_fft3_blocktime != fft3_blocktime))
733 {
734 sys_func(THRFLAG_CLOSE_RX_SNDOUT);
735 lir_sched_yield();
736 if(rx_daout_bytes == 1)
737 {
738 cc=0x80;
739 }
740 else
741 {
742 cc=0;
743 }
744 daout_px=0;
745 daout_pa=0;
746 memset(&daout[daout_px],cc,snd[RXDA].block_bytes);
747 sys_func(THRFLAG_OPEN_RX_SNDOUT);
748 if(kill_all_flag || lir_rxout_status != LIR_OK) goto da_output_error;
749 lir_empty_da_device_buffer();
750 da_start_bytes=-1;
751 local_channels=rx_daout_channels;
752 local_bytes=rx_daout_bytes;
753 local_fft3_blocktime=fft3_blocktime;
754 }
755 if(kill_all_flag) goto da_output_error;
756 goto resume;
757 }
758 }
759 da_output_error:;
760 count_rx_underrun_flag=FALSE;
761 if(blocking && thread_command_flag[THREAD_BLOCKING_RXOUT] != THRFLAG_NOT_ACTIVE)
762 {
763 linrad_thread_stop_and_join(THREAD_BLOCKING_RXOUT);
764 }
765 if(rx_audio_out >= 0)
766 {
767 /*
768 if( (ui.use_alsa&(PORTAUDIO_TX_IN+PORTAUDIO_RX_OUT)) == 0)
769 {
770 while( rx_audio_out == tx_audio_in)lir_sleep(10000);
771 }
772 // Perhaps when using OSS in RDWR mode???
773 */
774 sys_func(THRFLAG_CLOSE_RX_SNDOUT);
775 }
776 thread_status_flag[THREAD_RX_OUTPUT]=THRFLAG_RETURNED;
777 while(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_NOT_ACTIVE &&
778 thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_KILL)
779 {
780 lir_sleep(1000);
781 }
782 }
783
make_audio_signal(void)784 void make_audio_signal(void)
785 {
786 int i,i1,i2,i3,i4,mm,nn;
787 float t1,t2,t3,t4,t5,t6,t7;
788 float a1, a2, b1, b2, u1, u2;
789 double dt1;
790 short int *intvar;
791 short int *ntbuf;
792 float r1,r2,r3,r4;
793 float rdiff, final_gain1, final_gain2;
794 float baseb_r1, baseb_r2;
795 int loop_counter;
796 i=1;
797 if(bg_filter_points > 5 && 2*bg_filter_points < bg_xpoints)
798 {
799 if(bg.squelch_level !=0)
800 {
801 if(recent_time-squelch_turnon_time > bg.squelch_time+0.1)
802 {
803 i=0;
804 }
805 }
806 }
807 squelch_on=i;
808 // Resample the baseband signal so we get the correct sampling speed
809 // for the D/A converter.
810 // For each interval in baseb_out there is a non integer number of points
811 // in da_output.
812 dt1=1/sqrt(rx_daout_sin*rx_daout_sin+rx_daout_cos*rx_daout_cos);
813 rx_daout_sin*=dt1;
814 rx_daout_cos*=dt1;
815 final_gain1=final_gain2=0;
816 mm=snd[RXDA].framesize;
817 nn=2*baseb_channels;
818 baseb_r1=daout_pa/(mm*da_resample_ratio);
819 loop_counter=0;
820 resamp:;
821 baseb_r2=(daout_pa+mm)/(mm*da_resample_ratio);
822 i2=baseb_fx+baseb_r1+.5;
823 if(baseb_r2>baseb_r1)
824 {
825 i3=baseb_fx+baseb_r2+.5;
826 }
827 else
828 {
829 i3=baseb_fx+baseb_r2+.5+daout_size/da_resample_ratio;
830 }
831 i2&=baseband_mask;
832 i3&=baseband_mask;
833 if(abs(i3-i2) > 1)
834 {
835 i2=baseb_fx+(baseb_r1+baseb_r2)/2;
836 i3=i2+1;
837 i2&=baseband_mask;
838 i3&=baseband_mask;
839 }
840 else
841 {
842 if(i3==i2)
843 {
844 i2=baseb_fx+baseb_r1;
845 i2&=baseband_mask;
846 if(i3==i2)
847 {
848 i3=i2+1;
849 i3&=baseband_mask;
850 }
851 }
852 }
853 i4=(i3+1)&baseband_mask;
854 baseb_py=i4;
855 i1=(i2+baseband_mask)&baseband_mask;
856 baseb_wts=baseb_pa-baseb_r2-baseb_fx;
857 if(baseb_wts<0)baseb_wts+=baseband_size;
858 loop_counter++;
859 if(loop_counter > 2*baseb_output_block)lir_sched_yield();
860 if( ((daout_pa-daout_px+daout_size)&daout_bufmask) > (daout_size>>1) ||
861 ((baseb_pa-baseb_py+baseband_size)&baseband_mask) < baseb_min_block)
862 {
863 return;
864 }
865 rdiff=baseb_r1+baseb_fx-i2;
866 if(rdiff > baseband_size/2)
867 {
868 rdiff-=baseband_size;
869 }
870 // Use Lagrange's interpolation formula to fit a third degree
871 // polynomial to 4 points:
872 // a1=-rdiff * (rdiff-1)*(rdiff-2)*baseb_out[nn*i1]/6
873 // +(rdiff+1)*(rdiff-1)*(rdiff-2)*baseb_out[nn*i2]/2
874 // -(rdiff+1)* rdiff *(rdiff-2)*baseb_out[nn*i3]/2
875 // +(rdiff+1)* rdiff *(rdiff-1)*baseb_out[nn*i4]/6;
876 // Rewrite slightly to save a few multiplications - do not
877 // think the compiler is smart enough to do it for us.
878 t1=rdiff-1;
879 t2=rdiff-2;
880 t3=rdiff+1;
881 t4=t1*t2;
882 t5=t3*rdiff;
883 t6=rdiff*t4;
884 t4=t3*t4;
885 t7=t5*t2;
886 t5=t5*t1;
887 final_gain1=daout_gain;
888 final_gain2=daout_gain;
889 if(bg.agc_flag == 1)
890 {
891 if( daout_gain*baseb_agc_level[i2] > bg_agc_amplimit)
892 {
893 final_gain1=bg_agc_amplimit/baseb_agc_level[i2];
894 final_gain2=final_gain1;
895 }
896 }
897 if(bg.agc_flag == 2)
898 {
899 if( daout_gain*baseb_agc_level[2*i2] > bg_agc_amplimit)
900 {
901 final_gain1=bg_agc_amplimit/baseb_agc_level[2*i2];
902 }
903 if( daout_gain*baseb_agc_level[2*i2+1] > bg_agc_amplimit)
904 {
905 final_gain2=bg_agc_amplimit/baseb_agc_level[2*i2+1];
906 }
907 }
908 if(squelch_on == 0)
909 {
910 final_gain1=0;
911 final_gain2=0;
912 }
913
914 a1=final_gain1*(((t5*baseb_out[nn*i4 ]-t6*baseb_out[nn*i1 ])/3
915 +t4*baseb_out[nn*i2 ]-t7*baseb_out[nn*i3 ])/2);
916 a2=final_gain1*(((t5*baseb_out[nn*i4+1]-t6*baseb_out[nn*i1+1])/3
917 +t4*baseb_out[nn*i2+1]-t7*baseb_out[nn*i3+1])/2);
918 if(enable_resamp_iir5)
919 {
920 xva1[0]=xva1[1];
921 xva1[1]=xva1[2];
922 xva1[2]=xva1[3];
923 xva1[3]=xva1[4];
924 xva1[4]=xva1[5];
925 xva1[5]=a1/iir_a.gain;
926 yva1[0]=yva1[1];
927 yva1[1]=yva1[2];
928 yva1[2]=yva1[3];
929 yva1[3]=yva1[4];
930 yva1[4]=yva1[5];
931 yva1[5]=xva1[0]+xva1[5]+5*(xva1[1]+xva1[4])+10*(xva1[2]+xva1[3])+
932 iir_a.c0*yva1[0]+iir_a.c1*yva1[1]+iir_a.c2*yva1[2]+
933 iir_a.c3 * yva1[3]+iir_a.c4*yva1[4];
934 a1=yva1[5];
935 xva2[0]=xva2[1];
936 xva2[1]=xva2[2];
937 xva2[2]=xva2[3];
938 xva2[3]=xva2[4];
939 xva2[4]=xva2[5];
940 xva2[5]=a2/iir_a.gain;
941 yva2[0]=yva2[1];
942 yva2[1]=yva2[2];
943 yva2[2]=yva2[3];
944 yva2[3]=yva2[4];
945 yva2[4]=yva2[5];
946 yva2[5]=xva2[0]+xva2[5]+5*(xva2[1] + xva2[4])+10*(xva2[2]+xva2[3])+
947 iir_a.c0*yva2[0]+iir_a.c1*yva2[1]+iir_a.c2*yva2[2]+
948 iir_a.c3*yva2[3]+iir_a.c4*yva2[4];
949 a2=yva2[5];
950 }
951 old_out1=out1;
952 old_out2=out2;
953 if(baseb_channels == 1)
954 {
955 if( (ui.network_flag&NET_RXOUT_BASEB) != 0)
956 {
957 ntbuf=(short int*)&baseb_netsend_buffer[basebnet_pa];
958 if(rx_daout_bytes == 1)
959 {
960 ntbuf[0]=floor(256*a2);
961 ntbuf[1]=floor(256*a1);
962 }
963 else
964 {
965 ntbuf[0]=floor(a2);
966 ntbuf[1]=floor(a1);
967 }
968 basebnet_pa=(basebnet_pa+4)&basebnet_mask;
969 }
970 if(rx_mode == MODE_FM)
971 {
972 out1=a1;
973 out2=a2;
974 // ************************************
975 t1=(out1-old_out1)/daout_upsamp;
976 t2=old_out1;
977 t3=(out2-old_out2)/daout_upsamp;
978 t4=old_out2;
979 for(i=0; i<daout_upsamp; i++)
980 {
981 xv1[0]=xv1[1];
982 xv1[1]=xv1[2];
983 xv1[2]=xv1[3];
984 xv1[3]=t2/iir3_gain[daout_upsamp_n];
985 yv1[0]=yv1[1];
986 yv1[1]=yv1[2];
987 yv1[2]=yv1[3];
988 yv1[3]=xv1[0]+xv1[3]+3*(xv1[1]+xv1[2])+
989 iir3_c0[daout_upsamp_n]*yv1[0]+
990 iir3_c1[daout_upsamp_n]*yv1[1]+
991 iir3_c2[daout_upsamp_n]*yv1[2];
992 a1 = yv1[3];
993 xv2[0]=xv2[1];
994 xv2[1]=xv2[2];
995 xv2[2]=xv2[3];
996 xv2[3]=t4/iir3_gain[daout_upsamp_n];
997 yv2[0]=yv2[1];
998 yv2[1]=yv2[2];
999 yv2[2]=yv2[3];
1000 yv2[3]=xv2[0]+xv2[3]+3*(xv2[1]+xv2[2])+
1001 iir3_c0[daout_upsamp_n]*yv2[0]+
1002 iir3_c1[daout_upsamp_n]*yv2[1]+
1003 iir3_c2[daout_upsamp_n]*yv2[2];
1004 a2 = yv2[3];
1005 if(a1 < -bg_amplimit)a1=-bg_amplimit;
1006 if(a1 > bg_amplimit)a1=bg_amplimit;
1007 if(bg_maxamp < fabs(a1))bg_maxamp=fabs(a1);
1008 if(a2 < -bg_amplimit)a2=-bg_amplimit;
1009 if(a2 > bg_amplimit)a2=bg_amplimit;
1010 if(bg_maxamp < fabs(a2))bg_maxamp=fabs(a2);
1011 if(rx_daout_bytes == 1)
1012 {
1013 daout[daout_pa]=0x80+a1;
1014 if(rx_daout_channels == 2)daout[daout_pa+1]=0x80+a2;
1015 }
1016 else
1017 {
1018 intvar=(short int*)(&daout[daout_pa]);
1019 intvar[0]=a1;
1020 if(rx_daout_channels == 2)intvar[1]=a2;
1021 }
1022 daout_pa=(daout_pa+mm)&daout_bufmask;
1023 t2+=t1;
1024 t4+=t3;
1025 }
1026 }
1027 else
1028 {
1029 if(bg_expand != 2)
1030 {
1031 t1=sqrt(a1*a1+a2*a2);
1032 if(t1 > 0.5)
1033 {
1034 if(t1<bg_amplimit)t2=t1; else t2=bg_amplimit;
1035 if(bg_expand == 1)t2=bg_expand_a*(exp(bg_expand_b*t2)-1);
1036 t2/=t1;
1037 out1=t2*a1;
1038 out2=t2*a2;
1039 }
1040 else
1041 {
1042 out1=0;
1043 out2=0;
1044 }
1045 }
1046 else
1047 {
1048 out1=a1;
1049 out2=a2;
1050 }
1051 t1=(out1-old_out1)/daout_upsamp;
1052 t2=old_out1;
1053 t3=(out2-old_out2)/daout_upsamp;
1054 t4=old_out2;
1055 for(i=0; i<daout_upsamp; i++)
1056 {
1057 dt1=rx_daout_cos;
1058 rx_daout_cos=rx_daout_cos*rx_daout_phstep_cos+
1059 rx_daout_sin*rx_daout_phstep_sin;
1060 rx_daout_sin=rx_daout_sin*rx_daout_phstep_cos-
1061 dt1*rx_daout_phstep_sin;
1062 xv1[0]=xv1[1];
1063 xv1[1]=xv1[2];
1064 xv1[2]=xv1[3];
1065 xv1[3]=t2/iir3_gain[daout_upsamp_n];
1066 yv1[0]=yv1[1];
1067 yv1[1]=yv1[2];
1068 yv1[2]=yv1[3];
1069 yv1[3]=xv1[0]+xv1[3]+3*(xv1[1]+xv1[2])+
1070 iir3_c0[daout_upsamp_n]*yv1[0]+
1071 iir3_c1[daout_upsamp_n]*yv1[1]+
1072 iir3_c2[daout_upsamp_n]*yv1[2];
1073 a1 = yv1[3];
1074 xv2[0]=xv2[1];
1075 xv2[1]=xv2[2];
1076 xv2[2]=xv2[3];
1077 xv2[3]=t4/iir3_gain[daout_upsamp_n];
1078 yv2[0]=yv2[1];
1079 yv2[1]=yv2[2];
1080 yv2[2]=yv2[3];
1081 yv2[3]=xv2[0]+xv2[3]+3*(xv2[1]+xv2[2])+
1082 iir3_c0[daout_upsamp_n]*yv2[0]+
1083 iir3_c1[daout_upsamp_n]*yv2[1]+
1084 iir3_c2[daout_upsamp_n]*yv2[2];
1085 a2 = yv2[3];
1086 u1= a1*rx_daout_cos+a2*rx_daout_sin;
1087 if(u1 > bg_amplimit)u1=bg_amplimit;
1088 if(u1 < -bg_amplimit)u1=-bg_amplimit;
1089 if(bg_maxamp < fabs(u1))bg_maxamp=fabs(u1);
1090 if(da_ch2_sign == 0)
1091 {
1092 u2=-a1*rx_daout_sin+a2*rx_daout_cos;
1093 if(u2 > bg_amplimit)u2=bg_amplimit;
1094 if(u2 < -bg_amplimit)u2=-bg_amplimit;
1095 if(bg_maxamp < fabs(u2))bg_maxamp=fabs(u2);
1096 if(rx_daout_bytes == 1)
1097 {
1098 daout[daout_pa ]=0x80+u1;
1099 daout[daout_pa+1]=0x80+u2;
1100 }
1101 else
1102 {
1103 intvar=(short int*)(&daout[daout_pa]);
1104 intvar[0]=u1;
1105 intvar[1]=u2;
1106 }
1107 }
1108 else
1109 {
1110 if(rx_daout_bytes == 1)
1111 {
1112 daout[daout_pa]=0x80+u1;
1113 if(rx_daout_channels == 2)daout[daout_pa+1]=0x80+u1*da_ch2_sign;
1114 }
1115 else
1116 {
1117 intvar=(short int*)(&daout[daout_pa]);
1118 intvar[0]=u1;
1119 if(rx_daout_channels == 2)intvar[1]=u1*da_ch2_sign;
1120 }
1121 }
1122 daout_pa=(daout_pa+mm)&daout_bufmask;
1123 t2+=t1;
1124 t4+=t3;
1125 }
1126 }
1127 }
1128 else
1129 {
1130 old_out3=out3;
1131 old_out4=out4;
1132 b1=final_gain2*(((t5*baseb_out[nn*i4+2]-t6*baseb_out[nn*i1+2])/3
1133 +t4*baseb_out[nn*i2+2]-t7*baseb_out[nn*i3+2])/2);
1134 b2=final_gain2*(((t5*baseb_out[nn*i4+3]-t6*baseb_out[nn*i1+3])/3
1135 +t4*baseb_out[nn*i2+3]-t7*baseb_out[nn*i3+3])/2);
1136 if(enable_resamp_iir5)
1137 {
1138 xvb1[0]=xvb1[1];
1139 xvb1[1]=xvb1[2];
1140 xvb1[2]=xvb1[3];
1141 xvb1[3]=xvb1[4];
1142 xvb1[4]=xvb1[5];
1143 xvb1[5]=b1/iir_a.gain;
1144 yvb1[0]=yvb1[1];
1145 yvb1[1]=yvb1[2];
1146 yvb1[2]=yvb1[3];
1147 yvb1[3]=yvb1[4];
1148 yvb1[4]=yvb1[5];
1149 yvb1[5]=xvb1[0]+xvb1[5]+5*(xvb1[1]+xvb1[4])+10*(xvb1[2]+xvb1[3])+
1150 iir_a.c0*yvb1[0]+iir_a.c1*yvb1[1]+iir_a.c2*yvb1[2]+
1151 iir_a.c3 * yvb1[3]+iir_a.c4*yvb1[4];
1152 b1=yvb1[5];
1153 xvb2[0]=xvb2[1];
1154 xvb2[1]=xvb2[2];
1155 xvb2[2]=xvb2[3];
1156 xvb2[3]=xvb2[4];
1157 xvb2[4]=xvb2[5];
1158 xvb2[5]=b2/iir_a.gain;
1159 yvb2[0]=yvb2[1];
1160 yvb2[1]=yvb2[2];
1161 yvb2[2]=yvb2[3];
1162 yvb2[3]=yvb2[4];
1163 yvb2[4]=yvb2[5];
1164 yvb2[5]=xvb2[0]+xvb2[5]+5*(xvb2[1] + xvb2[4])+10*(xvb2[2]+xvb2[3])+
1165 iir_a.c0*yvb2[0]+iir_a.c1*yvb2[1]+iir_a.c2*yvb2[2]+
1166 iir_a.c3*yvb2[3]+iir_a.c4*yvb2[4];
1167 b2=yvb2[5];
1168 }
1169 if( (ui.network_flag&NET_RXOUT_BASEB) != 0)
1170 {
1171 ntbuf=(short int*)&baseb_netsend_buffer[basebnet_pa];
1172 if(rx_daout_bytes == 1)
1173 {
1174 ntbuf[0]=floor(256*a2);
1175 ntbuf[1]=floor(256*a1);
1176 ntbuf[2]=floor(256*b2);
1177 ntbuf[3]=floor(256*b1);
1178 }
1179 else
1180 {
1181 ntbuf[0]=floor(a2);
1182 ntbuf[1]=floor(a1);
1183 ntbuf[2]=floor(b2);
1184 ntbuf[3]=floor(b1);
1185 }
1186 basebnet_pa=(basebnet_pa+8)&basebnet_mask;
1187 }
1188 if( (bg_expand != 2 && bg.agc_flag != 2 ) || bg_twopol != 0)
1189 {
1190 t1=a1*a1+a2*a2;
1191 t2=b1*b1+b2*b2;
1192 if(t1 < t2)t1=t2;
1193 t1=sqrt(t1);
1194 if(t1 > 0.5)
1195 {
1196 if(t1<bg_amplimit)t2=t1; else t2=bg_amplimit;
1197 if(bg_expand == 1)t2=bg_expand_a*(exp(bg_expand_b*t2)-1);
1198 if(bg_maxamp < t2)bg_maxamp=t2;
1199 t2/=t1;
1200 out1=t2*a1;
1201 out2=t2*a2;
1202 out3=t2*b1;
1203 out4=t2*b2;
1204 }
1205 else
1206 {
1207 out1=0;
1208 out2=0;
1209 out3=0;
1210 out4=0;
1211 }
1212 }
1213 else
1214 {
1215 out1=a1;
1216 out2=a2;
1217 out3=b1;
1218 out4=b2;
1219 }
1220 // ************************************
1221 t1=(out1-old_out1)/daout_upsamp;
1222 t2=old_out1;
1223 t3=(out2-old_out2)/daout_upsamp;
1224 t4=old_out2;
1225 r1=(out3-old_out3)/daout_upsamp;
1226 r2=old_out3;
1227 r3=(out4-old_out4)/daout_upsamp;
1228 r4=old_out4;
1229 for(i=0; i<daout_upsamp; i++)
1230 {
1231 dt1=rx_daout_cos;
1232 rx_daout_cos=rx_daout_cos*rx_daout_phstep_cos+
1233 rx_daout_sin*rx_daout_phstep_sin;
1234 rx_daout_sin=rx_daout_sin*rx_daout_phstep_cos-
1235 dt1*rx_daout_phstep_sin;
1236 xv1[0]=xv1[1];
1237 xv1[1]=xv1[2];
1238 xv1[2]=xv1[3];
1239 xv1[3]=t2/iir3_gain[daout_upsamp_n];
1240 yv1[0]=yv1[1];
1241 yv1[1]=yv1[2];
1242 yv1[2]=yv1[3];
1243 yv1[3]=xv1[0]+xv1[3]+3*(xv1[1]+xv1[2])+
1244 iir3_c0[daout_upsamp_n]*yv1[0]+
1245 iir3_c1[daout_upsamp_n]*yv1[1]+
1246 iir3_c2[daout_upsamp_n]*yv1[2];
1247 a1 = yv1[3];
1248 xv2[0]=xv2[1];
1249 xv2[1]=xv2[2];
1250 xv2[2]=xv2[3];
1251 xv2[3]=t4/iir3_gain[daout_upsamp_n];
1252 yv2[0]=yv2[1];
1253 yv2[1]=yv2[2];
1254 yv2[2]=yv2[3];
1255 yv2[3]=xv2[0]+xv2[3]+3*(xv2[1]+xv2[2])+
1256 iir3_c0[daout_upsamp_n]*yv2[0]+
1257 iir3_c1[daout_upsamp_n]*yv2[1]+
1258 iir3_c2[daout_upsamp_n]*yv2[2];
1259 a2 = yv2[3];
1260 xv3[0]=xv3[1];
1261 xv3[1]=xv3[2];
1262 xv3[2]=xv3[3];
1263 xv3[3]=r2/iir3_gain[daout_upsamp_n];
1264 yv3[0]=yv3[1];
1265 yv3[1]=yv3[2];
1266 yv3[2]=yv3[3];
1267 yv3[3]=xv3[0]+xv3[3]+3*(xv3[1]+xv3[2])+
1268 iir3_c0[daout_upsamp_n]*yv3[0]+
1269 iir3_c1[daout_upsamp_n]*yv3[1]+
1270 iir3_c2[daout_upsamp_n]*yv3[2];
1271 b1 = yv3[3];
1272 xv4[0]=xv4[1];
1273 xv4[1]=xv4[2];
1274 xv4[2]=xv4[3];
1275 xv4[3]=r4/iir3_gain[daout_upsamp_n];
1276 yv4[0]=yv4[1];
1277 yv4[1]=yv4[2];
1278 yv4[2]=yv4[3];
1279 yv4[3]=xv4[0]+xv4[3]+3*(xv4[1]+xv4[2])+
1280 iir3_c0[daout_upsamp_n]*yv4[0]+
1281 iir3_c1[daout_upsamp_n]*yv4[1]+
1282 iir3_c2[daout_upsamp_n]*yv4[2];
1283 b2 = yv4[3];
1284 u1= a1*rx_daout_cos+a2*rx_daout_sin;
1285 if(u1 > bg_amplimit)u1=bg_amplimit;
1286 if(u1 < -bg_amplimit)u1=-bg_amplimit;
1287 // if(bg_maxamp < fabs(u1))bg_maxamp=fabs(u1);
1288 u2= b1*rx_daout_cos+b2*rx_daout_sin;
1289 if(u2 > bg_amplimit)u2=bg_amplimit;
1290 if(u2 < -bg_amplimit)u2=-bg_amplimit;
1291 // if(bg_maxamp < fabs(u2))bg_maxamp=fabs(u2);
1292 if(rx_daout_bytes == 1)
1293 {
1294 daout[daout_pa]=0x80+u1;
1295 if(rx_daout_channels == 2)daout[daout_pa+1]=0x80+u2;
1296 }
1297 else
1298 {
1299 intvar=(short int*)(&daout[daout_pa]);
1300 intvar[0]=u1;
1301 if(rx_daout_channels == 2)intvar[1]=u2;
1302 }
1303 if(rx_daout_channels==1)lirerr(213567);
1304 daout_pa=(daout_pa+mm)&daout_bufmask;
1305 t2+=t1;
1306 t4+=t3;
1307 r2+=r1;
1308 r4+=r3;
1309 }
1310 }
1311 baseb_r1=baseb_r2;
1312
1313 if(daout_pa > daout_bufmask)lirerr(994578);
1314 if(daout_pa == 0)
1315 {
1316 baseb_fx+=baseb_r2;
1317 baseb_r1=0;
1318 da_resample_ratio=new_da_resample_ratio;
1319 if(baseb_fx>baseband_size)baseb_fx-=baseband_size;
1320 if(use_bfo != 0)
1321 {
1322 t1=(2*PI_L*bg.bfo_freq)/genparm[DA_OUTPUT_SPEED];
1323 rx_daout_phstep_cos=cos(t1);
1324 rx_daout_phstep_sin=sin(t1);
1325 }
1326 }
1327 if(thread_command_flag[THREAD_RX_OUTPUT] != THRFLAG_ACTIVE)return;
1328 goto resamp;
1329 }
1330