簡體   English   中英

如何在Java中將播放音頻保存為WAV格式

[英]How to Save Playing Audio to WAV Format in Java

我正在使用Waywardgeek開發的Sonic Algorithm,以加快和減慢音頻文件的速度。 一切正常。 但是我需要的是我需要將播放音頻保存到wav文件。 我嘗試使用ByteArrayInputStreamTargetDataLink保存。 但是我做不到。 所以有人可以幫助我將播放音頻保存到wav文件嗎? 而且,我還是Java Audio的新手。

這是代碼,

Main.java

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Main {

    private static void runSonic(
            AudioInputStream audioStream,
            SourceDataLine line,
            float speed,
            float pitch,
            float rate,
            float volume,
            boolean emulateChordPitch,
            int quality,
            int sampleRate,
            int numChannels) throws IOException {
        Sonic sonic = new Sonic(sampleRate, numChannels);
        int bufferSize = line.getBufferSize();
        byte inBuffer[] = new byte[bufferSize];
        byte outBuffer[] = new byte[bufferSize];
        int numRead, numWritten;

        sonic.setSpeed(speed);
        sonic.setPitch(pitch);
        sonic.setRate(rate);
        sonic.setVolume(volume);
        sonic.setChordPitch(emulateChordPitch);
        sonic.setQuality(quality);
        do {
            numRead = audioStream.read(inBuffer, 0, bufferSize);
            if (numRead <= 0) {
                sonic.flushStream();
            } else {
                sonic.writeBytesToStream(inBuffer, numRead);
            }
            do {
                numWritten = sonic.readBytesFromStream(outBuffer, bufferSize);
                if (numWritten > 0) {
                    line.write(outBuffer, 0, numWritten);
                }
            } while (numWritten > 0);
        } while (numRead > 0);
    }

    public static void main(String[] argv) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        float speed = 1.0f;
        float pitch = 1.0f;
        float rate = 1.5f;
        float volume = 1.0f;
        boolean emulateChordPitch = false;
        int quality = 0;

        AudioInputStream stream = AudioSystem.getAudioInputStream(new File("C:\\audio1.wav"));
        AudioFormat format = stream.getFormat();
        int sampleRate = (int) format.getSampleRate();
        int numChannels = format.getChannels();
        SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format,
                ((int) stream.getFrameLength() * format.getFrameSize()));
        SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
        line.open(stream.getFormat());
        line.start();
        runSonic(stream, line, speed, pitch, rate, volume, emulateChordPitch, quality,
                sampleRate, numChannels);
        line.drain();
        line.stop();
    }
}

我嘗試使用以下代碼,將其保存到wav文件,但播放時具有一字音頻。 而且對於TargetDataLink ,什么都TargetDataLink

byteArrayOutputStream = new ByteArrayInputStream(outBuffer);
audioStreams = new AudioInputStream(byteArrayOutputStream, line.getFormat(), bufferSize);
AudioSystem.write(audioStreams, AudioFileFormat.Type.WAVE, new File("C:\\audio2.wav"));

Sonic.java

由於允許的字符數有限,因此無法在此處發布完整代碼。 代碼在這里

PS:該代碼由Bill Cox開發。 謝謝Bill Cox提供的出色代碼。

我已經嘗試過,現在我想出了一個使用ByteArrayInputStreamByteArrayOutputStream的解決方案。 首先,我使用ByteArrayOutputStreamSourceDataLine line.write()一樣寫outBuffer 然后將其轉換為byteArray並使用AudioInputStream保存。 java2s教程幫助我做到了這一點。 它正在工作,但我不知道這是否是最佳解決方案。 因此,歡迎提出任何建議。 謝謝。

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Main {

    private static void runSonic(
            AudioInputStream audioStream,
            SourceDataLine line,
            float speed,
            float pitch,
            float rate,
            float volume,
            boolean emulateChordPitch,
            int quality,
            int sampleRate,
            int numChannels) throws IOException {
        Sonic sonic = new Sonic(sampleRate, numChannels);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int bufferSize = line.getBufferSize();
        byte inBuffer[] = new byte[bufferSize];
        byte outBuffer[] = new byte[bufferSize];
        int numRead, numWritten;

        sonic.setSpeed(speed);
        sonic.setPitch(pitch);
        sonic.setRate(rate);
        sonic.setVolume(volume);
        sonic.setChordPitch(emulateChordPitch);
        sonic.setQuality(quality);
        do {
            numRead = audioStream.read(inBuffer, 0, bufferSize);
            if (numRead <= 0) {
                sonic.flushStream();
            } else {
                sonic.writeBytesToStream(inBuffer, numRead);
            }
            do {
                numWritten = sonic.readBytesFromStream(outBuffer, bufferSize);
                if (numWritten > 0) {
                    line.write(outBuffer, 0, numWritten);
                    byteArrayOutputStream.write(outBuffer, 0, numWritten);
                }
            } while (numWritten > 0);
        } while (numRead > 0);
        byte audioBytes[] = byteArrayOutputStream.toByteArray();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(audioBytes);
        AudioFormat format = line.getFormat();

        AudioInputStream audioInputStream = new AudioInputStream(byteArrayInputStream, format, audioBytes.length / format.getFrameSize());
        AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, new File("C:\\audio2.wav"));

    }

    public static void main(String[] argv) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        float speed = 1.0f;
        float pitch = 1.0f;
        float rate = 1.5f;
        float volume = 1.0f;
        boolean emulateChordPitch = false;
        int quality = 0;

        AudioInputStream stream = AudioSystem.getAudioInputStream(new File("C:\\audio1.wav"));
        AudioFormat format = stream.getFormat();
        int sampleRate = (int) format.getSampleRate();
        int numChannels = format.getChannels();
        SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format,
                ((int) stream.getFrameLength() * format.getFrameSize()));
        SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
        line.open(stream.getFormat());
        line.start();
        runSonic(stream, line, speed, pitch, rate, volume, emulateChordPitch, quality,
                sampleRate, numChannels);
        line.drain();
        line.stop();
    }
}

我很確定在過去的問題中都涵蓋了兩個問題,即如何更改播放速率以及如何保存波形。 例如Java-調整WAV文件的播放速度。請參見線性插值的答案。 這並不難實現。 如果僅希望將速度提高一倍,則選擇的答案很好,但是插值算法允許指定許多其他速度。

至於保存為wav,我建議從Oracle Sound教程開始。 https://docs.oracle.com/javase/tutorial/sound/converters.html

就將其作為流而不是將完整的文件保存在內存中而言,這需要一些管理,但這是一個非常常見的任務,應該放在任何程序員的手腕上。 在輸入和處理數據時,將其保存到輸出緩沖區陣列,並在輸出緩沖區上跟蹤進度。 僅在此緩沖區就緒時才寫入輸出流。

步驟概述:讀取字節,轉換為PCM,進行音高轉換,如果准備好輸出完整的緩沖區:將PCM轉換回字節,寫入字節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM