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

gegel

Свой
  • Постов

    425
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

1 Подписчик

Информация о gegel

  • Звание
    Местный
    Местный

Старые поля

  • skype
    Array

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Посетители профиля

2 215 просмотров профиля
  1. Посмотрите в моем проекте в коде MELPE: https://github.com/gegel/jackpair/tree/master/Src/melpe_old Сделан на основе рефференс-кода MELPE-1200, адаптированного мною к Cortex-M4 realtime путем использования ETSI-математики из dspfns.h (там не все совпадало, пришлось кое-что фиксить). Возьмите только npp.c и зависимости. Реализован весьма эффективный AT&T speech enhancement/noise pre-processing алгоритм (более подробные ссылки в статье: http://torfone.org/download/MELPe_Algorithm.pdf). Также я добавил VAD, основа для этого в коде уже заложена. Можно подправить параметры сработки по вашим требованиям, там все понятно в коде.
  2. Да, сдвиги все знаковые (в C-коде они и есть знаковые по умолчанию), т.е. эквивалентно умножению,делению на 2. Просто сдвиги в ARM архитектуре входят в сами команды. Хотя, наверное, компилятор и сам это оптимизирует, можно просто умножать/делить на 2 в исходнике. Я не имел ввиду короткий турбокод, т.е. длину всего фрейма. Фрейм для турбокода вполне может быть под тысячу бит. Но элементарный блочник (8,4) должен очень легко декодироваться жестко, т.к. это надо будет делать на каждом поступившем сэмпле и усреднять суммарное к-во ошибок во всем фрейме по каждому лагу. Лучшим есть табличный вариант, без всяких циклов. Т.е. декодируем дважды: - предварительные жесткие решения по каждому блоку (8,4) в фрейме по получению каждого сэмпла - на этапе синхронизации для получения к-ва ошибок по каждому лагу -в турбокоде с учетом метрик заданное число итераций - одни раз на фрейм, для получения полезных данных
  3. Таки не вписываются, как я и чувствовал. Внимательно перепроверил код и нашел свою тупейшую ошибку: контрольные биты у меня передаются в "хвосте" фрейма, причем в обратном порядке (для обострения корреляции на границу фрейма), а я брал их из массива по прямому индексу. Конечно же, получая "чужой" контрольный бит, алгоритм только ухудшал ситуацию. Последующий турбо-декодер корректировал как мог, но все было печально. Исправил, теперь все работает просто изумительно! Всем спасибо, и извините за вынос мозга из-за моей невнимательности. Итого: 1. Если передавать два бита и третий - контрольный (XOR двух информационных), то, используя метрики, можно успешно корректировать как жесткие решения информационных бит, так и их метрики (мягкий выход). 2. Для коррекции метрики можно к канальной метрике каждого бита добавить внешнюю, полученную из метрик двух остальных бит с помощью формулы: Lextr(u XOR p) = sign(u)*sign(p)*min(|u|,|p|) 3. После алгебраических преобразований получим эквивалентную формулу: l0 = ( k0<<1 + abs(kc-k1) - abs(kc+k1) ) >> 1 l1 = ( k1<<1 + abs(kc-k0) - abs(kc+k0) ) >> 1 Она возвращает тот же результат, но кажется менее ресурсозатратной для ARM-процессора (не содержит ветвления в min). Хотя надо смотреть по коду, генерируемому компилятором, а лучше замерять к-во тактов. Для плисины вообще не в курсе, возможно, первый вариант проще будет. Для чего мне это надо: 1. Как верно заметили на форуме, контрольные биты лучше выбросить (сузить полосу) или использовать в турбо-кодеке. 2. Но они у меня выполняют и другую функцию: обеспечивают синхронизацию. Фрейм разбивается на пары бит, для каждой рассчитывается контрольный бит, они собираются вместе и передаются в виде "хвоста" в конце фрейма, в порядке, обратном к порядку передачи информационных бит. Это дает возможность с точностью до сэмпла определить (и подстраивать на лету) лаг, указывающий на конец фрейма. 3. Синхронизация использует предварительные жесткие решения битов, что позволяет с минимальными вычислительными затратами, используя сдвиговые регистры, вычислять количество ошибок четности всех контрольных бит фрейма для каждого возможного лага (вновь поступившего сэмпла). Усреднение этого значения для 8 последних фремов позволяет после каждого принятого фрейма выбирать лучший лаг. Это прекрасно работает, обеспечивая стабильную синхронизацию до четко подсчитанного уровня BER, ниже которого уже нет смысла демодулировать. 4. Но это не идеально. Лучше было бы использовать свой турбокод, работающи с короткими с элементарными кодами типа (7,4) и научиться столь же просто выполнять синхронизацию на лету, используя малозатратное жесткое декодирование этих элементарных кодов в предварительных жестких решениях (как в "прямом" части, так и после интерливера). На досуге займусь. Еще раз всем спасибо за помощь, главное - требуемый результат получен!
  4. Но данные результаты полностью совпадают с моими! Инвертируем ваши метрики, чтобы перейти к моему правилу кодирования 0/1 -> -1/+1: -4.0 -1.0 1.5 Подставим в мои формулы выше: llr0 = -8 +abs(-1-1.5) -abs(-1+1.5)=-6 llr1= -2+abs(-4-1.5)-abs(-4+1.5)=1 Если пропорционально уменьшить все метрики вдвое и опять вернуться к правилу кодирования из статьи, то получим ваши 3.0 -0.5. Но, к сожалению, это работает хуже в сравнении с простым инвертированием наименьшей метрики в тройке бит. Модель - канал с Гауссовским шумом, добавляемым после BPSK (это другой проект, он не имеет отношения к AMR-сжатым каналам). C МАХ-log результат чуть лучше, реализовано так: после каждого взятия abs, если результат меньше максимального индекса якобиановской таблицы, добавляю значение из таблицы по индексу к результату. А алгебраической разницы между вариантами с МАХ и abs нет. По модели канал ответил, а вот с жесткими решениями интересно: при жесткой коррекции бита при несовпадении КС и тупо инверсии LLR к-во жестких битовых ошибок получается почти вдвое больше, чем после мягкой коррекции, описанной выше. А результат после турбо-декодера гораздо лучше. Эти данные не вписываются в теорию, поэтому не исключаю, что я где-то тупо ошибся в С-коде, все внимательно перепроверю еще раз. Почему же? Если речь идет о моем проекте модема для AMR-сжатого канала (https://github.com/gegel/jackpair/blob/master/Src/mdm/plsmdm.c), то там много чего взято с eCall (вейвформы пульсов в модуляторе, процедуры подсчета LLR в демодуляторе и т.д.). Разница лишь в том, что eСall работает с пакетами и обеспечивает гарантированную доставку, а у меня поток с допустимым уровнем ошибок. Поэтому полностью отличаются механизмы синхронизации. На самом деле это импульный модем, предложенный Кондозом (https://github.com/gegel/jackpair/blob/master/docs/Kondoz_modem.pdf), с дополнениями из дипломной работы Andreas Tyrberg (https://github.com/gegel/jackpair/blob/master/docs/Turtborg_PulseModem.pdf) + моя синхронизация. Битрейт - 800bps. Символ длиной в 24 8KHz PCM сэмпла содержит один пульс, занимающий 3 сэмпла в 4-х возможных позициях, и кодируется 3-мя битам: два определяют позицию, а третий - полярность. Это соответствует алгебраической кодовой таблице AMR-кодека, и в тесте дает хорошие результаты вплоть до AMR режима 6.75kbps. И это работает гораздо лучше, чем вариант BPSK. который я вам отсылал в прошлом году. Что касается речевого шифратора для аналоговых УКВ радио, то сейчас реализован вариант на новом бюджетном Cortex M4 Nuvoton M481LIDAE (192 MHz, 160K RAM, 512KROM), и там используется BPSK модем 1200 bps + куча всяких рюшек для быстрой синхро и борьбы с уходом частоты во время замираний (быстрая и медленная синхро, прогнозирование ухода и поиск лага с учетом вероятности как близости к прогнозируемому значению) и т.п. На практике работает изумительно: жалобы обычно на звучание MELPE (тут ничего не поделаешь), но не на модем. Обмен 32 -байтными шифроключами в начале сеанса связи, защищенными Голеем, надежно выполняется за 1-2 сек в каждую сторону даже в очень тяжелых условиях.
  5. Так вот в том и проблема, что теоретически неверно, но на практике работает лучше, чем то, что верно. Но всему есть причина, буду копать глубже. Формулы получил, рассуждая следующим образом (с самого начала): четыре верных варианта комбинации двух информационных и контрольного бита и их общие корреляционные коэффициенты как сумма коэффициентов индивидуальных бит, взятая с соответствующим знаком: k0 k1 kc 0 0 0 a=-k0-k1-kc 0 1 1 b=-k0+k1+kc 1 0 1 c=k0-k1+kc 1 1 0 d=k0+k1-kc Если искомый бит входит в комбинацию, добавляем его в положительную вероятность, если не входит, то в отрицательную. Самой грубым вариантом сложения вероятностей есть MAX, т.е. выбор большего значения из двух с учетом знака: p0 = MAX(c,d) n0 = MAX(a,b) llr0 = p0-n0 p1 = MAX(b,d) n0 = MAX(a,c) llr1 = p1-n1 Распишем, например, для бита 0: p0 = k0-k1+kc или k0+k1-kc (большее). Вынесем k0: k0-(k1-kc) или k0+(k1-kc) n0 = -k0-k1-kc или -k0+k1+kc (большее). Вынесем -k0: -k0-(k1+kc) или -k0+(k1+kc) Как видно, выражения справа отличаются знаком части в скобках. Поэтому максимальным из двух будет то, у которого велична в скобках максимальная. А так как она отличается знаком, то, соответственно, максимальным будет то выражение, у которого величина в скобках положительная. (функция MAX сравнивает с учетом знака!). Т.е. можно переписать так: p0 = k0+abs(k1-kc) n0=-k0+abs(k1+kc), откуда LLR0 = p0-n0 = 2*k0+abs(k1-kc)-abs(k1+kc) Аналогично для LLR1. Возможно, где-то я и ошибся, может, поправят добрые люди... Скажите - как, проверю :) Коррелирую, конечно, не с наработанным паттерном сигнала, а с чистым синусом (для когерентной BPSK). Т.к. синус симметричный, то все сводится к k = s0+2*s1+s2-s3-2*s4-s5 ( у меня для облегчения жизни используется точно 6 АЦП сэмплов на период несущей, и они кодируют один бит). Именно это k и используется в формулах выше. Это верно?
  6. Спасибо, просмотрел. Но, как Вы верно заметили в предыдущем посту, у меня предполагалось что-то типа каскадного кода. На сколько я понял, статья относится к вашему замечанию о возможности уточнить метрику пары в самом турбодекодере, и для этого нужно немного поправить калькулятор расчета метрик в декодере. Исходники турбо-декодера есть, но нету соответствующего скилла и, главное, времени его нарабатывать. Поэтому выбор и пал на каскадный вариант с готовым турбокодом. Но интересно другое: базируясь на моих вышеприведенных рассуждениях и школьной арифметике, вывел простые формулы получения LLR информационных бит (без MAX-log аппроксимации, используя максимальное значение): LLR0 = 2*k0+abs(k1-kc)-abs(k1+kc); LLR1 = 2*k1+abs(k2-kc)-abs(k2+kc); На первый взгляд выглядит идеально, возвращая скорректированные LLR при ошибке четности, и нулевые в неопределенной ситуации (когда две входящие метрики совпадают при ошибке четности). Но на практике при подаче на турбодекодер дает результат хуже, чем способ, предложенный в самом начале Grizzly: просто инвертировать метрику информационного бита при ошибке четности. Так что в моих рассуждениях где-то фундаментальная ошибка.
  7. Обдумал посты Милливольта о подсчете 4-х суммарных корреляционных коэффициентов для возможных комбинаций бит с учетом XOR, и des00 о передачей доверия. Получается где-то так: k0, k1, kс - входные корреляционные коэффициенты для двух информационных и контрольного битов LLR0, LLR1 - искомые выходные LLR двух информационных битов Возможные варианты комбинаций битов с учетом XOR и их суммарные коэффициенты (это не совсем идеально, как в варианте с полной корреляцией в предложении Милливольта, но по сути то же): 00 0 a=-k0-k1-kc 10 1 b=k0-k1+kc 01 1 c=-k0+k1+kc 11 0 d=k0+k1-kc Позитивные (бит входит в комбинацию) и негативные (бит не входит в комбинацию) вероятности для информационных битов 0 и 1: p1 = MAX(c,d) n1 = MAX(a,b) p0 = MAX(b,d) n0 = MAX(a,c) где MAX - функция Max-log апроксимации через Якобиановский логарифм (или в крайнем случае просто максимальное значение из двух аргументов с учетом знака) LLR0 = p0-n0 LLR1 = p1-n1 Вопрос больше к des00: вы это имели в виду?
  8. Это именно то, что мне нужно. Но, если можно, дайте ссылку или скажите, как это сделать в данном конкретном случае (с тремя битами). Да, синхробит является xor двух предыдущих. При передаче все синхробиты собираются в "хвост" и передаются в конце фрейма (в обратном порядке для обострения корреляции). Этот хвост предсказуем на основании предыдущих бит фрейма. Поэтому по нему происходит выравнивание на границу фрейма, и на границу самого бита (в сэмплах). Используются сдвиговые регистры предварительных жестких решений, с подсчетом и усреднением по каждому лагу (при приеме каждого сэмпла). Наилучший лаг указывает на границу бита и фрейма с точностью до сэмпла. Но это уже детали реализации, более подробно можно посмотреть в коде на гитхабе по ссылке выше. Да, это действительно было бы оптимально, но ресурсы как раз не позволяют, т.к. корреляцию надо проводить после приема каждого сэмпла в фрейме. Поэтому пришлось довольствоваться предварительными жесткими решениями и тогда все делается быстро с помощью сдвиговых регистров. Т.к. вес каждого лага усредняется, то идеальности в системе синхронизации и не требуется - не на первом, так на пятом-десятом фрейме будет найден оптимальный лаг (чем больше шум, тем позже). Детектирование битов реализовано отдельно, оно использует точную корреляцию, но выполняется только в определенных лагах (на верных границах битов).
  9. Контрольные биты в моем модеме - это синхровставка для синхронизации на лету. Я совместил функционал синхровставки с контрольными битами специально для снижения избыточности. В модеме, о котором упоминает Милливольт (https://github.com/gegel/jackpair, там импульсный модем Кондоза на 800 bps для работы с AMR-сжатыми каналами и мой реалтайм порт MELPE на CortexM4), использовался один контрольный бит на 4 или 9 информационных, этого хватало для устойчивой синхронизации при исходном BER в 3-4%. Но в другом проекте требования к модему более жесткие (синхронизация при 10-15% ошибок), но можно позволить избыточность. Поэтому малой кровью было использовать один контрольный на 2 информационных. А побочно контрольные биты (собственно, синхровставка) использую для худо-бедно первичной коррекции ошибок в модеме. Во втором проекте после модема идет турбо-декодер, поэтому логично было бы навесить на контрольные биты еще и уточнение LLR информационных бит, что и пытаюсь сделать. Опять у Вас все сводится к жестким решениям. Но я только хочу скорректировать LLR информационных бит по возможности. Коррекция жестких бит на данном этапе не производится.
  10. Готов согласиться, но только аргументируйте. Я рассуждаю так: допустим, есть два произвольных жестких бита, и третий - их xor. Затираем первый бит (что эквивалентно его LLR=0). Можем мы его восстановить по двум оставшимся? Без проблем. То же самое я пытаюсь корректно перенести на мягкие решения.
  11. Возможно, я недопонимаю суть, но все же мне кажется, что смысл есть. Я не пытаюсь исправить ошибку с помощью контрольного бита. Для этого будет использоваться полноценный турбо-декодер. Я пытаюсь скорректировать LLR с учетом контрольного бита, перед подачей на турбо-декодер. Например, передаем 00. Бит четности тоже 0. Принимаем -20, -70, -60 (последний - контрольный бит). По жесткому решению все ОК, контрольный бит совпадает. В турбо-декодер в составе полного фрейма длиной 3456 бит буду переданы -20 и -70. Но первый бит, очевидно, будет иметь более высокую надежность, т.к. она подкрепляется вторым и контрольным битами. Первая мысль, которая приходит в голову: из трех бит выбирать бит с минимальной метрикой, и заменять ее на бит со средней метрикой. В этом случае в турбо-декодер будут переданы значения -60 и -70. Грубо, конечно, т.к., очевидно, для первого бита метрика будет все же хуже -60, но лучше -20. Но не знаю, как сделать lege artis. Ну, и не могу гарантировать, что это вообще верно в принципе. ПС: - этот вопрос не имеет никакого отношения к мягкому Голею в соседней теме; - то, что я хочу сделать с LLR, не имеет никакого отношения к исправлению одной ошибки в слове с помощью контрольного бита мягким способом, как описано в начале темы. Это реально работает в физическом устройстве и улучшает BER даже при одном контрольном бите на 9 информационных (при низких исходных BER), не говоря уже об одном контрольном на два информационных.
  12. Я так и делаю сейчас. Но хотелось бы учитывать информацию, даваемую контрольным битом, для дальнейшего турбо-декодирования. Жесткий контрольный бит просто отбрасывается, а ведь он, по идее, связан с остальными и должен как-то влиять на их мягкие значения, что может быть полезно для турбо-декодера.
  13. Помогите, пожалуйста, разобраться в следующем: Два бита данных дополняются контрольным битом (0 xor 1) и передаются в поток (это нужно для синхронизации на лету). С выхода коррелятора (когерентный BPSK демодулятор) поступают ненормализованные значения -32767 ло 32767 Если в приянтой тройке жесткий контрольный бит не совпадает, то инвертируется жесткое решение бита с наименьшим мягким значением в тройке. Это работает ОК. Планируется использовать турбо-декодер (BCJR) для дальнейшего декодирования битов данных (на его входе Q15). Можно ли в данных условиях перед подачей на декодер подсчитать (скорректирвоать) мягкие значения двух информационных бит с учетом мягкого значения контрольного бита? Я полностью запутался в оценке вероятностей. Подскажите, как это реально сделать математически, т.е. как из трех значений выхода коррелятора получить два LLR, максимально пригодные для дальнейшего мягкого декодирования всего фрейма с помощью турбо-декодера.
  14. Посмотрите варианты тут: https://stackoverflow.com/questions/4608190/aac-codec-library-libfaac-alternative На STM32 я бы использовал исходник от 3GPP: http://www.3gpp.org/ftp//Specs/archive/26_series/26.410/26410-f00.zip Он на float, так что если будете портировать в M4, перепроверьте на предмет отсутствия неявно double.
  15. Пока правил свой пост , Вы уже ответили. И все же: сколько раз у Вас вызывается жесткий алгоритм в варианте с 16 ю кандидатами?
×
×
  • Создать...