Android:将double数组转换为byte数组方法(WAV存储场景)
Since you already have a method to convert WAV file bytes to a double array, converting the processed doubles back to a valid byte array (and ultimately a WAV file) depends on matching the audio format of your original WAV file. The most common format is 16-bit PCM (Pulse Code Modulation), where audio samples are stored as 16-bit signed integers, normalized to the range [-1.0, 1.0] in your double array.
Here's a practical implementation aligned with your existing code:
1. Core Double-to-Byte Conversion Method
This method converts your normalized double array back to a byte array in 16-bit PCM format (little-endian, the standard for WAV files):
private byte[] doublesToBytes(double[] doubleArray) { // 16-bit PCM uses 2 bytes per audio sample byte[] byteArray = new byte[doubleArray.length * 2]; ByteBuffer buffer = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); for (int i = 0; i < doubleArray.length; i++) { // Clamp values to [-1.0, 1.0] to prevent integer overflow double clampedValue = Math.max(-1.0, Math.min(1.0, doubleArray[i])); // Convert normalized double to 16-bit signed integer (range: -32768 to 32767) short sample = (short) (clampedValue * Short.MAX_VALUE); // Write the short value to buffer and copy to the output byte array buffer.putShort(sample); byte[] sampleBytes = buffer.array(); byteArray[i * 2] = sampleBytes[0]; byteArray[i * 2 + 1] = sampleBytes[1]; // Reset buffer for the next sample buffer.rewind(); } return byteArray; }
2. Save the Byte Array as a Valid WAV File
A valid WAV file requires its original header (which stores metadata like sample rate, bit depth, and channel count). Here's how to combine the header with your processed audio data:
private void saveDoubleArrayAsWav(double[] processedDoubles, File originalWav, File outputWav) { try (FileInputStream in = new FileInputStream(originalWav); FileOutputStream out = new FileOutputStream(outputWav)) { // Read the standard 44-byte WAV header from the original file byte[] header = new byte[44]; in.read(header); // Convert processed doubles to the required byte format byte[] dataBytes = doublesToBytes(processedDoubles); // Update header fields to reflect the new data size // Chunk size: 36 + total data byte length int chunkSize = 36 + dataBytes.length; ByteBuffer.wrap(header, 4, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(chunkSize); // Subchunk2 size: total data byte length ByteBuffer.wrap(header, 40, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(dataBytes.length); // Write the updated header and processed data to the output file out.write(header); out.write(dataBytes); } catch (IOException e) { e.printStackTrace(); } }
Important Considerations
- Format Compatibility: If your original WAV uses a non-16-bit PCM format (e.g., 24-bit PCM, 32-bit float), adjust the conversion logic. For 32-bit float WAV, you'd convert doubles directly to floats and then to bytes instead of using shorts.
- Value Clamping: Never skip clamping your double values to
[-1.0, 1.0]—values outside this range will cause overflow, leading to distorted or corrupted audio. - Byte Order: WAV files always use little-endian byte order for sample data, so ensure your
ByteBufferis configured withByteOrder.LITTLE_ENDIAN.
内容的提问来源于stack exchange,提问作者Florian

