使用javax.sound.sampled生成声音

New*_*biZ 1 java audio

我正试图用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));
}
Run Code Online (Sandbox Code Playgroud)

我使用以下方法将其发送到声音线:

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(); 
Run Code Online (Sandbox Code Playgroud)

我的问题在于它们之间的代码片段.我只是找不到将我转换int[]为输入流的方法!

fin*_*nnw 5

首先,我认为你想要short样品而不是int:

short[] data = new short[samples];
Run Code Online (Sandbox Code Playgroud)

因为您AudioFormat指定了16位样本.short是16位宽,但是int32位.

将其转换为流的简单方法是:

  • 分配一个 ByteBuffer
  • 使用putShort调用填充它
  • 包裹造成byte[]ByteArrayInputStream
  • AudioInputStreamByteArrayInputStream和格式创建

例:

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();
Run Code Online (Sandbox Code Playgroud)

注意:我将您更改AudioFormat为立体声,因为当我请求单声道线时它会引发异常.我还将波形的频率增加到可听范围内的某个频率.


更新 - 之前的修改(直接写入数据行)不是必需的 - 使用Clip工作正常.我还介绍了一些变量,使计算更清晰.