Trouble updating parameters between two classes


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Page 1 of 2 12 LastLast
Results 1 to 15 of 19

Thread: Trouble updating parameters between two classes

  1. #1
    Join Date
    Apr 2004
    Posts
    11

    Question Trouble updating parameters between two classes

    hey guys, great forum - very useful.

    When using more than one class, i'm having troubles passing variables between them (ie updating paramets when they change). In a simple example (with only 1 variable) there are two classes - Fader and FaderEffect (in seperate files). the faderEffect class has a constructor in it which creates a new faderEffect

    public FaderEffect(float volume){
    volumeLevel = volume;
    }

    In the fader class, i have code which creates a new object:

    FaderEffect fader = null; // setting it up

    if (fader==null){
    fader = new FaderEffect(volume);
    }

    Which is fine. In the fader class i also have code which automatically updates the volume parameter:

    public void parameterUpdate(String paramname, Object value) {
    if (paramname.equals("volume"))
    volume = new Float((String) value).floatValue();
    }

    But the problem is that the volumeLevel variable in the faderEffect class doesn't get updated because it only gets updated when you create the new object... so how can i get the varaibles to update automatically? At the moment i have to re-create a new 'Fader' each time...

    I hope someone can help, as this is the last piece of the puzzle!

    Thanks guys

  2. #2
    Join Date
    Dec 2002
    Posts
    83
    What you are looking to do is update the volumeLevel variable within your FaderEffect class, which itself is a variable of Fader.

    Put "getter and setter" methods in your FaderEffect class. The term "getters and setters" implies the method names match the variable that they get or set. So in your case, you want to be able to get and set the volumeLevel variable, so add two methods, "getVolumeLevel()" and "setVolume(float aVolumeLevel)" to FaderEffect. Your new FaderEffect class can be:
    Code:
    class FaderEffect {
    
    	private float volumeLevel;
    
    	public FaderEffect(float volume){
    		// I always call the set method, now that you have it
    		setVolumeLevel(volume);
    	}
    
    	public float getVolumeLevel() {
    		return volumeLevel;
    	}
    
    	public void setVolumeLevel(float aVolumeLevel) {
    		volumeLevel = aVolumeLevel;
    	}
    
    }
    Now your FaderEffect class can take care of its own variable like it should. When you want to change the value of the volumeLevel, just pass in a new one to the setVolumeLevel method.
    Code:
    FaderEffect fader = null; // setting it up
    
    if (fader==null){
    	fader = new FaderEffect(volume);
    }
    ...
    
    public void parameterUpdate(String paramname, Object value) {
    if (paramname.equals("volume"))
    	// this sets the volumeLevel of the FaderEffect instance, fader.
    	fader.setVolumeLevel(new Float((String) value).floatValue());
    }
    Likewise, when you want to get the volumeLevel value to use within Fader, you just use "fader.getVolumeLevel()" which returns you the float.

    Hope that helps and makes sense. Using getters and setters is a good thing to get used to.
    -- Steven

  3. #3
    Join Date
    Apr 2004
    Posts
    11
    many thanks, you're a lifesaver!

  4. #4
    Join Date
    Apr 2004
    Posts
    11
    Oh, dear, i've run into a bit of a more complicated situation!!! Bit tricky to explain!

    I have a class called SingleDelayEffect, which has a constructor:
    Code:
    public SingleDelayEffect(int forwardMemSize, int feedback, float delayInMs, 
    boolean chunked, double sampleRate)
        {
            super(forwardMemSize);
            setFeedback(feedback);
            setDelayOffset(delayOffset);
            setChunked(chunked);
            samplingFrequency = sampleRate;
    	}
    This gets the values from a class called SingleDelay. However SingleDelayEffect extends a class called AudioEffect. You can see here that i have used super(value) to add the value of 'fowardMemSize' to the contructor of AudioEffect. This is fine, but what if the forwardMemSize changes? Ordinarily (for a variable like 'feedback')i can juse ues a method like:
    Code:
    public void setFeedback(int feed){
    			feedbackFactor = (int)(feed / 100);
    	}
    to get the value of feedback from the SingleDelay class if this value changes. But because the value of forwardMemSize is calculated in SingleDelay, and passed over, it won't change. In the SingleDelay class, i'm making a new object each time:
    Code:
        SingleDelayEffect single = null;
    
    if (single==null){
               	single = new SingleDelayEffect(delayOffset, feedback, delayInMs, chunked, sampleRate);
            }
    I know the super(); call has to be the first line of the constructor so what do i do it this value varies

    I know i made a pigs ear of explaing this so if any more info is needed i can reply straight away

    Thank you!

  5. #5
    Join Date
    Dec 2002
    Posts
    83
    I think I followed you. My response might be confusing too though. Your issue is...within SingleDelay, you might need to set some of the values of your SingleDelayEffect instance, single. So while you can call "single.setFeedback(feedback)", you don't have a "setForwardMemSize(forwardMemSize)" method in SingleDelayEffect to call.

    That's fine, and is to be expected. Where I would expect to see the "setForwardMemSize" method is in the AudioEffect class. Each Class should take care of its own variables. And you know AudioEffect is what holds the forwardMemSize variable (or whatever it calls it) since it sets it in the constructor you activate with "super(forwardMemSize)".

    I'm guessing AudioEffect is a class you wrote? If so, just go ahead and add the forwardMemSize getter and setter methods to the AudioEffect class. Because your SingleDelayEffect extends AudioEffect, those methods will be available on your "single" variable.

    To sum up, if you add a "setForwardMemSize(forwardMemSize)" to AudioEffect, you can use "single.setForwardMemSize(forwardMemSize)". This is possible because of the beauty of Inheritance.

    If AudioEffect is something you didn't code, it probably already has a getter and setter defined. At least it should. Let me know if it doesn't.

    Side note, I'm assuming you just didn't include it here, but if your SingleDelayEffect class really does extend AudioEffect, you need the "extends AudioEffect" part:
    Code:
    public SingleDelayEffect(int forwardMemSize, int feedback, float delayInMs, 
    			boolean chunked, double sampleRate) extends AudioEffect
    {
    Let me know if I'm way off on what you were asking.
    -- Steven

  6. #6
    Join Date
    Apr 2004
    Posts
    11
    hi mate - thanks so much for the reply!

    it's kind of the other way around. The varaibles are set/changed in SingleDelay. SingleDelayEffect needs to know when the variables change as it perferms a process on the data with them. SingleDelayEffect extends AudioEffect (Audio effect is a class which deals with chunked data - this requires knowledge of forwardMemSize - which is the no. of samples to delay an audio signal by) and it does this after the class declaration.

    Now th problem is that in SingleDelay there is a GUI component that allows the user to change the delay time In milliseconds. I've dealt with this using:
    Code:
    public void setDelayOffset(float offset){
    		delaySamples = ((int)(offset * (float)samplingFrequency / (float)1000));
    	}
    which works fine. But going back to the main issue, and this is the main point:

    *I need forwardMemSize to change (and be equal to) delaySamples, so whenever delayInMs changes on the gui, forwardMemSize is updated*

    But i have to deal with them seperately because of the way java works (ie my crap understanding of it ). Isn't this correct? So my constructor is:
    Code:
    public AllPassEffect(int forwardMemSize, int feedback, boolean chunked, float delayInMs, double sampleRate)
        {
            super(forwardMemSize);
            samplingFrequency = sampleRate;
            setFeedback(feedback);
            setDelayOffset(delayInMs);
            setChunked(chunked);
    	}
    And it's important to note that forwardMemSize is a value calculated in SingleDelay which is ALREADY EQUAL to the initial delaySamples value. But what it means is that it won't ever be updated - although delaySamples will be!!!

    I have two methods - one for dealing with chunks (array is streamed), and one which processes the entire array before passing it back to the SingleDelay class. The chunked one won't work if you change the delayInMs value, but the other works perfectly (because that one doesn't use audioeffect16bit!

    Sorry for the essay, but that is the exact problem

  7. #7
    Join Date
    Apr 2004
    Posts
    11
    AudioEffect does indeed deal with it's own variables. Let me throw some code at you:

    Code:
    public AudioEffect16Bit(int forwardMemSize) {
            forwardMemory = new short[forwardMemSize];
        }
    
        public void initialiseForward(short val) {
            for (int i = 0; i < forwardMemory.length; ++i){
                forwardMemory[i] = val;
    		}
        }
    
        /**
         * Initializes the forward values to the values specified. The array
         * given must be the same size as the size of the previous memory array
         * otherwise the memory will not be initialized and an exception will be thrown
         */
        public void initialiseForward(short[] vals) throws IncompatibleSizeException {
            if (vals.length != forwardMemory.length)
                throw new IncompatibleSizeException("Given vals array incompatible size with forwardMemory array");
    
            for (int i = 0; i < forwardMemory.length; ++i){
                forwardMemory[i] = vals[i];
    	    }
        }
    initialiseForward is set every time a chunk is processed in the process(short[] input) method in SingleDelay using: super.initialiseForward(forwardBuffer); where forwardBuffer is the length of delaySamples!!!

    So you can see that these two need to match! If using chunks i pressplay with a certain delay size, it seems ok, then if i change it i get exceptions thrown. But i cant' seem to think of a way of getting the super(forwardMemSize) to change with delaySamples.....

    Sorry for posting so much - it's hard to explain the whole thing!

    Thank you again

  8. #8
    Join Date
    Dec 2002
    Posts
    83
    NM, going to read your next post first.
    -- Steven

  9. #9
    Join Date
    Apr 2004
    Posts
    11
    thanks. any more questions, ask away, i'll answer immediately!

    i'm stumped (and a little fed up )

  10. #10
    Join Date
    Dec 2002
    Posts
    83
    So what forwardMemSize really does is change the size allocation for the forwardMemory array. The constructor takes forwardMemSize and uses that to set the size of forwardMemory, which gets done only once ever.

    You want to be able to resize forwardMemory I think? That's pretty easy IF you can whipe out the existing forwardMemory data when you do that. If you have to keep the data, it's more of a trick. I'm going to go with assuming you can whipe out (completely redefine) forwardMemory when it changes length.

    So we really want a method in AudioEffect16Bit that redefines forwardMemory to a length as defined by the passed in parameter.
    Code:
    public resetForwardMemory(int forwardMemSize) {
    	forwardMemory = new short[forwardMemSize];
    }
    Then, for readability and to only do something in once place, I'd call that method from the Constructor:
    Code:
    public AudioEffect16Bit(int forwardMemSize) {
    	resetForwardMemory(forwardMemSize);
    }
    Now the Constructor (aka super(value)) and the new method both do the same thing. And you can call the resetForwardMemory(int forwardMemSize) method on any instance of AudioEffect16Bit (and it's children).

    WARNING: I need to repeat, calling resetForwardMemory(int forwardMemSize) will wipe out all data in your forwardMemory array. If that's OK for the way your app works, then great. If not, I guess we keep trying.
    -- Steven

  11. #11
    Join Date
    Apr 2004
    Posts
    11
    thanks for the replying so quickly

    i think it is ok to get rid of forwardMemSize - i'm not storing it anywhere - it just sets the size of an array.

    What's happening at the moment is this. I can set forwardMemSiez to be wahtever, and then while it's playing (in chunks of data, kinda like streaming) it's calling initialiseForward with the new size each time. This works fine and i can even change the delaySamples variable and hear an audible difference (ie it's working).

    The problem arises when you try to play it again, and the size you have set last isn't the one which is stored in forwardMemSize.... so i think the answer to your question is YES

    If i add this method, what else do i have to change... you've mentioned the modifications with audioeffect16bit but what about the constructor of the simple delay class Also, do you mean make an overloaded constructor in audioeffect16bit?

    Cheers

    Eddie

  12. #12
    Join Date
    Dec 2002
    Posts
    83
    I think you want to call the resetForwardMemory(int forwardMemSize) method at the same time as you set the delaySample variable.

    I could be way off on this solution by the way.
    -- Steven

  13. #13
    Join Date
    Apr 2004
    Posts
    11
    ah i see what you're trying to do - sneaky

    I'll try it right now and let you know what happens


  14. #14
    Join Date
    Apr 2004
    Posts
    11
    Hi - i think i implemented what you wrote correctly, i did:
    Code:
    public void setDelayOffset(float offset){
    		delaySamples = ((int)(offset * (float)samplingFrequency / (float)1000));
    		resetForwardMemory(delaySamples);
    		System.out.println("delaySamples = " + delaySamples);
    	}
    and changed the constructor in audioeffect16bit to what you said, and also added the reset method you gave...

    But this exception is still thrown the second time you try to run it (which is when a new object is created and a new forwardMemSize is passed i guess?):

    IncompatibleSizeException: Incompatible Size Exception :
    Given vals array incompatible size with forwardMemory array

    Whaddya think?

  15. #15
    Join Date
    Dec 2002
    Posts
    83
    I guess I should have asked earlier what the exception you were getting was. At least we know exactly where the exception is being generated.

    Where do you call initialiseForward(short[] vals)? More specifically where is vals set? Looks like the length of vals is what isn't matching up.

    That other stuff we just did might not be necessary.
    -- Steven

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center