Symbian OS предоставляет в распоряжения разработчиков богатые возможности для работы со звуком. В данной статье рассмотрены вопросы воспроизведения и записи звука в Symbian OS C++ приложениях.
Для работы со звуком в Symbian OS v7.0 добавлен новый межуровневый компонент, называемых Multimedia Framework (MMF). MMF базируется на ECOM plug-in архитектуре. MMF работает с Symbian Audio контроллером. Этот контроллер имеет каждое Symbian OS v7.0 устройство. (Кроме него в системе могут существовать и другие аудио контроллеры, например Advanced Audio Controller (в устройствах фирмы Nokia), но работа с ними останется за рамками этой статьи.)
Symbian OS располагает дополнительными аудио возможностями, называемыми DEVSOUND, позволяющими получить низкоуровневый доступ к звуковому оборудованию устройства. DEVSOUND главным образом используют разработчики игр, которым нужно одновременно проигрывать множество звуков. DEVSOUND также не рассматривается в данной статье.
MMF способен обеспечить локальное и потоковое воспроизведение звуковой информации различных форматов. Программисты могут использовать эти возможности через специальный API, включающий в себя такие функции как Play, Stop и Pause, а также функции по управлению метаданными.
MMF использует plug-in архитектуру, то есть позволяет проводить распознавание форматов и динамическую загрузку необходимых кодеров/декодеров перед непосредственным воспроизведением звука. Это позволяет устройству поддерживать любые аудио форматы, для которых имеются подходящие декодеры.
Несмотря на то, что MMF использует plug-in архитектуру, Wave формат поддерживается по-умолчанию всеми устройствами. Многие устройства поддерживают и другие популярные форматы (Wave, AMR, MIDI, MP3, AAC, Real Audio).
Поскольку кодеки загружаются динамически, при получении запроса MMF использует включенную в звуковой файл MIME информацию для определения необходимого кодека. Другими словами, определение формата не сводится к простому анализу расширения звукового файла. Поэтому при разработки приложения необходимо ориентироваться именно на метаданные.
MMF не способна работать с форматами-оболочками (MP4, 3GP, ...).
MMF предоставляет в распоряжение разработчика простой API, который не зависит ни от формата, ни от типа аудио данных. Этот API используется для работы как с локальным, так и с потоковым контентом. Он обеспечивается следующими классами:
Эти классы расположены в библиотеке MediaClientAudio.lib.
В этом разделе мы обсудим использования класса CMdaAudioPlaybackUtility для решения следующих задач:
Все операции, реализованные классом CMdaAudioPlaybackUtility являются асинхронными. Observer callback API состоит из следующих двух методов:
Эти методы вызываются после завершения инициализации воспроизведения и завершения воспроизведения аудиотрека.
Чтобы выполнить операции воспроизведения, необходимо первым делом создать объект класса CMdaAudioPlayerUtility.
CMdaAudioPlayerUtility* iPlayer = CMdaAudioPlayerUtility::NewL(*this);
Замечание: При создании объекта класса CMdaAudioPlayerUtiltiy можно задать приоритет и предпочтение. Эти параметры являются дополнительными и по умолчанию имеют значения EPriorityNormal и EMdaPriorityPreferenceTimeAndQuality.
После создания объекта, необходимо инициализировать плеер и открыть файл или URL. Файл можно открыть используя его полное имя, либо указатель.
Выполнить операцию открытия файла можно непосредственно при создании объекта плеера:
После завершения операции открытия, нужно вызвать метод MapcInitComplete(). Этот метод возвращает информацию об ошибках, произошедших в процессе открытия. Если все прошло успешно, будет возвращено значение KErrNone. После этого можно приступать к воспроизведению:
iPlayer->Play();
После открытия файла можно установить различные параметры: громкость, повтор, линейное изменение громкости, позицию воспроизведения; и атрибуты: максимальная громкость, текущая позиция, продолжительность воспроизведения. Если попытаться установить их до открытия файла, произойдет ошибка.
Для задания параметров используются следующие методы:
Для получения информации о воспроизведении используйте методы:
Для остановки(паузы) и продолжения воспроизведения:
Для завершения воспроизведения
iPlayer->Stop();
После завершения воспроизведения, вызывается метод MapcComplete(), содержащий информацию об ошибках.
После завершения работы с контентом, необходимо закрыть файл и очистить память:
iPlayer->Close();
Метаданными мы будем называть информацию о аудиотреке, встроенную в заголовок звукового файла. Наибольшее распространенным типом метаданных на сегодняшний день является ID3Tag, используемый в MP3 файлах. Операции CMMFMetaDataEntry API основаны на конвертировании информации, извлеченной из трека. Этот API физически расположен в библиотеке MMFControllerFramework.lib.
Помимо ID3Tag CMMFMetaDataEntry API поддерживает и другие типы метаданных.
При использовании CMMFMetaDataEntry API нужно сначала запросить систему о количестве доступных для указанного файла метаданных.
CMdaAudioPlayerUtility* iPlayerHelper = CMdaAudioPlayerUtility::NewL( *this );
iPlayerHelper->OpenFileL( aFilename );
User::LeaveIfError( iPlayerHelper->GetNumberOfMetaDataEntries( aNumEntries ));
Каждая порция метаданных ставится в соответствие поддерживаемым ID3Tag полям (табл 1).
EntryName элементы | Описание |
KMMFMetaEntrySongTitle | Название песни |
KMMFMetaEntryAlbum | Название альбома |
KMMFMetaEntryArtist | Имя исполнителя |
KMMFMetaEntryAlbumTrack | Номер трека в альбоме |
KMMFMetaEntryYear | Год выхода альбома |
KMMFMetaEntryGenre | Жанр музыки |
KMMFMetaEntryCopyright | Информация о правообладателе |
KMMFMetaEntryComment | Комментарии к треку |
KMMFMetaEntryComposer | Информация о композиторе |
KMMFMetaOriginalArtist | Информация об артисте, исполняющем оригинал |
HBufC* metadataValue=NULL; for( TInt j=0; j< aNumEntries; j++) { CMMFMetaDataEntry* entry=NULL; TRAPD( errorValue, entry= iPlayerHelper->GetMetaDataEntryL(j)); CleanupStack::PushL(entry); if(( errorValue== KErrNone)&&( entry)) { TName name( entry->Name()); TName value( entry->Value()); CleanupStack::PopAndDestroy(entry); if( name.CompareF( aMetadataName)==0) { //Нуль-конец строки TInt i= value.LocateF('\0'); if(i!= KErrNotFound) { value.SetLength(i); } metadataValue= value.AllocLC(); break; } } else { CleanupStack::PopAndDestroy(entry); if(( errorValue!= KErrNotFound)&( errorValue!= KErrNotSupported)) { User::LeaveIfError( errorValue); } } }
Возможность работы с потоками данных позволяет разработчику воспользоваться альтернативным способом получения звукового контента. Использование потоковых данных имеет два преимущества по сравнению с локальным контентом. Во-первых, поскольку контент не сохраняется в файловой системе устройства, он не может быть скопирован; во-вторых, потоковый контент легче обновлять.
Устройства поддерживают несколько потоковых форматов. Практически все устройства по-умолчанию умеют работать с mp3 и Real Audio.
Для проигрывания потокового контента используются интерфейсы CMdaAudioPlayerUtility,CMdaAudioOutputStream и CMdaAudioInputStream. Единственным отличием от проигрывания локального контента является способ открытия и инициализации. Метаданные для потокового контента могут быть получены аналогично локальному.
Как уже отмечалось ранее, MMF не поддерживает форматы-оболочки, поэтому потоковые файлы, такие как AAC, помещенные внутрь MP4, не могут быть воспроизведены. Ссылки на Real Audio файлы, помещенные внутрь *.ram файла, должны быть предварительно извлечены и открыты с помощью метода OpenUrlL(). MMF не поддерживает автоматическое извлечение ссылок из *.ram файлов. Более подробную информацию об извлечении можно найти в документе"Video And Streaming In Nokia Devices".
Необходимо аккуратно относиться к кодированию потоковых файлов. Так из-за плохой пропускной способности сетей файлы, bit rate которых превосходит 192 Kbps, воспроизводятся с заиканием и заметными задержками.
В Symbian OS v7.0 устройствах MMF помимо воспроизведения позволяет осуществлять и запись аудиоинформации.
Как правило, устройства позволяют сохранять записанный звук в форматах WAV и AMR. С помощью присоединения plug-in-ов может быть добавлена поддержка и других форматов.
При записи звука используется та же библиотека (MediaClientAudio.lib), что и при его воспроизведении. Для записи используются классы:
Класс CMdaAudioPlayerUtility используется при записи для решения вспомогательных задач, например CMdaAudioRecorderUtility не умеет изменять громкость и для этих целей используется CMdaAudioPlayerUtility.
Класс CMdaAudioRecorderUtility реализует набор базовых операций, таких как PlayL(), Stop() и OpenFile(), а также методы для записи Crop() и Record().
Процессы записи и воспроизведения очень похожи. Основное внимание в этом разделе будет уделено использованию класса CMdaAudioRecorderUtility.
При реализации класса CMdaAudioRecorderUtility необходимо унаследовать и получить абстрактный класс, состоящий из единственного метода.
void MoscoStateChangeEvent(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode);.
Этот метод будет изменяться каждый раз при изменении состояния CMdaAudioRecorderUtility.
Для начала записи необходимо создать экземпляр класса CMdaAudioRecorderUtility:
CMdaAudioRecorderUtility iRecorder = CMdaAudioRecorderUtility::NewL(*this)
Замечание: При создании объекта класса CMdaAudioRecorderUtility можно задать приоритет и предпочтение. Эти параметры являются дополнительными и по умолчанию имеют значения EMdaPriorityNormal и EMdaPriorityPreferenceTimeAndQuality. Для нормальной записи рекомендуется немного повысить приоритет хотя бы до 80 (100-максимальный).
После создания экземпляра класса CMdaAudioRecorderUtility необходимо открыть файл, куда будет сохраняться информация. Это нужно сделать до начала записи. Открыть файл можно либо используя его полное имя, либо указатель на файл.
После того как файл открыт, можно приступать к непосредственной записи звука. Для этого нужно вызвать метод RecordL():
iRecorder->RecordL();.
Для остановки процесса записи используется метод Stop():
iRecorder->Stop();
Каждый раз после остановки записи рекомендуется закрывать открытый файл (если конечно не предполагается использовать этот же файл для следующей сессии записи).
iRecorder->Close();
После того как файл открыт и выполнены операции воспроизведения или записи, callback функция MoscoStateChangeEvent() будет возвращать информацию о текущем или предыдущем состоянии процесса.
MMF не позволяет весьти запись во время телефонного разговора.
Оригинал: Symbian OS: Creating Audio Applications In C++ Version 1.0 May 11, 2005.
Перевод:aRix