Subversion Repositories Kolibri OS

Rev

Rev 9288 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8210 maxcodehac 1
#include "SDL_audio.h"
9789 turbocat 2
#include 
3
#include 
8210 maxcodehac 4
#include 
5
#include 
6
#include 
7
#include 
8
 
9789 turbocat 9
extern void SDL_printf(const char * fmt,...);
8210 maxcodehac 10
 
9789 turbocat 11
#define AUDIO_THREAD_STACK_SIZE 40960
12
 
13
static ksys_thread_t thread_info;
14
static int bInitialized = 0;
15
static SNDBUF hBuff = 0;
16
static uint8_t* data = NULL;
17
static int audio_tid = 0;
8210 maxcodehac 18
static int main_slot;
9789 turbocat 19
static uint32_t main_tid;
20
static char audio_thread_stack[AUDIO_THREAD_STACK_SIZE];
21
static uint32_t used_format = 0;
22
static int mix_size = 0;
8210 maxcodehac 23
 
24
static void (*callback)(void* userdata, Uint8* stream, int len);
25
static void* userdata;
26
 
27
int SDL_AudioInit(const char* driver_name)
28
{
9789 turbocat 29
    if (bInitialized) {
30
        SDL_SetError("Audio already initialized");
31
        return -1;
32
    }
33
    int ver;
34
    if (InitSound(&ver)) {
35
        SDL_printf("Warning: cannot load drivers, sound output will be disabled\n");
36
        return 0;
37
    }
38
    bInitialized = 1;
39
    return 0;
8210 maxcodehac 40
}
41
 
9789 turbocat 42
void SDL_AudioQuit(void) {/*STUB*/}
8210 maxcodehac 43
 
44
char* SDL_AudioDriverName(char* namebuf, int maxlen)
45
{
9789 turbocat 46
    if (!bInitialized)
47
            return NULL;
48
    strncpy(namebuf,"KolibriAudio",maxlen);
49
    return namebuf;
8210 maxcodehac 50
}
51
 
52
#define AUDIO_SUSPEND 1
53
#define AUDIO_RESUME 2
54
#define AUDIO_DIE 3
9789 turbocat 55
 
56
static volatile int audio_command=0, audio_response=0, bLocked=0, bInCallback=0;
57
 
8210 maxcodehac 58
static void audio_thread(void)
59
{
9789 turbocat 60
    SDL_printf("Audio_thread created\n");
61
    int bPaused;
62
    ksys_signal_info_t snd_signal;
8210 maxcodehac 63
        // initialize
9789 turbocat 64
    if (CreateBuffer(used_format|PCM_RING, 0, &hBuff)) {
8210 maxcodehac 65
        audio_response=1;
9789 turbocat 66
        exit(0);
67
    }
68
 
69
    GetBufferSize(hBuff, &mix_size);
70
    SDL_printf("buffer created, size is %d\n", mix_size);
71
    mix_size >>= 1;
72
    data = malloc(mix_size);
73
    audio_response = 1;
74
    if (!data) exit(0);
75
 
76
    // wait for resume
77
    while (audio_command != AUDIO_RESUME)
78
        _ksys_thread_yield();
79
    audio_command = 0;
80
    bPaused = 0;
81
    audio_response = 1;
82
    PlayBuffer(hBuff, 0);
83
 
84
    // main loop
85
    while(1) {
86
        if (audio_command == AUDIO_RESUME) {
87
            PlayBuffer(hBuff, 0);
88
            audio_command = 0;
89
            bPaused = 0;
90
            audio_response = 1;
91
        } else if (audio_command == AUDIO_SUSPEND) {
92
            StopBuffer(hBuff);
93
            audio_command = 0;
94
            bPaused = 1;
95
            audio_response = 1;
96
        }else if (audio_command == AUDIO_DIE) {
97
            audio_response = 1;
98
            StopBuffer(hBuff);
99
            DestroyBuffer(hBuff);
100
            exit(0);
101
        } else {
102
            _ksys_thread_info(&thread_info, main_slot);
103
            if (thread_info.slot_state == KSYS_SLOT_STATE_FREE || thread_info.pid !=main_tid) {
104
                audio_command = AUDIO_DIE;
105
                continue;
106
            }
8210 maxcodehac 107
        }
9789 turbocat 108
        if (bPaused) {
109
            _ksys_delay(5);
110
        } else {
111
            _ksys_wait_signal(&snd_signal);
112
            if (snd_signal.id != 0xFF000001)
113
                continue;
114
            while (bLocked)
115
                _ksys_thread_yield();
116
 
117
            bInCallback=1;
118
            callback(userdata, data, mix_size);
119
            bInCallback=0;
120
            SetBuffer(hBuff, data, ((int*)snd_signal.data)[2], mix_size);
121
        }
122
    }
8210 maxcodehac 123
}
124
 
125
int SDL_OpenAudio(SDL_AudioSpec* desired, SDL_AudioSpec* obtained)
126
{
9789 turbocat 127
    if (!bInitialized) {
128
        SDL_SetError("Audio device was not initialized");
129
        return -1;
130
    }
131
 
132
    if (!obtained) {
133
        SDL_SetError("Audio format: software emulation is not supported");
134
        return -1;
135
    }
136
 
137
    if (used_format) {
138
        SDL_SetError("Audio device was already opened");
139
        return -1;
140
    }
141
    memcpy(obtained, desired, sizeof(SDL_AudioSpec));
142
    switch (desired->freq) {
8210 maxcodehac 143
 
144
#define HANDLE_FREQ(freq,symb)                          \
145
        case freq:                                      \
146
                switch (desired->channels)              \
147
                {                                       \
148
                case 1:                                 \
149
                        switch (desired->format)        \
150
                        {                               \
151
                        case AUDIO_U8:                  \
152
                        case AUDIO_S8:                  \
153
                                used_format = PCM_1_8_##symb;   \
154
                                break;                  \
155
                        case AUDIO_U16SYS:              \
156
                        case AUDIO_S16SYS:              \
157
                                used_format = PCM_1_16_##symb;  \
158
                                break;                  \
159
                        }                               \
160
                        break;                          \
161
                case 2:                                 \
162
                        switch (desired->format)        \
163
                        {                               \
164
                        case AUDIO_U8:                  \
165
                        case AUDIO_S8:                  \
166
                                used_format = PCM_2_8_##symb;   \
167
                                break;                  \
168
                        case AUDIO_U16SYS:              \
169
                        case AUDIO_S16SYS:              \
170
                                used_format = PCM_2_16_##symb;  \
171
                                break;                  \
172
                        }                               \
173
                        break;                          \
174
                }                                       \
175
                break;
176
 
177
        HANDLE_FREQ(48000,48);
178
        HANDLE_FREQ(44100,44);
179
        HANDLE_FREQ(32000,32);
180
        HANDLE_FREQ(24000,24);
181
        HANDLE_FREQ(22050,22);
182
        HANDLE_FREQ(16000,16);
183
        HANDLE_FREQ(12000,12);
184
        HANDLE_FREQ(11025,11);
185
        HANDLE_FREQ(8000,8);
9789 turbocat 186
    }
187
 
188
    if (!used_format) {
189
        SDL_SetError("Unknown audio format");
190
        return -1;
191
    }
192
 
193
    callback = desired->callback;
194
    userdata = desired->userdata;
195
 
196
    _ksys_thread_info(&thread_info, KSYS_THIS_SLOT);
197
    main_tid = thread_info.pid;
198
    for (main_slot=0 ;; main_slot++) {
199
        _ksys_thread_info(&thread_info, main_slot);
200
        if (thread_info.slot_state != KSYS_SLOT_STATE_FREE && thread_info.pid == main_tid)
201
            break;
202
    }
203
    audio_tid = _ksys_create_thread(audio_thread, audio_thread_stack+AUDIO_THREAD_STACK_SIZE);
204
    if (audio_tid < 0) {
205
        SDL_SetError("Cannot create audio thread");
206
            return -1;
207
    }
208
 
209
    _ksys_focus_window(main_slot);
210
    while (!audio_response)
211
        _ksys_thread_yield();
212
 
213
    if (!hBuff) {
214
        SDL_SetError("Cannot create audio buffer");
215
        return -1;
216
    }
217
    if (!data){
218
        SDL_SetError("Cannot allocate audio buffer");
219
        return -1;
220
    }
221
    obtained->silence = (desired->format == AUDIO_U8 ? 0x80 : 0);
222
    obtained->size = mix_size;
223
    obtained->samples = obtained->size / obtained->channels;
224
 
225
    if (desired->format == AUDIO_U16SYS || desired->format == AUDIO_S16SYS)
226
        obtained->samples /= 2;
227
 
228
    SDL_printf("obtained size is %d, samples %d\n", obtained->size, obtained->samples);
229
    return 0;
8210 maxcodehac 230
}
231
void SDL_CloseAudio(void)
232
{
9789 turbocat 233
    if (!audio_tid) return;
234
    audio_response = 0;
235
    audio_command = AUDIO_DIE;
236
    while (!audio_response) _ksys_thread_yield();
237
    free(data);
238
    used_format = 0;
8210 maxcodehac 239
}
240
 
241
void SDL_PauseAudio(int pause_on)
242
{
9789 turbocat 243
    if (!audio_tid) return;
244
    audio_response = 0;
245
    audio_command = pause_on ? AUDIO_SUSPEND : AUDIO_RESUME;
246
    while (!audio_response) _ksys_thread_yield();
8210 maxcodehac 247
}
248
void SDL_LockAudio(void)
249
{
9789 turbocat 250
    if (!audio_tid) return;
251
    bLocked = 1;
252
    while (bInCallback) _ksys_thread_yield();
8210 maxcodehac 253
}
254
void SDL_UnlockAudio(void)
255
{
9789 turbocat 256
    bLocked = 0;
8210 maxcodehac 257
}