⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mikmod.texi

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
module player does a lot of things for us, but here we'll get more control over
what is actually played by the program. Let's look at an example:

@example
/* MikMod Sound Library example program: sound effects */

#include <unistd.h>
#include <mikmod.h>

main()
@{
    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 example

As in the previous example, we begin by registering the sound drivers and
initializing the library. We also ask for software mixing by modifying the
variable @code{md_mode}.

It's time to load our files, with the @code{Sample_Load} function. Don't forget
to test the return value --- it looks ugly here on such a small example, but
it'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 parameter
sets the number of module voices, and the second parameter the number of sound
effect voices. We don't want to set the number of module voices here (it's part
of the module player's duty), so we use the value @code{-1} to keep the current
value, and we reserve two sound effect voices.

Now we're ready to play, so we call @code{MikMod_EnableOutput} to make the
driver 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 which
you want to start, and the playback flags. More on this later. The function
returns the number of the voice associated to the sample.

We play the first sample for half a second, then we start to play the second
sample. Since we've reserved two channels, both samples play simultaneously. We
use the @code{Voice_Stopped} function to stop the playback: it returns the
current status of the voice argument, which is zero when the sample plays and
nonzero when it has finished. So the @code{do} loop will stop exactly when
the 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 iftex

Sound 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 these
attributes 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 between
the calls to @code{MikMod_EnableOutput} and @code{MikMod_DisableOutput}, with
the 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 example

The first thing you'll notice, is the @code{SFX_CRITICAL} flag used to play the
second sample. Since the @code{do} loop will add another sample every 100
@dmn{milliseconds}, and we reserved only two voices, the oldest voice will be
cut each time this is necessary. Doing this would cut the second sample in the
second 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 first
sample 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. In
this case we play the sample at 160. To make the sound look weird, we also
change its frequency with @code{Voice_SetFrequency}. The computation in the
example code makes the frequency more and more high (starting from the sample
frequency and then increasing from 1% each iteration).

And to demonstrate the @code{Voice_SetPanning} function, we change the panning
of the second sample at each iteration from the left to the right. The argument
can be one of the standard panning @code{PAN_LEFT}, @code{PAN_RIGHT},
@code{PAN_CENTER} and @code{PAN_SURROUND}@footnote{@code{PAN_SURROUND} will be
mapped to @code{PAN_CENTER} if the library is initialized without surround
sound, 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}) and
255 (@code{PAN_RIGHT}).

@c ========================================================== Using
@node Using the Library, Library Reference, Tutorial, Top
@chapter Using the Library

This 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 iftex

If your program is dynamically linked with the MikMod library, you should check
which version of the library you're working with.
To do this, the library defines a few constants and a function to help you
determine if the current library is adequate for your needs or if it has to
be upgraded.

When your program includes @code{mikmod.h}, the following constants are
defined:
@itemize @bullet
@item @code{LIBMIKMOD_VERSION_MAJOR} is equal to the major version number of
the library.
@item @code{LIBMIKMOD_VERSION_MINOR} is equal to the minor version number of
the 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 itemize

So your program can tell with which version of the library it has been compiled
this way:
@example
printf("Compiled with MikMod Sound Library version %ld.%ld.%ld\n",
       LIBMIKMOD_VERSION_MAJOR,
       LIBMIKMOD_VERSION_MINOR,
       LIBMIKMOD_REVISION);
@end example

The library defines the function @code{MikMod_GetVersion} which returns the
value of LIBMIKMOD_VERSION for the library. If this value is greater than or
equal to the value of LIBMIKMOD_VERSION for your program, your program will
work; otherwise, you'll have to inform the user that he has to upgrade the
library:

@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 iftex

MikMod defines several data types to deal with modules and sample data.
These types have the same memory size on every platform MikMod has been ported
to.

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 some
platforms.
@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 to
2.147.483.647).
@item @code{ULONG} is an unsigned 32 bit number (can range from 0 to
4.294.967.296).
@item @code{BOOL} is a boolean value. A value of 0 means false, any other value
means 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 iftex

Although 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 pointer
is @code{NULL} or the @code{BOOL} is 0 (false), an error has occurred.

MikMod errors are returned in the variable @code{MikMod_errno}. Each possible
error has a symbolic error code, beginning with @code{MMERR_}. For example, if
MikMod 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 name
suggests, 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 these
functions return an error and @code{MikMod_critical} is set, the library is left
in 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. This
function must be prototyped as @code{void MyFunction(void)}. Then, call
@code{MikMod_RegisterHandler} with your function as argument to have it notified
when an error occurs. There can only be one callback function registered, but
@code{MikMod_RegisterHandler} will return you the previous handler, so you can
chain 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -