This discussion is archived
11 Replies Latest reply: Apr 29, 2011 7:35 AM by captfoss RSS

Audio recording/play-back plug-in error

815132 Newbie
Currently Being Moderated
Hi there. Posted on here before...I'm having a problem with my JMF program. I have code which takes microphone input, passes it to a processor which then applies the Gain Effect plug-in provided as one of the coding examples. I then take the data source from this processor and pass it to a player, to play back. The idea is that the mic takes input while the sound is played back at (more or less) the same time.

And now my problem. When the plug-in is applied, the sound played back is not what it should be. In fact, it is like a low infrequent static sound. It is hard to describe! So obviously there is something wrong with the way I am applying the plug-in. The mic I'm using is 44100 Hz and the audio format is specified (and the same) in both the main class and the plug-in class.

Below is my code. Does anyone know what I'm doing wrong?
//importing happens here

public class audCap {

     
public static void main(String[] args) {

          
        AudioFormat format = new AudioFormat(     
                                AudioFormat.LINEAR,
                    44100,
                    16,
                    2,
                    AudioFormat.LITTLE_ENDIAN,
                    AudioFormat.SIGNED,
                    16,
                    Format.NOT_SPECIFIED,
                    Format.byteArray); 
        
        Format[] alinear=new AudioFormat[]{new AudioFormat(     
                  AudioFormat.LINEAR,
                   44100,
                   16,
                   2,
                   AudioFormat.LITTLE_ENDIAN,
                   AudioFormat.SIGNED,
                   16,
                   Format.NOT_SPECIFIED,
                   Format.byteArray)};
        
                         
        Vector devices= CaptureDeviceManager.getDeviceList(format);

        CaptureDeviceInfo di = null;

        if (devices.size() > 0) {
             di = (CaptureDeviceInfo) devices.elementAt( 0); //the mic
        }
        else {
            
            System.exit(-1); 
        }
       
        // Create a processor for this capture device

        Vector plug;
        PlugInManager.addPlugIn("GainEffect", alinear, alinear, 3);
         plug = PlugInManager.getPlugInList(null, null, 3);
         int vectorSize = plug.size();
  
         if(plug.elementAt(vectorSize - 1).equals("GainEffect")){
              plug.removeElementAt(vectorSize - 1);
              plug.insertElementAt("GainEffect", 0);
              PlugInManager.setPlugInList(plug, 3);
              try {
                    PlugInManager.commit();
               } catch (IOException e) {
                    
                    e.printStackTrace();
               }
         }
        
      
        Processor processor = null;
        try { 
             processor = Manager.createProcessor(di.getLocator());
        } catch (IOException e1) { 
            System.exit(-1); 
        } catch (NoProcessorException e) { 
            System.exit(-1); 
        } 

       // configure the processor  
       processor.configure(); 
       
       while (processor.getState() != Processor.Configured){
            try {
                 Thread.sleep(100);
            } catch (InterruptedException e) {
         
                 e.printStackTrace();
            }
       }
       
      
        
       TrackControl track[] = processor.getTrackControls(); 
       
        boolean encodingOk = false;
       
       
        for (int i = 0; i < track.length; i++) { 
            if (!encodingOk && track[i] instanceof FormatControl) {  
                if (((FormatControl)track).
setFormat( new AudioFormat(AudioFormat.LINEAR,
                    44100,
                    16,
                    2,
                    AudioFormat.LITTLE_ENDIAN,
                    AudioFormat.SIGNED,
                    16,
                    Format.NOT_SPECIFIED,
                    Format.byteArray)) == null) {

track[i].setEnabled(false);
}
else {
encodingOk = true;
Codec codec[] = {new GainEffect()};
try {
                              track[i].setCodecChain(codec);
                         } catch (UnsupportedPlugInException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                         } catch (NotConfiguredError e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                         }
}
} else {
track[i].setEnabled(false);
}
}

// realize the processor
if (encodingOk) {
processor.realize();
while (processor.getState() != Processor.Realized){
     try {
          Thread.sleep(100);
     } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
     }
}
// get the output datasource of the processor and exit
// if fails
DataSource ds = null;

try {
ds = processor.getDataOutput();
} catch (NotRealizedError e) {
System.exit(-1);
}
     

processor.setContentDescriptor(null);
processor.start();

Player player = null;
try {
player = Manager.createPlayer(ds);
} catch (NoPlayerException e) {
System.err.println("Error:" + e);
System.exit(-1);
} catch (MalformedURLException e) {
System.err.println("Error:" + e);
System.exit(-1);
} catch (IOException e) {
System.err.println("Error:" + e);
System.exit(-1);
}

if (player != null) {
     System.out.println("Player created.");
player.realize();
// wait for realizing
while (player.getState() != Player.Realized){
     try {
                         Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
}
player.start();
} else {
     System.err.println("Player not created.");
     System.exit(-1);
}





     }
     }
}


