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

add delay

This commit is contained in:
2024-12-31 22:41:32 +01:00
parent 138f6b3d69
commit c111e8e6d6
4 changed files with 64 additions and 5 deletions

View File

@@ -13,6 +13,9 @@ Also nearly no latency, not like Stereo Tool (or mpxgen which doesn't even work)
As far as i've tested it (29-31 december) it's been fine but after a fix it was great, so i'd redecommend you
# SSB-STCode
This is a version of the stereo code but instead of DSB-SC it transmits some kind of VSG (mostly USB with a bit of LSB)
# SCAMod
SCAMod is a simple FM modulator which can be used to modulate a secondary audio stream, has similiar cpu usage and latency as STCode

View File

@@ -38,4 +38,44 @@ float apply_low_pass_filter(LowPassFilter *lp, float sample) {
index = (index + 1) % FIR_TAPS;
}
return result*6;
}
void init_delay_line(DelayLine *delay_line, int max_delay) {
delay_line->buffer = (float *)calloc(max_delay, sizeof(float));
delay_line->size = max_delay;
delay_line->write_idx = 0;
delay_line->read_idx = 0;
delay_line->delay = 0;
}
void set_delay_line(DelayLine *delay_line, int new_delay) {
if (new_delay >= delay_line->size) {
new_delay = delay_line->size - 1;
}
if (new_delay < 0) {
new_delay = 0;
}
delay_line->delay = new_delay;
delay_line->read_idx = (delay_line->write_idx - new_delay + delay_line->size) % delay_line->size;
}
float delay_line(DelayLine *delay_line, float in) {
float out;
// Read the delayed sample
out = delay_line->buffer[delay_line->read_idx];
// Write the new sample
delay_line->buffer[delay_line->write_idx] = in;
// Update indices
delay_line->write_idx = (delay_line->write_idx + 1) % delay_line->size;
delay_line->read_idx = (delay_line->read_idx + 1) % delay_line->size;
return out;
}
void exit_delay_line(DelayLine *delay_line) {
free(delay_line->buffer);
}

View File

@@ -20,4 +20,18 @@ typedef struct {
} LowPassFilter;
void init_low_pass_filter(LowPassFilter *lp, float cutoff_frequency, float sample_rate);
float apply_low_pass_filter(LowPassFilter *lp, float sample);
float apply_low_pass_filter(LowPassFilter *lp, float sample);
typedef struct {
float *buffer;
int write_idx; // Write position
int read_idx; // Read position
int size; // Total buffer size
int delay; // Delay in samples
} DelayLine;
void init_delay_line(DelayLine *delay_line, int max_delay);
void set_delay_line(DelayLine *delay_line, int new_delay);
float delay_line(DelayLine *delay_line, float in);
void exit_delay_line(DelayLine *delay_line);

View File

@@ -60,7 +60,7 @@ static void stop(int signum) {
}
int main() {
printf("STCode : Stereo encoder made by radio95 (with help of ChatGPT and Claude, thanks!)\n");
printf("SSB-STCode : Stereo encoder made by radio95 (with help of ChatGPT and Claude, thanks!)\n");
// Define formats and buffer atributes
pa_sample_spec stereo_format = {
.format = PA_SAMPLE_FLOAT32NE, //Float32 NE, or Float32 Native Endian, the float in c uses the endianess of your pc, or native endian, and float is float32, and double is float64
@@ -124,6 +124,8 @@ int main() {
init_oscillator(&pilot_osc, 19000.0, SAMPLE_RATE); // Pilot, it's there to indicate stereo and as a refrence signal with the stereo carrier
HilbertTransformer hilbert;
init_hilbert(&hilbert);
DelayLine monoDelay;
init_delay_line(&monoDelay, 99);
#ifdef PREEMPHASIS
Emphasis preemp_l, preemp_r;
init_emphasis(&preemp_l, PREEMPHASIS_TAU, SAMPLE_RATE);
@@ -149,7 +151,7 @@ int main() {
uninterleave(input, left, right, BUFFER_SIZE*2);
for (int i = 0; i < BUFFER_SIZE; i++) {
float sin38 = sinf(pilot_osc.phase*2); // Stereo carrier should be a harmonic of the pilot which is in phase, best way to generate the harmonic is to multiply the pilot's phase by two, so it is mathematically impossible for them to not be in phase
float sin38 = sinf(pilot_osc.phase*2);
float cos38 = cosf(pilot_osc.phase*2); // Stereo carrier should be a harmonic of the pilot which is in phase, best way to generate the harmonic is to multiply the pilot's phase by two, so it is mathematically impossible for them to not be in phase
float pilot = get_oscillator_sin_sample(&pilot_osc); // This is after because if it was before then the stereo would be out of phase by one increment, so [GET STEREO] ([GET PILOT] [INCREMENT PHASE])
float l_in = left[i];
@@ -186,9 +188,9 @@ int main() {
float stereo = (current_left_input - current_right_input) / 2.0f; // Also Stereo to Mono but a bit diffrent
float stereo_i, stereo_q;
apply_hilbert(&hilbert, stereo, &stereo_i, &stereo_q);
float lsb = (stereo_i*cos38-stereo_q*(sin38*0.75f));
float lsb = (stereo_i*cos38-stereo_q*(sin38*0.7f));
mpx[i] = mono * MONO_VOLUME +
mpx[i] = delay_line(&monoDelay, mono) * MONO_VOLUME +
pilot * PILOT_VOLUME +
lsb*STEREO_VOLUME;
}