I read these 2 articles: Writing PCM recorded data into a .wav file (java android)
http://soundfile.sapp.org/doc/WaveFormat/
And created my program that converts .pcm file into .wav file. But when I open it with VLC, it doesn't play it. I have pcm file that works perfect so I don't know why my program doesn't work. I am putting all fields(except strings) inside a file in little-endian format with reverseBytes() function. What did I do wrong?
EDIT: Code works now
public class MainActivity extends AppCompatActivity {
private String pahtFile = "/sdcard/voice8K16bitmono.pcm";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
byte[] clipData = getBytesFromFile(new File(pahtFile));
myDatasize = clipData.length; //262 144 bytes in my PCM file
/** Data for creating "The canonical WAVE file format"
http://soundfile.sapp.org/doc/WaveFormat/
*/
int BitsPerSample = 16;
String ChunkID = "RIFF";
String Format = "WAVE";
String Subchunk1ID = "fmt ";
int mySubChunk1Size = 16;
short AudioFormat = 1;
short NumChannels = 1;
int SampleRate = 44100;
int ByteRate = SampleRate*((int)NumChannels)*BitsPerSample/8;
short BlockAlign = (short) (NumChannels*((short)(BitsPerSample/8)));
String Subchunk2ID = "data";
int Subchunk2Size = (int)myDatasize;
int chunkSize = 36 + Subchunk2Size;
Log.d("SEBALOG","BlockAlign: " + BlockAlign);
OutputStream os;
os = new FileOutputStream(new File("/sdcard/firstWav.wav"));
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream outFile = new DataOutputStream(bos);
outFile.writeBytes(ChunkID); // The riff chunk descriptor
outFile.writeInt(Integer.reverseBytes(chunkSize));
outFile.writeBytes(Format);
outFile.writeBytes(Subchunk1ID); // The fmt sub-chunk
outFile.writeInt(Integer.reverseBytes(mySubChunk1Size));
outFile.writeShort(Short.reverseBytes(AudioFormat));
outFile.writeShort(Short.reverseBytes(NumChannels));
outFile.writeInt(Integer.reverseBytes(SampleRate));
outFile.writeInt(Integer.reverseBytes(ByteRate));
outFile.writeShort(Short.reverseBytes(BlockAlign));
outFile.writeShort(Short.reverseBytes((short) BitsPerSample));
outFile.writeBytes(Subchunk2ID); // The "data" sub-chunk
outFile.writeInt(Integer.reverseBytes(Subchunk2Size));
outFile.write(clipData);
outFile.flush();
outFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] getBytesFromFile(File file) throws IOException{
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead = is.read(bytes, offset, Math.min(bytes.length - offset, 512*1024))) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
}