0
1
mirror of https://github.com/radio95-rnt/fm95.git synced 2026-02-26 19:23:51 +01:00

changes here and there

This commit is contained in:
2025-06-21 14:05:56 +02:00
parent 9bfff3fef2
commit aa6f87c0da
6 changed files with 46 additions and 154 deletions

View File

@@ -1,5 +1,5 @@
{ {
"port": 13452, "port": 13452,
"time": 1746171059613, "time": 1750505649575,
"version": "0.0.3" "version": "0.0.3"
} }

View File

@@ -5,11 +5,7 @@ void init_preemphasis(ResistorCapacitor *filter, float tau, float sample_rate, f
filter->alpha = tau / (tau + dt); filter->alpha = tau / (tau + dt);
float omega = M_2PI * ref_freq / sample_rate; float omega = M_2PI * ref_freq / sample_rate;
float cos_omega = cosf(omega); filter->gain = 1.0f / sqrtf(1.0f + filter->alpha * filter->alpha - 2.0f * filter->alpha * cosf(omega));
float numerator = sqrtf(1.0f + filter->alpha * filter->alpha - 2.0f * filter->alpha * cos_omega);
filter->gain = 1.0f / numerator;
filter->prev_sample = 0.0f; filter->prev_sample = 0.0f;
} }

View File

