drv_sb.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:5k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* MikMod sound library
  2. (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
  3. complete list.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of
  7. the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  17. 02111-1307, USA.
  18. */
  19. /*==============================================================================
  20.   $Id: drv_sb.c,v 1.4 2004/02/10 17:52:18 raph Exp $
  21.   Driver for SoundBlaster/Pro/16/AWE32 under DOS
  22. ==============================================================================*/
  23. /*
  24. Written by Andrew Zabolotny <bit@eltech.ru>
  25. */
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #ifdef DRV_SB
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #ifdef HAVE_FCNTL_H
  34. #include <fcntl.h>
  35. #endif
  36. #include "mikmod_internals.h"
  37. #include "dossb.h"
  38. static void SB_CommandLine(CHAR *cmdline)
  39. {
  40. char *ptr, *end;
  41. if ((ptr=MD_GetAtom("port",cmdline,0))) {
  42. sb.port = strtol(ptr, &end, 16);
  43. free(ptr);
  44. }
  45. if ((ptr=MD_GetAtom("irq",cmdline,0))) {
  46. sb.irq = strtol(ptr, &end, 10);
  47. free(ptr);
  48. }
  49. if ((ptr=MD_GetAtom("dma",cmdline,0))) {
  50. sb.dma8 = strtol(ptr, &end, 10);
  51. free(ptr);
  52. }
  53. if ((ptr=MD_GetAtom("hidma",cmdline,0))) {
  54. sb.dma16 = strtol(ptr, &end, 10);
  55. free(ptr);
  56. }
  57. }
  58. static BOOL SB_IsThere(void)
  59. {
  60. return sb_detect();
  61. }
  62. static BOOL SB_Init(void)
  63. {
  64. if (!sb_open()) {
  65. _mm_errno = MMERR_INVALID_DEVICE;
  66. return 1;
  67. }
  68. /* Adjust md_mode according to sound card capabilities */
  69. if (!(sb.caps & SBMODE_STEREO))
  70. md_mode &= ~DMODE_STEREO;
  71. if (!(sb.caps & SBMODE_16BITS))
  72. md_mode &= ~DMODE_16BITS;
  73. if (md_mixfreq < 4000)
  74. md_mixfreq = 4000;
  75. if (md_mode & DMODE_STEREO) {
  76. if (md_mixfreq > sb.maxfreq_stereo)
  77. md_mixfreq = sb.maxfreq_stereo;
  78. } else {
  79. if (md_mixfreq > sb.maxfreq_mono)
  80. md_mixfreq = sb.maxfreq_mono;
  81. }
  82. return VC_Init();
  83. }
  84. static void SB_Exit(void)
  85. {
  86. VC_Exit();
  87. sb_close();
  88. }
  89. /* The last buffer byte filled with sound */
  90. static unsigned int buff_tail = 0;
  91. static void SB_Callback(void)
  92. {
  93. unsigned int dma_size, dma_pos;
  94. ULONG (*mixer)(SBYTE *buf, ULONG todo);
  95. sb_query_dma(&dma_size, &dma_pos);
  96. /* There isn't much sense in filling less than 256 bytes */
  97. dma_pos &= ~255;
  98. /* If nothing to mix, quit */
  99. if (buff_tail == dma_pos)
  100. return;
  101. if (Player_Paused_internal())
  102. mixer = VC_SilenceBytes;
  103. else
  104. mixer = VC_WriteBytes;
  105. /* If DMA pointer still didn't wrapped around ... */
  106. if (dma_pos > buff_tail) {
  107. buff_tail += mixer (sb.dma_buff->linear + buff_tail, dma_pos - buff_tail);
  108. /* If we arrived right to the DMA buffer end, jump to the beginning */
  109. if (buff_tail >= dma_size)
  110. buff_tail = 0;
  111. } else {
  112. /* If wrapped around, fill first to the end of buffer */
  113. mixer (sb.dma_buff->linear + buff_tail, dma_size - buff_tail);
  114. /* Now fill from buffer beginning to current DMA pointer */
  115. buff_tail = mixer (sb.dma_buff->linear, dma_pos);
  116. }
  117. }
  118. static void SB_Update(void)
  119. {
  120. /* Do nothing: the real update is done during SB interrupts */
  121. }
  122. static BOOL SB_PlayStart (void)
  123. {
  124. if (VC_PlayStart())
  125. return 1;
  126. /* Enable speaker output */
  127. sb_output(TRUE);
  128. /* Set our routine to be called during SB IRQs */
  129. buff_tail = 0;
  130. sb.timer_callback = SB_Callback;
  131. /* Start cyclic DMA transfer */
  132. if (!sb_start_dma(((md_mode & DMODE_16BITS) ? SBMODE_16BITS | SBMODE_SIGNED : 0) |
  133. ((md_mode & DMODE_STEREO) ? SBMODE_STEREO : 0), md_mixfreq))
  134. {
  135. _mm_errno = MMERR_DOSSB_STARTDMA;
  136. return 1;
  137. }
  138. return 0;
  139. }
  140. static BOOL SB_Reset(void)
  141. {
  142. sb_reset();
  143. VC_Exit();
  144. return VC_Init();
  145. }
  146. static void SB_PlayStop(void)
  147. {
  148. sb.timer_callback = NULL;
  149. sb_output(FALSE);
  150. sb_stop_dma();
  151. VC_PlayStop();
  152. }
  153. MDRIVER drv_sb =
  154. {
  155. NULL,
  156. "Sound Blaster",
  157. "Sound Blaster Orig/2.0/Pro/16 v1.0",
  158. 0, 255,
  159. "sb",
  160. "port:c:220,230,240,250,260,270,280,32C,530,604,E80,F40,220:Sound Blaster base I/O portn"
  161. "irq:c:2,3,5,7,10,5:Sound Blaster IRQn"
  162. "dma:c:0,1,3,1:Sound Blaster 8 bit DMA channeln"
  163. "hidma:c:5,6,7,5:Sound Blaster 16 bit DMA channel (SB16/AWE32 only)n",
  164. SB_CommandLine,
  165. SB_IsThere,
  166. VC_SampleLoad,
  167. VC_SampleUnload,
  168. VC_SampleSpace,
  169. VC_SampleLength,
  170. SB_Init,
  171. SB_Exit,
  172. SB_Reset,
  173. VC_SetNumVoices,
  174. SB_PlayStart,
  175. SB_PlayStop,
  176. SB_Update,
  177. NULL,
  178. VC_VoiceSetVolume,
  179. VC_VoiceGetVolume,
  180. VC_VoiceSetFrequency,
  181. VC_VoiceGetFrequency,
  182. VC_VoiceSetPanning,
  183. VC_VoiceGetPanning,
  184. VC_VoicePlay,
  185. VC_VoiceStop,
  186. VC_VoiceStopped,
  187. VC_VoiceGetPosition,
  188. VC_VoiceRealVolume
  189. };
  190. #else // DRV_SB
  191. MISSING(drv_sb);
  192. #endif
  193. /* ex:set ts=4: */