# Can’t Write/Restore Integer plugin parameter

**URL:** <https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414>\
**Category:** Audio Plugins\
**Created:** [September 25, 2019, 7:51pm UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414 "2019-09-25T19:51:59Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 25, 2019, 7:51pm UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414/1 "2019-09-25T19:51:59Z")

</div>

I am trying to add an Integer Transpose parameter to the ArpeggiatorPluginDemo.

The code works in the AudioPluginHost and the values are indeed transposed. But when I write and restore a “preset”, the Transpose value does not restore to the correct value. What am I missing here?

Arpeggiator constructor:

```
{
    addParameter (speed = new AudioParameterFloat ("speed", "Arpeggiator Speed", 0.0, 1.0, 0.5));
    addParameter (transpose = new AudioParameterInt ("transpose", "Arpeggiator Transpose", -12, 12, 0));
}

```

Saving/Restoring:

```
    void getStateInformation (MemoryBlock& destData) override
    {
        MemoryOutputStream (destData, true).writeFloat (*speed);
        MemoryOutputStream (destData, true).writeInt (*transpose);
    }

    void setStateInformation (const void* data, int sizeInBytes) override
    {
        speed->setValueNotifyingHost (MemoryInputStream (data, static_cast<size_t> (sizeInBytes), false).readFloat());
        transpose->setValueNotifyingHost (MemoryInputStream (data, static_cast<size_t> (sizeInBytes), false).readInt());
    }

private:
    //==============================================================================
    AudioParameterFloat* speed;
    AudioParameterInt* transpose;
```

---

<div class="post-metadata">

**Author:** ![cpr2323](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/cpr2323/32/18682_2.png) [@cpr2323](https://forum.juce.com/u/cpr2323)\
**Post date:** [September 25, 2019, 8:11pm UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414/2 "2019-09-25T20:11:04Z")

</div>

I believe you are using `MemoryInputStream` incorrectly. I didn’t test this, but I think you want something like:

```auto
void setStateInformation (const void* data, int sizeInBytes) override
{
    MemoryInputStream mis (data, static_cast<size_t> (sizeInBytes), false);
    speed->setValueNotifyingHost (mis.readFloat());
    transpose->setValueNotifyingHost (mis.readInt());
}

```

And you can probably do something similar with the `MemoryOutputStream` in `getStateInformation`. It might be working how you have it, but it will be _ **more correct** _ if you instantiate a `MemoryOuputStream` object that you then operate on for each of the pieces of data you write to it.

---

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 25, 2019, 10:13pm UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414/3 "2019-09-25T22:13:30Z")

</div>

Thanks - that was my erroneous assumption on how it should work based on not having an example of multiple parameters.

I have searched and I can only find one example in class AUv3SynthProcessor .h:

```
AUv3SynthProcessor : public AudioProcessor
{
public:
    AUv3SynthProcessor ()
        : AudioProcessor (BusesProperties().withOutput ("Output", AudioChannelSet::stereo(), true)),
          currentRecording (1, 1), currentProgram (0)
    {
        // initialize parameters
        addParameter (isRecordingParam = new AudioParameterBool ("isRecording", "Is Recording", false));
        addParameter (roomSizeParam = new AudioParameterFloat ("roomSize", "Room Size", 0.0f, 1.0f, 0.5f));
	
	[…]

//==============================================================================
void getStateInformation (MemoryBlock& destData) override
{
    MemoryOutputStream stream (destData, true);

    stream.writeFloat (*isRecordingParam);
    stream.writeFloat (*roomSizeParam);
}

void setStateInformation (const void* data, int sizeInBytes) override
{
    MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);

    isRecordingParam->setValueNotifyingHost (stream.readFloat());
    roomSizeParam->setValueNotifyingHost (stream.readFloat());

}
private:
[…]

AudioParameterBool* isRecordingParam;
AudioParameterFloat* roomSizeParam;

```

What this shows is that, although two parameters are declared and added as a Bool and a Float, they are both written and read as Floats. Is that correct?

Anyway, I tried it both ways in my plugin and it still doesn’t work:

Reading/writing as different types:

```
[…]
{
    addParameter (speed = new AudioParameterFloat ("speed", "Arpeggiator Speed", 0.0, 1.0, 0.5));
    addParameter (transpose = new AudioParameterInt ("transpose", "Arpeggiator Transpose", -12, 12, 0));
}
[…]
//==============================================================================
void getStateInformation (MemoryBlock& destData) override
{
    MemoryOutputStream stream (destData, true);
    
    stream.writeFloat (*speed);
    stream.writeInt (*transpose);
}

void setStateInformation (const void* data, int sizeInBytes) override
{
    MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);

    speed->setValueNotifyingHost (stream.readFloat());
    transpose->setValueNotifyingHost (stream.readInt());
}

private:
//==============================================================================
AudioParameterFloat* speed;
AudioParameterInt* transpose;

```

Reading/Writing as Floats:

```
[…]
{
    addParameter (speed = new AudioParameterFloat ("speed", "Arpeggiator Speed", 0.0, 1.0, 0.5));
    addParameter (transpose = new AudioParameterInt ("transpose", "Arpeggiator Transpose", -12, 12, 0));
}
[…]
//==============================================================================
void getStateInformation (MemoryBlock& destData) override
{
    MemoryOutputStream stream (destData, true);
    
    stream.writeFloat (*speed);
    stream.writeFloat (*transpose);
}

void setStateInformation (const void* data, int sizeInBytes) override
{
    MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);

    speed->setValueNotifyingHost (stream.readFloat());
    transpose->setValueNotifyingHost (stream.readFloat());
}

private:
//==============================================================================
AudioParameterFloat* speed;
AudioParameterInt* transpose;

```

Neither of these work correctly. When saving and opening a preset in the AudioPluginHost, The speed value is restored correctly, the transpose value is not.

I understand there may be better ways of handling multiple parameters such as XML or ValueTree, but I’m proceeding step by step with the tutorials and would like to understand this, first. Thanks!

---

<div class="post-metadata">

**Author:** ![cpr2323](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/cpr2323/32/18682_2.png) [@cpr2323](https://forum.juce.com/u/cpr2323)\
**Post date:** [September 25, 2019, 10:31pm UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414/4 "2019-09-25T22:31:56Z")

</div>

I haven’t done plugin work (ie. haven’t worked with the `AudioParameterXX` functions) in a while, so I don’t know what the issue might be. But, the code doesn’t have issues with the `MemoryStream`s any more. Hopefully someone with more plugin knowledge will step in to help now. 🙂

---

<div class="post-metadata">

**Author:** ![getdunne](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/getdunne/32/2712_2.png) [@getdunne](https://forum.juce.com/u/getdunne)\
**Post date:** [September 26, 2019, 1:21am UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414/5 "2019-09-26T01:21:43Z")

</div>

Welcome to the JUCE learning curve.

The demo examples tend to be written far more tightly than they probably ought to be, as teaching examples; hence the first mistake you make by invoking the `MemoryOutputStream` constructor twice.

The bigger issue is that the JUCE documentation, though generally quite good, is often missing _really important little nuggets_, like the fact that `AudioProcessorParameter::setValueNotifyingHost()` (which `AudioProcessorInt` inherits, and does _not override in an integer-specific way_, as one might expect) takes a `float` parameter which is _normalized_ to the range [0.0f, 1.0], and you can invoke another inherited function, `RangedAudioParameter::convertTo0to1()` to do the required conversion.

The authors of the Arpeggiator demo were able to skirt all of that complexity by using exactly one `float` parameter, which, because it is already in the magic range [0.0f, 1.0f], does not need to be normalized/denormalized.

The resulting (working) code is:

```auto
void Arpeggiator::getStateInformation (MemoryBlock& destData)
{
    MemoryOutputStream stream(destData, false);
    stream.writeFloat(*speed);
    stream.writeInt(*transpose);
}

void Arpeggiator::setStateInformation (const void* data, int sizeInBytes)
{
    MemoryInputStream stream(data, static_cast<size_t> (sizeInBytes), false);

    float sp = stream.readFloat();
    int tr = stream.readInt();

    float sp01 = speed->convertTo0to1(sp);
    float tr01 = transpose->convertTo0to1(float(tr));

    speed->setValueNotifyingHost(sp01);
    transpose->setValueNotifyingHost(tr01);
}

```

As far as I know, none of this is actually written down anywhere. I had to figure it all out by trial and error.

---

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 26, 2019, 3:00am UTC](https://forum.juce.com/t/can-t-write-restore-integer-plugin-parameter/35414/6 "2019-09-26T03:00:01Z")

</div>

Thanks! That works a treat. Would not have figured that out at this point. 🙂
