Java - проблема с объединением более 2 файлов .wav

для проекта, над которым я работаю, я хочу иметь возможность объединять несколько файлов .wav.

Благодаря моим исследованиям я смог придумать этот код:

File sample1 = new File("F:\\Programming\\Resources\\Java_Sound\\trumpet1.wav");
File sample2 = new File("F:\\Programming\\Resources\\Java_Sound\\trumpet2.wav");

File fileOut = new File("F:\\Programming\\Resources\\Java_Sound\\Test.wav");

AudioInputStream audio1 = AudioSystem.getAudioInputStream(sample1);
AudioInputStream audio2 = AudioSystem.getAudioInputStream(sample2);

AudioInputStream audioBuild = new AudioInputStream(new SequenceInputStream(audio1, audio2), audio1.getFormat(), audio1.getFrameLength() + audio2.getFrameLength());

//for(int i = 0; i < 5; i++){
//    audioBuild = new AudioInputStream(new SequenceInputStream(audioBuild, audio2), audioBuild.getFormat(), audioBuild.getFrameLength() + audio2.getFrameLength());
//}

AudioSystem.write(audioBuild, AudioFileFormat.Type.WAVE, fileOut);

он отлично работает для объединения двух файлов .wav, однако, когда я раскомментирую цикл for, созданный файл .wav воспроизводит звук только для первого объединения. Звуковая дорожка, кажется, заканчивается раньше, так как полоса продолжительности wmp проходит только около 1\5 пути по экрану.

Я предположил, что проблема связана с заголовком в созданном файле .wav. Я исследовал много разных веб-страниц, обсуждающих, как создается заголовок, но все они имели немного разные определения, но все говорили, что заголовок должен быть в шестнадцатеричном формате. При преобразовании потока (не аудиопотока, стандартного FileInputStream) заголовки, которые у меня были, были десятичными. Кроме того, после части RIFF и перед частью WAVE предполагается размер всего файла, не включая первые 8 байтов. Однако некоторые из моих включали дефисы. Честно говоря, я понятия не имею, что они означают. Однако, игнорируя их, размер тестового файла после раскомментирования приведенного выше кода по-прежнему остается большим.

Итак, изучив, как объединять несколько аудиофайлов и как создавать \ управлять заголовками .wav, я до сих пор понятия не имею, почему остальная часть моего аудио не воспроизводится, если она вообще существует. Любая помощь приветствуется. Заранее спасибо.


person Pojo226    schedule 17.06.2011    source источник


Ответы (2)


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

Это должно работать с небольшой модификацией, продолжайте создавать новые входные аудиопотоки в цикле:

File sample1 = new File("f1.wav");
File sample2 = new File("f2.wav");

File fileOut = new File("combined.wav");

AudioInputStream audio1 = AudioSystem.getAudioInputStream(sample1);
AudioInputStream audio2 = AudioSystem.getAudioInputStream(sample2);

AudioInputStream audioBuild = new AudioInputStream(new SequenceInputStream(audio1, audio2), audio1.getFormat(), audio1.getFrameLength() + audio2.getFrameLength());

for(int i = 0; i < 5; i++)
{
    audioBuild = new AudioInputStream(new SequenceInputStream(audioBuild, /* keep creating new input streams */ AudioSystem.getAudioInputStream(sample2)), audioBuild.getFormat(), audioBuild.getFrameLength() + audio2.getFrameLength());
}

AudioSystem.write(audioBuild, AudioFileFormat.Type.WAVE, fileOut);

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

person prunge    schedule 17.06.2011
comment
Спасибо, создание нового входного потока каждый раз работает отлично. Мой единственный вопрос сейчас заключается в том, должны ли создаваемые входные потоки закрываться как последняя строка кода в цикле for? - person Pojo226; 18.06.2011
comment
@ Pojo226: Закрытие входного потока последовательности закрывает все его базовые потоки, а закрытие входных аудиопотоков также закрывает его базовый поток. Закрытие audioBuild в конце блока finally должно быть достаточно хорошим, но не закрывайте их перед вызовом AudioSystem.write(), потому что это вызов, который считывает все потоки. - person prunge; 20.06.2011

Это то, что я использовал для объединения любого количества волновых файлов. Я просмотрел список строковых значений для путей к волновым файлам и каждый раз соединял предыдущий результирующий поток AudioInputStream со следующим клипом.

List<String> paths;
AudioInputStream clip1 = null;
for (String path : paths)
{
    if(clip1 == null)
    {
        clip1 = AudioSystem.getAudioInputStream(new File(path));
        continue;
    }
    AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(path));
    AudioInputStream appendedFiles = new AudioInputStream(
            new SequenceInputStream(clip1, clip2),     
            clip1.getFormat(), 
            clip1.getFrameLength() + clip2.getFrameLength());
    clip1 = appendedFiles;
}
AudioSystem.write(clip1, AudioFileFormat.Type.WAVE, new File("exported.wav"));
person The.Power.Process    schedule 01.04.2013
comment
как мне сделать то же самое, но вместо того, чтобы добавить смесь между ними, что означает перекрытие? - person Asaf Magen; 28.04.2020