Как извлечь звуковые данные из файла wav?
во-первых, это домашнее задание или... проект.
У меня возникли проблемы с пониманием идеи о том, как рисовать звуковые волны данных на графике на Java для проекта. Я должен сделать это задание полностью с нуля с помощью пользовательского интерфейса и всего, что в основном делает.редактор файлов wav. основная проблема, с которой я сталкиваюсь, - это получение звуковых данных в график для рисования. В настоящее время у меня есть случайно сгенерированный массив значений, которые просто рисуются правильно сейчас.
до сих пор у меня есть мини-программа, работающая и проверяющая wav-файл, чтобы он действительно был wav-файлом.
Я читаю ее с FileInputStream и форумчане: рифф байтов(0-3), FileLength(4-7), волна байт(8-11), то формат блока формата(начиная с конца RIFF кусок; и позиционирование индекса до конца его и давая формате 0-3, длина формата кусок 4-7, затем следующие 16 байт для всех технические характеристики Wave-файл и хранение их в соответствующих именованных переменных.
Как только я доберусь до куска данных и его длины, это все мои звуковые данные, и это то, что я не уверен, как хранить каждый байт для байта звуковых данных или даже перевести его в значение, связанное с амплитудой звука. Я думал, что проверка была похожа, поэтому она будет такой же, но это не так... Либо это, либо я усложняю что-то супер простое, так как я смотрел на это несколько раз дней теперь.
любая помощь приветствуется спасибо.
3 ответов
Я не программист Java,но я знаю достаточно много о рендеринге звука, поэтому, надеюсь, следующее может помочь...
учитывая, что у вас почти всегда будет гораздо больше образцов, чем доступных пикселей, разумно было бы сделать, чтобы сделать из кэшированного сокращения или "резюме" данных образца. Это, как правило, как аудио Редакторы (например,смелость) аудио данных. На самом деле наиболее распространенной стратегией является вычисление числа образцы на пиксель, затем найдите максимальные и минимальные образцы для каждого блока размера SamplesPerPixel
, затем нарисуйте вертикальную линию между каждой парой max-min. Возможно, вы захотите кэшировать это сокращение или, возможно, серию таких сокращений для разных уровней масштабирования. Audacity кэширует временные файлы ('block files') на диске.
вышеизложенное, возможно, является чем-то вроде упрощения, однако, потому что на самом деле вы захотите вычислить начальные пары max-min из куска фиксированного размера-скажем 256 образцов-а не из одного размера SamplesPerPixel
. Затем вы можете вычислить дальнейшие сокращения "на лету" из этого кэшированного сокращения. Дело в том, что SamplesPerPixel
обычно будет динамической величиной-так как пользователь может изменить размер холста в любое время (надеюсь, что это имеет смысл...).
также помните, что при рисовании на холсте вам нужно будет масштабировать значения выборки по ширине и высоте холста. Лучший способ сделать это (по крайней мере, в вертикальном направлении) - чтобы нормализовать образцы, умножьте их на высоту холста. 16-битный звук состоит из сэмплов в диапазоне [-32768, 32767], поэтому для нормализации просто сделайте деление с плавающей запятой на 32768. Затем переверните знак (чтобы перевернуть форму волны в координаты холста), добавьте 1 (чтобы компенсировать отрицательные значения) и умножьте на пол высоту холста. Во всяком случае, так я это делаю.
этой страница показывает, как построить рудиментарный дисплей формы волны С Java Качать. Я не рассматривал его подробно, но я думаю, что он просто уменьшает данные, а не вычисляет пары max-min. Это, конечно, не обеспечит такое точное сокращение, как метод max-min, но его легче рассчитать.
Если вы хотите знать, как делать все правильно, вы должны копаться в исходном коде Audacity (будьте осторожны, однако - это довольно gnarly c++). Чтобы получить общий обзор вы можете посмотреть на ' быстрая структура данных для дискового аудио Редактирование', оригинальным автором Audacity, Доминик Маццони. Вам нужно будет приобрести это от CMJ однако.
для стандартных файлов WAV это на самом деле довольно просто. Как только вы пройдете мимо заголовков, вы просто интерпретируете каждые 16 бит как целое число дополнения two. Я бы рекомендовал использовать DataInputStream, так как тогда это так же просто, как вызов readShort().
Это значения амплитуды в каждой точке выборки. Вы можете сделать некоторые средние значения или что-то еще, потому что в большинстве случаев будет больше образцов, чем горизонтальных пикселей. Попытка построить все образцы на каком-то линейном графике возможно, это не лучший способ.
Первое, что вам нужно сделать, это прочитать исходные данные. Написание парсера WAV-файлов не слишком сложно, но вы также можете использовать API javasound. Есть несколько отличных советов и пример кода для использования этого api здесь:
Если вы хотите написать свой собственный парсер, вы можете начать здесь:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
Как только вы имеете сырцовые данные, вы может отображать его как функцию времени. Это называется Волны.
однако отображение формы волны занимает много времени, когда пользователь "уменьшил масштаб" на большом количестве данных: стоимость часа данных займет много времени, чтобы отобразить таким образом. Поэтому большинство приложений предварительно вычисляют некоторые данные, чтобы сделать рисование уменьшенных данных быстрее. "Правильный" способ сделать это заключается в следующем:
- цикл на блоках образцов в файле (от 50 до 500 или так)
- прочитайте блок образцов
- взять абсолютное значение всех этих образцов
- примите максимум абсолютного значения
- сохранить максимум как значение "zoomed out" для этого блока
когда я говорю "правильно", я имею в виду, что это то, что все делают, поэтому это приведет к представлению, которое выглядит так, как люди ожидают. Если вы делаете что-то другое (например, вычисление журналов или усреднение вместо поиска для пика) вы получите что-то, что не выглядит правильно, как этот парень обнаружил: