src/audio/mint/SDL_mintaudio.c
author Sam Lantinga
Sat, 19 Sep 2009 13:29:40 +0000
changeset 3280 00cace2d9080
parent 2859 99210400e8b9
permissions -rw-r--r--
Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
slouken@398
     1
/*
patmandin@644
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
patmandin@644
     4
patmandin@644
     5
    This library is free software; you can redistribute it and/or
patmandin@644
     6
    modify it under the terms of the GNU Library General Public
patmandin@644
     7
    License as published by the Free Software Foundation; either
patmandin@644
     8
    version 2 of the License, or (at your option) any later version.
patmandin@644
     9
patmandin@644
    10
    This library is distributed in the hope that it will be useful,
patmandin@644
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
patmandin@644
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
patmandin@644
    13
    Library General Public License for more details.
slouken@398
    14
patmandin@644
    15
    You should have received a copy of the GNU Library General Public
patmandin@644
    16
    License along with this library; if not, write to the Free
patmandin@644
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
patmandin@644
    18
patmandin@644
    19
    Sam Lantinga
patmandin@644
    20
    slouken@libsdl.org
patmandin@644
    21
*/
slouken@1402
    22
#include "SDL_config.h"
patmandin@644
    23
patmandin@644
    24
/*
patmandin@644
    25
	Audio interrupt variables and callback function
patmandin@644
    26
patmandin@644
    27
	Patrice Mandin
patmandin@644
    28
*/
patmandin@644
    29
patmandin@1111
    30
#include <unistd.h>
patmandin@1111
    31
patmandin@1111
    32
#include <mint/osbind.h>
patmandin@1111
    33
#include <mint/falcon.h>
patmandin@1111
    34
#include <mint/mintbind.h>
patmandin@2187
    35
#include <mint/cookie.h>
slouken@398
    36
slouken@398
    37
#include "SDL_audio.h"
slouken@398
    38
#include "SDL_mintaudio.h"
patmandin@644
    39
#include "SDL_mintaudio_stfa.h"
slouken@398
    40
patmandin@644
    41
/* The audio device */
slouken@398
    42
patmandin@644
    43
SDL_AudioDevice *SDL_MintAudio_device;
slouken@1895
    44
Uint8 *SDL_MintAudio_audiobuf[2];       /* Pointers to buffers */
slouken@1895
    45
unsigned long SDL_MintAudio_audiosize;  /* Length of audio buffer=spec->size */
slouken@1895
    46
volatile unsigned short SDL_MintAudio_numbuf;   /* Buffer to play */
patmandin@1819
    47
volatile unsigned short SDL_MintAudio_mutex;
patmandin@1819
    48
volatile unsigned long SDL_MintAudio_clocktics;
slouken@1895
    49
cookie_stfa_t *SDL_MintAudio_stfa;
slouken@398
    50
patmandin@1111
    51
/* MiNT thread variables */
patmandin@1111
    52
SDL_bool SDL_MintAudio_mint_present;
patmandin@1111
    53
SDL_bool SDL_MintAudio_quit_thread;
patmandin@1111
    54
SDL_bool SDL_MintAudio_thread_finished;
patmandin@1111
    55
long SDL_MintAudio_thread_pid;
patmandin@1111
    56
patmandin@644
    57
/* The callback function, called by each driver whenever needed */
slouken@398
    58
slouken@1895
    59
void
slouken@1895
    60
SDL_MintAudio_Callback(void)
slouken@398
    61
{
slouken@1895
    62
    Uint8 *buffer;
slouken@1895
    63
    SDL_AudioDevice *audio = SDL_MintAudio_device;
slouken@398
    64
slouken@1895
    65
    buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
slouken@1895
    66
    SDL_memset(buffer, audio->spec.silence, audio->spec.size);
patmandin@1034
    67
slouken@1895
    68
    if (audio->paused)
slouken@1895
    69
        return;
patmandin@1034
    70
slouken@1895
    71
    if (audio->convert.needed) {
slouken@1895
    72
        int silence;
slouken@398
    73
slouken@1895
    74
        if (audio->convert.src_format == AUDIO_U8) {
slouken@1895
    75
            silence = 0x80;
slouken@1895
    76
        } else {
slouken@1895
    77
            silence = 0;
slouken@1895
    78
        }
slouken@1895
    79
        SDL_memset(audio->convert.buf, silence, audio->convert.len);
slouken@1895
    80
        audio->spec.callback(audio->spec.userdata,
slouken@1895
    81
                             (Uint8 *) audio->convert.buf,
slouken@1895
    82
                             audio->convert.len);
slouken@1895
    83
        SDL_ConvertAudio(&audio->convert);
slouken@1895
    84
        SDL_memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
slouken@1895
    85
    } else {
slouken@1895
    86
        audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
slouken@1895
    87
    }
slouken@398
    88
}
slouken@398
    89
patmandin@961
    90
/* Add a new frequency/clock/predivisor to the current list */
slouken@1895
    91
void
slouken@1895
    92
SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock,
slouken@1895
    93
                           Uint32 prediv, int gpio_bits)
patmandin@961
    94
{
slouken@1895
    95
    int i, p;
slouken@1895
    96
slouken@1895
    97
    if (MINTAUDIO_freqcount == MINTAUDIO_maxfreqs) {
slouken@1895
    98
        return;
slouken@1895
    99
    }
patmandin@961
   100
slouken@1895
   101
    /* Search where to insert the frequency (highest first) */
slouken@1895
   102
    for (p = 0; p < MINTAUDIO_freqcount; p++) {
slouken@1895
   103
        if (frequency > MINTAUDIO_frequencies[p].frequency) {
slouken@1895
   104
            break;
slouken@1895
   105
        }
slouken@1895
   106
    }
patmandin@961
   107
slouken@1895
   108
    /* Put all following ones farer */
slouken@1895
   109
    if (MINTAUDIO_freqcount > 0) {
slouken@1895
   110
        for (i = MINTAUDIO_freqcount; i > p; i--) {
slouken@1895
   111
            SDL_memcpy(&MINTAUDIO_frequencies[i],
slouken@1895
   112
                       &MINTAUDIO_frequencies[i - 1],
slouken@1895
   113
                       sizeof(mint_frequency_t));
slouken@1895
   114
        }
slouken@1895
   115
    }
patmandin@961
   116
slouken@1895
   117
    /* And insert new one */
slouken@1895
   118
    MINTAUDIO_frequencies[p].frequency = frequency;
slouken@1895
   119
    MINTAUDIO_frequencies[p].masterclock = clock;
slouken@1895
   120
    MINTAUDIO_frequencies[p].predivisor = prediv;
slouken@1895
   121
    MINTAUDIO_frequencies[p].gpio_bits = gpio_bits;
patmandin@961
   122
slouken@1895
   123
    MINTAUDIO_freqcount++;
patmandin@961
   124
}
patmandin@961
   125
patmandin@961
   126
/* Search for the nearest frequency */
slouken@1895
   127
int
slouken@1895
   128
SDL_MintAudio_SearchFrequency(_THIS, int desired_freq)
slouken@398
   129
{
slouken@1895
   130
    int i;
slouken@398
   131
slouken@1895
   132
    /* Only 1 freq ? */
slouken@1895
   133
    if (MINTAUDIO_freqcount == 1) {
slouken@1895
   134
        return 0;
slouken@1895
   135
    }
slouken@398
   136
slouken@1895
   137
    /* Check the array */
slouken@1895
   138
    for (i = 0; i < MINTAUDIO_freqcount; i++) {
slouken@1895
   139
        if (desired_freq >= ((MINTAUDIO_frequencies[i].frequency +
slouken@1895
   140
                              MINTAUDIO_frequencies[i + 1].frequency) >> 1)) {
slouken@1895
   141
            return i;
slouken@1895
   142
        }
slouken@1895
   143
    }
slouken@398
   144
slouken@1895
   145
    /* Not in the array, give the latest */
slouken@1895
   146
    return MINTAUDIO_freqcount - 1;
slouken@398
   147
}
patmandin@1111
   148
patmandin@2027
   149
/* Check if FPU is present */
slouken@2043
   150
void
slouken@2043
   151
SDL_MintAudio_CheckFpu(void)
patmandin@2027
   152
{
slouken@2043
   153
    unsigned long cookie_fpu;
patmandin@2027
   154
slouken@2043
   155
    SDL_MintAudio_hasfpu = 0;
slouken@2043
   156
    if (Getcookie(C__FPU, &cookie_fpu) != C_FOUND) {
slouken@2043
   157
        return;
slouken@2043
   158
    }
slouken@2043
   159
    switch ((cookie_fpu >> 16) & 0xfffe) {
slouken@2043
   160
    case 2:
slouken@2043
   161
    case 4:
slouken@2043
   162
    case 6:
slouken@2043
   163
    case 8:
slouken@2043
   164
    case 16:
slouken@2043
   165
        SDL_MintAudio_hasfpu = 1;
slouken@2043
   166
        break;
slouken@2043
   167
    }
patmandin@2027
   168
}
patmandin@2027
   169
patmandin@1111
   170
/* The thread function, used under MiNT with xbios */
slouken@1895
   171
int
slouken@1895
   172
SDL_MintAudio_Thread(long param)
patmandin@1111
   173
{
slouken@1895
   174
    SndBufPtr pointers;
slouken@1895
   175
    SDL_bool buffers_filled[2] = { SDL_FALSE, SDL_FALSE };
patmandin@1111
   176
slouken@1895
   177
    SDL_MintAudio_thread_finished = SDL_FALSE;
slouken@1895
   178
    while (!SDL_MintAudio_quit_thread) {
slouken@1895
   179
        if (Buffptr(&pointers) != 0)
slouken@1895
   180
            continue;
patmandin@1111
   181
slouken@1895
   182
        if (((unsigned long) pointers.play >=
slouken@1895
   183
             (unsigned long) SDL_MintAudio_audiobuf[0])
slouken@1895
   184
            && ((unsigned long) pointers.play <=
slouken@1895
   185
                (unsigned long) SDL_MintAudio_audiobuf[1])) {
slouken@1895
   186
            /* DMA is reading buffer #0, setup buffer #1 if not already done */
slouken@1895
   187
            if (!buffers_filled[1]) {
slouken@1895
   188
                SDL_MintAudio_numbuf = 1;
slouken@1895
   189
                SDL_MintAudio_Callback();
slouken@1895
   190
                Setbuffer(0, SDL_MintAudio_audiobuf[1],
slouken@1895
   191
                          SDL_MintAudio_audiobuf[1] +
slouken@1895
   192
                          SDL_MintAudio_audiosize);
slouken@1895
   193
                buffers_filled[1] = SDL_TRUE;
slouken@1895
   194
                buffers_filled[0] = SDL_FALSE;
slouken@1895
   195
            }
slouken@1895
   196
        } else {
slouken@1895
   197
            /* DMA is reading buffer #1, setup buffer #0 if not already done */
slouken@1895
   198
            if (!buffers_filled[0]) {
slouken@1895
   199
                SDL_MintAudio_numbuf = 0;
slouken@1895
   200
                SDL_MintAudio_Callback();
slouken@1895
   201
                Setbuffer(0, SDL_MintAudio_audiobuf[0],
slouken@1895
   202
                          SDL_MintAudio_audiobuf[0] +
slouken@1895
   203
                          SDL_MintAudio_audiosize);
slouken@1895
   204
                buffers_filled[0] = SDL_TRUE;
slouken@1895
   205
                buffers_filled[1] = SDL_FALSE;
slouken@1895
   206
            }
slouken@1895
   207
        }
patmandin@1111
   208
slouken@1895
   209
        usleep(100);
slouken@1895
   210
    }
slouken@1895
   211
    SDL_MintAudio_thread_finished = SDL_TRUE;
slouken@1895
   212
    return 0;
patmandin@1111
   213
}
patmandin@1111
   214
slouken@1895
   215
void
slouken@1895
   216
SDL_MintAudio_WaitThread(void)
patmandin@1111
   217
{
slouken@1895
   218
    if (!SDL_MintAudio_mint_present)
slouken@1895
   219
        return;
patmandin@1111
   220
slouken@1895
   221
    if (SDL_MintAudio_thread_finished)
slouken@1895
   222
        return;
patmandin@1111
   223
slouken@1895
   224
    SDL_MintAudio_quit_thread = SDL_TRUE;
slouken@1895
   225
    while (!SDL_MintAudio_thread_finished) {
slouken@1895
   226
        Syield();
slouken@1895
   227
    }
patmandin@1111
   228
}
slouken@1895
   229
slouken@1895
   230
/* vi: set ts=4 sw=4 expandtab: */