3 Replies Latest reply on Oct 12, 2012 9:40 AM by 966377

    Recording audio files in PCM_FLOAT format


      I'm trying to record voice sample and I've got a problem with my .wav format. With:
      AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 1, 2, 44100.0F, false);
      everything works fine. But what I need (because of further analysis of this audio file in Matlab) is PCM_FLOAT format:
      AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_FLOAT, 8000.0F, 32, 1, 4, 8000.0F, true);
      which unfortunately returns an error:
      Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException:
       No line matching interface TargetDataLine supporting format PCM_FLOAT 8000.0 Hz, 32 bit, mono, 4 bytes/frame,  is supported.
      I've tried a lot of different combinations with PCM_FLOAT but every one of them returns same exception. I'm probably missing something but the question is: what? How can I find what audio formats could work with my sound card? If I can only use PCM_SIGNED or UNSIGNED how can I convert recorded .wav file to PCMFLOAT?
        • 1. Re: Recording audio files in PCM_FLOAT format
          Does Matlab need a formal PCM_FLOAT Audio format encoding or does it just need a stream/array of floating point numbers? If the latter then this is very easy to create from PCM_SIGNED by taking the PCM value and dividing by the maximum value (128.0 on single byte, 32768.0 in double byte etc etc) and casting to 'float'. If the former then it will be a little more complex but probably not difficult; the conversion to 4 byte float' values is the same so you will just have to convert the rest of the fields.

          Note - of course I am assuming that the 'float' format is the IEEE 754 that Matlab uses internally.
          1 person found this helpful
          • 2. Re: Recording audio files in PCM_FLOAT format
            I've finally been able to try what you suggested. As server received from the client an array of bytes I tried to convert it to an array of floats:
            IntBuffer sbuf = ByteBuffer.wrap(myAudioBytes).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
            int[] audioInts = new int[sbuf.capacity()];
            float[][] audioFloats = new float[audioInts.length][1];
            for (int k = 0; k < audioInts.length; k++) 
                audioFloats[k][0] = ((float)audioInts[k])/0x8000; // Two dimensions in audioFloats because Utils.floatsToWav needs to know whether it's mono or not.
            and then save it to file using http://code.google.com/p/j-simple-wav-io/ :
            Utils.floatsToWAV(audioFloats,new File("output.wav"),8000);
            Unfortunately it didn't work. I checked the .wav files with AudioFileInfo from jsresources.org and it recognizes the format of output.wav as:
            Type: WAVE
            AudioFormat: PCM_SIGNED, 8000.0 Hz, 16 bit, mono, 2 bits/frame, little-endian
            Lenght of audio data: 22050 frames, 44100 bytes, 2,75625 seconds
            Total lenght of file (including headers): 44144 bytes
            while valid audio file (I mean the one that actually works with my Matlab script) is:
            Type: WAVE
            AudioFormat: PCM_FLOAT, 8000.0 Hz, 32 bit, mono, 4 bits/frame
            Lenght of audio data: unknown
            Total lenght of file (including headers): unknown
            Before that I tried to do it another way:

            - getTargetEncodings(originalFormat) --> returned PCM_FLOAT (amongst others);
            - isConversionSupported(targetFormat, originalFormat) --> returned true;

            (where originalFormat is "PCM_SIGNED, 8000.0F, 16, 1, 2, 8000.0F, false" and targetFormat is "PCM_FLOAT, 8000.0F, 32, 1, 4, 8000.0F, false" - as you can see above I don't really know if Matlab wants little or big endian).

            so I thought sth like this will do the trick:
            ByteArrayInputStream bais = new ByteArrayInputStream(myAudioBytes);
            AudioInputStream AIS = new AudioInputStream(bais, originalFormat, myAudioBytes.length / originalFormat.getFrameSize());
            if(AudioSystem.isConversionSupported(targetFormat, originalFormat))
                AIS = AudioSystem.getAudioInputStream(targetFormat, AIS);
            File file = new File(fileName);
            int nWrittenBytes = 0;
                nWrittenBytes = AudioSystem.write(AIS, AudioFileFormat.Type.WAVE, file);
            It didn't work either (but it seems that this bit can help switching from 16 to 32 bits and from 2 to 4 bits/frame).

            So - clearly I've done something wrong but again have no idea what. I'm sort of new to Java and an absolute novice to processing audio files so thanks for all the advices :-).
            • 3. Re: Recording audio files in PCM_FLOAT format
              Ok, I did it. But I don't think I like Java anymore.

              In case anybody has the same problem:

              I recorded an audio sample in PCM_SIGNED, 44,1kHz, 16, 1, 2.

              Then in terminal: sudo apt-get install sox

              And in Java code:
              Process convert = Runtime.getRuntime().exec("sox /home/source/input.wav -e floating-point -r 8000 /home/destination/output.wav");