src/audio/macrom/SDL_romaudio.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
icculus@1133
    24
#if defined(__APPLE__) && defined(__MACH__)
icculus@1133
    25
#  include <Carbon/Carbon.h>
icculus@1133
    26
#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
slouken@0
    27
#  include <Carbon.h>
slouken@0
    28
#else
slouken@1662
    29
#  include <Sound.h>            /* SoundManager interface */
slouken@0
    30
#  include <Gestalt.h>
slouken@323
    31
#  include <DriverServices.h>
slouken@0
    32
#endif
slouken@0
    33
icculus@1133
    34
#if !defined(NewSndCallBackUPP) && (UNIVERSAL_INTERFACES_VERSION < 0x0335)
slouken@1662
    35
#if !defined(NewSndCallBackProc)        /* avoid circular redefinition... */
icculus@1133
    36
#define NewSndCallBackUPP NewSndCallBackProc
icculus@1133
    37
#endif
icculus@1135
    38
#if !defined(NewSndCallBackUPP)
icculus@1135
    39
#define NewSndCallBackUPP NewSndCallBackProc
icculus@1135
    40
#endif
icculus@1133
    41
#endif
icculus@1133
    42
slouken@0
    43
#include "SDL_audio.h"
slouken@1361
    44
#include "../SDL_audio_c.h"
slouken@1361
    45
#include "../SDL_sysaudio.h"
slouken@0
    46
#include "SDL_romaudio.h"
slouken@0
    47
slouken@0
    48
/* Audio driver functions */
slouken@0
    49
slouken@1668
    50
static void Mac_CloseAudio(_THIS);
slouken@1668
    51
static int Mac_OpenAudio(_THIS, SDL_AudioSpec * spec);
slouken@1668
    52
static void Mac_LockAudio(_THIS);
slouken@1668
    53
static void Mac_UnlockAudio(_THIS);
slouken@0
    54
slouken@0
    55
/* Audio driver bootstrap functions */
slouken@0
    56
slouken@0
    57
slouken@1662
    58
static int
slouken@1668
    59
Audio_Available(void)
slouken@0
    60
{
slouken@1662
    61
    return (1);
slouken@0
    62
}
slouken@0
    63
slouken@1662
    64
static void
slouken@1668
    65
Audio_DeleteDevice(SDL_AudioDevice * device)
slouken@0
    66
{
slouken@1668
    67
    SDL_free(device->hidden);
slouken@1668
    68
    SDL_free(device);
slouken@0
    69
}
slouken@0
    70
slouken@1662
    71
static SDL_AudioDevice *
slouken@1668
    72
Audio_CreateDevice(int devindex)
slouken@0
    73
{
slouken@0
    74
    SDL_AudioDevice *this;
slouken@0
    75
slouken@0
    76
    /* Initialize all variables that we clean on shutdown */
slouken@1668
    77
    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
slouken@1662
    78
    if (this) {
slouken@1668
    79
        SDL_memset(this, 0, (sizeof *this));
slouken@0
    80
        this->hidden = (struct SDL_PrivateAudioData *)
slouken@1668
    81
            SDL_malloc((sizeof *this->hidden));
slouken@0
    82
    }
slouken@1662
    83
    if ((this == NULL) || (this->hidden == NULL)) {
slouken@1668
    84
        SDL_OutOfMemory();
slouken@1662
    85
        if (this) {
slouken@1668
    86
            SDL_free(this);
slouken@0
    87
        }
slouken@1662
    88
        return (0);
slouken@0
    89
    }
slouken@1668
    90
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
slouken@0
    91
slouken@0
    92
    /* Set the function pointers */
slouken@1662
    93
    this->OpenAudio = Mac_OpenAudio;
slouken@1662
    94
    this->CloseAudio = Mac_CloseAudio;
slouken@1662
    95
    this->LockAudio = Mac_LockAudio;
slouken@323
    96
    this->UnlockAudio = Mac_UnlockAudio;
slouken@1662
    97
    this->free = Audio_DeleteDevice;
slouken@0
    98
slouken@1662
    99
#ifdef __MACOSX__               /* Mac OS X uses threaded audio, so normal thread code is okay */
slouken@1662
   100
    this->LockAudio = NULL;
slouken@348
   101
    this->UnlockAudio = NULL;
slouken@348
   102
#endif
slouken@0
   103
    return this;
slouken@0
   104
}
slouken@0
   105
