home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / AmigaOS / audio_amiga.cpp < prev    next >
C/C++ Source or Header  |  1999-11-03  |  8KB  |  307 lines

  1. /*
  2.  *  audio_amiga.cpp - Audio support, AmigaOS implementation using AHI
  3.  *
  4.  *  Basilisk II (C) 1997-1999 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
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include "sysdeps.h"
  22.  
  23. #include <exec/types.h>
  24. #include <exec/memory.h>
  25. #include <devices/ahi.h>
  26. #include <proto/exec.h>
  27. #include <proto/ahi.h>
  28.  
  29. #include "cpu_emulation.h"
  30. #include "main.h"
  31. #include "prefs.h"
  32. #include "user_strings.h"
  33. #include "audio.h"
  34. #include "audio_defs.h"
  35.  
  36. #define DEBUG 0
  37. #include "debug.h"
  38.  
  39.  
  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};
  47.  
  48.  
  49. // Global variables
  50. static ULONG ahi_id = AHI_DEFAULT_ID;            // AHI audio ID
  51. static struct AHIAudioCtrl *ahi_ctrl = NULL;
  52. static struct AHISampleInfo sample[2];            // Two sample infos for double-buffering
  53. static struct Hook sf_hook;
  54. static int play_buf = 0;                        // Number of currently played buffer
  55. static long sound_buffer_size;                    // Size of one audio buffer in bytes
  56. static int audio_block_fetched = 0;                // Number of audio blocks fetched by interrupt routine
  57.  
  58.  
  59. // Prototypes
  60. static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/);
  61.  
  62.  
  63. /*
  64.  *  Initialization
  65.  */
  66.  
  67. void AudioInit(void)
  68. {
  69.     sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
  70.  
  71.     // Init audio status and feature flags
  72.     AudioStatus.sample_rate = audio_sample_rates[0];
  73.     AudioStatus.sample_size = audio_sample_sizes[0];
  74.     AudioStatus.channels = audio_channel_counts[0];
  75.     AudioStatus.mixer = 0;
  76.     AudioStatus.num_sources = 0;
  77.     audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
  78.  
  79.     // Sound disabled in prefs? Then do nothing
  80.     if (PrefsFindBool("nosound"))
  81.         return;
  82.  
  83.     // AHI available?
  84.     if (AHIBase == NULL) {
  85.         WarningAlert(GetString(STR_NO_AHI_WARN));
  86.         return;
  87.     }
  88.  
  89.     // Initialize callback hook
  90.     sf_hook.h_Entry = (HOOKFUNC)audio_callback;
  91.  
  92.     // Read "sound" preferences
  93.     const char *str = PrefsFindString("sound");
  94.     if (str)
  95.         sscanf(str, "ahi/%08lx", &ahi_id);
  96.  
  97.     // Open audio control structure
  98.     if ((ahi_ctrl = AHI_AllocAudio(
  99.         AHIA_AudioID, ahi_id,
  100.         AHIA_MixFreq, AudioStatus.sample_rate >> 16,
  101.         AHIA_Channels, 1,
  102.         AHIA_Sounds, 2,
  103.         AHIA_SoundFunc, (ULONG)&sf_hook,
  104.         TAG_END)) == NULL) {
  105.         WarningAlert(GetString(STR_NO_AHI_CTRL_WARN));
  106.         return;
  107.     }
  108.  
  109.     // 2048 frames per block
  110.     audio_frames_per_block = 2048;
  111.     sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
  112.  
  113.     // Prepare SampleInfos and load sounds (two sounds for double buffering)
  114.     sample[0].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S;
  115.     sample[0].ahisi_Length = audio_frames_per_block;
  116.     sample[0].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
  117.     sample[1].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S;
  118.     sample[1].ahisi_Length = audio_frames_per_block;
  119.     sample[1].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
  120.     if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL)
  121.         return;
  122.     AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl);
  123.     AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl);
  124.  
  125.     // Set parameters
  126.     play_buf = 0;
  127.     AHI_SetVol(0, 0x10000, 0x8000, ahi_ctrl, AHISF_IMM);
  128.     AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, AHISF_IMM);
  129.     AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM);
  130.  
  131.     // Everything OK
  132.     audio_open = true;
  133. }
  134.  
  135.  
  136. /*
  137.  *  Deinitialization
  138.  */
  139.  
  140. void AudioExit(void)
  141. {
  142.     // Free everything
  143.     if (ahi_ctrl != NULL) {
  144.         AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END);
  145.         AHI_FreeAudio(ahi_ctrl);
  146.     }
  147.  
  148.     FreeVec(sample[0].ahisi_Address);
  149.     FreeVec(sample[1].ahisi_Address);
  150. }
  151.  
  152.  
  153. /*
  154.  *  First source added, start audio stream
  155.  */
  156.  
  157. void audio_enter_stream()
  158. {
  159.     AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_END);
  160. }
  161.  
  162.  
  163. /*
  164.  *  Last source removed, stop audio stream
  165.  */
  166.  
  167. void audio_exit_stream()
  168. {
  169.     AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END);
  170. }
  171.  
  172.  
  173. /*
  174.  *  AHI sound callback, request next buffer
  175.  */
  176.  
  177. static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/)
  178. {
  179.     play_buf ^= 1;
  180.  
  181.     // New buffer available?
  182.     if (audio_block_fetched) {
  183.         audio_block_fetched--;
  184.  
  185.         // Get size of audio data
  186.         uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
  187.         if (apple_stream_info) {
  188.             int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
  189.             D(bug("stream: work_size %d\n", work_size));
  190.             if (work_size > sound_buffer_size)
  191.                 work_size = sound_buffer_size;
  192.  
  193.             // Put data into AHI buffer (convert 8-bit data unsigned->signed)
  194.             if (AudioStatus.sample_size == 16)
  195.                 Mac2Host_memcpy(sample[play_buf].ahisi_Address, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
  196.             else {
  197.                 uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
  198.                 uint32 *q = (uint32 *)sample[play_buf].ahisi_Address;
  199.                 int r = work_size >> 2;
  200.                 while (r--)
  201.                     *q++ = *p++ ^ 0x80808080;
  202.             }
  203.             if (work_size != sound_buffer_size)
  204.                 memset((uint8 *)sample[play_buf].ahisi_Address + work_size, 0, sound_buffer_size - work_size);
  205.         }
  206.  
  207.     } else
  208.         memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size);
  209.  
  210.     // Play next buffer
  211.     AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, 0);
  212.  
  213.     // Trigger audio interrupt to get new buffer
  214.     if (AudioStatus.num_sources) {
  215.         D(bug("stream: triggering irq\n"));
  216.         SetInterruptFlag(INTFLAG_AUDIO);
  217.         TriggerInterrupt();
  218.     }
  219.     return 0;
  220. }
  221.  
  222.  
  223. /*
  224.  *  MacOS audio interrupt, read next data block
  225.  */
  226.  
  227. void AudioInterrupt(void)
  228. {
  229.     D(bug("AudioInterrupt\n"));
  230.  
  231.     // Get data from apple mixer
  232.     if (AudioStatus.mixer) {
  233.         M68kRegisters r;
  234.         r.a[0] = audio_data + adatStreamInfo;
  235.         r.a[1] = AudioStatus.mixer;
  236.         Execute68k(audio_data + adatGetSourceData, &r);
  237.         D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
  238.     } else
  239.         WriteMacInt32(audio_data + adatStreamInfo, 0);
  240.  
  241.     // Signal stream function
  242.     audio_block_fetched++;
  243.     D(bug("AudioInterrupt done\n"));
  244. }
  245.  
  246.  
  247. /*
  248.  *  Set sampling parameters
  249.  *  "index" is an index into the audio_sample_rates[] etc. arrays
  250.  *  It is guaranteed that AudioStatus.num_sources == 0
  251.  */
  252.  
  253. void audio_set_sample_rate(int index)
  254. {
  255. }
  256.  
  257. void audio_set_sample_size(int index)
  258. {
  259. }
  260.  
  261. void audio_set_channels(int index)
  262. {
  263. }
  264.  
  265.  
  266. /*
  267.  *  Get/set volume controls (volume values received/returned have the left channel
  268.  *  volume in the upper 16 bits and the right channel volume in the lower 16 bits;
  269.  *  both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
  270.  */
  271.  
  272. bool audio_get_main_mute(void)
  273. {
  274.     return false;
  275. }
  276.  
  277. uint32 audio_get_main_volume(void)
  278. {
  279.     return 0x01000100;
  280. }
  281.  
  282. bool audio_get_speaker_mute(void)
  283. {
  284.     return false;
  285. }
  286.  
  287. uint32 audio_get_speaker_volume(void)
  288. {
  289.     return 0x01000100;
  290. }
  291.  
  292. void audio_set_main_mute(bool mute)
  293. {
  294. }
  295.  
  296. void audio_set_main_volume(uint32 vol)
  297. {
  298. }
  299.  
  300. void audio_set_speaker_mute(bool mute)
  301. {
  302. }
  303.  
  304. void audio_set_speaker_volume(uint32 vol)
  305. {
  306. }
  307.