| 1 | /* $Id: waudio.cpp,v 1.2 2001/04/30 21:07:59 sandervl Exp $ */
|
|---|
| 2 |
|
|---|
| 3 | /* SCCSID = %W% %E% */
|
|---|
| 4 | /****************************************************************************
|
|---|
| 5 | * *
|
|---|
| 6 | * Copyright (c) IBM Corporation 1994 - 1997. *
|
|---|
| 7 | * *
|
|---|
| 8 | * The following IBM OS/2 source code is provided to you solely for the *
|
|---|
| 9 | * the purpose of assisting you in your development of OS/2 device drivers. *
|
|---|
| 10 | * You may use this code in accordance with the IBM License Agreement *
|
|---|
| 11 | * provided in the IBM Device Driver Source Kit for OS/2. *
|
|---|
| 12 | * *
|
|---|
| 13 | ****************************************************************************/
|
|---|
| 14 | /**@internal %W%
|
|---|
| 15 | * @notes
|
|---|
| 16 | * @version %I%
|
|---|
| 17 | * @context Unless otherwise noted, all interfaces are Ring-0, 16-bit,
|
|---|
| 18 | * <stack context>.
|
|---|
| 19 | * @history
|
|---|
| 20 | *
|
|---|
| 21 | */
|
|---|
| 22 | #define INCL_NOPMAPI
|
|---|
| 23 | #include <os2.h>
|
|---|
| 24 | #include <os2medef.h>
|
|---|
| 25 | #include <audio.h>
|
|---|
| 26 | #include <sbvsd.h>
|
|---|
| 27 |
|
|---|
| 28 | #include <linux/soundcard.h>
|
|---|
| 29 |
|
|---|
| 30 | #include "waudio.hpp"
|
|---|
| 31 | #include "ossidc.h"
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 | // Rudi: no support for ALAW and MULAW formats
|
|---|
| 36 | #define NO_xLAW
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 | // the following 3-D array defines the subtypes for DATATYPE_WAVEFORM
|
|---|
| 40 | // The array is 4x2x2 and is indexed using frequency index, bits per
|
|---|
| 41 | // sample being 8 or 16 represented by 0 or 1 resp. and mono or stereo
|
|---|
| 42 | // mode represented by 0 or 1 respectively. For eg. to find out the
|
|---|
| 43 | // subtype for 22050Hz sampling frequency, using 16 bits per sample
|
|---|
| 44 | // and stereo mode, we use aaulWave[FREQ22KHZ][BPS16][1]. This avoids
|
|---|
| 45 | // inefficient nested if's and switches to find a matching value given
|
|---|
| 46 | // the same.
|
|---|
| 47 | //
|
|---|
| 48 | USHORT aaulWave[NUMFREQS][BPSTYPES][MONOSTEREO] = {
|
|---|
| 49 | WAVE_FORMAT_1M08, /* 11.025kHz, 8-bit Mono */
|
|---|
| 50 | WAVE_FORMAT_1S08, /* 11.025kHz, 8-bit Stereo */
|
|---|
| 51 | WAVE_FORMAT_1M16, /* 11.025kHz, 16-bit Mono */
|
|---|
| 52 | WAVE_FORMAT_1S16, /* 11.025kHz, 16-bit Stereo */
|
|---|
| 53 | WAVE_FORMAT_2M08, /* 22.05kHz , 8-bit Mono */
|
|---|
| 54 | WAVE_FORMAT_2S08, /* 22.05kHz , 8-bit Stereo */
|
|---|
| 55 | WAVE_FORMAT_2M16, /* 22.05kHz , 16-bit Mono */
|
|---|
| 56 | WAVE_FORMAT_2S16, /* 22.05kHz , 16-bit Stereo */
|
|---|
| 57 | WAVE_FORMAT_4M08, /* 44.1kHz , 8-bit Mono */
|
|---|
| 58 | WAVE_FORMAT_4S08, /* 44.1kHz , 8-bit Stereo */
|
|---|
| 59 | WAVE_FORMAT_4M16, /* 44.1kHz , 16-bit Mono */
|
|---|
| 60 | WAVE_FORMAT_4S16, /* 44.1kHz , 16-bit Stereo */
|
|---|
| 61 | WAVE_FORMAT_8M08, /* 8.0kHz , 8-bit Mono */
|
|---|
| 62 | WAVE_FORMAT_8S08, /* 8.0kHz , 8-bit Stereo */
|
|---|
| 63 | WAVE_FORMAT_8M16, /* 8.0kHz , 16-bit Mono */
|
|---|
| 64 | WAVE_FORMAT_8S16 /* 8.0kHz , 16-bit Stereo */
|
|---|
| 65 | };
|
|---|
| 66 |
|
|---|
| 67 | /*
|
|---|
| 68 | USHORT aaulMPEG[NUMFREQS][MONOSTEREO] = {
|
|---|
| 69 | MPEG1_FORMAT_3M16, // 11.025kHz Mono
|
|---|
| 70 | MPEG1_FORMAT_3S16, // 11.025kHz Stereo
|
|---|
| 71 | MPEG1_FORMAT_3M16, // 22.05kHz Mono
|
|---|
| 72 | MPEG1_FORMAT_3S16, // 22.05kHz Stereo
|
|---|
| 73 | MPEG1_FORMAT_4M16, // 44.1kHz / 48kHz Mono
|
|---|
| 74 | MPEG1_FORMAT_4S16, // 44.1kHz / 48kHz Stereo
|
|---|
| 75 | MPEG1_FORMAT_3M16, // 8.0kHz Mono
|
|---|
| 76 | MPEG1_FORMAT_3S16, // 8.0kHz Stereo
|
|---|
| 77 | };
|
|---|
| 78 | */
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 | #ifndef NO_xLAW
|
|---|
| 82 |
|
|---|
| 83 | // the following 2-D array defines the subtypes for DATATYPE_ALAW
|
|---|
| 84 | // it is indexed by the sampling rate ordinal (from
|
|---|
| 85 | // _usfind_matching_sample_rate) and the number of channels
|
|---|
| 86 | USHORT aaulAlaw[NUMFREQS][MONOSTEREO] = {
|
|---|
| 87 | ALAW_8B11KM, /* 8bit 11kHz mono*/
|
|---|
| 88 | ALAW_8B11KS, /* 8bit 11kHz stereo*/
|
|---|
| 89 | ALAW_8B22KM, /* 8bit 22kHz mono*/
|
|---|
| 90 | ALAW_8B22KS, /* 8bit 22kHz stereo*/
|
|---|
| 91 | ALAW_8B44KM, /* 8bit 44kHz mono*/
|
|---|
| 92 | ALAW_8B44KS, /* 8bit 44kHz stereo*/
|
|---|
| 93 | ALAW_8B8KM , /* 8bit 8kHz mono*/
|
|---|
| 94 | ALAW_8B8KS /* 8bit 8kHz stereo*/
|
|---|
| 95 | };
|
|---|
| 96 |
|
|---|
| 97 | // the following 2-D array defines the subtypes for DATATYPE_MULAW
|
|---|
| 98 | // it is indexed by the sampling rate ordinal (from
|
|---|
| 99 | // _usfind_matching_sample_rate) and the number of channels
|
|---|
| 100 | USHORT aaulMulaw[NUMFREQS][MONOSTEREO] = {
|
|---|
| 101 | MULAW_8B11KM, /* 8bit 11kHz mono*/
|
|---|
| 102 | MULAW_8B11KS, /* 8bit 11kHz stereo*/
|
|---|
| 103 | MULAW_8B22KM, /* 8bit 22kHz mono*/
|
|---|
| 104 | MULAW_8B22KS, /* 8bit 22kHz stereo*/
|
|---|
| 105 | MULAW_8B44KM, /* 8bit 44kHz mono*/
|
|---|
| 106 | MULAW_8B44KS, /* 8bit 44kHz stereo*/
|
|---|
| 107 | MULAW_8B8KM , /* 8bit 8kHz mono*/
|
|---|
| 108 | MULAW_8B8KS /* 8bit 8kHz stereo*/
|
|---|
| 109 | };
|
|---|
| 110 |
|
|---|
| 111 | #endif
|
|---|
| 112 |
|
|---|
| 113 | /**@internal _usfind_matching_sample_rate
|
|---|
| 114 | * @param PULONG pulSampleRate
|
|---|
| 115 | * @return
|
|---|
| 116 | * @notes
|
|---|
| 117 | * The following function takes a sampling rate as input and finds out
|
|---|
| 118 | * the closest sampling rate in 11KHz, 22KHz, 44KHz and 8KHz. It retuns
|
|---|
| 119 | * the ordinal value of the matching sampling rate which should be used
|
|---|
| 120 | * to reference an array element by the frequency index.
|
|---|
| 121 | * This function is called by the DevCaps member function.
|
|---|
| 122 | *
|
|---|
| 123 | */
|
|---|
| 124 |
|
|---|
| 125 | // the following macro only takes positive arguments and returns the
|
|---|
| 126 | // absolute difference between the two arguments
|
|---|
| 127 | #define distance(x, y) ((x>y)? x-y : y-x)
|
|---|
| 128 |
|
|---|
| 129 | USHORT WAVEAUDIO::_usfind_matching_sample_rate(PULONG pulSampleRate)
|
|---|
| 130 | {
|
|---|
| 131 | // The aulSuppSampleRates array is used by member function
|
|---|
| 132 | // _usfind_matching_sample_rate to determine the sampling rate
|
|---|
| 133 | // ordinal
|
|---|
| 134 | static ULONG aulSuppSampleRates[NUMFREQS] = {11025, 22050, 44100, 8000};
|
|---|
| 135 | ULONG ulDistance, ulMinDistance = 0x7fffffff;
|
|---|
| 136 | USHORT us, usMatching;
|
|---|
| 137 |
|
|---|
| 138 | for ( us = 0; us < NUMFREQS; us++ ) {
|
|---|
| 139 | ulDistance = distance( *pulSampleRate, aulSuppSampleRates[us] );
|
|---|
| 140 | if (ulDistance < ulMinDistance) {
|
|---|
| 141 | ulMinDistance = ulDistance;
|
|---|
| 142 | usMatching = us;
|
|---|
| 143 | }
|
|---|
| 144 | }
|
|---|
| 145 | *pulSampleRate = aulSuppSampleRates[usMatching];
|
|---|
| 146 | return usMatching;
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | /**@internal
|
|---|
| 150 | * @param
|
|---|
| 151 | * @return
|
|---|
| 152 | * @notes
|
|---|
| 153 | *
|
|---|
| 154 | */
|
|---|
| 155 | void WAVEAUDIO::DevCaps(PAUDIO_CAPS pCaps)
|
|---|
| 156 | {
|
|---|
| 157 | USHORT usSampleRateIndex, usChannelIndex;
|
|---|
| 158 | ULONG ulSampleRate;
|
|---|
| 159 |
|
|---|
| 160 | // Rudi: moved from below
|
|---|
| 161 | pCaps->ulFlags = FIXED | // Fixed length data
|
|---|
| 162 | INPUT | // Input select is supported
|
|---|
| 163 | OUTPUT | // Output select is supported
|
|---|
| 164 | MONITOR | // Monitor is supported
|
|---|
| 165 | VOLUME; // Volume control is supported
|
|---|
| 166 |
|
|---|
| 167 | // This device driver supports Playback or Record Operations
|
|---|
| 168 | // anything else makes no sence. Note: This a per stream operation so
|
|---|
| 169 | // even if this sevice can do full-duplex, it can not do PLAY_AND_RECORD
|
|---|
| 170 |
|
|---|
| 171 | if ( pCaps->ulOperation != OPERATION_PLAY &&
|
|---|
| 172 | pCaps->ulOperation != OPERATION_RECORD ) {
|
|---|
| 173 | pCaps->ulSupport = UNSUPPORTED_OPERATION;
|
|---|
| 174 | return;
|
|---|
| 175 | }
|
|---|
| 176 |
|
|---|
| 177 | // Stereo or Mono only
|
|---|
| 178 | // Rudi: experimental 4 channel support
|
|---|
| 179 | if( !(pCaps->ulChannels == 1 ||
|
|---|
| 180 | pCaps->ulChannels == 2 ||
|
|---|
| 181 | pCaps->ulChannels == 4 &&
|
|---|
| 182 | pCaps->ulOperation == OPERATION_PLAY && pCaps->ulBitsPerSample == 16) )
|
|---|
| 183 | {
|
|---|
| 184 | pCaps->ulSupport = UNSUPPORTED_CHANNELS;
|
|---|
| 185 | return;
|
|---|
| 186 | }
|
|---|
| 187 |
|
|---|
| 188 | // supported bits per sample are 8 (for unsigned PCM, u-law or A-law )
|
|---|
| 189 | // and 16 (for 2's complement PCM)
|
|---|
| 190 | if (pCaps->ulBitsPerSample != 8 && pCaps->ulBitsPerSample != 16) {
|
|---|
| 191 | pCaps->ulSupport = UNSUPPORTED_BPS;
|
|---|
| 192 | return;
|
|---|
| 193 | }
|
|---|
| 194 |
|
|---|
| 195 | //save the sampling rate called with
|
|---|
| 196 | ulSampleRate = pCaps->ulSamplingRate;
|
|---|
| 197 | if (ulSampleRate < 4000 || ulSampleRate > 56000 ) {
|
|---|
| 198 | pCaps->ulSupport = UNSUPPORTED_RATE;
|
|---|
| 199 | return;
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | // find out the closest sampling rate (may or may not be the same )
|
|---|
| 203 | // from one of the following: 11025Hz, 22050Hz, 44100Hz and 8000Hz
|
|---|
| 204 | // _usfind_matching_sample_rate will update pCaps->ulSamplingRate if there
|
|---|
| 205 | // is not an exact match.
|
|---|
| 206 | usSampleRateIndex = _usfind_matching_sample_rate(&pCaps->ulSamplingRate);
|
|---|
| 207 | usChannelIndex = ( pCaps->ulChannels > 1 ) ? 1 : 0;
|
|---|
| 208 |
|
|---|
| 209 | // If _usfind_matching_sample_rate changed the sampling rate set
|
|---|
| 210 | // the best fit flag.
|
|---|
| 211 | if (ulSampleRate != pCaps->ulSamplingRate)
|
|---|
| 212 | pCaps->ulFlags |= BESTFIT_PROVIDED;
|
|---|
| 213 |
|
|---|
| 214 | // Determine the ulDataSubType and update any format specific flags
|
|---|
| 215 | // Note: All data types have more than one value.
|
|---|
| 216 | switch ( (USHORT)pCaps->ulDataType ) {
|
|---|
| 217 | case PCM:
|
|---|
| 218 | case DATATYPE_WAVEFORM:
|
|---|
| 219 | // determine subtype for PCM:
|
|---|
| 220 | pCaps->ulDataSubType = aaulWave[usSampleRateIndex]
|
|---|
| 221 | [(pCaps->ulBitsPerSample >> 3) - 1]
|
|---|
| 222 | [usChannelIndex];
|
|---|
| 223 | if (pCaps->ulBitsPerSample == 16)
|
|---|
| 224 | pCaps->ulFlags |= TWOS_COMPLEMENT; // 2's complement data
|
|---|
| 225 | break;
|
|---|
| 226 |
|
|---|
| 227 | case DATATYPE_AC3:
|
|---|
| 228 | if (pCaps->ulOperation == OPERATION_RECORD) {
|
|---|
| 229 | pCaps->ulSupport = UNSUPPORTED_DATATYPE;
|
|---|
| 230 | return;
|
|---|
| 231 | }
|
|---|
| 232 |
|
|---|
| 233 | pCaps->ulDataSubType = 0;
|
|---|
| 234 | break;
|
|---|
| 235 |
|
|---|
| 236 | #ifndef NO_xLAW
|
|---|
| 237 | //SvL: Does the SB live hardware support this or is it just a limitation of the linux driver?
|
|---|
| 238 | case A_LAW:
|
|---|
| 239 | case DATATYPE_ALAW:
|
|---|
| 240 | case DATATYPE_RIFF_ALAW:
|
|---|
| 241 | // determine subtype for A_LAW
|
|---|
| 242 | pCaps->ulDataSubType = aaulAlaw[usSampleRateIndex][usChannelIndex];
|
|---|
| 243 | break;
|
|---|
| 244 |
|
|---|
| 245 | case MU_LAW:
|
|---|
| 246 | case DATATYPE_MULAW:
|
|---|
| 247 | case DATATYPE_RIFF_MULAW:
|
|---|
| 248 | // determine subtype for MU_LAW
|
|---|
| 249 | pCaps->ulDataSubType = aaulMulaw[usSampleRateIndex][usChannelIndex];
|
|---|
| 250 | break;
|
|---|
| 251 | #endif
|
|---|
| 252 |
|
|---|
| 253 | default:
|
|---|
| 254 | pCaps->ulSupport = UNSUPPORTED_DATATYPE;
|
|---|
| 255 | return;
|
|---|
| 256 | } // end switch
|
|---|
| 257 |
|
|---|
| 258 |
|
|---|
| 259 | // Full Duplex Enabling Stuff here !!
|
|---|
| 260 | // The number of resource units is described in the MMPM2.INI
|
|---|
| 261 | // This can be thought of the number of active streams the
|
|---|
| 262 | // driver can manage at one time. We list this number as 2.
|
|---|
| 263 | // we tell MMPM here how many of these units THIS stream will consume.
|
|---|
| 264 | // The answer is so simple it's brilliant, (Thanks to Joe Nord at Crystal
|
|---|
| 265 | // Semi) If we are enabled to do full-duplex this stream will consume 1
|
|---|
| 266 | // unit, If we are not enabled to do full-duplex this stream will consume 2
|
|---|
| 267 | // (or all the available units)
|
|---|
| 268 | // Along with the resource units, we defined 2 resources classes,
|
|---|
| 269 | // one for playback and one for capture. We tell MMPM (in the MMPM2.INI)
|
|---|
| 270 | // that we can handle doing 1 playback and 1 capture stream or 1 capture and
|
|---|
| 271 | // one playback stream at the same time. (Valid Resource combos in the
|
|---|
| 272 | // MMPM2.INI) check if we are a playback or capture and set the correct
|
|---|
| 273 | // resource class (Playback = 1, Capture = 2)
|
|---|
| 274 |
|
|---|
| 275 | pCaps->ulResourceUnits = 1;
|
|---|
| 276 | pCaps->ulResourceClass = ( pCaps->ulOperation == OPERATION_PLAY ) ?
|
|---|
| 277 | WAVE_PLAYBACK_CLASS : WAVE_RECORD_CLASS;
|
|---|
| 278 |
|
|---|
| 279 | // Rudi: Joe Nord said it so, docs say it's unused
|
|---|
| 280 | // pCaps->fCanRecord = 1; // Yes Virgina we can record
|
|---|
| 281 | pCaps->fCanRecord = 0;
|
|---|
| 282 |
|
|---|
| 283 | // Rudi: align on "whole" samples
|
|---|
| 284 | // pCaps->ulBlockAlign = 1; // Block alignment for this mode
|
|---|
| 285 | pCaps->ulBlockAlign = (pCaps->ulChannels * pCaps->ulBitsPerSample) >> 3;
|
|---|
| 286 |
|
|---|
| 287 | //return success
|
|---|
| 288 | pCaps->ulSupport = SUPPORT_SUCCESS;
|
|---|
| 289 | }
|
|---|
| 290 |
|
|---|
| 291 | /**@internal
|
|---|
| 292 | * @param
|
|---|
| 293 | * @return
|
|---|
| 294 | * @notes
|
|---|
| 295 | *
|
|---|
| 296 | */
|
|---|
| 297 | void WAVEAUDIO::DevCaps(LPDAUDIO_CAPS lpCaps)
|
|---|
| 298 | {
|
|---|
| 299 | lpCaps->dwFlags = DAUDIOCAPS_PRIMARYMONO |
|
|---|
| 300 | DAUDIOCAPS_PRIMARYSTEREO |
|
|---|
| 301 | DAUDIOCAPS_PRIMARY8BIT |
|
|---|
| 302 | DAUDIOCAPS_PRIMARY16BIT |
|
|---|
| 303 | DAUDIOCAPS_CONTINUOUSRATE |
|
|---|
| 304 | DAUDIOCAPS_CERTIFIED |
|
|---|
| 305 | DAUDIOCAPS_SECONDARYMONO |
|
|---|
| 306 | DAUDIOCAPS_SECONDARYSTEREO |
|
|---|
| 307 | DAUDIOCAPS_SECONDARY8BIT |
|
|---|
| 308 | DAUDIOCAPS_SECONDARY16BIT;
|
|---|
| 309 |
|
|---|
| 310 | lpCaps->dwMinSecondarySampleRate = 8000; //SBLIVECAPS_MINSAMPLERATE;
|
|---|
| 311 | lpCaps->dwMaxSecondarySampleRate = 48000; //SBLIVECAPS_MAXSAMPLERATE;
|
|---|
| 312 |
|
|---|
| 313 | lpCaps->dwMaxHwMixingAllBuffers = //SBLIVECAPS_MAXSTREAMS;
|
|---|
| 314 | lpCaps->dwMaxHwMixingStaticBuffers = //SBLIVECAPS_MAXSTREAMS;
|
|---|
| 315 | lpCaps->dwMaxHwMixingStreamingBuffers = //SBLIVECAPS_MAXSTREAMS;
|
|---|
| 316 | lpCaps->dwPrimaryBuffers = 1;
|
|---|
| 317 |
|
|---|
| 318 | lpCaps->dwMaxHw3DAllBuffers =
|
|---|
| 319 | lpCaps->dwMaxHw3DStaticBuffers =
|
|---|
| 320 | lpCaps->dwMaxHw3DStreamingBuffers =
|
|---|
| 321 | lpCaps->dwFreeHw3DAllBuffers =
|
|---|
| 322 | lpCaps->dwFreeHw3DStaticBuffers =
|
|---|
| 323 | lpCaps->dwFreeHw3DStreamingBuffers =
|
|---|
| 324 | lpCaps->dwTotalHwMemBytes =
|
|---|
| 325 | lpCaps->dwFreeHwMemBytes =
|
|---|
| 326 | lpCaps->dwMaxContigFreeHwMemBytes =
|
|---|
| 327 | lpCaps->dwUnlockTransferRateHwBuffers =
|
|---|
| 328 | lpCaps->dwPlayCpuOverheadSwBuffers =
|
|---|
| 329 | lpCaps->dwReserved1 =
|
|---|
| 330 | lpCaps->dwReserved2 = 0;
|
|---|
| 331 | }
|
|---|
| 332 |
|
|---|
| 333 | /**@internal
|
|---|
| 334 | * @param
|
|---|
| 335 | * @return
|
|---|
| 336 | * @notes
|
|---|
| 337 | *
|
|---|
| 338 | */
|
|---|
| 339 | virtual void WAVEAUDIO::ConfigDev(STREAM *stream, PWAVECONFIGINFO pConfigInfo)
|
|---|
| 340 | {
|
|---|
| 341 | FORMAT_INFO formatInfo;
|
|---|
| 342 | ULONG /*ulCount, */ulConsumeRate, ulBytesPerIRQ, uSampleShift;
|
|---|
| 343 |
|
|---|
| 344 | // Set the clock select bits (_ucClockData)
|
|---|
| 345 |
|
|---|
| 346 | // Set up _ucFormatData and write usSilence for the WAVESTREAM
|
|---|
| 347 | switch (pConfigInfo->usDataType) {
|
|---|
| 348 | case PCM:
|
|---|
| 349 | case DATATYPE_AC3:
|
|---|
| 350 | case DATATYPE_WAVEFORM:
|
|---|
| 351 | pConfigInfo->usSilence =
|
|---|
| 352 | ( pConfigInfo->usBitsPerSample == 16 ) ? 0x0000 : 0x8080;
|
|---|
| 353 | break;
|
|---|
| 354 |
|
|---|
| 355 | #ifndef NO_xLAW
|
|---|
| 356 | case DATATYPE_ALAW:
|
|---|
| 357 | case DATATYPE_RIFF_ALAW:
|
|---|
| 358 | case A_LAW:
|
|---|
| 359 | pConfigInfo->usSilence = 0x5555;
|
|---|
| 360 | break;
|
|---|
| 361 |
|
|---|
| 362 | case DATATYPE_MULAW:
|
|---|
| 363 | case DATATYPE_RIFF_MULAW:
|
|---|
| 364 | case MU_LAW:
|
|---|
| 365 | pConfigInfo->usSilence = 0x7F7F;
|
|---|
| 366 | break;
|
|---|
| 367 | #endif
|
|---|
| 368 | } /* endswitch */
|
|---|
| 369 |
|
|---|
| 370 | // Set the Stereo bit if necessary
|
|---|
| 371 | // if (pConfigInfo->usNumChannels == 2)
|
|---|
| 372 | // _ucFormatData |= STEREO_BIT;
|
|---|
| 373 |
|
|---|
| 374 | uSampleShift = (pConfigInfo->usBitsPerSample == 16);
|
|---|
| 375 |
|
|---|
| 376 | // For All Devices :
|
|---|
| 377 | // We want to generate 32 interrupts per second but if this requires that
|
|---|
| 378 | // we copy more than 0x0800 bytes of data per irq. Then we recalculate
|
|---|
| 379 | // If more that 0x0800 bytes is transfered per interrupt then there
|
|---|
| 380 | // may be problems with apps that use DART and stream small buffers
|
|---|
| 381 |
|
|---|
| 382 | ulBytesPerIRQ = pConfigInfo->ulSampleRate >> 5;
|
|---|
| 383 |
|
|---|
| 384 | // Calculate the BytesPerIRQ
|
|---|
| 385 | // The BytesPerIRQ is the number of bytes consumed by this data format
|
|---|
| 386 | // for every interrupt generated by the codec.
|
|---|
| 387 | // This inforamtion is returned to the WAVESTREAM which uses it in
|
|---|
| 388 | // buffer management decisions....
|
|---|
| 389 |
|
|---|
| 390 | // Rudi: experimental 4 channel support
|
|---|
| 391 | ulBytesPerIRQ *= pConfigInfo->usNumChannels << uSampleShift;
|
|---|
| 392 | // if (pConfigInfo->usBitsPerSample == 16) ulBytesPerIRQ <<= 1;
|
|---|
| 393 | // if (pConfigInfo->usNumChannels == 2) ulBytesPerIRQ <<= 1;
|
|---|
| 394 |
|
|---|
| 395 | if( ulBytesPerIRQ > 2048 ) ulBytesPerIRQ = 2048;
|
|---|
| 396 | pConfigInfo->ulBytesPerIRQ = ulBytesPerIRQ;
|
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 | #if 0
|
|---|
| 400 | // Check that we are at or below 0x800 bytes per irq
|
|---|
| 401 | // if not reclaculate based on 0x800 bytes per irq
|
|---|
| 402 |
|
|---|
| 403 | if (ulBytesPerIRQ > 0x00000800) {
|
|---|
| 404 | ulCount = 0x00000800;
|
|---|
| 405 | pConfigInfo->ulBytesPerIRQ = 0x00000800;
|
|---|
| 406 |
|
|---|
| 407 | // Rudi: experimental 4 channel support
|
|---|
| 408 | ulCount /= pConfigInfo->usNumChannels << uSampleShift;
|
|---|
| 409 | // if (pConfigInfo->usBitsPerSample == 16) ulCount >>= 1;
|
|---|
| 410 | // if (pConfigInfo->usNumChannels == 2) ulCount >>= 1;
|
|---|
| 411 |
|
|---|
| 412 | _usCountData = (USHORT)(ulCount -1);
|
|---|
| 413 | }
|
|---|
| 414 | #endif
|
|---|
| 415 |
|
|---|
| 416 |
|
|---|
| 417 | // Calculate the PCMConsumeRate
|
|---|
| 418 | // The consume rate is the number of bytes consumed by this data format
|
|---|
| 419 | // per second. It calculated by taking the following equation:
|
|---|
| 420 | // sampling rate * (BitsPerSample/8) * NumChannels
|
|---|
| 421 | // This info is returned to the WAVESTREAM and used to calculate stream time
|
|---|
| 422 |
|
|---|
| 423 | ulConsumeRate = pConfigInfo->ulSampleRate;
|
|---|
| 424 | // Rudi: experimental 4 channel support
|
|---|
| 425 | ulConsumeRate *= pConfigInfo->usNumChannels << uSampleShift;
|
|---|
| 426 | // if (pConfigInfo->usBitsPerSample == 16) ulConsumeRate <<= 1;
|
|---|
| 427 | // if (pConfigInfo->usNumChannels == 2) ulConsumeRate <<= 1;
|
|---|
| 428 | pConfigInfo->ulPCMConsumeRate = ulConsumeRate;
|
|---|
| 429 |
|
|---|
| 430 |
|
|---|
| 431 | formatInfo.ulSampleRate = pConfigInfo->ulSampleRate;
|
|---|
| 432 | formatInfo.ulNumChannels = pConfigInfo->usNumChannels;
|
|---|
| 433 | formatInfo.ulBitsPerSample = pConfigInfo->usBitsPerSample;
|
|---|
| 434 |
|
|---|
| 435 | switch( pConfigInfo->usDataType )
|
|---|
| 436 | {
|
|---|
| 437 | #ifndef NO_xLAW
|
|---|
| 438 | case A_LAW:
|
|---|
| 439 | case DATATYPE_ALAW:
|
|---|
| 440 | case DATATYPE_RIFF_ALAW:
|
|---|
| 441 | formatInfo.ulDataType = AFMT_A_LAW;
|
|---|
| 442 | break;
|
|---|
| 443 |
|
|---|
| 444 | case MU_LAW:
|
|---|
| 445 | case DATATYPE_MULAW:
|
|---|
| 446 | case DATATYPE_RIFF_MULAW:
|
|---|
| 447 | formatInfo.ulDataType = AFMT_MU_LAW;
|
|---|
| 448 | break;
|
|---|
| 449 | #endif
|
|---|
| 450 |
|
|---|
| 451 | case DATATYPE_AC3:
|
|---|
| 452 | formatInfo.ulDataType = 0x00000400L; // AFMT_AC3
|
|---|
| 453 | break;
|
|---|
| 454 |
|
|---|
| 455 | default:
|
|---|
| 456 | formatInfo.ulDataType =
|
|---|
| 457 | ( pConfigInfo->usBitsPerSample == 8 ) ? AFMT_U8 : AFMT_S16_LE;
|
|---|
| 458 | }
|
|---|
| 459 |
|
|---|
| 460 | OSS16_StreamSetFormat(stream, (ULONG)&formatInfo);
|
|---|
| 461 | }
|
|---|
| 462 |
|
|---|
| 463 |
|
|---|
| 464 | /**@internal Start
|
|---|
| 465 | * @param None
|
|---|
| 466 | * @return
|
|---|
| 467 | * @notes
|
|---|
| 468 | */
|
|---|
| 469 | int WAVEAUDIO::Start(STREAM *stream)
|
|---|
| 470 | {
|
|---|
| 471 | return OSS16_StartStream(stream);
|
|---|
| 472 | }
|
|---|
| 473 |
|
|---|
| 474 | /**@internal Stop
|
|---|
| 475 | * @param None
|
|---|
| 476 | * @return
|
|---|
| 477 | * @notes
|
|---|
| 478 | */
|
|---|
| 479 | int WAVEAUDIO::Stop(STREAM *stream)
|
|---|
| 480 | {
|
|---|
| 481 | return OSS16_StopStream(stream);
|
|---|
| 482 | }
|
|---|
| 483 |
|
|---|
| 484 |
|
|---|
| 485 | /**@internal Pause
|
|---|
| 486 | * @param None
|
|---|
| 487 | * @return int 1
|
|---|
| 488 | * @notes
|
|---|
| 489 | * stub function pause is implemented as a stop by the stream
|
|---|
| 490 | */
|
|---|
| 491 | int WAVEAUDIO::Pause(STREAM */*stream*/)
|
|---|
| 492 | {
|
|---|
| 493 | return 1;
|
|---|
| 494 | }
|
|---|
| 495 |
|
|---|
| 496 | /**@internal Resume
|
|---|
| 497 | * @param None
|
|---|
| 498 | * @return int 1
|
|---|
| 499 | * @notes
|
|---|
| 500 | * stub function resume is implemented as a start by the stream
|
|---|
| 501 | */
|
|---|
| 502 | int WAVEAUDIO::Resume(STREAM */*stream*/)
|
|---|
| 503 | {
|
|---|
| 504 | return 1;
|
|---|
| 505 | }
|
|---|
| 506 |
|
|---|
| 507 |
|
|---|