1

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;
}
}
Community
  • 1
  • 1
user101
  • 595
  • 1
  • 4
  • 18
  • What do you mean by "it doesn't play"? Does VLC output any kind of error to you? Can you post a hex dump of the resulting RIFF header you produce? – PhilMasteG Aug 24 '15 at 14:07
  • @PhilippGrassl It plays the file(no error is shown) in a split second without a sound. The recording is 12.5 seconds long. How can I get hex dump of the RIFF header?`127|shell@luv50ssn:/sdcard $ hexdump firstWav.wav /system/bin/sh: hexdump: not found` – user101 Aug 24 '15 at 14:28
  • @user101 use `adb pull` to get the wav onto your computer and use a hex editor there – Buddy Aug 24 '15 at 19:03
  • with hex tool I found that there are couple of errors in the code:`outFile.writeShort(Short.reverseBytes(BlockAlign));` was missing and `BitsPerSample/2` Should be 8 instead of 2. I updated the code and the program now works. – user101 Aug 25 '15 at 09:06

0 Answers0