This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_umsaudio.c
563 lines (496 loc) · 17.5 KB
1
2
3
4
5
/* I'm gambling no one uses this audio backend...we'll see who emails. :) */
#error this code has not been updated for SDL 1.3.
#error if no one emails icculus at icculus.org and tells him that this
#error code is needed, this audio backend will eventually be removed from SDL.
6
/*
7
SDL - Simple DirectMedia Layer
8
Copyright (C) 1997-2011 Sam Lantinga
9
10
This library is free software; you can redistribute it and/or
11
modify it under the terms of the GNU Lesser General Public
12
License as published by the Free Software Foundation; either
13
version 2.1 of the License, or (at your option) any later version.
14
15
16
17
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
Lesser General Public License for more details.
19
20
21
22
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24
25
26
27
28
Carsten Griwodz
griff@kom.tu-darmstadt.de
based on linux/SDL_dspaudio.c by Sam Lantinga
*/
29
#include "SDL_config.h"
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Allow access to a raw mixing buffer */
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "SDL_audio.h"
43
#include "../SDL_audio_c.h"
44
45
46
47
48
49
50
51
#include "SDL_umsaudio.h"
/* The tag name used by UMS audio */
#define UMS_DRIVER_NAME "ums"
#define DEBUG_AUDIO 1
/* Audio driver functions */
52
static int UMS_OpenAudio(_THIS, SDL_AudioSpec * spec);
53
54
55
56
static void UMS_PlayAudio(_THIS);
static Uint8 *UMS_GetAudioBuf(_THIS);
static void UMS_CloseAudio(_THIS);
57
58
static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode,
long flags);
59
static UMSAudioDevice_ReturnCode UADClose(_THIS);
60
static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long *bits);
61
static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits);
62
63
static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate,
long *set_rate);
64
65
66
67
68
69
static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order);
static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt);
static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt);
static UMSAudioDevice_ReturnCode UADInitialize(_THIS);
static UMSAudioDevice_ReturnCode UADStart(_THIS);
static UMSAudioDevice_ReturnCode UADStop(_THIS);
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS,
UMSAudioTypes_TimeFormat
fmt);
static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long *buff_size);
static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long *buff_size);
static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long *buff_size);
static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes,
long *bytes_ret);
static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume);
static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance);
static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels);
static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block);
static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output,
long *left_gain,
long *right_gain);
static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer * buff,
long samples,
long *samples_written);
88
89
/* Audio driver bootstrap functions */
90
91
static int
Audio_Available(void)
92
93
94
95
{
return 1;
}
96
97
static void
Audio_DeleteDevice(_THIS)
98
{
99
100
101
102
103
if (this->hidden->playbuf._buffer)
SDL_free(this->hidden->playbuf._buffer);
if (this->hidden->fillbuf._buffer)
SDL_free(this->hidden->fillbuf._buffer);
_somFree(this->hidden->umsdev);
104
105
SDL_free(this->hidden);
SDL_free(this);
106
107
}
108
109
static SDL_AudioDevice *
Audio_CreateDevice(int devindex)
110
111
112
113
114
115
116
{
SDL_AudioDevice *this;
/*
* Allocate and initialize management storage and private management
* storage for this SDL-using library.
*/
117
118
this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
if (this) {
119
SDL_memset(this, 0, (sizeof *this));
120
121
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
122
}
123
if ((this == NULL) || (this->hidden == NULL)) {
124
SDL_OutOfMemory();
125
if (this) {
126
SDL_free(this);
127
}
128
return (0);
129
}
130
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
131
132
133
134
135
136
137
#ifdef DEBUG_AUDIO
fprintf(stderr, "Creating UMS Audio device\n");
#endif
/*
* Calls for UMS env initialization and audio object construction.
*/
138
this->hidden->ev = somGetGlobalEnvironment();
139
140
141
142
143
this->hidden->umsdev = UMSAudioDeviceNew();
/*
* Set the function pointers.
*/
144
145
146
this->OpenAudio = UMS_OpenAudio;
this->WaitAudio = NULL; /* we do blocking output */
this->PlayAudio = UMS_PlayAudio;
147
this->GetAudioBuf = UMS_GetAudioBuf;
148
149
this->CloseAudio = UMS_CloseAudio;
this->free = Audio_DeleteDevice;
150
151
152
153
154
155
156
157
#ifdef DEBUG_AUDIO
fprintf(stderr, "done\n");
#endif
return this;
}
AudioBootStrap UMS_bootstrap = {
158
UMS_DRIVER_NAME, "AIX UMS audio",
159
Audio_Available, Audio_CreateDevice, 0
160
161
};
162
163
static Uint8 *
UMS_GetAudioBuf(_THIS)
164
165
166
167
168
169
170
171
172
173
174
175
176
177
{
#ifdef DEBUG_AUDIO
fprintf(stderr, "enter UMS_GetAudioBuf\n");
#endif
return this->hidden->fillbuf._buffer;
/*
long bufSize;
UMSAudioDevice_ReturnCode rc;
rc = UADSetTimeFormat(this, UMSAudioTypes_Bytes );
rc = UADWriteBuffSize(this, bufSize );
*/
}
178
179
static void
UMS_CloseAudio(_THIS)
180
181
182
183
184
185
186
187
188
189
190
{
UMSAudioDevice_ReturnCode rc;
#ifdef DEBUG_AUDIO
fprintf(stderr, "enter UMS_CloseAudio\n");
#endif
rc = UADPlayRemainingData(this, TRUE);
rc = UADStop(this);
rc = UADClose(this);
}
191
192
static void
UMS_PlayAudio(_THIS)
193
194
{
UMSAudioDevice_ReturnCode rc;
195
196
197
long samplesToWrite;
long samplesWritten;
UMSAudioTypes_Buffer swpbuf;
198
199
200
201
#ifdef DEBUG_AUDIO
fprintf(stderr, "enter UMS_PlayAudio\n");
#endif
202
203
204
205
206
207
208
209
210
211
212
213
214
215
samplesToWrite =
this->hidden->playbuf._length / this->hidden->bytesPerSample;
do {
rc = UADWrite(this, &this->hidden->playbuf,
samplesToWrite, &samplesWritten);
samplesToWrite -= samplesWritten;
/* rc values: UMSAudioDevice_Success
* UMSAudioDevice_Failure
* UMSAudioDevice_Preempted
* UMSAudioDevice_Interrupted
* UMSAudioDevice_DeviceError
*/
if (rc == UMSAudioDevice_DeviceError) {
216
#ifdef DEBUG_AUDIO
217
fprintf(stderr, "Returning from PlayAudio with devices error\n");
218
#endif
219
220
return;
}
221
} while (samplesToWrite > 0);
222
223
SDL_LockAudio();
224
225
226
227
SDL_memcpy(&swpbuf, &this->hidden->playbuf, sizeof(UMSAudioTypes_Buffer));
SDL_memcpy(&this->hidden->playbuf, &this->hidden->fillbuf,
sizeof(UMSAudioTypes_Buffer));
SDL_memcpy(&this->hidden->fillbuf, &swpbuf, sizeof(UMSAudioTypes_Buffer));
228
229
230
231
232
233
234
235
SDL_UnlockAudio();
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote audio data and swapped buffer\n");
#endif
}
#if 0
236
237
238
239
240
241
242
// /* Set the DSP frequency */
// value = spec->freq;
// if ( ioctl(this->hidden->audio_fd, SOUND_PCM_WRITE_RATE, &value) < 0 ) {
// SDL_SetError("Couldn't set audio frequency");
// return(-1);
// }
// spec->freq = value;
243
244
#endif
245
246
static int
UMS_OpenAudio(_THIS, SDL_AudioSpec * spec)
247
{
248
249
250
251
252
253
254
255
char *audiodev = "/dev/paud0";
long lgain;
long rgain;
long outRate;
long outBufSize;
long bitsPerSample;
long samplesPerSec;
long success;
256
SDL_AudioFormat test_format;
257
int frag_spec;
258
259
260
261
262
UMSAudioDevice_ReturnCode rc;
#ifdef DEBUG_AUDIO
fprintf(stderr, "enter UMS_OpenAudio\n");
#endif
263
264
265
266
rc = UADOpen(this, audiodev, "PLAY", UMSAudioDevice_BlockingIO);
if (rc != UMSAudioDevice_Success) {
SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
return -1;
267
}
268
269
rc = UADSetAudioFormatType(this, "PCM");
270
271
272
success = 0;
test_format = SDL_FirstAudioFormat(spec->format);
273
do {
274
275
276
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
277
switch (test_format) {
278
279
280
case AUDIO_U8:
/* from the mac code: better ? */
/* sample_bits = spec->size / spec->samples / spec->channels * 8; */
281
success = 1;
282
bitsPerSample = 8;
283
284
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
285
286
287
rc = UADSetNumberFormat(this, "UNSIGNED");
break;
case AUDIO_S8:
288
success = 1;
289
bitsPerSample = 8;
290
291
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
292
293
294
rc = UADSetNumberFormat(this, "SIGNED");
break;
case AUDIO_S16LSB:
295
success = 1;
296
bitsPerSample = 16;
297
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
298
299
300
301
rc = UADSetByteOrder(this, "LSB");
rc = UADSetNumberFormat(this, "SIGNED");
break;
case AUDIO_S16MSB:
302
success = 1;
303
bitsPerSample = 16;
304
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
305
306
307
308
rc = UADSetByteOrder(this, "MSB");
rc = UADSetNumberFormat(this, "SIGNED");
break;
case AUDIO_U16LSB:
309
success = 1;
310
bitsPerSample = 16;
311
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
312
313
314
315
rc = UADSetByteOrder(this, "LSB");
rc = UADSetNumberFormat(this, "UNSIGNED");
break;
case AUDIO_U16MSB:
316
success = 1;
317
bitsPerSample = 16;
318
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
319
320
321
322
323
324
rc = UADSetByteOrder(this, "MSB");
rc = UADSetNumberFormat(this, "UNSIGNED");
break;
default:
break;
}
325
if (!success) {
326
327
test_format = SDL_NextAudioFormat();
}
328
} while (!success && test_format);
329
330
if (success == 0) {
331
332
333
334
335
336
SDL_SetError("Couldn't find any hardware audio formats");
return -1;
}
spec->format = test_format;
337
338
for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
if ((0x01 << frag_spec) != spec->size) {
339
340
341
SDL_SetError("Fragment size must be a power of two");
return -1;
}
342
343
if (frag_spec > 2048)
frag_spec = 2048;
344
345
346
this->hidden->bytesPerSample = (bitsPerSample / 8) * spec->channels;
samplesPerSec = this->hidden->bytesPerSample * outRate;
347
348
this->hidden->playbuf._length = 0;
349
this->hidden->playbuf._maximum = spec->size;
350
351
this->hidden->playbuf._buffer = (unsigned char *) SDL_malloc(spec->size);
this->hidden->fillbuf._length = 0;
352
this->hidden->fillbuf._maximum = spec->size;
353
this->hidden->fillbuf._buffer = (unsigned char *) SDL_malloc(spec->size);
354
355
356
357
rc = UADSetBitsPerSample(this, bitsPerSample);
rc = UADSetDMABufferSize(this, frag_spec, &outBufSize);
rc = UADSetChannels(this, spec->channels); /* functions reduces to mono or stereo */
358
359
360
361
lgain = 100; /*maximum left input gain */
rgain = 100; /*maimum right input gain */
rc = UADEnableOutput(this, "LINE_OUT", &lgain, &rgain);
362
363
364
365
366
367
368
369
370
rc = UADInitialize(this);
rc = UADStart(this);
rc = UADSetVolume(this, 100);
rc = UADSetBalance(this, 0);
/* We're ready to rock and roll. :-) */
return 0;
}
371
372
373
static UMSAudioDevice_ReturnCode
UADGetBitsPerSample(_THIS, long *bits)
374
{
375
376
return UMSAudioDevice_get_bits_per_sample(this->hidden->umsdev,
this->hidden->ev, bits);
377
378
}
379
380
static UMSAudioDevice_ReturnCode
UADSetBitsPerSample(_THIS, long bits)
381
{
382
383
return UMSAudioDevice_set_bits_per_sample(this->hidden->umsdev,
this->hidden->ev, bits);
384
385
}
386
387
static UMSAudioDevice_ReturnCode
UADSetSampleRate(_THIS, long rate, long *set_rate)
388
389
{
/* from the mac code: sample rate = spec->freq << 16; */
390
391
return UMSAudioDevice_set_sample_rate(this->hidden->umsdev,
this->hidden->ev, rate, set_rate);
392
393
}
394
395
static UMSAudioDevice_ReturnCode
UADSetByteOrder(_THIS, string byte_order)
396
{
397
398
return UMSAudioDevice_set_byte_order(this->hidden->umsdev,
this->hidden->ev, byte_order);
399
400
}
401
402
static UMSAudioDevice_ReturnCode
UADSetAudioFormatType(_THIS, string fmt)
403
404
{
/* possible PCM, A_LAW or MU_LAW */
405
406
return UMSAudioDevice_set_audio_format_type(this->hidden->umsdev,
this->hidden->ev, fmt);
407
408
}
409
410
static UMSAudioDevice_ReturnCode
UADSetNumberFormat(_THIS, string fmt)
411
412
{
/* possible SIGNED, UNSIGNED, or TWOS_COMPLEMENT */
413
414
return UMSAudioDevice_set_number_format(this->hidden->umsdev,
this->hidden->ev, fmt);
415
416
}
417
418
static UMSAudioDevice_ReturnCode
UADInitialize(_THIS)
419
{
420
return UMSAudioDevice_initialize(this->hidden->umsdev, this->hidden->ev);
421
422
}
423
424
static UMSAudioDevice_ReturnCode
UADStart(_THIS)
425
{
426
return UMSAudioDevice_start(this->hidden->umsdev, this->hidden->ev);
427
428
}
429
430
static UMSAudioDevice_ReturnCode
UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt)
431
432
433
434
435
{
/*
* Switches the time format to the new format, immediately.
* possible UMSAudioTypes_Msecs, UMSAudioTypes_Bytes or UMSAudioTypes_Samples
*/
436
437
return UMSAudioDevice_set_time_format(this->hidden->umsdev,
this->hidden->ev, fmt);
438
439
}
440
441
static UMSAudioDevice_ReturnCode
UADWriteBuffSize(_THIS, long *buff_size)
442
443
444
445
{
/*
* returns write buffer size in the current time format
*/
446
447
return UMSAudioDevice_write_buff_size(this->hidden->umsdev,
this->hidden->ev, buff_size);
448
449
}
450
451
static UMSAudioDevice_ReturnCode
UADWriteBuffRemain(_THIS, long *buff_size)
452
453
454
455
456
{
/*
* returns amount of available space in the write buffer
* in the current time format
*/
457
458
return UMSAudioDevice_write_buff_remain(this->hidden->umsdev,
this->hidden->ev, buff_size);
459
460
}
461
462
static UMSAudioDevice_ReturnCode
UADWriteBuffUsed(_THIS, long *buff_size)
463
464
465
466
467
{
/*
* returns amount of filled space in the write buffer
* in the current time format
*/
468
469
return UMSAudioDevice_write_buff_used(this->hidden->umsdev,
this->hidden->ev, buff_size);
470
471
}
472
473
static UMSAudioDevice_ReturnCode
UADSetDMABufferSize(_THIS, long bytes, long *bytes_ret)
474
475
476
477
478
479
{
/*
* Request a new DMA buffer size, maximum requested size 2048.
* Takes effect with next initialize() call.
* Devices may or may not support DMA.
*/
480
481
482
return UMSAudioDevice_set_DMA_buffer_size(this->hidden->umsdev,
this->hidden->ev,
bytes, bytes_ret);
483
484
}
485
486
static UMSAudioDevice_ReturnCode
UADSetVolume(_THIS, long volume)
487
488
489
490
491
{
/*
* Set the volume.
* Takes effect immediately.
*/
492
493
return UMSAudioDevice_set_volume(this->hidden->umsdev,
this->hidden->ev, volume);
494
495
}
496
497
static UMSAudioDevice_ReturnCode
UADSetBalance(_THIS, long balance)
498
499
500
501
502
{
/*
* Set the balance.
* Takes effect immediately.
*/
503
504
return UMSAudioDevice_set_balance(this->hidden->umsdev,
this->hidden->ev, balance);
505
506
}
507
508
static UMSAudioDevice_ReturnCode
UADSetChannels(_THIS, long channels)
509
510
511
512
513
{
/*
* Set mono or stereo.
* Takes effect with next initialize() call.
*/
514
515
516
517
if (channels != 1)
channels = 2;
return UMSAudioDevice_set_number_of_channels(this->hidden->umsdev,
this->hidden->ev, channels);
518
519
}
520
521
static UMSAudioDevice_ReturnCode
UADOpen(_THIS, string device, string mode, long flags)
522
{
523
524
return UMSAudioDevice_open(this->hidden->umsdev,
this->hidden->ev, device, mode, flags);
525
526
}
527
528
529
static UMSAudioDevice_ReturnCode
UADWrite(_THIS, UMSAudioTypes_Buffer * buff,
long samples, long *samples_written)
530
{
531
532
533
return UMSAudioDevice_write(this->hidden->umsdev,
this->hidden->ev,
buff, samples, samples_written);
534
535
}
536
537
static UMSAudioDevice_ReturnCode
UADPlayRemainingData(_THIS, boolean block)
538
{
539
540
return UMSAudioDevice_play_remaining_data(this->hidden->umsdev,
this->hidden->ev, block);
541
542
}
543
544
static UMSAudioDevice_ReturnCode
UADStop(_THIS)
545
{
546
return UMSAudioDevice_stop(this->hidden->umsdev, this->hidden->ev);
547
548
}
549
550
static UMSAudioDevice_ReturnCode
UADClose(_THIS)
551
{
552
return UMSAudioDevice_close(this->hidden->umsdev, this->hidden->ev);
553
554
}
555
556
static UMSAudioDevice_ReturnCode
UADEnableOutput(_THIS, string output, long *left_gain, long *right_gain)
557
{
558
559
560
return UMSAudioDevice_enable_output(this->hidden->umsdev,
this->hidden->ev,
output, left_gain, right_gain);
561
562
}
563
/* vi: set ts=4 sw=4 expandtab: */