2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 griff@kom.tu-darmstadt.de
22 based on linux/SDL_dspaudio.c by Sam Lantinga
24 #include "SDL_config.h"
26 /* Allow access to a raw mixing buffer */
31 #include <sys/types.h>
33 #include <sys/ioctl.h>
37 #include "SDL_audio.h"
38 #include "../SDL_audio_c.h"
39 #include "../SDL_audiodev_c.h"
40 #include "SDL_umsaudio.h"
42 /* The tag name used by UMS audio */
43 #define UMS_DRIVER_NAME "ums"
47 /* Audio driver functions */
48 static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec);
49 static void UMS_PlayAudio(_THIS);
50 static Uint8 *UMS_GetAudioBuf(_THIS);
51 static void UMS_CloseAudio(_THIS);
53 static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode, long flags);
54 static UMSAudioDevice_ReturnCode UADClose(_THIS);
55 static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long* bits);
56 static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits);
57 static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate, long* set_rate);
58 static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order);
59 static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt);
60 static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt);
61 static UMSAudioDevice_ReturnCode UADInitialize(_THIS);
62 static UMSAudioDevice_ReturnCode UADStart(_THIS);
63 static UMSAudioDevice_ReturnCode UADStop(_THIS);
64 static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt );
65 static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long* buff_size );
66 static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long* buff_size );
67 static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long* buff_size );
68 static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes, long* bytes_ret );
69 static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume );
70 static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance );
71 static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels );
72 static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block );
73 static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output, long* left_gain, long* right_gain);
74 static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer* buff, long samples, long* samples_written);
76 /* Audio driver bootstrap functions */
77 static int Audio_Available(void)
82 static void Audio_DeleteDevice(_THIS)
84 if(this->hidden->playbuf._buffer) SDL_free(this->hidden->playbuf._buffer);
85 if(this->hidden->fillbuf._buffer) SDL_free(this->hidden->fillbuf._buffer);
86 _somFree( this->hidden->umsdev );
87 SDL_free(this->hidden);
91 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
93 SDL_AudioDevice *this;
96 * Allocate and initialize management storage and private management
97 * storage for this SDL-using library.
99 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
101 SDL_memset(this, 0, (sizeof *this));
102 this->hidden = (struct SDL_PrivateAudioData *)SDL_malloc((sizeof *this->hidden));
104 if ( (this == NULL) || (this->hidden == NULL) ) {
111 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
113 fprintf(stderr, "Creating UMS Audio device\n");
117 * Calls for UMS env initialization and audio object construction.
119 this->hidden->ev = somGetGlobalEnvironment();
120 this->hidden->umsdev = UMSAudioDeviceNew();
123 * Set the function pointers.
125 this->OpenAudio = UMS_OpenAudio;
126 this->WaitAudio = NULL; /* we do blocking output */
127 this->PlayAudio = UMS_PlayAudio;
128 this->GetAudioBuf = UMS_GetAudioBuf;
129 this->CloseAudio = UMS_CloseAudio;
130 this->free = Audio_DeleteDevice;
133 fprintf(stderr, "done\n");
138 AudioBootStrap UMS_bootstrap = {
139 UMS_DRIVER_NAME, "AIX UMS audio",
140 Audio_Available, Audio_CreateDevice
143 static Uint8 *UMS_GetAudioBuf(_THIS)
146 fprintf(stderr, "enter UMS_GetAudioBuf\n");
148 return this->hidden->fillbuf._buffer;
151 UMSAudioDevice_ReturnCode rc;
153 rc = UADSetTimeFormat(this, UMSAudioTypes_Bytes );
154 rc = UADWriteBuffSize(this, bufSize );
158 static void UMS_CloseAudio(_THIS)
160 UMSAudioDevice_ReturnCode rc;
163 fprintf(stderr, "enter UMS_CloseAudio\n");
165 rc = UADPlayRemainingData(this, TRUE);
170 static void UMS_PlayAudio(_THIS)
172 UMSAudioDevice_ReturnCode rc;
175 UMSAudioTypes_Buffer swpbuf;
178 fprintf(stderr, "enter UMS_PlayAudio\n");
180 samplesToWrite = this->hidden->playbuf._length/this->hidden->bytesPerSample;
183 rc = UADWrite(this, &this->hidden->playbuf,
186 samplesToWrite -= samplesWritten;
188 /* rc values: UMSAudioDevice_Success
189 * UMSAudioDevice_Failure
190 * UMSAudioDevice_Preempted
191 * UMSAudioDevice_Interrupted
192 * UMSAudioDevice_DeviceError
194 if ( rc == UMSAudioDevice_DeviceError ) {
196 fprintf(stderr, "Returning from PlayAudio with devices error\n");
201 while(samplesToWrite>0);
204 SDL_memcpy( &swpbuf, &this->hidden->playbuf, sizeof(UMSAudioTypes_Buffer) );
205 SDL_memcpy( &this->hidden->playbuf, &this->hidden->fillbuf, sizeof(UMSAudioTypes_Buffer) );
206 SDL_memcpy( &this->hidden->fillbuf, &swpbuf, sizeof(UMSAudioTypes_Buffer) );
210 fprintf(stderr, "Wrote audio data and swapped buffer\n");
215 // /* Set the DSP frequency */
216 // value = spec->freq;
217 // if ( ioctl(this->hidden->audio_fd, SOUND_PCM_WRITE_RATE, &value) < 0 ) {
218 // SDL_SetError("Couldn't set audio frequency");
221 // spec->freq = value;
224 static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec)
226 char* audiodev = "/dev/paud0";
236 UMSAudioDevice_ReturnCode rc;
239 fprintf(stderr, "enter UMS_OpenAudio\n");
241 rc = UADOpen(this, audiodev,"PLAY", UMSAudioDevice_BlockingIO);
242 if ( rc != UMSAudioDevice_Success ) {
243 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
247 rc = UADSetAudioFormatType(this, "PCM");
250 test_format = SDL_FirstAudioFormat(spec->format);
254 fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
256 switch ( test_format )
259 /* from the mac code: better ? */
260 /* sample_bits = spec->size / spec->samples / spec->channels * 8; */
263 rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
264 rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
265 rc = UADSetNumberFormat(this, "UNSIGNED");
270 rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
271 rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
272 rc = UADSetNumberFormat(this, "SIGNED");
277 rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
278 rc = UADSetByteOrder(this, "LSB");
279 rc = UADSetNumberFormat(this, "SIGNED");
284 rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
285 rc = UADSetByteOrder(this, "MSB");
286 rc = UADSetNumberFormat(this, "SIGNED");
291 rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
292 rc = UADSetByteOrder(this, "LSB");
293 rc = UADSetNumberFormat(this, "UNSIGNED");
298 rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
299 rc = UADSetByteOrder(this, "MSB");
300 rc = UADSetNumberFormat(this, "UNSIGNED");
306 test_format = SDL_NextAudioFormat();
309 while ( ! success && test_format );
311 if ( success == 0 ) {
312 SDL_SetError("Couldn't find any hardware audio formats");
316 spec->format = test_format;
318 for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec );
319 if ( (0x01<<frag_spec) != spec->size ) {
320 SDL_SetError("Fragment size must be a power of two");
323 if ( frag_spec > 2048 ) frag_spec = 2048;
325 this->hidden->bytesPerSample = (bitsPerSample / 8) * spec->channels;
326 samplesPerSec = this->hidden->bytesPerSample * outRate;
328 this->hidden->playbuf._length = 0;
329 this->hidden->playbuf._maximum = spec->size;
330 this->hidden->playbuf._buffer = (unsigned char*)SDL_malloc(spec->size);
331 this->hidden->fillbuf._length = 0;
332 this->hidden->fillbuf._maximum = spec->size;
333 this->hidden->fillbuf._buffer = (unsigned char*)SDL_malloc(spec->size);
335 rc = UADSetBitsPerSample(this, bitsPerSample );
336 rc = UADSetDMABufferSize(this, frag_spec, &outBufSize );
337 rc = UADSetChannels(this, spec->channels); /* functions reduces to mono or stereo */
339 lgain = 100; /*maximum left input gain*/
340 rgain = 100; /*maimum right input gain*/
341 rc = UADEnableOutput(this, "LINE_OUT",&lgain,&rgain);
342 rc = UADInitialize(this);
344 rc = UADSetVolume(this, 100);
345 rc = UADSetBalance(this, 0);
347 /* We're ready to rock and roll. :-) */
352 static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long* bits)
354 return UMSAudioDevice_get_bits_per_sample( this->hidden->umsdev,
359 static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits)
361 return UMSAudioDevice_set_bits_per_sample( this->hidden->umsdev,
366 static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate, long* set_rate)
368 /* from the mac code: sample rate = spec->freq << 16; */
369 return UMSAudioDevice_set_sample_rate( this->hidden->umsdev,
375 static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order)
377 return UMSAudioDevice_set_byte_order( this->hidden->umsdev,
382 static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt)
384 /* possible PCM, A_LAW or MU_LAW */
385 return UMSAudioDevice_set_audio_format_type( this->hidden->umsdev,
390 static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt)
392 /* possible SIGNED, UNSIGNED, or TWOS_COMPLEMENT */
393 return UMSAudioDevice_set_number_format( this->hidden->umsdev,
398 static UMSAudioDevice_ReturnCode UADInitialize(_THIS)
400 return UMSAudioDevice_initialize( this->hidden->umsdev,
404 static UMSAudioDevice_ReturnCode UADStart(_THIS)
406 return UMSAudioDevice_start( this->hidden->umsdev,
410 static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt )
413 * Switches the time format to the new format, immediately.
414 * possible UMSAudioTypes_Msecs, UMSAudioTypes_Bytes or UMSAudioTypes_Samples
416 return UMSAudioDevice_set_time_format( this->hidden->umsdev,
421 static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long* buff_size )
424 * returns write buffer size in the current time format
426 return UMSAudioDevice_write_buff_size( this->hidden->umsdev,
431 static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long* buff_size )
434 * returns amount of available space in the write buffer
435 * in the current time format
437 return UMSAudioDevice_write_buff_remain( this->hidden->umsdev,
442 static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long* buff_size )
445 * returns amount of filled space in the write buffer
446 * in the current time format
448 return UMSAudioDevice_write_buff_used( this->hidden->umsdev,
453 static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes, long* bytes_ret )
456 * Request a new DMA buffer size, maximum requested size 2048.
457 * Takes effect with next initialize() call.
458 * Devices may or may not support DMA.
460 return UMSAudioDevice_set_DMA_buffer_size( this->hidden->umsdev,
466 static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume )
470 * Takes effect immediately.
472 return UMSAudioDevice_set_volume( this->hidden->umsdev,
477 static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance )
481 * Takes effect immediately.
483 return UMSAudioDevice_set_balance( this->hidden->umsdev,
488 static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels )
491 * Set mono or stereo.
492 * Takes effect with next initialize() call.
494 if ( channels != 1 ) channels = 2;
495 return UMSAudioDevice_set_number_of_channels( this->hidden->umsdev,
500 static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode, long flags)
502 return UMSAudioDevice_open( this->hidden->umsdev,
509 static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer* buff,
511 long* samples_written)
513 return UMSAudioDevice_write( this->hidden->umsdev,
520 static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block )
522 return UMSAudioDevice_play_remaining_data( this->hidden->umsdev,
527 static UMSAudioDevice_ReturnCode UADStop(_THIS)
529 return UMSAudioDevice_stop( this->hidden->umsdev,
533 static UMSAudioDevice_ReturnCode UADClose(_THIS)
535 return UMSAudioDevice_close( this->hidden->umsdev,
539 static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output, long* left_gain, long* right_gain)
541 return UMSAudioDevice_enable_output( this->hidden->umsdev,