Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Изучаем Core Audio. Практическое руководство по программированию звука в Mac и iOS

Покупка
Артикул: 817131.01.99
Доступ онлайн
519 ₽
В корзину
Звук оказывает мощное и самое непосредственное воздействие на человеческий мозг. Благодаря подсистеме Apple Core Audio мы сможете задействовать эту мощь в своих программах для Mac и iOS: захватывать звук с устройств ввода, накладывать эффекты в реальном времени, воспроизводить MP3-файлы, играть на виртуальных музыкальных инструментах, слушать веб-радио, поддерживать технологию VoIP и т.д. Самая развитая из всех когда-либо созданных систем программирования звука, Core Audio отнюдь не проста. В этом издании один из лучших авторов книг по программирования в iOS Крис Адамсон и легендарный специалист по Core Audio Кэвин Авила во всех подробностях рассказывают об этой потрясающей подсистеме, чтобы программисты на платформах Mac и iOS могли воспользоваться всеми ее возможностями. Издание предназначено для программистов различного уровня подготовки, создающих приложения в Mac OS и iOS.
Адамсон, К. Изучаем Core Audio. Практическое руководство по программированию звука в Mac и iOS : практическое руководство / К. Адамсон, К. Авила. - пер. с англ. — 2-е изд. - Москва : ДМК Пресс, 2023. - 361 с. - ISBN 978-5-89818-639-5. - Текст : электронный. - URL: https://znanium.com/catalog/product/2108532 (дата обращения: 04.05.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Изучаем Core Audio

Практическое руководство
по программированию звука в Mac и iOS

Крис Адамсон, Кэвин Авила
Learning Core Audio

A Hands-On Guide to Audio
Programming for Mac and iOS

Chris Adamson, Kevin Avila
Изучаем Core Audio

Практическое руководство 
по программированию звука в Mac и iOS

Москва, 2023

Крис Адамсон, Кэвин Авила

2-е издание, электронное
УДК 004.451iOS
ББК 32.973.26-018.2
А28

А28
Адамсон, Крис.

Изучаем Core Audio. Практическое руководство по программированию 
звука в Mac и iOS / К. Адамсон, К. Авила ; пер. с англ. — 2-е изд., эл. — 
1 файл pdf : 361 с. — Москва : ДМК Пресс, 2023. — Систем. требования: 
Adobe Reader XI либо Adobe Digital Editions 4.5 ; экран 10". — Текст : электронный.


ISBN 978-5-89818-639-5

Звук оказывает мощное и самое непосредственное воздействие на человеческий 
мозг. Благодаря подсистеме Apple Core Audio мы сможете задействовать эту мощь 
в своих программах для Mac и iOS: захватывать звук с устройств ввода, накладывать 
эффекты в реальном времени, воспроизводить MP3-файлы, играть на виртуальных 
музыкальных инструментах, слушать веб-радио, поддерживать технологию 
VoIP и т.д. Самая развитая из всех когда-либо созданных систем программирования 
звука, Core Audio отнюдь не проста. В этом издании один из лучших авторов 
книг по программирования в iOS Крис Адамсон и легендарный специалист по Core 
Audio Кэвин Авила во всех подробностях рассказывают об этой потрясающей подсистеме, 
чтобы программисты на платформах Mac и iOS могли воспользоваться 
всеми ее возможностями.
Издание предназначено для программистов различного уровня подготовки, создающих 
приложения в Mac OS и iOS.

УДК 004.451iOS 
ББК 32.973.26-018.2

Электронное издание на основе печатного издания: Изучаем Core Audio. Практическое руководство 
по программированию звука в Mac и iOS / К. Адамсон, К. Авила ; пер. с англ. — Москва : 
ДМК Пресс, 2016. — 360 с. — ISBN 978-5-97060-413-7. — Текст : непосредственный.

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

В соответствии со ст. 1299 и 1301 ГК РФ при устранении ограничений, установленных техническими средствами 
защиты авторских прав, правообладатель вправе требовать от нарушителя возмещения убытков или выплаты компенсации.


ISBN 978-5-89818-639-5
© Pearson Education, Inc.
©  Оформление, перевод 
ДМК Пресс, 2016
Содержание

Благодарности ................................................................................ 9
Об авторах ...................................................................................... 11
Предисловие ................................................................................. 12
Введение ........................................................................................ 17

Часть I. ПРИНЦИПЫ РАБОТЫ CORE AUDIO ............................. 31
Глава 1. Общие сведения о Core Audio .................................... 31

Основные каркасы подсистемы Core Audio ......................................... 32
Соглашения, применяемые в Core Audio ............................................. 35
Первое приложение с применением Core Audio .................................. 36
Запуск примера .............................................................................. 40
Свойства Core Audio ........................................................................... 42
Резюме .............................................................................................. 44

Глава 2. Кое-что о звуке .............................................................. 46

Создание звуковых колебаний ........................................................... 46
Цифровой звук ................................................................................... 48
Отсчеты – сделай сам ........................................................................ 54
Буферы .............................................................................................. 64
Звуковые форматы ............................................................................. 65
Резюме .............................................................................................. 66

Глава 3. Обработка звука с помощью Core Audio.................. 68

Форматы звуковых данных ................................................................. 68
Пример: определение формата....................................................... 72
Канонические форматы ...................................................................... 79
Обработка звука с помощью аудиоблоков .......................................... 80
Модель вытягивания .......................................................................... 83
Резюме .............................................................................................. 84

Часть II. ПРОСТЫЕ ОПЕРАЦИИ СО ЗВУКОМ ........................... 85
Глава 4. Запись ............................................................................. 85

Все об аудиоочередях ........................................................................ 86
Содержание

Разработка рекордера ....................................................................... 87
Функция CheckError() ......................................................................... 90
Создание и использование аудиоочереди .......................................... 92
Служебные функции для аудиоочереди ............................................ 100
Функция обратного вызова для записи звуковых данных ............... 104
Резюме ............................................................................................ 108

Глава 5. Воспроизведение ....................................................... 110
Постановка задачи ........................................................................... 110
Подготовка очереди для воспроизведения звукового файла ............ 112
Подготовка буферов для воспроизведения ................................... 115
Запуск очереди воспроизведения ................................................. 118
Служебные функции для воспроизведения ...................................... 119
Обработка сигнатуры формата ...................................................... 120
Вычисление размера буфера и ожидаемого числа пакетов ........... 121
Функция обратного вызова для аудиоочереди воспроизведения ..... 122
Резюме ............................................................................................ 127

Глава 6. Преобразование ......................................................... 129
Утилита afconvert .............................................................................. 129
Использование службы Audio Converter Services .............................. 132
Подготовка файлов .......................................................................... 135
Вызов службы Audio Converter Services.......................................... 138
Реализация функции обратного вызова для конвертера ................ 143
Преобразование с применением службы Extended Audio File 
Services ............................................................................................ 147
Чтение и преобразование данных с помощью расширенных 
звуковых файлов ........................................................................... 151
Резюме ............................................................................................ 154

Часть III. БОЛЕЕ СЛОЖНЫЕ ОПЕРАЦИИ СО ЗВУКОМ ........ 156
Глава 7. Аудиоблоки: генераторы, эффекты 
и рендеринг .................................................................................. 156
Там, где вершится волшебство ......................................................... 157
Как работает каркас Audio Units ........................................................ 158
Какие существуют аудиоблоки ......................................................... 160
Первое знакомство с аудиоблоками ................................................. 164
Функция main() .............................................................................. 166
Создание графа аудиоблоков ........................................................ 169
Конфигурирование аудиоблока плеера файлов ............................. 173
Синтез речи и наложение эффектов с помощью аудиоблоков .......... 178
Составные части графа синтеза речи ............................................ 179
Создание графа синтеза речи ....................................................... 181
Конфигурирование синтезатора речи ........................................... 183
Содержание

Добавление эффектов .................................................................. 184
Включение собственного кода в процесс рендеринга звука ............. 187
Цикл рендеринга аудиоблока ........................................................ 188
Пример нестандартного рендеринга ............................................. 190
Создание и соединение аудиоблоков ............................................ 192
Функция обратного вызова рендеринга......................................... 194
Резюме ............................................................................................ 199

Глава 8. Аудиоблоки: ввод и микширование ....................... 201
Работа с устройствами ввода ........................................................... 202
Соединение блоков ввода и вывода .............................................. 204
Кольцевые буферы спешат на помощь .......................................... 205
Использование кольцевого буфера при работе с аудиоблоками ..... 207
Создание блока AUHAL для ввода .................................................. 210
Функция обратного вызова ввода .................................................. 219
Построение графа для воспроизведения отсчетов 
из кольцевого буфера ................................................................... 221
Функция обратного вызова рендеринга для программы 
сквозного воспроизведения .......................................................... 224
Запуск программы сквозного воспроизведения ............................ 226
Микширование ................................................................................. 227
Резюме ............................................................................................ 235

Глава 9. Позиционный звук ...................................................... 236
Звук в пространстве ......................................................................... 236
OpenAL API ....................................................................................... 239
Размещение звука в пространстве ................................................... 243
Подготовка к написанию программы ............................................. 244
Использование объектов OpenAL .................................................. 247
Изменение позиции источника ...................................................... 254
Загрузка отсчетов для буфера OpenAL .......................................... 255
Потоковая передача звука в OpenAL ................................................. 259
Подготовительные действия в примере работы с потоковым 
API OpenAL .................................................................................... 260
Подготовка ExtAudioFile к потоковому воспроизведению ............... 265
Повторное заполнение буферов OpenAL ....................................... 267
Резюме ............................................................................................ 270

Часть IV. ДОПОЛНИТЕЛЬНЫЕ ТЕМЫ ...................................... 272
Глава 10. Core Audio в системе iOS ........................................ 272

А та ли это Core Audio? ..................................................................... 272
Мирное сосуществование: служба Audio Session Services ................ 274
Пример работы с аудиосеансом ....................................................... 276
Подготовительные действия ......................................................... 277
Содержание

Инициализация аудиосеанса и аудиоочереди ............................... 281
Метод генерации звука нужной высоты ......................................... 285
Обработка прерываний в iOS ......................................................... 287
Аудиоблоки в iOS .............................................................................. 290
Разработка приложения для сквозного воспроизведения звука 
с помощью блока удаленного ввода-вывода в iOS ......................... 292
Подготовительные действия ......................................................... 293
Настройка аудиоблока удаленного ввода-вывода для захвата 
и воспроизведения ....................................................................... 297
Обратный вызов от блока удаленного ввода-вывода ..................... 304
Другие приемы работы со звуком в iOS ............................................ 307
Дистанционное управление в iOS .................................................. 307
Аппаратные неожиданности в iOS ................................................. 309
Резюме ............................................................................................ 310

Глава 11. Core MIDI ..................................................................... 311
Концепции MIDI ................................................................................ 311
Core MIDI .......................................................................................... 312
Архитектура Core MIDI ................................................................... 313
Терминология Core MIDI ................................................................ 313
Свойства Core MIDI ....................................................................... 315
Сообщения MIDI ............................................................................ 315
Инструментальные блоки ................................................................. 316
Разработка простого MIDI-синтезатора ............................................ 317
Подключение к MIDI-устройству .................................................... 320
Обработка уведомлений и событий MIDI .......................................... 323
Воспроизведение графа ............................................................... 325
Создание событий MIDI .................................................................... 326
Подготовка к разработке программы MIDIWifiSource ..................... 326
Подготовка к передаче MIDI по сети Wi-Fi ...................................... 328
Отправка сообщений MIDI ............................................................. 331
Настройка Mac для получения данных MIDI по сети Wi-Fi ............... 333
Резюме: MIDI – это хорошо, но как насчет мобильности? ................. 335

Глава 12. Кода ............................................................................. 337
Еще немного Core Audio ................................................................... 337
Что дальше? ..................................................................................... 338
Цифровая обработка сигналов ...................................................... 339
Lion и iOS 5 ....................................................................................... 340
AUSampler ..................................................................................... 340
Core Audio в iOS 5 .......................................................................... 345
Сообщество Core Audio .................................................................... 346
Резюме: неплохо звучит ................................................................... 347

Предметный указатель ............................................................. 349
Благодарности

От Криса Адамсона

Эта книга не состоялась бы без помощи со стороны Кэвина Авилы 
и Майка Ли, нашедшего издательство, которое не только не 
отшатнулось при мысли о книге, посвященной трудной, узкоспециализированной 
теме программирования для Mac и iOS, но даже 
нашло особое удовольствие в том, чтобы выпустить ее на рынок. 
Они знали, что вот уже много лет публика жаждет получить изложение 
технологии Core Audio в такой форме, которая позволила 
бы среднему программисту по-настоящему воспользоваться ее фантастической 
мощью. За кулисами работу над книгой от начала до 
конца курировал Чак Топорек (Chuck Toporek), который подгонял 
меня, когда что-то стопорилось. И за то, что книга все-таки вышла 
в свет, его следует благодарить больше, чем кого-либо другого.
Мы не смогли бы довести дело до конца без щедрой поддержки со 
стороны сообщества разработчиков Core Audio, особенно участников 
списка рассылки coreaudio-api. Идейный отец Core Audio Уильям 
Стюарт (William Stewart) и Дуг Уайат (Doug Wyatt) из компании 
Apple не раз тратили свое время, чтобы ответить на вопросы, отправленные 
в этот список, и помочь нам выйти из очередного тупика. 
Мы также благодарны многочисленным техническим рецензентам 
и читателям предварительной версии книги, которые сообщали об 
ошибках и делились своими впечатлениями по мере того, как книга 
постепенно двигалась к завершению.
Из домашних я благодарю свою жену Кэлли и наших детей, Ки-
ган и Куинн, за то, что они предоставили мне свободу действий и 
не шарахались, когда из папиного кабинета в подвальном этаже дома 
доносилась очередная порция проклятий из-за того, что пример 
никак не хотел работать правильно.
Ну и обязательные для такой книги упоминания о музыке, которую 
мы слушали: на этот раз это были рок-группы We Are The City, 
And You Will Know Us by the Trail of Dead, Daft Punk, Dr. Dog, Fun 
и (очень кстати) Хацунэ Мику1.

От Кэвина Авилы

Я благодарен Большому Взрыву, гравитации и акту любви между 
моими родителями, из-за которых эта книга стала возможной.
Чак Топорек (@chuckdude), Крис Адамсон (@invalidname), Майк 
Ли (@bmf): нет слов, чтобы выразить мою признательность за кровь, 
пот и мысли, которые вы вложили не только в эту книгу, но и во 
все сообщество разработчиков. Спасибо вам!
Билл Стюарт (Bill Stewart), Джефф Мур (Jeff Moore), Дуг Уайат, 
Майкл Хопкинс (Michael Hopkins), Боб Эрон (Bob Aron), Джеймс 
Маккартни (James McCartney), Мехул Триведи (Mehul Trivedi), 
Синтия Максвелл (Cynthia Maxwell), Тори Уолкер (Torrey Walker), 
Ник Томпсон (Nick Thompson), мэтью Мора (Matthew Mora), Брэд 
Форд (Brad Ford), Марей Джейсон (Murray Jason) и Эдвард Агабег 
(Edward Agabeg): спасибо за то, что разделяете со мной страсть к познанию 
тайн звука.
Отдельное спасибо Дэвиду Авила (David Avila), Дэниэлю Кауф-
ману (Daniel Kaufman), Андрэ Лабраншу (Andre LaBranche), Квентину 
Карничелли (Quentin Carnicelli), Эдду Вину (Ed Wynne) и 
Стиву Джобсу.
Звучит на моем iPod: AC/DC, Rush, Beach Boys, Sublime, Primus, 
KRS-One, Beastie Boys, Mac Dre,Vokab Kompany и великий, как никто 
другой, Джордж Карлин.

1 Актуальный список недавно прослушанных композиций см. по адресу 
www.last.fm/user/invalidname.

10
Благодарности
Об авторах

Крис Адамсон – независимый писатель, редактор и разработчик. 
Проживает в Гранд Рапидс, штат Мичиган. В настоящее время интересуется 
разработкой для iOS и Mac, является соавтором книги 
iOS SDK Development (Pragmatic Programmers, 2012). Также является 
автором книги QuickTime for Java: A Developer’s Notebook (O’Reilly 
Media, 2005) и соавтором Swing Hacks (O’Reilly Media, 2005). Ранее 
работал редактором на сайтах java.net и ONJava.com. Консультационную 
и издательскую деятельность осуществляет через свою компанию 
Subsequently and Furthermore, Inc., специализирующуюся на 
разработке пользовательских интерфейсов и цифрового мультимедийного 
материала для приложений на платформах Mac и iOS. Ведет 
блог по разработке ПО для работы с мультимедиа (www.subfurther.
com/blog). Ранее был автором текстов и помощником продюсера 
на кабельном телевизионном новостном канале CNN Headline News. 
С годами стал счастливым обладателем 11 с половиной Mac’ов.
Кэвин Авила (известный также под ником dogbert) – удачная 
смесь углерода, кислорода, водорода и азота с добавлением небольшого 
количества разных примесей. Попутно имеет за плечами более 
15 лет разработки для Mac и для iPhone – с момента его появления. 
Кэвин засветился в каждом уголке рынка аудио – от инженера в 
Apple до настройки профессиональных студий звукозаписи. В настоящее 
время пишет код по заказу различных клиентов, посиживая 
в нижнем белье у себя дома и попивая кофе.
Предисловие

Задумайтесь о своем ремесле. О тех, кто на протяжении минувших 
столетий разделял аналогичный опыт. О художниках, доводивших 
себя до исступления, пытаясь найти внутри себя источник, который 
позволил бы создать что-то значимое. О промышленниках, веривших, 
что стоят у порога новой эры, которую сами и заложили.
Подумайте о древних поборниках магии, стремящихся овладеть 
силами, скрытыми в тайных знаниях. А затем вспомните, как однажды, 
овладев секретами уличного фокусника – например, потоком 
управления и структурами данных, – вы наконец получили доступ 
к библиотекам API. Представьте себе глаза ученика мага, широко 
распахнувшиеся и заблестевшие от зрелища неисчерпаемых возможностей, 
открывшихся в комнате, полной пахнущих плесенью книг.
Это один из ключевых моментов в карьере любого программиста, 
его можно сравнить с восхождением на вершину холма, с которой 
только открывается вид на гору вдалеке. В этот момент с пугающей 
ясностью осознаешь, что программирование – это путешествие длиною 
в жизнь, на каждом этапе которого предстоит учиться. Многие 
незадавшиеся волшебники просто стремглав выбежали бы из комнаты, 
оставив этот страшный мир ради более спокойного времяпрепровождения.

Но раз вы читаете эти страницы, то принадлежите к немногим 
избранным, у которых имеется генетическая предрасположенность 
к решению трудных задач. Именно они пересекают порог и входят 
в открывшийся мир, без остатка посвящая себя изучению новых заклинаний 
и исследованию новых видов магии.
Ибо что такое программирование, как не магия? Произнесение 
тайных слов для управления могучими силами, которые вы едва понимаете, 
призывание духов ушедших волшебников, чтобы облегчить 
свое бремя, упрощение последовательностей действий и – в качестве 
награды – способность вызывать восторг и удивление непосвященных.

Раздумывая над очередным томом, в котором описываются новые 
виды магии, вы начинаете комбинировать их с тем, что уже знаете, 
Предисловие

