среда, 31 декабря 2008 г.

FreeSWITCH, кодеки, g729

А вы в курсе, что FreeSWITCH практически единственное решение в мире открытых исходников, которое поддерживает HD кодеки?

Так недавно была добавлена поддержка кодеков Siren от компании Polycom. Была добавлена поддержка кодека celt! А кодек celt это 48 кГц - больше чем у CD записей. И это в полосе меньшей, чем у G.711 с 8 кГц. В общем жду когда эти кодеки можно будет попробовать в каком-нибудь IP-телефоне.

Хотя чего ждать? FreeSWITCH может работать как программный IP-телефон. Фактически, linux+FS это готовая программная начинка для IP-телефона с огромными возможностями. 3-way конференция? Легко, причем в HD качестве. Правда пытался присмотреться к железу, на котором можно было бы подобное собрать, и понял что ничего в этом не понимаю - большинство попадавшихся плат были для разработчиков, то есть не для использования для сборки в каких либо продуктах, и откуда берут платы производители телефонов не понимаю. Видимо они их могут сами спроектировать.

А пока я пытаюсь собрать/дописать кодек G.729. Программист на C из меня вообще никакой, так что утечки памяти гарантирую :) Исходники моего творчества лежат тут, если кто то захочет помочь - милости прощу, с радостью свалю задачу человеку, который хорошо понимает значение всех этих звездочек. Если кому то просто интересно получить рабочий кодек (не гарантирую, что стабильный) заглядывайте, смотрите на прогресс.

воскресенье, 21 декабря 2008 г.

Путешествие группы формант по голосовому тракту

Трое монтажников связи. Страдания Джорджа и Гарриса. Жертва ста семи помех. Полезные рецепты. Средство против болезней голосового тракта у монтажников. Монтажники сходятся на том, что переутомились и что им нужен отдых. Неделя в море, вдали от лапши? Джордж предлагает путешествие по реке. Монморенси выдвигает возражение, лапша недостаточно удаляется. Первоначальное предложение принято большинством трех против одного.


Аналоговая телефония



Все что нужно, чтобы связаться посредством двух телефонов - двухжильный провод и питание постоянным током (батарейка "Крона", например). Эту нехитрую истину знают монтажники связи - десятилетия у каждого из представителей доблестной профессии в сумке болтается переделанная трубка от советского дискового телефона.

То есть сама основа аналогового телефонного разговора проста - в трубке установлен угольный микрофон, под действием звуковых волн сопротивление его меняется - происходит модуляция тока. На другом конце, под действием модулированного тока, вибрирует динамик - телефонный капсюль. Первые телефонные станции реализовывали именно эту схему - телефонистка соединяла шнурами двух абонентов.

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

В дисковых телефонах номер набирался серией импульсов, что в трубке слышалось как серия щелчков. Импульсный набор зародился во времена декадно-шаговых АТС. Импульсы с телефонного аппарата напрямую управляли процессом набора номера на станции. Декадно-шаговые АТС были первыми автоматическими телефонными станциями.

На сегодняшний день используются цифровые АТС и IP-АТС. То есть, конечно, в глухих лесах необъятной Родины можно найти и АТС декадно-шаговой системы, координатные АТС и прочие системы, но на новых объектах их не ставят, а в городах стараются заменять.

АТС в телефонном тракте на начальном этапе играла роль источника питания и коммутатора - между абонентами одной АТС соединение устанавливало одну электрическую цепь. Конечно же на качестве связи отражалось всё - скрутки, станционные приборы, наводки, тепловые токи и т.д.

Цифра


Цифровая передача получила дорогу в жизнь на магистралях - передача аналогового сигнала на большие расстояния бесперспективна - помехи суммируются и сигнал становится невозможного для восприятия качества. Цифровой же сигнал замечательно регенерируется - достаточно распознать импульсы и сгенерировать такую же последовательность - на выходе повторителя такой же сигнал, каким он был десяток километров назад.

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

Человеческое ухо способно воспринимать звук с частотами от 20 герц до 24-25 килогерц. В соответствии с теоремой Котельникова (Найквиста) для оцифровки сигнала требуется частота выборки в два раза большая частоты сигнала. В действительности, для передачи голоса, достаточно гораздо более узкой полосы - в телефонии принята полоса от 300 Гц до 3 кГц. То есть в этой полосе располагаются основные форманты, которые наиболее значимы для различимости речи. В телефонии используется частота дискретизации (выборки) 8 кГц. При использовании 8-ми бит на один шаг получаем 64 кбит/c. В IP-телефонии кодек с такими характеристиками называется G.711.

Таким образом 64 кбит/c является стандартной скоростью передачи одного голосового канала в цифровой технике связи. С какой бы технологией вы не столкнулись - многоканальная связь, цифровая телефония, ISDN, ИКМ - везде под один голосовой канал отводится именно такая пропускная способность. Все скорости передачи в цифровой телефонии кратны 64 кбит/с и теперь вы знаете почему. Так же вам теперь понятно, почему сигнал ADSL, использующий частоты за голосовым спектром, не может быть пропущен через цифровые тракты, и обычно оканчивается на ближайшей городской АТС - телефония предполагает передачу сигнала с частотой не более 3 кГц.

Модемы и факсы также спроектированы с учетом этих фактов. Поэтому, когда в IP-телефонии используется этот же кодек (G711,64 кбит/с), факсы путешествуют через такие каналы без проблем.

Цифровые АТС работают именно с такими потоками. Если к цифровой АТС есть возможность подключить традиционные аналоговые телефоны - на входе их сигнал будет кодирован в цифровой и внутри АТС будет обрабатываться точно так же, как сигналы от цифровых телефонов.

В данной серии были изложены основы и упомянута теорема Котельникова, а Монморенси совершил подвиг, зажав зубами кабель, и спас селекторное. В следующих сериях страшные истории про кодеки, SIP и SDP, а также продолжение серии о монтажнике Джордже.

Принимаются критические замечания, в том числе и в гугл-группе freeswitch-ru.

пятница, 12 декабря 2008 г.

FreeSWITCH, факсы

Итак, кое-что о факсах. Какими бы бурными темпами ни двигался интернет в каждый дом, факс остается весьма важным средством передачи документов. В протоколах VoIP этому моменту уделено внимание, специально для факсов создан протокол T.38.

Временное отсутствие T.38 в FreeSWITCH я не считаю большой проблемой - на сегодняшний день лучше всего передаются факсы при использовании кодека G.711. T.38 будет реализован в обозримом будущем, а пока я опишу то, что уже есть.
В FreeSWITCH был добавлен модуль mod_fax. Он предоставляет две функции - txfax и rxfax. На текущий момент поддерживается протокол T.30. Пример из wiki:

<extension name="fax">
<condition field="destination_number" expression="^fax$">
<action application="answer" />
<action application="playback" data="silence_stream://2000"/>
<action application="rxfax" data="/usr/local/freeswitch/fax/${caller_id_number}-${strftime(%Y-%m-%d-%H-%M-%S)}.tiff"/>
<action application="hangup"/>
</condition>
</extension>



Обнаружение передачи факса.

FreeSWITCH предоставляет специальную функцию для обнаружения тоновых сигналов в голосовом потоке - tone_detect.

<extension name="5555555">
<condition field="destination_number" expression="^(5555555)$"/>
<action application="tone_detect" data="fax 1100 r +5000 transfer fax XML default"/>
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="ivr" data="main"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="fax">
<condition field="destination_number" expression="^fax$">
<action application="answer" />
<action application="playback" data="silence_stream://2000"/>
<action application="rxfax" data="/usr/local/freeswitch/fax/${caller_id_number}-${strftime(%Y-%m-%d-%H-%M-%S)}.tiff"/>
<action application="hangup"/>
</condition>
</extension>



А можно поставить обнаружение на всю сессию:

<!-- continue="true" - означает, что надо продолжить выполнение номерного плана после этого пункта -->
<extension name="fax_tone_detect_permanent" continue="true">
<!-- ловим любые звонки, так как .* означает любое кол-во любых символов -->
<condition field="destination_number" expression="^.*$"/>
<!-- ставим обнаружение тона 1100 со стороны звонящего(r) бесконечное время(0)
В случае обнаружения тона передаем (transfer) на обработку в "default" номерной план
с номером "fax"-->
<action application="tone_detect" data="fax 1100 r 0 transfer fax XML default"/>
</condition>
</extension>


Таким образом прием факсов в FreeSWITCH организовать достаточно легко. Надеюсь реализация T.38 не заставит себя долго ждать.

Слабым местом пока остается поддержка кодеков. Все заинтересованные уже знакомы с патентной системой США - практически все дистрибутивы в нашей стране имеют "поддержку кодеков из коробки".
G.729, G.723, AMR сейчас поддерживаются только в режиме без перекодирования. То есть использовать с этими кодеками голосовую почту, голосовые меню, запись разговоров затруднительно.

Заколдованый круг - пока FreeSWITCH не поддерживает кодеки он не очень интересен у нас. А пока он не очень интересен - кодеки реализовывать некому.

воскресенье, 23 ноября 2008 г.

Google-группы по kerberos и Freeswitch

Я создал две новых google-группы для обсуждения вопросов, связанных с kerberos и freeswitch. Просьба все свои вопросы задавать там - формат комментариев к блогу не очень хорошо подходит для подобных обсуждений.


1. ru-kerberos
2. freswitch-ru

четверг, 13 ноября 2008 г.

plasma-mediacontroller

Почему то Am4rok, из Ubuntu 8.10, у меня не работает. Не разбирался, ведь те, кто следят за блогом, знают - теперь есть биндинги под python! Сделал себе свой велосипед - plasma-mediacontroller. Он конечно не так здорово смотрится, но главное он у меня работает.

Если кому то будет интересен, можно продолжить разработку. Сейчас он работает только с Amarok, но нет ничего сложного в добавлении поддержки практически любого медиаплеера. Ведь большинство из них реализует стандартный интерфейс DBus для медиаплееров.

Кому интересно - берите тут. В первой записи о plasma-python есть инструкции по установке плазмоида.

понедельник, 10 ноября 2008 г.

8.10, dkms, nvidia, btrfs

Итак, раз уж в рубунтнете поднялась мода описывать свой опыт по общению с разного вида "козлами" (у кого насколько переводческой фантазии хватит), присоединюсь к этому движению. Да, я тоже обновился до 8.10, чему очень рад. Собственно рад я в основном новой фишке - DKMS.

Некоторое время у меня задурил драйвер Nvidia - я особо не разбирался конечно, и с налету решить не удалось - вместо модуля nvidia_new, который новой версии, грузился старый nvidia. В 8.10 эту часть работы с модулями заменили на DKMS.

Итак, а что это? А это такая система автоматической сборки модуля под ваше ядро. Предположим поставили вы себе 2.6.28, а DKMS тут как тут - тут же соберет модуль и установит его под новое ядро. То есть думать о том, что вы там такого стороннего в ядро напихали, каждый раз совершенно не надо.

И тут у нашего повествования этакий плавный переход. Связующее звено у двух повествований все тот же DKMS. Я экспериментировал с Btrfs, а так как это новая файловая система, планируемая (авторами, когда нибудь : )) ) к включению в ядро, и вообще чтобы корень на нее помещать, то представляет собой она собственно модуль ядра. А модулями ядра у нас теперь ведает - DKMS.

Итак, чтобы вы тоже приобщились к 21 веку, и познали прелесть COW (copy-on-write) систем, дам вам указание верного пути, то есть dkms.conf.
Стягиваем исходники модуля ядра и кладем их в /usr/src/btrfs-0.16 (ну вот такая вот у нас текущая версия). В том же каталоге создаем dkms.conf следующего содержания:

MAKE[0]=make
BUILT_MODULE_NAME[0]=btrfs
DEST_MODULE_LOCATION[0]="/kernel/fs/btrfs"
PACKAGE_NAME="btrfs"
PACKAGE_VERSION="0.16"
CLEAN="make clean"
AUTOINSTALL="yes"


Далее следует серия команд для запуска модуля в работу:

root:host~# dkms add -m btrfs -v 0.16
root@rni-15:~# dkms add -m btrfs -v 0.16

Creating symlink /var/lib/dkms/btrfs/0.16/source ->
/usr/src/btrfs-0.16

DKMS: add Completed.
root:host~#
root:host~# dkms build -m btrfs -v 0.16

Kernel preparation unnecessary for this kernel. Skipping...

Building module:
cleaning build area....
make KERNELRELEASE=2.6.27-7-generic............
cleaning build area....

DKMS: build Completed.

root:host~# dkms install -m btrfs -v 0.16
Running module version sanity check.

btrfs.ko:
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/2.6.27-7-generic/updates/dkms/

depmod........

DKMS: install Completed.

root:host~# modprobe btrfs

