Самый эффективный способ воспроизведения звука WAV на Java

1

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

class MakeSound {

    private final int BUFFER_SIZE = 128000;
    private File soundFile;
    private AudioInputStream audioStream;
    private AudioFormat audioFormat;
    private SourceDataLine sourceLine;

    /**
     * @param filename the name of the file that is going to be played
     */
    public void playSound(String filename){

        String strFilename = filename;

        try {
            soundFile = new File(strFilename);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            audioStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e){
            e.printStackTrace();
            System.exit(1);
        }

        audioFormat = audioStream.getFormat();

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        try {
            sourceLine = (SourceDataLine) AudioSystem.getLine(info);
            sourceLine.open(audioFormat);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        sourceLine.start();

        int nBytesRead = 0;
        byte[] abData = new byte[BUFFER_SIZE];
        while (nBytesRead != -1) {
            try {
                nBytesRead = audioStream.read(abData, 0, abData.length);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (nBytesRead >= 0) {
                @SuppressWarnings("unused")
                int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
            }
        }

        sourceLine.drain();
        sourceLine.close();
    }
}

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

благодаря

  • 1
    Вы можете попробовать добавить этот вопрос на codereview.stackexchange.com !
  • 0
    Да, обзор кода может многое сказать об этом коде. Например, вы неправильно используете переменные экземпляра, как если бы они были локальными переменными.
Показать ещё 2 комментария
Теги:
audio

1 ответ

1

Я предполагаю, что у вас есть рабочий метод, который выглядит так:

пример № 1: (не делайте этого)

public void startMetronome(){
    boolean abort = false;
    String audoFileName = new String("myAudioFile);
    do{
        playSound(audoFileName );
    while(abort != false);    
}

или, может быть, вы сделали некоторую лучшую реализацию следующим образом:

exapmle # 2: (не делайте этого тоже)

Runnable r = new Runnable(){
    boolean abort = false;
    String audoFileName = new String("myAudioFile);
    do{
        playSound(audoFileName );
        try{
            Thread.sleep(500);
        }catch (Exception e);
    while(abort != false);    
}
new Thread(r).start();

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

но это неправильный подход, вам нужно загрузить файл один раз, открыть строку один раз и воспроизвести звук по-разному на линии!

(дешевое) решение № 3:

скорректируйте свой playSoundmethode следующим образом:

public void playSound(String filename){

    //same as above
    String strFilename = filename;
    soundFile = new File(strFilename); //i've shorened the catch/throws, to make it more readable 
    audioStream = AudioSystem.getAudioInputStream(soundFile);
    audioFormat = audioStream.getFormat();
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
    sourceLine = (SourceDataLine) AudioSystem.getLine(info);
    sourceLine.open(audioFormat);

    sourceLine.start();

    //right now, the line is set up and all data is availible
    boolean isRunning = true;

    while(isRunning){ //this is an endless loop!
        int nBytesRead = 0;
        byte[] abData = new byte[BUFFER_SIZE];
        while (nBytesRead != -1) {
        nBytesRead = audioStream.read(abData, 0, abData.length);

        //and your timing here
        try{
            Thread.sleep(500);
        }catch (Exception e);
    }

    sourceLine.drain();
    sourceLine.close();
}

и наилучшей практикой было бы сыграть все в отдельном потоке... (как пример № 2)

  • 0
    Но разве это не инициализирует переменную звука каждый раз? Я имею в виду метод playSound ()
  • 0
    он останется внутри цикла: while (true) {...} цикл никогда не будет прерван ...
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню