Статьи

iOS лаконично — аудио

iOS предоставляет несколько вариантов работы со звуком. В этой главе мы представим две основы для работы с разными типами звуков. Audio Toolbox Framework включает библиотеку C для воспроизведения простых системных звуков, а AVFoundation Framework предоставляет объектно-ориентированный интерфейс для воспроизведения и записи промежуточного уровня.

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

Системный звуковой API определяется в Audio Toolbox Framework. Вся эта структура написана на C вместо Objective-C, поэтому мы будем работать с интерфейсом C в приложении для iOS в первой половине этой главы. Это меняет то, как мы будем взаимодействовать с основными объектами iOS, но пусть это вас не пугает. Мы по-прежнему имеем дело с теми же объектами и концепциями, что и на протяжении всей книги Например, вместо использования метода mainBundle NSBundle , мы будем использовать функцию C под названием CFBundleGetMainBundle () для доступа к пакету приложения.


Как и в предыдущей главе, все, что нам понадобится, — это простое приложение Single View . Создайте новый проект и назовите его Audio . Как обычно, используйте edu.self для Идентификатора компании и iPhone для устройств и убедитесь, что установлены оба флажка: Использовать раскадровки и Использовать автоматический подсчет ссылок .

В отличие от предыдущей главы, нам нужен доступ к двум аудио-фреймворкам, которые не включены в шаблон. Чтобы добавить новый фреймворк в проект, щелкните значок проекта в Навигаторе проектов и выберите цель « Аудио» . На вкладке Сводка прокрутите вниз до раздела Связанные фреймворки и библиотеки .

tutorial_image
Рисунок 113: фреймворки, которые в настоящее время включены в наш проект

Это библиотеки кода, к которым у вас есть доступ из кода приложения. Вам необходимо добавить Audio Toolbox Framework для работы с системными звуками, поэтому щелкните значок плюса в левом нижнем углу. Результирующий диалог содержит список всех доступных платформ и библиотек. Начните вводить « audiotoolbox » в строку поиска, чтобы найти желаемую структуру.

tutorial_image
Рисунок 114: Поиск инфраструктуры Audio Toolbox

Нажмите AudioToolbox.framework, а затем нажмите « Добавить», чтобы включить его в проект. Нам также понадобится доступ к AVFoundation Framework для части AVAudioPlayer этой главы, поэтому повторите процесс и для этой библиотеки. Вы должны увидеть AVFoundation.framework и AudioToolbox.framework на вкладке Сводка, прежде чем двигаться дальше.

tutorial_image
Рисунок 115: Все необходимые библиотеки для нашего примера проекта

Теперь мы готовы начать работу с системными звуками и AVAudioPlayer .


Системные звуки предназначены для использования в простых вещах, таких как оповещения и звуковые эффекты пользовательского интерфейса (например, нажатия кнопок). Они очень просты в использовании, но компромисс в том, что они не предоставляют много возможностей для управления воспроизведением. Основные ограничения API системного звука заключаются в следующем.

  • Звуки не могут быть длиннее тридцати секунд.
  • Вы не можете контролировать громкость системных звуков. Они используют текущий объем устройства. Только один звук может играть одновременно.
  • Звуки не могут быть зациклены или воспроизведены после определенной задержки.
  • Они поддерживают только файлы .caf, .aif и .wav.
  • Невозможно настроить, как звуки справляются с прерываниями, такими как входящие звонки.

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

Пакет ресурсов для этой книги содержит короткий звуковой файл blip.wav . Добавьте это в комплект приложений, перетащив его в Навигатор проектов . Помните, что системные звуки используют интерфейс C, поэтому мы будем обращаться к этому файлу немного другим способом, чем в предыдущих главах. В ViewController.m измените viewDidLoad на следующее.

1
2
3
4
5
6
7
8
— (void)viewDidLoad {
    [super viewDidLoad];
    CFURLRef blipURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
                                               CFSTR («blip»),
                                               CFSTR («wav»),
                                               NULL);
    NSLog(@»%@», blipURL);
}

CFBundleGetMainBundle () по сути такой же, как [[NSBundle] mainBundle] , за исключением того, что он возвращает объект CoreFoundation, который представляет пакет приложения, а не версию Foundation Framework. CoreFoundation Framework — это низкоуровневая альтернатива Foundation Framework . Нам нужно использовать объекты CoreFoundation, потому что это то, что Audio Toolbox принимает в качестве аргументов.

CFBundleCopyResourceURL () является версией CoreFoundation pathForResource: ofType: метода NSBundle . Он просто возвращает путь к запрошенному ресурсу, и вы должны увидеть знакомый путь к файлу в выводе NSLog () .

Когда у вас есть путь к звуковому файлу, вам нужно создать звуковой объект с помощью функции AudioServicesCreateSystemSoundID () . Добавьте следующее к viewDidLoad .

1
AudioServicesCreateSystemSoundID(blipURL, &_blipOne);

Эта функция считывает содержимое звукового файла, превращает его в звуковой объект, который API-интерфейс системного звука умеет воспроизводить, и возвращает идентификатор, который можно использовать для ссылки на него позже. AudioServicesCreateSystemSoundID () определяется Audio Toolbox Framework, поэтому вам необходимо импортировать его в ViewController.m, прежде чем вы сможете его использовать. Добавьте следующее в начало файла.

1
#import <AudioToolbox/AudioToolbox.h>

Вы храните идентификатор звукового объекта в закрытой переменной экземпляра с именем _blip , так что добавьте это и в объявление реализации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@implementation ViewController {
    SystemSoundID _blip;
}
Playing the Sounds
Next, programmatically add a button to the scene;
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [aButton setTitle:@»Blip»
             forState:UIControlStateNormal];
    [aButton addTarget:self
                action:@selector(playBlip:)
      forControlEvents:UIControlEventTouchUpInside];
aButton.frame = CGRectMake(100.0, 200.0, 120.0, 40.0);
[[self view] addSubview:aButton];
For the playBlip: action, we’ll call the AudioServicesPlaySystemSound() function to play the sound.
— (void)playBlip:(id)sender {
    AudioServicesPlaySystemSound(_blip);
}

Когда вы компилируете проект, вы сможете нажать кнопку и услышать короткий звук. Убедитесь, что ваши динамики не отключены.

tutorial_image
Рисунок 116: кнопка

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

AudioServicesCreateSystemSoundID () и AudioServicesPlaySystemSound () — это почти все, что нужно для системных звуков. Также может оказаться полезной функция AudioServicesPlayAlertSound () . Он работает точно так же, как AudioServicesPlaySystemSound () , но заставляет телефон вибрировать, если он у него включен.


Платформа AVFoundation Framework предоставляет интерфейс более высокого уровня для управления воспроизведением аудио. Для игр, пользовательских музыкальных проигрывателей и других приложений, требующих сложного управления звуком, вам следует использовать эту среду. Некоторые из его возможностей включают в себя:

  • Нет ограничений по продолжительности звука.
  • Вы можете воспроизводить несколько звуков одновременно.
  • Громкость можно контролировать для отдельных звуков.
  • По окончании воспроизведения возможно зациклить звук или выполнить другие действия.
  • Вы можете перейти к произвольным точкам в звуковом файле.
  • Легко настроить поведение для обработки прерываний через объект делегата.

AVAudioPlayer — это основной класс, который вы будете использовать в AVFoundation Framework. Он предоставляет объектно-ориентированный способ установки громкости, воспроизведения звука, остановки звука, указания, какую часть звука воспроизводить, и так далее. Вы можете думать об этом как о звуковом эквиваленте UIImage / UIImageView .

Поддерживаемые форматы файлов для AVAudioPlayer включают .m4a, .aac, .wav, .mp3, .aif, .pcm, .caf и некоторые другие. См. Руководство по программированию мультимедиа Apple для подробного обсуждения форматов аудиофайлов.

AVAudioPlayer предназначен для использования с более длинными звуковыми файлами, такими как песни, поэтому мы распространили общедоступную мелодию Billie Holiday с этой книгой. Перетащите файл good-morning-heartache.mp3 из пакета ресурсов в Навигатор проектов, чтобы добавить его в комплект.

Поскольку AVFoundation является библиотекой Objective-C, мы можем вернуться к использованию NSBundle для доступа к медиаресурсам. Идите дальше и удалите все в viewDidLoad и замените его следующим.

1
2
3
4
5
NSURL *soundFileURL = [[NSBundle mainBundle]
                        URLForResource:@»good-morning-heartache»
                         withExtension:@»mp3″];
    _player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL
                                                     error:nil];

URLForResource: withExtension: метод является NSURL-эквивалентом pathForResource: ofType:. Это был лучший вариант для поиска аудиофайла, поскольку для инициализации AVAudioPlayer необходим объект NSURL . Метод initWithContentsOfURL: error: загружает содержимое звукового файла в экземпляр AVAudioPlayer , очень похоже на строку NSString stringWithContentsOfURL: encoding: error: method.

AVAudioPlayer находится в библиотеке AVFoundation, поэтому обязательно добавьте следующий оператор импорта в ViewController.h . Нам понадобится доступ к нему из заголовочного файла позже.

1
#import <AVFoundation/AVFoundation.h>

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@implementation ViewController {
    AVAudioPlayer *_player;
    UIButton *_playButton;
    UIButton *_stopButton;
}
Playing the Song
Next, add a Play button to the scene:
_playButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_playButton setTitle:@»Play»
             forState:UIControlStateNormal];
[_playButton addTarget:self
                action:@selector(playOrPause:)
      forControlEvents:UIControlEventTouchUpInside];
     
_playButton.frame = CGRectMake(100.0, 170.0, 120.0, 40.0);
[[self view] addSubview:_playButton];
The playOrPause: action should be implemented like this:
— (void)playOrPause:(id)sender {
    if (_player.playing) {
        [_player pause];
        [_playButton setTitle:@»Play» forState:UIControlStateNormal];
    } else {
        [_player play];
        [_playButton setTitle:@»Pause» forState:UIControlStateNormal];
    }
}

Это проверяет, играет ли песня уже через свойство воспроизведения AVAudioPlayer . Если это так, он приостанавливает песню, используя метод паузы, и соответственно меняет название кнопки. Если это не так, песня начинается с вызова метода воспроизведения. Теперь вы сможете скомпилировать приложение и воспроизвести или приостановить воспроизведение песни, нажав кнопку.

Давайте сделаем еще один шаг, создав кнопку « Стоп» . Добавьте следующее в метод viewDidLoad .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
_stopButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_stopButton setTitle:@»Stop»
             forState:UIControlStateNormal];
[_stopButton addTarget:self
                action:@selector(stop:)
      forControlEvents:UIControlEventTouchUpInside];
 
_stopButton.frame = CGRectMake(100.0, 230.0, 120.0, 40.0);
[[self view] addSubview:_stopButton];[/sourcecode]
The corresponding action calls the AVAudioPlayer’s stop method.
[sourcecode]- (void)stop:(id)sender {
    [_player stop];
    _player.currentTime = 0;
    [_playButton setTitle:@»Play» forState:UIControlStateNormal];
}

Другое преимущество использования AVAudioPlayer над API системных звуков заключается в том, что он позволяет обрабатывать прерывания с использованием знакомого шаблона делегата. Протокол AVAudioPlayerDelegate определяет ряд методов, которые позволяют вам знать, когда определенные события происходят за пределами вашего приложения.

Когда начинается прерывание, например, входящий телефонный звонок, audioPlayerBeginInterruption: метод вызывается для объекта делегата. Звук будет автоматически приостанавливаться, но это дает вам возможность написать любой другой код обработки, который вам может понадобиться. Аналогично, метод audioPlayerEndInterruption: withOptions: вызывается, когда прерывание заканчивается, и вы можете снова использовать аудиоплеер. Однако система не возобновляет воспроизведение автоматически. Вам нужно вручную вызвать метод play, если вы хотите, чтобы это произошло.

В дополнение к обработке прерываний объект делегата также позволяет узнать, когда закончился звук. Определив audioPlayerDidFinishPlaying: успешно: метод на объекте делегата, вы можете выполнить пользовательскую очистку. Например, вы можете использовать это для сброса кнопки воспроизведения и возврата к началу песни, например, так.

1
2
3
4
— (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    [self stop:nil];
    NSLog(@»Song finished playing!»);
}

Чтобы этот код работал, вам нужно сделать контроллер представления формальным делегатом для AVAudioPlayer . В ViewController.h измените объявление интерфейса на следующее.

1
@interface ViewController : UIViewController <AVAudioPlayerDelegate>

Затем контроллер представления должен назначить себя в качестве объекта делегата. В методе viewDidLoad объекта ViewController.m добавьте следующую строку.

1
_player.delegate = self;

Теперь, если вы позволите воспроизвести песню до конца, кнопка « Пауза» автоматически превратится в кнопку « Воспроизведение» , и нажатие на нее запустит песню с начала.

tutorial_image
Рисунок 117: Наш простой музыкальный проигрыватель

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

Для обычного приложения iOS платформа AVFoundation Framework обеспечивает хороший баланс между удобным API и детальным контролем над звуками. Но имейте в виду, что iOS также предоставляет более продвинутые низкоуровневые аудиофункции, такие как Audio Queue Services, а также высокоуровневый API для взаимодействия с существующей библиотекой iTunes пользователя через Media Player Framework. Для специализированных приложений вы даже можете открыть OpenAL, кроссплатформенную библиотеку для симуляции трехмерной звуковой среды.

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


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

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

Этот урок представляет собой главу из iOS, сжатой , бесплатной электронной книги от команды Syncfusion .