This discussion is archived
3 Replies Latest reply: Oct 12, 2012 2:40 AM by 966377 RSS

Recording audio files in PCM_FLOAT format

966377 Newbie
Currently Being Moderated
Hello!

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
    sabre150 Expert
    Currently Being Moderated
    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.
  • 2. Re: Recording audio files in PCM_FLOAT format
    966377 Newbie
    Currently Being Moderated
    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()];
    sbuf.get(audioInts);
    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;
    try
    {
        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
    966377 Newbie
    Currently Being Moderated
    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");
    :)

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points