Closed og0 closed 9 years ago
Hi
If I understand you correctly you want to make a granular synth. There's already one of these in the ofxMaxim branch, and an old example of how to use it here (requires openframeworks)
On Tuesday, July 15, 2014, og0 notifications@github.com wrote:
Hi!
First, thanks and congratulations with Maximilian, it works great and is well optimized.
I use it on OpenFrameworks for iOS. I don't manage to do a simple stuff: a very basic granular synthesis. I would like to play a orchestral wav file with position (in the wav file) as a parameter. I explain, i would like to have 16 grain players, and every xx milliseconds (xx = random numbers) one of these players plays a very short part of the file (at the right play head position), with no loop. Because there are 16 players and they play very quickly small grains, it gives you the impression that the play head stays immobile. I made a Max/MSP patch and it works well, but i cannot make it in OpenFrameworks / Maximilian.
Hope my explanation is obvious. Thanks for your help!
Cheers, Olivier
— Reply to this email directly or view it on GitHub https://github.com/micknoise/Maximilian/issues/25.
Sent from my mobile
Hi,
Thank you for you quick answer. Yes i started with this example. My problem is that (if i'm right) it only plays one grain at a time. I would like to play each grain once (and not in loop) and trigger them with random offset and a random length.
BTW i tried to play several grains (with a maxiTimestretch array) in loop, like in your example, but i think i play them all in the same time, although i give to each player a random grain length. So it doesn't give the feeling that the play head stays immobile because we hear the loops (they're not mixed together) so it's still very percussive.
Here is the audioRequest function
for (i = 0; i < bufferSize; i++) { mix = 0.0f;
for (j = 0; j < NBGRAINS; j++)
{
//_wave[j] = _ts[j]->play2(_pos, _grainLength[j], 1);
_wave[j] = _ts[j]->play(1.0f, 0.05, 1, _pos);
if (_fft[j].process(_wave[j]))
{
_oct[j].calculate(_fft[j].magnitudes);
}
if (j == 1)
{
_wave[j] = _wave[j] * 0.05;
}
mix += _wave[j];
}
// Mix
_channel.stereo(mix, _outputs, 0.5);
output[i*nChannels ] = _outputs[0];
output[i*nChannels + 1] = _outputs[1];
}
Maybe i should use only the _sample->play() function ? Thank you for your advice.
The _pos variable is a parameter updated at each update() function, this is the most important because it can stay at the same position. The sample is a violin long note so if _pos stays at 0.2 for example, my goal is to hear only the same violin note playing endless, but without hearing a loop or a percussive grain. It stays always at speed = 1. I think this is a trigger problem (in my code all grain triggers at the same moment, don't they ?), but i'm not familiar with audio in OpenFrameworks... Thank you!
OK i managed to do what i wanted with maxiGrain class. Thank you.
But i have another problem :) I have a huge memory leak. Here's my code :
for (i = 0; i < bufferSize; i++) { mix = 0.0f;
if (_active)
{
for (j = 0; j < NBGRAINS; j++)
{
if (_grain[j] != NULL)
{
if (_grain[j]->finished)
{
delete(_grain[j]);
_grain[j] = new maxiGrain<grainPlayerWin>(&_sample,
_pos + ofRandom(0.05),
ofRandom(FOURNIER_MINGRAINLENGTH, FOURNIER_MAXGRAINLENGTH),
1,
_windowCache);
}
else if (!_grain[j]->finished)
{
_wave[j] = _grain[j]->play();
}
}
mix += _wave[j];
}
}
// Mix
_channel.stereo(mix, _outputs, 0.5);
output[i*nChannels ] = _outputs[0] * _volume;
output[i*nChannels + 1] = _outputs[1] * _volume;
The memory leaks seem to be linked with the _windowCache (of type maxiGrainWindowCache
What do i do wrong ? Can you help please ? Thank you.
Hi,
I'm not sure where your memory leak is coming from, but instead you could try to override or make a modified copy of the maxiGrainPlayer class to get the behaviour you need - we know this runs already without memory leaks.
Cheers,
Chris
On 17 Jul 2014, at 21:40, og0 notifications@github.com<mailto:notifications@github.com> wrote:
But i have another problem :) I have a huge memory leak. Here's my code :
for (i = 0; i < bufferSize; i++) { mix = 0.0f;
if (_active)
{
for (j = 0; j < NBGRAINS; j++)
{
if (_grain[j] != NULL)
{
if (_grain[j]->finished)
{
delete(_grain[j]);
_grain[j] = new maxiGrain<grainPlayerWin>(&_sample,
_pos + ofRandom(0.05),
ofRandom(FOURNIER_MINGRAINLENGTH, FOURNIER_MAXGRAINLENGTH),
1,
_windowCache);
}
else if (!_grain[j]->finished)
{
_wave[j] = _grain[j]->play();
}
}
mix += _wave[j];
}
}
// Mix
_channel.stereo(mix, _outputs, 0.5);
output[i*nChannels ] = _outputs[0] * _volume;
output[i*nChannels + 1] = _outputs[1] * _volume;
The memory leaks seem to be linked with the _windowCache (of type maxiGrainWindowCache*). In the constructor of maxiGrain there is window = windowCache->getWindow(sampleDur); This functions always mallocs cache but the class never frees it.
What do i do wrong ? Can you help please ? Thank you.
— Reply to this email directly or view it on GitHubhttps://github.com/micknoise/Maximilian/issues/25#issuecomment-49362502.
Thanks for you help. I found another simple solution. I don't know why but memory leaks came from the fact the length of grains always changed (the ofRandom(MINGRAINLENGTH, MAXGRAINLENGTH) argument). I just deleted and re-created my window before the re-creation of the grain and it works.
for (i = 0; i < bufferSize; i++) { mix = 0.0f;
if (_active)
{
for (j = 0; j < NBGRAINS; j++)
{
if (_grain[j] != NULL)
{
if (_grain[j]->finished)
{
// Delete old stuff
delete(_grain[j]);
delete(_windowCache[j]);
// Create new window cache
_windowCache[j] = new maxiGrainWindowCache<grainPlayerWin>();
_windowCache[j]->cacheSize = MAXGRAINLENGTH * AUDIO_SAMPLERATE;
// Create new grain
_grain[j] = new maxiGrain<grainPlayerWin>(&_sample,
_pos + ofRandom(0.05),
ofRandom(MINGRAINLENGTH, MAXGRAINLENGTH),
1,
_windowCache[j]);
}
else if (!_grain[j]->finished)
{
_wave[j] = _grain[j]->play();
}
}
mix += _wave[j];
}
}
// Mix
_channel.stereo(mix, _outputs, 0.5);
output[i*nChannels ] = _outputs[0] * _volume;
output[i*nChannels + 1] = _outputs[1] * _volume;
} Thank you again !
that makes sense now - it wasn't really a memory leak, it's the windowcache object storing each size of window in the cache - the system should stop using memory once it has a copy of each size of window you are using. It's a memory-speed trade of, and with a lot of variance in the window size, you might be better off recalculating the window each time
OK, thanks for the explanation. I meant memory leak in my software, not in Maximilian of course :)
Hi!
First, thanks and congratulations with Maximilian, it works great and is well optimized.
I use it on OpenFrameworks for iOS. I don't manage to do a simple stuff: a very basic granular synthesis. I would like to play a orchestral wav file with position (in the wav file) as a parameter. I explain, i would like to have 16 grain players, and every xx milliseconds (xx = random numbers) one of these players plays a very short part of the file (at the right play head position), with no loop. Because there are 16 players and they play very quickly small grains, it gives you the impression that the play head stays immobile. I made a Max/MSP patch and it works well, but i cannot make it in OpenFrameworks / Maximilian.
Hope my explanation is obvious. Thanks for your help!
Cheers, Olivier