2016-03-01 17:40:38 +00:00
/* Common transceiver functions
*
* ( C ) 2016 by Andreas Eversberg < jolly @ eversberg . eu >
* All Rights Reserved
*
* 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/>.
*/
2016-07-31 13:09:46 +00:00
# define CHAN sender->kanal
2016-03-01 17:40:38 +00:00
# include <stdio.h>
# include <stdint.h>
# include <stdlib.h>
# include <errno.h>
# include <string.h>
2017-11-18 07:06:06 +00:00
# include "../libsample/sample.h"
2017-11-18 07:58:57 +00:00
# include "../libdebug/debug.h"
2016-03-01 17:40:38 +00:00
# include "sender.h"
2017-11-13 19:00:52 +00:00
# include "../libtimer/timer.h"
2021-11-07 15:33:30 +00:00
# ifdef HAVE_SDR
# include "../libsdr/sdr_config.h"
# endif
2017-08-16 16:34:46 +00:00
/* debug time consumption of audio processing */
//#define DEBUG_TIME_CONSUMPTION
2016-03-01 17:40:38 +00:00
sender_t * sender_head = NULL ;
static sender_t * * sender_tailp = & sender_head ;
2016-02-16 17:56:55 +00:00
int cant_recover = 0 ;
2020-06-28 15:53:23 +00:00
int check_channel = 1 ;
2016-03-01 17:40:38 +00:00
/* Init transceiver instance and link to list of transceivers. */
2021-09-18 09:43:01 +00:00
int sender_create ( sender_t * sender , const char * kanal , double sendefrequenz , double empfangsfrequenz , const char * device , int use_sdr , int samplerate , double rx_gain , double tx_gain , int pre_emphasis , int de_emphasis , const char * write_rx_wave , const char * write_tx_wave , const char * read_rx_wave , const char * read_tx_wave , int loopback , enum paging_signal paging_signal )
2016-03-01 17:40:38 +00:00
{
2017-01-04 13:14:02 +00:00
sender_t * master , * slave ;
2016-03-01 17:40:38 +00:00
int rc = 0 ;
2016-07-31 13:09:46 +00:00
sender - > kanal = kanal ;
2017-01-04 13:14:02 +00:00
sender - > sendefrequenz = sendefrequenz ;
2017-09-25 16:46:50 +00:00
sender - > empfangsfrequenz = ( loopback ) ? sendefrequenz : empfangsfrequenz ;
2021-09-18 09:43:01 +00:00
strncpy ( sender - > device , device , sizeof ( sender - > device ) - 1 ) ;
2016-07-31 13:09:46 +00:00
sender - > samplerate = samplerate ;
sender - > rx_gain = rx_gain ;
2020-06-14 18:59:41 +00:00
sender - > tx_gain = tx_gain ;
2016-07-31 13:09:46 +00:00
sender - > pre_emphasis = pre_emphasis ;
sender - > de_emphasis = de_emphasis ;
sender - > loopback = loopback ;
2017-01-07 09:33:13 +00:00
sender - > paging_signal = paging_signal ;
2017-01-13 06:31:15 +00:00
sender - > write_rx_wave = write_rx_wave ;
sender - > write_tx_wave = write_tx_wave ;
sender - > read_rx_wave = read_rx_wave ;
2017-07-09 17:17:37 +00:00
sender - > read_tx_wave = read_tx_wave ;
2016-07-31 13:09:46 +00:00
2017-01-29 07:16:10 +00:00
/* no gain with SDR */
2020-06-14 18:59:41 +00:00
if ( use_sdr ) {
2017-01-29 07:16:10 +00:00
sender - > rx_gain = 1.0 ;
2020-06-14 18:59:41 +00:00
sender - > tx_gain = 1.0 ;
}
2017-01-29 07:16:10 +00:00
2019-05-30 16:19:06 +00:00
if ( samplerate < 8000 ) {
PDEBUG ( DSENDER , DEBUG_NOTICE , " Given sample rate is below 8 KHz. Please use higher sample rate! \n " ) ;
rc = - EINVAL ;
goto error ;
}
2016-07-31 13:09:46 +00:00
PDEBUG_CHAN ( DSENDER , DEBUG_DEBUG , " Creating 'Sender' instance \n " ) ;
2016-03-01 17:40:38 +00:00
2016-04-25 18:20:54 +00:00
/* if we find a channel that uses the same device as we do,
* we will link us as slave to this master channel . then we
* receive and send audio via second channel of the device
* of the master channel .
*/
for ( master = sender_head ; master ; master = master - > next ) {
2019-07-20 16:11:17 +00:00
if ( ! strcmp ( master - > kanal , kanal ) ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Channel %s may not be defined for multiple transceivers! \n " , kanal ) ;
2016-04-25 18:20:54 +00:00
rc = - EIO ;
goto error ;
}
2020-06-28 15:53:23 +00:00
if ( check_channel & & abs ( atoi ( master - > kanal ) - atoi ( kanal ) ) = = 1 ) {
2017-05-24 12:01:25 +00:00
PDEBUG ( DSENDER , DEBUG_NOTICE , " ------------------------------------------------------------------------ \n " ) ;
2019-07-20 16:11:17 +00:00
PDEBUG ( DSENDER , DEBUG_NOTICE , " NOTE: Channel %s is next to channel %s. This will cause interferences. \n " , kanal , master - > kanal ) ;
2017-05-24 12:01:25 +00:00
PDEBUG ( DSENDER , DEBUG_NOTICE , " Please use at least one channel distance to avoid that. \n " ) ;
PDEBUG ( DSENDER , DEBUG_NOTICE , " ------------------------------------------------------------------------ \n " ) ;
}
2021-09-18 09:43:01 +00:00
if ( ! strcmp ( master - > device , device ) )
2016-04-25 18:20:54 +00:00
break ;
}
if ( master ) {
2017-05-14 10:27:56 +00:00
if ( master - > paging_signal ! = PAGING_SIGNAL_NONE & & ! use_sdr ) {
2019-07-20 16:11:17 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " Cannot share audio device with channel %s, because its second audio channel is used for paging signal! Use different audio device. \n " , master - > kanal ) ;
2016-04-25 18:20:54 +00:00
rc = - EBUSY ;
goto error ;
}
2017-05-14 10:27:56 +00:00
if ( paging_signal ! = PAGING_SIGNAL_NONE & & ! use_sdr ) {
2019-07-20 16:11:17 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " Cannot share audio device with channel %s, because we need a second audio channel for paging signal! Use different audio device. \n " , master - > kanal ) ;
2016-04-25 18:20:54 +00:00
rc = - EBUSY ;
goto error ;
}
2017-01-04 13:14:02 +00:00
/* link us to a master */
2016-04-25 18:20:54 +00:00
sender - > master = master ;
2017-01-04 13:14:02 +00:00
/* link master (or last slave) to us */
for ( slave = master ; ; slave = slave - > slave ) {
if ( ! slave - > slave )
break ;
}
slave - > slave = sender ;
2016-04-25 18:20:54 +00:00
} else {
2017-01-04 13:14:02 +00:00
/* link audio device */
2017-01-04 13:21:49 +00:00
# ifdef HAVE_SDR
2017-05-14 10:27:56 +00:00
if ( use_sdr ) {
2017-01-04 13:21:49 +00:00
sender - > audio_open = sdr_open ;
2017-02-25 06:09:53 +00:00
sender - > audio_start = sdr_start ;
2017-01-04 13:21:49 +00:00
sender - > audio_close = sdr_close ;
sender - > audio_read = sdr_read ;
sender - > audio_write = sdr_write ;
2017-03-04 05:35:38 +00:00
sender - > audio_get_tosend = sdr_get_tosend ;
2017-01-04 13:21:49 +00:00
} else
# endif
2017-01-04 13:14:02 +00:00
{
2018-01-21 09:43:45 +00:00
# ifdef HAVE_ALSA
2017-01-04 13:14:02 +00:00
sender - > audio_open = sound_open ;
2017-02-25 06:09:53 +00:00
sender - > audio_start = sound_start ;
2017-01-04 13:14:02 +00:00
sender - > audio_close = sound_close ;
sender - > audio_read = sound_read ;
sender - > audio_write = sound_write ;
2017-03-04 05:35:38 +00:00
sender - > audio_get_tosend = sound_get_tosend ;
2018-01-21 09:43:45 +00:00
# else
PDEBUG ( DSENDER , DEBUG_ERROR , " No sound card support compiled in! \n " ) ;
rc = - ENOTSUP ;
goto error ;
# endif
2016-04-25 18:20:54 +00:00
}
}
2017-05-13 14:04:00 +00:00
rc = init_samplerate ( & sender - > srstate , 8000.0 , ( double ) samplerate , 3300.0 ) ;
2016-03-01 17:40:38 +00:00
if ( rc < 0 ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to init sample rate conversion! \n " ) ;
goto error ;
}
2017-01-04 13:14:02 +00:00
rc = jitter_create ( & sender - > dejitter , samplerate / 5 ) ;
2016-03-01 17:40:38 +00:00
if ( rc < 0 ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to create and init audio buffer! \n " ) ;
goto error ;
}
2018-01-20 14:49:19 +00:00
rc = init_emphasis ( & sender - > estate , samplerate , CUT_OFF_EMPHASIS_DEFAULT , CUT_OFF_HIGHPASS_DEFAULT , CUT_OFF_LOWPASS_DEFAULT ) ;
2016-04-23 16:50:11 +00:00
if ( rc < 0 )
goto error ;
2016-03-01 17:40:38 +00:00
* sender_tailp = sender ;
sender_tailp = & sender - > next ;
2018-01-21 08:30:00 +00:00
display_wave_init ( & sender - > dispwav , samplerate , sender - > kanal ) ;
display_measurements_init ( & sender - > dispmeas , samplerate , sender - > kanal ) ;
2016-06-17 05:28:45 +00:00
2016-03-01 17:40:38 +00:00
return 0 ;
error :
sender_destroy ( sender ) ;
return rc ;
}
2021-09-18 09:43:01 +00:00
int sender_open_audio ( int buffer_size , double interval )
2017-01-04 13:14:02 +00:00
{
sender_t * master , * inst ;
int channels ;
int i ;
2017-01-13 06:31:15 +00:00
int rc ;
2017-01-04 13:14:02 +00:00
for ( master = sender_head ; master ; master = master - > next ) {
/* skip audio slaves */
if ( master - > master )
continue ;
/* get list of frequencies */
channels = 0 ;
for ( inst = master ; inst ; inst = inst - > slave ) {
channels + + ;
}
2017-09-25 16:46:50 +00:00
double tx_f [ channels ] , rx_f [ channels ] , paging_frequency = 0.0 ;
2019-12-05 16:24:30 +00:00
int am [ channels ] ;
2017-01-04 13:14:02 +00:00
for ( i = 0 , inst = master ; inst ; i + + , inst = inst - > slave ) {
tx_f [ i ] = inst - > sendefrequenz ;
2017-09-25 16:46:50 +00:00
rx_f [ i ] = inst - > empfangsfrequenz ;
2019-12-05 16:24:30 +00:00
am [ i ] = inst - > am ;
2017-01-07 09:33:13 +00:00
if ( inst - > ruffrequenz )
paging_frequency = inst - > ruffrequenz ;
2017-01-04 13:14:02 +00:00
}
2017-01-13 06:31:15 +00:00
if ( master - > write_rx_wave ) {
2019-12-05 16:24:30 +00:00
rc = wave_create_record ( & master - > wave_rx_rec , master - > write_rx_wave , master - > samplerate , channels , ( master - > max_deviation ) ? : 1.0 ) ;
2017-01-13 06:31:15 +00:00
if ( rc < 0 ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to create WAVE recoding instance! \n " ) ;
return rc ;
}
}
if ( master - > write_tx_wave ) {
2019-12-05 16:24:30 +00:00
rc = wave_create_record ( & master - > wave_tx_rec , master - > write_tx_wave , master - > samplerate , channels , ( master - > max_deviation ) ? : 1.0 ) ;
2017-01-13 06:31:15 +00:00
if ( rc < 0 ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to create WAVE recoding instance! \n " ) ;
return rc ;
}
}
if ( master - > read_rx_wave ) {
2019-12-05 16:24:30 +00:00
rc = wave_create_playback ( & master - > wave_rx_play , master - > read_rx_wave , & master - > samplerate , & channels , ( master - > max_deviation ) ? : 1.0 ) ;
2017-01-13 06:31:15 +00:00
if ( rc < 0 ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to create WAVE playback instance! \n " ) ;
return rc ;
}
}
2017-07-09 17:17:37 +00:00
if ( master - > read_tx_wave ) {
2019-12-05 16:24:30 +00:00
rc = wave_create_playback ( & master - > wave_tx_play , master - > read_tx_wave , & master - > samplerate , & channels , ( master - > max_deviation ) ? : 1.0 ) ;
2017-07-09 17:17:37 +00:00
if ( rc < 0 ) {
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to create WAVE playback instance! \n " ) ;
return rc ;
}
}
2017-01-13 06:31:15 +00:00
2017-01-04 13:14:02 +00:00
/* open device */
2021-09-18 09:43:01 +00:00
master - > audio = master - > audio_open ( master - > device , tx_f , rx_f , am , channels , paging_frequency , master - > samplerate , buffer_size , interval , ( master - > max_deviation ) ? : 1.0 , master - > max_modulation , master - > modulation_index ) ;
2017-01-04 13:14:02 +00:00
if ( ! master - > audio ) {
2019-10-27 06:03:23 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " No device for transceiver! \n " ) ;
2017-01-04 13:14:02 +00:00
return - EIO ;
}
}
2018-01-21 08:30:00 +00:00
# ifdef HAVE_SDR
/* in case of initialized spectrum display (SDR), we add all channels.
* if spectrum display was not initialized ( sound card ) , function call is ignored */
for ( inst = sender_head ; inst ; inst = inst - > next )
2021-11-07 15:33:30 +00:00
display_spectrum_add_mark ( inst - > kanal , ( sdr_config - > swap_links ) ? inst - > sendefrequenz : inst - > empfangsfrequenz ) ;
2018-01-21 08:30:00 +00:00
# endif
2017-01-04 13:14:02 +00:00
return 0 ;
}
2017-02-25 06:09:53 +00:00
int sender_start_audio ( void )
{
sender_t * master ;
int rc = 0 ;
for ( master = sender_head ; master ; master = master - > next ) {
/* skip audio slaves */
if ( master - > master )
continue ;
rc = master - > audio_start ( master - > audio ) ;
if ( rc )
break ;
}
return rc ;
}
2016-03-01 17:40:38 +00:00
/* Destroy transceiver instance and unlink from list. */
void sender_destroy ( sender_t * sender )
{
2016-07-31 13:09:46 +00:00
PDEBUG_CHAN ( DSENDER , DEBUG_DEBUG , " Destroying 'Sender' instance \n " ) ;
2016-03-01 17:40:38 +00:00
sender_tailp = & sender_head ;
while ( * sender_tailp ) {
if ( sender = = * sender_tailp )
2016-04-25 18:20:54 +00:00
* sender_tailp = ( * sender_tailp ) - > next ;
else
sender_tailp = & ( ( * sender_tailp ) - > next ) ;
2016-03-01 17:40:38 +00:00
}
2017-01-04 13:14:02 +00:00
if ( sender - > audio ) {
sender - > audio_close ( sender - > audio ) ;
sender - > audio = NULL ;
2016-10-28 14:55:39 +00:00
}
2016-03-01 17:40:38 +00:00
2016-11-27 05:47:06 +00:00
wave_destroy_record ( & sender - > wave_rx_rec ) ;
wave_destroy_record ( & sender - > wave_tx_rec ) ;
wave_destroy_playback ( & sender - > wave_rx_play ) ;
2017-07-09 17:17:37 +00:00
wave_destroy_playback ( & sender - > wave_tx_play ) ;
2016-03-25 12:58:16 +00:00
2017-01-04 13:14:02 +00:00
jitter_destroy ( & sender - > dejitter ) ;
2016-03-01 17:40:38 +00:00
}
2019-12-05 07:33:08 +00:00
/* set frequency modulation and parameters */
void sender_set_fm ( sender_t * sender , double max_deviation , double max_modulation , double speech_deviation , double max_display )
2017-01-29 06:25:12 +00:00
{
sender - > max_deviation = max_deviation ;
sender - > max_modulation = max_modulation ;
2019-12-05 07:33:08 +00:00
sender - > speech_deviation = speech_deviation ;
2017-01-29 06:25:12 +00:00
sender - > max_display = max_display ;
2021-01-01 21:11:48 +00:00
PDEBUG_CHAN ( DSENDER , DEBUG_DEBUG , " Maximum deviation: %.1f kHz, Maximum modulation: %.1f kHz \n " , max_deviation / 1000.0 , max_modulation / 1000.0 ) ;
2019-12-05 07:33:08 +00:00
PDEBUG_CHAN ( DSENDER , DEBUG_DEBUG , " Deviation at speech level: %.1f kHz \n " , speech_deviation / 1000.0 ) ;
2017-01-29 06:25:12 +00:00
}
2019-12-05 16:24:30 +00:00
/* set amplitude modulation and parameters */
void sender_set_am ( sender_t * sender , double max_modulation , double speech_level , double max_display , double modulation_index )
{
sender - > am = 1 ;
sender - > max_deviation = 0 ;
sender - > max_modulation = max_modulation ;
sender - > speech_deviation = speech_level ;
sender - > max_display = max_display ;
sender - > modulation_index = modulation_index ;
PDEBUG_CHAN ( DSENDER , DEBUG_DEBUG , " Modulation degree: %.0f %%, Maximum modulation: %.1f kHz \n " , modulation_index / 100.0 , max_modulation / 1000.0 ) ;
}
2017-01-27 15:57:34 +00:00
static void gain_samples ( sample_t * samples , int length , double gain )
2016-05-06 05:00:27 +00:00
{
int i ;
2017-01-27 15:57:34 +00:00
for ( i = 0 ; i < length ; i + + )
* samples + + * = gain ;
2016-05-06 05:00:27 +00:00
}
2016-03-01 17:40:38 +00:00
/* Handle audio streaming of one transceiver. */
2021-09-18 09:43:01 +00:00
void process_sender_audio ( sender_t * sender , int * quit , int buffer_size )
2016-03-01 17:40:38 +00:00
{
2017-01-03 11:31:59 +00:00
sender_t * inst ;
2016-03-01 17:40:38 +00:00
int rc , count ;
2017-01-03 11:31:59 +00:00
int num_chan , i ;
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
static double t1 , t2 , t3 , t4 , t5 , d1 = 0 , d2 = 0 , d3 = 0 , d4 = 0 , s = 0 ;
# endif
2017-01-03 11:31:59 +00:00
/* count instances for audio channel */
for ( num_chan = 0 , inst = sender ; inst ; num_chan + + , inst = inst - > slave ) ;
2021-09-18 09:43:01 +00:00
sample_t buff [ num_chan ] [ buffer_size ] , * samples [ num_chan ] ;
uint8_t pbuff [ num_chan ] [ buffer_size ] , * power [ num_chan ] ;
2017-01-07 09:33:13 +00:00
enum paging_signal paging_signal [ num_chan ] ;
int on [ num_chan ] ;
2017-10-09 18:49:14 +00:00
double rf_level_db [ num_chan ] ;
2017-01-07 09:33:13 +00:00
for ( i = 0 ; i < num_chan ; i + + ) {
2017-01-03 11:31:59 +00:00
samples [ i ] = buff [ i ] ;
2017-08-19 10:27:05 +00:00
power [ i ] = pbuff [ i ] ;
2017-01-07 09:33:13 +00:00
}
2016-03-01 17:40:38 +00:00
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
t1 = get_time ( ) ;
# endif
2021-09-18 09:43:01 +00:00
count = sender - > audio_get_tosend ( sender - > audio , buffer_size ) ;
2016-03-01 17:40:38 +00:00
if ( count < 0 ) {
2020-07-26 11:13:01 +00:00
PDEBUG_CHAN ( DSENDER , DEBUG_ERROR , " Failed to get number of samples in buffer (rc = %d)! \n " , count ) ;
2016-02-16 17:56:55 +00:00
if ( count = = - EPIPE ) {
if ( cant_recover ) {
cant_recover :
PDEBUG ( DSENDER , DEBUG_ERROR , " Cannot recover due to measurements, quitting! \n " ) ;
* quit = 1 ;
return ;
}
2016-03-01 17:40:38 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " Trying to recover! \n " ) ;
2016-02-16 17:56:55 +00:00
}
2016-03-01 17:40:38 +00:00
return ;
}
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
t2 = get_time ( ) ;
# endif
2017-03-04 05:35:38 +00:00
if ( count > 0 ) {
2017-03-18 08:57:38 +00:00
/* limit to our buffer */
2021-09-18 09:43:01 +00:00
if ( count > buffer_size )
count = buffer_size ;
2017-01-03 11:31:59 +00:00
/* loop through all channels */
for ( i = 0 , inst = sender ; inst ; i + + , inst = inst - > slave ) {
/* load TX data from audio loop or from sender instance */
if ( inst - > loopback = = 3 )
2017-01-04 13:14:02 +00:00
jitter_load ( & inst - > dejitter , samples [ i ] , count ) ;
2016-04-25 18:20:54 +00:00
else
2017-08-19 10:27:05 +00:00
sender_send ( inst , samples [ i ] , power [ i ] , count ) ;
2017-01-03 11:31:59 +00:00
/* internal loopback: loop back TX audio to RX */
if ( inst - > loopback = = 1 ) {
2018-01-21 08:30:00 +00:00
display_wave ( & inst - > dispwav , samples [ i ] , count , inst - > max_display ) ;
2017-10-09 18:49:14 +00:00
sender_receive ( inst , samples [ i ] , count , 0.0 ) ;
2016-04-25 18:20:54 +00:00
}
2017-01-28 17:18:44 +00:00
/* do pre emphasis towards radio */
2017-01-03 11:31:59 +00:00
if ( inst - > pre_emphasis )
pre_emphasis ( & inst - > estate , samples [ i ] , count ) ;
2020-06-14 18:59:41 +00:00
/* tx gain */
if ( inst - > tx_gain ! = 1.0 )
gain_samples ( samples [ i ] , count , inst - > tx_gain ) ;
2019-12-05 07:33:08 +00:00
/* normal level to frequency deviation of speech level */
gain_samples ( samples [ i ] , count , inst - > speech_deviation ) ;
2017-01-07 09:33:13 +00:00
/* set paging signal */
2017-01-14 07:03:42 +00:00
paging_signal [ i ] = inst - > paging_signal ;
on [ i ] = inst - > paging_on ;
2016-03-01 17:40:38 +00:00
}
2017-01-03 11:31:59 +00:00
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
t2 = get_time ( ) ;
# endif
2017-01-13 06:31:15 +00:00
if ( sender - > wave_tx_rec . fp )
wave_write ( & sender - > wave_tx_rec , samples , count ) ;
2017-07-09 17:17:37 +00:00
if ( sender - > wave_tx_play . fp )
wave_read ( & sender - > wave_tx_play , samples , count ) ;
2017-01-13 06:31:15 +00:00
2017-08-19 10:27:05 +00:00
rc = sender - > audio_write ( sender - > audio , samples , power , count , paging_signal , on , num_chan ) ;
2016-03-01 17:40:38 +00:00
if ( rc < 0 ) {
2017-01-04 13:14:02 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to write TX data to audio device (rc = %d) \n " , rc ) ;
2016-02-16 17:56:55 +00:00
if ( rc = = - EPIPE ) {
if ( cant_recover )
goto cant_recover ;
2016-03-01 17:40:38 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " Trying to recover! \n " ) ;
2016-02-16 17:56:55 +00:00
}
2016-03-01 17:40:38 +00:00
return ;
}
}
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
t3 = get_time ( ) ;
# endif
2016-03-01 17:40:38 +00:00
2021-09-18 09:43:01 +00:00
count = sender - > audio_read ( sender - > audio , samples , buffer_size , num_chan , rf_level_db ) ;
2016-03-01 17:40:38 +00:00
if ( count < 0 ) {
2017-01-04 13:14:02 +00:00
/* special case when audio_read wants us to quit */
if ( count = = - EPERM ) {
* quit = 1 ;
return ;
}
PDEBUG ( DSENDER , DEBUG_ERROR , " Failed to read from audio device (rc = %d)! \n " , count ) ;
2016-02-16 17:56:55 +00:00
if ( count = = - EPIPE ) {
if ( cant_recover )
goto cant_recover ;
2016-03-01 17:40:38 +00:00
PDEBUG ( DSENDER , DEBUG_ERROR , " Trying to recover! \n " ) ;
2016-02-16 17:56:55 +00:00
}
2016-03-01 17:40:38 +00:00
return ;
}
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
t4 = get_time ( ) ;
# endif
2016-03-01 17:40:38 +00:00
if ( count ) {
2017-01-13 06:31:15 +00:00
if ( sender - > wave_rx_rec . fp )
wave_write ( & sender - > wave_rx_rec , samples , count ) ;
if ( sender - > wave_rx_play . fp )
wave_read ( & sender - > wave_rx_play , samples , count ) ;
2017-01-03 11:31:59 +00:00
/* loop through all channels */
for ( i = 0 , inst = sender ; inst ; i + + , inst = inst - > slave ) {
2019-12-05 07:33:08 +00:00
/* frequency deviation of speech level to normal level */
gain_samples ( samples [ i ] , count , 1.0 / inst - > speech_deviation ) ;
2017-01-03 11:31:59 +00:00
/* rx gain */
if ( inst - > rx_gain ! = 1.0 )
gain_samples ( samples [ i ] , count , inst - > rx_gain ) ;
2017-01-28 17:18:44 +00:00
/* do filter and de-emphasis from radio receive audio, process echo test */
if ( inst - > de_emphasis ) {
dc_filter ( & inst - > estate , samples [ i ] , count ) ;
2017-01-03 11:31:59 +00:00
de_emphasis ( & inst - > estate , samples [ i ] , count ) ;
2017-01-28 17:18:44 +00:00
}
2017-01-03 11:31:59 +00:00
if ( inst - > loopback ! = 1 ) {
2018-01-21 08:30:00 +00:00
display_wave ( & inst - > dispwav , samples [ i ] , count , inst - > max_display ) ;
2017-10-09 18:49:14 +00:00
sender_receive ( inst , samples [ i ] , count , rf_level_db [ i ] ) ;
2016-04-25 18:20:54 +00:00
}
2017-01-03 11:31:59 +00:00
if ( inst - > loopback = = 3 )
2017-01-04 13:14:02 +00:00
jitter_save ( & inst - > dejitter , samples [ i ] , count ) ;
2016-03-01 17:40:38 +00:00
}
}
2017-08-16 16:34:46 +00:00
# ifdef DEBUG_TIME_CONSUMPTION
t5 = get_time ( ) ;
d1 + = ( t2 - t1 ) ;
d2 + = ( t3 - t2 ) ;
d3 + = ( t4 - t3 ) ;
d4 + = ( t5 - t4 ) ;
if ( get_time ( ) - s > = 1.0 ) {
printf ( " duration: %.3f (process TX), %.3f (send TX), %.3f (receive RX), %.3f (process RX) \n " , d1 , d2 , d3 , d4 ) ;
s = get_time ( ) ;
d1 = d2 = d3 = d4 = 0 ;
}
# endif
2016-03-01 17:40:38 +00:00
}
2017-01-07 09:33:13 +00:00
void sender_paging ( sender_t * sender , int on )
2016-10-03 12:46:25 +00:00
{
2017-01-07 09:33:13 +00:00
sender - > paging_on = on ;
2016-10-03 12:46:25 +00:00
}
2017-09-25 16:46:50 +00:00
sender_t * get_sender_by_empfangsfrequenz ( double freq )
{
sender_t * sender ;
for ( sender = sender_head ; sender ; sender = sender - > next ) {
if ( sender - > empfangsfrequenz = = freq )
return sender ;
}
return NULL ;
}