@@ -15,7 +15,7 @@ void initAGC(AGC* agc, int sampleRate, float targetLevel, float minGain, float m
agc->currentLevel = 0.0f; agc->currentLevel = 0.0f;
agc->rms_buffer = 0.0f; agc->rms_buffer = 0.0f;
agc->rmsAlpha = expf(-1.0f / (sampleRate * 0.04f)); agc->rmsAlpha = expf(-1.0f / (sampleRate * 0.02f));
} }
float process_agc(AGC* agc, float sidechain) { float process_agc(AGC* agc, float sidechain) {

View File

@@ -44,10 +44,6 @@ static void stop(int signum) {
to_run = 0; to_run = 0;
} }
void show_version() {
printf("chimer95 (GTS time signal encoder by radio95) version 1.1\n");
}
void show_help(char *name) { void show_help(char *name) {
printf( printf(
"Usage:\t%s\n" "Usage:\t%s\n"
@@ -66,50 +62,8 @@ void show_help(char *name) {
); );
} }
void generate_signal(float *output, int buffer_size, Oscillator *osc, float volume, int *elapsed_samples, int total_samples, int pip_samples, int pause_samples, int beep_samples, int num_pips) { void generate_signal(float *output, Oscillator *osc, float volume, int *elapsed_samples, int total_samples, int pip_samples, int pause_samples, int beep_samples, int num_pips) {
#if USE_NEON for (int i = 0; i < BUFFER_SIZE; i++) {
float32x4_t v_volume = vdupq_n_f32(volume);
for (int i = 0; i < buffer_size; i += 4) {
if (*elapsed_samples >= total_samples) {
vst1q_f32(&output[i], vdupq_n_f32(0.0f));
playing_sequence = 0;
} else {
int cycle_position = *elapsed_samples;
int pip_cycle = pip_samples + pause_samples;
float32x4_t v_samples;
if (cycle_position < num_pips * pip_cycle) {
int within_cycle = cycle_position % pip_cycle;
if (within_cycle < pip_samples) {
float samples[4] = {
get_oscillator_sin_sample(osc),
get_oscillator_sin_sample(osc),
get_oscillator_sin_sample(osc),
get_oscillator_sin_sample(osc),
};
v_samples = vmulq_f32(vld1q_f32(samples), v_volume);
} else {
v_samples = vdupq_n_f32(0.0f);
}
} else if (cycle_position < num_pips * pip_cycle + beep_samples) {
float samples[4] = {
get_oscillator_sin_sample(osc),
get_oscillator_sin_sample(osc),
get_oscillator_sin_sample(osc),
get_oscillator_sin_sample(osc),
};
v_samples = vmulq_f32(vld1q_f32(samples), v_volume);
} else {
v_samples = vdupq_n_f32(0.0f);
}
vst1q_f32(&output[i], v_samples);
(*elapsed_samples) += 4;
}
}
#else
for (int i = 0; i < buffer_size; i++) {
if (*elapsed_samples >= total_samples) { if (*elapsed_samples >= total_samples) {
output[i] = 0; output[i] = 0;
playing_sequence = 0; playing_sequence = 0;
@@ -118,22 +72,14 @@ void generate_signal(float *output, int buffer_size, Oscillator *osc, float volu
int pip_cycle = pip_samples + pause_samples; int pip_cycle = pip_samples + pause_samples;
if (cycle_position < num_pips * pip_cycle) { if (cycle_position < num_pips * pip_cycle) {
int within_cycle = cycle_position % pip_cycle; if ((cycle_position % pip_cycle) < pip_samples) output[i] = get_oscillator_sin_sample(osc) * volume;
if (within_cycle < pip_samples) { else output[i] = 0;
output[i] = get_oscillator_sin_sample(osc) * volume; } else if (cycle_position < num_pips * pip_cycle + beep_samples) output[i] = get_oscillator_sin_sample(osc) * volume;
} else { else output[i] = 0;
output[i] = 0;
}
} else if (cycle_position < num_pips * pip_cycle + beep_samples) {
output[i] = get_oscillator_sin_sample(osc) * volume;
} else {
output[i] = 0;
}
(*elapsed_samples)++; (*elapsed_samples)++;
} }
} }
#endif
} }
int check_time_for_sequence(int test_mode, int offset) { int check_time_for_sequence(int test_mode, int offset) {
@@ -152,19 +98,11 @@ int check_time_for_sequence(int test_mode, int offset) {
return SEQ_NONE; return SEQ_NONE;
} }
if (minute == 29 && second == (56 + offset)) { last_sequence_time = now;
last_sequence_time = now; if (minute == 29 && second == (56 + offset)) return SEQ_29_56;
return SEQ_29_56; if (minute == 59 && second == (55 + offset)) return SEQ_59_55;
}
if (minute == 59 && second == (55 + offset)) {
last_sequence_time = now;
return SEQ_59_55;
}
if (test_mode && second == (55 + offset) && minute != last_minute) { if (test_mode && second == (55 + offset) && minute != last_minute) {
last_minute = minute; last_minute = minute;
last_sequence_time = now;
return SEQ_TEST_HOUR; return SEQ_TEST_HOUR;
} }
@@ -172,7 +110,7 @@ int check_time_for_sequence(int test_mode, int offset) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
show_version(); printf("chimer95 (GTS time signal encoder by radio95) version 1.1\n");
PulseOutputDevice output_device; PulseOutputDevice output_device;
@@ -266,9 +204,7 @@ int main(int argc, char **argv) {
printf("Ready to play time signals.\n"); printf("Ready to play time signals.\n");
printf("Will trigger at XX:29:%02d and XX:59:%02d\n", 56+offset, 55+offset); printf("Will trigger at XX:29:%02d and XX:59:%02d\n", 56+offset, 55+offset);
if (test_mode) { if (test_mode) printf("TEST MODE: Will also play full hour signal at the end of every minute\n");
printf("TEST MODE: Will also play full hour signal at the end of every minute\n");
}
int elapsed_samples = 0; int elapsed_samples = 0;
int total_sequence_samples = 0; int total_sequence_samples = 0;
@@ -302,7 +238,7 @@ int main(int argc, char **argv) {
} }
int num_pips = (sequence_type == SEQ_29_56) ? 4 : 5; int num_pips = (sequence_type == SEQ_29_56) ? 4 : 5;
generate_signal(output, BUFFER_SIZE, &osc, master_volume, generate_signal(output, &osc, master_volume,
&elapsed_samples, total_sequence_samples, &elapsed_samples, total_sequence_samples,
pip_samples, pause_samples, beep_samples, num_pips); pip_samples, pause_samples, beep_samples, num_pips);

View File

@@ -119,7 +119,7 @@ void calculate_dcf77_bits(time_t now, int *bits) {
bits[20] = 1; bits[20] = 1;
int minutes = t->tm_min; int minutes = t->tm_min;
for (int i = 0; i < 4; i++) bits[21 + i] = (minutes % 10 >> i) & 1; for (int i = 0; i < 4; i++) bits[21 + i] = (minutes % 10 >> i) & 1; // BCD
for (int i = 0; i < 3; i++) bits[25 + i] = (minutes / 10 >> i) & 1; for (int i = 0; i < 3; i++) bits[25 + i] = (minutes / 10 >> i) & 1;
int minute_parity = 0; int minute_parity = 0;
@@ -155,8 +155,6 @@ void calculate_dcf77_bits(time_t now, int *bits) {
int year_parity = 0; int year_parity = 0;
for (int i = 36; i <= 57; i++) year_parity ^= bits[i]; for (int i = 36; i <= 57; i++) year_parity ^= bits[i];
bits[58] = year_parity; bits[58] = year_parity;
bits[59] = 2;
} }
void print_dcf77_bits(const int *bits) { void print_dcf77_bits(const int *bits) {
@@ -205,7 +203,6 @@ int main(int argc, char **argv) {
uint8_t test_mode = 0; uint8_t test_mode = 0;
uint8_t no_phase = 0; uint8_t no_phase = 0;
// #region Parse Arguments
int opt; int opt;
const char *short_opt = "o:F:s:v:t:Tnh"; const char *short_opt = "o:F:s:v:t:Tnh";
struct option long_opt[] = struct option long_opt[] =
@@ -251,7 +248,6 @@ int main(int argc, char **argv) {
return 0; return 0;
} }
} }
// #endregion
if(test_mode) { if(test_mode) {
time_t now = time(NULL) + offset + 60; time_t now = time(NULL) + offset + 60;
@@ -364,17 +360,14 @@ int main(int argc, char **argv) {
int current_bit = bit_position > 0 ? bit_position - 1 : 59; int current_bit = bit_position > 0 ? bit_position - 1 : 59;
in_dsss_period = (elapsed_samples >= dsss_start_samples && in_dsss_period = (elapsed_samples >= dsss_start_samples && elapsed_samples < dsss_end_samples);
elapsed_samples < dsss_end_samples);
float phase_offset = 0.0; float phase_offset = 0.0;
if (in_dsss_period && transmitting && !no_phase) { if (in_dsss_period && transmitting && !no_phase) {
if (current_cycle_count == 0) { if (current_cycle_count == 0) {
if (current_chip_count < CHIPS_PER_BIT) { if (current_chip_count < CHIPS_PER_BIT) {
unsigned int chip = generate_chip(); unsigned int modulated_chip = generate_chip() ^ dcf77_bits[current_bit];
unsigned int modulated_chip = chip ^ dcf77_bits[current_bit];
if (modulated_chip == 0) phase_offset = phase_shift_rad; if (modulated_chip == 0) phase_offset = phase_shift_rad;
else phase_offset = -phase_shift_rad; else phase_offset = -phase_shift_rad;
@@ -386,12 +379,11 @@ int main(int argc, char **argv) {
current_cycle_count = (current_cycle_count + 1) % CHIP_CYCLES; current_cycle_count = (current_cycle_count + 1) % CHIP_CYCLES;
} }
float t = osc.phase + phase_offset; float carrier = sinf(osc.phase + phase_offset);
float carrier = sinf(t);
advance_oscillator(&osc); advance_oscillator(&osc);
if (transmitting) { if (transmitting) {
if ((dcf77_bits[current_bit] == 0 && ms_within_second < PULSE_0_DURATION) || if (current_bit != 59 && (dcf77_bits[current_bit] == 0 && ms_within_second < PULSE_0_DURATION) ||
(dcf77_bits[current_bit] == 1 && ms_within_second < PULSE_1_DURATION)) { (dcf77_bits[current_bit] == 1 && ms_within_second < PULSE_1_DURATION)) {
output[i] = carrier * master_volume * REDUCED_AMPLITUDE; output[i] = carrier * master_volume * REDUCED_AMPLITUDE;
} else output[i] = carrier * master_volume; } else output[i] = carrier * master_volume;

View File

@@ -9,6 +9,7 @@
#define DEFAULT_STEREO 1 #define DEFAULT_STEREO 1
#define DEFAULT_STEREO_POLAR 0 #define DEFAULT_STEREO_POLAR 0
#define DEFAULT_RDS_STREAMS 2
#define DEFAULT_CLIPPER_THRESHOLD 1.0f #define DEFAULT_CLIPPER_THRESHOLD 1.0f
#define DEFAULT_SCA_FREQUENCY 67000.0f #define DEFAULT_SCA_FREQUENCY 67000.0f
#define DEFAULT_SCA_DEVIATION 7000.0f #define DEFAULT_SCA_DEVIATION 7000.0f
@@ -30,7 +31,6 @@
#define INPUT_DEVICE "FM_Audio.monitor" #define INPUT_DEVICE "FM_Audio.monitor"
#define OUTPUT_DEVICE "alsa_output.platform-soc_sound.stereo-fallback" #define OUTPUT_DEVICE "alsa_output.platform-soc_sound.stereo-fallback"
#define RDS_DEVICE "RDS.monitor" #define RDS_DEVICE "RDS.monitor"
#define RDS2_DEVICE "\0" // Disabled, this is for the additional two RDS channels, 71.25 and 76 khz
#define MPX_DEVICE "FM_MPX.monitor" #define MPX_DEVICE "FM_MPX.monitor"
#define SCA_DEVICE "\0" // Disabled #define SCA_DEVICE "\0" // Disabled
@@ -45,12 +45,8 @@
#define PILOT_VOLUME 0.09f // 9% #define PILOT_VOLUME 0.09f // 9%
#define STEREO_VOLUME 0.3f // 30% #define STEREO_VOLUME 0.3f // 30%
#define RDS_VOLUME 0.0475f // 4.75% #define RDS_VOLUME 0.0475f // 4.75%
#define RDS2_VOLUME 0.04f // 4% #define RDS_VOLUME_STEP 0.9f // 90%, so RDS2 stream 4 is 90% of stream 3 which is 90% of stream 2, which again is 90% of stream 1...
#define RDS3_VOLUME 0.0375f // 3.75% #define SCA_VOLUME 0.1f // 10%, needs to be high because this is analog. TODO: move sca to its own program (because then you can have as much scas as your computer allows to, here you have just one, and sca does not need any phase sync)
#define RDS4_VOLUME 0.035f // 3.5%
#define SCA_VOLUME 0.1f // 10%, needs to be high because this is analog
#define MPX_VOLUME 1.0f
static volatile sig_atomic_t to_run = 1; static volatile sig_atomic_t to_run = 1;
@@ -72,7 +68,7 @@ void show_help(char *name) {
"\t-o,--output\tOverride output device [default: %s]\n" "\t-o,--output\tOverride output device [default: %s]\n"
"\t-M,--mpx\tOverride MPX input device [default: %s]\n" "\t-M,--mpx\tOverride MPX input device [default: %s]\n"
"\t-r,--rds\tOverride RDS95 input device [default: %s]\n" "\t-r,--rds\tOverride RDS95 input device [default: %s]\n"
"\t-R,--rds2\tOverride the RDS2 additional stream device [default: %s]\n" "\t-R,--rds_streams\tSpecifies the number of the RDS streams provided by RDS95 [default: %d]\n"
"\t-S,--sca\tOverride the SCA input device [default: %s]\n" "\t-S,--sca\tOverride the SCA input device [default: %s]\n"
"\t-f,--sca_freq\tOverride the SCA frequency [default: %.1f]\n" "\t-f,--sca_freq\tOverride the SCA frequency [default: %.1f]\n"
"\t-F,--sca_dev\tOverride the SCA deviation [default: %.2f]\n" "\t-F,--sca_dev\tOverride the SCA deviation [default: %.2f]\n"
@@ -92,7 +88,7 @@ void show_help(char *name) {
,OUTPUT_DEVICE ,OUTPUT_DEVICE
,MPX_DEVICE ,MPX_DEVICE
,RDS_DEVICE ,RDS_DEVICE
,RDS2_DEVICE ,DEFAULT_RDS_STREAMS
,SCA_DEVICE ,SCA_DEVICE
,DEFAULT_SCA_FREQUENCY ,DEFAULT_SCA_FREQUENCY
,DEFAULT_SCA_DEVIATION ,DEFAULT_SCA_DEVIATION
@@ -109,14 +105,15 @@ void show_help(char *name) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
printf("fm95 (an FM Processor by radio95) version 1.7\n"); printf("fm95 (an FM Processor by radio95) version 1.8\n");
PulseInputDevice input_device, mpx_device, rds_device, rds2_device, sca_device; PulseInputDevice input_device, mpx_device, rds_device, sca_device;
PulseOutputDevice output_device; PulseOutputDevice output_device;
float clipper_threshold = DEFAULT_CLIPPER_THRESHOLD; float clipper_threshold = DEFAULT_CLIPPER_THRESHOLD;
uint8_t stereo = DEFAULT_STEREO; uint8_t stereo = DEFAULT_STEREO;
uint8_t polar_stereo = DEFAULT_STEREO_POLAR; uint8_t polar_stereo = DEFAULT_STEREO_POLAR;
uint8_t rds_streams = DEFAULT_RDS_STREAMS;
float sca_frequency = DEFAULT_SCA_FREQUENCY; float sca_frequency = DEFAULT_SCA_FREQUENCY;
float sca_deviation = DEFAULT_SCA_DEVIATION; float sca_deviation = DEFAULT_SCA_DEVIATION;
@@ -126,7 +123,6 @@ int main(int argc, char **argv) {
char audio_output_device[48] = OUTPUT_DEVICE; char audio_output_device[48] = OUTPUT_DEVICE;
char audio_mpx_device[48] = MPX_DEVICE; char audio_mpx_device[48] = MPX_DEVICE;
char audio_rds_device[48] = RDS_DEVICE; char audio_rds_device[48] = RDS_DEVICE;
char audio_rds2_device[48] = RDS2_DEVICE;
char audio_sca_device[48] = SCA_DEVICE; char audio_sca_device[48] = SCA_DEVICE;
float preemphasis_tau = DEFAULT_PREEMPHASIS_TAU; float preemphasis_tau = DEFAULT_PREEMPHASIS_TAU;
@@ -184,8 +180,12 @@ int main(int argc, char **argv) {
case 'r': // RDS in case 'r': // RDS in
memcpy(audio_rds_device, optarg, 47); memcpy(audio_rds_device, optarg, 47);
break; break;
case 'R': // RDS2 in case 'R': // RDS Streams
memcpy(audio_rds2_device, optarg, 47); rds_streams = atoi(optarg);
if(rds_streams > 4) {
printf("Can't do more RDS streams than 4 (why even?)\n");
exit(1);
}
break; break;
case 'S': //SCA in case 'S': //SCA in
memcpy(audio_sca_device, optarg, 47); memcpy(audio_sca_device, optarg, 47);
@@ -236,12 +236,9 @@ int main(int argc, char **argv) {
// #endregion // #endregion
int mpx_on = (strlen(audio_mpx_device) != 0); int mpx_on = (strlen(audio_mpx_device) != 0);
int rds_on = (strlen(audio_rds_device) != 0); int rds_on = (strlen(audio_rds_device) != 0 && rds_streams != 0);
int rds2_on = (rds_on && strlen(audio_rds2_device) != 0);
int sca_on = (strlen(audio_sca_device) != 0); int sca_on = (strlen(audio_sca_device) != 0);
// #region Setup devices
// Define formats and buffer atributes // Define formats and buffer atributes
pa_buffer_attr input_buffer_atr = { pa_buffer_attr input_buffer_atr = {
.maxlength = buffer_maxlength, .maxlength = buffer_maxlength,
@@ -275,7 +272,7 @@ int main(int argc, char **argv) {
if(rds_on) { if(rds_on) {
printf("Connecting to RDS95 device... (%s)\n", audio_rds_device); printf("Connecting to RDS95 device... (%s)\n", audio_rds_device);
opentime_pulse_error = init_PulseInputDevice(&rds_device, sample_rate, 2, "fm95", "RDS95 Input", audio_rds_device, &input_buffer_atr, PA_SAMPLE_FLOAT32NE); opentime_pulse_error = init_PulseInputDevice(&rds_device, sample_rate, rds_streams, "fm95", "RDS95 Input", audio_rds_device, &input_buffer_atr, PA_SAMPLE_FLOAT32NE);
if (opentime_pulse_error) { if (opentime_pulse_error) {
fprintf(stderr, "Error: cannot open RDS device: %s\n", pa_strerror(opentime_pulse_error)); fprintf(stderr, "Error: cannot open RDS device: %s\n", pa_strerror(opentime_pulse_error));
free_PulseInputDevice(&input_device); free_PulseInputDevice(&input_device);
@@ -283,18 +280,6 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
} }
if(rds2_on) {
printf("Connecting to RDS2 device... (%s)\n", audio_rds2_device);
opentime_pulse_error = init_PulseInputDevice(&rds2_device, sample_rate, 1, "fm95", "RDS2 Input", audio_rds2_device, &input_buffer_atr, PA_SAMPLE_FLOAT32NE);
if (opentime_pulse_error) {
fprintf(stderr, "Error: cannot open RDS2 device: %s\n", pa_strerror(opentime_pulse_error));
free_PulseInputDevice(&input_device);
if(mpx_on) free_PulseInputDevice(&mpx_device);
if(rds_on) free_PulseInputDevice(&rds_device);
return 1;
}
}
if(sca_on) { if(sca_on) {
printf("Connecting to SCA device... (%s)\n", audio_sca_device); printf("Connecting to SCA device... (%s)\n", audio_sca_device);
@@ -305,7 +290,6 @@ int main(int argc, char **argv) {
free_PulseInputDevice(&input_device); free_PulseInputDevice(&input_device);
if(mpx_on) free_PulseInputDevice(&mpx_device); if(mpx_on) free_PulseInputDevice(&mpx_device);
if(rds_on) free_PulseInputDevice(&rds_device); if(rds_on) free_PulseInputDevice(&rds_device);
if(rds2_on) free_PulseInputDevice(&rds2_device);
return 1; return 1;
} }
} }
@@ -318,11 +302,9 @@ int main(int argc, char **argv) {
free_PulseInputDevice(&input_device); free_PulseInputDevice(&input_device);
if(mpx_on) free_PulseInputDevice(&mpx_device); if(mpx_on) free_PulseInputDevice(&mpx_device);
if(rds_on) free_PulseInputDevice(&rds_device); if(rds_on) free_PulseInputDevice(&rds_device);
if(rds2_on) free_PulseInputDevice(&rds2_device);
if(sca_on) free_PulseInputDevice(&sca_device); if(sca_on) free_PulseInputDevice(&sca_device);
return 1; return 1;
} }
// #endregion
if(calibration_mode != 0) { if(calibration_mode != 0) {
Oscillator osc; Oscillator osc;
@@ -350,7 +332,6 @@ int main(int argc, char **argv) {
free_PulseInputDevice(&input_device); free_PulseInputDevice(&input_device);
if(mpx_on) free_PulseInputDevice(&mpx_device); if(mpx_on) free_PulseInputDevice(&mpx_device);
if(rds_on) free_PulseInputDevice(&rds_device); if(rds_on) free_PulseInputDevice(&rds_device);
if(rds2_on) free_PulseInputDevice(&rds2_device);
if(sca_on) free_PulseInputDevice(&sca_device); if(sca_on) free_PulseInputDevice(&sca_device);
free_PulseOutputDevice(&output_device); free_PulseOutputDevice(&output_device);
return 0; return 0;
@@ -388,8 +369,7 @@ int main(int argc, char **argv) {
float audio_stereo_input[BUFFER_SIZE*2]; // Stereo float audio_stereo_input[BUFFER_SIZE*2]; // Stereo
float rds1_rds2_in[BUFFER_SIZE*2] = {0}; // Stereo float rds_in[BUFFER_SIZE*rds_streams] = {0}; // multichannel
float rds3_rds4_in[BUFFER_SIZE*2] = {0}; // Stereo
float mpx_in[BUFFER_SIZE] = {0}; float mpx_in[BUFFER_SIZE] = {0};
float sca_in[BUFFER_SIZE] = {0}; float sca_in[BUFFER_SIZE] = {0};
@@ -411,21 +391,13 @@ int main(int argc, char **argv) {
} }
} }
if(rds_on) { if(rds_on) {
if((pulse_error = read_PulseInputDevice(&rds_device, rds1_rds2_in, sizeof(rds1_rds2_in)))) { if((pulse_error = read_PulseInputDevice(&rds_device, rds_in, sizeof(rds_in)))) {
if(pulse_error == -1) fprintf(stderr, "RDS95 PulseInputDevice reported as uninitialized."); if(pulse_error == -1) fprintf(stderr, "RDS95 PulseInputDevice reported as uninitialized.");
else fprintf(stderr, "Error reading from RDS95 device: %s\n", pa_strerror(pulse_error)); else fprintf(stderr, "Error reading from RDS95 device: %s\n", pa_strerror(pulse_error));
to_run = 0; to_run = 0;
break; break;
} }
} }
if(rds2_on) {
if((pulse_error = read_PulseInputDevice(&rds2_device, rds3_rds4_in, sizeof(rds3_rds4_in)))) {
if(pulse_error == -1) fprintf(stderr, "RDS2 PulseInputDevice reported as uninitialized.");
else fprintf(stderr, "Error reading from RDS2 device: %s\n", pa_strerror(pulse_error));
to_run = 0;
break;
}
}
if(sca_on) { if(sca_on) {
if((pulse_error = read_PulseInputDevice(&sca_device, sca_in, sizeof(sca_in)))) { if((pulse_error = read_PulseInputDevice(&sca_device, sca_in, sizeof(sca_in)))) {
if(pulse_error == -1) fprintf(stderr, "SCA PulseInputDevice reported as uninitialized."); if(pulse_error == -1) fprintf(stderr, "SCA PulseInputDevice reported as uninitialized.");
@@ -466,18 +438,13 @@ int main(int argc, char **argv) {
} }
} }
if(rds_on && !polar_stereo) { if(rds_on && !polar_stereo) {
float rds_carrier = get_oscillator_cos_multiplier_ni(&osc, 12); // 57 KHz for(int stream = 0; stream < rds_streams; stream++) {
float rds2_carrier_66 = get_oscillator_cos_multiplier_ni(&osc, 14); // 66.5 KHz uint8_t osc_stream = 12+stream;
mpx += (rds1_rds2_in[2*i+0]*rds_carrier)*RDS_VOLUME; if(osc_stream == 13) osc_stream++; // 61.75 KHz is not used, idk why but would be cool if it was
mpx += (rds1_rds2_in[2*i+1]*rds2_carrier_66)*RDS2_VOLUME; mpx += (rds_in[rds_streams*i+stream]*get_oscillator_cos_multiplier_ni(&osc, osc_stream)) * (RDS_VOLUME * powf(RDS_VOLUME_STEP, stream - 1));
if(rds2_on) {
float rds2_carrier_71 = get_oscillator_cos_multiplier_ni(&osc, 15); // 71.25 KHz
float rds2_carrier_76 = get_oscillator_cos_multiplier_ni(&osc, 16); // 76 KHz
mpx += (rds3_rds4_in[2*i+0]*rds2_carrier_71)*RDS3_VOLUME;
mpx += (rds3_rds4_in[2*i+1]*rds2_carrier_76)*RDS4_VOLUME;
} }
} }
if(mpx_on) mpx += mpx_in[i]*MPX_VOLUME; if(mpx_on) mpx += mpx_in[i];
if(sca_on) mpx += modulate_fm(&sca_mod, hard_clip(sca_in[i], sca_clipper_threshold))*SCA_VOLUME; if(sca_on) mpx += modulate_fm(&sca_mod, hard_clip(sca_in[i], sca_clipper_threshold))*SCA_VOLUME;
float mpxonly_power = measure_mpx(&mpx_only_power, mpx * mpx_deviation); float mpxonly_power = measure_mpx(&mpx_only_power, mpx * mpx_deviation);
@@ -492,12 +459,14 @@ int main(int argc, char **argv) {
target_gain = fmaxf(target_gain, 0.1f); target_gain = fmaxf(target_gain, 0.1f);
target_gain = fminf(target_gain, 1.0f); target_gain = fminf(target_gain, 1.0f);
bs412_audio_gain = 0.8f * bs412_audio_gain + 0.2f * target_gain; bs412_audio_gain = 0.85f * bs412_audio_gain + 0.15f * target_gain;
} }
} else { } else {
bs412_audio_gain = fminf(1.0f, bs412_audio_gain + 0.001f); bs412_audio_gain = fminf(1.0f, bs412_audio_gain + 0.001f);
} }
audio *= bs412_audio_gain;
iirfilt_rrrf_execute(mpx_lpf, audio, &audio); // Should have no effect, as audio should be 0-15, and 23-53, this is a filter for 53, assuming the filter is good, this is precaution and recomendation iirfilt_rrrf_execute(mpx_lpf, audio, &audio); // Should have no effect, as audio should be 0-15, and 23-53, this is a filter for 53, assuming the filter is good, this is precaution and recomendation
audio = hard_clip(audio, 1.0f-mpx); // Prevent clipping, via clipping the audio signal with relation to the mpx signal audio = hard_clip(audio, 1.0f-mpx); // Prevent clipping, via clipping the audio signal with relation to the mpx signal
@@ -520,7 +489,6 @@ int main(int argc, char **argv) {
free_PulseInputDevice(&input_device); free_PulseInputDevice(&input_device);
if(mpx_on) free_PulseInputDevice(&mpx_device); if(mpx_on) free_PulseInputDevice(&mpx_device);
if(rds_on) free_PulseInputDevice(&rds_device); if(rds_on) free_PulseInputDevice(&rds_device);
if(rds2_on) free_PulseInputDevice(&rds2_device);
if(sca_on) free_PulseInputDevice(&sca_device); if(sca_on) free_PulseInputDevice(&sca_device);
free_PulseOutputDevice(&output_device); free_PulseOutputDevice(&output_device);
return 0; return 0;