Отлично, теперь скачайте утилиты для работы с btrfs и посмотрите, что вам может дать эта система. А может она вам дать снимки, тома, контрольную сумму всех блоков, raid различных уровней и многое другое. Работает гораздо живее zfs которая на fuse. Но не стоит пока размещать на ней /home or /.

Кстати о снимках, если вы пересилите себя, и доберетесь до самого первого поста этого блога, то увидите там бесподобную идею поставить /etc/ под контроль версий. Идея умерла с того момента, как я познакомился с концепциями zfs и btrfs - это наше файловое будущее.

Подробности, одни из, тут.

четверг, 30 октября 2008 г.

Мой первый плазмоид

Я поклонник KDE и python. С удивлением я, как и многие другие, смотрел на KDE 4.0. После вылизанного 3.5 это было конечно страшно. Особенно мне не хватало kicker и его "кикоидов". Но время идет, проект продолжает развиваться невзирая на возню анонимов на веб просторах, и теперь наконец то есть привязки plasma для python, а значит теперь я сам себе автор плазмоидов.

Мой первый плазмоид страшно кособок, но тем не менее показателен. Итак, по устоявшейся традиции среди Qt-шников, будем делать свой браузер. Правда этот, удивительный своей неординарностью, экземпляр, мы встроим прямо в рабочий стол.

Этот код просто вставьте в командную строку, он создаст структуру каталогов, файлы, соберет пакет, и установит его для текущего пользователя.


mkdir -p wwwv/contents/code
cd wwwv
cat > metadata.desktop << EOF
[Desktop Entry]
Encoding=UTF-8
Name=WWW viewer
Type=Service
ServiceTypes=Plasma/Applet
X-Plasma-API=python
Icon=chronometer

X-KDE-PluginInfo-Author=Mikhail Krivushin
X-KDE-PluginInfo-Email=mkrivushin@yandex.ru
X-KDE-PluginInfo-Name=plasma-wwwv
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://deepwalker.blogspot.com
X-KDE-PluginInfo-Category=Tests
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
EOF

cat > contents/code/main.py << EOF
#! /usr/bin/python

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtWebKit
from PyKDE4.kdecore import *
from PyKDE4.kdeui import *
from PyKDE4.plasma import Plasma
import plasma

class PyWWWvApplet(plasma.Applet):
def __init__(self,parent,args=None):
plasma.Applet.__init__(self,parent)

self.url = None
self.clicked = QPoint()

def init(self):
KGlobal.locale().insertCatalog("www")

self.setHasConfigurationInterface(False)
self.setAspectRatioMode(Plasma.IgnoreAspectRatio)

self.dialog = None

self.theme = Plasma.Svg(self)
self.theme.setImagePath("widgets/background")
self.theme.setContainsMultipleImages(False)
self.theme.resize(self.size())

self.webview = Plasma.WebContent()
self.mlayout = QGraphicsLinearLayout(Qt.Vertical)
self.eline = Plasma.LineEdit()
self.mlayout.addItem(self.eline)
self.mlayout.addItem(self.webview)
self.setLayout(self.mlayout)

self.connect(self.eline,SIGNAL('returnPressed()'),self.open_page)

self.webview.setUrl(KUrl('http://127.0.0.1/'))
self.webview.update()

def open_page(self):
page = self.eline.text()
#print "Go to %s"%page
self.webview.setUrl(KUrl(page))
self.webview.update()

def shape(self):
if self.theme.hasElement("hint-square-clock"):
return plasma.Applet.shape(self)
path = QPainterPath()
path.addEllipse(self.boundingRect().adjusted(-2, -2, 2, 2))
return path


def constraintsEvent(self, constraints):
if constraints & Plasma.SizeConstraint:
self.resize(self.size())

def CreateApplet(parent):
return PyWWWvApplet(parent)
EOF

zip -r ../wwwv.zip .

plasmapkg -i wwwv.zip


Конечно же надо поставить соответствующие привязки. Так как я уже на 8.10, то просто сделал aptitude install python-plasma.

Далее располагайте плазмоид на рабочем столе и удивляйтесь мощи моего гения. Теперь же я, пожалуй, отправлюсь спать. А вы, дорогие мои, утомляйте неутомимый google бесчисленными запросами - "plasma python qt webkit" в поисках ответа на вопрос - а как же сделать, чтобы оно использовало прокси?