ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Irix/audio_irix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/Irix/audio_irix.cpp (file contents):
Revision 1.6 by cebix, 2002-02-07T16:10:56Z vs.
Revision 1.7 by cebix, 2003-07-12T11:04:38Z

# Line 40 | Line 40
40   #include "debug.h"
41  
42  
43 + // The currently selected audio parameters (indices in audio_sample_rates[]
44 + // etc. vectors)
45 + static int audio_sample_rate_index = 0;
46 + static int audio_sample_size_index = 0;
47 + static int audio_channel_count_index = 0;
48 +
49   // Global variables
50   static int audio_fd = -1;                                                       // fd from audio library
51   static sem_t audio_irq_done_sem;                                        // Signal from interrupt to streaming thread: data block read
# Line 52 | Line 58 | static pthread_attr_t stream_thread_attr
58   static bool stream_thread_active = false;                       // Flag: streaming thread installed
59   static volatile bool stream_thread_cancel = false;      // Flag: cancel streaming thread
60  
61 + static bool current_main_mute = false;                          // Flag: output muted
62 + static bool current_speaker_mute = false;                       // Flag: speaker muted
63 + static uint32 current_main_volume = 0;                          // Output volume
64 + static uint32 current_speaker_volume = 0;                       // Speaker volume
65 +
66   // IRIX libaudio control structures
67   static ALconfig config;
68   static ALport   port;
# Line 59 | Line 70 | static ALport   port;
70  
71   // Prototypes
72   static void *stream_func(void *arg);
73 + static uint32 read_volume(void);
74 + static bool read_mute(void);
75 + static void set_mute(bool mute);
76  
77  
78   /*
# Line 68 | Line 82 | static void *stream_func(void *arg);
82   // Set AudioStatus to reflect current audio stream format
83   static void set_audio_status_format(void)
84   {
85 <        AudioStatus.sample_rate = audio_sample_rates[0];
86 <        AudioStatus.sample_size = audio_sample_sizes[0];
87 <        AudioStatus.channels = audio_channel_counts[0];
85 >        AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
86 >        AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
87 >        AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
88   }
89  
90 < // Init libaudio, returns false on error
77 < bool audio_init_al(void)
90 > bool open_audio(void)
91   {
92          ALpv     pv[2];
93  
94          printf("Using libaudio audio output\n");
95  
96 <        // Try to open the audio library
96 >        // Get supported sample formats
97 >
98 >        if (audio_sample_sizes.empty()) {
99 >                // All sample sizes are supported
100 >                audio_sample_sizes.push_back(8);
101 >                audio_sample_sizes.push_back(16);
102 >
103 >                // Assume at least two channels are supported.  Some IRIX boxes
104 >                // can do 4 or more...  MacOS only handles up to 2.
105 >                audio_channel_counts.push_back(1);
106 >                audio_channel_counts.push_back(2);
107 >
108 >                if (audio_sample_sizes.empty() || audio_channel_counts.empty()) {
109 >                        WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
110 >                        alClosePort(port);
111 >                        audio_fd = -1;
112 >                        return false;
113 >                }
114 >
115 >                audio_sample_rates.push_back( 8000 << 16);
116 >                audio_sample_rates.push_back(11025 << 16);
117 >                audio_sample_rates.push_back(22050 << 16);
118 >                audio_sample_rates.push_back(44100 << 16);
119 >
120 >                // Default to highest supported values
121 >                audio_sample_rate_index = audio_sample_rates.size() - 1;
122 >                audio_sample_size_index = audio_sample_sizes.size() - 1;
123 >                audio_channel_count_index = audio_channel_counts.size() - 1;
124 >        }
125 >
126 >        // Set the sample format
127  
128 +        D(bug("Size %d, channels %d, rate %d\n",
129 +                  audio_sample_sizes[audio_sample_size_index],
130 +                  audio_channel_counts[audio_channel_count_index],
131 +                  audio_sample_rates[audio_sample_rate_index] >> 16));
132          config = alNewConfig();
133          alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP);
134 <        alSetWidth(config, AL_SAMPLE_16);
135 <        alSetChannels(config, 2);       // stereo
134 >        if (audio_sample_sizes[audio_sample_size_index] == 8) {
135 >                alSetWidth(config, AL_SAMPLE_8);
136 >        }
137 >        else {
138 >                alSetWidth(config, AL_SAMPLE_16);
139 >        }
140 >        alSetChannels(config, audio_channel_counts[audio_channel_count_index]);
141          alSetDevice(config, AL_DEFAULT_OUTPUT); // Allow selecting via prefs?
142          
143 +        // Try to open the audio library
144 +
145          port = alOpenPort("BasiliskII", "w", config);
146          if (port == NULL) {
147                  fprintf(stderr, "ERROR: Cannot open audio port: %s\n",
148                                  alGetErrorString(oserror()));
149 +                WarningAlert(GetString(STR_NO_AUDIO_WARN));
150                  return false;
151          }
152 <
152 >        
153          // Set the sample rate
154  
155          pv[0].param = AL_RATE;
156 <        pv[0].value.ll = alDoubleToFixed(audio_sample_rates[0] >> 16);
156 >        pv[0].value.ll = alDoubleToFixed(audio_sample_rates[audio_sample_rate_index] >> 16);
157          pv[1].param = AL_MASTER_CLOCK;
158          pv[1].value.i = AL_CRYSTAL_MCLK_TYPE;
159          if (alSetParams(AL_DEFAULT_OUTPUT, pv, 2) < 0) {
# Line 108 | Line 163 | bool audio_init_al(void)
163                  return false;
164          }
165  
111        // TODO:  list all supported sample formats?
112
113        // Set AudioStatus again because we now know more about the sound
114        // system's capabilities
115        set_audio_status_format();
116
166          // Compute sound buffer size and libaudio refill point
167  
168          config = alGetConfig(port);
# Line 124 | Line 173 | bool audio_init_al(void)
173                  alClosePort(port);
174                  return false;
175          }
176 <        D(bug("alGetQueueSize %d\n", audio_frames_per_block));
176 >        D(bug("alGetQueueSize %d, width %d, channels %d\n",
177 >                  audio_frames_per_block,
178 >                  alGetWidth(config),
179 >                  alGetChannels(config)));
180 >
181 >        // Put a limit on the Mac sound buffer size, to decrease delay
182 > #define AUDIO_BUFFER_MSEC 50    // milliseconds of sound to buffer
183 >        int target_frames_per_block =
184 >                (audio_sample_rates[audio_sample_rate_index] >> 16) *
185 >                AUDIO_BUFFER_MSEC / 1000;
186 >        if (audio_frames_per_block > target_frames_per_block)
187 >                audio_frames_per_block = target_frames_per_block;
188 >        D(bug("frames per block %d\n", audio_frames_per_block));
189  
190          alZeroFrames(port, audio_frames_per_block);     // so we don't underflow
191  
192 <        // Put a limit on the Mac sound buffer size, to decrease delay
193 <        if (audio_frames_per_block > 2048)
194 <                audio_frames_per_block = 2048;
134 <        // Try to keep the buffer pretty full.  5000 samples of slack works well.
135 <        sound_buffer_fill_point = alGetQueueSize(config) - 5000;
192 >        // Try to keep the buffer pretty full
193 >        sound_buffer_fill_point = alGetQueueSize(config) -
194 >                2 * audio_frames_per_block;
195          if (sound_buffer_fill_point < 0)
196                  sound_buffer_fill_point = alGetQueueSize(config) / 3;
197          D(bug("fill point %d\n", sound_buffer_fill_point));
198  
199 <        sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
199 >        sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) *
200 >                audio_channel_counts[audio_channel_count_index] *
201 >                audio_frames_per_block;
202 >        set_audio_status_format();
203  
204          // Get a file descriptor we can select() on
205  
# Line 149 | Line 211 | bool audio_init_al(void)
211                  return false;
212          }
213  
214 <        return true;
215 < }
214 >        // Initialize volume, mute settings
215 >        current_main_volume = current_speaker_volume = read_volume();
216 >        current_main_mute = current_speaker_mute = read_mute();
217  
218  
219 < /*
220 < *  Initialization
221 < */
219 >        // Start streaming thread
220 >        Set_pthread_attr(&stream_thread_attr, 0);
221 >        stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
222 >
223 >        // Everything went fine
224 >        audio_open = true;
225 >        return true;
226 > }
227  
228   void AudioInit(void)
229   {
230 <        // Init audio status (defaults) and feature flags
231 <        audio_sample_rates.push_back(44100 << 16);
232 <        audio_sample_sizes.push_back(16);
233 <        audio_channel_counts.push_back(2);
166 <        set_audio_status_format();
230 >        // Init audio status (reasonable defaults) and feature flags
231 >        AudioStatus.sample_rate = 44100 << 16;
232 >        AudioStatus.sample_size = 16;
233 >        AudioStatus.channels = 2;
234          AudioStatus.mixer = 0;
235          AudioStatus.num_sources = 0;
236          audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
# Line 172 | Line 239 | void AudioInit(void)
239          if (PrefsFindBool("nosound"))
240                  return;
241  
175        // Try to open audio library
176        if (!audio_init_al())
177                        return;
178
242          // Init semaphore
243          if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
244                  return;
245          sem_inited = true;
246  
247 <        // Start streaming thread
248 <        Set_pthread_attr(&stream_thread_attr, 0);
186 <        stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
187 <
188 <        // Everything OK
189 <        audio_open = true;
247 >        // Open and initialize audio device
248 >        open_audio();
249   }
250  
251  
# Line 194 | Line 253 | void AudioInit(void)
253   *  Deinitialization
254   */
255  
256 < void AudioExit(void)
256 > static void close_audio(void)
257   {
258          // Stop stream and delete semaphore
259          if (stream_thread_active) {
# Line 204 | Line 263 | void AudioExit(void)
263   #endif
264                  pthread_join(stream_thread, NULL);
265                  stream_thread_active = false;
266 +                stream_thread_cancel = false;
267          }
208        if (sem_inited)
209                sem_destroy(&audio_irq_done_sem);
268  
269          // Close audio library
270          alClosePort(port);
271 +
272 +        audio_open = false;
273 + }
274 +
275 + void AudioExit(void)
276 + {
277 +        // Close audio device
278 +        close_audio();
279 +
280 +        // Delete semaphore
281 +        if (sem_inited) {
282 +                sem_destroy(&audio_irq_done_sem);
283 +                sem_inited = false;
284 +        }
285   }
286  
287  
# Line 239 | Line 311 | void audio_exit_stream()
311  
312   static void *stream_func(void *arg)
313   {
314 <        int16 *last_buffer = new int16[sound_buffer_size / 2];
314 >        int32 *last_buffer = new int32[sound_buffer_size / 4];
315          fd_set audio_fdset;
316          int    numfds, was_error;
317  
# Line 257 | Line 329 | static void *stream_func(void *arg)
329                          sem_wait(&audio_irq_done_sem);
330                          D(bug("stream: ack received\n"));
331  
260                        uint32 apple_stream_info;       // Mac address of SoundComponentData struct describing next buffer
332                          // Get size of audio data
333 <                        apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
334 <
335 <                        if (apple_stream_info) {
333 >                        uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
334 >                        if (!current_main_mute &&
335 >                                !current_speaker_mute &&
336 >                                apple_stream_info) {
337                                  int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
338                                  D(bug("stream: work_size %d\n", work_size));
339                                  if (work_size > sound_buffer_size)
# Line 269 | Line 341 | static void *stream_func(void *arg)
341                                  if (work_size == 0)
342                                          goto silence;
343  
344 <                                // Send data to audio library
345 <                                if (work_size == sound_buffer_size)
344 >                                // Send data to audio library.  Convert 8-bit data
345 >                                // unsigned->signed, using same algorithm as audio_amiga.cpp.
346 >                                // It works fine for 8-bit mono, but not stereo.
347 >                                if (AudioStatus.sample_size == 8) {
348 >                                        uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
349 >                                        uint32 *q = (uint32 *)last_buffer;
350 >                                        int r = work_size >> 2;
351 >                                        // XXX not quite right....
352 >                                        while (r--)
353 >                                                *q++ = *p++ ^ 0x80808080;
354 >                                        if (work_size != sound_buffer_size)
355 >                                                memset((uint8 *)last_buffer + work_size, silence_byte, sound_buffer_size - work_size);
356 >                                        alWriteFrames(port, last_buffer, audio_frames_per_block);
357 >                                }
358 >                                else if (work_size == sound_buffer_size)
359                                          alWriteFrames(port, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), audio_frames_per_block);
360                                  else {
361                                          // Last buffer
# Line 314 | Line 399 | static void *stream_func(void *arg)
399  
400  
401   /*
402 + * Read or set the current output volume using the audio library
403 + */
404 +
405 + static uint32 read_volume(void)
406 + {
407 +        ALpv x[2];
408 +        ALfixed gain[8];
409 +        double maxgain, mingain;
410 +        ALparamInfo pi;
411 +        uint32 ret = 0x01000100;        // default, maximum value
412 +        int dev = alGetDevice(config);
413 +
414 +        // Fetch the maximum and minimum gain settings
415 +
416 +        alGetParamInfo(dev, AL_GAIN, &pi);
417 +        maxgain = alFixedToDouble(pi.max.ll);
418 +        mingain = alFixedToDouble(pi.min.ll);
419 + //      printf("maxgain = %lf dB, mingain = %lf dB\n", maxgain, mingain);
420 +
421 +        // Get the current gain values
422 +
423 +        x[0].param = AL_GAIN;
424 +        x[0].value.ptr = gain;
425 +        x[0].sizeIn = sizeof(gain) / sizeof(gain[0]);
426 +        x[1].param = AL_CHANNELS;
427 +        if (alGetParams(dev, x, 2) < 0) {
428 +                printf("alGetParams failed: %s\n", alGetErrorString(oserror()));
429 +        }
430 +        else {
431 +                if (x[0].sizeOut < 0) {
432 +                        printf("AL_GAIN was an unrecognized parameter\n");
433 +                }
434 +                else {
435 +                        double v;
436 +                        uint32 left, right;
437 +
438 +                        // Left
439 +                        v = alFixedToDouble(gain[0]);
440 +                        if (v < mingain)
441 +                                v = mingain;    // handle gain == -inf
442 +                        v = (v - mingain) / (maxgain - mingain); // scale to 0..1
443 +                        left = (uint32)(v * (double)256); // convert to 8.8 fixed point
444 +
445 +                        // Right
446 +                        if (x[0].sizeOut <= 1) {        // handle a mono interface
447 +                                right = left;
448 +                        }
449 +                        else {
450 +                                v = alFixedToDouble(gain[1]);
451 +                                if (v < mingain)
452 +                                        v = mingain; // handle gain == -inf
453 +                                v = (v - mingain) / (maxgain - mingain); // scale to 0..1
454 +                                right = (uint32)(v * (double)256); // convert to 8.8 fixed point
455 +                        }
456 +
457 +                        ret = (left << 16) | right;
458 +                }
459 +        }
460 +
461 +        return ret;
462 + }
463 +
464 + static void set_volume(uint32 vol)
465 + {
466 +        ALpv x[1];
467 +        ALfixed gain[2];                        // left and right
468 +        double maxgain, mingain;
469 +        ALparamInfo pi;
470 +        int dev = alGetDevice(config);
471 +
472 +        // Fetch the maximum and minimum gain settings
473 +
474 +        alGetParamInfo(dev, AL_GAIN, &pi);
475 +        maxgain = alFixedToDouble(pi.max.ll);
476 +        mingain = alFixedToDouble(pi.min.ll);          
477 +
478 +        // Set the new gain values
479 +
480 +        x[0].param = AL_GAIN;
481 +        x[0].value.ptr = gain;
482 +        x[0].sizeIn = sizeof(gain) / sizeof(gain[0]);
483 +
484 +        uint32 left = vol >> 16;
485 +        uint32 right = vol & 0xffff;
486 +        double lv, rv;
487 +
488 +        if (left == 0 && pi.specialVals & AL_NEG_INFINITY_BIT) {
489 +                lv = AL_NEG_INFINITY;
490 +        }
491 +        else {
492 +                lv = ((double)left / 256) * (maxgain - mingain) + mingain;
493 +        }
494 +
495 +        if (right == 0 && pi.specialVals & AL_NEG_INFINITY_BIT) {
496 +                rv = AL_NEG_INFINITY;
497 +        }
498 +        else {
499 +                rv = ((double)right / 256) * (maxgain - mingain) + mingain;
500 +        }
501 +
502 +        D(bug("set_volume:  left=%lf dB, right=%lf dB\n", lv, rv));
503 +
504 +        gain[0] = alDoubleToFixed(lv);
505 +        gain[1] = alDoubleToFixed(rv);
506 +
507 +        if (alSetParams(dev, x, 1) < 0) {
508 +                printf("alSetParams failed: %s\n", alGetErrorString(oserror()));
509 +        }
510 + }
511 +
512 +
513 + /*
514 + * Read or set the mute setting using the audio library
515 + */
516 +
517 + static bool read_mute(void)
518 + {
519 +        bool ret;
520 +        int dev = alGetDevice(config);
521 +        ALpv x;
522 +        x.param = AL_MUTE;
523 +
524 +        if (alGetParams(dev, &x, 1) < 0) {
525 +                printf("alSetParams failed: %s\n", alGetErrorString(oserror()));
526 +                return current_main_mute; // Or just return false?
527 +        }
528 +
529 +        ret = x.value.i;
530 +
531 +        D(bug("read_mute:  mute=%d\n", ret));
532 +        return ret;
533 + }
534 +
535 + static void set_mute(bool mute)
536 + {
537 +        D(bug("set_mute: mute=%ld\n", mute));
538 +
539 +        int dev = alGetDevice(config);
540 +        ALpv x;
541 +        x.param = AL_MUTE;
542 +        x.value.i = mute;
543 +
544 +        if (alSetParams(dev, &x, 1) < 0) {
545 +                printf("alSetParams failed: %s\n", alGetErrorString(oserror()));
546 +        }
547 + }
548 +
549 +
550 +
551 + /*
552   *  MacOS audio interrupt, read next data block
553   */
554  
# Line 339 | Line 574 | void AudioInterrupt(void)
574  
575   /*
576   *  Set sampling parameters
577 < *  "index" is an index into the audio_sample_rates[] etc. arrays
577 > *  "index" is an index into the audio_sample_rates[] etc. vectors
578   *  It is guaranteed that AudioStatus.num_sources == 0
579   */
580  
581   bool audio_set_sample_rate(int index)
582   {
583 <        return true;
583 >        close_audio();
584 >        audio_sample_rate_index = index;
585 >        return open_audio();
586   }
587  
588   bool audio_set_sample_size(int index)
589   {
590 <        return true;
590 >        close_audio();
591 >        audio_sample_size_index = index;
592 >        return open_audio();
593   }
594  
595   bool audio_set_channels(int index)
596   {
597 <        return true;
597 >        close_audio();
598 >        audio_channel_count_index = index;
599 >        return open_audio();
600   }
601  
602  
# Line 367 | Line 608 | bool audio_set_channels(int index)
608  
609   bool audio_get_main_mute(void)
610   {
611 <        return false;
611 >        D(bug("audio_get_main_mute:  mute=%ld\n", current_main_mute));
612 >
613 >        return current_main_mute;
614   }
615  
616   uint32 audio_get_main_volume(void)
617   {
618 <        return 0x01000100;
618 >        uint32 ret = current_main_volume;
619 >
620 >        D(bug("audio_get_main_volume:  vol=0x%x\n", ret));
621 >
622 >        return ret;
623   }
624  
625   bool audio_get_speaker_mute(void)
626   {
627 <        return false;
627 >        D(bug("audio_get_speaker_mute:  mute=%ld\n", current_speaker_mute));
628 >
629 >        return current_speaker_mute;
630   }
631  
632   uint32 audio_get_speaker_volume(void)
633   {
634 <        return 0x01000100;
634 >        uint32 ret = current_speaker_volume;
635 >
636 >        D(bug("audio_get_speaker_volume:  vol=0x%x\n", ret));
637 >
638 >        return ret;
639   }
640  
641   void audio_set_main_mute(bool mute)
642   {
643 +        D(bug("audio_set_main_mute: mute=%ld\n", mute));
644 +
645 +        if (mute != current_main_mute) {
646 +                current_main_mute = mute;
647 +        }
648 +
649 +        set_mute(current_main_mute);
650   }
651  
652   void audio_set_main_volume(uint32 vol)
653   {
654 +
655 +        D(bug("audio_set_main_volume:  vol=%x\n", vol));
656 +
657 +        current_main_volume = vol;
658 +
659 +        set_volume(vol);
660   }
661  
662   void audio_set_speaker_mute(bool mute)
663   {
664 +        D(bug("audio_set_speaker_mute: mute=%ld\n", mute));
665 +
666 +        if (mute != current_speaker_mute) {
667 +                current_speaker_mute = mute;
668 +        }
669 +
670 +        set_mute(current_speaker_mute);
671   }
672  
673   void audio_set_speaker_volume(uint32 vol)
674   {
675 +        D(bug("audio_set_speaker_volume:  vol=%x\n", vol));
676 +
677 +        current_speaker_volume = vol;
678 +
679 +        set_volume(vol);
680   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines