0

I have no idea how to do this. I have read the answers to several similar questions and some websites that probably had the answer somewhere, but either I could not understand them or they were not what I am trying to do. It is also possible that some did have the answer, but I could not focus well enough to interpret it. I want a method that converts the data from a WAV file signed 16-bit raw audio data and puts this into a short[]. I would prefer short minimalistic easy to understand answers because I would have less difficulty focusing on those.

Edit: Some have said this might be a duplicate of stackoverflow.com/questions/5210147/reading-wav-file-in-java. I do not understand that question or its answers well enough to even say whether it is different or why or how to change my question so it is not confused for that one.

Another edit: I have attempted using Phil Freihofner's answer, but when testing this by attempting to pay back the audio, I just heard a lot of clicks. I am not sure if I implemented it correctly. Here is the method that reads the file:

static void loadAudioDataTest(String filepath){
        int totalFramesRead = 0;
        File fileIn = new File(filepath);
        try {
          AudioInputStream audioInputStream = 
            AudioSystem.getAudioInputStream(fileIn);
          int bytesPerFrame = 
            audioInputStream.getFormat().getFrameSize();
            if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) {
            bytesPerFrame = 1;
          } 
          int numBytes = 1024 * bytesPerFrame; 
          byte[] audioBytes = new byte[numBytes];
          audioArray=new short[numBytes/2];
          try{
            int numBytesRead = 0;
            int numFramesRead = 0;
            while ((numBytesRead = 
              audioInputStream.read(audioBytes)) != -1) {
              numFramesRead = numBytesRead / bytesPerFrame;
              totalFramesRead += numFramesRead;
            }for(int a=0;a<audioArray.length;a++){
                  audioArray[acc]=(short)((audioBytes[a*2]&0xff)|(audioBytes[acc*2+1]<<8));
            }
          } catch (Exception ex) { 
            // Handle the error...
          }
        } catch (Exception e) {
          // Handle the error...
        }
    }

This bit plays the sound and is inside an actionPerformed(ActionEvent) void that is repeatedly activated by a timer, in case the issue is there

byte[]buf=new byte[2];
        AudioFormat af=new AudioFormat(44100,16,1,true,false);
        SourceDataLine sdl;
        try{
            sdl=AudioSystem.getSourceDataLine(af);
            sdl.open();
            sdl.start();
                buf[1]=(byte) (audioArray[t%audioArray.length]&0xFF); 
                buf[0]=(byte) (audioArray[t%audioArray.length]>>8);
                sdl.write(buf,0,2);
            sdl.drain();
            sdl.stop();
        }catch(LineUnavailableException e1){
            e1.printStackTrace();
        }t++;
Jyon Nyre
  • 61
  • 6

1 Answers1

0

The current core java class commonly used for loading data into a byte array is AudioInputStream (javax.sound.sampled.AudioInputStream). An example of its use, with explanation, can be found in the Oracle tutorial Using Files and Format Converters. The sample code is in the section titled "Reading Sound Files". Note the point in the innermost while loop with the following line: // Here, do something useful with the audio data. At that point, you would load the data into your array.

Taking two bytes and converting them to a short has been answered several times but I don't have the links handy. It's easier to just post some code I have used.

audioArray[i] = ( buffer[bufferIdx] & 0xff )
                        | ( buffer[bufferIdx + 1] << 8 ) ;

... where audioArray could be a short[]. (In my code I use float[] and do another step to scale the values to range from -1 to 1.)

This is a slightly modified snipped from the library AudioCue on github, quoting from lines 391-393.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41