* [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions
@ 2023-07-10 0:01 Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 2/5] avradio/sdrdemux: shift 19khz carrier differntly Michael Niedermayer
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-07-10 0:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
libavradio/sdrdemux.c | 56 ++++++++++++++++++++-----------------------
1 file changed, 26 insertions(+), 30 deletions(-)
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 7cc71b2cfb..92b218d899 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -616,43 +616,39 @@ static double find_am_carrier(SDRContext *sdr, const AVComplexFloat *data, int d
}
/**
- * Demodulate with a carrier that is in the middle of the signal like in AM
- * This will normalize the signal based on the carrier amplitude and subtract the carrier
+ * Demodulate with a carrier that is a N-th of the frequency.
+ * If N is one the carrier will be subtracted from the signal too.
+ * N==1 corresponds to classical AM, N>1 are demodulations with suppressed carriers.
+ *
+ * For N==1 and N==3 the signal will be normalized. For N==2 it will not be
+ * This is to avoid a sqrt() and happens to be what we want in the current use cases.
+ *
+ * The output will be scaled by the window.
*/
-static void synchronous_am_demodulation(AVComplexFloat *iblock, AVComplexFloat *icarrier, float *window, int len)
+static av_always_inline void synchronous_am_demodulationN(AVComplexFloat *iblock, AVComplexFloat *icarrier, float *window, int len, int N)
{
+ av_assert0(N>=1 && N<=3); //currently supported, trivial to add more if needed
+
for (int i = 0; i<len; i++) {
AVComplexFloat c = icarrier[i];
AVComplexFloat s = iblock[i];
float w = window[i];
- float den = w / (c.re*c.re + c.im*c.im);
- av_assert0(c.re*c.re + c.im*c.im > 0);
+ AVComplexFloat c2= {c.re*c.re, c.im*c.im};
+ float den = w/(c2.re + c2.im);
+
+ if (N==2) {
+ c.im *= c.re + c.re;
+ c.re = c2.re - c2.im;
+ } else if (N==3) {
+ den *= den;
+ c.re *= c2.re - 3*c2.im;
+ c.im *= 3*c2.re - c2.im;
+ }
iblock[i].re = ( s.im*c.im + s.re*c.re) * den;
iblock[i].im = ( s.im*c.re - s.re*c.im) * den;
- iblock[i].re -= w;
- }
-}
-
-/**
- * Demodulate with a carrier that is half the frequency and reduced amplitude
- * This will not normalize the signal based on the carrier amplitude
- */
-static void synchronous_am_demodulation2(AVComplexFloat *iblock, AVComplexFloat *icarrier, float *window, int len)
-{
- for (int i = 0; i<len; i++) {
- AVComplexFloat c = icarrier[i];
- AVComplexFloat s = iblock[i];
- AVComplexFloat c2;
- float w = window[i];
- float den = w / (c.re*c.re + c.im*c.im);
- av_assert0(c.re*c.re + c.im*c.im > 0);
-
- c2.re = c.re*c.re - c.im*c.im;
- c2.im = c.re*c.im + c.im*c.re;
-
- iblock[i].re = ( s.im*c2.im + s.re*c2.re) * den;
- iblock[i].im = ( s.im*c2.re - s.re*c2.im) * den;
+ if (N==1)
+ iblock[i].re -= w;
}
}
@@ -728,7 +724,7 @@ static int demodulate_am(SDRContext *sdr, int stream_index, AVPacket *pkt)
sst->block[i] = sdr->block[index + i - len];
sst->ifft(sst->ifft_ctx, sst->icarrier, sst->block, sizeof(AVComplexFloat));
- synchronous_am_demodulation(sst->iblock, sst->icarrier, sst->window, 2*sst->block_size);
+ synchronous_am_demodulationN(sst->iblock, sst->icarrier, sst->window, 2*sst->block_size, 1);
scale = 0.9;
} else {
// Synchronous demodulation using Macleod based systhesized carrier
@@ -997,7 +993,7 @@ static int demodulate_fm(SDRContext *sdr, int stream_index, AVPacket *pkt)
apply_deemphasis(sdr, sst->block + i + 2*carrier19_i - 2*shift, sst->block_size_p2, sample_rate_p2, + 1);
apply_deemphasis(sdr, sst->block + i + 2*carrier19_i - 2*shift, sst->block_size_p2, sample_rate_p2, - 1);
sst->ifft_p2(sst->ifft_p2_ctx, sst->iside , sst->block + i, sizeof(AVComplexFloat));
- synchronous_am_demodulation2(sst->iside, sst->icarrier, sst->window_p2, 2*sst->block_size_p2);
+ synchronous_am_demodulationN(sst->iside, sst->icarrier, sst->window_p2, 2*sst->block_size_p2, 2);
}
memset(sst->block + len17_i, 0, (2*sst->block_size_p2 - len17_i) * sizeof(AVComplexFloat));
apply_deemphasis(sdr, sst->block, 2*sst->block_size_p2, sample_rate_p2, + 1);
--
2.31.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 6+ messages in thread
* [FFmpeg-devel] [PATCH 2/5] avradio/sdrdemux: shift 19khz carrier differntly
2023-07-10 0:01 [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
@ 2023-07-10 0:01 ` Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 3/5] avradio/sdrdemux: only allocare iside and window_p2 when needed Michael Niedermayer
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-07-10 0:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
This simplifies the following commits
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
libavradio/sdrdemux.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 92b218d899..ef8a8a91d3 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -983,15 +983,17 @@ static int demodulate_fm(SDRContext *sdr, int stream_index, AVPacket *pkt)
carrier19_i = lrint(carrier19_i_exact);
if (carrier19_i >= 0) {
- int shift = carrier19_i/2;
i = sst->block_size;
memset(sst->block + i, 0, 2*sst->block_size_p2 * sizeof(AVComplexFloat));
- memcpy(sst->block + i + carrier19_i - W - shift , sst->block + carrier19_i - W, sizeof(AVComplexFloat)*(2*W+1));
+ memcpy(sst->block + i, sst->block + carrier19_i, sizeof(AVComplexFloat)*(W+1));
+ memcpy(sst->block + i + 2*sst->block_size_p2 - W, sst->block + carrier19_i - W, sizeof(AVComplexFloat)*W);
sst->ifft_p2(sst->ifft_p2_ctx, sst->icarrier, sst->block + i, sizeof(AVComplexFloat));
- memcpy(sst->block + i + 2*carrier19_i - 2*shift - len17_i, sst->block + 2*carrier19_i - len17_i, sizeof(AVComplexFloat)*2*len17_i);
- apply_deemphasis(sdr, sst->block + i + 2*carrier19_i - 2*shift, sst->block_size_p2, sample_rate_p2, + 1);
- apply_deemphasis(sdr, sst->block + i + 2*carrier19_i - 2*shift, sst->block_size_p2, sample_rate_p2, - 1);
+ memcpy(sst->block + i, sst->block + 2*carrier19_i, sizeof(AVComplexFloat)*len17_i);
+ memcpy(sst->block + i + 2*sst->block_size_p2 - len17_i, sst->block + 2*carrier19_i - len17_i, sizeof(AVComplexFloat)*len17_i);
+
+ apply_deemphasis(sdr, sst->block + i, sst->block_size_p2, sample_rate_p2, + 1);
+ apply_deemphasis(sdr, sst->block + i + 2*sst->block_size_p2, sst->block_size_p2, sample_rate_p2, - 1);
sst->ifft_p2(sst->ifft_p2_ctx, sst->iside , sst->block + i, sizeof(AVComplexFloat));
synchronous_am_demodulationN(sst->iside, sst->icarrier, sst->window_p2, 2*sst->block_size_p2, 2);
}
--
2.31.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 6+ messages in thread
* [FFmpeg-devel] [PATCH 3/5] avradio/sdrdemux: only allocare iside and window_p2 when needed
2023-07-10 0:01 [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 2/5] avradio/sdrdemux: shift 19khz carrier differntly Michael Niedermayer
@ 2023-07-10 0:01 ` Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 4/5] avradio/sdrdemux: factor block_time out Michael Niedermayer
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-07-10 0:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
libavradio/sdrdemux.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index ef8a8a91d3..36b8aac2fb 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -1136,16 +1136,23 @@ static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
if (ret < 0)
return ret;
+ sst->window_p2 = av_malloc(sizeof(*sst->window_p2)* 2 * sst->block_size_p2);
+ sst->iside = av_malloc(sizeof(*sst->iside) * 2 * sst->block_size_p2);
+ if (!sst->iside || !sst->window_p2)
+ return AVERROR(ENOMEM);
+
+ avpriv_kbd_window_init(sst->window_p2, sdr->kbd_alpha, sst->block_size_p2);
+ for(int i = sst->block_size_p2; i < 2 * sst->block_size_p2; i++) {
+ sst->window_p2[i] = sst->window_p2[2*sst->block_size_p2 - i - 1];
+ }
}
sst->out_buf = av_malloc(sizeof(*sst->out_buf) * 2 * sst->block_size);
sst->block = av_malloc(sizeof(*sst-> block) * 2 * sst->block_size);
sst->iblock = av_malloc(sizeof(*sst->iblock) * 2 * sst->block_size);
sst->icarrier = av_malloc(sizeof(*sst->icarrier) * 2 * sst->block_size);
- sst->iside = av_malloc(sizeof(*sst->iside) * 2 * sst->block_size_p2);
sst->window = av_malloc(sizeof(*sst->window) * 2 * sst->block_size);
- sst->window_p2 = av_malloc(sizeof(*sst->window_p2)* 2 * sst->block_size_p2);
- if (!sst->out_buf || !sst->block || !sst->iblock || !sst->icarrier || !sst->iside || !sst->window || !sst->window_p2)
+ if (!sst->out_buf || !sst->block || !sst->iblock || !sst->icarrier || !sst->window)
return AVERROR(ENOMEM);
avpriv_kbd_window_init(sst->window, sdr->kbd_alpha, sst->block_size);
@@ -1153,10 +1160,6 @@ static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
sst->window[i] = sst->window[2*sst->block_size - i - 1];
}
- avpriv_kbd_window_init(sst->window_p2, sdr->kbd_alpha, sst->block_size_p2);
- for(int i = sst->block_size_p2; i < 2 * sst->block_size_p2; i++) {
- sst->window_p2[i] = sst->window_p2[2*sst->block_size_p2 - i - 1];
- }
sst->am_amplitude = 0;
}
--
2.31.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 6+ messages in thread
* [FFmpeg-devel] [PATCH 4/5] avradio/sdrdemux: factor block_time out
2023-07-10 0:01 [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 2/5] avradio/sdrdemux: shift 19khz carrier differntly Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 3/5] avradio/sdrdemux: only allocare iside and window_p2 when needed Michael Niedermayer
@ 2023-07-10 0:01 ` Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 5/5] avradio: RDS support Michael Niedermayer
2023-07-11 20:10 ` [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
4 siblings, 0 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-07-10 0:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
libavradio/sdrdemux.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 36b8aac2fb..0cad9a2d3a 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -1099,6 +1099,7 @@ static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
AVFormatContext *s = sdr->avfmt;
AVStream *st = s->streams[stream_index];
SDRStream *sst = st->priv_data;
+ double block_time = sdr->block_size / (double)sdr->sdr_sample_rate;
int ret;
//For now we expect each station to be only demodulated once, nothing should break though if its done more often
@@ -1116,7 +1117,7 @@ static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
free_stream(sdr, stream_index);
- for (sst->block_size = 4; 2ll *sst->station->bandwidth * sdr->block_size / sdr->sdr_sample_rate > sst->block_size; sst->block_size <<= 1)
+ for (sst->block_size = 4; 2ll *sst->station->bandwidth * block_time > sst->block_size; sst->block_size <<= 1)
;
sst->block_size = FFMIN(sdr->block_size, sst->block_size);
@@ -1130,7 +1131,7 @@ static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
if (ret < 0)
return ret;
- for (sst->block_size_p2 = 4; 2ll *sst->station->bandwidth_p2 * sdr->block_size / sdr->sdr_sample_rate > sst->block_size_p2; sst->block_size_p2 <<= 1)
+ for (sst->block_size_p2 = 4; 2ll *sst->station->bandwidth_p2 * block_time > sst->block_size_p2; sst->block_size_p2 <<= 1)
;
ret = av_tx_init(&sst->ifft_p2_ctx, &sst->ifft_p2, AV_TX_FLOAT_FFT, 1, 2*sst->block_size_p2, NULL, 0);
if (ret < 0)
--
2.31.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 6+ messages in thread
* [FFmpeg-devel] [PATCH 5/5] avradio: RDS support
2023-07-10 0:01 [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
` (2 preceding siblings ...)
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 4/5] avradio/sdrdemux: factor block_time out Michael Niedermayer
@ 2023-07-10 0:01 ` Michael Niedermayer
2023-07-11 20:10 ` [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
4 siblings, 0 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-07-10 0:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
libavradio/Makefile | 4 +-
libavradio/rds.c | 203 ++++++++++++++++++++++++++++++++++++++++
libavradio/sdr.h | 13 ++-
libavradio/sdrdemux.c | 18 +++-
libavradio/vissualize.c | 13 ++-
5 files changed, 240 insertions(+), 11 deletions(-)
create mode 100644 libavradio/rds.c
diff --git a/libavradio/Makefile b/libavradio/Makefile
index 40b38f798e..5efc2588c3 100644
--- a/libavradio/Makefile
+++ b/libavradio/Makefile
@@ -11,5 +11,5 @@ OBJS = allradios.o \
# input/output radios
-OBJS-$(CONFIG_SDR_INRADIO) += sdrinradio.o vissualize.o
-OBJS-$(CONFIG_SDRFILE_INRADIO) += sdrdemux.o vissualize.o
+OBJS-$(CONFIG_SDR_INRADIO) += sdrinradio.o vissualize.o rds.o
+OBJS-$(CONFIG_SDRFILE_INRADIO) += sdrdemux.o vissualize.o rds.o
diff --git a/libavradio/rds.c b/libavradio/rds.c
new file mode 100644
index 0000000000..dd9a934c3c
--- /dev/null
+++ b/libavradio/rds.c
@@ -0,0 +1,203 @@
+/*
+ * RDS
+ * Copyright (c) 2023 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ *
+ *
+ */
+
+#include "sdr.h"
+
+#include <float.h>
+#include "libavutil/avassert.h"
+#include "libavutil/ffmath.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "libavformat/avformat.h"
+#include "libavformat/demux.h"
+
+/**
+ * Check and correct RDS block
+ * @param[out] group the data bits are returned here
+ * @param block block nu,ber (0 to 3)
+ * @return 1 if correctable single bit error, 0 if no error, >99 if non correctable errors
+ */
+static int check_rds_block(uint16_t group[4], const float diff[104], int block)
+{
+#define RDS_G 0x5B9 //101 1011 1001
+ static const uint16_t offset[4] = {0x0FC, 0x198, 0x168, 0x1B4};
+ unsigned codeword = 0;
+ unsigned syndrom = 0;
+ //we carry floats through to here so we can do a soft decission decoder
+ //ATM lets just do hard decission decoding that should be more than good enough
+
+ //FIXME we could do this more efficiently but does it matter?
+ for(int i=0; i<26; i++) {
+ int bit = (diff[i + block*26]<0);
+ codeword += codeword + bit;
+ syndrom += syndrom + bit;
+ if (syndrom & (1<<10))
+ syndrom ^= RDS_G;
+ }
+ if (block==2 && (group[1]&0x800)) {
+ syndrom ^= 0x350;
+ }else
+ syndrom ^= offset[block];
+ //FIXME the spec talks about a special case of a 0 offset used in the USA
+
+ group[block] = codeword >> 10;
+
+ // try correcting some basic errors
+ if (syndrom) {
+ for (unsigned e = 1; e <= 2; e ++) {
+ unsigned mask = 255 >> (8-e);
+ unsigned syndrom1 = mask;
+ for(int i=0; i<27-e; i++) {
+ if (syndrom == syndrom1) {
+ group[block] ^= (mask<<i) >> 10;
+ return e;
+ }
+ syndrom1 += syndrom1;
+ if (syndrom1 & (1<<10))
+ syndrom1 ^= RDS_G;
+ }
+ }
+ return 100; // this is a good place do a 2nd pass with a soft decssion multi bit decoder
+ }
+
+ return 0;
+}
+
+static int decode_rds_group(SDRContext *sdr, SDRStream *sst, uint16_t group[4])
+{
+ Station *station = sst->station;
+ int pi = group[0];
+ int a = group[1] >> 12;
+ int b = group[1] & 0x800;
+ int tp = group[1] & 0x400;
+ int pty= (group[1] >> 5) & 0x1F;
+
+ switch(a) {
+ case 0:
+ AV_WB16(station->name + 2*(group[1]&3), group[3]);
+ break;
+ case 2:
+ if (b) {
+ AV_WB16(station->radiotext + 2*(group[1]&15) , group[3]);
+ } else {
+ AV_WB16(station->radiotext + 4*(group[1]&15) , group[2]);
+ AV_WB16(station->radiotext + 4*(group[1]&15) + 2, group[3]);
+ }
+ break;
+ case 10:
+ if (b==0) {
+ AV_WB16(station->programm_type_name + 4*(group[1]&1) , group[2]);
+ AV_WB16(station->programm_type_name + 4*(group[1]&1) + 2, group[3]);
+ }
+ break;
+// case 14:
+// break;
+ default:
+ av_log(sdr->avfmt, AV_LOG_DEBUG, "RDS: PI %X, A %X B %X PTY %X\n", pi,a,b,pty);
+ }
+
+ return 0;
+}
+
+int ff_sdr_decode_rds(SDRContext *sdr, SDRStream *sst, AVComplexFloat *signal)
+{
+ int i, phase;
+ float (*ring)[2] = sst->rds_ring;
+ float diff[2*104 - 1];
+ uint16_t group[4];
+ int64_t num_step_in_p2 = sdr->sdr_sample_rate * (int64_t)sst->block_size_p2;
+ int64_t den_step_on_p2 = sdr->block_size * 2375LL;
+#define IDX(I) ((I)*num_step_in_p2/den_step_on_p2)
+
+ av_assert0(sst->rds_ring_pos <= sst->rds_ring_size - 2*sst->block_size_p2);
+
+ //For reasons that are beyond me, RDS spec allows inphase and quadrature so we have to compute and check both
+ for (int i=0; i < sst->block_size_p2; i++) {
+ ring[ sst->rds_ring_pos + i ][0] += signal[i].re * sst->window_p2[i];
+ ring[ sst->rds_ring_pos + i + sst->block_size_p2 ][0] = signal[i + sst->block_size_p2].re * sst->window_p2[i + sst->block_size_p2];
+ ring[ sst->rds_ring_pos + i ][1] += signal[i].im * sst->window_p2[i];
+ ring[ sst->rds_ring_pos + i + sst->block_size_p2 ][1] = signal[i + sst->block_size_p2].im * sst->window_p2[i + sst->block_size_p2];
+ }
+ sst->rds_ring_pos += sst->block_size_p2;
+
+ while (sst->rds_ring_pos > IDX(2) + IDX(4*104-1)) {
+ int best_phase;
+ float best_amplitude = -1;
+ for (phase = 0; phase < 2*IDX(2); phase++) {
+ double a = 0;
+ for (i = 0; i<2*104; i++) {
+ a += fabs(ring[IDX(2*i+1)][phase] - ring[IDX(2*i)][phase]);
+ }
+ if (a > best_amplitude) {
+ best_amplitude = a;
+ best_phase = phase;
+ }
+ }
+
+ phase = best_phase;
+ float last_bpsk = 0;
+ for (i = 0; i<2*104; i++) {
+ float bpsk = ring[IDX(2*i+1)][phase] - ring[IDX(2*i)][phase];
+ if (i)
+ diff[i-1] = bpsk * last_bpsk;
+ last_bpsk = bpsk;
+ }
+
+ int best_errors = INT_MAX;
+ for (phase = 0; phase < 104; phase++) {
+ int error = 0;
+ for (int block = 0; block < 4; block++) {
+ error += check_rds_block(group, diff + phase, block);
+ }
+ if (error < best_errors) {
+ best_errors = error;
+ best_phase = phase;
+ }
+ }
+ av_log(sdr->avfmt, AV_LOG_DEBUG, "RDS ERR:%d\n", best_errors);
+
+ // are we having no errors or correctable errors
+ if (best_errors < 10) {
+ int error = 0;
+ for (int block = 0; block < 4; block++) {
+ error += check_rds_block(group, diff + best_phase, block);
+ }
+ //have to recheck because of floats
+ if (error < 10) {
+ decode_rds_group(sdr, sst, group);
+ }
+ }
+ int step = IDX(2*(best_phase + 103));
+
+ av_assert0(sst->rds_ring_pos >= step);
+ memmove(ring, ring + step, (sst->rds_ring_pos + sst->block_size_p2 - step) * sizeof(*sst->rds_ring));
+ sst->rds_ring_pos -= step;
+ }
+ av_assert0 (sst->rds_ring_pos + 2*sst->block_size_p2 <= sst->rds_ring_size);
+
+ return 0;
+}
diff --git a/libavradio/sdr.h b/libavradio/sdr.h
index 1582f70d86..212358fad9 100644
--- a/libavradio/sdr.h
+++ b/libavradio/sdr.h
@@ -71,7 +71,9 @@ typedef enum Modulation {
#define HISTOGRAMM_SIZE 9
typedef struct Station {
- char *name;
+ char name[9];
+ char radiotext[65];
+ char programm_type_name[9];
enum Modulation modulation;
double frequency;
int nb_frequency; ///< number of detections which are used to compute the frequency
@@ -110,6 +112,9 @@ typedef struct SDRStream {
AVComplexFloat *iside;
float *window;
float *window_p2;
+ float (*rds_ring)[2];
+ int rds_ring_size;
+ int rds_ring_pos;
Station *station;
float am_amplitude;
@@ -266,6 +271,12 @@ int ff_sdr_find_stations(SDRContext *sdr, double freq, double range, Station **s
int ff_sdr_histogram_score(Station *s);
+/**
+ * Decode RDS
+ * @param signal the time domain RDS signal
+ */
+int ff_sdr_decode_rds(SDRContext *sdr, SDRStream *sst, AVComplexFloat *signal);
+
static inline float len2(AVComplexFloat c)
{
return c.re*c.re + c.im*c.im;
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 0cad9a2d3a..a34f784e63 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -99,7 +99,6 @@ static void apply_deemphasis(SDRContext *sdr, AVComplexFloat *data, int len, int
static void free_station(Station *station)
{
- av_freep(&station->name);
if (station->stream)
station->stream->station = NULL;
av_free(station);
@@ -937,7 +936,8 @@ static int demodulate_fm(SDRContext *sdr, int stream_index, AVPacket *pkt)
int ret, i;
float clip = 1.0;
int carrier19_i = 2L*sst->block_size*19000 / sample_rate;
- int len17_i = 2L*sst->block_size*17000 / sample_rate;
+ int len17_i = 2L*sst->block_size*16500 / sample_rate;
+ int len2_4_i = 2L*sst->block_size* 2400 / sample_rate;
double carrier19_i_exact;
int W= 5;
@@ -989,9 +989,14 @@ static int demodulate_fm(SDRContext *sdr, int stream_index, AVPacket *pkt)
memcpy(sst->block + i + 2*sst->block_size_p2 - W, sst->block + carrier19_i - W, sizeof(AVComplexFloat)*W);
sst->ifft_p2(sst->ifft_p2_ctx, sst->icarrier, sst->block + i, sizeof(AVComplexFloat));
+ memcpy(sst->block + i, sst->block + 3*carrier19_i, sizeof(AVComplexFloat)*len2_4_i);
+ memcpy(sst->block + i + 2*sst->block_size_p2 - len2_4_i, sst->block + 3*carrier19_i - len2_4_i, sizeof(AVComplexFloat)*len2_4_i);
+ sst->ifft_p2(sst->ifft_p2_ctx, sst->iside , sst->block + i, sizeof(AVComplexFloat));
+ synchronous_am_demodulationN(sst->iside, sst->icarrier, sst->window_p2, 2*sst->block_size_p2, 3);
+ ff_sdr_decode_rds(sdr, sst, sst->iside);
+
memcpy(sst->block + i, sst->block + 2*carrier19_i, sizeof(AVComplexFloat)*len17_i);
memcpy(sst->block + i + 2*sst->block_size_p2 - len17_i, sst->block + 2*carrier19_i - len17_i, sizeof(AVComplexFloat)*len17_i);
-
apply_deemphasis(sdr, sst->block + i, sst->block_size_p2, sample_rate_p2, + 1);
apply_deemphasis(sdr, sst->block + i + 2*sst->block_size_p2, sst->block_size_p2, sample_rate_p2, - 1);
sst->ifft_p2(sst->ifft_p2_ctx, sst->iside , sst->block + i, sizeof(AVComplexFloat));
@@ -1091,7 +1096,7 @@ static void free_stream(SDRContext *sdr, int stream_index)
av_freep(&sst->iside);
av_freep(&sst->window);
av_freep(&sst->window_p2);
-
+ av_freep(&sst->rds_ring);
}
static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
@@ -1137,9 +1142,12 @@ static int setup_stream(SDRContext *sdr, int stream_index, Station *station)
if (ret < 0)
return ret;
+ sst->rds_ring_size = ceil((2*105 / 1187.5 + 2.0*block_time) * sst->block_size_p2 / block_time);
+
+ sst->rds_ring = av_malloc(sizeof(*sst->rds_ring ) * sst->rds_ring_size);
sst->window_p2 = av_malloc(sizeof(*sst->window_p2)* 2 * sst->block_size_p2);
sst->iside = av_malloc(sizeof(*sst->iside) * 2 * sst->block_size_p2);
- if (!sst->iside || !sst->window_p2)
+ if (!sst->iside || !sst->window_p2 || !sst->rds_ring)
return AVERROR(ENOMEM);
avpriv_kbd_window_init(sst->window_p2, sdr->kbd_alpha, sst->block_size_p2);
diff --git a/libavradio/vissualize.c b/libavradio/vissualize.c
index b27f78f171..d87ca167de 100644
--- a/libavradio/vissualize.c
+++ b/libavradio/vissualize.c
@@ -202,7 +202,7 @@ int ff_sdr_vissualization(SDRContext *sdr, AVStream *st, AVPacket *pkt)
Station *s = station_list[station_index];
double f = s->frequency;
int xmid = 256*( f - sdr->block_center_freq + sdr->sdr_sample_rate/2) * w / sdr->sdr_sample_rate;
- char text[80];
+ char text[100];
int color = s->stream ? 64 : 32;
int size = s->stream ? 181 : 128;
int xd = size, yd = size;
@@ -210,10 +210,17 @@ int ff_sdr_vissualization(SDRContext *sdr, AVStream *st, AVPacket *pkt)
if (!s->in_station_list)
continue;
- snprintf(text, sizeof(text), "%s %f Mhz %d %d %d",
- ff_sdr_modulation_descs[s->modulation].shortname,
+ if (s->name[0]) {
+ snprintf(text, sizeof(text), "%s ", s->name);
+ } else {
+ snprintf(text, sizeof(text), "%s ", ff_sdr_modulation_descs[s->modulation].shortname);
+ }
+ av_strlcatf(text, sizeof(text), "%f Mhz %d %d %d",
f/1000000, (int)s->score, ff_sdr_histogram_score(s), s->timeout);
draw_string(pkt->data, 4*w, text, xmid + 8*yd, 320*h2, xd, yd, color, color, color, w, h);
+ if (s->radiotext[0]) {
+ draw_string(pkt->data, 4*w, s->radiotext, xmid + 8*yd, 320*h2 + 24*yd, xd, yd, color, color, color, w, h);
+ }
}
}
--
2.31.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions
2023-07-10 0:01 [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
` (3 preceding siblings ...)
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 5/5] avradio: RDS support Michael Niedermayer
@ 2023-07-11 20:10 ` Michael Niedermayer
4 siblings, 0 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-07-11 20:10 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 629 bytes --]
On Mon, Jul 10, 2023 at 02:01:00AM +0200, Michael Niedermayer wrote:
> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> ---
> libavradio/sdrdemux.c | 56 ++++++++++++++++++++-----------------------
> 1 file changed, 26 insertions(+), 30 deletions(-)
will apply patchset
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The real ebay dictionary, page 1
"Used only once" - "Some unspecified defect prevented a second use"
"In good condition" - "Can be repaird by experienced expert"
"As is" - "You wouldnt want it even if you were payed for it, if you knew ..."
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-07-11 20:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-10 0:01 [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 2/5] avradio/sdrdemux: shift 19khz carrier differntly Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 3/5] avradio/sdrdemux: only allocare iside and window_p2 when needed Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 4/5] avradio/sdrdemux: factor block_time out Michael Niedermayer
2023-07-10 0:01 ` [FFmpeg-devel] [PATCH 5/5] avradio: RDS support Michael Niedermayer
2023-07-11 20:10 ` [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions Michael Niedermayer
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git