[…]
Looking at the documentation, a few questions pop up:
* Is it still true that only WAV files can be
used for samples? I suppose it would be
possible to use SDL_sound for decoding other
formats to memory, and then having libMikMod
load it from there...
.WAV is the only filetype that can be used as a sample, but the
streamed formats are entirely another story. Pitch shifting on
streamed players is rather difficult and you might have to resort to
system-specific code for doing that.
That sounds strange… What’s system specific about resampling? It
sounds like these streams actually bypass the normal mixing engine or
something.
Anyway, I’ll just read the source and see what I find…
* It appears that the "Player" is a singleton,
which would mean that only one module can be
played at a time. Is there a way around this?
(For crossfading, using music as sound effects
and stuff like that.)
Speaking of which; what, if anything, does
SDL_sound do about this?
SDL_sound wraps both MikMod and ModPlugTracker. It’s possible that
ModPlugTracker’s library might handle this. Not an ideal solution
IMHO since you have two music players loaded in simultaneously.
Well, the correct solution would obviously be to fix libMikMod and/or
ModPlug, so SDL_sound doesn’t have to worry about global state
conflicts, but I have no idea how much work that would be. As long as
we’re not dealing with lower level resources with further global
state issues, it’s theoretically just a matter of moving global
variables into a state struct and adjusting the API accordingly.
* I can't seem to find a pitch/transpose control
for the Player. Not exactly essential for
music (though some games in the 8 bit days
did transpose the music), but nice if you want
to use music formats for sound effects.
I think it only will transpose individual samples using the
Voice_SetFrequency() function but I haven’t tried it. Have a look
at http://mikmod.raphnet.net/doc/libmikmod-3.1.10/docs/mikmod.html
for the specific documentation on the Voice_SetFrequency() function.
(Just scroll down from the Sample Functins link.)
Well, it’s a Voice call, so I don’t see how you could even reference
a “music context” with it. (And there seems to be only one “music
context” anyway, pretty much like in SDL_mixer…)
My idea was more along the lines of providing something very light
weight and modular, with few, if any dependencies. Smaller and
simpler than SDL_mixer, with no explicit music or decoding support
at all. Something that does one thing, and does it well.
I would certainly welcome such a library becuase I am writing a
program that compiles ProTracker music modules into C source and am
having to make it system-specific to the Amiga-like operating
systems that support AHI drivers because it would be so redundant
with SDL_mixer and MikMod around.
It appears that the basic idea with AHI is to provide an abstract and
enhanced version of Paula. (Good old days…! The API pretty much
reflects how you’d go about programming the chip “to the metal”, but
obviously, the abstraction allows emulation over other hardware,
voice virtualization and stuff like that.
The main difference with the API I have in mind is less focus on
hardware acceleration, and more focus on ease of use and useful
features.
The situation with hardware mixing is pretty much the same as in early
days of 3D acceleration. No standard language for custom DSP code
(corresponding to pixel shaders), many platforms lack driver or API
support, many systems lack hardware mixing entirely etc.
Of course, the API won’t necessarily rule out hardware acceleration,
but if you want effects to sound the same everywhere, want to drop in
custom effects, or need accurate timing and/or reliable inter-voice
synchronization, you’re pretty much guaranteed to be dropped back to
full software processing anyway. And if you don’t need effects and
stuff, you don’t really need hardware mixing, unless you’re on very
low end hardware and/or need insane numbers of voices…
That said, I suppose one could support AHI other APIs as well as SDL
audio, to make use of hardware mixing where available. It would work
as long as no master effects or similar are used - and such things
are probably no option anyway on platforms that really need hardware
mixing for speed. Just optionally dropping the effects is a lot less
work than supporting a different API, so it still helps portability.
There are several other libs (SDL_sound, libsndfile, various codec
libs etc…) that specialize in decoding/playing various types of
files and streams. Just plug one of these in if you need music.
The interesting part is that these would stream through the New
Mixer, giving you pitch control, effects and stuff, just as for
sound effects.
I think this is the problem with getting stuff to work on platform
independent libraries like SDL. I don’t know what Windows is like
or ALSA on Linux or Mac. I use SDL because there is little money to
be made on Amiga-like OSs with AHI drivers.
Well, they all have one thing in common: The only type of audio you
can count on is fixed rate stereo output. Anything beyond that is
only available on certain hardware, if at all accessible through
standard APIs.
The (original) Amiga is rather unique with it’s four (more or less)
independent hardware mixed DMA voices… (Well, every Live! and
Audigy and many other cards do that too - but it’s hard, if at all
possible to access it in any useful way, and even basic pitch control
is hardware specific, as most cards have resampling ratio
restrictions.)
If you wanted to port the AHI source code it would make my life
simpler but I doubt it would replace ALSA or some of the better
supported driver/mixer formats. The AHI source code is at
http://arp2.berlios.de/ahi/ if you’re interested. (The AROS version
is x86, the original AmigaOS 2.x-3.x version is
68000-based, and the AmigaOS 4.0 and MorphOS versions are PowerPC.)
The biggest problem is that it does things that “normal” audio APIs
these days don’t, so it pretty much ends up looking like a software
mixer/sound engine API, rather than a sound drivern API.
It would certainly be possible to implement it over ALSA, SDL audio,
DirectSound or whatever, but as there seems to be quite a bit of
AmigaOS specifics that need to be removed from the API, I’m not sure
there is much point…
I just thought that I would point out MikMod since it’s portable and
LGPL, AHI is also GPL/LGPL for the current parts respectively. I
don’t know how hard it is to write a wrapper functionity for a sound
driver but I’ll be using the AHI drivers for my Music Compiler
nonetheless.
As long as the semantics and feature sets match, it’s usually pretty
straightforward.
Looking at the AHI low level API, I don’t think it should be much of a
problem to have your code talk to this “New Mixer” thing, or to use
AHI as an alternate backend to the default software-over-SDL-audio
thing.
I’ll eagerly await any portable solutions you can come up with. I’m
not an expert on sound but I’m pretty well initiated with how things
are done on the Amiga. Drop me an email or post here and I’ll try
to help out any way I can.
What I’m most interested in at this point is which features you need.
After some browsing of the AHI docs, it seems like I’ll pretty much
provide a superset of the low level API. Not quite sure about the
waveform/stream handling, though. There are a few basic models that
might be relevant here:
1. Synchronous streaming callbacks. Pretty much the
same deal as SDL audio; one callback for each
output buffer - except here, you'd get one
callback for each voice, asking for the number
of *input* samples needed to render the next
buffer. That is, these callbacks will be asked
for buffers of varying size depending on voice
pitch. (The point is to keep the CPU load as
constant as possible across audio output
buffers. Though this may not be essential in
your average game, it is critical in low latency
applications that use any significant percentage
of the CPU time.) The API may allow callbacks to
optionally return pointers instead of copying
data.
This works for everything (this is the way
all serious low level audio APIs are designed),
but may not be the easiset way of just getting
some sounds played.
2. Engine managed sounds. You will need to upload
sounds to the mixer, pretty much like you upload
textures to OpenGL. You tell the mixer to start
and stop sounds by making calls from the
application main thread, or from within mixer
driven callbacks, the former being asynchronous
and the latter being synchronous and potentially
sample accurate.
Easy to use and suitable for most things
except real time synthesis and streaming.
3. Asynchronous buffer queue streaming. The
application pushes buffers of arbitrary sizes
onto a (per voice) queue where the mixer picks
them up and plays them one by one.
Suitable for streaming from a decoder running
in a background thread, but not of much use for
low latency sound.
All three models allow callbacks to be used to make real time
decisions when reaching the end of a sound, at regular (sample
accurate) intervals and things like that, to implement looping,
envelopes etc. (This is where you’d hook in a music player that wants
to “play” the mixer, rather than mixing on it’s own.)
All models have their uses, though 2 and 3 are higher level models
that can be implemented over 1, whereas the other way around is not
possible without additional buffering and latency problems.
Model 2 seems to be the obvious, easy to use choice for pretty much
everything but real time synthesis (ie hacking your own virtual
analog oscillators and stuff) and streaming from non real time safe
decoders. So, I suppose the main focus of the API should be on that
model, but I think there will be trouble if the other two models
aren’t somehow accessible.
Model 1 is useful when you want to plug in some code that would
normally use SDL audio or a similar low level audio API directly.
Publishing this interface allows integrating such code with the
mixer, without additional latency.
Model 3 is handy when using IFFT based decoders and the like; sources
that won’t safely run inside a low latency real time thread. Indeed,
it can be implemented over 1, but then again, building it into the
mixer shouldn’t add much code, and it would make it easier for non
audio hackers to do things the proper way.
Thoughts? What did I miss?
//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 Friday 19 January 2007 21:38, Samuel Crow wrote: