我正在尝试用Java生成声音。最后,我愿意不断地向声卡发送声音,但现在我可以发送一个独特的声波。
所以,我用44100个有符号的整数填充了一个数组,表示一个简单的正弦波,我想把它发送到我的声卡上,但我就是不能让它工作。
int samples = 44100; // 44100 samples/s
int[] data = new int[samples];
// Generate all samples
for ( int i=0; i<samples; ++i )
{
data[i] = (int) (Math.sin((double)i/(double)samples*2*Math.PI)*(Integer.MAX_VALUE/2));
}我把它发送到一条声音线路上,使用:
AudioFormat format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 1, 1, 44100, false);
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = new AudioInputStream(ais,format,44100);
clip.open(inputStream);
clip.start(); 我的问题存在于这些代码片段之间。我就是找不到一种方法把我的int[]转换成输入流!
发布于 2011-02-04 02:03:49
首先,我认为您需要的是short样本而不是int
short[] data = new short[samples];因为您的AudioFormat指定了16位样本。short是16位宽,但int是32位。
将其转换为流的一种简单方法是:
和Allocate a ByteBuffer
putShort calls
ByteArrayInputStream
byte[]并格式化AudioInputStream < ByteArrayInputStream >F221<>
示例:
float frameRate = 44100f; // 44100 samples/s
int channels = 2;
double duration = 1.0;
int sampleBytes = Short.SIZE / 8;
int frameBytes = sampleBytes * channels;
AudioFormat format =
new AudioFormat(Encoding.PCM_SIGNED,
frameRate,
Short.SIZE,
channels,
frameBytes,
frameRate,
true);
int nFrames = (int) Math.ceil(frameRate * duration);
int nSamples = nFrames * channels;
int nBytes = nSamples * sampleBytes;
ByteBuffer data = ByteBuffer.allocate(nBytes);
double freq = 440.0;
// Generate all samples
for ( int i=0; i<nFrames; ++i )
{
double value = Math.sin((double)i/(double)frameRate*freq*2*Math.PI)*(Short.MAX_VALUE);
for (int c=0; c<channels; ++ c) {
int index = (i*channels+c)*sampleBytes;
data.putShort(index, (short) value);
}
}
AudioInputStream stream =
new AudioInputStream(new ByteArrayInputStream(data.array()), format, nFrames*2);
Clip clip = AudioSystem.getClip();
clip.open(stream);
clip.start();
clip.drain();注意:我把你的AudioFormat改成了立体声,因为当我请求单声道线路时,它抛出了一个异常。我还把你的波形频率调到了听得见的范围内。
更新-之前的修改(直接写入数据线)不是必需的-使用Clip可以正常工作。我还引入了一些变量,以使计算更加清晰。
发布于 2015-04-13 00:46:20
如果你想播放一个简单的声音,你应该使用SourceDataLine。
下面是一个例子:
import javax.sound.sampled.*;
public class Sound implements Runnable {
//Specify the Format as
//44100 samples per second (sample rate)
//16-bit samples,
//Mono sound,
//Signed values,
//Big-Endian byte order
final AudioFormat format=new AudioFormat(44100f,16,2,true,true);
//Your output line that sends the audio to the speakers
SourceDataLine line;
public Sound(){
try{
line=AudioSystem.getSourceDataLine(format);
line.open(format);
}catch(LineUnavailableExcecption oops){
oops.printStackTrace();
}
new Thread(this).start();
}
public void run(){
//a buffer to store the audio samples
byte[] buffer=new byte[1000];
int bufferposition=0;
//a counter to generate the samples
long c=0;
//The pitch of your sine wave (440.0 Hz in this case)
double wavelength=44100.0/440.0;
while(true){
//Generate a sample
short sample=(short) (Math.sin(2*Math.PI*c/wavelength)*32000);
//Split the sample into two bytes and store them in the buffer
buffer[bufferposition]=(byte) (sample>>>8);
bufferposition++;
buffer[bufferposition]=(byte) (sample & 0xff);
bufferposition++;
//if the buffer is full, send it to the speakers
if(bufferposition>=buffer.length){
line.write(buffer,0,buffer.length);
line.start();
//Reset the buffer
bufferposition=0;
}
}
//Increment the counter
c++;
}
public static void main(String[] args){
new Sound();
}
}在本例中,您将连续生成一个正弦波,但您可以使用此代码播放来自任何源的声音。您只需确保样例格式正确即可。在本例中,我使用的是未压缩的原始16位样本,采样率为44100 Hz。但是,如果要播放文件中的音频,则可以使用Clip对象
public void play(File file){
Clip clip=AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(file));
clip.loop(1);
}https://stackoverflow.com/questions/4889750
复制相似问题