📄 mikmod.texi
字号:
int i; /* sound effects */ SAMPLE *sfx1, *sfx2; /* voices */ int v1, v2; /* register all the drivers */ MikMod_RegisterAllDrivers(); /* initialize the library */ md_mode |= DMODE_SOFT_SNDFX; if (MikMod_Init("")) @{ fprintf(stderr, "Could not initialize sound, reason: %s\n", MikMod_strerror(MikMod_errno)); return; @} /* load samples */ sfx1 = Sample_Load("first.wav"); if (!sfx1) @{ MikMod_Exit(); fprintf(stderr, "Could not load the first sound, reason: %s\n", MikMod_strerror(MikMod_errno)); return; @} sfx2 = Sample_Load("second.wav"); if (!sfx2) @{ Sample_Free(sfx1); MikMod_Exit(); fprintf(stderr, "Could not load the second sound, reason: %s\n", MikMod_strerror(MikMod_errno)); return; @} /* reserve 2 voices for sound effects */ MikMod_SetNumVoices(-1, 2); /* get ready to play */ MikMod_EnableOutput(); /* play first sample */ v1 = Sample_Play(sfx1, 0, 0); for(i = 0; i < 5; i++) @{ MikMod_Update(); usleep(100000); @} /* half a second later, play second sample */ v2 = Sample_Play(sfx2, 0, 0); do @{ MikMod_Update(); usleep(100000); @} while (!Voice_Stopped(v2)); MikMod_DisableOutput(); Sample_Free(sfx2); Sample_Free(sfx1); MikMod_Exit();@}@end exampleAs in the previous example, we begin by registering the sound drivers andinitializing the library. We also ask for software mixing by modifying thevariable @code{md_mode}.It's time to load our files, with the @code{Sample_Load} function. Don't forgetto test the return value --- it looks ugly here on such a small example, butit's a good practice@enddots{}Since we want to play two samples, we have to use at least two voices for this,so we reserve them with a @code{MikMod_SetNumVoices} call. The first parametersets the number of module voices, and the second parameter the number of soundeffect voices. We don't want to set the number of module voices here (it's partof the module player's duty), so we use the value @code{-1} to keep the currentvalue, and we reserve two sound effect voices.Now we're ready to play, so we call @code{MikMod_EnableOutput} to make thedriver ready. Sound effects are played by the @code{Sample_Play} function.You just have to specify which sample you want to play, the offset from whichyou want to start, and the playback flags. More on this later. The functionreturns the number of the voice associated to the sample.We play the first sample for half a second, then we start to play the secondsample. Since we've reserved two channels, both samples play simultaneously. Weuse the @code{Voice_Stopped} function to stop the playback: it returns thecurrent status of the voice argument, which is zero when the sample plays andnonzero when it has finished. So the @code{do} loop will stop exactly whenthe second sample is finished, regardless of the length of the first sample.To finish, we get rid of the samples with @code{Sample_Free}.@c ========================================================== More effects@node More Sound Effects, , Playing Sound Effects, Tutorial@section More Sound Effects@iftex@findex MikMod_Update@findex Sample_Play@findex Voice_SetFrequency@findex Voice_SetPanning@findex Voice_SetVolume@findex Voice_Stop@findex Voice_Stopped@end iftexSound effects have some attributes that can be affected to control the playback.These are speed, panning, and volume. Given a voice number, you can affect theseattributes with the @code{Voice_SetFrequency}, @code{Voice_SetPanning} and@code{Voice_SetVolume} functions.In the previous example, we'll replace the actual sound code, located betweenthe calls to @code{MikMod_EnableOutput} and @code{MikMod_DisableOutput}, withthe following code:@example Sample_Play(sfx1, 0, 0); for(i = 0; i < 5; i++) @{ MikMod_Update(); usleep(100000); @} v2 = Sample_Play(sfx2, 0, SFX_CRITICAL); i = 0; do @{ MikMod_Update(); usleep(100000); v1 = Sample_Play(sfx1, 0, 0); Voice_SetVolume(v1, 160); Voice_SetFrequency(v1, (sfx1->speed * (100 + i)) / 100); Voice_SetPanning(v2, (i++ & 1) ? PAN_LEFT : PAN_RIGHT); @} while (!Voice_Stopped(v2));@end exampleThe first thing you'll notice, is the @code{SFX_CRITICAL} flag used to play thesecond sample. Since the @code{do} loop will add another sample every 100@dmn{milliseconds}, and we reserved only two voices, the oldest voice will becut each time this is necessary. Doing this would cut the second sample in thesecond iteration of the loop. However, since we flagged this sound as``critical'', it won't be cut until it is finished or we stop it with a@code{Voice_Stop} call. So the second sample will play fine, whereas the firstsample will be stopped every loop iteration.Then, we choose to play the first sample a bit lower, with@code{Voice_SetVolume}. Volume voices range from 0 (silence) to 256. Inthis case we play the sample at 160. To make the sound look weird, we alsochange its frequency with @code{Voice_SetFrequency}. The computation in theexample code makes the frequency more and more high (starting from the samplefrequency and then increasing from 1% each iteration).And to demonstrate the @code{Voice_SetPanning} function, we change the panningof the second sample at each iteration from the left to the right. The argumentcan be one of the standard panning @code{PAN_LEFT}, @code{PAN_RIGHT},@code{PAN_CENTER} and @code{PAN_SURROUND}@footnote{@code{PAN_SURROUND} will bemapped to @code{PAN_CENTER} if the library is initialized without surroundsound, that is, if the variable @code{md_mode} doesn't have the bit@code{DMODE_SURROUND} set.}, or a numeric value between 0 (@code{PAN_LEFT}) and255 (@code{PAN_RIGHT}).@c ========================================================== Using@node Using the Library, Library Reference, Tutorial, Top@chapter Using the LibraryThis chapter describes the various parts of the library and their uses.@menu* Library Version::* Type Definitions::* Error Handling::* Library Initialization::* Samples and Voice Control::* Modules and Player Control::* Loading Data from Memory::@end menu@c ========================================================== Version@node Library Version, Type Definitions, Using the Library, Using the Library@section Library Version@iftex@findex MikMod_GetVersion@end iftexIf your program is dynamically linked with the MikMod library, you should checkwhich version of the library you're working with.To do this, the library defines a few constants and a function to help youdetermine if the current library is adequate for your needs or if it has tobe upgraded.When your program includes @code{mikmod.h}, the following constants aredefined:@itemize @bullet@item @code{LIBMIKMOD_VERSION_MAJOR} is equal to the major version number ofthe library.@item @code{LIBMIKMOD_VERSION_MINOR} is equal to the minor version number ofthe library.@item @code{LIBMIKMOD_REVISION} is equal to the revision number of the library.@item @code{LIBMIKMOD_VERSION} is the sum of @code{LIBMIKMOD_VERSION_MAJOR} shifted 16 times, @code{LIBMIKMOD_VERSION_MINOR} shifted 8 times, and@code{LIBMIKMOD_REVISION}.@end itemizeSo your program can tell with which version of the library it has been compiledthis way:@exampleprintf("Compiled with MikMod Sound Library version %ld.%ld.%ld\n", LIBMIKMOD_VERSION_MAJOR, LIBMIKMOD_VERSION_MINOR, LIBMIKMOD_REVISION);@end exampleThe library defines the function @code{MikMod_GetVersion} which returns thevalue of LIBMIKMOD_VERSION for the library. If this value is greater than orequal to the value of LIBMIKMOD_VERSION for your program, your program willwork; otherwise, you'll have to inform the user that he has to upgrade thelibrary:@example@{ long engineversion = MikMod_GetVersion(); if (engineversion < LIBMIKMOD_VERSION) @{ printf("MikMod library version (%ld.%ld.%ld) is too old.\n", (engineversion >> 16) & 255, (engineversion >> 8) & 255, (engineversion) & 255); printf("This programs requires at least version %ld.%ld.%ld\n", LIBMIKMOD_VERSION_MAJOR, LIBMIKMOD_VERSION_MINOR, LIBMIKMOD_REVISION); puts("Please upgrade your MikMod library."); exit(1); @}@}@end example@c ========================================================== Types@node Type Definitions, Error Handling, Library Version, Using the Library@section Type Definitions@iftex@tindex BOOL@tindex CHAR@tindex SBYTE@tindex SLONG@tindex SWORD@tindex UBYTE@tindex ULONG@tindex UWORD@end iftexMikMod defines several data types to deal with modules and sample data.These types have the same memory size on every platform MikMod has been portedto.These types are:@itemize @bullet@item @code{CHAR} is a printable character. For now it is the same as the@code{char} type, but in the future it may be wide char (Unicode) on someplatforms.@item @code{SBYTE} is a signed 8 bit number (can range from -128 to 127).@item @code{UBYTE} is an unsigned 8 bit number (can range from 0 to 255).@item @code{SWORD} is a signed 16 bit number (can range from -32768 to 32767).@item @code{UWORD} is an unsigned 16 bit number (can range from 0 to 65535).@item @code{SLONG} is a signed 32 bit number (can range from -2.147.483.648 to2.147.483.647).@item @code{ULONG} is an unsigned 32 bit number (can range from 0 to4.294.967.296).@item @code{BOOL} is a boolean value. A value of 0 means false, any other valuemeans true.@end itemize@c ========================================================== Errors@node Error Handling, Library Initialization, Type Definitions, Using the Library@section Error Handling@iftex@findex MikMod_RegisterErrorHandler@vindex MikMod_critical@vindex MikMod_errno@vindex MikMod_strerror@end iftexAlthough MikMod does its best to do its work, there are times where it can't.For example, if you're trying to play a corrupted file, well, it can't.A lot of MikMod functions return pointers or @code{BOOL} values. If the pointeris @code{NULL} or the @code{BOOL} is 0 (false), an error has occurred.MikMod errors are returned in the variable @code{MikMod_errno}. Each possibleerror has a symbolic error code, beginning with @code{MMERR_}. For example, ifMikMod can't open a file, @code{MikMod_errno} will receive the value@code{MMERR_OPENING_FILE}.You can get an appropriate error message to display from the function@code{MikMod_strerror}.There is a second error variable named @code{MikMod_critical}. As its namesuggests, it is only set if the error lets the library in an unstable state.This variable can only be set by the functions @code{MikMod_Init}, @code{MikMod_SetNumVoices} and @code{MikMod_EnableOutput}. If one of thesefunctions return an error and @code{MikMod_critical} is set, the library is leftin the uninitialized state (i.e. it was not initialized, or @code{MikMod_Exit}was called).If you prefer, you can use a callback function to get notified of errors. Thisfunction must be prototyped as @code{void MyFunction(void)}. Then, call@code{MikMod_RegisterHandler} with your function as argument to have it notifiedwhen an error occurs. There can only be one callback function registered, but@code{MikMod_RegisterHandler} will return you the previous handler, so you canchain handlers if you want to.@c ========================================================== Initialization@node Library Initialization, Samples and Voice Control, Error Handling, Using the Library@section Library Initialization and Core Functions@iftex@findex MikMod_Active@findex MikMod_DisableOutput@findex MikMod_EnableOutput@findex MikMod_Exit@findex MikMod_InfoDriver@findex MikMod_Init@findex MikMod_InitThreads@findex MikMod_Lock@findex MikMod_RegisterAllDrivers@findex MikMod_RegisterDriver@findex MikMod_Reset@findex MikMod_SetNumVoices@findex MikMod_Unlock@findex MikMod_Update@vindex md_device@vindex md_mixfreq@vindex md_mode@end iftexTo initialize the library, you must register some sound drivers first. You caneither register all the drivers embedded in the library for your platform with@code{MikMod_RegisterAllDrivers}, or register only some of them with@code{MikMod_RegisterDriver}. If you choose to register the drivers manually,you must be careful in their order, since @code{MikMod_Init} will try them inthe order you registered them. The @code{MikMod_RegisterAllDrivers} functionregisters the network drivers first (for playing sound over the network), thenthe hardware drivers, then the disk writers, and in last resort, the nosounddriver. Registering the nosound driver first would not be a very goodidea@enddots{}You can get some printable information regarding the registered drivers with@code{MikMod_InfoDriver}; don't forget to call @code{free} on the returnedstring when you don't need it anymore.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -