aboutsummaryrefslogtreecommitdiff
path: root/src/sound.c
blob: 3ff9fa459f349ff3989700467d37ce2f4cbc1100 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <stdint.h>
#include <stdlib.h>
#include <dos.h>

#include "mikmod.h"
#include "ubox_sound.h"

static uint8_t has_sound = 0;
static uint8_t cur = 0;
static uint32_t voice = 0;

static SAMPLE **effects = NULL;
static uint8_t effects_cnt = 0;
static MODULE *music = NULL;

uint8_t ubox_sound_init(const ubox_sound_data *mus, const ubox_sound_data *efx, uint8_t efx_cnt)
{
    MikMod_InitThreads();

    MikMod_RegisterDriver(&drv_sb);
    MikMod_RegisterLoader(&load_it);

    md_mode |= DMODE_SOFT_SNDFX | DMODE_SOFT_MUSIC;
    md_volume = 128;
    md_sndfxvolume = 128;
    md_pansep = 0;
    md_mixfreq = 22050;

    if (MikMod_Init(NULL))
        /* has_sound is 0 */
        return 1;

    if (efx && efx_cnt)
    {
        effects = (SAMPLE **)calloc(efx_cnt, sizeof(SAMPLE *));
        if (!effects)
            return 0;

        for (uint8_t i = 0; i < efx_cnt; i++)
        {
            effects[i] = Sample_LoadMem(efx[i].data, efx[i].len);
            if (!effects[i])
                return 0;
        }

        /* 1 voice for effects */
        if (MikMod_SetNumVoices(-1, 1))
            /* has_sound is 0 */
            return 1;
    }

    /* needs a song playing to get effects; have a "silence" pattern on 0 */
    if (mus)
    {
        music = Player_LoadMem(mus->data, mus->len, 8, 0);
        if (!music)
            return 0;

        Player_Start(music);
    }

    if (MikMod_EnableOutput())
        /* has_sound is 0 */
        return 1;

    has_sound = 1;
    return 1;
}

volatile static uint8_t divider = 0;

void ubox_sound_update()
{
    if (!has_sound)
        return;

    if (++divider == UBOX_SOUND_DIVIDER)
    {
        divider = 0;
        MikMod_Update();
    }
}

void ubox_sound_mute()
{
    if (has_sound)
        MikMod_DisableOutput();
}

void ubox_sound_unmute()
{
    if (has_sound)
        MikMod_EnableOutput();
}

void ubox_sound_free()
{
    if (!has_sound)
        return;

    MikMod_DisableOutput();

    if (music)
        Player_Free(music);

    if (effects && effects_cnt)
    {
        for (uint8_t i = 0; i < effects_cnt; i++)
            if (effects[i])
                Sample_Free(effects[i]);

        free(effects);
    }

    MikMod_Exit();
}

void ubox_sound_music_pattern(uint16_t pat)
{
    if (has_sound && music)
        Player_SetPosition(pat);
}

void ubox_sound_play_efx(uint8_t efxno)
{
    if (has_sound && effects)
    {
        if (cur > efxno && !Voice_Stopped(voice))
            return;

        cur = efxno;
        voice = Sample_Play(effects[cur], 0, 0);
    }
}