From patchwork Mon Jul 10 00:01:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 42571 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6da1:b0:131:a7d0:bc6d with SMTP id gl33csp360441pzb; Sun, 9 Jul 2023 17:01:17 -0700 (PDT) X-Google-Smtp-Source: APBJJlGRno3DbTJDtiQBFzgXinS5FIVod5FD2nTCrVhE3U4SUwu60ghTTgr5hemlMOmtZ1wc0p/z X-Received: by 2002:a2e:a314:0:b0:2b4:6d59:7863 with SMTP id l20-20020a2ea314000000b002b46d597863mr8612659lje.25.1688947277363; Sun, 09 Jul 2023 17:01:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688947277; cv=none; d=google.com; s=arc-20160816; b=D9GXQl1jPTqIB7J4ooNFYlDtKsUuIGj9pJgCeWtbyxDvvJeqlabU2RlOSg04T6dkAI yWX6cD7LFSxDp5tX5Enf+/+1vtL0vU2A/4Gm3OiHzeLC/tI0IXD3yImUE68Sdjsd4pVJ CV6IKGvBEX6NGyBhPwPFJm8A53deN3M5hd+P7P6fviT2Via0P+Cqp96dbjnMQGGgtug8 bYxHatJZMGiWBKkt05eaZPvTv+SrW74i2EvmXQAwJjjBlSMGBXORoG5hXYwTqP31GIdz 5bRz+BMgq5yTNRSpCSHU90fXlOwB2hPvnYfwP9bRWmdj5PQ2++HI7CiloBzRhmNRrSMl R+cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:message-id:date:to:from :delivered-to; bh=acjA108rYhZ6REP5oPysFjoPuuZryavN8YNYtArYCsk=; fh=YYwLYmpaV0Fpw/rxmSKNRLS2XzDkAlGbHATiKOPtZrY=; b=kclBpP4C9trr7bJF1Lfs5bMshzwUO1CsXZf3ziLKOlgxKHPzeJJjrb3VvAYnCJppET ERHaTw7dbE3OcNyol+cYfCYZ02tqrd4NBp8ThGY//KLPXm5UyUSO08Xx8LSfyWF/jP7c n/FvmXZVyUzuTnseNr+qT2exMzQcyghdHrnEcSE+tKY4sz9EsApNDt/INo29C0W5kUc8 7F7qe0MJBIo4QCVKmuDqQPIoSMpbBD/NFKFgkk5NFMrn3ghmanD72AEKlxx6qiaLnYiQ lxLnAonfBa67yBUtBSLbiJ6ztRFKAW+pOhl1qzPmic0bBcrXGnzI7Dh3uS2ZLfd6sS65 l0Qg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id lc1-20020a170906dfe100b00992cef85664si7485849ejc.139.2023.07.09.17.01.16; Sun, 09 Jul 2023 17:01:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7919568C580; Mon, 10 Jul 2023 03:01:13 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9795368C4CF for ; Mon, 10 Jul 2023 03:01:06 +0300 (EEST) X-GND-Sasl: michael@niedermayer.cc Received: by mail.gandi.net (Postfix) with ESMTPSA id C991920005 for ; Mon, 10 Jul 2023 00:01:05 +0000 (UTC) From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Mon, 10 Jul 2023 02:01:00 +0200 Message-Id: <20230710000104.3597392-1-michael@niedermayer.cc> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/5] avradio/sdrdemux: Factorize synchronous_am_demodulation* functions X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: FCN6u2uyTcbN Signed-off-by: Michael Niedermayer --- 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 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 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); From patchwork Mon Jul 10 00:01:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 42570 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6da1:b0:131:a7d0:bc6d with SMTP id gl33csp360517pzb; Sun, 9 Jul 2023 17:01:27 -0700 (PDT) X-Google-Smtp-Source: APBJJlGXtGVcDok9aQAIlKHXJVsxSC4cS43PNG2HTLQKID0/A8l+wpsse/h2rKXCxXi5uzgULBRl X-Received: by 2002:a05:651c:120c:b0:2b5:80e0:f18e with SMTP id i12-20020a05651c120c00b002b580e0f18emr8444372lja.3.1688947287171; Sun, 09 Jul 2023 17:01:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688947287; cv=none; d=google.com; s=arc-20160816; b=LJCMOWhzaor6C6pRqT+D6t1Xrq5yYI8n0tKFCy1J66cx0QSqAZT7yOgh2TiowrZeV5 4vYCIsOYhCgIt5CJ7ItMZUJOTjbE0BrQwBKWtEeBIS6kXzd79knag3ljhh0WCOV/GjYL cKySIx7cphp6DnVghNLzWE2VsGwVuXXYUOkrLOGQbVDKWWqKHOr8H9THMQthTae/kySn jxhqCFMez65WyWnsWBMM/gnU0rRq9DTynJi956fXKB8iYRJJy+lctJzl9O5By5wglVNc aiG3g6hsW0okXyfiFnuCBoBsyGpWUxZGWKT8awfTUku8ZBGCKTVgPHHPlGpm/Upfo4K0 s4ig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=9AIsISo9Z/txye1UAgV3I+/XTcFSE5DMtbK7KEkw5qk=; fh=YYwLYmpaV0Fpw/rxmSKNRLS2XzDkAlGbHATiKOPtZrY=; b=jnjWpBjsUFdgOJYgUx9qTo/BsLIWlbrHz86/gCUA+g9WT2WTGh2SxFv0xn6OHypyAE eEJWIQX/LStgFfgUtia6vHb48FDgylXJcR92kWegFGI/lKUEo8A81tGY/PqpHHjgc1cf f+5pu8XLkUeCPcc1VHAVtXgF5VkjU45/8jLIkeZ5gCsw7u4J5T0S/jmxokdv0SO4gSTc YPCSDjXS3rLrDCItWSt6S3BCAFXg1t0DmiB51Ixx1dnEyn4pLlB8MpATDrZJ2zdtPbxl ygnWpWGXaW99a33rd7NvsYvAyseK3gTeOndmH/5oebBgAYoKMCKdzSr5W2sG/shE/m5g IC3Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id qn4-20020a170907210400b0099317635beesi6575542ejb.470.2023.07.09.17.01.26; Sun, 09 Jul 2023 17:01:27 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8806368C65B; Mon, 10 Jul 2023 03:01:15 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 173E968C580 for ; Mon, 10 Jul 2023 03:01:08 +0300 (EEST) X-GND-Sasl: michael@niedermayer.cc Received: by mail.gandi.net (Postfix) with ESMTPSA id 460EE60002 for ; Mon, 10 Jul 2023 00:01:07 +0000 (UTC) From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Mon, 10 Jul 2023 02:01:01 +0200 Message-Id: <20230710000104.3597392-2-michael@niedermayer.cc> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230710000104.3597392-1-michael@niedermayer.cc> References: <20230710000104.3597392-1-michael@niedermayer.cc> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/5] avradio/sdrdemux: shift 19khz carrier differntly X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 1RnfrSrDCRZS This simplifies the following commits Signed-off-by: Michael Niedermayer --- 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); } From patchwork Mon Jul 10 00:01:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 42572 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6da1:b0:131:a7d0:bc6d with SMTP id gl33csp360583pzb; Sun, 9 Jul 2023 17:01:35 -0700 (PDT) X-Google-Smtp-Source: APBJJlFXFyP+3ZNPYohsN0J9VzH1LAjroky0X3qXf9hVpWUTAlrtkQbCu4sK0BaQZQztGlt0JCGr X-Received: by 2002:a05:6512:3122:b0:4f8:6b57:87f9 with SMTP id p2-20020a056512312200b004f86b5787f9mr8122996lfd.22.1688947295644; Sun, 09 Jul 2023 17:01:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688947295; cv=none; d=google.com; s=arc-20160816; b=XluS7TxOKfBbHBsf7fSwk/ncIMa+kyyXziRtiVTvcZqbbDRp6cvU8pudHXQsh3aIn/ PnAQPCYr5XtBMUIaDAIzjkHm9tR2cRIDsjHajcIjeELlY6Cr9wpivzEl4mXWH3ypN/zU tCuQJ1XDnn1qlRg0LkbcRX7qnyqDbIVfry4GUktGq3Se/HJkfd8Bkm9h1MWAzNrStEXb 1NRMdzFimfagCFAnBkOYVeX5FRt0u9ShH3tKWMDjQF2fso7BfNrnnHM8RVobDR1smi2S 0A+Q+kAeNU4+Gy/QQHbkltU3hrfKffGhCWtre+q4Y9Ugkgy+L/owU5jLhHqjCl6qVtJC dkXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=1OXJLm/KkNGSlAEd69bAZ3V+bgFa5IHwWXLCWhMotQE=; fh=YYwLYmpaV0Fpw/rxmSKNRLS2XzDkAlGbHATiKOPtZrY=; b=CDyNFd5R8M9YrCSIkrisp3CN/ErQaDz+C1vzXJZrdb/D4tHyaCw5pYKKTNBKCz9icA dlOthAFX1waRrZMez9/5P/eppF5/UY4gVBtH0A7rBTdWjxxDRUBA5Ec1TBnX/g49eqkT z5gB5Lf4ET1j+eilO4QZUwOFNOqIaprnEBM2XRrWIa+Vfdt0DBprJzUAZdHCA7pZNwLY KjgBAX19+b70c8zBlHeJ31J3UBJZuarzS1m7wuZ16iEpusItYP1HpIgkRmnVM8SDgb94 BveThel5fZg/M1zeCgImlk/jctUwUKmrrc2mnmDSXMoIs1cXQ0UN0JrJwOlSNypSUEIs jBeQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id lc1-20020a170906dfe100b00992cef85664si7486851ejc.139.2023.07.09.17.01.35; Sun, 09 Jul 2023 17:01:35 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A363068C66C; Mon, 10 Jul 2023 03:01:16 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6126768C5E1 for ; Mon, 10 Jul 2023 03:01:09 +0300 (EEST) X-GND-Sasl: michael@niedermayer.cc Received: by mail.gandi.net (Postfix) with ESMTPSA id 9F200240007 for ; Mon, 10 Jul 2023 00:01:08 +0000 (UTC) From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Mon, 10 Jul 2023 02:01:02 +0200 Message-Id: <20230710000104.3597392-3-michael@niedermayer.cc> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230710000104.3597392-1-michael@niedermayer.cc> References: <20230710000104.3597392-1-michael@niedermayer.cc> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/5] avradio/sdrdemux: only allocare iside and window_p2 when needed X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: nAaNJ0qo5s6Q Signed-off-by: Michael Niedermayer --- 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; } From patchwork Mon Jul 10 00:01:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 42573 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6da1:b0:131:a7d0:bc6d with SMTP id gl33csp360661pzb; Sun, 9 Jul 2023 17:01:44 -0700 (PDT) X-Google-Smtp-Source: APBJJlG/iookhp8Fp2EcMRWZQPq1dkkMFy9Cd9qFXe1z1ZxYQ+oXsUOaVeWrRr3JlhjY0FiXK2WD X-Received: by 2002:a2e:99c8:0:b0:2b6:d48a:5dc3 with SMTP id l8-20020a2e99c8000000b002b6d48a5dc3mr7790814ljj.39.1688947304085; Sun, 09 Jul 2023 17:01:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688947304; cv=none; d=google.com; s=arc-20160816; b=b8mGUbHoXbvL3D0O088yfBooYUeacmUFkbY4RlknYnQfWIKcUr2zbMhHSr3xpu/z6V Hf4egsikAL/Z+bjtTRgVjW3Xw5R4kkl4LIuz9sDJgpIZSmDfymbGYHFv66ifDSnRDV4R VdfLxcgBl5iL06278XGx4FAoF1dd35+n09NYH3ltLkPT4Rwo18qoXUUhIMc22VaFU2P5 DQ3M4D33o3Q4ZU9/oFUWW7V13FP8ZSer+0NiW5QyY7WOUIZms3tmTF4dMildmsGc1PDh 2eExUtUgT32UNpCVu1jzSLzEA7gQM+u8g8ue0lj5sB22g/2/65FIGWIc9EoH5B6gQ8w0 o2AQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=wp2Rhs3sqWYWzGUXa1SMD3eZ8rRgKGbAQhSduvAEZLo=; fh=YYwLYmpaV0Fpw/rxmSKNRLS2XzDkAlGbHATiKOPtZrY=; b=fwkX7MK//GojmaJd0nFM5o9WPEJUvBX3/2H1qOcwosJRmtscj7XPHcktJodCxRenRH M9lZMsXF+tkcAjigf4EteBFGHP6Vqywjy8p1iH3uSmjqZsjOJPVJ57g2Mi3ozTo/Ajow iV6mL6fpLzfD66YWA4d0/RUHECGWQpYGLIy4KgkKPBjVgHqHSrEu+TfTyVCRx4ipN+j6 8iNcduBNBKA9JaDUBuxv8kYA0CTP2zu4GBl7vNLJBwhq80gB0JudZ4UhcaMn2LyhmYhS +EbaOULwJHfZ02KR6Xi0ld8KjETOM0YUoL3uN3WRKqLg0gRw+XuLOHHRHIUqhIo90v2V QjLA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id la20-20020a170906ad9400b00992ee199abdsi6979391ejb.276.2023.07.09.17.01.43; Sun, 09 Jul 2023 17:01:44 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A986068C653; Mon, 10 Jul 2023 03:01:17 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0A0C568C644 for ; Mon, 10 Jul 2023 03:01:09 +0300 (EEST) X-GND-Sasl: michael@niedermayer.cc Received: by mail.gandi.net (Postfix) with ESMTPSA id 6C77E20004 for ; Mon, 10 Jul 2023 00:01:09 +0000 (UTC) From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Mon, 10 Jul 2023 02:01:03 +0200 Message-Id: <20230710000104.3597392-4-michael@niedermayer.cc> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230710000104.3597392-1-michael@niedermayer.cc> References: <20230710000104.3597392-1-michael@niedermayer.cc> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/5] avradio/sdrdemux: factor block_time out X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: m3Ey0nOpQ+bh Signed-off-by: Michael Niedermayer --- 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) From patchwork Mon Jul 10 00:01:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 42574 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6da1:b0:131:a7d0:bc6d with SMTP id gl33csp360730pzb; Sun, 9 Jul 2023 17:01:52 -0700 (PDT) X-Google-Smtp-Source: APBJJlHsMXIWdQQoXdWothKfj2UkA4h0qOmipkm/abVmpk5uDV8AmS650lWnHTAmy/xFHOmaYXG+ X-Received: by 2002:adf:db44:0:b0:314:3fc0:ba82 with SMTP id f4-20020adfdb44000000b003143fc0ba82mr9651771wrj.37.1688947312606; Sun, 09 Jul 2023 17:01:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688947312; cv=none; d=google.com; s=arc-20160816; b=hYPFxhMbzLF60XDV+gZ62DgYkAPj2Ty+2xp8DLJAJzGTEQsq3e4mUEwRVWOaxBhfIp eNMeTXNQ0JU/+5nyXiG/+3Il+QJVDz1yno+UBN2ubsVzMz5gGrds8BBzZ26jlvkqufob kddZO0bhZcGUsdemF5zf8J8gt0Haee3xjnAtag2jqwr/uWX1C8dXlJbUUv2qqHrnZiId PukHvdGOLOZ4VU7yyQsWPAQUGgss1K6+DifZ1eYJgLfRB/uDwE15FwnfOhAUpZhOLhXI qj8MnoQSCG+MD5V5soAbA4+54p2SVyTXqaB4nfj/95IS0NaOHMW4jiJT+eWAs6Qwia5v vh/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=C5CC7Hd1fpnGfNEBpToH4jCOzh9Ae4DWbiCC/8EJmdU=; fh=YYwLYmpaV0Fpw/rxmSKNRLS2XzDkAlGbHATiKOPtZrY=; b=sD0JLxsrdS0gJaey5OgXtpnA/1OalC2i+g7AXBdMN6MQgXnp0tFn/XlEDtcLAyDHEs 34oq3j9LGxEhhLw6WPxv2EcIIr4Vzr1LrpAynSpOs6kmRyKPo7Rh4gS4hkDA5i+Bc9l/ RedSeYx/C8RdlyJMX1ETMaUTeBdpLLMmkzHQniozo7GRGF9g/GWwaI2LsXkrulXVzdds 7aqUyR1QCoZyY6R4orLOCH/NFJlPvv5/mFnrOA7Kns48QH653EcfvPhWp7UbNBpY3RAd fPh4VMi1CQWUrHU5AwdKpX2MEnIUg4UV9T9EkcEdnsrM0S2+ZZiMmGSGXxnDf5LaTnVO C8bQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id s3-20020a056402164300b0051e24cc65c0si4816569edx.669.2023.07.09.17.01.52; Sun, 09 Jul 2023 17:01:52 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BB1D668C696; Mon, 10 Jul 2023 03:01:18 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5C0F468C671 for ; Mon, 10 Jul 2023 03:01:11 +0300 (EEST) X-GND-Sasl: michael@niedermayer.cc Received: by mail.gandi.net (Postfix) with ESMTPSA id 93B30E0003 for ; Mon, 10 Jul 2023 00:01:10 +0000 (UTC) From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Mon, 10 Jul 2023 02:01:04 +0200 Message-Id: <20230710000104.3597392-5-michael@niedermayer.cc> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230710000104.3597392-1-michael@niedermayer.cc> References: <20230710000104.3597392-1-michael@niedermayer.cc> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/5] avradio: RDS support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: wUPNatE1FcRz Signed-off-by: Michael Niedermayer --- 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 +#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<> 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); + } } }