在android中进行PCM到WAV的转换

时间:2015-12-14 14:11:05

标签: java android wav pcm

我使用AudioRecord类录制了声音。但它不能通过音乐播放器播放。所以我在音频文件中添加了一些标题信息。虽然它现在可以通过音乐播放器播放,但它的滞后和嘈杂,它没有播放精确的声音。 任何帮助,将不胜感激 。 我的代码在

之下
private void rawToWave(final File rawFile, 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 {
        int myBitsPerSample= 2;
        int myFormat = 1;
        long myChannels = 1;
        long mySampleRate = 8000 ;
        long myByteRate = mySampleRate * myChannels * myBitsPerSample/8;
        int myBlockAlign = (int) (myChannels * myBitsPerSample/8);

        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, (int)mySampleRate ); // sample ratemySampleRate
        writeInt(output, (int) (myByteRate)); // byte rate
        writeShort(output, (short) myBlockAlign); // 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(bytes.array());
    } finally {
        if (output != null) {
            output.close();
        }
    }
}

public  void writeShortLE(DataOutputStream out, short value) throws IOException {
    out.writeByte(value & 0xFF);
    out.writeByte((value >> 8) & 0xFF);
}



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));
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个完整的工作示例:

/**
 * @param input         raw PCM data
 *                      limit of file size for wave file: < 2^(2*4) - 36 bytes (~4GB)
 * @param output        file to encode to in wav format
 * @param channelCount  number of channels: 1 for mono, 2 for stereo, etc.
 * @param sampleRate    sample rate of PCM audio
 * @param bitsPerSample bits per sample, i.e. 16 for PCM16
 * @throws IOException in event of an error between input/output files
 * @see <a href="http://soundfile.sapp.org/doc/WaveFormat/">soundfile.sapp.org/doc/WaveFormat</a>
 */
static public void PCMToWAV(File input, File output, int channelCount, int sampleRate, int bitsPerSample) throws IOException {
    final int inputSize = (int) input.length();

    try (OutputStream encoded = new FileOutputStream(output)) {
        // WAVE RIFF header
        writeToOutput(encoded, "RIFF"); // chunk id
        writeToOutput(encoded, 36 + inputSize); // chunk size
        writeToOutput(encoded, "WAVE"); // format

        // SUB CHUNK 1 (FORMAT)
        writeToOutput(encoded, "fmt "); // subchunk 1 id
        writeToOutput(encoded, 16); // subchunk 1 size
        writeToOutput(encoded, (short) 1); // audio format (1 = PCM)
        writeToOutput(encoded, (short) channelCount); // number of channelCount
        writeToOutput(encoded, sampleRate); // sample rate
        writeToOutput(encoded, sampleRate * channelCount * bitsPerSample / 8); // byte rate
        writeToOutput(encoded, (short) (channelCount * bitsPerSample / 8)); // block align
        writeToOutput(encoded, (short) bitsPerSample); // bits per sample

        // SUB CHUNK 2 (AUDIO DATA)
        writeToOutput(encoded, "data"); // subchunk 2 id
        writeToOutput(encoded, inputSize); // subchunk 2 size
        copy(new FileInputStream(input), encoded);
    }
}


/**
 * Size of buffer used for transfer, by default
 */
private static final int TRANSFER_BUFFER_SIZE = 10 * 1024;

/**
 * Writes string in big endian form to an output stream
 *
 * @param output stream
 * @param data   string
 * @throws IOException
 */
public static void writeToOutput(OutputStream output, String data) throws IOException {
    for (int i = 0; i < data.length(); i++)
        output.write(data.charAt(i));
}

public static void writeToOutput(OutputStream output, int data) throws IOException {
    output.write(data >> 0);
    output.write(data >> 8);
    output.write(data >> 16);
    output.write(data >> 24);
}

public static void writeToOutput(OutputStream output, short data) throws IOException {
    output.write(data >> 0);
    output.write(data >> 8);
}

public static long copy(InputStream source, OutputStream output)
        throws IOException {
    return copy(source, output, TRANSFER_BUFFER_SIZE);
}

public static long copy(InputStream source, OutputStream output, int bufferSize) throws IOException {
    long read = 0L;
    byte[] buffer = new byte[bufferSize];
    for (int n; (n = source.read(buffer)) != -1; read += n) {
        output.write(buffer, 0, n);
    }
    return read;
}