Si encuentras algún detalle que no comprendes puedes comentarlo y te responderemos tan rápido como podamos.
Tienes la mayor parte del código correcto. El único problema que puedo ver es la parte en la que escribe los datos PCM en el archivo WAV. Esto debería ser bastante simple de hacer porque WAV = Metadatos + PCM (en ese orden). Esto debería funcionar:
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
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, 44100); // sample rate
writeInt(output, RECORDER_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));
Cómo utilizar
Es muy sencillo de utilizar. Solo llámalo así:
File f1 = new File("/sdcard/44100Sampling-16bit-mono-mic.pcm"); // The location of your PCM file
File f2 = new File("/sdcard/44100Sampling-16bit-mono-mic.wav"); // The location where you want your WAV file
try
rawToWave(f1, f2);
catch (IOException e)
e.printStackTrace();
Como funciona todo esto
Como puede ver, el encabezado WAV es la única diferencia entre los formatos de archivo WAV y PCM. La suposición es que está grabando audio PCM MONO de 16 bits (que de acuerdo con su código, lo está). La función rawToWave simplemente agrega encabezados al archivo WAV, para que los reproductores de música sepan qué esperar cuando se abre su archivo, y luego, después de los encabezados, simplemente escribe los datos PCM desde el último bit en adelante.
Consejo genial
Si desea cambiar el tono de su voz o crear una aplicación de cambio de voz, todo lo que tiene que hacer es aumentar / disminuir el valor de writeInt(output, 44100); // sample rate
en su código. Disminuirlo le dirá al jugador que lo reproduzca a una velocidad diferente, cambiando así el tono de salida. Solo un poco más de "bueno saber". 🙂