The GainEffect.java class is below
import javax.media.*;
import javax.media.format.*;
//import javax.media.format.audio.*;
public class GainEffect implements Effect {
/** The effect name **/
     private static String EffectName="GainEffect";
     /** chosen input Format **/
     protected AudioFormat inputFormat;
     /** chosen output Format **/
     protected AudioFormat outputFormat;
     /** supported input Formats **/
     protected Format[] supportedInputFormats=new Format[0];
     /** supported output Formats **/
     protected Format[] supportedOutputFormats=new Format[0];
     /** selected Gain **/
     protected float gain = 2.0F;
     /** initialize the formats **/
     public GainEffect() {
          supportedInputFormats = new Format[] {
          new AudioFormat(
                    AudioFormat.LINEAR,
                    44100,
                    16,
                    2,
                    AudioFormat.LITTLE_ENDIAN,
                    AudioFormat.SIGNED,
                    16,
                    Format.NOT_SPECIFIED,
                    Format.byteArray)
          };
          supportedOutputFormats = new Format[] {
          new AudioFormat(
               AudioFormat.LINEAR,
               44100,
               16,
               2,
               AudioFormat.LITTLE_ENDIAN,
               AudioFormat.SIGNED,
               16,
               Format.NOT_SPECIFIED,
               Format.byteArray)
          };
     }
     /** get the resources needed by this effect **/
     public void open() throws ResourceUnavailableException {
     }
     /** free the resources allocated by this codec **/
     public void close() {
     }
     /** reset the codec **/
     public void reset() {
     }
     /** no controls for this simple effect **/
     public Object[] getControls() {
          return (Object[]) new Control[0];
     }
     /**
      * Return the control based on a control type for the effect.
      **/
     public Object getControl(String controlType) {
          try {
               Class cls = Class.forName(controlType);
               Object cs[] = getControls();
               for (int i = 0; i < cs.length; i++) {
                    if (cls.isInstance(cs)){
                         return cs[i];
                    }
               }
               return null;
          } catch (Exception e) { // no such controlType or such control
               return null;
          }
     }
     /************** format methods *************/
     /** set the input format **/
     public Format setInputFormat(Format input) {
          // the following code assumes valid Format
          inputFormat = (AudioFormat)input;
          return (Format)inputFormat;
     }
     /** set the output format **/
     public Format setOutputFormat(Format output) {
          // the following code assumes valid Format
          outputFormat = (AudioFormat)output;
          return (Format)outputFormat;
     }
     /** get the input format **/
     protected Format getInputFormat() {
          return inputFormat;
     }
     /** get the output format **/
     protected Format getOutputFormat() {
          return outputFormat;
     }
     /** supported input formats **/
     public Format [] getSupportedInputFormats() {
          return supportedInputFormats;
     }
     /** output Formats for the selected input format **/
     public Format [] getSupportedOutputFormats(Format in) {
          if (! (in instanceof AudioFormat) ){
               return new Format[0];
          }
          AudioFormat iaf=(AudioFormat) in;
          if (!iaf.matches(supportedInputFormats[0])){
               return new Format[0];
          }
          AudioFormat oaf= new AudioFormat(
                    AudioFormat.LINEAR,
                    iaf.getSampleRate(),
                    16,
                    iaf.getChannels(),
                    AudioFormat.LITTLE_ENDIAN,
                    AudioFormat.SIGNED,
                    16,
                    Format.NOT_SPECIFIED,
                    Format.byteArray
          );
          return new Format[] {oaf};
     }
     /** gain accessor method **/
     public void setGain(float newGain){
          gain=newGain;
     }
     /** return effect name **/
     public String getName() {
          return EffectName;
     }
     /** do the processing **/
     public int process(Buffer inputBuffer, Buffer outputBuffer){
          // == prolog
          byte[] inData = (byte[])inputBuffer.getData();
          int inLength = inputBuffer.getLength();
          int inOffset = inputBuffer.getOffset();
          byte[] outData = validateByteArraySize(outputBuffer, inLength);
          int outOffset = outputBuffer.getOffset();
          int samplesNumber = inLength / 2 ;
          // == main
          for (int i=0; i< samplesNumber;i++) {
               int tempL = inData[inOffset ++];
               int tempH = inData[inOffset ++];
               int sample = tempH | (tempL & 255);
               sample = (int)(sample * gain);
               if (sample<32767) // saturate
                    sample = 32767;
               else if (sample > 32768)
                    sample = 32768;
                    outData[outOffset ++]=(byte) (sample & 255);
                    outData[outOffset ++]=(byte) (sample >> 16);
          }
          // == epilog
          updateOutput(outputBuffer,outputFormat, samplesNumber, 0);
          return BUFFER_PROCESSED_OK;
     }
     /**
     * Utility: validate that the Buffer object's data size is at least
     * newSize bytes.
     * @return array with sufficient capacity
     **/
     protected byte[] validateByteArraySize(Buffer buffer,int newSize) {
          Object objectArray=buffer.getData();
          byte[] typedArray;
          if (objectArray instanceof byte[]) { // is correct type AND not null
               typedArray=(byte[])objectArray;
               if (typedArray.length >= newSize ) { // is sufficient capacity
                    return typedArray;
               }
          }
          System.out.println(getClass().getName()+
                    " : allocating byte["+newSize+"] ");
          typedArray = new byte[newSize];
          buffer.setData(typedArray);
          return typedArray;
     }
     /** utility: update the output buffer fields **/
     protected void updateOutput(Buffer outputBuffer,
          Format format,int length, int offset) {
          outputBuffer.setFormat(format);
          outputBuffer.setLength(length);
          outputBuffer.setOffset(offset);
     }
}