и так рождаются новые заклинания, открывающие новые возможности. 
Все познанное ранее мостит дорогу к новым знаниям, дорога 
разветвляется снова и снова, пока в один прекрасный день не 
упирается в тупик.
Во многих древних текстах упоминается темное искусство программирования 
звука, но нигде не дается ясных указаний. И какой 
бы важной ни была технология Core Audio, вы не найдете ни посвященных 
ей книг, ни свитков с заклинаниями, ни даже простого 
примера кода, чтобы попрактиковаться. Программировать звук 
желательно в разных случаях, но коль скоро это черная магия, то 
сведения о ней скудны и непонятны.
Крис Адамсон нашел человека, практикующего звуковые искусства. 
Имя этого седеющего мудреца, сведущего в C, – Кэвин Авила. 
Применяя попеременно подкуп и честное расспрашивание, Крис 
сумел набиться к нему в подмастерья. Кроличья нора, в которую 
он проник, не имеет конца, но, распознавая темные повороты и закоулки 
лишь по слуху, он выучил новый язык для описания звука, 
а вместе с ним и новый взгляд на мир.
Спустя вечность, он – сам уже седеющий мудрец – снова сидел 
в библиотеке, размышляя об отсутствующих томах, и в этот момент 
осознал свое предназначение – пролить свет на темное искусство 
Core Audio. Само определение мастерства предполагает, что мы 
должны обучать тому, чему научились сами. Именно так устроено 
круговращение от подмастерья к мастеру. Именно этот механизм 
стремит поколения вперед, так что каждое проходит дальше по пути 
к той неуловимой маячащей впереди точке, которую мы называем 
будущим.
Как и любой обряд посвящения, задача оказалась титанически 
трудной, потребовала совершенно нового набора навыков и иного 
способа мышления. Мы должны вывернуть наизнанку и себя, и свои 
знания, чтобы найти не только истину, но и скрытую за ней красоту, 
которая оставляет отклик в душах на протяжении многих веков.
Все для того, чтобы в какой-то неведомый момент в будущем там, 
где когда-то был тупик и незаполненный промежуток между Core 
Animation и Core Data, некий юный ученик смог обрести мудрость 
и учительское наставление. Чтобы он смог объединить новое знание 
с тем, что ему уже известно, и подготовиться к встрече с собственными 
тупиками и собственным темным искусством.
Этот момент, любезный читатель, настал. Юный ученик – это ты, 
а колдовская книга, которую ты держишь в руках, содержит всю 
Предисловие

мудрость и более чем достаточно заклинаний, чтобы ты мог перейти 
на следующую ступень постижения магии. Эта книга – твой ключ 
к овладению невыразимой силой, силой звука и природы, силой 
Core Audio.
Что, слишком много слов для какой-то книги о программировании 
звука? Не усмехайтесь скептически, я, пожалуй, расхвалил ее 
даже недостаточно. Звук – невероятно мощная штука по силе воздействия 
на мозг человека, которое мы понимаем очень плохо. Подумайте 
о влиянии музыки на свою жизнь. А теперь учтите, что вся 
на свете музыка составляет жалкие 10% от того, что можно сказать 
о звуке.
Возможности программирования звука далеко не ограничиваются 
тем, что можно воспринять на слух. Раньше для считывания информации 
с кредитной карты был необходим дорогостоящий прибор. 
Теперь для этого достаточно иметь дешевый пластиковый электронный 
ключ, вставляемый в гнездо для наушников в iPhone. Чтобы 
творить чудеса со звуком, не нужна музыка.
Первый образчик кода для Core Audio вы встретите уже в главе 1 
этой книги «Общие сведения о Core Audio», когда только будете 
знакомиться с тем, что такое технология Core Audio и когда имеет 
(а когда не имеет) смысл прибегать к ее мощи.
Core Audio, как и все темные искусства, корнями своими уходит 
в свойства природы. Глава 2 «Кое-что о звуке» повествует о звуке 
не как о природном явлении, а как о науке. Вы узнаете о языке и 
технике, позволяющих переводить колебания молекул воздуха в математические 
формулы, понятные компьютеру, и наоборот.
Вы также узнаете о терминологии, применяемой в работах, посвященных 
звуку, и, в частности, о том, что же на самом деле озна чают 
технические термины, которые вам доводилось слышать, а то и использовать 
на протяжении многих лет: шаг дискретизации, частота 
кадров, буфер и сжатие. Эта тематика будет продолжена в главе 3 
«Обработка звука с помощью Core Audio», где будет сорван покров 
тайны со звуковых форматов и рассказано о канонических форматах, 
используемых на внутреннем уровне Core Audio.
Познакомившись с основами Core Audio, вы, несомненно, захотите 
применить новые умения, освоив такие дешевые трюки, как 
запись (глава 5 «Запись») и воспроизведение (глава 6 «Воспроизведение»), 
с помощью высокоуровневой архитектуры Audio Queue.
Разумеется, слово «высокоуровневый» может показаться неудачным, 
особенно если у вас за плечами опыт работы с таким объектно-
Доступ онлайн
519 ₽
В корзину