Java处理音频

一、Java中如何调用电脑麦克风?

我最近在开发一款电脑的智能语音交互程序时(类似于智能手机上的小爱),我们要捕获声音,然后交给语音识别接口就行识别,那么问题来了,我们应该如何捕获声音呢?也就是说Java中如何调用麦克风,进行音频的输入呢?

Java 中提供的底层类库javax.sound。我们需要引入相关的类库,就可以调用 JDK 封装好的调用麦克风的方法。

代码如下:

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;

//读取麦克风数据
AudioFormat audioFormat = new AudioFormat(16000.0F, 16, 1, true, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open(audioFormat);
targetDataLine.start();

int nByte = 0;
final int bufSize = 3200;
byte[] buffer = new byte[bufSize];
while ((nByte = targetDataLine.read(buffer, 0, bufSize)) > 0) {
    //直接发送麦克风数据流
    // 这个方法是把音频以二进制流的方式发送到语音识别接口上
    transcriber.send(buffer, nByte);
}

targetDataLine.read(buffer, 0, bufSize)才是真正的开始把音频读入到电脑内存中。

二、Java中如何播放音频文件?

从上面的代码中,我们会了如何调用麦克风,把音频读取到内存中。因为我做的是智能语音交互程序,不光要能识别我们讲的话,还要能处理我们的话,处理完还要回应我们,也就是说我们还要用到语音合成,把获取到的音频流播放出来。这里说一下自己子在项目中遇到的一个坑。因为语音合成接口是分段响应二进制音频流的,如果我们直接播放,就会造成声音卡顿。所以这里我们最好是先把音频流存储到本地电脑上,也就是保存为音频格式文件,然后再播放,就不会有卡顿现象。当然这样会有IO操作,如果我们实时播放音频流就不会有IO操作,在性能上更优。

Java 调用扬声器进行播放代码如下:

public static void playAudio() {
    // 从文件中获取音频的文件格式
    AudioFileFormat fileFormat;
    DataLine.Info info;
    SourceDataLine sourceDataLine;
    try {
        FileInputStream fis = new FileInputStream("tts_test.wav");
        fileFormat = AudioSystem.getAudioFileFormat(new File("tts_test.wav"));
        info = new DataLine.Info(SourceDataLine.class, fileFormat.getFormat());
        sourceDataLine = (SourceDataLine) AudioSystem.getLine(info);
        sourceDataLine.open(fileFormat.getFormat());
        sourceDataLine.start();
        byte[] bytes = new byte[1024];
        while (fis.read(bytes) > 0) {
            sourceDataLine.write(bytes, 0, bytes.length);
        }
    } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
        e.printStackTrace();
    }
}

这里需要注意:在new byte[]时,创建的空间必须是偶数,否则会报异常。这里的new byte[]是创建一个缓存,根据上面代码的意思是创建了1024字节的缓存,也就是每次从硬盘中加载1024字节内容进内存中。同时需要注意,并不是说这个偶数填的越大越好,太大会造成内存溢出。其实这里还可以使用fis.available()大小的缓存。

sourceDataLine.write(bytes, 0, bytes.length)才是真正的开始把音频写出到扬声器中。

三、Java如何播放音频流?

上面提到的是使用Java播放本地电脑中的音频文件,那如果我们要播放网络或接口中传过来的音频流,我们应该如何播放呢?

Java 播放实时音频流代码:

import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;

public class AudioPlayer {
    private InputStream stream;
    private AudioFormat format;
    private AudioInputStream audioInputStream;
    private SourceDataLine line;

    public AudioPlayer(InputStream stream, AudioFormat format) {
        this.stream = stream;
        this.format = format;
    }

    public void play() throws IOException {
        audioInputStream = new AudioInputStream(stream, format, AudioSystem.NOT_SPECIFIED);
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format);
            line.start();
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        byte[] buffer = new byte[1024];
        int n = 0;
        while (n != -1) {
            n = audioInputStream.read(buffer, 0, buffer.length);
            if (n > 0) {
                line.write(buffer, 0, n);
            }
        }

        line.drain();
        line.stop();
        line.close();
        audioInputStream.close();
    }
}

调用上面写的播放器类中的播放方法。

InputStream is = new ByteArrayInputStream(bytesArray);
AudioFormat format = new AudioFormat(16000.0F, 16, 1, true, false);
AudioPlayer player = new AudioPlayer(is, format);
player.play();

要注意音频格式,必须要写正确的音频格式才能正常播放。

这里给大家扩展一下知识,因为语音合成的回调方法中的参数是java.nio.ByteBuffer,所以我们要想办法将其转为字节输入流。

第一步:先把byteBuffer转为字节数组。

byte[] bytesArray = new byte[byteBuffer.remaining()];
byteBuffer.get(bytesArray, 0, bytesArray.length);

第二步:把字节数组转为字节流。

InputStream is = new ByteArrayInputStream(bytesArray);
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Java处理音频特征向量,你可以使用音频处理库,如TarsosDSP或Librosa等,这些库提供了许多功能和算法,用于处理音频特征向量。下面是一个使用TarsosDSP库实现处理音频特征向量的示例代码: ```java import be.tarsos.dsp.AudioDispatcher; import be.tarsos.dsp.AudioEvent; import be.tarsos.dsp.AudioProcessor; import be.tarsos.dsp.io.TarsosDSPAudioInputStream; import be.tarsos.dsp.io.jvm.JVMAudioInputStream; import be.tarsos.dsp.mfcc.MFCC; import javax.sound.sampled.*; import java.io.File; import java.io.IOException; public class AudioFeatureProcessing { public static void main(String[] args) { String audioFile = "audio.wav"; // 读取音频文件 File file = new File(audioFile); AudioInputStream audioStream; try { audioStream = AudioSystem.getAudioInputStream(file); } catch (UnsupportedAudioFileException | IOException e) { e.printStackTrace(); return; } // 将音频流转换为TarsosDSP需要的格式 TarsosDSPAudioInputStream audioInputStream = new JVMAudioInputStream(audioStream); // 创建MFCC对象 int sampleRate = (int) audioInputStream.getFormat().getSampleRate(); int bufferSize = 1024; // 缓冲区大小 int bufferOverlap = 0; // 缓冲区重叠大小 int mfccCoefficients = 13; // MFCC系数数量 MFCC mfcc = new MFCC(bufferSize, sampleRate, mfccCoefficients, 40, 300, 133.3334f, 22050.0f); // 创建AudioDispatcher对象并注册处理器 AudioDispatcher dispatcher = new AudioDispatcher(audioInputStream, bufferSize, bufferOverlap); dispatcher.addAudioProcessor(new AudioProcessor() { @Override public boolean process(AudioEvent audioEvent) { float[] audioBuffer = audioEvent.getFloatBuffer(); // 计算MFCC特征向量 mfcc.process(audioBuffer); double[] featureVector = mfcc.getMFCC(); // 处理特征向量 processFeatureVector(featureVector); return true; } @Override public void processingFinished() { // 处理完成回调 } }); // 启动处理 dispatcher.run(); } public static void processFeatureVector(double[] featureVector) { // 处理特征向量 // ... } } ``` 上述代码使用TarsosDSP库将音频文件转换为TarsosDSP所需的格式,并通过MFCC(Mel Frequency Cepstral Coefficients)算法计算MFCC特征向量。你可以根据实际需求选择合适的特征提取方法和处理方式。请注意,上述代码只是演示了大致的实现思路,具体的特征提取和处理方法需要根据实际情况进行选择和实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值