vwsnd
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. vwsnd - Sound driver for the Silicon Graphics 320 and 540 Visual
  2. Workstations' onboard audio.
  3. Copyright 1999 Silicon Graphics, Inc.  All rights reserved.
  4. At the time of this writing, March 1999, there are two models of
  5. Visual Workstation, the 320 and the 540.  This document only describes
  6. those models.  Future Visual Workstation models may have different
  7. sound capabilities, and this driver will probably not work on those
  8. boxes.
  9. The Visual Workstation has an Analog Devices AD1843 "SoundComm" audio
  10. codec chip.  The AD1843 is accessed through the Cobalt I/O ASIC, also
  11. known as Lithium.  This driver programs both both chips.
  12. ==============================================================================
  13. QUICK CONFIGURATION
  14. # insmod soundcore
  15. # insmod vwsnd
  16. ==============================================================================
  17. I/O CONNECTIONS
  18. On the Visual Workstation, only three of the AD1843 inputs are hooked
  19. up.  The analog line in jacks are connected to the AD1843's AUX1
  20. input.  The CD audio lines are connected to the AD1843's AUX2 input.
  21. The microphone jack is connected to the AD1843's MIC input.  The mic
  22. jack is mono, but the signal is delivered to both the left and right
  23. MIC inputs.  You can record in stereo from the mic input, but you will
  24. get the same signal on both channels (within the limits of A/D
  25. accuracy).  Full scale on the Line input is +/- 2.0 V.  Full scale on
  26. the MIC input is 20 dB less, or +/- 0.2 V.
  27. The AD1843's LOUT1 outputs are connected to the Line Out jacks.  The
  28. AD1843's HPOUT outputs are connected to the speaker/headphone jack.
  29. LOUT2 is not connected.  Line out's maximum level is +/- 2.0 V peak to
  30. peak.  The speaker/headphone out's maximum is +/- 4.0 V peak to peak.
  31. The AD1843's PCM input channel and one of its output channels (DAC1)
  32. are connected to Lithium.  The other output channel (DAC2) is not
  33. connected.
  34. ==============================================================================
  35. CAPABILITIES
  36. The AD1843 has PCM input and output (Pulse Code Modulation, also known
  37. as wavetable).  PCM input and output can be mono or stereo in any of
  38. four formats.  The formats are 16 bit signed and 8 bit unsigned,
  39. u-Law, and A-Law format.  Any sample rate from 4 KHz to 49 KHz is
  40. available, in 1 Hz increments.
  41. The AD1843 includes an analog mixer that can mix all three input
  42. signals (line, mic and CD) into the analog outputs.  The mixer has a
  43. separate gain control and mute switch for each input.
  44. There are two outputs, line out and speaker/headphone out.  They
  45. always produce the same signal, and the speaker always has 3 dB more
  46. gain than the line out.  The speaker/headphone output can be muted,
  47. but this driver does not export that function.
  48. The hardware can sync audio to the video clock, but this driver does
  49. not have a way to specify syncing to video.
  50. ==============================================================================
  51. PROGRAMMING
  52. This section explains the API supported by the driver.  Also see the
  53. Open Sound Programming Guide at http://www.opensound.com/pguide/ .
  54. This section assumes familiarity with that document.
  55. The driver has two interfaces, an I/O interface and a mixer interface.
  56. There is no MIDI or sequencer capability.
  57. ==============================================================================
  58. PROGRAMMING PCM I/O
  59. The I/O interface is usually accessed as /dev/audio or /dev/dsp.
  60. Using the standard Open Sound System (OSS) ioctl calls, the sample
  61. rate, number of channels, and sample format may be set within the
  62. limitations described above.  The driver supports triggering.  It also
  63. supports getting the input and output pointers with one-sample
  64. accuracy.
  65. The SNDCTL_DSP_GETCAP ioctl returns these capabilities.
  66. DSP_CAP_DUPLEX - driver supports full duplex.
  67. DSP_CAP_TRIGGER - driver supports triggering.
  68. DSP_CAP_REALTIME - values returned by SNDCTL_DSP_GETIPTR
  69. and SNDCTL_DSP_GETOPTR are accurate to a few samples.
  70. Memory mapping (mmap) is not implemented.
  71. The driver permits subdivided fragment sizes from 64 to 4096 bytes.
  72. The number of fragments can be anything from 3 fragments to however
  73. many fragments fit into 124 kilobytes.  It is up to the user to
  74. determine how few/small fragments can be used without introducing
  75. glitches with a given workload.  Linux is not realtime, so we can't
  76. promise anything.  (sigh...)
  77. When this driver is switched into or out of mu-Law or A-Law mode on
  78. output, it may produce an audible click.  This is unavoidable.  To
  79. prevent clicking, use signed 16-bit mode instead, and convert from
  80. mu-Law or A-Law format in software.
  81. ==============================================================================
  82. PROGRAMMING THE MIXER INTERFACE
  83. The mixer interface is usually accessed as /dev/mixer.  It is accessed
  84. through ioctls.  The mixer allows the application to control gain or
  85. mute several audio signal paths, and also allows selection of the
  86. recording source.
  87. Each of the constants described here can be read using the
  88. MIXER_READ(SOUND_MIXER_xxx) ioctl.  Those that are not read-only can
  89. also be written using the MIXER_WRITE(SOUND_MIXER_xxx) ioctl.  In most
  90. cases, <sys/soundcard.h> defines constants SOUND_MIXER_READ_xxx and
  91. SOUND_MIXER_WRITE_xxx which work just as well.
  92. SOUND_MIXER_CAPS Read-only
  93. This is a mask of optional driver capabilities that are implemented.
  94. This driver's only capability is SOUND_CAP_EXCL_INPUT, which means
  95. that only one recording source can be active at a time.
  96. SOUND_MIXER_DEVMASK Read-only
  97. This is a mask of the sound channels.  This driver's channels are PCM,
  98. LINE, MIC, CD, and RECLEV.
  99. SOUND_MIXER_STEREODEVS Read-only
  100. This is a mask of which sound channels are capable of stereo.  All
  101. channels are capable of stereo.  (But see caveat on MIC input in I/O
  102. CONNECTIONS section above).
  103. SOUND_MIXER_OUTMASK Read-only
  104. This is a mask of channels that route inputs through to outputs.
  105. Those are LINE, MIC, and CD.
  106. SOUND_MIXER_RECMASK Read-only
  107. This is a mask of channels that can be recording sources.  Those are
  108. PCM, LINE, MIC, CD.
  109. SOUND_MIXER_PCM Default: 0x5757 (0 dB)
  110. This is the gain control for PCM output.  The left and right channel
  111. gain are controlled independently.  This gain control has 64 levels,
  112. which range from -82.5 dB to +12.0 dB in 1.5 dB steps.  Those 64
  113. levels are mapped onto 100 levels at the ioctl, see below.
  114. SOUND_MIXER_LINE Default: 0x4a4a (0 dB)
  115. This is the gain control for mixing the Line In source into the
  116. outputs.  The left and right channel gain are controlled
  117. independently.  This gain control has 32 levels, which range from
  118. -34.5 dB to +12.0 dB in 1.5 dB steps.  Those 32 levels are mapped onto
  119. 100 levels at the ioctl, see below.
  120. SOUND_MIXER_MIC Default: 0x4a4a (0 dB)
  121. This is the gain control for mixing the MIC source into the outputs.
  122. The left and right channel gain are controlled independently.  This
  123. gain control has 32 levels, which range from -34.5 dB to +12.0 dB in
  124. 1.5 dB steps.  Those 32 levels are mapped onto 100 levels at the
  125. ioctl, see below.
  126. SOUND_MIXER_CD Default: 0x4a4a (0 dB)
  127. This is the gain control for mixing the CD audio source into the
  128. outputs.  The left and right channel gain are controlled
  129. independently.  This gain control has 32 levels, which range from
  130. -34.5 dB to +12.0 dB in 1.5 dB steps.  Those 32 levels are mapped onto
  131. 100 levels at the ioctl, see below.
  132. SOUND_MIXER_RECLEV  Default: 0 (0 dB)
  133. This is the gain control for PCM input (RECording LEVel).  The left
  134. and right channel gain are controlled independently.  This gain
  135. control has 16 levels, which range from 0 dB to +22.5 dB in 1.5 dB
  136. steps.  Those 16 levels are mapped onto 100 levels at the ioctl, see
  137. below.
  138. SOUND_MIXER_RECSRC  Default: SOUND_MASK_LINE
  139. This is a mask of currently selected PCM input sources (RECording
  140. SouRCes).  Because the AD1843 can only have a single recording source
  141. at a time, only one bit at a time can be set in this mask.  The
  142. allowable values are SOUND_MASK_PCM, SOUND_MASK_LINE, SOUND_MASK_MIC,
  143. or SOUND_MASK_CD.  Selecting SOUND_MASK_PCM sets up internal
  144. resampling which is useful for loopback testing and for hardware
  145. sample rate conversion.  But software sample rate conversion is
  146. probably faster, so I don't know how useful that is.
  147. SOUND_MIXER_OUTSRC DEFAULT: SOUND_MASK_LINE|SOUND_MASK_MIC|SOUND_MASK_CD
  148. This is a mask of sources that are currently passed through to the
  149. outputs.  Those sources whose bits are not set are muted.
  150. ==============================================================================
  151. GAIN CONTROL
  152. There are five gain controls listed above.  Each has 16, 32, or 64
  153. steps.  Each control has 1.5 dB of gain per step.  Each control is
  154. stereo.
  155. The OSS defines the argument to a channel gain ioctl as having two
  156. components, left and right, each of which ranges from 0 to 100.  The
  157. two components are packed into the same word, with the left side gain
  158. in the least significant byte, and the right side gain in the second
  159. least significant byte.  In C, we would say this.
  160. #include <assert.h>
  161. ...
  162.   assert(leftgain >= 0 && leftgain <= 100);
  163. assert(rightgain >= 0 && rightgain <= 100);
  164. arg = leftgain | rightgain << 8;
  165. So each OSS gain control has 101 steps.  But the hardware has 16, 32,
  166. or 64 steps.  The hardware steps are spread across the 101 OSS steps
  167. nearly evenly.  The conversion formulas are like this, given N equals
  168. 16, 32, or 64.
  169. int round = N/2 - 1;
  170. OSS_gain_steps = (hw_gain_steps * 100 + round) / (N - 1);
  171. hw_gain_steps = (OSS_gain_steps * (N - 1) + round) / 100;
  172. Here is a snippet of C code that will return the left and right gain
  173. of any channel in dB.  Pass it one of the predefined gain_desc_t
  174. structures to access any of the five channels' gains.
  175. typedef struct gain_desc {
  176. float min_gain;
  177. float gain_step;
  178. int nbits;
  179. int chan;
  180. } gain_desc_t;
  181. const gain_desc_t gain_pcm    = { -82.5, 1.5, 6, SOUND_MIXER_PCM    };
  182. const gain_desc_t gain_line   = { -34.5, 1.5, 5, SOUND_MIXER_LINE   };
  183. const gain_desc_t gain_mic    = { -34.5, 1.5, 5, SOUND_MIXER_MIC    };
  184. const gain_desc_t gain_cd     = { -34.5, 1.5, 5, SOUND_MIXER_CD     };
  185. const gain_desc_t gain_reclev = {   0.0, 1.5, 4, SOUND_MIXER_RECLEV };
  186. int get_gain_dB(int fd, const gain_desc_t *gp,
  187. float *left, float *right)
  188. {
  189. int word;
  190. int lg, rg;
  191. int mask = (1 << gp->nbits) - 1;
  192. if (ioctl(fd, MIXER_READ(gp->chan), &word) != 0)
  193. return -1; /* fail */
  194. lg = word & 0xFF;
  195. rg = word >> 8 & 0xFF;
  196. lg = (lg * mask + mask / 2) / 100;
  197. rg = (rg * mask + mask / 2) / 100;
  198. *left = gp->min_gain + gp->gain_step * lg;
  199. *right = gp->min_gain + gp->gain_step * rg;
  200. return 0;
  201. }
  202. And here is the corresponding routine to set a channel's gain in dB.
  203. int set_gain_dB(int fd, const gain_desc_t *gp, float left, float right)
  204. {
  205. float max_gain =
  206. gp->min_gain + (1 << gp->nbits) * gp->gain_step;
  207. float round = gp->gain_step / 2;
  208. int mask = (1 << gp->nbits) - 1;
  209. int word;
  210. int lg, rg;
  211. if (left < gp->min_gain || right < gp->min_gain)
  212. return EINVAL;
  213. lg = (left - gp->min_gain + round) / gp->gain_step;
  214. rg = (right - gp->min_gain + round) / gp->gain_step;
  215. if (lg >= (1 << gp->nbits) || rg >= (1 << gp->nbits))
  216. return EINVAL;
  217. lg = (100 * lg + mask / 2) / mask;
  218. rg = (100 * rg + mask / 2) / mask;
  219. word = lg | rg << 8;
  220. return ioctl(fd, MIXER_WRITE(gp->chan), &word);
  221. }