Lutovid 0 30 июля, 2021 Опубликовано 30 июля, 2021 · Жалоба Привет! Возник вопрос по реализации стерео модулятора/демодулятора. На базе примера из 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Самурай 12 8 августа, 2021 Опубликовано 8 августа, 2021 · Жалоба 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 канал, т.е. все как на картинке из описания на ф-ю: А вот потом для режима "Стерео" начинается что-то необъяснимое: вместо вполне разумного для канала 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. ... Заранее извиняюсь, если что-то напутал, все-таки суббота вечер, да еще и август:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lutovid 0 16 августа, 2021 Опубликовано 16 августа, 2021 · Жалоба Ну там действительно должен иметься высокодобротный фильтр пилота, его удобно делать через IIR, но задержки нужно будет конечно учитывать. В общем, можно сделать вывод что функционал не доступен пока, как я понимаю... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться