Как стать автором
Обновить

Комментарии 39

Но что из себя представляет «слепок звука» за единицу времени? А представляет он собой вот такой массив из чисел типа Float:
Почему именно Float? Может и Int быть, причем от 4 до 64 бит.
Обычно 24 для музыки. 24-бит глубина дает динамический диапазон — 144дБ
64 бита наверное даже аудиофилам не надо — 385дБ. Никакая аудио аппаратура такое не воспроизведет. А если воспроизведет, то человек навряд-ли услышит разницу. 144дБ уже воспринимается как абсолютно черный фон в беззвучных местах, паузах.
А для игры наверное и 16 бит хватит — 96дБ.
Хотя у Float могут быть преимущества, за счет нелинейного представления уровней можно добиться большего ДД, ИМХО, того же самого можно добиться и на целочисленном кодировании путем нелинейного представления уровня звука для каждого целого числа.
Потом, зачем сырой wav поток по сети гонять. Можно зажать в MP3.
Я не гоняю сырой wav, а использую нативный "Препроцессор".
Если нужно именно mp3, то ищем в статье строчку кода:
audioFormat.mFormatID = kAudioFormatLinearPCM;

Заменяем на
audioFormat.mFormatID = kAudioFormatMPEGLayer3;
Почему бы не использовать pjsip для мобильного приложения? Под iOS собирается на ура. Есть демонстрационное приложение в пару сотен строк на pjsua (high-level api). На борту уже несколько кодеков, не нужно гонять wav. VoIP сервер Kamalio поднимается за пол часа. И можно звонить.
Вот тут можно почитать как это всё делается по шагам.
К сожалению по вашему линку устаревшая инструкция по сборке, в xcode 7.3 — pjsip не собирается на iOS, огромное количество ошибок. Часть ошибок я попробовал исправить, но потратив 10 минут, скомпилировать на iOS мне не удалось. Возможно, потратив больше времени, можно собрать pjsip на iOS 9, если у вас есть данный опыт, поделитесь готовым архивом с проектом. Тут еще дело в том, что мой сервер, написанный с нуля, помимо распределения аудио данных, рассылает IN-APP нотификации и синхронизирует информацию о VK друзьях с базой данных. В принципе можно модифицировать Kamailio сервер, но не уверен, что это тривиальная задача.
Можно сразу WebRTC из кода хромиума взять, ага-ага.

Про задержку, задержка не проблема, проблема — синхронизация. В гугл — за decoding time stamp (DTS), и за presentation time stamp (PTS).
Как я понимаю, "временный штампы" нужны для синхронизации видео потока с аудио потоком и субтитрами, а так же для обнаружения пропущенных семплов.
Если вы посмотрите на код активации Callback в статье, вы увидите эту метку — AudioTimeStamp * inTimeStamp:
#pragma mark ======== AudioUnit recording callback =========
static OSStatus PushCurrentInputBufferIntoAudioUnit(void * inRefCon,
    AudioUnitRenderActionFlags * ioActionFlags,
    const AudioTimeStamp * inTimeStamp,
    UInt32 inBusNumber,
    UInt32 inNumberFrames,
    AudioBufferList * ioData)
{
    //inTimeStamp - это и есть наша временная метка
} 

struct AudioTimeStamp {
    Float64 mSampleTime;   // временная метка в количестве семплов
    UInt64  mHostTime;   // временная метка в абсолютном системном времени
    // ...
    UInt32 mFlags;   // маска, указывающая на то, какие из полей заполнены
 };
Абсолютно верный и уместный комментарий, я планировал на сервере открыть 2 порта, один TCP: для авторизации и обменом ВК информацией, второй UDP: для пересылки аудио пакетов. Возможно, попробую UDP позже.
Возьмите voximplant и будет вам и UDP, и нормальный звук и даже видео :)
Платные решения я не рассматриваю по трем причинам (помимо той, что большинство этих решений написано на том же Core Audio):
  • Есть в наличии свои сервера.
  • Я планирую сделать приватные чаты с шифрованием по паролю. Использовать сторонние сервера — удар по приватности пользователей.
  • Работая со звуком на «низком уровне», есть возможность создавать голосовые фильтры, модифицировать голос, что я и хочу сделать в дальнейших обновлениях.
