--- nick thomas <[EMAIL PROTECTED]> wrote: > On 5/2/07, Stephen Cameron <[EMAIL PROTECTED]> 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 [email protected] http://lists.linuxaudio.org/mailman/listinfo.cgi/linux-audio-dev
