只需使用Java进行重采样

这是一个从PC麦克风以8000Hz/16bit获取的示例,采用线性插值转换为16000Hz/16bit的采样。

import static java.lang.System.out;

import java.util.Arrays;

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

public class MicrophoneResamplingTest {

    // SampleRate:8000Hz, SampleSizeInBits: 16, Number of channels: 1, Signed:true, bigEndian: false
    public static final AudioFormat audioFormat = new AudioFormat(8000, 16, 1, true, false);

    // Set the system information to read from the microphone audio stream
    public static final DataLine.Info targetInfo = new Info(TargetDataLine.class, audioFormat);

    public static void main(String[] args) throws Exception {
        if (!AudioSystem.isLineSupported(targetInfo)) {
            out.println("Microphone not supported");
            return;
        }
        new MicrophoneResamplingTest().test();
    }

    // マイク音声を取得しリサンプリング
    void test() throws Exception {
        TargetDataLine dataLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
        dataLine.open(audioFormat);
        dataLine.start();

        byte[] bytes = new byte[1024];

        while (dataLine.isOpen()) {
            int numBytesRead = dataLine.read(bytes, 0, bytes.length);
            if ((numBytesRead <= 0) && (dataLine.isOpen()))
                continue;

            // 例:8000Hzから16000Hzのupsampling
            byte[] resampled = resampling(bytes, 16, 8000, 16000);
            out.println(Arrays.toString(resampled));// リサンプリングされたデータ
        }
    }

    // 線形補間によるリサンプリング
    byte[] resampling(byte[] sourceData, int bitsPerSample, int sourceRate, int targetRate) {
        int bytePerSample = bitsPerSample / 8;
        int numSamples = sourceData.length / bytePerSample;
        short[] amplitudes = new short[numSamples];
        int pointer = 0;
        for (int i = 0; i < numSamples; i++) {
            short amplitude = 0;
            for (int byteNumber = 0; byteNumber < bytePerSample; byteNumber++)
                amplitude |= (short) ((sourceData[pointer++] & 0xFF) << (byteNumber * 8));
            amplitudes[i] = amplitude;
        }
        // Linear interpolation
        short[] targetSample = interpolate(sourceRate, targetRate, amplitudes);
        int targetLength = targetSample.length;
        byte[] bytes;
        if (bytePerSample == 1) {
            bytes = new byte[targetLength];
            for (int i = 0; i < targetLength; i++)
                bytes[i] = (byte) targetSample[i];
        } else {
            bytes = new byte[targetLength * 2];
            for (int i = 0; i < targetSample.length; i++) {
                bytes[i * 2] = (byte) (targetSample[i] & 0xff);
                bytes[i * 2 + 1] = (byte) ((targetSample[i] >> 8) & 0xff);
            }
        }
        return bytes;
    }

    // 線形補間
    short[] interpolate(int oldSampleRate, int newSampleRate, short[] samples) {
        if (oldSampleRate == newSampleRate)
            return samples;
        int newLength = Math.round(((float) samples.length / oldSampleRate * newSampleRate));
        float lengthMultiplier = (float) newLength / samples.length;
        short[] interpolatedSamples = new short[newLength];
        for (int i = 0; i < newLength; i++) {
            float currentPosition = i / lengthMultiplier;
            int nearestLeftPosition = (int) currentPosition;
            int nearestRightPosition = nearestLeftPosition + 1;
            if (nearestRightPosition >= samples.length)
                nearestRightPosition = samples.length - 1;
            float slope = samples[nearestRightPosition] - samples[nearestLeftPosition];
            float positionFromLeft = currentPosition - nearestLeftPosition;
            interpolatedSamples[i] = (short) (slope * positionFromLeft + samples[nearestLeftPosition]);
        }
        return interpolatedSamples;
    }

}
广告
将在 10 秒后关闭
bannerAds