保存wave音频流的方法

Posted passedbylove

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了保存wave音频流的方法相关的知识,希望对你有一定的参考价值。

保存到文件:

void saveToFile(String filename, ByteBuffer buffer)
    {
        byte[] bytes = buffer.array();
        OutputStream outStream = null;
        try {
            File file = new File(filename);
            String directory = file.getParent();
            if(Files.notExists(Paths.get(directory)))
            {
                Files.createDirectories(Paths.get(directory));
            }
            //TODO:改成nio FileChannel
            outStream = new FileOutputStream(file);


            /**
             * 8 bit Unsigned
             * 16 bit Signed 16000 16
             */
            //TODO:改成直接操作二进制的代码 StdWavFile:signed 16bit pcm le wav
            WaveFileWriter writer = new WaveFileWriter();
            AudioFormat frmt = new AudioFormat(16000, 16, 1, true, false);
            ByteArrayInputStream bi = new ByteArrayInputStream(bytes);

            InputStream in = new AudioInputStream(bi, frmt,bytes.length);
            writer.write((AudioInputStream) in, AudioFileFormat.Type.WAVE, outStream);
            outStream.close();
        } catch (Exception e) {
            getLogger().error("文件保存失败:{}",e);
        }
    }

其他方法:

/***
     * 将pcm音频流封装成wave音频流
     * @param rawData 音频流
     * @param sampleRate 采样率
     * @return
     * @throws IOException
     */
    private byte[] rawToWave(final byte[] rawData, int sampleRate) throws IOException {
        DataOutputStream output = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            output = new DataOutputStream(outputStream);
            // WAVE header
            // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
            writeString(output, "RIFF"); // chunk id
            writeInt(output, 36 + rawData.length); // chunk size
            writeString(output, "WAVE"); // format
            writeString(output, "fmt "); // subchunk 1 id
            writeInt(output, 16); // subchunk 1 size
            writeShort(output, (short) 1); // audio format (1 = PCM)
            writeShort(output, (short) 1); // number of channels
            writeInt(output, sampleRate); // sample rate
            writeInt(output, sampleRate * 2); // byte rate
            writeShort(output, (short) 2); // block align
            writeShort(output, (short) 16); // bits per sample
            writeString(output, "data"); // subchunk 2 id
            writeInt(output, rawData.length); // subchunk 2 size
            // Audio data (conversion big endian -> little endian)
            short[] shorts = new short[rawData.length / 2];
            ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
            ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
            for (short s : shorts) {
                bytes.putShort(s);
            }

            output.write(rawData);
            return outputStream.toByteArray();
        } finally {
            if (output != null) {
                output.close();
            }
        }
    }

    /***
     * 将pcm音频流封装成wave音频文件
     * @param rawData 原始音频
     * @param sampleRate 采样率
     * @param waveFile wave声音文件
     * @throws IOException
     */
    private void rawToWave(final byte[] rawData, int sampleRate,final File waveFile) throws IOException {
        DataOutputStream output = null;
        try {
            output = new DataOutputStream(new FileOutputStream(waveFile));
            // WAVE header
            // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
            writeString(output, "RIFF"); // chunk id
            writeInt(output, 36 + rawData.length); // chunk size
            writeString(output, "WAVE"); // format
            writeString(output, "fmt "); // subchunk 1 id
            writeInt(output, 16); // subchunk 1 size
            writeShort(output, (short) 1); // audio format (1 = PCM)
            writeShort(output, (short) 1); // number of channels
            writeInt(output, sampleRate); // sample rate
            writeInt(output, sampleRate * 2); // byte rate
            writeShort(output, (short) 2); // block align
            writeShort(output, (short) 16); // bits per sample
            writeString(output, "data"); // subchunk 2 id
            writeInt(output, rawData.length); // subchunk 2 size
            // Audio data (conversion big endian -> little endian)
            short[] shorts = new short[rawData.length / 2];
            ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
            ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
            for (short s : shorts) {
                bytes.putShort(s);
            }

            output.write(rawData);
        } finally {
            if (output != null) {
                output.close();
            }
        }
    }

    /***
     * 将pcm音频文件封装成wave文件
     * @param rawFile pcm音频数据文件
     * @param sampleRate 采样率
     * @param waveFile wave文件
     * @throws IOException
     */
    private void rawToWave(final File rawFile, int sampleRate,final File waveFile) throws IOException {

        byte[] rawData = new byte[(int) rawFile.length()];
        DataInputStream input = null;
        try {
            input = new DataInputStream(new FileInputStream(rawFile));
            input.read(rawData);
        } finally {
            if (input != null) {
                input.close();
            }
        }

        DataOutputStream output = null;
        try {
            output = new DataOutputStream(new FileOutputStream(waveFile));
            // WAVE header
            // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
            writeString(output, "RIFF"); // chunk id
            writeInt(output, 36 + rawData.length); // chunk size
            writeString(output, "WAVE"); // format
            writeString(output, "fmt "); // subchunk 1 id
            writeInt(output, 16); // subchunk 1 size
            writeShort(output, (short) 1); // audio format (1 = PCM)
            writeShort(output, (short) 1); // number of channels
            writeInt(output, sampleRate); // sample rate
            writeInt(output, sampleRate * 2); // byte rate
            writeShort(output, (short) 2); // block align
            writeShort(output, (short) 16); // bits per sample
            writeString(output, "data"); // subchunk 2 id
            writeInt(output, rawData.length); // subchunk 2 size
            // Audio data (conversion big endian -> little endian)
            short[] shorts = new short[rawData.length / 2];
            ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
            ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
            for (short s : shorts) {
                bytes.putShort(s);
            }

            output.write(fullyReadFileToBytes(rawFile));
        } finally {
            if (output != null) {
                output.close();
            }
        }
    }

    byte[] fullyReadFileToBytes(File f) throws IOException {
        int size = (int) f.length();
        byte bytes[] = new byte[size];
        byte tmpBuff[] = new byte[size];
        FileInputStream fis= new FileInputStream(f);
        try {

            int read = fis.read(bytes, 0, size);
            if (read < size) {
                int remain = size - read;
                while (remain > 0) {
                    read = fis.read(tmpBuff, 0, remain);
                    System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
                    remain -= read;
                }
            }
        }  catch (IOException e){
            throw e;
        } finally {
            fis.close();
        }

        return bytes;
    }
    private void writeInt(final DataOutputStream output, final int value) throws IOException {
        output.write(value >> 0);
        output.write(value >> 8);
        output.write(value >> 16);
        output.write(value >> 24);
    }

    private void writeShort(final DataOutputStream output, final short value) throws IOException {
        output.write(value >> 0);
        output.write(value >> 8);
    }

    private void writeString(final DataOutputStream output, final String value) throws IOException {
        for (int i = 0; i < value.length(); i++) {
            output.write(value.charAt(i));
        }
    }

代码来源:https://stackoverflow.com/questions/37281430/how-to-convert-pcm-file-to-wav-or-mp3

以上是关于保存wave音频流的方法的主要内容,如果未能解决你的问题,请参考以下文章

Goldwave生成wave音频数据

Wave文件编码:保存文件

PyDub 从变量播放音频

Wave 文件 - 处理特定的音频数据块

在java中录制流式音频?

C# NAudio:如何访问 SignalGenerator 提供的样本以将它们保存为 WAVE 格式?