You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中将short[]数组写入.wav文件?

直接将short[]格式PCM数据导出为WAV文件的实现方案

你完全不需要通过“播放再录制”这种绕路的方式,直接利用WAV文件的结构特性,把AudioTrack使用的short[]格式PCM数据写入WAV文件即可——WAV本质就是标准文件头 + 原始PCM数据的组合,而你手里的short[]正好是16位PCM采样数据,完美匹配。

实现步骤

  1. 构建标准WAV文件头:WAV文件头固定为44字节,需要根据你的AudioTrack配置(采样率、声道数)填充对应参数:

    • 采样率:和你初始化AudioTrack时的参数一致(比如44100Hz、48000Hz)
    • 声道数:单声道填1,立体声填2
    • 位深度:固定为16位(对应short类型)
  2. 写入文件:先把构建好的文件头写入目标文件,再将short[]数据按小端字节顺序(符合WAV标准)转换成字节数组写入文件。

代码示例(Android/Java)

import java.io.FileOutputStream;
import java.io.IOException;

public class WavExporter {
    // 导出short[]格式PCM为WAV文件
    public static void exportShortPcmToWav(short[] pcmData, int sampleRate, int channels, String outputPath) throws IOException {
        FileOutputStream fos = new FileOutputStream(outputPath);
        int bitsPerSample = 16;
        byte[] wavHeader = buildWavHeader(pcmData.length, sampleRate, channels, bitsPerSample);
        
        // 先写入WAV文件头
        fos.write(wavHeader);
        // 将short类型PCM数据转换为小端字节数组并写入
        byte[] pcmBytes = new byte[pcmData.length * 2];
        for (int i = 0; i < pcmData.length; i++) {
            short sample = pcmData[i];
            pcmBytes[i * 2] = (byte) (sample & 0xFF);
            pcmBytes[i * 2 + 1] = (byte) ((sample >> 8) & 0xFF);
        }
        fos.write(pcmBytes);
        fos.close();
    }

    // 构建44字节的标准WAV文件头
    private static byte[] buildWavHeader(int pcmSampleCount, int sampleRate, int channels, int bitsPerSample) {
        byte[] header = new byte[44];
        int byteRate = sampleRate * channels * bitsPerSample / 8;
        int dataSize = pcmSampleCount * channels * bitsPerSample / 8;
        int fileSize = 36 + dataSize;

        // RIFF标识
        header[0] = 'R';
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        // 文件总大小
        header[4] = (byte) (fileSize & 0xFF);
        header[5] = (byte) ((fileSize >> 8) & 0xFF);
        header[6] = (byte) ((fileSize >> 16) & 0xFF);
        header[7] = (byte) ((fileSize >> 24) & 0xFF);
        // WAVE标识
        header[8] = 'W';
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        // fmt子块标识
        header[12] = 'f';
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        // fmt子块大小(PCM格式固定为16)
        header[16] = 16;
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        // 音频格式(PCM格式固定为1)
        header[20] = 1;
        header[21] = 0;
        // 声道数
        header[22] = (byte) channels;
        header[23] = 0;
        // 采样率
        header[24] = (byte) (sampleRate & 0xFF);
        header[25] = (byte) ((sampleRate >> 8) & 0xFF);
        header[26] = (byte) ((sampleRate >> 16) & 0xFF);
        header[27] = (byte) ((sampleRate >> 24) & 0xFF);
        // 字节率
        header[28] = (byte) (byteRate & 0xFF);
        header[29] = (byte) ((byteRate >> 8) & 0xFF);
        header[30] = (byte) ((byteRate >> 16) & 0xFF);
        header[31] = (byte) ((byteRate >> 24) & 0xFF);
        // 块对齐
        header[32] = (byte) (channels * bitsPerSample / 8);
        header[33] = 0;
        // 位深度
        header[34] = (byte) bitsPerSample;
        header[35] = 0;
        // data子块标识
        header[36] = 'd';
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        // PCM数据大小
        header[40] = (byte) (dataSize & 0xFF);
        header[41] = (byte) ((dataSize >> 8) & 0xFF);
        header[42] = (byte) ((dataSize >> 16) & 0xFF);
        header[43] = (byte) ((dataSize >> 24) & 0xFF);

        return header;
    }
}

使用说明

调用时直接传入你的short[]音频数据、AudioTrack使用的采样率、声道数,以及输出文件路径即可:

// 示例:单声道、44100Hz采样率的音频数据导出
try {
    WavExporter.exportShortPcmToWav(yourShortPcmData, 44100, 1, "/sdcard/Music/your_music.wav");
} catch (IOException e) {
    e.printStackTrace();
}

这种方式完全避免了播放录制的弊端:无需播放音频、导出速度极快、不会引入外界杂音,直接利用已有数据完成导出,是最直接高效的方案。

内容的提问来源于stack exchange,提问作者16-bit-apps

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 13:28:24