Spec-Zone .ru
спецификации, руководства, описания, API
|
Как обсуждено в Главе 13, "Введение в Интерфейсы Поставщика услуг," API Звука Java включает два пакета, javax.sound.sampled.spi
и javax.sound.midi.spi
, это определяет абстрактные классы, которые будут использоваться разработчиками звуковых служб. Реализовывая и устанавливая подкласс одного из этих абстрактных классов, поставщик услуг регистрирует новую службу, расширяя функциональность системы времени выполнения. Существующая глава говорит Вам, как пойти об использовании javax.sound.sampled.spi
пакет, чтобы предоставить новые услуги для того, чтобы обработать выбранное аудио.
Эта глава может быть безопасно пропущена прикладными программистами, которые просто хотят использовать существующие аудио службы в их программах. Для использования установленных аудио служб в прикладной программе см. Первую часть, "Выбранное Аудио," из Руководства этого Программиста. Эта глава предполагает, что читатель знаком с методами API Звука JavaTM, которые прикладные программы вызывают, чтобы получить доступ к установленным аудио службам.
Есть четыре абстрактных класса в javax.sound.sampled.spi
пакет, представляя четыре различных типов служб, что можно предусмотреть выбранную аудиосистему:
AudioFileWriter
предоставляет пишущие звуковой файл услуги. Эти службы позволяют прикладной программе записать поток аудиоданных к файлу определенного типа. AudioFileReader
предоставляет читающие файл услуги. Эти службы позволяют прикладной программе установить характеристики звукового файла, и получить поток, из которого могут быть считаны аудиоданные файла. FormatConversionProvider
предоставляет услуги для того, чтобы преобразовать форматы аудиоданных. Эти службы позволяют прикладной программе преобразовывать аудиопотоки от одного формата данных до другого. MixerProvider
обеспечивает управление определенным видом микшера. Этот механизм позволяет прикладной программе получать информацию о, и экземпляры доступа, данный вид микшера.
В основном есть двойная изоляция экземпляров службы от разработчика приложений. Прикладная программа никогда непосредственно создает экземпляры объектов службы, таких как микшеры или преобразователи формата, в которых она нуждается для его задач обработки аудиоданных. И при этом программа даже непосредственно не запрашивает эти объекты от классов SPI, которые администрируют их. Прикладная программа обращается с просьбами к AudioSystem
объект в javax.sound.sampled
пакет, и AudioSystem
поочередно использует объекты SPI обработать эти запросы и запросы на обслуживание.
Существование новых аудио служб могло бы быть абсолютно прозрачным и пользователю и прикладному программисту. Все ссылки приложения через стандартные объекты javax.sound.sampled
пакет, прежде всего AudioSystem
, и специальная обработка, которую могли бы обеспечивать новые службы, часто полностью скрывается.
В этой главе мы будем продолжать соглашение предыдущей главы обращения к новым подклассам SPI именами как AcmeMixer
и AcmeMixerProvider
.
Давайте запустим с AudioFileWriter
, один из более простых классов SPI.
Подкласс, который реализует методы AudioFileWriter
должен обеспечить реализации ряда методов, чтобы обработать запросы о форматах файлов и типах файлов, поддерживаемых классом, так же как обеспечить методы, которые фактически выписывают предоставленный поток аудиоданных к a File
или OutputStream
.
AudioFileWriter
включает два метода, у которых есть конкретные реализации в базовом классе:
boolean isFileTypeSupported(AudioFileFormat.Type fileType) boolean isFileTypeSupported(AudioFileFormat.Type fileType, AudioInputStream stream)Первый из этих методов сообщает вызывающей стороне, может ли этот писатель файла записать звуковые файлы указанного типа. Этот метод является справкой по общим вопросам, он возвратится
true
если писатель файла может записать такой файл, предполагая, что писателю файла вручают соответствующие аудиоданные. Однако, возможность записать файл может зависеть от формата определенных аудиоданных, которые это вручается писателю файла. Писатель файла не мог бы поддерживать каждый формат аудиоданных, или ограничение могло бы быть наложено форматом файла непосредственно. (Не все виды аудиоданных могут быть записаны всем видам звуковых файлов.) Второй метод является более определенным, тогда, спрашивая ли деталь AudioInputStream
может быть записан определенному типу файла. Обычно, Вы не должны будете переопределить эти два конкретных метода. Каждый - просто обертка, которая вызывает один из двух других методов запроса и выполняет итерации по возвращенным результатам. Эти другие два метода запроса абстрактны и поэтому должны быть реализованы в подклассе:
abstract AudioFileFormat.Type[] getAudioFileTypes() abstract AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream)Эти методы соответствуют непосредственно предыдущим двум. Каждый возвращает массив всех поддерживаемых типов файлов - все, что поддерживается вообще, в случае первого метода, и все, что поддерживается для определенного аудиопотока, в случае второго метода. Типичная реализация первого метода могла бы просто возвратить массив, который инициализирует конструктор писателя файла. Реализация второго метода могла бы протестировать поток
AudioFormat
объект видеть, является ли это форматом данных, который поддерживает требуемый тип файла. Заключительные два метода AudioFileWriter
сделайте фактическую пишущую файл работу:
abstract int write(AudioInputStream stream, AudioFileFormat.Type fileType, java.io.File out) abstract int write(AudioInputStream stream, AudioFileFormat.Type fileType, java.io.OutputStream out)Эти методы пишут поток байтов, представляющих аудиоданные потоку или файлу, определенному третьим параметром. Детали того, как это делается, зависят от структуры указанного типа файла.
write
метод должен записать заголовок файла и аудиоданные, таким образом предписанные для звуковых файлов этого формата (является ли это стандартным типом звукового файла или нового, возможно собственный).
AudioFileReader
класс состоит из шести абстрактных методов, которые Ваш подкласс должен реализовать фактически, два различных перегруженных метода, каждый из которых может взять a File
, URL
, или InputStream
параметр. Первый из этих перегруженных методов принимает запросы о формате файла указанного файла:
abstract AudioFileFormat getAudioFileFormat( java.io.File file) abstract AudioFileFormat getAudioFileFormat( java.io.InputStream stream) abstract AudioFileFormat getAudioFileFormat( java.net.URL url)Типичная реализация
getAudioFileFormat
метод читает и анализирует заголовок звукового файла, чтобы установить его формат файла. См. описание класса AudioFileFormat, чтобы видеть то, что поля должны быть считаны из заголовка, и отсылать к спецификации для определенного типа файла, чтобы выяснить, как проанализировать заголовок. Поскольку вызывающая сторона, обеспечивающая поток как параметр этому методу, ожидает, что поток будет неизменен методом, средство чтения файлов должно обычно запуститься, отмечая поток. После чтения до конца заголовка, это должно сбросить поток к своей исходной позиции.
Другой перегруженный AudioFileReader
метод предоставляет читающие файл услуги, возвращая AudioInputStream, из которого могут быть считаны аудиоданные файла:
abstract AudioInputStream getAudioInputStream( java.io.File file) abstract AudioInputStream getAudioInputStream( java.io.InputStream stream) abstract AudioInputStream getAudioInputStream( java.net.URL url)Как правило, реализация
getAudioInputStream
возвраты AudioInputStream
раньте к началу блока данных файла (после заголовка), готовый к чтению. Это было бы мыслимо, тем не менее, для средства чтения файлов, чтобы возвратиться AudioInputStream
чей аудиоформат представляет поток данных, которые в некотором роде декодируются от того, что содержится в файле. Важная вещь состоит в том, что метод возвращает отформатированный поток, из которого могут быть считаны аудиоданные, содержавшиеся в файле. AudioFormat
инкапсулировавший в возвращенном AudioInputStream
объект сообщит вызывающей стороне о формате данных потока, который обычно является, но не обязательно, то же самое как формат данных в файле непосредственно. Обычно, возвращенный поток является экземпляром AudioInputStream
; маловероятно, что Вы должны были бы когда-либо разделять на подклассы AudioInputStream
.
A FormatConversionProvider
подкласс преобразовывает AudioInputStream
у этого есть один формат аудиоданных в тот, у которого есть другой формат. Прежний (ввод) поток упоминается как исходный поток, и последний (вывод), поток упоминается как целевой поток. Вспомните из Главы 2, "Краткий обзор Выбранного Пакета," это AudioInputStream
содержит AudioFormat
, и AudioFormat
поочередно содержит определенный тип кодирования данных, представленного AudioFormat.Encoding
объект. Формат и кодирующий в исходном потоке вызывают исходным форматом и исходным кодированием, и тех в целевом потоке аналогично вызывают целевым форматом и целевым кодированием.
Работа преобразования выполняется в перегруженном абстрактном методе FormatConversionProvider
вызванный getAudioInputStream
. У класса также есть абстрактные методы запроса для того, чтобы узнать обо всей поддерживаемой цели и исходных форматах и кодировках. Есть конкретные методы обертки для того, чтобы запросить об определенном преобразовании.
Две разновидности getAudioInputStream
:
abstract AudioInputStream getAudioInputStream( AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream)и
abstract AudioInputStream getAudioInputStream( AudioFormat targetFormat, AudioInputStream sourceStream)Они отличаются по первому параметру, согласно тому, определяет ли вызывающая сторона полный целевой формат или только кодирование формата.
Типичная реализация getAudioInputStream
работы, возвращая новый подкласс AudioInputStream
это переносит оригинал (источник) AudioInputStream
и применяет преобразование формата данных в его данные всякий раз, когда a read
метод вызывается. Например, рассмотрите случай нового FormatConversionProvider
подкласс вызывают AcmeCodec
, который работает с новым AudioInputStream
подкласс вызывают AcmeCodecStream
.
Реализация AcmeCodec's
второй getAudioInputStream
метод мог бы быть:
public AudioInputStream getAudioInputStream (AudioFormat outputFormat, AudioInputStream stream) { AudioInputStream cs = null; AudioFormat inputFormat = stream.getFormat(); if (inputFormat.matches(outputFormat) ) { cs = stream; } else { cs = (AudioInputStream) (new AcmeCodecStream(stream, outputFormat)); tempBuffer = new byte[tempBufferSize]; } return cs; }Фактическое преобразование формата имеет место в новом
read
методы возвращенного AcmeCodecStream
, подкласс AudioInputStream
. Снова, прикладные программы, которые получают доступ к этому, возвратились AcmeCodecStream
просто работайте на этом как AudioInputStream
, и не должны знать детали о его реализации. Другие методы a FormatConversionProvider
все разрешение запрашивает о кодировках входа и выхода и форматах, которые поддерживает объект. Следующие четыре метода, будучи абстрактным, должны быть реализованы:
abstract AudioFormat.Encoding[] getSourceEncodings() abstract AudioFormat.Encoding[] getTargetEncodings() abstract AudioFormat.Encoding[] getTargetEncodings( AudioFormat sourceFormat) abstract AudioFormat[] getTargetFormats( AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat)
Как в методах запроса AudioFileReader
класс, обсужденный выше, эти запросы обычно обрабатываются, проверяя частные данные объекта и, для последних двух методов, сравнивая их против параметра (ов).
Оставление четыре FormatConversionProvider
методы конкретны и обычно не должны быть переопределены:
boolean isConversionSupported( AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat) boolean isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat) boolean isSourceEncodingSupported( AudioFormat.Encoding sourceEncoding) boolean isTargetEncodingSupported( AudioFormat.Encoding targetEncoding)Как с
AudioFileWriter.isFileTypeSupported()
, реализация по умолчанию каждого из этих методов является по существу оберткой, которая вызывает один из других методов запроса и выполняет итерации по возвращенным результатам.
Поскольку его имя подразумевает, a MixerProvider
экземпляры предоставлений микшеров. Каждый бетон MixerProvider
разделите действия на подклассы как фабрику для Mixer
объекты используются прикладной программой. Конечно, определение нового MixerProvider
только имеет смысл если один или более новые реализации Mixer
интерфейс также определяется. Как в FormatConversionProvider
пример выше, где наш getAudioInputStream
метод, возвращенный подкласс AudioInputStream
это выполняло преобразование, наш новый класс AcmeMixerProvider
имеет метод getMixer
это возвращает экземпляр другого нового класса, который реализует Mixer
интерфейс. Мы вызовем последний класс AcmeMixer
. Особенно, если микшер реализуется в аппаратных средствах, провайдер мог бы поддерживать только один статический экземпляр требуемого устройства. Если так, это должно возвратить этот статический экземпляр в ответ на каждый вызов getMixer
.
С тех пор AcmeMixer
поддерживает Mixer
интерфейс, прикладные программы не требуют, чтобы никакая дополнительная информация получила доступ к своей основной функциональности. Однако, если AcmeMixer
поддерживает функциональность, не определенную в Mixer
интерфейс, и поставщик хотят сделать эту расширенную функциональность доступной для прикладных программ, микшер должен, конечно, быть определен как общедоступный класс с дополнительными, хорошо задокументированными открытыми методами, так, чтобы программа, которая хочет использовать эту расширенную функциональность, могла импортировать AcmeMixer
и бросок объект, возвращенный getMixer
к этому типу.
Другие два метода MixerProvider
:
abstract Mixer.Info[] getMixerInfo()и
boolean isMixerSupported(Mixer.Info info)Эти методы позволяют аудиосистеме определять, может ли этот определенный класс провайдера произвести устройство, в котором нуждается прикладная программа. Другими словами,
AudioSystem
объект может выполнить итерации по всему установленному MixerProviders
видеть, которые, если таковые вообще имеются, могут предоставить устройство, которое прикладная программа запросила AudioSystem
. (См. обсуждение при "Получении Микшера" в Главе 3, "Получая доступ к Ресурсам Аудиосистемы.") getMixerInfo
метод возвращает массив объектов, содержащих информацию о видах микшера, доступного от этого объекта провайдера. Система может передать эти информационные объекты, наряду с теми от других провайдеров, к прикладной программе. Сингл MixerProvider
может обеспечить больше чем один вид микшера. Когда система вызывает MixerProvider's getMixerInfo
метод, это получает список информационных объектов, идентифицирующих различные виды микшера, который поддерживает этот провайдер. Система может тогда вызвать MixerProvider.getMixer(Mixer.Info)
получить каждый микшер интереса.
Ваш подкласс должен реализовать getMixerInfo
, поскольку это абстрактно. isMixerSupported
метод конкретен и не должен обычно быть переопределен. Реализация по умолчанию просто сравнивает обеспеченный Mixer.Info
каждому в массиве, возвращенном getMixerInfo
.