Перейти к содержанию
    

FMBroadcastModulator вопрос по стерео демодуляции

Привет! Возник вопрос по реализации стерео модулятора/демодулятора. На базе примера из help https://www.mathworks.com/help/comm/ref/comm.fmbroadcastmodulator-system-object.html реализовал коротенький скрипт:

clear all;

    [y,Fs] = audioread('stereo_file.mp3');
%         soundsc(y, Fs)
    AirFs = 441000;
    fmbMod = comm.FMBroadcastModulator('AudioSampleRate',Fs, ...
        'SampleRate',AirFs, 'Stereo', true);
    fmbDemod = comm.FMBroadcastDemodulator( ...
        'AudioSampleRate',Fs, ...
        'SampleRate',AirFs,'PlaySound',true, 'Stereo', true);

    audioData = y(1:AirFs*2, 1:2);
    modData = fmbMod(audioData);
    demodData = fmbDemod(modData);

В результате выполнения проигрывается моно сигнал(взял запись теста стереоэффекта с поочередным появлением звука то в одном канале, то в другом). Если убрать комментарий и проиграть soundsc(y, Fs), то стереоэффект есть.

Еще информация - в исходном стереосигнале есть большая разница между сигналами R и L, после демодуляции разница между каналами на 4 порядка ниже.

Если использовать пример из хелпа, то он не репрезентативный(пример с RBDS) так как там хоть и стоит флаг stereo, но в исходном сигнале нет стереоэффекта(rbds_capture_47500.wav)

Так же пробовал повторить в симулинке - там такая же проблема.

Более того если построить спектр от моделированного сигнала, я ожидал увидеть нечто похожее на картинку из help - то есть L+R, L-R и пилот на 19кГц, я же такой картины не вижу, то есть явно есть какая-то проблема с модуляцией.

Помогите пожалуйста разобраться.

Вот тут этот же вопрос задал, но может на этом форуме мне быстрее помогут. Извините за копипаст

https://hub.exponenta.ru/quest/fmbroadcastmodulator-vopros-po-stereo-demodulyatsii680

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

30.07.2021 в 17:36, Lutovid сказал:

Помогите пожалуйста разобраться.

К сожалению, сейчас нет возможности самому все проверить в Матлабе, но есть возможность проанализировать исходники ф-и comm.FMBroadcastDemodulator...  Всю ф-ю приводить не буду, только самое интересное.

Итак, вот код, непосредственно отвечающий за основной функционал:

function [yAudio, yRBDS] = stepImpl(obj,u)
    x = complex(u);           % Complex inflation
    yDemod = obj.pFMDemod(x); % FM Demodulation

    % Intermediate rate conversion to 228 kHz
    if ~obj.pLegacyMode || obj.RBDS
      yDemodIntermediate228 = obj.pRateConv228(yDemod);
    end

    if obj.pLegacyMode
      % Intermediate rate conversion to 152 kHz (legacy mode) for backwards
      % compatibility
      yDemodIntermediate152 = obj.pRateConv152(yDemod);
    end

    % Construct needed reference tones at 19 kHz, 38 kHz, 57 kHz
    if obj.Stereo || obj.RBDS

      % Get 19 kHz pilot tone at Fs = 228 kHz
      if ~obj.pLegacyMode || obj.RBDS
        pilotSin19_228 = obj.pBandPass19_228(yDemodIntermediate228);
      end
      if obj.pLegacyMode
        pilotSin19_152 = obj.pBandPass19_152(yDemodIntermediate152);
      end
      
      if obj.pLegacyMode
        % Construct 38 kHz pilot tone from the 19 kHz pilot tone:
        refToneSin38  = obj.getRefTone152(pilotSin19_152);
        if obj.RBDS
          % Construct 57 kHz pilot tone from the 19 kHz pilot tone:
          [~, refToneCos57] = obj.getRefTones228(pilotSin19_228);
        end
      else
        % Construct 38 and 57 kHz pilot tone from 19 kHz pilot tone:
        [refToneSin38 , refToneCos57] = obj.getRefTones228(pilotSin19_228);
      end
    end
   
    %%%%%% Основной алгоритм декодирования и восстановления стерео-сигнала: %%%%%%%%%%
      
    % Low pass filter to isolate L+R (Mono):
    if obj.pLegacyMode
      leftPlusRight = obj.pLowPass(yDemodIntermediate152);
    else
      leftPlusRight = obj.pLowPass(yDemodIntermediate228);
    end

    if obj.Stereo
      % coherent AM demodulation with 38 kHz carrier:
      leftMinusRight = refToneSin38 .* obj.pBandPass38(leftPlusRight);
      y1 = [leftPlusRight, leftMinusRight]; % [L+R, L-R]
      % Output [L R]:
      yAudioIntermediate = [y1(:, 1)+y1(:, 2), y1(:, 1)-y1(:, 2)];

    else % Mono (L+R)
      yAudioIntermediate = leftPlusRight;
    end

    if obj.RBDS
     ...
    end

    % De-emphasis
    yFilt =  obj.pDeEmphFilter(yAudioIntermediate);
    % Rate conversion from intermediate sample rate (228/152 kHz) to AudioSampleRate
    yAudio = obj.pAudioRateConv(yFilt);

    % Play using audio device
    if obj.PlaySound
      obj.pAudio(yAudio);
    end
  end

Все достаточно прозрачно, единственный нюанс, что после ЧМ-демодулятора, частота дискретизации понижается до промежуточной частоты 152кГц или 228кГц (в зависимости от каких-то мутных условий), на которой и идет вся дальнейшая обработка. Частоты удобны тем, что они кратны 19кГц, 38кГц и 57кГц, которые вовсю используются для стерео-кодирования.

 

Дальше полосовым фильтром выделяется пилотный тон 19кГц, из которого формируются опорные частоты 38 и 57 кГц.

Потом ФНЧ с частотой среза 15кГц выделяет L+R канал, т.е. все как на картинке из описания на ф-ю:

mpx_decoder.png

А вот потом для режима "Стерео" начинается что-то необъяснимое: вместо вполне разумного для канала L-R маршрута:

 

вх.сигнал -> ПФ 38кГц -> умножение на несущую -> ФНЧ 15кГц,

 

в коде лично я вижу лютый бред: через ПФ на 38кГц пропускается не входной сигнал, а сигнал, полученный после ФНЧ на 15кГц, т.е канал L+R, в котором после этих самых 15кГц все задавлено в ноль!:))) На этом фоне упоминать, что для канала L-R забыли ФНЧ на 15кГц, наверно уже нет смысла...:)

 

Посчитав, что этого недостаточно, разработчики данной ф-и решили подстраховаться и разбросали по коду еще немного сюрпризов:

1. В коде в разнобой используются как FIR, так и IIR фильтры.

2. Задержки FIR фильтров никак не компенсируются и не учитываются.

3. Разумеется, задержки IIR фильтров тоже считаются нулевыми.

4. ФНЧ на 15кГц для канала L+R сделан FIR-ом, а вот ПФ на 38кГц для канала L-R уже IIR! Ну и разумеется, см. пп.2 и пп.3:)))

5. Пилотный тон 19кГц для когерентной демодуляции L-R канала выделяется IIR фильтром! И да, см. пп.3:)

6. Все IIR фильтры сделаны 50-ого порядка!!! Но это ладно, рука у человека дрогнула, бывает, но они захардкодены в виде коэффициентов, причем все коэффициенты имеют всего лишь 4 знака после запятой, вот примерно вот так: 0.9997, 0.9998, 0.9998 0.9999... И это для IIR 50-ого порядка, пусть даже разбитого на секции 2-ого порядка???:)))

7. ...

 

Заранее извиняюсь, если что-то напутал, все-таки суббота вечер, да еще и август:)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну там действительно должен иметься высокодобротный фильтр пилота, его удобно делать через IIR, но задержки нужно будет конечно учитывать. В общем, можно сделать вывод что функционал не доступен пока, как я понимаю...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...