# Simple sampler example

**URL:** <https://forum.juce.com/t/simple-sampler-example/34674>\
**Category:** Development\
**Created:** [August 6, 2019, 6:49am UTC](https://forum.juce.com/t/simple-sampler-example/34674 "2019-08-06T06:49:08Z")\
**Posts on this page:** 13\
**Page:** 2

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [August 8, 2019, 6:19pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/22 "2019-08-08T18:19:39Z")

</div>

When you implement your SynthesiserVoice, you override renderNextBlock(), which is where you would apply the gain. You have a pointer to the currently playing SynthesiserSound, where you would store the gain setting.  
You might have to use dynamic\_cast to down cast the sound to your actual sound in order to access the additional gain setting.

---

<div class="post-metadata">

**Author:** ![Trickster2](https://avatars.discourse-cdn.com/v4/letter/t/ee59a6/32.png) [@Trickster2](https://forum.juce.com/u/Trickster2)\
**Post date:** [August 21, 2019, 8:17am UTC](https://forum.juce.com/t/simple-sampler-example/34674/24 "2019-08-21T08:17:44Z")

</div>

I’ve implemented my SynthesiserVoice with renderNextBlock(). Now I can change volume, panning, etc for each note.  
But still can’t understand how can I change volume of individual sound. I understand, that it should be something like this  
`auto sound1 = dynamic_cast<const SynthesiserSound*> (sound);`  
but where should I use it and how can I change gain of this sound?

Just to remind. I have 4 different samples for each note. At this moment I use 18 notes. 4 samples for each (72 samples).

Thank you.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [August 21, 2019, 9:51am UTC](https://forum.juce.com/t/simple-sampler-example/34674/25 "2019-08-21T09:51:54Z")

</div>

Each voice has a renderNextBlock(), that you override to mix the generated sound to the output. Since it is mixing here, you need the information about the desired gain here, after mixing you have no longer access to the individual voice’s signal.

The sound the voice is playing bears the information of your desired gain (which is a method you added, hence the cast you quoted). It could work along these lines:

```auto
void SynthesiserVoice::renderNextBlock (AudioBuffer<float>& outputBuffer,
                                        int startSample, int numSamples)
{
    auto gain = 1.0f;
    if (auto* sound = dynamic_cast<const MySynthesiserSound*> (getCurrentlyPlayingSound().get()))
        gain = sound->getGain();

    // generate your signal and use gain as multiplier
    for (int c = 0; c < outputBuffer.getNumChannels(); ++c)
        outputBuffer.addFromWithRamp (..., lastGain, gain);

    lastGain = gain; // lastGain should be a member to have smooth gain changes
}

class MySynthesiserSound : public SynthesiserSound
{
public:
    // ...
    float getGain() const { return gain.load(); }
    void setGain (float g) { gain.store (g); }
private:
    // ...
    std::atomic<float> gain = 1.0f;
}

```

Hope that helps

EDIT: you might need to make gain atomic, I added that just in case it is set from a non-audio thread

EDIT 2: you might want to set lastGain in noteOn, otherwise you get unexpected gain ramps from the previous played sound

---

<div class="post-metadata">

**Author:** ![Trickster2](https://avatars.discourse-cdn.com/v4/letter/t/ee59a6/32.png) [@Trickster2](https://forum.juce.com/u/Trickster2)\
**Post date:** [August 21, 2019, 10:19am UTC](https://forum.juce.com/t/simple-sampler-example/34674/26 "2019-08-21T10:19:18Z")

</div>

> [@daniel](#):
>
> 2: you might want to set lastGain in noteOn, otherwise you get unexpected gain ramps from the previous played sound

Thank you! Will try.

---

<div class="post-metadata">

**Author:** ![Trickster2](https://avatars.discourse-cdn.com/v4/letter/t/ee59a6/32.png) [@Trickster2](https://forum.juce.com/u/Trickster2)\
**Post date:** [August 21, 2019, 7:20pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/27 "2019-08-21T19:20:43Z")

</div>

> [@daniel](#):
>
> outputBuffer.addFromWithRamp (…, lastGain, gain);

What is a const Type\* source in this method?

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [August 21, 2019, 7:24pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/28 "2019-08-21T19:24:08Z")

</div>

AudioBuffer is a template, and `Type` is the type of the samples, i.e. either `float` or `double`.

`AudioSampleBuffer` is actually `AudioBuffer<float>`. I.e. in your case `Type*` is `float*`, and you get it via `buffer.getReadPointer (channel)`.

---

<div class="post-metadata">

**Author:** ![Trickster2](https://avatars.discourse-cdn.com/v4/letter/t/ee59a6/32.png) [@Trickster2](https://forum.juce.com/u/Trickster2)\
**Post date:** [August 21, 2019, 9:42pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/29 "2019-08-21T21:42:20Z")

</div>

If I use my own MySynthesiserSound class, what is a solution to set samples?  
Previously I made something like this:

> synth.addSound(new SamplerSound(“name1”, \*reader1, notes, 30, 0, 10, 10.0));  
> synth.addSound(new SamplerSound(“name2”, \*reader2, notes, 30, 0, 10, 10.0));  
> synth.addSound(new SamplerSound(“name3”, \*reader3, notes, 30, 0, 10, 10.0));  
> synth.addSound(new SamplerSound(“name4”, \*reader4, notes, 30, 0, 10, 10.0));

But it’s not an option now, right?

---

<div class="post-metadata">

**Author:** ![xenakios](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/xenakios/32/4047_2.png) [@xenakios](https://forum.juce.com/u/xenakios)\
**Post date:** [August 21, 2019, 9:53pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/30 "2019-08-21T21:53:18Z")

</div>

Assuming the constructor for your sound class is the same as SamplerSound has :

> [@Trickster2](#):
>
> synth.addSound(new MySynthesiserSound(“name1”, \*reader1, notes, 30, 0, 10, 10.0));

Of course you have to implement all the stuff Juce’s SamplerSound does in your own sound class besides your custom things. If I recall right, it’s not necessarily going to be useful to inherit from SamplerSound, you may need to inherit SynthesiserSound and implement all the functionality from scratch. If the inheritance from SamplerSound doesn’t work out, you could copy paste the code from Juce’s SamplerSound, I guess…

---

<div class="post-metadata">

**Author:** ![xenakios](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/xenakios/32/4047_2.png) [@xenakios](https://forum.juce.com/u/xenakios)\
**Post date:** [August 22, 2019, 9:39am UTC](https://forum.juce.com/t/simple-sampler-example/34674/31 "2019-08-22T09:39:34Z")

</div>

Looks like the Juce SamplerSound can be inherited from and you can pretty easily add the desired per-sound gain property :

```auto
class MySamplerSound : public SamplerSound
{
public:
	MySamplerSound(const String& name,
		AudioFormatReader& source,
		const BigInteger& midiNotes,
		int midiNoteForNormalPitch,
		double attackTimeSecs,
		double releaseTimeSecs,
		double maxSampleLengthSeconds, float initialGain) :
		SamplerSound(name, source, midiNotes, midiNoteForNormalPitch, attackTimeSecs, releaseTimeSecs, maxSampleLengthSeconds),
		soundGain(initialGain)
	{
	}
	float getGain() const { return soundGain; }
	void setGain(float g) { soundGain = g; }
private:
	float soundGain = 1.0f;
};
```

The soundGain member variable isn’t atomic or protected with a mutex here. It probably should be, though, if it is going to be changed during audio playback.

---

<div class="post-metadata">

**Author:** ![Trickster2](https://avatars.discourse-cdn.com/v4/letter/t/ee59a6/32.png) [@Trickster2](https://forum.juce.com/u/Trickster2)\
**Post date:** [August 22, 2019, 12:17pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/32 "2019-08-22T12:17:44Z")

</div>

Yes. It works like this. I’ve already done it. Thank you.

Maybe you can give me an advice or example what is the good way to implement renderNextBlock  
now it’s like an endless loop with the code:

```
void renderNextBlock(AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
{
	if (auto* playingSound = static_cast<SynthSound*> (getCurrentlyPlayingSound().get()))
	{

		auto& data = *playingSound->data;

		for (int c = 0; c < data.getNumChannels(); ++c) {
			outputBuffer.addFromWithRamp(c, startSample, data.getReadPointer(c), numSamples, lastGain, gain);
		}

```

`}`

I believe it should be something with numSamples?

---

<div class="post-metadata">

**Author:** ![xenakios](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/xenakios/32/4047_2.png) [@xenakios](https://forum.juce.com/u/xenakios)\
**Post date:** [August 22, 2019, 12:28pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/33 "2019-08-22T12:28:27Z")

</div>

You need to advance the read position into your source sample audio buffer at each renderNextBlock call. `data.getReadPointer(c)` just gets a pointer to the beginning of the source sample data at each render call.

Add a position variable as a member of your synth voice class and increment it in renderNextBlock as needed. (In your particular code, I guess by numSamples). You need to be very careful you don’t attempt reading past the end of the source sample buffer, it will lead to a crash or worse. (Note that addFromWithRamp doesn’t take care of that for you.)

---

<div class="post-metadata">

**Author:** ![Trickster2](https://avatars.discourse-cdn.com/v4/letter/t/ee59a6/32.png) [@Trickster2](https://forum.juce.com/u/Trickster2)\
**Post date:** [August 27, 2019, 7:07pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/34 "2019-08-27T19:07:57Z")

</div>

Thank you. Now it works.

But have another question:)

Each note has a mix of the four samples, but it could be different velocity with another four samples.  
What is the best way to load all samples for all velocities and then select it during the playback?

My idea is to create SynthesiserSounds for each velocity range and then select required in renderNextBlock. Is it a good option?

---

<div class="post-metadata">

**Author:** ![dplakon](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dplakon/32/7696_2.png) [@dplakon](https://forum.juce.com/u/dplakon)\
**Post date:** [December 28, 2019, 9:27pm UTC](https://forum.juce.com/t/simple-sampler-example/34674/36 "2019-12-28T21:27:18Z")

</div>

Would you be willing to share your source? Am working on a similar problem.

[Previous page](https://forum.juce.com/t/simple-sampler-example/34674.md?page=1)
