From f5b6a124867b5819ff256710ae8b52e167669be7 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Fri, 24 Jan 2025 17:24:46 +0100 Subject: [PATCH] add alsa output to STCode --- .vscode/.server-controller-port.log | 2 +- .vscode/settings.json | 6 ++- README.md | 2 + src/stereo_coder.c | 58 ++++++++++++++++++++++++++--- wip/tv_encoder.c | 48 ++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 wip/tv_encoder.c diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 4aa429f..ba686a6 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1737621156918, + "time": 1737734479782, "version": "0.0.3" } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 0c55742..f765936 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,10 @@ "options.h": "c", "random": "c", "__locale": "c", - "complex": "c" + "complex": "c", + "stdbool.h": "c", + "format": "c", + "ios": "c", + "stdint.h": "c" } } \ No newline at end of file diff --git a/README.md b/README.md index 25ba6ed..fd7e8ac 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ As far as i've tested it (29-31 december) it's been fine but after a fix it was Also i'd recommend to use the SSB version because it's more spectrum effiecent but SSB has slightly more cpu usage +This supports alsa output + # PSTCode This is a yet another version of a Stereo encoder, however for the OIRT band which is in use in Russia, Belarus and other countries diff --git a/src/stereo_coder.c b/src/stereo_coder.c index 8958706..8b0df72 100644 --- a/src/stereo_coder.c +++ b/src/stereo_coder.c @@ -1,6 +1,4 @@ #include -#include -#include #include #include #include @@ -10,7 +8,9 @@ #include "options.h" //#define SSB +#ifdef SSB //#define USB +#endif #include "../lib/constants.h" #include "../lib/oscillator.h" @@ -23,9 +23,16 @@ #define INPUT_DEVICE "real_real_tx_audio_input.monitor" #define OUTPUT_DEVICE "alsa_output.platform-soc_sound.stereo-fallback" +#define ALSA_OUTPUT // Output, not input or both #define BUFFER_SIZE 512 #define CLIPPER_THRESHOLD 0.525 // Adjust this as needed +#include +#include +#ifdef ALSA_OUTPUT +#include +#endif + #define MONO_VOLUME 0.45f // L+R Signal #define PILOT_VOLUME 0.09f // 19 KHz Pilot #define STEREO_VOLUME 0.45f // L-R signal possibly can be set to .9 because im not sure if usb will be 2 times stronger than dsb-sc @@ -88,6 +95,8 @@ int main() { .prebuf = buffer_prebuf }; + int open_pulse_error; + printf("Connecting to input device... (%s)\n", INPUT_DEVICE); pa_simple *input_device = pa_simple_new( @@ -99,15 +108,16 @@ int main() { &stereo_format, NULL, &input_buffer_atr, - NULL + &open_pulse_error ); if (!input_device) { - fprintf(stderr, "Error: cannot open input device.\n"); + fprintf(stderr, "Error: cannot open input device: %s\n", pa_strerror(open_pulse_error)); return 1; } printf("Connecting to output device... (%s)\n", OUTPUT_DEVICE); + #ifndef ALSA_OUTPUT pa_simple *output_device = pa_simple_new( NULL, "StereoEncoder", @@ -117,13 +127,40 @@ int main() { &mono_format, NULL, &output_buffer_atr, - NULL + &open_pulse_error ); if (!output_device) { - fprintf(stderr, "Error: cannot open output device.\n"); + fprintf(stderr, "Error: cannot open output device: %s\n", pa_strerror(open_pulse_error)); pa_simple_free(input_device); return 1; } + #else + snd_pcm_hw_params_t *output_params; + snd_pcm_t *output_handle; + int output_error = snd_pcm_open(&output_handle, OUTPUT_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); + if(output_error < 0) { + fprintf(stderr, "Error: cannot open output device: %s\n", snd_strerror(output_error)); + pa_simple_free(input_device); + return 1; + } + snd_pcm_hw_params_malloc(&output_params); + snd_pcm_hw_params_any(output_handle, output_params); + snd_pcm_hw_params_set_access(output_handle, output_params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(output_handle, output_params, SND_PCM_FORMAT_FLOAT); // Same as pulse's Float32NE + snd_pcm_hw_params_set_channels(output_handle, output_params, 1); + unsigned int rate = SAMPLE_RATE; + int dir; + snd_pcm_hw_params_set_rate_near(output_handle, output_params, &rate, &dir); + snd_pcm_uframes_t frames = BUFFER_SIZE; + snd_pcm_hw_params_set_period_size_near(output_handle, output_params, &frames, &dir); // i don't have a clue why like this + output_error = snd_pcm_hw_params(output_handle, output_params); + if(output_error < 0) { + fprintf(stderr, "Error: cannot open output device: %s\n", snd_strerror(output_error)); + snd_pcm_close(output_handle); + pa_simple_free(input_device); + return 1; + } + #endif Oscillator pilot_osc; init_oscillator(&pilot_osc, 19000.0, SAMPLE_RATE); // Pilot, it's there to indicate stereo and as a refrence signal with the stereo carrier @@ -216,15 +253,24 @@ int main() { #endif } +#ifndef ALSA_OUTPUT if (pa_simple_write(output_device, mpx, sizeof(mpx), &pulse_error) < 0) { fprintf(stderr, "Error writing to output device: %s\n", pa_strerror(pulse_error)); to_run = 0; break; } +#else + snd_pcm_writei(output_handle, mpx, sizeof(mpx)); +#endif } printf("Cleaning up...\n"); pa_simple_free(input_device); + #ifndef ALSA_OUTPUT pa_simple_free(output_device); + #else + snd_pcm_drain(output_handle); + snd_pcm_free(output_handle); + #endif #ifdef SSB exit_hilbert(&hilbert); exit_delay_line(&monoDelay); diff --git a/wip/tv_encoder.c b/wip/tv_encoder.c new file mode 100644 index 0000000..c0de682 --- /dev/null +++ b/wip/tv_encoder.c @@ -0,0 +1,48 @@ +// This will encode a black and white TV signal using a luminance value, how does it work? +/* + It encodes the luminance into negative values, so totally white pixel should output -1, a black one should be 0 + + Every new line it sends a 0.5, every frame it is a 1.0 +*/ + +#include "../lib/fm_modulator.h" + +unsigned int rgb_to_luminance(unsigned int r, unsigned int g, unsigned int b) { + return (unsigned int)(0.299 * r + 0.587 * g + 0.114 * b); +} + +typedef struct { + int line; + int pixel; + int lines; + int pixels; +} TVEncoder; + +void init_tv_modulator(TVEncoder* tv, int lines, int pixels) { + tv->pixels = pixels; + tv->lines = lines; + tv->line = 0; + tv->pixel = 0; +} + +float tv_encode(TVEncoder* tv, float luminance) { + float normalized_luminance = luminance / 255.0f; // Normalize luminance to [0, 1] + + if (tv->line < tv->lines) { + if (tv->pixel < tv->pixels) { + // Process pixel within the current line + tv->pixel++; + return -normalized_luminance; + } else { + // End of line: reset pixel counter and move to the next line + tv->pixel = 0; + tv->line++; + return 0.5f; + } + } else { + // End of frame: reset frame counters + tv->line = 0; + tv->pixel = 0; + return 1.0f; + } +} \ No newline at end of file