Subversion Repositories psp

[/] [trunk/] [neopop/] [System_PSP/] [psplib/] [audio.c] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 34 jack
/** PSP helper library ***************************************/
2
/**                                                         **/
3
/**                          audio.c                        **/
4
/**                                                         **/
5
/** This file contains the audio rendering library. It is   **/
6
/** based almost entirely on the pspaudio library by Adresd **/
7
/** and Marcus R. Brown, 2005.                              **/
8
/**                                                         **/
9
/** Akop Karapetyan 2007                                    **/
10
/*************************************************************/
11
#include "audio.h"
12
 
13
#include <stdio.h>
14
#include <pspaudio.h>
15 9 jack
#include <pspthreadman.h>
16 34 jack
#include <string.h>
17 24 jack
#include <malloc.h>
18 34 jack
 
19
#define AUDIO_CHANNELS       1
20
#define DEFAULT_SAMPLE_COUNT 512
21
 
22
static int AudioReady;
23
static volatile int StopAudio;
24 24 jack
static int SampleCount;
25 34 jack
 
26
typedef struct {
27
  int ThreadHandle;
28
  int Handle;
29
  int LeftVolume;
30
  int RightVolume;
31
  pspAudioCallback Callback;
32
  void *Userdata;
33
} ChannelInfo;
34 145 jack
 
35
static int DirectHandle;
36 24 jack
static ChannelInfo AudioStatus[AUDIO_CHANNELS];
37
static short *AudioBuffer[AUDIO_CHANNELS][2];
38 34 jack
 
39 24 jack
static int AudioChannelThread(int args, void *argp);
40 34 jack
static void FreeBuffers();
41
static int OutputBlocking(unsigned int channel,
42 24 jack
  unsigned int vol1, unsigned int vol2, void *buf, int length);
43 34 jack
 
44
int pspAudioInit(int sample_count)
45
{
46
  int i, j, failed;
47
 
48 24 jack
  StopAudio = 0;
49 145 jack
  AudioReady = 0;
50
  DirectHandle = -1;
51 34 jack
 
52
  for (i = 0; i < AUDIO_CHANNELS; i++)
53
  {
54
    AudioStatus[i].Handle = -1;
55
    AudioStatus[i].ThreadHandle = -1;
56 88 jack
    AudioStatus[i].LeftVolume = PSP_AUDIO_MAX_VOLUME;
57
    AudioStatus[i].RightVolume = PSP_AUDIO_MAX_VOLUME;
58 34 jack
    AudioStatus[i].Callback = NULL;
59
    AudioStatus[i].Userdata = NULL;
60
 
61
    for (j = 0; j < 2; j++)
62
      AudioBuffer[i][j] = NULL;
63
  }
64 145 jack
 
65
  DirectHandle = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL,
66
    DEFAULT_SAMPLE_COUNT, PSP_AUDIO_FORMAT_STEREO);
67
 
68
  /* No callback */
69
  if ((SampleCount = sample_count) == 0)
70
    return 1;
71
 
72
  /* Check sample count */
73
  if ((SampleCount = sample_count) < 0)
74 34 jack
    SampleCount = DEFAULT_SAMPLE_COUNT;
75 24 jack
  SampleCount = PSP_AUDIO_SAMPLE_ALIGN(SampleCount);
76 145 jack
 
77
  /* Initialize buffers */
78 34 jack
  for (i = 0; i < AUDIO_CHANNELS; i++)
79
  {
80
    for (j = 0; j < 2; j++)
81
    {
82
      if (!(AudioBuffer[i][j] = (short*)malloc(SampleCount * 2 * sizeof(short))))
83
      {
84
        FreeBuffers();
85
        return 0;
86
      }
87
    }
88
  }
89 145 jack
 
90
  /* Initialize channels */
91 34 jack
  for (i = 0, failed = 0; i < AUDIO_CHANNELS; i++)
92
  {
93
    AudioStatus[i].Handle = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL,
94
      SampleCount, PSP_AUDIO_FORMAT_STEREO);
95
 
96
    if (AudioStatus[i].Handle < 0)
97
    {
98
      failed = 1;
99
      break;
100 24 jack
    }