Добавить поддержку видео в мое приложение на данном этапе — довольно просто, но тема для отдельной статьи.
Из вашей статьи видно, что знаний по работе с real-time у вас почти нет, то же самое кодирование звука mp3 говорит о многом, как и передача данных по TCP. Voximplant поддерживает бесплатные P2P звонки, это к вопросу про приватность, бесплатность и прочие ваши требования. Не хотите Voximplant, который уже решил за вас большинство проблем, погуглите хотя бы про WebRTC.
Я понимаю, что, как сотрудник Voximplant, вы пытаетесь рекламировать свой продукт, возможно это и правильно, но не понимаю, как iOS пользователи без внешнего IP могут приватно совершать P2P звонки, не пропуская весь трафик через ваши сервера. Я понимаю, что большинство VoIP работают на UDP, но мне хотелось провести эксперимент с гарантированной доставкой пакетов, поэтому я попробовал использовать TCP для гарантированной передачи зашифрованных пакетов, чтобы принимающая сторона могла их гарантированно расшифровать.
но не понимаю, как iOS пользователи без внешнего IP могут приватно совершать P2P звонки, не пропуская весь трафик через ваши сервера.

мда, все еще хуже чем я думал, удачи вам)
НЛО прилетело и опубликовало эту надпись здесь
Зря минусите человека. Действительно — UDP. И действительно брать RTP. А собственно SIP — это как раз то, что автор хочет гонять по TCP, т.е. всякая разная авторизация и прочие не-голосовые данные.
Все верно, в интернете есть примеры iOS RTP проектов, я так же пытался собрать и XMPP проект, но при выходе новых версий iOS — эти проекты у меня просто перестали компилироваться. Причем в старых версиях XCODE эти проекты собирались, но Apple запретил нам пользоваться старыми версиями XCODE, скаченными со сторонних ресурсов, под угрозой исключения приложений из App Store. Лично у меня не хватило терпения разобраться со всеми ошибками компилятора, если у вас есть рабочие iOS примеры — поделитесь с нами, пожалуйста.
Старые версии Xcode всегда можно скачать с дев портала эппл developer.apple.com/downloads
Действительно, спасибо за ссылку
Спасибо, я к сожалению в SIP мало понимаю, но постараюсь разобраться. Получается такая ситуация: у нас есть два iPhone, без выделенных IP, которые нужно соединить по UDP протоколу. Открыть UDP порт для принятия данных телефон не может. Каждый из них сначала опросит STUN сервер, чтобы узнать, что у него нет выделенного IP, хотя нужно ли это действие, когда и так понятно, что выделенного IP нету? Затем каждый из iPhone создаст постоянное TCP(!) соединение со своим TURN сервером, для того, чтобы иметь возможность через TURN сервер принимать (проксировать) UDP данные. В итоге, для того, чтобы соединить два телефона, у нас висит 2 TCP соединения, 2 UDP соединения (от клиентов на TURN сервер противоположного iPhone), да и еще коммуникация между TURN серверами + первоначальный опрос STUN серверов? И для чего такая сложная топология нужна — только для того, чтобы при потере пакетов не заморачиваться на повторную отправку данных? Верно я понимаю данную схему или допустил ошибку? Буду благодарен, если объясните.
даже заимев STUN проблемы не решаются.
начинаются более интересные вещи:

односторонняя слышимость
симметричный NAT
в некоторых случаях ни как без проксирования (а значит нужен и media proxy)

Проблемы с проброской канала — это основная сложность, с которой борются в voip ip.
без решения как минимум этих проблем — это сферический конь в вакуме
Неверно.
Клиент отправляет UDP-пакет на STUN-сервер, NAT открывает внешний порт, по которому клиент сможет получать входящие UDP-пакеты, STUN-сервер видит этот порт, а также адрес NAT, и отправляет их другому клиенту, который на этот адрес и порт начинает транслировать разговор по UDP. На пальцах так, подробнее в RFC, Wiki и Google. Схема работает не для всех видов NAT, поэтому всегда предусматривают TURN-сервер как запасной вариант. Где-то видел статистику, что p2p работает для ~90% (точно не помню, но порядок такой), остальное проксируется через TURN.
P.S. Шифровать без проблем можно и по UDP, см. хотя бы DTLS.
когда с обоих сторон будет симметричный NAT — только проксирование.
насчет p2p, вы, очевидно, путаете его с децентрализованой сетью
p2p это просто одноранговая сеть, для тех показателей, о которых вы говорите, такая сеть нуждается в координаторах, которыми могут являться и сами клиенты, но такая сеть уже минимум являться гибридной
Согласен с Вашим комментарием, он уточняет мой упрощенный посыл, в каком направлении копать. :)
НЛО прилетело и опубликовало эту надпись здесь
" Так почему бы не сделать приложение, в котором можно узнать, сколько человек меня разделяют в VK, например, с Павлом Дуровым?" — но ведь именно такое давно уже в разных приложениях?
Скиньте ссылку, пожалуйста, или название приложения, где это можно сделать.
Спасибо за ссылку, поигрался с приложением, работает :)
Не за что
Дело в том, что iOS не позволяет запускать новые звуки, когда приложение свернуто, для проверки можете запустить песню в Safari из ВК и свернуть браузер. Как только трек закончится, новый трек из плейлиста не включится до тех пор, пока вы не сделаете браузер активным!

Извините, что немного не по теме пишу, но как можно сделать, чтобы вот как раз в этом Safari песни переключались? А то я когда слушаю аудиозаписи через ВК мне приходится всегда держать экран включенным и браузер открытым на этой страничке с музыкой, а если проходит более 30 минут, то тогда если экран всё ещё включен, айфон начинает нагреваться и зарядка быстрее уходит, и ещё есть вираятность случайно куда-то нажать…
Дело в том, что iOS не позволяет запускать новые звуки, когда приложение свернуто
У меня Napster отлично играет в фоне, более того, я подключенный к колонкам старый телефон даже не разблокирую неделями, запускаю музыку прямо с экрана блокировки.
Ну все верно, iOS не позволяет создавать новые звуки в фоне, но разрешает в фоне держать «аудиопоток», который остается активным, и в котором можно будет воспроизводить звуки в дальнейшем. Помимо описанного в статье способа обхода запрета запуска новых звуков в iOS, есть и другие методы, которые и используют создатели iOS музыкальных плееров.

Но если вы попробуете запустить в фоне звук с помощью классического метода:

AVAudioPlayer *avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:
    [NSURL fileURLWithPath:@"имя_файла.caf"] error:nil];
[avPlayer play];


— то звук в фоне не запустится. Именно поэтому, при воспроизведении музыки из VK через Safari на iOS — следующий трек не включается, если приложение свернуто.
это не совсем так.
приложение — специализированный аудиоплеер
использую AVPlayer для звука (вместо AVAudioPlayer, так нужно в моем случае) и флаг что я играю в фоне звук.
по исчерпании текущего аудиопотока да — iOS усыпляет приложение. Только никто не мешает попросить еще немного background time (кодом вроде CLogINFO(LOGDOMAIN_MINIPLAYER,@«Asking for more background time»);
newTaskID=[[UIApplication sharedApplication] beginBackgroundTaskWithName:@«AudioRestartTask» expirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:newTaskID];
newTaskID = UIBackgroundTaskInvalid;
}];

) и запустить там новый аудиопоток. Все работает с выключенным экраном
Ну я же написал, что «есть и другие методы обхода», спасибо за способ, полезный коммент, забираю к себе в заметки. Мне кстати по данной теме еще понравилось, как некоторые приложения обходят запрет за воспроизведение звуков во время телефонного звонка — они воспроизводят музыку через локальные in-app уведомления.
А что используется из вконтакте АПИ? Логин и получение друзей?
Да, только публичная информация, ФИО и список друзей.
А Вам не кажется что этого маловато для участия в конкурсе Vkontakte? Вы используете только два общедоступных метода, а как же комментарии, лайки, репосты и тп. Или участие в конкурсе не первостепенная причина для написания приложения?
Первостепенная, в идеале хотелось бы, чтобы Core Audio стало частью новых общественных методов и аудио звонки вошли бы в состав стандартного VK SDK
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории