--- nick thomas <jesuswaffle@email-addr-hidden> wrote:
> On 5/2/07, Stephen Cameron <smcameron@email-addr-hidden> wrote:
> > So, I found libao ( http://xiph.org/ao/doc/ ) which looks
> > nice and simple, and the sample program I tried
> > ( http://xiph.org/ao/doc/ao_example.c ) worked right off
> > the bat,
> >
> If you want real-time, then you'd better use a callback-based API.
> PortAudio might be a good choice for your application:
>
> http://www.portaudio.com/
Ok, that looks cool.
>
> > and the idea of synthesizing my own sounds by
> > constructing waveforms using sine waves is appealing for
> > a retro styled app like mine (though I have no experience
> > doing that and only a vague memory of trigonometry), but
> > I wonder about how to mix sound (add the waveforms, I guess)
> > and construct them on the fly (or trigger pre-computed
> > chunks of audio).
> >
> Since you're just doing this for fun, you might opt to synthesize your
> own sounds in real-time, but it would probably be more "sensible" to
> synthesize them ahead of time. In this case, I suppose it really comes
> down to your personal preference.
Yeah, I planned on doing it ahead of time, where possible.
The game already eats about 35% of a 2.1GHz Athlon, heh.
>
> To answer your question about mixing: yes, you just add the waveforms.
> You have to be sure to avoid clipping, so it can be a bit more
> complicated than that, but that's the gist of it. An explanation of
> how analog-emulation synthesis works is out of the scope of this
> email, but I'm sure there's some literature you can find on the
> subject. For my own part, I just trawled Wikipedia and gradually
> assembled a picture of how it all works, but that's a rather
> time-consuming option. Maybe someone else can recommend some
> literature. :)
>
> > So, I imagine that for a game, in order to satisfy the
> > real-time-ish requirements, I'd instead construct maybe
> > 1/10th or 1/20th second chunks, which would be queued up
> > in my program for playback, and whenever some event happens
> > which demands some sound be produced _right now_ (like the
> > user presses the "fire" button, and so needs some bleeping
> > laser gun sounds to be produced) I would then start adding
> > (arithmetic addition) laser-gun-waveform-data into whatever
> > chunks were already in the queue, and so out would come
> > the sound...
> >
> I think that if you look at the way PortAudio works, you'll see that
> this sort of "queueing" logic is taken care of for you by the library,
> so you don't need to worry about it.
Hmm, no, I don't see that.
I see it has a callback where I have to feed it audio data
X samples at a time (where I get to define X), but I don't
see anything to help with mixing various audio sources.
I guess the callback to do that would look something like
this: (based on what I see here:
http://www.portaudio.com/trac/wiki/TutorialDir/WritingACallback )
/* I imagine sound_source_list to be a pointer to
array of various sound sources I want to mix,
passed to my callback in a cookie */
sound_source_list = (my_whatever *) callback_cookie;
/* "out" is ptr via which to feed portaudio interleaved
L and R audio data for playback */
out[0] = 0;
out[1] = 0;
new_num_sound_sources = num_sound_sources;
for (i=0;i<frames_per_buffer) {
for (j=0;j<num_sound_sources;j++) {
int pos = sound_source[j]->pos;
if (sound_source[j] == NULL)
continue;
out[0] += sound_source[j]->data[pos].left; /* left */
out[1] += sound_source[j]->data[pos].right; /* right */
sound_source[j]->pos++;
if sound_source[j]->pos = sound_source[j].maxpos; {
sound_source[j] = NULL;
if (j == num_sound_sources)
new_num_sound_sources--;
}
}
out += 2;
num_sound_sources = new_num_sound_sources;
}
Then, when the user presses some button that needs to make
noise, a new sound source just gets added to the sound_source
array, maybe like this:
/* Set up structure to hold index and pointer to laser sound data */
new_sound->data = laser_sound_data;
new_sound->pos = 0;
new_sound->maxpos = laser_sound_data_num_samples;
/* add it to sound_source list */
found = 0;
for (i=0;i<num_sound_sources;i++) {
if (sound_source[i] == NULL) {
sound_source[i] = new_sound;
found = i;
}
}
if (!found && num_sound_sources < MAX_SOUND_SOURCES)
sound_source[num_sound_sources++] = new_sound;
Does all that seem more or less about right?
Eh, I see a race in setting num_sound_sources. Hmmm.
Am I even close?
(Hope that wasn't so sketchy that it failed to be comprehesible.)
>
> > I might also want to playback some ogg encoded files for maybe
> > prerecorded sound effects and music to be mixed
> > in with the synthesized sound effects. libao won't do that by itself, but
> > I think there are some other libs on xiph.org that do that, but
> > I'm not sure how well they'd accomodate mixing random bits of
> > sound in with them.
> >
> If you're going for the "retro" effect, you might actually consider
> synthesizing the music in real-time from a MIDI-style score. :) If
> you'd rather do it pre-recorded, however, the approach that you'll
> take would be to find a decoder library, have it decode your music
> into a memory buffer (probably streaming it somehow), and then mix
> that into your own output buffer along with the sound effects.
>
> Hope that helps!
Yes, very much. Thanks.
-- steve
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
_______________________________________________
Linux-audio-dev mailing list
Linux-audio-dev@email-addr-hidden
http://lists.linuxaudio.org/mailman/listinfo.cgi/linux-audio-dev
Received on Thu May 3 08:15:02 2007
This archive was generated by hypermail 2.1.8 : Thu May 03 2007 - 08:15:02 EEST