src/audio/psp/SDL_pspaudio.c
author Ryan C. Gordon
Wed, 18 Mar 2015 02:01:17 -0400
changeset 9394 bb28e5281770
parent 9329 64bb8e49c6a6
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Bunch of reworking to how we manage audio devices.

Device enumeration now happens at startup and then is managed exclusively
through hotplugging instead of full redetection. The device name list now has
a unique "handle" associated with each item and SDL will pass this to the
backend so they don't have to figure out how a human readable name maps to
real hardware for a second time.

Other cleanups, fixes, improvements, plus all the audio backends updated to
the new interface...largely untested at this point, though.
kimonline@7009
     1
/*
kimonline@7009
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
kimonline@7009
     4
kimonline@7009
     5
  This software is provided 'as-is', without any express or implied
kimonline@7009
     6
  warranty.  In no event will the authors be held liable for any damages
kimonline@7009
     7
  arising from the use of this software.
kimonline@7009
     8
kimonline@7009
     9
  Permission is granted to anyone to use this software for any purpose,
kimonline@7009
    10
  including commercial applications, and to alter it and redistribute it
kimonline@7009
    11
  freely, subject to the following restrictions:
kimonline@7009
    12
kimonline@7009
    13
  1. The origin of this software must not be misrepresented; you must not
kimonline@7009
    14
     claim that you wrote the original software. If you use this software
kimonline@7009
    15
     in a product, an acknowledgment in the product documentation would be
kimonline@7009
    16
     appreciated but is not required.
kimonline@7009
    17
  2. Altered source versions must be plainly marked as such, and must not be
kimonline@7009
    18
     misrepresented as being the original software.
kimonline@7009
    19
  3. This notice may not be removed or altered from any source distribution.
kimonline@7009
    20
*/
philipp@9328
    21
#include "../../SDL_internal.h"
kimonline@7009
    22
philipp@9329
    23
#if SDL_AUDIO_DRIVER_PSP
philipp@9329
    24
kimonline@7009
    25
#include <stdio.h>
kimonline@7009
    26
#include <string.h>
kimonline@7009
    27
#include <stdlib.h>
kimonline@7009
    28
#include <malloc.h>
kimonline@7009
    29
kimonline@7009
    30
#include "SDL_audio.h"
kimonline@7009
    31
#include "SDL_error.h"
kimonline@7009
    32
#include "SDL_timer.h"
kimonline@7009
    33
#include "../SDL_audiomem.h"
kimonline@7009
    34
#include "../SDL_audio_c.h"
kimonline@7009
    35
#include "../SDL_audiodev_c.h"
kimonline@7009
    36
#include "../SDL_sysaudio.h"
kimonline@7009
    37
#include "SDL_pspaudio.h"
kimonline@7009
    38
kimonline@7009
    39
#include <pspaudio.h>
kimonline@7009
    40
#include <pspthreadman.h>
kimonline@7009
    41
kimonline@7009
    42
/* The tag name used by PSP audio */
kimonline@7009
    43
#define PSPAUD_DRIVER_NAME         "psp"
kimonline@7009
    44
kimonline@7009
    45
static int
icculus@9394
    46
PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
kimonline@7009
    47
{
slouken@7191
    48
    int format, mixlen, i;
kimonline@7009
    49
    this->hidden = (struct SDL_PrivateAudioData *)
kimonline@7009
    50
        SDL_malloc(sizeof(*this->hidden));
kimonline@7009
    51
    if (this->hidden == NULL) {
icculus@7038
    52
        return SDL_OutOfMemory();
kimonline@7009
    53
    }
kimonline@7009
    54
    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
slouken@7191
    55
    switch (this->spec.format & 0xff) {
slouken@7191
    56
        case 8:
slouken@7191
    57
        case 16:
slouken@7191
    58
            this->spec.format = AUDIO_S16LSB;
slouken@7191
    59
            break;
slouken@7191
    60
        default:
slouken@7191
    61
            return SDL_SetError("Unsupported audio format");
slouken@7191
    62
    }
kimonline@7009
    63
slouken@7191
    64
    /* The sample count must be a multiple of 64. */
slouken@7191
    65
    this->spec.samples = PSP_AUDIO_SAMPLE_ALIGN(this->spec.samples);
slouken@7191
    66
    this->spec.freq = 44100;
kimonline@7009
    67
slouken@7191
    68
    /* Update the fragment size as size in bytes. */
gabomdq@7677
    69
/*  SDL_CalculateAudioSpec(this->spec); MOD */
kimonline@7009
    70
    switch (this->spec.format) {
kimonline@7009
    71
    case AUDIO_U8:
kimonline@7009
    72
        this->spec.silence = 0x80;
kimonline@7009
    73
        break;
kimonline@7009
    74
    default:
kimonline@7009
    75
        this->spec.silence = 0x00;
kimonline@7009
    76
        break;
kimonline@7009
    77
    }
kimonline@7009
    78
    this->spec.size = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
kimonline@7009
    79
    this->spec.size *= this->spec.channels;
kimonline@7009
    80
    this->spec.size *= this->spec.samples;
slouken@7191
    81
gabomdq@7678
    82
/* ========================================== */
kimonline@7009
    83
slouken@7191
    84
    /* Allocate the mixing buffer.  Its size and starting address must
slouken@7191
    85
       be a multiple of 64 bytes.  Our sample count is already a multiple of
slouken@7191
    86
       64, so spec->size should be a multiple of 64 as well. */
slouken@7191
    87
    mixlen = this->spec.size * NUM_BUFFERS;
slouken@7191
    88
    this->hidden->rawbuf = (Uint8 *) memalign(64, mixlen);
slouken@7191
    89
    if (this->hidden->rawbuf == NULL) {
slouken@7191
    90
        return SDL_SetError("Couldn't allocate mixing buffer");
slouken@7191
    91
    }
kimonline@7009
    92
slouken@7191
    93
    /* Setup the hardware channel. */
slouken@7191
    94
    if (this->spec.channels == 1) {
slouken@7191
    95
        format = PSP_AUDIO_FORMAT_MONO;
slouken@7191
    96
    } else {
slouken@7191
    97
        format = PSP_AUDIO_FORMAT_STEREO;
slouken@7191
    98
    }
slouken@7191
    99
    this->hidden->channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, this->spec.samples, format);
slouken@7191
   100
    if (this->hidden->channel < 0) {
slouken@7191
   101
        free(this->hidden->rawbuf);
slouken@7191
   102
        this->hidden->rawbuf = NULL;
slouken@7191
   103
        return SDL_SetError("Couldn't reserve hardware channel");
slouken@7191
   104
    }
kimonline@7009
   105
slouken@7191
   106
    memset(this->hidden->rawbuf, 0, mixlen);
slouken@7191
   107
    for (i = 0; i < NUM_BUFFERS; i++) {
slouken@7191
   108
        this->hidden->mixbufs[i] = &this->hidden->rawbuf[i * this->spec.size];
slouken@7191
   109
    }
kimonline@7009
   110
slouken@7191
   111
    this->hidden->next_buffer = 0;
slouken@7191
   112
    return 0;
kimonline@7009
   113
}
kimonline@7009
   114
kimonline@7009
   115
static void PSPAUD_PlayDevice(_THIS)
kimonline@7009
   116
{
slouken@7191
   117
    Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
kimonline@7009
   118
slouken@7191
   119
    if (this->spec.channels == 1) {
slouken@7191
   120
        sceAudioOutputBlocking(this->hidden->channel, PSP_AUDIO_VOLUME_MAX, mixbuf);
slouken@7191
   121
    } else {
slouken@7191
   122
        sceAudioOutputPannedBlocking(this->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, mixbuf);
slouken@7191
   123
    }
kimonline@7009
   124
slouken@7191
   125
    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
kimonline@7009
   126
}
kimonline@7009
   127
kimonline@7009
   128
/* This function waits until it is possible to write a full sound buffer */
kimonline@7009
   129
static void PSPAUD_WaitDevice(_THIS)
kimonline@7009
   130
{
slouken@7191
   131
    /* Because we block when sending audio, there's no need for this function to do anything. */
kimonline@7009
   132
}
kimonline@7009
   133
static Uint8 *PSPAUD_GetDeviceBuf(_THIS)
kimonline@7009
   134
{
slouken@7191
   135
    return this->hidden->mixbufs[this->hidden->next_buffer];
kimonline@7009
   136
}
kimonline@7009
   137
kimonline@7009
   138
static void PSPAUD_CloseDevice(_THIS)
kimonline@7009
   139
{
slouken@7191
   140
    if (this->hidden->channel >= 0) {
slouken@7191
   141
        sceAudioChRelease(this->hidden->channel);
slouken@7191
   142
        this->hidden->channel = -1;
slouken@7191
   143
    }
kimonline@7009
   144
slouken@7191
   145
    if (this->hidden->rawbuf != NULL) {
slouken@7191
   146
        free(this->hidden->rawbuf);
slouken@7191
   147
        this->hidden->rawbuf = NULL;
slouken@7191
   148
    }
kimonline@7009
   149
}
kimonline@7009
   150
static void PSPAUD_ThreadInit(_THIS)
kimonline@7009
   151
{
slouken@7191
   152
    /* Increase the priority of this audio thread by 1 to put it
slouken@7191
   153
       ahead of other SDL threads. */
slouken@7191
   154
    SceUID thid;
slouken@7191
   155
    SceKernelThreadInfo status;
slouken@7191
   156
    thid = sceKernelGetThreadId();
slouken@7191
   157
    status.size = sizeof(SceKernelThreadInfo);
slouken@7191
   158
    if (sceKernelReferThreadStatus(thid, &status) == 0) {
slouken@7191
   159
        sceKernelChangeThreadPriority(thid, status.currentPriority - 1);
slouken@7191
   160
    }
kimonline@7009
   161
}
kimonline@7009
   162
kimonline@7009
   163
kimonline@7009
   164
static int
kimonline@7009
   165
PSPAUD_Init(SDL_AudioDriverImpl * impl)
kimonline@7009
   166
{
kimonline@7009
   167
gabomdq@7677
   168
    /* Set the function pointers */
kimonline@7009
   169
    impl->OpenDevice = PSPAUD_OpenDevice;
kimonline@7009
   170
    impl->PlayDevice = PSPAUD_PlayDevice;
kimonline@7009
   171
    impl->WaitDevice = PSPAUD_WaitDevice;
slouken@7191
   172
    impl->GetDeviceBuf = PSPAUD_GetDeviceBuf;
kimonline@7009
   173
    impl->WaitDone = PSPAUD_WaitDevice;
kimonline@7009
   174
    impl->CloseDevice = PSPAUD_CloseDevice;
kimonline@7009
   175
    impl->ThreadInit = PSPAUD_ThreadInit;
slouken@7191
   176
gabomdq@7678
   177
    /* PSP audio device */
slouken@7191
   178
    impl->OnlyHasDefaultOutputDevice = 1;
kimonline@7009
   179
/*
kimonline@7009
   180
    impl->HasCaptureSupport = 1;
kimonline@7009
   181
kimonline@7009
   182
    impl->OnlyHasDefaultInputDevice = 1;
kimonline@7009
   183
*/
kimonline@7009
   184
    /*
kimonline@7009
   185
    impl->DetectDevices = DSOUND_DetectDevices;
kimonline@7009
   186
    impl->Deinitialize = DSOUND_Deinitialize;
kimonline@7009
   187
    */
kimonline@7009
   188
    return 1;   /* this audio target is available. */
kimonline@7009
   189
}
kimonline@7009
   190
kimonline@7009
   191
AudioBootStrap PSPAUD_bootstrap = {
kimonline@7009
   192
    "psp", "PSP audio driver", PSPAUD_Init, 0
kimonline@7009
   193
};
kimonline@7009
   194
gabomdq@7677
   195
 /* SDL_AUDI */
kimonline@7009
   196
philipp@9329
   197
#endif /* SDL_AUDIO_DRIVER_PSP */
kimonline@7009
   198
philipp@9329
   199
/* vi: set ts=4 sw=4 expandtab: */