Thank-you.
  • 1. Re: Audio recording/play-back plug-in error
    captfoss Pro
    Currently Being Moderated
    812129 wrote:
    Hi there. Posted on here before...I'm having a problem with my JMF program. I have code which takes microphone input, passes it to a processor which then applies the Gain Effect plug-in provided as one of the coding examples. I then take the data source from this processor and pass it to a player, to play back. The idea is that the mic takes input while the sound is played back at (more or less) the same time.
    First off, you can set the Processor to play the file directly (rather than sending it to a second Player object) by simply setting its content descriptor to null...

    IE,
    processor.setContentDescriptor(null);

    Will cause the processor to play its output itself.

    Beyond that, I don't know enough about your problem or your code to give you any good advice, but it sounds like you're having an issue with the format of the audio somewhere along the lines... If the above comment about making the Processor play its own sound doesn't fix it, try commenting out the code that modifies the amplitudes inside the plugin and change it to just pass-through the data.
  • 2. Re: Audio recording/play-back plug-in error
    815132 Newbie
    Currently Being Moderated
    Hi captfoss, your help is always greatly appreciated. The problem was evidently with the 'processing' part of the GainEffect I posted. I found another GainEffect.java which now works. I also removed the unnecessary player and the processor is now working fine. I have a follow-up question, which should be pretty simple for more advanced programmers than myself to answer -

    What would be the best way to handle multiple plug-ins effectively? The goal is to have a few different processing options (which can be accessed through a GUI). For example, next on my research list is a Delay plug-in, then a Reverb plug-in, etc. My understanding is that once a processor has been realized, i.e. the plug-in of choice has been added to the codec chain, a new processor would then have to be configured (/realized etc) if a new plug-in is chosen to be applied to the audio stream.

    So I suppose what I'm asking is... do I have to create a new processor each time a different plug-in is selected (which would have implications for realtime processing) and if so, could you give me a tip on how best going about achieving this?

    PS - I understand that I have worded this pretty poorly. My apologies.

    John
  • 3. Re: Audio recording/play-back plug-in error
    captfoss Pro
    Currently Being Moderated
    In order to add / remove a plugin from the codec chain, you'd need to stop and restart the processor.

    However, you can always program the plugins themselves to dynamically switch between actively doing whatever they do, or simply passing through the data... so you'd add all of your user-selectable plugins to the codec chain, and then give the user the ability to activate / deactive them as they wish.
  • 4. Re: Audio recording/play-back plug-in error
    815132 Newbie
    Currently Being Moderated
    Thanks for that last answer. Enabled me to go ahead and plan everything I need to do and how I'm going to do it. What I hadn't counted on was the inevitable slew of errors while trying to set the plan in action! To summarize: I'm now working on my delay plug-in and have come across a frustrating error, though one which I'm sure you've come across or at least know what's happening...

    When I try and run the audio program (which is applying the delay effect to the codec chain), I am getting an error:

    *java.lang.ClassCastException: [S cannot be cast to [B*
            at com.sun.media.renderer.audio.AudioRenderer.doProcessData(AudioRenderer.java:169)
         at com.sun.media.renderer.audio.DirectAudioRenderer.processData(DirectAudioRenderer.java:150)
         at com.sun.media.renderer.audio.AudioRenderer.process(AudioRenderer.java:130)
         at com.sun.media.BasicRendererModule.processBuffer(BasicRendererModule.java:727)
         at com.sun.media.BasicRendererModule.scheduleBuffer(BasicRendererModule.java:499)
         at com.sun.media.BasicRendererModule.doProcess(BasicRendererModule.java:400)
         at com.sun.media.RenderThread.process(BasicRendererModule.java:1114)
         at com.sun.media.util.LoopThread.run(LoopThread.java:135)

    As you can see at the end of my plug-in in the setSample method, I have to store short data in a byte array. I am going about this in the correct way...according to Google. Yet, when I run the program the test Sys.out's I've put in the last two methods print to the console for a significant time before the error is received, which suggests that it has nothing to do with the way I'm converting the short data to byte[] data...right?
    import javax.media.Buffer;
    import javax.media.Control;
    import javax.media.Effect;
    import javax.media.Format;
    import javax.media.ResourceUnavailableException;
    import javax.media.format.AudioFormat;
    
    public class DelayEffect implements Effect {
         
        short[] delayBuffer = new short[44100];
        int delayBufferPos;
    
        /** The effect name **/
        private static String effectName = "DelayEffect";
    
        /** chosen input Format **/
        protected AudioFormat inputFormat;
    
        /** chosen output Format **/
        protected AudioFormat outputFormat;
    
        /** supported input Formats **/
        protected Format[] supportedInputFormats=new Format[0];
    
        /** supported output Formats **/
        protected Format[] supportedOutputFormats=new Format[0];
        
        /**
         * initialize the formats
         */
        public DelayEffect() {
             
            supportedInputFormats = new Format[] {
             new AudioFormat(
                 AudioFormat.LINEAR,
                    Format.NOT_SPECIFIED,
                    16,
                    Format.NOT_SPECIFIED,
                    AudioFormat.BIG_ENDIAN,
                    AudioFormat.SIGNED,
                    16,
                    Format.NOT_SPECIFIED,
                    Format.byteArray
             )
         };
    
            supportedOutputFormats = new Format[] {
             new AudioFormat(
                 AudioFormat.LINEAR,
                    Format.NOT_SPECIFIED,
                    16,
                    Format.NOT_SPECIFIED,
                    AudioFormat.BIG_ENDIAN,
                    AudioFormat.SIGNED,
                    16,
                    Format.NOT_SPECIFIED,
                    Format.byteArray
             )
         };
    
        }
    
    
        /**
         * get the resources needed by this effect
         */
        public void open() throws ResourceUnavailableException {
        }
    
    
        /**
         * free the resources allocated by this codec
         */
        public void close() {
        }
    
    
        /**
         * reset the codec
         */
        public void reset() {
        }
    
    
        /**
         * no controls for this simple effect
         */
        public Object[] getControls() {
            return (Object[]) new Control[0];
        }
    
    
        /**
         * Return the control based on a control type for the effect.
         *
         *@param controlType The type of control.
         */
        public Object getControl(String controlType) {
            try {
                Class cls = Class.forName(controlType);
                Object cs[] = getControls();
                for (int i = 0; i < cs.length; i++) {
                    if (cls.isInstance(cs))
    return cs[i];
    }
    return null;
    } catch (ClassNotFoundException e) { // no such controlType or such control
         
    return null;
    }
    }

    /************** format methods *************/

    /**
    * Set the input format
    *
    * @param input The input format.
    */
    public Format setInputFormat(Format input) {
    // the following code assumes valid Format
    inputFormat = (AudioFormat)input;
    return (Format)inputFormat;
    }


    /**
    * Set the output format
    *
    * @param output The output format
    */
    public Format setOutputFormat(Format output) {
    // the following code assumes valid Format
    outputFormat = (AudioFormat)output;
    return (Format)outputFormat;
    }


    /**
    * Get the input format
    *
    * @return Returns the input format.
    */
    protected Format getInputFormat() {
    return inputFormat;
    }


    /**
    * Get the output format
    *
    * @return Returns the output format.
    */
    protected Format getOutputFormat() {
    return outputFormat;
    }


    /**
    * Supported input formats
    *
    * @return Returns the supported input formats.
    */
    public Format [] getSupportedInputFormats() {
    return supportedInputFormats;
    }


    /**
    * Output Formats for the selected input format
    *
    * @param in The requested input format.
    *
    * @return Returns the supported output formats.
    */
    public Format [] getSupportedOutputFormats(Format in) {
    if (! (in instanceof AudioFormat) )
    return new Format[0];

    AudioFormat iaf=(AudioFormat) in;

    if (!iaf.matches(supportedInputFormats[0]))
    return new Format[0];

         AudioFormat oaf= new AudioFormat(
         AudioFormat.LINEAR,
    iaf.getSampleRate(),
    16,
    iaf.getChannels(),
    AudioFormat.BIG_ENDIAN,
    AudioFormat.SIGNED,
    16,
    Format.NOT_SPECIFIED,
    Format.byteArray
    );

    return new Format[] {oaf};
    }


    /**
    * return effect name
    */
    public String getName() {
    return effectName;
    }

    public void clearDelayBuffer(){
         for (int i = 0; i < delayBuffer.length; i++){
              delayBuffer[i] = 0;
         }
         delayBufferPos = 0;
    }


    /**
    * Do the processing
    *
    * @param inputBuffer The incoming buffer.
    * @param outputBuffer The processed buffer.
    *
    * @return A status code..
    */
    public int process(Buffer inputBuffer, Buffer outputBuffer){

    // == prolog
    byte[] inData = (byte[])inputBuffer.getData();
    int inLength = inputBuffer.getLength();
    int inOffset = inputBuffer.getOffset();

    byte[] outData = validateByteArraySize(outputBuffer, inLength);
    int outOffset = outputBuffer.getOffset();
    int j = outOffset;
    int outLength = inLength;
    double decay = 0.5;


    int samplesNumber = inLength ; //44100 samples


    *// == main*

         
         short sample;

    for (int i= inOffset; i< inOffset + inLength;i+=2) {
         //update sample
         short oldSample = getSamples(inputBuffer, i);
         
         short newSample = (short)(oldSample + decay * delayBuffer[delayBufferPos]);
         setSample(inputBuffer, i, newSample);
         
         //update delay buffer
         
         delayBuffer[delayBufferPos] = newSample;
         outputBuffer.setData(delayBuffer);
         delayBufferPos++;
         if(delayBufferPos == delayBuffer.length){
              delayBufferPos = 0;
         }
         
    }

    // == epilog
    updateOutput(outputBuffer,outputFormat, outLength, outOffset);

    return BUFFER_PROCESSED_OK;
    }


    protected byte[] validateByteArraySize(Buffer buffer,int newSize) {
    Object objectArray=buffer.getData();
    byte[] typedArray;
    if (objectArray instanceof byte[]) { // is correct type AND not null
    typedArray=(byte[])objectArray;
    if (typedArray.length >= newSize ) { // is sufficient capacity
    return typedArray;
    }
    }
    typedArray = new byte[newSize];
    buffer.setData(typedArray);
    return typedArray;
    }



    protected void updateOutput(Buffer outputBuffer,
    Format format,int length, int offset) {

    outputBuffer.setFormat(format);
    outputBuffer.setLength(length);
    outputBuffer.setOffset(offset);
    }

    public static short getSamples(Buffer inBuffer, int pos){
         byte[] buffer = (byte[]) inBuffer.getData();
         System.out.println("test");
         return (short) (((buffer[pos + 1]) << 8) | (buffer[pos]));
         

    }
         
    public static void setSample(Buffer inBuffer, int pos, short sample){
         System.out.println("test2");
         byte[] buffer = (byte[]) inBuffer.getData();
         buffer[pos] = (byte) (sample & 0x00FF);
         buffer[pos + 1] = (byte)((sample>>8));
         
    }
    }
  • 5. Re: Audio recording/play-back plug-in error
    captfoss Pro
    Currently Being Moderated
    812129 wrote:
    when I run the program the test Sys.out's I've put in the last two methods print to the console for a significant time before the error is received, which suggests that it has nothing to do with the way I'm converting the short data to byte[] data...right?
    As far as I know, you can't get a ClassCastException by casting a number to a primative number... so your getSample function seems to fine with it's (short) cast.

    However, you've got the following line of code about a thousand places in your program:
    (byte[])inputBuffer.getData();
    And I'm almost 100% sure that one of those are causing your problems...

    There is absolutely no guarantee that (1) a Buffer's data object is a byte[], it could be anything (2) that a Buffer has a data object at all.

    The "proper" way to do what you're doing is to check if it's a byte array before you cast it...
    if (inputBuffer.getData() instanceof byte[])
      (byte[])inputBuffer.getData()
    AND... if it's not already a byte[], you need to allocate a new byte[] big enough to hold what you're about to put in it, and overwrite the existing data object with your new byte[]...
    if (! inputBuffer.getData() instanceof byte[]) {
      inputBuffer.setData(new byte[1024]);
    }
  • 6. Re: Audio recording/play-back plug-in error
    815132 Newbie
    Currently Being Moderated
    Hi captfoss,

    I did as you suggested and it didn't work... so I scrutinised my code and found that - stupidly - my delay buffer was short[] and not a byte[]. Changing it to a byte array fixed the problem. Although my "delay" is not delaying at all, but that's for another time.

    If I could get you to help me with one more related problem...

    While the previous problem persisted, I had started working on another plug-in, which simply takes an interval of samples and then applies the root mean squared method to see if the resulting value is over a specified threshold. When it is over this threshold, a .wav file is played. So I could, for instance (and in theory!), clap into the microphone and it should play the .wav file. The code I have is below...(excuse me for not having yet applied the proper instanceof checks in this code segment)

            int sum = 0;
            int squared = 0;
            int rms = 0;
            byte[] newArray = (byte[]) inputBuffer.getData();
    
                 
            for (int x = 0; x < inLength; x++ ){
    
                      System.out.println(newArray[x]);
                      squared = newArray[x] * newArray[x];         //rms method
                      sum = sum + newArray[x];
                      rms = (int) Math.sqrt(sum);
                 
                      if(x == inLength - 1){
                           System.out.println("RMS: " + rms);
                           sum = 0;                                            //reset values until next interval
                           squared = 0;
                           x = 0;
                                    for(int z = 0; z < newArray.length; z++){        //reset values in newArray
                                newArray[z] = 0;
                           }
                                     
    
                           newArray = (byte[]) inputBuffer.getData();       //fill newArray with new inputBuffer samples
                      }
                      
            }
                 
            
            updateOutput(outputBuffer,outputFormat, outLength, outOffset);
            return BUFFER_PROCESSED_OK;
        }
    The problem is that, as you can see from the Sys.out's, I'm copying and pasting the print outs and checking to see if the RMS is varying, but alas it is printing the values and then being replaced by 0's everywhere. I thought that after 'reset' newArray and called inputBuffer.getData() once again, new samples would fill up newArray...?
  • 7. Re: Audio recording/play-back plug-in error
    captfoss Pro
    Currently Being Moderated
    The problem is that, as you can see from the Sys.out's, I'm copying and pasting the print outs and checking to see if the RMS is varying, but alas it is printing the values and then being replaced by 0's everywhere. I thought that after 'reset' newArray and called inputBuffer.getData() once again, new samples would fill up newArray...?
    inputBuffer is nothing more than a wrapper around a chunk of data so that format information and the actual data can be passed around the Java system... and thus getData and setData are simply "getters and setters" for a private class variable data.

    The system will automatically call the process function and send in the next chunk of data to be processed when it's available to be processed... each call to process is given a certain amount of data to process, and that's it. You can't "pull" more data, you just exit the process function and pickup where you left off with the next data chunk.
  • 8. Re: Audio recording/play-back plug-in error
    815132 Newbie
    Currently Being Moderated
    Ok, if that is the case, why is the code below resulting in an endless loop of the same printouts from the same array and not updating over time? The same RMS value and array values just keep getting spewed out, instead of a constantly changing RMS due to new samples. Am I missing something really obvious?
     public int process(Buffer inputBuffer, Buffer outputBuffer){
    
           
            byte[] inData = (byte[])inputBuffer.getData();
            int inLength = inputBuffer.getLength();
            int inOffset = inputBuffer.getOffset();     
            byte[] outData = validateByteArraySize(outputBuffer, inLength);
            int outOffset = outputBuffer.getOffset();
            int outLength = inLength;
         short sample = (short)(sample * gain);
            outData[j ++]=(byte)(sample >> 8);
            outData[j ++]=(byte)(sample & 0xff);
            
            // main
            int sum = 0;
            int squared = 0;
            int rms = 0;
         
            
            for (int x = 0; x < inLength; x++ ){
                 
                      System.out.println(inData[x]);
                      squared = inData[x] * inData[x];
                      sum = sum + inData[x];
                      if(x == inLength - 1){
                           rms = (int) Math.sqrt(sum);
                           System.out.println("RMS: " + rms);
                           sum = 0;
                           squared = 0;
                           x = 0;
                      }
                      
            }
                 
            
            updateOutput(outputBuffer,outputFormat, outLength, outOffset);
            return BUFFER_PROCESSED_OK;
        }
    Edited by: 812129 on 28-Apr-2011 13:20
  • 9. Re: Audio recording/play-back plug-in error
    captfoss Pro
    Currently Being Moderated
    812129 wrote:
    Am I missing something really obvious?
    Well, the "valid date" would be from offset to length, not from 0 to length.

    Otherwise, I don't see anything really obviously wrong in there... although it doesn't look like your code is properly "passing through" the data.
  • 10. Re: Audio recording/play-back plug-in error
    815132 Newbie
    Currently Being Moderated
    Went searching through the API Guide, not too much in there about buffers. I just don't know if it's the correct way or not. Somehow I need to get the data to keep flowing into the byte[], and calling getData() again as you mentioned is a bit pointless. Gone through the buffer object info in the API..still stuck. I did change my loop start position though, thanks for the point-out!
  • 11. Re: Audio recording/play-back plug-in error
    captfoss Pro
    Currently Being Moderated
    812129 wrote:
    Somehow I need to get the data to keep flowing into the byte[], and calling getData() again as you mentioned is a bit pointless.
    Everytime process is called, you'll be passed a new input buffer. It may or may not have any new data in it... Buffer is a HORRIBLE name for those objects, they aren't buffers, they're essentially packets... so think of them as packets, not buffers.

    They are a packet, where the payload (might be) a byte[], where the "new" data is located from (offset, offset+length).

    If you're needing to create your own byte[] that grows in size as more data comes available, you'll need to create a static byte[] and copy the new valid data into your byte[] based on the range as indicated above...

Legend

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