Как получить управление панорамированием из файла .mp3?

Я учусь воспроизводить звук в Java, но с расширенными элементами управления.

Я обнаружил одну проблему: javax.sound.sampled.AudioInputStream не поддерживает файлы Mp3, и у меня заканчиваются идеи, как получить контроль над панорамированием.

Мне удалось воспроизвести файл Mp3 с помощью javazoom.jl.player.advanced.AdvancedPlayer, но у него нет управления панорамированием, или я его не создал.

Мой фактический код открывает файл, если формат совместим с AudioInputStream, он воспроизводит только правильный канал. Если формат не подходит, он воспроизводится с помощью AdvancedPlayer.

Знаете ли вы, как управлять панорамированием mp3-файлов?

Мой код здесь:

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;

import javax.sound.sampled.*;
import javax.swing.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class AudioPlayerExample2 {
    private static final int BUFFER_SIZE = 4096;

    public static void main(String[] args) throws IOException, LineUnavailableException, JavaLayerException {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.showOpenDialog(null);

        new AudioPlayerExample2().play(fileChooser.getSelectedFile());
    }


    void play(File file) throws IOException, LineUnavailableException, JavaLayerException {


        AudioInputStream audioStream;

        try {
            audioStream = AudioSystem.getAudioInputStream(file);

            AudioFormat format = audioStream.getFormat();
            System.err.println(format.toString());

            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

            SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);

            audioLine.open(format);

            audioLine.start();

            FloatControl pan = (FloatControl) audioLine.getControl(FloatControl.Type.PAN);

            byte[] bytesBuffer = new byte[BUFFER_SIZE];
            int bytesRead = -1;


            while ((bytesRead = audioStream.read(bytesBuffer)) != -1) {
                pan.setValue((float) (1));
                audioLine.write(bytesBuffer, 0, bytesRead);
            }

            audioLine.drain();
            audioLine.close();
            audioStream.close();
        } catch (UnsupportedAudioFileException e) {
            FileInputStream fis = new FileInputStream(file);
            AdvancedPlayer player = new AdvancedPlayer(fis);

            player.play();
        }


    }
}

person Mango    schedule 15.07.2018    source источник
comment
Вы также можете попробовать использовать медиаплеер JavaFX. (См. также stackoverflow.com/q/6045384/2891664.)   -  person Radiodef    schedule 15.07.2018
comment
не поддерживает файлы Mp3 См. информацию о звуке Java. страница в разделе "Интерфейс поставщика услуг".   -  person Andrew Thompson    schedule 18.07.2018


Ответы (2)


Регуляторы панорамирования и громкости зависят от системы и иногда могут немного глючить, даже если они на месте. Например, если вы одновременно слишком сильно измените громкость или панорамирование, разрыв вызовет щелчок.

Одно из решений состоит в том, чтобы зайти туда для каждого кадра и внести изменения самостоятельно. Например, см. раздел «Непосредственное управление аудиоданными» в конце руководства Обработка Аудио с элементами управления.

В качестве примера ознакомьтесь с кодом из следующего руководства: Использование файлов и конвертеры форматов. Посмотрите под заголовком «Чтение звуковых файлов» и найдите комментарий в коде «\ Вот, сделайте что-нибудь полезное...»

Я приглашаю вас также взглянуть на код, который я написал и сделал доступным, класс под названием AudioCue, который имеет панорамирование в реальном времени, а также элементы управления громкостью и высотой тона в реальном времени. Я добавил сглаживание (1024 шага для изменения панорамирования), чтобы уменьшить вероятность разрывов.

Вам предстоит взять mp3-файл и декодировать его в массив аудиоданных. Я думаю, что библиотеки javazoom, доступные на github, должны предоставить вам достаточный доступ к коду, чтобы понять, как это сделать (я сделал это для декодирования ogg/vorbis). Если у вас есть массив аудиоданных с плавающей запятой (стерео, знаковые числа с плавающей запятой в диапазоне от -1 до 1), его можно напрямую загрузить в AudioCue.

person Phil Freihofner    schedule 17.07.2018

Прежде всего, благодаря Эндрю Томпсону и Филу Фрайхофнеру, мне очень приятно быть частью этого сообщества и иметь кого-то, кому можно доверять. Вы действительно делаете счастливыми :)

Я оставляю здесь полный код, который делает именно то, что я хотел.

Как сказано в документации JavaZoom MP3 SPI: убедитесь, что библиотеки JLayer, Tritonus и MP3SPI доступны в вашем CLASSPATH.

import javax.sound.sampled.*;
import javax.swing.*;
import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException, 
UnsupportedAudioFileException, LineUnavailableException {
    JFileChooser chooser = new JFileChooser();
    chooser.showOpenDialog(null);
    String path = chooser.getSelectedFile().getAbsolutePath();

    System.err.println(path);
    File file = new File(path);

    AudioInputStream baseStream = AudioSystem.getAudioInputStream(file);

    AudioFormat baseFormat = baseStream.getFormat();

    System.err.println(baseFormat.toString());
    AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
baseFormat.getSampleRate(),
            16, baseFormat.getChannels(), baseFormat.getChannels() * 2, 
baseFormat.getSampleRate(), true);

    DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

    AudioInputStream stream = AudioSystem.getAudioInputStream(format, baseStream);

    SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);


    audioLine.open(format);
    audioLine.start();

    FloatControl pan = (FloatControl) audioLine.getControl(FloatControl.Type.PAN);

    pan.setValue(1);

    int BUFFER_SIZE = 4096;

    byte[] buffer = new byte[BUFFER_SIZE];

    int read = -1;

    while((read = stream.read(buffer)) != -1){
        audioLine.write(buffer, 0, read);
    }

    audioLine.drain();
    audioLine.close();
}
}
person Mango    schedule 31.07.2018