101 34 jack
  }
102 145 jack
 
103
  if (!failed)
104
          DirectHandle = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL,
105
            SampleCount, PSP_AUDIO_FORMAT_STEREO);
106
 
107 34 jack
  if (failed)
108
  {
109
    for (i = 0; i < AUDIO_CHANNELS; i++)
110 24 jack
    {
111 34 jack
      if (AudioStatus[i].Handle != -1)
112
      {
113
        sceAudioChRelease(AudioStatus[i].Handle);
114
        AudioStatus[i].Handle = -1;
115
      }
116
    }
117 145 jack
 
118
    if (DirectHandle != -1)
119
      sceAudioChRelease(DirectHandle);
120
 
121 34 jack
    FreeBuffers();
122
    return 0;
123
  }
124
 
125
  AudioReady = 1;
126
 
127
  char label[16];
128
  strcpy(label, "audiotX");
129
 
130
  for (i = 0; i < AUDIO_CHANNELS; i++)
131
  {
132
    label[6] = '0' + i;
133
    AudioStatus[i].ThreadHandle =
134
      sceKernelCreateThread(label, (void*)&AudioChannelThread, 0x12, 0x10000,
135
        0, NULL);
136
 
137
    if (AudioStatus[i].ThreadHandle < 0)
138
    {
139 24 jack
      AudioStatus[i].ThreadHandle = -1;
140
      failed = 1;
141
      break;
142
    }
143 34 jack
 
144
    if (sceKernelStartThread(AudioStatus[i].ThreadHandle, sizeof(i), &i) != 0)
145 24 jack
    {
146
      failed = 1;
147
      break;
148
    }
149 34 jack
  }
150
 
151
  if (failed)
152 24 jack
  {
153
    StopAudio = 1;
154 34 jack
    for (i = 0; i < AUDIO_CHANNELS; i++)
155
    {
156
      if (AudioStatus[i].ThreadHandle != -1)
157 24 jack
      {
158
        //sceKernelWaitThreadEnd(AudioStatus[i].threadhandle,NULL);
159
        sceKernelDeleteThread(AudioStatus[i].ThreadHandle);
160
      }
161 34 jack
 
162 24 jack
      AudioStatus[i].ThreadHandle = -1;
163
    }
164 34 jack
 
165 24 jack
    AudioReady = 0;
166 34 jack
    FreeBuffers();
167 24 jack
    return 0;
168
  }
169 34 jack
 
170
  return SampleCount;
171 24 jack
}
172 34 jack
 
173
void pspAudioShutdown()
174
{
175 24 jack
  int i;
176
  AudioReady = 0;
177
  StopAudio = 1;
178 9 jack
 
179 34 jack
  for (i = 0; i < AUDIO_CHANNELS; i++)
180 24 jack
  {
181 34 jack
    if (AudioStatus[i].ThreadHandle != -1)
182 24 jack
    {
183
      //sceKernelWaitThreadEnd(AudioStatus[i].threadhandle,NULL);
184
      sceKernelDeleteThread(AudioStatus[i].ThreadHandle);
185
    }
186 34 jack
 
187 24 jack
    AudioStatus[i].ThreadHandle = -1;
188
  }
189 9 jack
 
190 34 jack
  for (i = 0; i < AUDIO_CHANNELS; i++)
191
  {
192
    if (AudioStatus[i].Handle != -1)
193 24 jack
    {
194
      sceAudioChRelease(AudioStatus[i].Handle);
195
      AudioStatus[i].Handle = -1;
196
    }
197
  }
198 34 jack
 
199 145 jack
  if (DirectHandle != -1)
200
  {
201
    sceAudioChRelease(DirectHandle);
202
    DirectHandle = -1;
203
  }
204
 
205 34 jack
  FreeBuffers();
206
}
207
 
208 9 jack
void pspAudioSetVolume(int channel, int left, int right)
209
{
210 24 jack
  AudioStatus[channel].LeftVolume = left;
211 34 jack
  AudioStatus[channel].RightVolume = right;
212 9 jack
}
213 34 jack
 
214 9 jack
static int AudioChannelThread(int args, void *argp)
215
{
216 24 jack
  volatile int bufidx = 0;
217 34 jack
  int channel = *(int*)argp;
218 24 jack
  int i;
219 34 jack
  unsigned int *ptr, length;
220
  void *bufptr;
221 24 jack
  pspAudioCallback callback;
222 34 jack
 
223
  for (i = 0; i < 2; i++)
224
    memset(AudioBuffer[channel][bufidx],
225 24 jack
      0, sizeof(short) * SampleCount * 2);
226 34 jack
 
227
  while (!StopAudio)
228 24 jack
  {
229
    callback = AudioStatus[channel].Callback;
230 34 jack
    bufptr = AudioBuffer[channel][bufidx];
231 24 jack
    length = SampleCount;
232 34 jack
 
233 88 jack
    if (callback) callback(bufptr, &length, AudioStatus[channel].Userdata);
234
    else for (i = 0, ptr = bufptr; i < SampleCount; i++) *(ptr++) = 0;
235 34 jack
 
236 57 jack
          OutputBlocking(channel, AudioStatus[channel].LeftVolume,
237
      AudioStatus[channel].RightVolume, bufptr, length);
238 34 jack
 
239 24 jack
    bufidx = (bufidx ? 0 : 1);
240
  }
241 34 jack
 
242 24 jack
  sceKernelExitThread(0);
243
  return 0;
244 9 jack
}
245 34 jack
 
246 145 jack
int pspAudioOutputBlocking(void *buf, unsigned int length)
247 44 jack
{
248 145 jack
  if (DirectHandle < 0) return -1;
249
 
250
  sceAudioSetChannelDataLen(DirectHandle, length);
251
  return sceAudioOutputPannedBlocking(DirectHandle, PSP_AUDIO_MAX_VOLUME,
252
    PSP_AUDIO_MAX_VOLUME, buf);
253 44 jack
}
254
 
255 145 jack
int pspAudioOutput(void *buf, unsigned int length)
256
{
257
  if (DirectHandle < 0) return -1;
258
 
259
  sceAudioSetChannelDataLen(DirectHandle, length);
260
  return sceAudioOutputPanned(DirectHandle, PSP_AUDIO_MAX_VOLUME,
261
    PSP_AUDIO_MAX_VOLUME, buf);
262
}
263
 
264 57 jack
static int OutputBlocking(unsigned int channel,
265 24 jack
  unsigned int vol1, unsigned int vol2, void *buf, int length)
266 9 jack
{
267 24 jack
  if (!AudioReady) return -1;
268
  if (channel >= AUDIO_CHANNELS) return -1;
269 88 jack
  if (vol1 > PSP_AUDIO_MAX_VOLUME) vol1 = PSP_AUDIO_MAX_VOLUME;
270
  if (vol2 > PSP_AUDIO_MAX_VOLUME) vol2 = PSP_AUDIO_MAX_VOLUME;
271 34 jack
 
272 106 jack
  sceAudioSetChannelDataLen(AudioStatus[channel].Handle, length);
273 34 jack
  return sceAudioOutputPannedBlocking(AudioStatus[channel].Handle,
274 24 jack
    vol1, vol2, buf);
275 9 jack
}
276 34 jack
 
277
static void FreeBuffers()
278
{
279
  int i, j;
280
 
281
  for (i = 0; i < AUDIO_CHANNELS; i++)
282
  {
283
    for (j = 0; j < 2; j++)
284
    {
285
      if (AudioBuffer[i][j])
286
      {
287
        free(AudioBuffer[i][j]);
288
        AudioBuffer[i][j] = NULL;
289
      }
290
    }
291
  }
292
}
293
 
294 24 jack
void pspAudioSetChannelCallback(int channel, pspAudioCallback callback, void *userdata)
295 9 jack
{
296 24 jack
  volatile ChannelInfo *pci = &AudioStatus[channel];
297
  pci->Callback = NULL;
298
  pci->Userdata = userdata;
299
  pci->Callback = callback;
300 9 jack
}
301 88 jack
 
302
int pspAudioGetSampleCount()
303
{
304
  return SampleCount;
305
}
306