Spec-Zone .ru
спецификации, руководства, описания, API
|
Большинство прикладных программ, которые имеют дело со звуковой потребностью считать звуковые файлы или аудиопотоки. Это - общая функциональность, независимо от того, что программа может впоследствии сделать с данными, которые это читает (такие как игра, соединение, или обработайте это). Точно так же много программ должны записать звуковые файлы (или потоки). В некоторых случаях данные, которые были считаны (или это будет записано) должны быть преобразованы в различный формат.
Как был кратко упомянут в Главе 3, "Получая доступ к Ресурсам Аудиосистемы," API Звука Java предоставляет разработчикам приложений различные средства для ввода/вывода файла и преобразований формата. Прикладные программы могут читать, записать, и преобразовать между множеством форматов звукового файла и форматами аудиоданных.
Глава 2, "Краткий обзор Выбранного Пакета," представлял основные классы, связанные с форматами аудиоданных и звуковыми файлами. Как анализ:
AudioInputStream
объект. (AudioInputStream
наследовался от java.io.InputStream
.) AudioFormat
объект.
Этот формат определяет, как сами аудиосэмплы располагаются, но не структура файла, в котором они могли бы быть сохранены. Другими словами, AudioFormat
описывает "необработанные" аудиоданные, такие как система мог бы вручить Вашу программу после получения этого от ввода микрофона или после парсинга этого от звукового файла. AudioFormat
включает такую информацию как кодирование, порядок байтов, число каналов, уровня выборки, и числа битов на выборку.
AudioFileFormat
объект. AudioFileFormat
включает AudioFormat
объект описать формат аудиоданных, сохраненных в файле, и также, включает информацию о типе файла и длине данных в файле. AudioSystem
класс обеспечивает методы для (1) хранение потока аудиоданных от AudioInputStream
в аудиофайл определенного типа (другими словами, пишущий файл), (2) извлечение потока аудио байтов ( AudioInputStream
) от аудиофайла (другими словами, читая файл), и (3) аудиоданные преобразования от одного формата данных до другого. Существующая глава, которая делится на три раздела, объясняет эти три вида действия.
AudioSystem
класс предоставляет методы, которые позволяют прикладным программам изучать, какие преобразования доступны, как описано позже в этой главе при "Преобразовании Форматов файлов и Форматов данных."
AudioSystem
класс обеспечивает два типа читающих файл служб:
getAudioFileFormat
метод: static AudioFileFormat getAudioFileFormat (java.io.File file)
static AudioFileFormat getAudioFileFormat(java.io.InputStream stream)
static AudioFileFormat getAudioFileFormat (java.net.URL url)
Как упомянуто выше, возвращенный AudioFileFormat
объект говорит Вам тип файла, длину данных в файле, кодировании, порядке байтов, числе каналов, уровня выборки, и числа битов на выборку.
Второй тип читающей файл функциональности дается ими AudioSystem
методы
static AudioInputStream getAudioInputStream (java.io.File file)
static AudioInputStream getAudioInputStream (java.net.URL url)
static AudioInputStream getAudioInputStream (java.io.InputStream stream)
Эти методы дают Вам объект ( AudioInputStream
) это позволяет Вам читать аудиоданные файла, используя один из методов чтения AudioInputStream
. Мы будем видеть пример на мгновение.
Предположите, что Вы пишете приложение редактирования звука, которое позволяет пользователю загружать звуковые данные из файла, выводить на экран соответствующую форму волны или спектрограмму, редактировать звук, воспроизводить отредактированные данные, и сохранять результат в новом файле. Или возможно Ваша программа считает данные, хранившие в файле, применит некоторую обработку сигнала (такую как алгоритм, который замедляет звук, не изменяя его подачу), и затем играйте обработанное аудио. В любом случае Вы должны получить доступ к данным, содержавшимся в аудиофайле. Предположение, что Ваша программа предоставляет некоторые средства пользователю выбрать или определить входной звуковой файл, читая, что аудиоданные файла включают три шага:
AudioInputStream
объект от файла. int totalFramesRead = 0; File fileIn = new File(somePathName); // somePathName is a pre-existing string whose value was // based on a user selection. try { AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(fileIn); int bytesPerFrame = audioInputStream.getFormat().getFrameSize(); // Set an arbitrary buffer size of 1024 frames. int numBytes = 1024 * bytesPerFrame; byte[] audioBytes = new byte[numBytes]; try { int numBytesRead = 0; int numFramesRead = 0; // Try to read numBytes bytes from the file. while ((numBytesRead = audioInputStream.read(audioBytes)) != -1) { // Calculate the number of frames actually read. numFramesRead = numBytesRead / bytesPerFrame; totalFramesRead += numFramesRead; // Here, do something useful with the audio data that's // now in the audioBytes array... } } catch (Exception ex) { // Handle the error... } } catch (Exception e) { // Handle the error... }Давайте смотреть на то, что происходит в вышеупомянутом примере кода. Во-первых, внешний пункт попытки инстанцирует
AudioInputStream
объект посредством звонка AudioSystem.getAudioInputStream(File)
метод. Этот метод прозрачно выполняет все тестирование, требуемое определить, является ли указанный файл фактически звуковым файлом типа, который поддерживается API Звука Java. Если осматриваемый файл (fileIn
в этом примере), не звуковой файл, или звуковой файл некоторого неподдерживаемого типа, UnsupportedAudioFileException
исключение выдается. Это поведение удобно в этом, прикладной программист не должен быть обеспокоен тестированием атрибутов файла, ни соблюдением никаких соглашений о присвоении имен файла. Вместо этого getAudioInputStream
метод заботится обо всем низкоуровневом парсинге и проверке, которая обязана проверять входного файла. Внешнее try
пункт тогда создает байтовый массив, audioBytes
, из произвольной фиксированной длины. Мы удостоверяемся, что его длина в байтах равняется целому числу фреймов, так, чтобы мы не закончили тем, что читали только часть фрейма или, еще хуже, только часть выборки. Этот байтовый массив будет служить буфером, чтобы временно содержать блок аудиоданных, поскольку это читается из потока. Если бы мы знали, что будем читать только очень короткие звуковые файлы, то мы могли бы сделать этот массив той же самой длиной как данные в файле, получая длину в байтах от длины во фреймах, как возвращено AudioInputStream's getFrameLength
метод. (Фактически, мы, вероятно, только использовали бы a Clip
объект вместо этого.), Но избегать исчерпывать память в общем случае, мы вместо этого читаем файл в блоках, один буфер за один раз.
Внутреннее try
пункт содержит a while
цикл, который является, где мы читаем аудиоданные из AudioInputStream
в байтовый массив. Следует добавить, что код в этом цикле, чтобы обработать аудиоданные в этом массиве любым способом является подходящим для потребностей Вашей программы. Если Вы примените некоторую обработку сигнала к данным, то Вы должны будете, вероятно, запросить AudioInputStream's AudioFormat
далее, чтобы изучить число битов на выборку и так далее.
Отметьте что метод AudioInputStream.read(byte[])
возвращает число чтения байтов — не число выборок или фреймов. Этот метод возвращается-1, когда нет больше данных, чтобы читать. После обнаружения этого условия мы повреждаемся от while
цикл.
Предыдущий раздел, описанный основы чтения звукового файла, используя определенные методы AudioSystem
и AudioInputStream
классы. Этот раздел описывает, как выписать аудиоданные к новому файлу.
Следующий AudioSystem
метод создает дисковый файл указанного типа файла. Файл будет содержать аудиоданные, это находится в указанном AudioInputStream
:
static int write(AudioInputStream in, AudioFileFormat.Type fileType, File out)Отметьте, что вторым параметром должны быть одни из типов файлов, поддерживаемых системой (например, AU, AIFF, или WAV), иначе
write
метод бросит IllegalArgumentException
. Чтобы избежать этого, можно протестировать действительно ли деталь AudioInputStream
может быть записан определенному типу файла, вызывая это AudioSystem
метод: static boolean isFileTypeSupported (AudioFileFormat.Type fileType, AudioInputStream stream)который возвратится
true
только если определенная комбинация поддерживается. Более широко можно изучить, какие типы файла система может записать, вызывая один из них AudioSystem
методы:
static AudioFileFormat.Type[] getAudioFileTypes() static AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream)Первый из этих возвратов все типы файла, который система может записать, и вторые возвраты только те, которых система может записать из данного потока звукового входа.
Следующая выборка демонстрирует один метод для того, чтобы создать выходной файл из AudioInputStream
использование write
метод упоминается выше.
File fileOut = new File(someNewPathName); AudioFileFormat.Type fileType = fileFormat.getType(); if (AudioSystem.isFileTypeSupported(fileType, audioInputStream)) { AudioSystem.write(audioInputStream, fileType, fileOut); }Первый оператор выше, создает новое
File
объект, fileOut
, с пользователем - или определенный программой путь. Второй оператор получает тип файла от существования ранее AudioFileFormat
объект вызывают fileFormat
, который, возможно, был получен из другого звукового файла, такого как тот, который был считан в "разделе" Звуковых файлов Чтения этой главы. (Вы могли вместо этого предоставить любой поддерживаемый тип файла, который Вы хотите, вместо того, чтобы получить тип файла откуда-либо. Например, Вы могли бы удалить второй оператор и заменить другие два возникновения fileType
в коде выше с AudioFileFormat.Type.WAVE
.) Третий оператор тестирует, может ли файл определяемого типа быть записан из требуемого AudioInputStream
. Как формат файла, этот поток, возможно, был получен из звукового файла ранее чтение. (Если так, по-видимому Вы обработали или изменили его данные в некотором роде, потому что иначе есть более легкие способы просто скопировать файл.) Или возможно поток содержит байты, которые были недавно получены от ввода микрофона.
Наконец, поток, тип файла, и выходной файл передают к AudioSystem
.write
метод, чтобы выполнить цель записи файла.
Вспомните из раздела, "Каковы Отформатированные Аудиоданные?" в Главе 2, "Краткий обзор Выбранного Пакета," это API Звука Java различает форматы аудиофайла и форматы аудиоданных. Эти два более или менее независимы. Примерно говоря, формат данных обращается к пути, которым компьютер представляет каждый, необработанные данные указывают (выборка), в то время как формат файла обращается к организации звукового файла как сохраненный на диске. У каждого формата звукового файла есть определенная структура, которая определяет, например, информацию, хранившую в заголовке файла. В некоторых случаях формат файла также включает структуры, которые содержат некоторую форму метаданных, в дополнение к фактическим "необработанным" аудиосэмплам. Остаток от этой главы исследует методы API Звука Java, которые включают множеству преобразования формата данных и формат файла.
Эти покрытия раздела основные принципы преобразования аудиофайла вводят API Звука Java. Еще раз мы излагаем гипотетическую программу, цель которой, на сей раз, состоит в том, чтобы считать аудиоданные из произвольного входного файла и записать это в файл, тип которого является AIFF. Конечно, входной файл должен иметь тип, что система способна к чтению, и выходной файл должен иметь тип, что система способна к записи. (В этом примере мы предполагаем, что система способна к записи файлов AIFF.) Пример программы не делает никакого преобразования формата данных. Если входной формат данных файла не может быть представлен как файл AIFF, программа просто уведомляет пользователя той проблемы. С другой стороны, если входной звуковой файл уже файл AIFF, программа уведомляет пользователя, что нет никакой потребности преобразовать это.
Следующая функция реализует логику, только описанную:
public void ConvertFileToAIFF(String inputPath, String outputPath) { AudioFileFormat inFileFormat; File inFile; File outFile; try { inFile = new File(inputPath); outFile = new File(outputPath); } catch (NullPointerException ex) { System.out.println("Error: one of the ConvertFileToAIFF" +" parameters is null!"); return; } try { // query file type inFileFormat = AudioSystem.getAudioFileFormat(inFile); if (inFileFormat.getType() != AudioFileFormat.Type.AIFF) { // inFile is not AIFF, so let's try to convert it. AudioInputStream inFileAIS = AudioSystem.getAudioInputStream(inFile); inFileAIS.reset(); // rewind if (AudioSystem.isFileTypeSupported( AudioFileFormat.Type.AIFF, inFileAIS)) { // inFileAIS can be converted to AIFF. // so write the AudioInputStream to the // output file. AudioSystem.write(inFileAIS, AudioFileFormat.Type.AIFF, outFile); System.out.println("Successfully made AIFF file, " + outFile.getPath() + ", from " + inFileFormat.getType() + " file, " + inFile.getPath() + "."); inFileAIS.close(); return; // All done now } else System.out.println("Warning: AIFF conversion of " + inFile.getPath() + " is not currently supported by AudioSystem."); } else System.out.println("Input file " + inFile.getPath() + " is AIFF." + " Conversion is unnecessary."); } catch (UnsupportedAudioFileException e) { System.out.println("Error: " + inFile.getPath() + " is not a supported audio file type!"); return; } catch (IOException e) { System.out.println("Error: failure attempting to read " + inFile.getPath() + "!"); return; } }
Как упомянуто, цель этой функции в качестве примера, ConvertFileToAIFF
, должен запросить входной файл, чтобы определить, является ли это звуковым файлом AIFF, и если это не, чтобы попытаться преобразовать это в одного, производя новую копию, путь которой определяется вторым параметром. (Как осуществление, Вы могли бы попытаться делать эту функцию более общей, так, чтобы вместо того, чтобы всегда преобразовать в AIFF, функция преобразовала в тип файла, определенный новым аргументом функции.) Отмечают, что формат аудиоданных копии — то есть, новый файл - подражает формату аудиоданных исходного входного файла.
Большая часть этой функции является очевидной и не является определенной для API Звука Java. Есть, однако, несколько методов API Звука Java, используемых подпрограммой, которые крайне важны для звуковых преобразований типа файла. Эти вызовы метода все находятся во втором try
пункт, выше, и включает следующее:
AudioSystem.getAudioFileFormat
: используемый здесь, чтобы определить, является ли входной файл уже типом AIFF. Если так, функция быстро возвращается; иначе попытка преобразования продолжается. AudioSystem.isFileTypeSupported
: Указывает, может ли система записать файл указанного типа, который содержит аудиоданные от указанного AudioInputStream.
В нашем примере, этот метод возвраты true
если указанный файл звукового входа может быть преобразован в формат аудиофайла AIFF. Если AudioFileFormat.Type.AIFF
не поддерживается, ConvertFileToAIFF
выпускает предупреждение, что входной файл не может быть преобразован, затем возвращается. AudioSystem.write
: используемый здесь, чтобы записать аудиоданные из AudioInputStream inFileAIS
к выходному файлу outFile
.
isFileTypeSupported
, помогает определить, перед записью, может ли определенный входной звуковой файл быть преобразован в определенный выходной тип звукового файла. В следующем разделе мы будем видеть как с несколькими модификациями к этому ConvertFileToAIFF
демонстрационная подпрограмма, мы можем преобразовать формат аудиоданных, так же как тип звукового файла.
Предыдущий раздел показал, как использовать API Звука Java, чтобы преобразовать файл из одного формата файла (то есть, один тип звукового файла) другому. Этот раздел исследует некоторые из методов, которые включают преобразованиям формата аудиоданных.
В предыдущем разделе мы читаем данные из файла произвольного типа, и сохранили это в файле AIFF. Отметьте, что, хотя мы изменили тип файла, используемого, чтобы хранить данные, мы не изменяли формат аудиоданных непосредственно. (Наиболее распространенные типы аудиофайла, включая AIFF, могут содержать аудиоданные различных форматов.), Так если исходный файл содержавшие аудиоданные качества CD (16-разрядный объем выборки, демонстрационный уровень на 44.1 кГц, и два канала), так был бы наш выходной файл AIFF.
Теперь предположите, что мы хотим определить формат данных выходного файла, так же как тип файла. Например, возможно мы сохранили много длинных файлов для использования в Интернете, и обеспокоены количеством дискового пространства и загружаем время, требуемое нашими файлами. Мы могли бы хотеть создавать меньшие файлы AIFF, которые содержат данные например более низкого разрешения, данные, у которых есть 8-разрядный объем выборки, демонстрационный уровень на 8 кГц, и единственный канал.
Не проникая в так много деталей кодирования как прежде, давайте исследовать некоторые из методов, используемых для преобразования формата данных, и давайте рассматривать модификации, которые мы должны были бы сделать к ConvertFileToAIFF
функция, чтобы выполнить новую цель.
Основной метод для преобразования аудиоданных, еще раз, находится в AudioSystem
класс. Этот метод является разновидностью getAudioInputStream
:
AudioInputStream getAudioInputStream(AudioFormat format, AudioInputStream stream)Эта функция возвращается
AudioInputStream
это - результат преобразования AudioInputStream
, stream
, использование обозначенного AudioFormat
, format
. Если преобразование не поддерживается AudioSystem
, эта функция бросает IllegalArgumentException
. Избегать, чтобы, мы могли сначала проверить, может ли система выполнить необходимое преобразование, вызывая это AudioSystem
метод:
boolean isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat)В этом случае мы передали бы
stream.getFormat()
как второй параметр. Создать определенное AudioFormat
объект, мы используем один из двух AudioFormat
конструкторы, показанные ниже, также
AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian)который создает
AudioFormat
с линейным кодированием PCM и данными параметрами, или AudioFormat(AudioFormat.Encoding encoding, float sampleRate, int sampleSizeInBits, int channels, int frameSize, float frameRate, boolean bigEndian)который также создает
AudioFormat
, но позволяет Вам определять кодирование, тип телосложения, и частоту кадров, в дополнение к другим параметрам. Теперь, вооруженный методами выше, давайте видеть, как мы могли бы расширить наш ConvertFileToAIFF
функция, чтобы выполнить требуемые "низкие-res" аудиоданные форматирует преобразование. Во-первых, мы создали бы AudioFormat
объект, описывающий требуемый выходной формат аудиоданных. Следующий оператор был бы достаточен и мог быть вставлен около вершины функции:
AudioFormat outDataFormat = new AudioFormat((float) 8000.0, (int) 8, (int) 1, true, false);Начиная с
AudioFormat
конструктор выше описывает формат с 8-разрядными выборками, последний параметр конструктору, который определяет, с обратным порядком байтов ли выборки или с прямым порядком байтов, не важен. (Большой против прямого порядка байтов только проблема, если объем выборки больше чем единственный байт.) Следующий пример показывает, как мы использовали бы это новое AudioFormat
преобразовать AudioInputStream
, inFileAIS
, то, что мы создали из входного файла:
AudioInputStream lowResAIS; if (AudioSystem.isConversionSupported(outDataFormat, inFileAIS.getFormat())) { lowResAIS = AudioSystem.getAudioInputStream (outDataFormat, inFileAIS); }Не имело бы значения слишком много, где мы вставили этот код, пока это было после конструкции
inFileAIS
. Без isConversionSupported
тест, вызов привел бы к сбою и бросил бы IllegalArgumentException
если определенное преобразование, которое требуют, неподдерживалось. (В этом случае управление передало бы соответствующему catch
пункт в нашей функции.) Так этой точкой в процессе, мы произвели бы новое AudioInputStream
, следуя из преобразования исходного входного файла (в AudioInputStream
форма) к требуемым аудиоданным с низкой разрешающей способностью форматируют как определено outDataFormat
.
Заключительный шаг, чтобы произвести требуемый звуковой файл AIFF с низкой разрешающей способностью должен был бы заменить AudioInputStream
параметр в звонке AudioSystem.write
(то есть, первый параметр) с нашим преобразованным потоком, lowResAIS
, следующим образом:
AudioSystem.write(lowResAIS, AudioFileFormat.Type.AIFF, outFile);Эти немного модификаций к нашему более раннему функциональному продукту что-то, что преобразовывает и аудиоданные и формат файла любого указанного входного файла, предполагая, конечно, что система поддерживает преобразование.
Несколько AudioSystem
методы тестируют свои параметры, чтобы определить, поддерживает ли система определенное преобразование формата данных или пишущую файл работу. (Как правило, каждый метод соединяется с другим, который выполняет преобразование данных или пишет файл.) Один из этих методов запроса, AudioSystem.isFileTypeSupported
, использовался в нашей функции в качестве примера, ConvertFileToAIFF
, определить, была ли система способна к записи аудиоданных к файлу AIFF. Связанное AudioSystem
метод, getAudioFileTypes(AudioInputStream)
, возвращает полный список поддерживаемых типов файлов для данного потока, как массив AudioFileFormat.Type
экземпляры. Метод:
boolean isConversionSupported(AudioFormat.Encoding encoding,используется, чтобы определить, может ли поток звукового входа указанного кодирования быть получен из потока звукового входа, у которого есть указанный аудиоформат. Точно так же метод:
AudioFormat format)
boolean isConversionSupported(AudioFormat newFormat, AudioFormat oldFormat)
говорит нам ли AudioInputStream
с указанным аудиоформатом, newFormat
, может быть получен через преобразование AudioInputStream
у этого есть аудиоформат oldFormat
. (Этот метод был вызван в выборке кода предыдущего раздела, которая создала поток звукового входа с низкой разрешающей способностью, lowResAIS
.)
Эти связанные с форматом запросы помогают предотвратить ошибки, пытаясь выполнить преобразования формата с API Звука Java.