slouken@0
   106
AudioBootStrap SNDMGR_bootstrap = {
slouken@1662
   107
    "sndmgr", "MacOS SoundManager 3.0",
slouken@1662
   108
    Audio_Available, Audio_CreateDevice
slouken@0
   109
};
slouken@0
   110
slouken@323
   111
#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
slouken@1621
   112
/* This works correctly on Mac OS X */
slouken@323
   113
slouken@323
   114
#pragma options align=power
slouken@323
   115
slouken@323
   116
static volatile SInt32 audio_is_locked = 0;
slouken@323
   117
static volatile SInt32 need_to_mix = 0;
slouken@0
   118
slouken@1662
   119
static UInt8 *buffer[2];
slouken@0
   120
static volatile UInt32 running = 0;
slouken@0
   121
static CmpSoundHeader header;
slouken@323
   122
static volatile Uint32 fill_me = 0;
slouken@323
   123
slouken@1662
   124
static void
slouken@1668
   125
mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer)
slouken@323
   126
{
slouken@1662
   127
    if (!audio->paused) {
slouken@1402
   128
#ifdef __MACOSX__
slouken@1668
   129
        SDL_mutexP(audio->mixer_lock);
slouken@348
   130
#endif
slouken@1662
   131
        if (audio->convert.needed) {
slouken@1668
   132
            audio->spec.callback(audio->spec.userdata,
slouken@1668
   133
                                 (Uint8 *) audio->convert.buf,
slouken@1668
   134
                                 audio->convert.len);
slouken@1668
   135
            SDL_ConvertAudio(&audio->convert);
slouken@1662
   136
            if (audio->convert.len_cvt != audio->spec.size) {
slouken@1662
   137
                /* Uh oh... probably crashes here */ ;
slouken@323
   138
            }
slouken@1668
   139
            SDL_memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
slouken@323
   140
        } else {
slouken@1668
   141
            audio->spec.callback(audio->spec.userdata, buffer,
slouken@1668
   142
                                 audio->spec.size);
slouken@323
   143
        }
slouken@1402
   144
#ifdef __MACOSX__
slouken@1668
   145
        SDL_mutexV(audio->mixer_lock);
slouken@348
   146
#endif
slouken@323
   147
    }
slouken@323
   148
slouken@1668
   149
    DecrementAtomic((SInt32 *) & need_to_mix);
slouken@323
   150
}
slouken@323
   151
slouken@1662
   152
static void
slouken@1668
   153
Mac_LockAudio(_THIS)
slouken@323
   154
{
slouken@1668
   155
    IncrementAtomic((SInt32 *) & audio_is_locked);
slouken@323
   156
}
slouken@323
   157
slouken@1662
   158
static void
slouken@1668
   159
Mac_UnlockAudio(_THIS)
slouken@323
   160
{
slouken@323
   161
    SInt32 oldval;
slouken@1662
   162
slouken@1668
   163
    oldval = DecrementAtomic((SInt32 *) & audio_is_locked);
slouken@1662
   164
    if (oldval != 1)            /* != 1 means audio is still locked. */
slouken@323
   165
        return;
slouken@323
   166
slouken@323
   167
    /* Did we miss the chance to mix in an interrupt? Do it now. */
slouken@1668
   168
    if (BitAndAtomic(0xFFFFFFFF, (UInt32 *) & need_to_mix)) {
slouken@323
   169
        /*
slouken@323
   170
         * Note that this could be a problem if you missed an interrupt
slouken@323
   171
         *  while the audio was locked, and get preempted by a second
slouken@323
   172
         *  interrupt here, but that means you locked for way too long anyhow.
slouken@323
   173
         */
slouken@1668
   174
        mix_buffer(this, buffer[fill_me]);
slouken@323
   175
    }
slouken@323
   176
}
slouken@0
   177
slouken@1662
   178
static void
slouken@1668
   179
callBackProc(SndChannel * chan, SndCommand * cmd_passed)
slouken@1662
   180
{
slouken@1662
   181
    UInt32 play_me;
slouken@1662
   182
    SndCommand cmd;
slouken@1662
   183
    SDL_AudioDevice *audio = (SDL_AudioDevice *) chan->userInfo;
slouken@323
   184
slouken@1668
   185
    IncrementAtomic((SInt32 *) & need_to_mix);
slouken@323
   186
slouken@1662
   187
    fill_me = cmd_passed->param2;       /* buffer that has just finished playing, so fill it */
slouken@1662
   188
    play_me = !fill_me;         /* filled buffer to play _now_ */
slouken@0
   189
slouken@1662
   190
    if (!audio->enabled) {
slouken@1662
   191
        return;
slouken@1662
   192
    }
slouken@47
   193
slouken@1662
   194
    /* queue previously mixed buffer for playback. */
slouken@1662
   195
    header.samplePtr = (Ptr) buffer[play_me];
slouken@1662
   196
    cmd.cmd = bufferCmd;
slouken@1662
   197
    cmd.param1 = 0;
slouken@1662
   198
    cmd.param2 = (long) &header;
slouken@1668
   199
    SndDoCommand(chan, &cmd, 0);
slouken@47
   200
slouken@1668
   201
    memset(buffer[fill_me], 0, audio->spec.size);
slouken@323
   202
slouken@1662
   203
    /*
slouken@1662
   204
     * if audio device isn't locked, mix the next buffer to be queued in
slouken@1662
   205
     *  the memory block that just finished playing.
slouken@1662
   206
     */
slouken@1668
   207
    if (!BitAndAtomic(0xFFFFFFFF, (UInt32 *) & audio_is_locked)) {
slouken@1668
   208
        mix_buffer(audio, buffer[fill_me]);
slouken@1662
   209
    }
slouken@1662
   210
slouken@1662
   211
    /* set this callback to run again when current buffer drains. */
slouken@1662
   212
    if (running) {
slouken@1662
   213
        cmd.cmd = callBackCmd;
slouken@1662
   214
        cmd.param1 = 0;
slouken@1662
   215
        cmd.param2 = play_me;
slouken@1662
   216
slouken@1668
   217
        SndDoCommand(chan, &cmd, 0);
slouken@1662
   218
    }
slouken@0
   219
}
slouken@0
   220
slouken@1662
   221
static int
slouken@1668
   222
Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
slouken@1662
   223
{
slouken@0
   224
slouken@1662
   225
    SndCallBackUPP callback;
slouken@1662
   226
    int sample_bits;
slouken@1662
   227
    int i;
slouken@1662
   228
    long initOptions;
slouken@1662
   229
slouken@1662
   230
    /* Very few conversions are required, but... */
slouken@0
   231
    switch (spec->format) {
slouken@1662
   232
    case AUDIO_S8:
slouken@0
   233
        spec->format = AUDIO_U8;
slouken@0
   234
        break;
slouken@1662
   235
    case AUDIO_U16LSB:
slouken@0
   236
        spec->format = AUDIO_S16LSB;
slouken@0
   237
        break;
slouken@1662
   238
    case AUDIO_U16MSB:
slouken@0
   239
        spec->format = AUDIO_S16MSB;
slouken@0
   240
        break;
slouken@0
   241
    }
slouken@1668
   242
    SDL_CalculateAudioSpec(spec);
slouken@1662
   243
slouken@0
   244
    /* initialize bufferCmd header */
slouken@1668
   245
    memset(&header, 0, sizeof(header));
slouken@1668
   246
    callback = (SndCallBackUPP) NewSndCallBackUPP(callBackProc);
slouken@0
   247
    sample_bits = spec->size / spec->samples / spec->channels * 8;
slouken@0
   248
slouken@0
   249
#ifdef DEBUG_AUDIO
slouken@1668
   250
    fprintf(stderr,
slouken@1668
   251
            "Audio format 0x%x, channels = %d, sample_bits = %d, frequency = %d\n",
slouken@1668
   252
            spec->format, spec->channels, sample_bits, spec->freq);
slouken@0
   253
#endif /* DEBUG_AUDIO */
slouken@1662
   254
slouken@0
   255
    header.numChannels = spec->channels;
slouken@1662
   256
    header.sampleSize = sample_bits;
slouken@1662
   257
    header.sampleRate = spec->freq << 16;
slouken@1662
   258
    header.numFrames = spec->samples;
slouken@1662
   259
    header.encode = cmpSH;
slouken@1662
   260
slouken@0
   261
    /* Note that we install the 16bitLittleEndian Converter if needed. */
slouken@1662
   262
    if (spec->format == 0x8010) {
slouken@0
   263
        header.compressionID = fixedCompression;
slouken@0
   264
        header.format = k16BitLittleEndianFormat;
slouken@0
   265
    }
slouken@1662
   266
slouken@0
   267
    /* allocate 2 buffers */
slouken@1662
   268
    for (i = 0; i < 2; i++) {
slouken@1668
   269
        buffer[i] = (UInt8 *) malloc(sizeof(UInt8) * spec->size);
slouken@1662
   270
        if (buffer[i] == NULL) {
slouken@1668
   271
            SDL_OutOfMemory();
slouken@1662
   272
            return (-1);
slouken@1662
   273
        }
slouken@1668
   274
        memset(buffer[i], 0, spec->size);
slouken@0
   275
    }
slouken@1662
   276
slouken@1662
   277
    /* Create the sound manager channel */
slouken@1668
   278
    channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
slouken@1662
   279
    if (channel == NULL) {
slouken@1668
   280
        SDL_OutOfMemory();
slouken@1662
   281
        return (-1);
slouken@1662
   282
    }
slouken@1662
   283
    if (spec->channels >= 2) {
slouken@0
   284
        initOptions = initStereo;
slouken@0
   285
    } else {
slouken@0
   286
        initOptions = initMono;
slouken@0
   287
    }
slouken@1662
   288
    channel->userInfo = (long) this;
slouken@0
   289
    channel->qLength = 128;
slouken@1668
   290
    if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) {
slouken@1668
   291
        SDL_SetError("Unable to create audio channel");
slouken@1668
   292
        SDL_free(channel);
slouken@0
   293
        channel = NULL;
slouken@1662
   294
        return (-1);
slouken@0
   295
    }
slouken@1662
   296
slouken@1662
   297
    /* start playback */
slouken@1662
   298
    {
slouken@1662
   299
        SndCommand cmd;
slouken@1662
   300
        cmd.cmd = callBackCmd;
slouken@1662
   301
        cmd.param2 = 0;
slouken@1662
   302
        running = 1;
slouken@1668
   303
        SndDoCommand(channel, &cmd, 0);
slouken@1662
   304
    }
slouken@1662
   305
slouken@1662
   306
    return 1;
slouken@0
   307
}
slouken@0
   308
slouken@1662
   309
static void
slouken@1668
   310
Mac_CloseAudio(_THIS)
slouken@1662
   311
{
slouken@1662
   312
slouken@1662
   313
    int i;
slouken@1662
   314
slouken@1662
   315
    running = 0;
slouken@1662
   316
slouken@1662
   317
    if (channel) {
slouken@1668
   318
        SndDisposeChannel(channel, true);
slouken@1662
   319
        channel = NULL;
slouken@1662
   320
    }
slouken@1662
   321
slouken@1662
   322
    for (i = 0; i < 2; ++i) {
slouken@1662
   323
        if (buffer[i]) {
slouken@1668
   324
            SDL_free(buffer[i]);
slouken@0
   325
            buffer[i] = NULL;
slouken@0
   326
        }
slouken@0
   327
    }
slouken@0
   328
}
slouken@0
   329
slouken@323
   330
#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */
slouken@323
   331
slouken@1662
   332
static void
slouken@1668
   333
Mac_LockAudio(_THIS)
slouken@323
   334
{
slouken@323
   335
    /* no-op. */
slouken@323
   336
}
slouken@323
   337
slouken@1662
   338
static void
slouken@1668
   339
Mac_UnlockAudio(_THIS)
slouken@323
   340
{
slouken@323
   341
    /* no-op. */
slouken@323
   342
}
slouken@323
   343
slouken@0
   344
slouken@0
   345
/* This function is called by Sound Manager when it has exhausted one of
slouken@0
   346
   the buffers, so we'll zero it to silence and fill it with audio if
slouken@0
   347
   we're not paused.
slouken@0
   348
*/
slouken@1662
   349
static pascal void
slouken@1668
   350
sndDoubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr newbuf)
slouken@0
   351
{
slouken@1662
   352
    SDL_AudioDevice *audio = (SDL_AudioDevice *) newbuf->dbUserInfo[0];
slouken@0
   353
slouken@0
   354
    /* If audio is quitting, don't do anything */
slouken@1662
   355
    if (!audio->enabled) {
slouken@0
   356
        return;
slouken@0
   357
    }
slouken@1668
   358
    memset(newbuf->dbSoundData, 0, audio->spec.size);
slouken@0
   359
    newbuf->dbNumFrames = audio->spec.samples;
slouken@1662
   360
    if (!audio->paused) {
slouken@1662
   361
        if (audio->convert.needed) {
slouken@1668
   362
            audio->spec.callback(audio->spec.userdata,
slouken@1668
   363
                                 (Uint8 *) audio->convert.buf,
slouken@1668
   364
                                 audio->convert.len);
slouken@1668
   365
            SDL_ConvertAudio(&audio->convert);
slouken@0
   366
#if 0
slouken@1662
   367
            if (audio->convert.len_cvt != audio->spec.size) {
slouken@1662
   368
                /* Uh oh... probably crashes here */ ;
slouken@0
   369
            }
slouken@0
   370
#endif
slouken@1668
   371
            SDL_memcpy(newbuf->dbSoundData, audio->convert.buf,
slouken@1668
   372
                       audio->convert.len_cvt);
slouken@0
   373
        } else {
slouken@1668
   374
            audio->spec.callback(audio->spec.userdata,
slouken@1668
   375
                                 (Uint8 *) newbuf->dbSoundData,
slouken@1668
   376
                                 audio->spec.size);
slouken@0
   377
        }
slouken@0
   378
    }
slouken@1662
   379
    newbuf->dbFlags |= dbBufferReady;
slouken@0
   380
}
slouken@0
   381
slouken@1662
   382
static int
slouken@1668
   383
DoubleBufferAudio_Available(void)
slouken@0
   384
{
slouken@0
   385
    int available;
slouken@0
   386
    NumVersion sndversion;
slouken@0
   387
    long response;
slouken@0
   388
slouken@0
   389
    available = 0;
slouken@1668
   390
    sndversion = SndSoundManagerVersion();
slouken@1662
   391
    if (sndversion.majorRev >= 3) {
slouken@1668
   392
        if (Gestalt(gestaltSoundAttr, &response) == noErr) {
slouken@1662
   393
            if ((response & (1 << gestaltSndPlayDoubleBuffer))) {
slouken@0
   394
                available = 1;
slouken@0
   395
            }
slouken@0
   396
        }
slouken@0
   397
    } else {
slouken@1668
   398
        if (Gestalt(gestaltSoundAttr, &response) == noErr) {
slouken@1662
   399
            if ((response & (1 << gestaltHasASC))) {
slouken@0
   400
                available = 1;
slouken@0
   401
            }
slouken@0
   402
        }
slouken@0
   403
    }
slouken@1662
   404
    return (available);
slouken@0
   405
}
slouken@0
   406
slouken@1662
   407
static void
slouken@1668
   408
Mac_CloseAudio(_THIS)
slouken@0
   409
{
slouken@0
   410
    int i;
slouken@0
   411
slouken@1662
   412
    if (channel != NULL) {
slouken@0
   413
        /* Clean up the audio channel */
slouken@1668
   414
        SndDisposeChannel(channel, true);
slouken@0
   415
        channel = NULL;
slouken@0
   416
    }
slouken@1662
   417
    for (i = 0; i < 2; ++i) {
slouken@1662
   418
        if (audio_buf[i]) {
slouken@1668
   419
            SDL_free(audio_buf[i]);
slouken@0
   420
            audio_buf[i] = NULL;
slouken@0
   421
        }
slouken@0
   422
    }
slouken@0
   423
}
slouken@0
   424
slouken@1662
   425
static int
slouken@1668
   426
Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
slouken@0
   427
{
slouken@0
   428
    SndDoubleBufferHeader2 audio_dbh;
slouken@0
   429
    int i;
slouken@0
   430
    long initOptions;
slouken@0
   431
    int sample_bits;
slouken@0
   432
    SndDoubleBackUPP doubleBackProc;
slouken@0
   433
slouken@0
   434
    /* Check to make sure double-buffered audio is available */
slouken@1668
   435
    if (!DoubleBufferAudio_Available()) {
slouken@1668
   436
        SDL_SetError("Sound manager doesn't support double-buffering");
slouken@1662
   437
        return (-1);
slouken@0
   438
    }
slouken@0
   439
slouken@0
   440
    /* Very few conversions are required, but... */
slouken@0
   441
    switch (spec->format) {
slouken@1662
   442
    case AUDIO_S8:
slouken@0
   443
        spec->format = AUDIO_U8;
slouken@0
   444
        break;
slouken@1662
   445
    case AUDIO_U16LSB:
slouken@0
   446
        spec->format = AUDIO_S16LSB;
slouken@0
   447
        break;
slouken@1662
   448
    case AUDIO_U16MSB:
slouken@0
   449
        spec->format = AUDIO_S16MSB;
slouken@0
   450
        break;
slouken@0
   451
    }
slouken@1668
   452
    SDL_CalculateAudioSpec(spec);
slouken@0
   453
slouken@0
   454
    /* initialize the double-back header */
slouken@1668
   455
    SDL_memset(&audio_dbh, 0, sizeof(audio_dbh));
slouken@1668
   456
    doubleBackProc = NewSndDoubleBackProc(sndDoubleBackProc);
slouken@0
   457
    sample_bits = spec->size / spec->samples / spec->channels * 8;
slouken@1662
   458
slouken@0
   459
    audio_dbh.dbhNumChannels = spec->channels;
slouken@1662
   460
    audio_dbh.dbhSampleSize = sample_bits;
slouken@0
   461
    audio_dbh.dbhCompressionID = 0;
slouken@1662
   462
    audio_dbh.dbhPacketSize = 0;
slouken@1662
   463
    audio_dbh.dbhSampleRate = spec->freq << 16;
slouken@1662
   464
    audio_dbh.dbhDoubleBack = doubleBackProc;
slouken@1662
   465
    audio_dbh.dbhFormat = 0;
slouken@0
   466
slouken@0
   467
    /* Note that we install the 16bitLittleEndian Converter if needed. */
slouken@1662
   468
    if (spec->format == 0x8010) {
slouken@0
   469
        audio_dbh.dbhCompressionID = fixedCompression;
slouken@0
   470
        audio_dbh.dbhFormat = k16BitLittleEndianFormat;
slouken@0
   471
    }
slouken@0
   472
slouken@0
   473
    /* allocate the 2 double-back buffers */
slouken@1662
   474
    for (i = 0; i < 2; ++i) {
slouken@1668
   475
        audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer) + spec->size);
slouken@1662
   476
        if (audio_buf[i] == NULL) {
slouken@1668
   477
            SDL_OutOfMemory();
slouken@1662
   478
            return (-1);
slouken@0
   479
        }
slouken@0
   480
        audio_buf[i]->dbNumFrames = spec->samples;
slouken@0
   481
        audio_buf[i]->dbFlags = dbBufferReady;
slouken@1662
   482
        audio_buf[i]->dbUserInfo[0] = (long) this;
slouken@0
   483
        audio_dbh.dbhBufferPtr[i] = audio_buf[i];
slouken@0
   484
    }
slouken@0
   485
slouken@0
   486
    /* Create the sound manager channel */
slouken@1668
   487
    channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
slouken@1662
   488
    if (channel == NULL) {
slouken@1668
   489
        SDL_OutOfMemory();
slouken@1662
   490
        return (-1);
slouken@0
   491
    }
slouken@1662
   492
    if (spec->channels >= 2) {
slouken@0
   493
        initOptions = initStereo;
slouken@0
   494
    } else {
slouken@0
   495
        initOptions = initMono;
slouken@0
   496
    }
slouken@0
   497
    channel->userInfo = 0;
slouken@0
   498
    channel->qLength = 128;
slouken@1668
   499
    if (SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr) {
slouken@1668
   500
        SDL_SetError("Unable to create audio channel");
slouken@1668
   501
        SDL_free(channel);
slouken@0
   502
        channel = NULL;
slouken@1662
   503
        return (-1);
slouken@0
   504
    }
slouken@1662
   505
slouken@0
   506
    /* Start playback */
slouken@1668
   507
    if (SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr) & audio_dbh)
slouken@1662
   508
        != noErr) {
slouken@1668
   509
        SDL_SetError("Unable to play double buffered audio");
slouken@1662
   510
        return (-1);
slouken@0
   511
    }
slouken@1662
   512
slouken@0
   513
    return 1;
slouken@0
   514
}
slouken@0
   515
slouken@323
   516
#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */
slouken@1662
   517
/* vi: set ts=4 sw=4 expandtab: */