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

Comparing BasiliskII/src/AmigaOS/audio_amiga.cpp (file contents):
Revision 1.3 by cebix, 1999-10-20T15:13:55Z vs.
Revision 1.12 by gbeauche, 2008-01-01T09:40:31Z

# Line 1 | Line 1
1   /*
2   *  audio_amiga.cpp - Audio support, AmigaOS implementation using AHI
3   *
4 < *  Basilisk II (C) 1997-1999 Christian Bauer
4 > *  Basilisk II (C) 1997-2008 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 23 | Line 23
23   #include <exec/types.h>
24   #include <exec/memory.h>
25   #include <devices/ahi.h>
26 + #define __USE_SYSBASE
27   #include <proto/exec.h>
28   #include <proto/ahi.h>
29 + #include <inline/exec.h>
30 + #include <inline/ahi.h>
31  
32   #include "cpu_emulation.h"
33   #include "main.h"
# Line 36 | Line 39
39   #define DEBUG 0
40   #include "debug.h"
41  
42 <
40 < // Supported sample rates, sizes and channels
41 < int audio_num_sample_rates = 1;
42 < uint32 audio_sample_rates[] = {22050 << 16};
43 < int audio_num_sample_sizes = 1;
44 < uint16 audio_sample_sizes[] = {16};
45 < int audio_num_channel_counts = 1;
46 < uint16 audio_channel_counts[] = {2};
42 > #define D1(x) ;
43  
44  
45   // Global variables
# Line 55 | Line 51 | static int play_buf = 0;                                               // Number
51   static long sound_buffer_size;                                  // Size of one audio buffer in bytes
52   static int audio_block_fetched = 0;                             // Number of audio blocks fetched by interrupt routine
53  
54 + static bool main_mute = false;
55 + static bool speaker_mute = false;
56 + static ULONG supports_volume_changes = false;
57 + static ULONG supports_stereo_panning = false;
58 + static ULONG current_main_volume;
59 + static ULONG current_speaker_volume;
60 +
61  
62   // Prototypes
63 < static __saveds __regargs ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/);
63 > static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/);
64 > void audio_set_sample_rate_byval(uint32 value);
65 > void audio_set_sample_size_byval(uint32 value);
66 > void audio_set_channels_byval(uint32 value);
67  
68  
69   /*
70   *  Initialization
71   */
72  
73 + // Set AudioStatus to reflect current audio stream format
74 + static void set_audio_status_format(int sample_rate_index)
75 + {
76 +        AudioStatus.sample_rate = audio_sample_rates[sample_rate_index];
77 +        AudioStatus.sample_size = audio_sample_sizes[0];
78 +        AudioStatus.channels = audio_channel_counts[0];
79 + }
80 +
81   void AudioInit(void)
82   {
83          sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
84  
85          // Init audio status and feature flags
86 <        AudioStatus.sample_rate = audio_sample_rates[0];
87 <        AudioStatus.sample_size = audio_sample_sizes[0];
74 <        AudioStatus.channels = audio_channel_counts[0];
86 >        audio_channel_counts.push_back(2);
87 > //      set_audio_status_format();
88          AudioStatus.mixer = 0;
89          AudioStatus.num_sources = 0;
90          audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
# Line 106 | Line 119 | void AudioInit(void)
119                  return;
120          }
121  
122 +        ULONG max_channels, sample_rate, frequencies, sample_rate_index;
123 +
124 +        AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
125 +                AHIDB_MaxChannels, (ULONG) &max_channels,
126 +                AHIDB_Frequencies, (ULONG) &frequencies,
127 +                TAG_END);
128 +
129 +        D(bug("AudioInit: max_channels=%ld frequencies=%ld\n", max_channels, frequencies));
130 +
131 +        for (int n=0; n<frequencies; n++)
132 +                {
133 +                AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
134 +                        AHIDB_FrequencyArg, n,
135 +                        AHIDB_Frequency, (ULONG) &sample_rate,
136 +                        TAG_END);
137 +
138 +                D(bug("AudioInit: f=%ld Hz\n", sample_rate));
139 +                audio_sample_rates.push_back(sample_rate << 16);
140 +                }
141 +
142 +        ULONG sample_size_bits = 16;
143 +
144 +        D(bug("AudioInit: sampe_rates=%ld\n", audio_sample_rates.size() ));
145 +
146 +        // get index of sample rate closest to 22050 Hz
147 +        AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
148 +                AHIDB_IndexArg, 22050,
149 +                AHIDB_Bits, (ULONG) &sample_size_bits,
150 +                AHIDB_Index, (ULONG) &sample_rate_index,
151 +                AHIDB_Volume, (ULONG) &supports_volume_changes,
152 +                AHIDB_Panning, (ULONG) &supports_stereo_panning,
153 +                TAG_END);
154 +
155 +        audio_sample_sizes.push_back(16);
156 +
157 +        set_audio_status_format(sample_rate_index);
158 +
159          // 2048 frames per block
160          audio_frames_per_block = 2048;
161          sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
# Line 119 | Line 169 | void AudioInit(void)
169          sample[1].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
170          if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL)
171                  return;
172 +
173          AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl);
174          AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl);
175  
176          // Set parameters
177          play_buf = 0;
178 <        AHI_SetVol(0, 0x10000, 0x8000, ahi_ctrl, AHISF_IMM);
178 >        current_main_volume = current_speaker_volume = 0x10000;
179 >        AHI_SetVol(0, current_speaker_volume, 0x8000, ahi_ctrl, AHISF_IMM);
180 >
181          AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, AHISF_IMM);
182          AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM);
183  
# Line 174 | Line 227 | void audio_exit_stream()
227   *  AHI sound callback, request next buffer
228   */
229  
230 < static __saveds __regargs ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/)
230 > static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/)
231   {
232          play_buf ^= 1;
233  
234          // New buffer available?
235 <        if (audio_block_fetched) {
235 >        if (audio_block_fetched)
236 >                {
237                  audio_block_fetched--;
238  
239 <                // Get size of audio data
240 <                uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
241 <                if (apple_stream_info) {
242 <                        int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
243 <                        D(bug("stream: work_size %d\n", work_size));
244 <                        if (work_size > sound_buffer_size)
245 <                                work_size = sound_buffer_size;
246 <
247 <                        // Put data into AHI buffer (convert 8-bit data unsigned->signed)
248 <                        if (AudioStatus.sample_size == 16)
249 <                                memcpy(sample[play_buf].ahisi_Address, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), work_size);
250 <                        else {
251 <                                uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
252 <                                uint32 *q = (uint32 *)sample[play_buf].ahisi_Address;
253 <                                int r = work_size >> 2;
254 <                                while (r--)
255 <                                        *q++ = *p++ ^ 0x80808080;
239 >                if (main_mute || speaker_mute)
240 >                        {
241 >                        memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size);
242 >                        }
243 >                else
244 >                        {
245 >                        // Get size of audio data
246 >                        uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
247 >                        if (apple_stream_info) {
248 >                                int32 sample_count = ReadMacInt32(apple_stream_info + scd_sampleCount);
249 >
250 >                                uint32 num_channels = ReadMacInt16(apple_stream_info + scd_numChannels);
251 >                                uint32 sample_size = ReadMacInt16(apple_stream_info + scd_sampleSize);
252 >                                uint32 sample_rate = ReadMacInt32(apple_stream_info + scd_sampleRate);
253 >
254 >                                D(bug("stream: sample_count=%ld  num_channels=%ld  sample_size=%ld  sample_rate=%ld\n", sample_count, num_channels, sample_size, sample_rate >> 16));
255 >
256 >                                // Yes, this can happen.
257 >                                if(sample_count != 0) {
258 >                                        if(sample_rate != AudioStatus.sample_rate) {
259 >                                                audio_set_sample_rate_byval(sample_rate);
260 >                                        }
261 >                                        if(num_channels != AudioStatus.channels) {
262 >                                                audio_set_channels_byval(num_channels);
263 >                                        }
264 >                                        if(sample_size != AudioStatus.sample_size) {
265 >                                                audio_set_sample_size_byval(sample_size);
266 >                                        }
267 >                                }
268 >
269 >                                if (sample_count < 0)
270 >                                        sample_count = 0;
271 >
272 >                                int work_size = sample_count * num_channels * (sample_size>>3);
273 >                                D(bug("stream: work_size=%ld  sound_buffer_size=%ld\n", work_size, sound_buffer_size));
274 >
275 >                                if (work_size > sound_buffer_size)
276 >                                        work_size = sound_buffer_size;
277 >
278 >                                // Put data into AHI buffer (convert 8-bit data unsigned->signed)
279 >                                if (AudioStatus.sample_size == 16)
280 >                                        Mac2Host_memcpy(sample[play_buf].ahisi_Address, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
281 >                                else {
282 >                                        uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
283 >                                        uint32 *q = (uint32 *)sample[play_buf].ahisi_Address;
284 >                                        int r = work_size >> 2;
285 >                                        while (r--)
286 >                                                *q++ = *p++ ^ 0x80808080;
287 >                                }
288 >                                if (work_size != sound_buffer_size)
289 >                                        memset((uint8 *)sample[play_buf].ahisi_Address + work_size, 0, sound_buffer_size - work_size);
290                          }
203                        if (work_size != sound_buffer_size)
204                                memset((uint8 *)sample[play_buf].ahisi_Address + work_size, 0, sound_buffer_size - work_size);
291                  }
292  
293 <        } else
293 >                }
294 >        else
295                  memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size);
296  
297          // Play next buffer
# Line 212 | Line 299 | static __saveds __regargs ULONG audio_ca
299  
300          // Trigger audio interrupt to get new buffer
301          if (AudioStatus.num_sources) {
302 <                D(bug("stream: triggering irq\n"));
302 >                D1(bug("stream: triggering irq\n"));
303                  SetInterruptFlag(INTFLAG_AUDIO);
304                  TriggerInterrupt();
305          }
# Line 226 | Line 313 | static __saveds __regargs ULONG audio_ca
313  
314   void AudioInterrupt(void)
315   {
316 <        D(bug("AudioInterrupt\n"));
316 >        D1(bug("AudioInterrupt\n"));
317  
318          // Get data from apple mixer
319          if (AudioStatus.mixer) {
# Line 234 | Line 321 | void AudioInterrupt(void)
321                  r.a[0] = audio_data + adatStreamInfo;
322                  r.a[1] = AudioStatus.mixer;
323                  Execute68k(audio_data + adatGetSourceData, &r);
324 <                D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
324 >                D1(bug(" GetSourceData() returns %08lx\n", r.d[0]));
325          } else
326                  WriteMacInt32(audio_data + adatStreamInfo, 0);
327  
328          // Signal stream function
329          audio_block_fetched++;
330 <        D(bug("AudioInterrupt done\n"));
330 >        D1(bug("AudioInterrupt done\n"));
331   }
332  
333  
# Line 250 | Line 337 | void AudioInterrupt(void)
337   *  It is guaranteed that AudioStatus.num_sources == 0
338   */
339  
340 < void audio_set_sample_rate(int index)
340 > void audio_set_sample_rate_byval(uint32 value)
341   {
342 +        bool changed = (AudioStatus.sample_rate != value);
343 +        if(changed)
344 +                {
345 +                ULONG sample_rate_index;
346 +
347 +                // get index of sample rate closest to <value> Hz
348 +                AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
349 +                        AHIDB_IndexArg, value >> 16,
350 +                        AHIDB_Index, (ULONG) &sample_rate_index,
351 +                        TAG_END);
352 +
353 +                D(bug(" audio_set_sample_rate_byval requested rate=%ld Hz\n", value >> 16));
354 +
355 +                AudioStatus.sample_rate = audio_sample_rates[sample_rate_index];
356 +
357 +                AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, 0);
358 +                }
359 +
360 +        D(bug(" audio_set_sample_rate_byval rate=%ld Hz\n", AudioStatus.sample_rate >> 16));
361   }
362  
363 < void audio_set_sample_size(int index)
363 > void audio_set_sample_size_byval(uint32 value)
364   {
365 +        bool changed = (AudioStatus.sample_size != value);
366 +        if(changed) {
367 + //              AudioStatus.sample_size = value;
368 + //              update_sound_parameters();
369 + //              WritePrivateProfileInt( "Audio", "SampleSize", AudioStatus.sample_size, ini_file_name );
370 +        }
371 +        D(bug(" audio_set_sample_size_byval %d\n", AudioStatus.sample_size));
372   }
373  
374 < void audio_set_channels(int index)
374 > void audio_set_channels_byval(uint32 value)
375   {
376 +        bool changed = (AudioStatus.channels != value);
377 +        if(changed) {
378 + //              AudioStatus.channels = value;
379 + //              update_sound_parameters();
380 + //              WritePrivateProfileInt( "Audio", "Channels", AudioStatus.channels, ini_file_name );
381 +        }
382 +        D(bug(" audio_set_channels_byval %d\n", AudioStatus.channels));
383 + }
384 +
385 + bool audio_set_sample_rate(int index)
386 + {
387 +        if(index >= 0 && index < audio_sample_rates.size() ) {
388 +                audio_set_sample_rate_byval( audio_sample_rates[index] );
389 +                D(bug(" audio_set_sample_rate index=%ld rate=%ld\n", index, AudioStatus.sample_rate >> 16));
390 +        }
391 +
392 +        return true;
393 + }
394 +
395 + bool audio_set_sample_size(int index)
396 + {
397 +        if(index >= 0 && index < audio_sample_sizes.size()  ) {
398 +                audio_set_sample_size_byval( audio_sample_sizes[index] );
399 +                D(bug(" audio_set_sample_size %d,%d\n", index,AudioStatus.sample_size));
400 +        }
401 +
402 +        return true;
403 + }
404 +
405 + bool audio_set_channels(int index)
406 + {
407 +        if(index >= 0 && index < audio_channel_counts.size()   ) {
408 +                audio_set_channels_byval( audio_channel_counts[index] );
409 +                D(bug(" audio_set_channels %d,%d\n", index,AudioStatus.channels));
410 +        }
411 +
412 +        return true;
413   }
414  
415  
# Line 271 | Line 421 | void audio_set_channels(int index)
421  
422   bool audio_get_main_mute(void)
423   {
424 <        return false;
424 >        D(bug("audio_get_main_mute:  mute=%ld\n", main_mute));
425 >
426 >        return main_mute;
427   }
428  
429   uint32 audio_get_main_volume(void)
430   {
431 +        D(bug("audio_get_main_volume\n"));
432 +
433 +                ULONG volume = current_main_volume >> 8;        // 0x10000 => 0x100
434 +
435 +                D(bug("audio_get_main_volume: volume=%08lx\n", volume));
436 +
437 +                return (volume << 16) + volume;
438 +
439          return 0x01000100;
440   }
441  
442   bool audio_get_speaker_mute(void)
443   {
444 <        return false;
444 >        D(bug("audio_get_speaker_mute:  mute=%ld\n", speaker_mute));
445 >
446 >        return speaker_mute;
447   }
448  
449   uint32 audio_get_speaker_volume(void)
450   {
451 +        D(bug("audio_get_speaker_volume: \n"));
452 +
453 +        if (audio_open)
454 +                {
455 +                ULONG volume = current_speaker_volume >> 8;     // 0x10000 => 0x100
456 +
457 +                D(bug("audio_get_speaker_volume: volume=%08lx\n", volume));
458 +
459 +                return (volume << 16) + volume;
460 +                }
461 +
462          return 0x01000100;
463   }
464  
465   void audio_set_main_mute(bool mute)
466   {
467 +        D(bug("audio_set_main_mute: mute=%ld\n", mute));
468 +
469 +        if (mute != main_mute)
470 +                {
471 +                main_mute = mute;
472 +                }
473   }
474  
475   void audio_set_main_volume(uint32 vol)
476   {
477 +        D(bug("audio_set_main_volume: vol=%08lx\n", vol));
478 +
479 +        if (audio_open && supports_volume_changes)
480 +                {
481 +                ULONG volume = 0x80 * ((vol >> 16) + (vol & 0xffff));
482 +
483 +                D(bug("audio_set_main_volume: volume=%08lx\n", volume));
484 +
485 +                current_main_volume = volume;
486 +
487 +                AHI_SetVol(0, volume, 0x8000, ahi_ctrl, AHISF_IMM);
488 +                }
489   }
490  
491   void audio_set_speaker_mute(bool mute)
492   {
493 +        D(bug("audio_set_speaker_mute: mute=%ld\n", mute));
494 +
495 +        if (mute != speaker_mute)
496 +                {
497 +                speaker_mute = mute;
498 +                }
499   }
500  
501   void audio_set_speaker_volume(uint32 vol)
502   {
503 +        D(bug("audio_set_speaker_volume: vol=%08lx\n", vol));
504 +
505 +        if (audio_open && supports_volume_changes)
506 +                {
507 +                ULONG volume = 0x80 * ((vol >> 16) + (vol & 0xffff));
508 +
509 +                D(bug("audio_set_speaker_volume: volume=%08lx\n", volume));
510 +
511 +                current_speaker_volume = volume;
512 +
513 +                AHI_SetVol(0, volume, 0x8000, ahi_ctrl, AHISF_IMM);
514 +                }
515   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines