不支持的控件类型:采样率

时间:2015-09-22 18:22:18

标签: java javax.sound.sampled

所以我试图让Java在这方面以一定的速度播放声音我尝试为SourceDataLine获取一个Controll for Sample rate:

`package com.pap.sound;

import javax.sound.sampled.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.BitSet;

public class Player implements Playable {
private AudioFormat format;
private SourceDataLine sourceDataLine;
private DataLine.Info info;
private final URL soundUrl;
private final boolean[] stopped;
private float playRate;
private boolean playRateChanged;


public Player(URL soundUrl) throws LineUnavailableException,     MalformedURLException {
    this.format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44100, 16, 2 , 4, 44100,false);
    this.info = new DataLine.Info(SourceDataLine.class, format);
    this.sourceDataLine =  (SourceDataLine) AudioSystem.getLine(info);
    this.soundUrl = soundUrl;
    this.stopped = new boolean[1];
    this.stopped[0] = false;
    this.playRate = 1;
    this.playRateChanged = false;
}
@Override
public boolean play() throws LineUnavailableException {
    sourceDataLine.open();
    Thread playerThread = new Thread(){

        @Override
        public void run() {
            int numberOfBitesRead = 0;
            AudioInputStream auis = null;
            try {
                auis = AudioSystem.getAudioInputStream(soundUrl);
            } catch (UnsupportedAudioFileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] bytes = new byte[4];
            sourceDataLine.start();
            try {
                auis.mark(auis.available());

            while(!stopped[0]) {

                numberOfBitesRead = auis.read(bytes);
                if(numberOfBitesRead == -1) {
                    auis.reset();
                }

                sourceDataLine.write(bytes, 0, bytes.length);
                FloatControl fc = (FloatControl)     sourceDataLine.getControl(FloatControl.Type.SAMPLE_RATE);
                if(playRateChanged) {
                    fc.setValue((int)(44200*playRate));
                    playRateChanged = false;
                }
            }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    };

    playerThread.start();

    return false;
}

@Override
public boolean stop() {
    this.stopped[0] = true;
    this.sourceDataLine.stop();
    this.sourceDataLine.close();
    return false;
}

@Override
public boolean setPlayRate(float playRate) {
    this.playRate = playRate;
    this.playRateChanged = true;
    return false;
}

}`

但在运行时我得到:

Exception in thread "Thread-1" java.lang.IllegalArgumentException: Unsupported control type: Sample Rate
    at com.sun.media.sound.AbstractLine.getControl(AbstractLine.java:150)
    at com.pap.sound.Player$1.run(Player.java:67)

你们有没有遇到过这样的事情?我试着为此寻找答案,却找不到答案。 我使用的是Java 8。 enter image description here 谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

最后我想出了一个解决方案。因为旧的FloatControl.Type.SAMPLE_RATE在Java 8中不再可用,我选择通过在播放声音时省略一些字节来增加样本量,解决方案如下所示:

这是界面:

package com.pap.sound;

import javax.sound.sampled.LineUnavailableException;


public interface Playable {
public boolean play() throws LineUnavailableException;
public boolean stop();
public boolean setPlayRate(float playRate);
}

这是玩家类:

package com.pap.sound;

import com.sun.media.sound.AudioFloatFormatConverter;
import com.sun.media.sound.JavaSoundAudioClip;
import com.sun.media.sound.SoftMixingDataLine;

import javax.sound.sampled.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;


public class Player implements Playable {
 private AudioFormat format;
 private SourceDataLine sourceDataLine;
 private DataLine.Info info;
 private final URL soundUrl;
 private final boolean[] stopped;
 private float playRate;
 private boolean playRateChanged;
 private int bytesWritten;
 private int bytesIgnorred;


public Player(URL soundUrl) throws LineUnavailableException, MalformedURLException {
    this.format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44100, 16, 2 , 4, 44100,false);
    this.info = new DataLine.Info(SourceDataLine.class, format);
    this.sourceDataLine =  (SourceDataLine) AudioSystem.getLine(info);
    TargetDataLine tdl = AudioSystem.getTargetDataLine(format);

    this.soundUrl = soundUrl;
    this.stopped = new boolean[1];
    this.stopped[0] = false;
    this.playRate = 1;
    this.playRateChanged = false;
    this.bytesWritten =0;
    this.bytesIgnorred = 0;
}
@Override
public boolean play() throws LineUnavailableException {
    sourceDataLine.open();
    final Thread playerThread = new Thread(){

        @Override
        public void run() {
            int numberOfBitesRead = 0;
            AudioInputStream auis = null;
            try {
                auis = AudioSystem.getAudioInputStream(soundUrl);
            } catch (UnsupportedAudioFileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] bytes = new byte[4];
            sourceDataLine.start();
            try {
                auis.mark(auis.available());

            while(!stopped[0]) {

                numberOfBitesRead = auis.read(bytes);
                if(numberOfBitesRead == -1) {
                    auis.reset();
                }
                if(bytesWritten < (10)) {
                    sourceDataLine.write(bytes, 0, bytes.length);
                    bytesWritten+=4;
                } else {
                    if(bytesIgnorred < ((int)(playRate*10-10))) {
                        bytesIgnorred+=4;
                    } else {
                        bytesWritten =0;
                        bytesIgnorred = 0;
                    }
                }
            }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    };

    playerThread.start();

    return false;
}

@Override
public boolean stop() {
    this.stopped[0] = true;
    this.sourceDataLine.stop();
    this.sourceDataLine.close();
    return false;
}

@Override
public boolean setPlayRate(float playRate) {
    this.playRate = playRate;
    this.playRateChanged = true;
    return false;
}

}

为了测试它,我使用了以下代码:

package com.pap.main;

import com.pap.sound.Player;
import javax.sound.sampled.LineUnavailableException;
import java.net.MalformedURLException;
import java.net.URL;


public class Main {
public static void main(String[] args) throws MalformedURLException, LineUnavailableException, InterruptedException {
    URL url = ClassLoader.getSystemClassLoader().getSystemResource("steam.wav");
    Player player = new Player(url);
    player.play();
    Thread.sleep(2000);
    for(int i=0;i<60;i++) {
        player.setPlayRate(1f+(float)(i)*0.1f);
        System.out.println(1f+(float)(i)*0.1f + "x");
        Thread.sleep(1000);
    }
    player.stop();
}

}