Создание звукового файла с переменной скоростью воспроизведения в Java - PullRequest
0 голосов
/ 26 сентября 2019

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

Другой метод - взять исходный файл как поток, а затем создать потокиспользуя это, которое ускоряет или замедляет его по мере необходимости.Кажется, что это будет работать хорошо, но для создания AudioInputStream мне либо нужен InptutStream известной длины, который невозможно определить заранее, либо TargetDataLine, который имеет интерфейс, который имеет гораздо больше методов, чем я.хотел бы реализовать.

Есть ли лучший способ сделать это?Кроме того, почему AudioInputStream должен знать длину потока?

Альтернативно, есть ли внешняя библиотека, которую я мог бы использовать?

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

(Полагаю, * * * * * * * * * * * * * * * * * * * * * * * * * * * - - ответила Филу. Я просто отправляю это, чтобы добавить свои два цента о повторной выборке.)

Краткий ответ: Создайте AudioInputStream, который либо отбрасывает сэмплы, либо добавляет ноль сэмплов.В качестве длины вы можете установить AudioSystem.NOT_SPECIFIED.

Длинный ответ: Если вы добавляете ноль выборок, вы можете интерполировать , но не линейно.Причиной интерполяции для повышения частоты дискретизации является aliasing , которого вы можете избежать.Вы делаете это, применяя фильтр нижних частот .Причина этого проста.Теорема Найквиста-Шеннона гласит, что когда сигнал дискретизируется с X Hz, вы можете однозначно представлять частоты только до X/2 Hz.Когда вы повышаете частоту, вы увеличиваете частоту сэмплирования, поэтому теоретически вы можете представить больший частотный диапазон.Действительно, просто добавляя нули, вы видите некоторую энергию в этих дополнительных частотных диапазонах, которых не должно быть, потому что у вас нет информации об этом.Таким образом, вам нужно «отрезать их», используя фильтр низких частот.Подробнее о повышении частоты дискретизации можно найти в Википедии .

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

Бесстыдная вилка: если вы все же хотите это сделать несколько правильнее , вы можете найти Resample класс jipes полезным.Это не универсальный ресэмплер, т. Е. Он поддерживает только ограниченное количество факторов, таких как 2, 4, ..., но может оказаться полезным для вас.

import com.tagtraum.jipes.math.MultirateFilters.Resampler;

[...]

float[] original = ... ; // original signal as float

Resampler downsampler2 = new MultirateFilters.Resampler(1, 2);
float[] downsampled = downsampler2.map(original);

Resampler upsampler2 = new MultirateFilters.Resampler(2, 1);
float[] upsampled = upsampler2.map(original);

Если вы хотите модификация шкалы времени (TSM) , т. е. для изменения темпа без изменения частот вы можете использовать Rubberband для Java .

1 голос
/ 26 сентября 2019

Если вы просто воспроизводите аудиофайл (например, .wav) и все в порядке с высотой звука, смещаемой, простая возможность - прочитать данные из AudioInputStream, перевести в PCM, интерполироватьхотя эти данные с желаемой скоростью переводят обратно в байты корабля через SourceDataLine.

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

Это сделано для достижения изменений частоты в реальном времени в библиотеке с открытым исходным кодом AudioCue на github.Установлено, что сглаживание между изменениями частоты происходит в течение 1028 кадров (примерно 1/40 секунды).Но более быстрые изменения, безусловно, возможны.Звуковые данные в этой библиотеке взяты из внутреннего массива значений PCM.Но хороший пример кода, необходимого для чтения данных в виде строки, а не фиксированного массива, можно увидеть в первом примере кода в Sound Trail, Использование файловых фильтров и преобразователей .Возможно, вы захотите использовать InputStream в качестве аргумента для AudioInputStream.В той точке примера, где написано «Вот, сделайте что-нибудь полезное ...», вы конвертируете в PCM, а затем перемещаетесь по полученному PCM с требуемой частотой, используя линейную интерполяцию, а затем перепаковываете и отправляете через * 1013.*.

Если вы хотите сохранить высоту тона (только растягивание по времени или сжатие), то для этого требуется более интенсивный DSP. В этой теме на сайте цифровой обработки StackExchange есть некоторая информация об этом.У меня был некоторый успех в создании гранул с окном Хэмминга , чтобы помочь перекрестному затуханию между ними, но некоторые другие решения были у меня над головой (и я не вернулся к этой проблеме вдолго пока).Но было возможно изменить расстояние между гранулами в реальном времени, если я правильно помню.Хотя это звучало не так хорошо, как алгоритм инструмента Audacity, но это скорее для меня, чем для меня.Я в основном самоучка и экспериментирую, профессионально не работаю в поле.

...