El Mi?rcoles, 17 de Enero de 2007 14:14, David Olofson escribi?:
Ok. So the mixer callbacks won’t be of much help here.
Well, not the way they’re supposed to be used, but you could
probably get away with implementing a resampling
wavetable “oscillator”, the way I suggested; by implementing an
effect that ignores the input and just generates output.
I see. The first time you suggested that I thought that this could
be hard to implement, so I decided to leave mix effects. Now I
realize that maybe this is the simpler way, because inside of the
callback function I can keep track of which part of the sound is
being played and what is needed for the next buffer.
Exactly. And, besides, this is how your average synth oscillator
is implemented. Apart from stepping outside the official semantics of
the SDL_mixer API, it’s actually the correct and straightforward way
of doing it.
One thing to note is that I am not generating my waveform, but
altering a digitized preexistent bank of sounds,
Well, that’s the usual way.
(I think actual real time synthesis of engine sounds - and musical
instruments and other sounds, for that matter - pretty much died as
the 6581, AY*/YM*, OPL* and similar chips went out of fashion.)
so the code would be something as:
struct soundInfo
{
int rpms;
int numSample, soundSampleLenght;
/* the number of samples played and the total of samples for that
sound will
help us to know what is to play next /
int bankNumber;
/ which sound of our bank of sounds is being played for the present
frequency. If the frequency range falls out of this sound, we’ll
start
playing the sound above or below in the bank */
};
void effect_function( int channel, void *stream, int len, void
*udata)
{
struct soundInfo *p = (struct soundInfo *) data;
/* check p->rpms to know which sound fits best into that frequency
/
/ from our bank of sounds */
/* Interpolate “len” number of samples from the current stream
position /
/ and write then into “stream” */
}
That “current stream position” would be scaled by the pitch to match
the position of the unmolested sound and get the real offset from
the beggining of it, so I can control what part is to be feeded in
each call.
Keep in mind that the stream position should be fractional, so you
don’t get annoying buzzing or humming at the buffer rate.
Oh, and looping needs to be handled that way too; reset only the
integer sample position - not the fracional position.
…or you can just rip the “voice mixer” code from Audiality.
It supports i big matrix of sample formats, mono/stereo, various
interpolation methods and oversampling, but since you seem to have a
bank of waveforms (which can be bandlimited and resampled in a sound
editor, or at load time), you only really need one version. Anything
but cubic interpolation is pointless unless you want to run on an old
Pentium (memory access costs more than the interpolation), and the
oversampling isn’t needed if you mip-map the waveforms. (Well, 2x, if
you really want the treble flat up to Nyqvist, but for all practical
matters, you can usually push cubic interpolation up to 1.5 * fs or
so without too much aliasing.)
[…]
Thank you for that explanation. It is very interesting. However, I
hope I have not got to implement my sound routines down to that
level!
Well, if you have a bank of waveforms, all you need is some nice
cross-fading - but of course, you still need to figure out when and
how to use each waveform from the bank.
Anyway, interesting problem - and it’s becoming a bit of an FAQ.
Maybe it’s time for another little SDL programming example?
Thank you very much for your help, David. I was also surprised that
this topic has been discussed so many times, but at least in the
posts I have found, the actual implementation of the sound stream
feeding wasn’t shown. I hope then that this post’s pseudocode could
act as a temporary miniFAQ to this question.
Well, that’s why I’ve been thinking about coding an example; I still
haven’t seen one, despite people asking this question over and over.
Apparently, a sound effects mixer without pitch control and stuff
just doesn’t cut it these days…
However I have to test it first! I’ll write when I have got it
done.
Yeah, I think it would be nice to have some “canned code”,
demonstrating how to do it with SDL_mixer, as SDL_mixer seems to do
what most people need, apart from this “little detail” that is sound
FX pitch control.
//David Olofson - Programmer, Composer, Open Source Advocate
.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Wednesday 17 January 2007 15:53, Alberto Luaces wrote: