13 Replies Latest reply: Jul 26, 2010 2:25 PM by 843802 RSS

    Raw data to wav

    843802
      I have the following code:
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      DataOutputStream dos = new DataOutputStream(baos);
      
      int[] values = t.getIntArray();
      
      for (int i = 0; i < values.length; i++)
          dos.writeInt(values);

      AudioFormat wavFormat = new AudioFormat(8000, 16, 1, true, true);
      byte[] abAudioData = baos.toByteArray();
      ByteArrayInputStream bais = new ByteArrayInputStream(abAudioData);
      AudioInputStream stream = new AudioInputStream(bais, wavFormat, abAudioData.length
      / wavFormat.getFrameSize());
      AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("mywav.wav"));
      The problem with this is "clipping" some of the samples created are clipped.
      
      In fact I have limited understanding of sound and WAV, I've been reading about sound in general but I still strugle with basic things.
      
      
      The whole issue here is the data I am working with, it is raw integers.  So my questions are:
      
      How do you convert such data into WAV format?  Am i on the right path by what you see above?
      How do I deal with clipping?
      
      I tried:
      dos.writeInt(values[i]/100);
      and
      dos.writeInt(values[i]/1000);
      Nothing changed except for the amplitude.
      
      How do compute the correct amplification needed if any?
      Can I just take the raw data and copy it in to the audioinputstream, or do I have to work the data before.
      
      I know I have too many questions but I am hoping I get some input to guide me further.  Thank you in advance                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        • 1. Re: Raw data to wav
          captfoss
          First off, integers in Java are 32-bit, and you're specifing in your audio format object that the samples are 16-bit. You should be using dos.writeShort to write 16-bit samples, otherwise you're writing data into the stream in a different manner than the audio stream is expecting...
          How do you convert such data into WAV format?
          How do I convert raw data into JPEG format? Well, depends on the data, doesn't it?
          How do I deal with clipping?
          Depends on what you mean by clipping, and it depends on where the clipping is coming from.

          A series of questions for you...

          1) What is this "raw data" you're dealing with?
          2) What do you mean by clipping?
          3) Is the data itself clipped, or do you believe the clipping to be a byproduct of the way you're rendering it?
          • 2. Re: Raw data to wav
            843802
            Thank you for your reply:

            I want to start with the data itself. The data is very raw, its coming from sensors measuring movement, the sensors are basic; they are not audio sensors or anything like that. The data is sampled at rate of 20 bits/second, stored as signed bi endians. Thats everything I know about the data. Now I am trying to generate wav files and increase sampling rate to 8000. I've been reading about sound and wav but not much help.

            As for the 16 PCM and writeInt, I did:
            AudioFormat wavFormat = new AudioFormat(8000, 32, 1, true, true);
            but got back:
            java.lang.IllegalArgumentException: could not write audio file: file type not supported: WAVE
            Clipping as I understanding it from the reading I have done is when data values are bigger than the maximum a system can take!
            • 3. Re: Raw data to wav
              captfoss
              As for the 16 PCM and writeInt, I did:
              AudioFormat wavFormat = new AudioFormat(8000, 32, 1, true, true);
              but got back:
              java.lang.IllegalArgumentException: could not write audio file: file type not supported: WAVE
              If you'll notice, I told you to change the way you were writing the data, not to change the format object for your audio stream. This was intentional, because 16-bit is the biggest standard format for audio encoding... the largest supported is probably 24-bit, but, then you'd have all sorts of bad stuff happening (because there's no 24-bit numbers in existance, you'd have to handle the conversions yourself)....
              Clipping as I understanding it from the reading I have done is when data values are bigger than the maximum a system can take!
              Yeah, I wasn't really looking for a definition, I know what the word means...

              You said "some of the samples created are clipped."

              How do you know they are clipped?

              Edited by: captfoss on Jul 26, 2010 10:53 AM
              • 4. Re: Raw data to wav
                843802
                Thanks again.

                I was not trying to define clipping, I only wanted to tell you how I understand it. First, I hear clicks in the audio. Second I read the generated file and plotted the values and I can see where the highest point is and how more samples are clipped there. I may be wrong about my conclusion.

                How do you convert the data to short, is there a way specific to sound to do the conversion.
                • 5. Re: Raw data to wav
                  captfoss
                  yaza wrote:
                  First, I hear clicks in the audio.
                  The clicks in the audio likely have to do with the fact you're writing integers instead of shorts...
                  How do you convert the data to short, is there a way specific to sound to do the conversion.
                  There's nothing numerically special about sound, you're just dealing with a stream of numbers...
                  Second I read the generated file and plotted the values and I can see where the highest point is and how more samples are clipped there. I may be wrong about my conclusion.
                  If you want to be fancy about it, you'd want to scan through your entire file, find the highest value & the lowest value, and then scale all of your values to fit into 16 bits...

                  IE, given lowest_sample and highest_sample,

                  1) Subtract lowest_sample from each sample, to align your lowest value to 0.
                  2) Multiple each sample by (highest_sample / 2^16), to scale your highest value to fit within 16-bits.

                  That assumes, of course, that you're dealing with data on the range of 0,whatever. If you've got negative numbers, then the calculations will be slightly more complicated...

                  But you scale the numbers equally to fit within the range you're allowed (16-bits), and then you can just cast them to shorts and be fine.

                  That assumes, of course, you're using unsigned
                  • 6. Re: Raw data to wav
                    843802
                    Why do you need an audio file?
                    • 7. Re: Raw data to wav
                      843802
                      Its an interesting project. the idea is to hear sound/waves generated from movement.
                      • 8. Re: Raw data to wav
                        843802
                        yaza wrote:
                        Its an interesting project. the idea is to hear sound/waves generated from movement.
                        Since movement is likely to be very low frequency outside the human range, it sounds to me like you will need to use the sample values to modulate (frequency/phase) some audible carrier. I have just done some simple tests and middle C (440 Hz) is not a bad carrier frequency with a maximum frequency modulation of about 40 HZ (10 % ish);
                        • 9. Re: Raw data to wav
                          843802
                          Any hints or pointers on how to do that. Are you talking about Fourier transformation? Again, my background in sound is so limited and basic. All I am doing here is changing sampling rate to 80000:
                          AudioFormat wavFormat = new AudioFormat(8000, 16, 1, true, true);
                          Is the above good enough?
                          Thank you
                          • 10. Re: Raw data to wav
                            843802
                            This is what I have so far
                            static int positiveMax = 0;
                                 static int positiveMin = 100000;
                                 static int negativeMax = 0;
                                 static int negativeMin = 100000;
                            
                                 public static AudioInputStream convertDoublesToAudioStream(TimeSeries t,
                                           int sampleRate) {
                                      ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                      DataOutputStream dos = new DataOutputStream(baos);
                            
                                      int[] values = t.getIntArray();
                            
                                      int value = 0;
                                      for (int i = 0; i < values.length; i++) {
                                           value = values;
                                           if (value < 0) {
                                                value = -value;
                                                if (negativeMax < value) {
                                                     negativeMax = value;
                                                }
                                                if (negativeMin > value) {
                                                     negativeMin = value;
                                                }
                                           } else {
                                                if (positiveMax < value) {
                                                     positiveMax = value;
                                                }
                                                if (positiveMin > value) {
                                                     positiveMin = value;
                                                }
                                           }
                                      }
                                      negativeMax = -negativeMax;
                                      negativeMin = -negativeMin;
                                      System.out.println("positiveMax: " + positiveMax);
                                      System.out.println("positiveMin: " + positiveMin);
                                      System.out.println("negativeMax: " + negativeMax);
                                      System.out.println("negativeMin: " + negativeMin);


                                      try {
                                           double someNumber = Math.pow(2,16);
                                           for (int i = 0; i < values.length; i++) {

                                                value = values[i];
                                                if(value > 0){
                                                     value = value - positiveMin;
                                                     value = (int)(value * (someNumber/positiveMax));
                                                }else{
                                                     value = value - negativeMin;
                                                     value = (int)-(value * (someNumber/negativeMax));
                                                }
                                                System.out.println(value);
                                                //value = values[i] * 32768 / max;

                                                //dos.writeShort(value >>> 3);// values[i]>>3);
                                                dos.writeShort(value);// values[i]>>3);

                                           }
                                      } catch (IOException e) {
                                           e.printStackTrace();
                                      }

                                      // AudioFormat wavFormat = new
                                      // AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sampleRate, 32, 1, 32,
                                      // 3, true);
                                      AudioFormat wavFormat = new AudioFormat(sampleRate, 16, 1, true, true);

                                      byte[] abAudioData = baos.toByteArray();
                                      ByteArrayInputStream bais = new ByteArrayInputStream(abAudioData);

                                      return new AudioInputStream(bais, wavFormat, abAudioData.length
                                                / wavFormat.getFrameSize());
                                 }
                            However, I hear clicks, they are loud and disturbing.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                            • 11. Re: Raw data to wav
                              captfoss
                              Well, for onc, you're not handling the conversion correctly... you can't scale above 0 and below zero at different levels, that doesn't even make sense if you think about it...

                              You'd need to locate the number that has the largest absolute value, and scale based on that...

                              But that isn't likely to fix the disturbing clicks...because, as sabre said, you're probably trying to listen to something that isn't pretty to listen to...
                              • 12. Re: Raw data to wav
                                843802
                                yaza wrote:
                                Any hints or pointers on how to do that. Are you talking about Fourier transformation?
                                No! Nothing that complicated. Create a carrier using Math.sin() and modulate the frequency/phase as a linear function of the position measurement.
                                Again, my background in sound is so limited and basic.
                                Then you need to get up to speed fast. Whether this is a college/university/school project or for industry nobody here is going to do the work for you so start learning.
                                All I am doing here is changing sampling rate to 80000:
                                That will shift the frequency up but make the listening period correspondingly shorter.
                                AudioFormat wavFormat = new AudioFormat(8000, 16, 1, true, true);
                                Is the above good enough?
                                For a 440 Hz carrier that is more than enough. You can probably go down to about 1600 samples per second (4 times the Nyquist frequency) for 440 Hz carrier.
                                Thank you
                                • 13. Re: Raw data to wav
                                  843802
                                  I'm betting that each two byte output from the OP's device is either signed short or an excess 0x8000 short encoded as two bytes. If the OP is just going to create an audio file from the samples then he is pretty much there. If signed values then the bytes do not need modifying. If excess 0800 he just needs to xor the most significant byte with 0x80 .

                                  If the OP is going to process the values maybe along the lines I have suggested then he need to convert the pairs to shorts and then to doubles. I always scale the doubles to +/- 1.0 by dividing by 32768.0 .