source: sbliveos2/trunk/drv16/waudio.cpp@ 302

Last change on this file since 302 was 178, checked in by sandervl, 24 years ago

DirectAudio interface updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/* $Id: waudio.cpp 178 2001-04-30 21:08:00Z sandervl $ */
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
27#include "waudio.hpp"
28
29
30//
31//
32// the following 3-D array defines the subtypes for DATATYPE_WAVEFORM
33// The array is 4x2x2 and is indexed using frequency index, bits per
34// sample being 8 or 16 represented by 0 or 1 resp. and mono or stereo
35// mode represented by 0 or 1 respectively. For eg. to find out the
36// subtype for 22050Hz sampling frequency, using 16 bits per sample
37// and stereo mode, we use aaulWave[FREQ22KHZ][BPS16][1]. This avoids
38// inefficient nested if's and switches to find a matching value given
39// the same.
40//
41ULONG aaulWave[NUMFREQS][BPSTYPES][MONOSTEREO] = {
42 WAVE_FORMAT_1M08, /* 11.025kHz, 8-bit Mono */
43 WAVE_FORMAT_1S08, /* 11.025kHz, 8-bit Stereo */
44 WAVE_FORMAT_1M16, /* 11.025kHz, 16-bit Mono */
45 WAVE_FORMAT_1S16, /* 11.025kHz, 16-bit Stereo */
46 WAVE_FORMAT_2M08, /* 22.05kHz , 8-bit Mono */
47 WAVE_FORMAT_2S08, /* 22.05kHz , 8-bit Stereo */
48 WAVE_FORMAT_2M16, /* 22.05kHz , 16-bit Mono */
49 WAVE_FORMAT_2S16, /* 22.05kHz , 16-bit Stereo */
50 WAVE_FORMAT_4M08, /* 44.1kHz , 8-bit Mono */
51 WAVE_FORMAT_4S08, /* 44.1kHz , 8-bit Stereo */
52 WAVE_FORMAT_4M16, /* 44.1kHz , 16-bit Mono */
53 WAVE_FORMAT_4S16, /* 44.1kHz , 16-bit Stereo */
54 WAVE_FORMAT_8M08, /* 8.0kHz , 8-bit Mono */
55 WAVE_FORMAT_8S08, /* 8.0kHz , 8-bit Stereo */
56 WAVE_FORMAT_8M16, /* 8.0kHz , 16-bit Mono */
57 WAVE_FORMAT_8S16 /* 8.0kHz , 16-bit Stereo */
58 };
59
60//
61// the following 2-D array defines the subtypes for DATATYPE_ALAW
62// it is indexed by the sampling rate ordinal (from
63// _usfind_matching_sample_rate) and the number of channels
64ULONG aaulAlaw[NUMFREQS][MONOSTEREO] = {
65 ALAW_8B11KM, /* 8bit 11kHz mono*/
66 ALAW_8B11KS, /* 8bit 11kHz stereo*/
67 ALAW_8B22KM, /* 8bit 22kHz mono*/
68 ALAW_8B22KS, /* 8bit 22kHz stereo*/
69 ALAW_8B44KM, /* 8bit 44kHz mono*/
70 ALAW_8B44KS, /* 8bit 44kHz stereo*/
71 ALAW_8B8KM , /* 8bit 8kHz mono*/
72 ALAW_8B8KS /* 8bit 8kHz stereo*/
73 };
74//
75// the following 2-D array defines the subtypes for DATATYPE_MULAW
76// it is indexed by the sampling rate ordinal (from
77// _usfind_matching_sample_rate) and the number of channels
78ULONG aaulMulaw[NUMFREQS][MONOSTEREO] = {
79 MULAW_8B11KM, /* 8bit 11kHz mono*/
80 MULAW_8B11KS, /* 8bit 11kHz stereo*/
81 MULAW_8B22KM, /* 8bit 22kHz mono*/
82 MULAW_8B22KS, /* 8bit 22kHz stereo*/
83 MULAW_8B44KM, /* 8bit 44kHz mono*/
84 MULAW_8B44KS, /* 8bit 44kHz stereo*/
85 MULAW_8B8KM , /* 8bit 8kHz mono*/
86 MULAW_8B8KS /* 8bit 8kHz stereo*/
87 };
88
89//
90// The aulSuppSampleRates array is used by member function
91// _usfind_matching_sample_rate to determine the sampling rate
92// ordinal
93ULONG aulSuppSampleRates[] = {11025, 22050, 44100, 8000};
94
95// the following macro only takes positive arguments and returns the
96// absolute difference between the two arguments
97#define distance(x, y) ((x>y)? x-y : y-x)
98
99/**@internal _usfind_matching_sample_rate
100 * @param PULONG pulSampleRate
101 * @return
102 * @notes
103 * The following function takes a sampling rate as input and finds out
104 * the closest sampling rate in 11KHz, 22KHz, 44KHz and 8KHz. It retuns
105 * the ordinal value of the matching sampling rate which should be used
106 * to reference an array element by the frequency index.
107 * This function is called by the DevCaps member function.
108 *
109 */
110USHORT WAVEAUDIO::_usfind_matching_sample_rate(PULONG pulSampleRate)
111{
112ULONG ulMinDistance = 0x7fffffff;
113USHORT usMatching;
114USHORT us;
115
116 for ( us = 0; us < 4; us++ ) {
117 ULONG ulDistance = distance( *pulSampleRate, aulSuppSampleRates[us] );
118 if (ulDistance < ulMinDistance) {
119 ulMinDistance = ulDistance;
120 usMatching = us;
121 }
122 }
123 *pulSampleRate = aulSuppSampleRates[usMatching];
124 return usMatching;
125}
126
127/**@internal
128 * @param
129 * @return
130 * @notes
131 *
132 */
133void WAVEAUDIO::DevCaps(PAUDIO_CAPS pCaps)
134{
135USHORT usSampleRateIndex;
136ULONG ulSampleRate;
137
138
139 // This device driver supports Playback or Record Operations
140 // anything else makes no sence. Note: This a per stream operation so
141 // even if this sevice can do full-duplex, it can not do PLAY_AND_RECORD
142
143 if ( pCaps->ulOperation != OPERATION_PLAY &&
144 pCaps->ulOperation != OPERATION_RECORD ) {
145 pCaps->ulSupport = UNSUPPORTED_OPERATION;
146 return;
147 }
148
149 // Stereo or Mono only
150 if (pCaps->ulChannels != 1 && pCaps->ulChannels != 2) {
151 pCaps->ulSupport = UNSUPPORTED_CHANNELS;
152 return;
153 }
154
155 // supported bits per sample are 8 (for unsigned PCM, u-law or A-law )
156 // and 16 (for 2's complement PCM)
157 if (pCaps->ulBitsPerSample != 8 && pCaps->ulBitsPerSample != 16) {
158 pCaps->ulSupport = UNSUPPORTED_BPS;
159 return;
160 }
161
162 ulSampleRate = pCaps->ulSamplingRate; //save the sampling rate called with
163
164 // find out the closest sampling rate (may or may not be the same )
165 // from one of the following: 11025Hz, 22050Hz, 44100Hz and 8000Hz
166 // _usfind_matching_sample_rate will update pCaps->ulSamplingRate if there
167 // is not an exact match.
168 usSampleRateIndex = _usfind_matching_sample_rate(&pCaps->ulSamplingRate);
169
170 // If _usfind_matching_sample_rate changed the sampling rate set
171 // the best fit flag.
172 if (ulSampleRate != pCaps->ulSamplingRate)
173 pCaps->ulFlags |= BESTFIT_PROVIDED;
174
175 // Determine the ulDataSubType and update any format specific flags
176 // Note: All data types have more than one value.
177 switch ( pCaps->ulDataType ) {
178 case DATATYPE_WAVEFORM:
179 case PCM:
180 // determine subtype for PCM:
181 pCaps->ulDataSubType = aaulWave[usSampleRateIndex]
182 [(pCaps->ulBitsPerSample-8)/8]
183 [pCaps->ulChannels-1];
184 if (pCaps->ulBitsPerSample == 16)
185 pCaps->ulFlags |= TWOS_COMPLEMENT; // 2's complement data
186 break;
187
188#if 0
189//SvL: Does the SB live hardware support this or is it just a limitation of the linux driver?
190 case DATATYPE_ALAW:
191 case DATATYPE_RIFF_ALAW:
192 case A_LAW:
193 // determine subtype for A_LAW
194 pCaps->ulDataSubType = aaulAlaw[usSampleRateIndex][pCaps->ulChannels-1];
195 break;
196
197 case DATATYPE_MULAW:
198 case DATATYPE_RIFF_MULAW:
199 case MU_LAW:
200 // determine subtype for MU_LAW
201 pCaps->ulDataSubType = aaulMulaw[usSampleRateIndex][pCaps->ulChannels-1];
202 break;
203#endif
204 default:
205 pCaps->ulSupport = UNSUPPORTED_DATATYPE;
206 return;
207 } // end switch
208
209 pCaps->ulFlags = FIXED | // Fixed length data
210 LEFT_ALIGNED | // Left align bits on byte bndry
211 BIG_ENDIAN | // MSB's first (motorola format)
212 INPUT | // Input select is supported
213 OUTPUT | // Output select is supported
214 MONITOR | // Monitor is supported
215 VOLUME; // Volume control is supported
216
217 // Full Duplex Enabling Stuff here !!
218 // The number of resource units is described in the MMPM2.INI
219 // This can be thought of the number of active streams the
220 // driver can manage at one time. We list this number as 2.
221 // we tell MMPM here how many of these units THIS stream will consume.
222 // The answer is so simple it's brilliant, (Thanks to Joe Nord at Crystal
223 // Semi) If we are enabled to do full-duplex this stream will consume 1
224 // unit, If we are not enabled to do full-duplex this stream will consume 2
225 // (or all the available units)
226 // Along with the resource units, we defined 2 resources classes,
227 // one for playback and one for capture. We tell MMPM (in the MMPM2.INI)
228 // that we can handle doing 1 playback and 1 capture stream or 1 capture and
229 // one playback stream at the same time. (Valid Resource combos in the
230 // MMPM2.INI) check if we are a playback or capture and set the correct
231 // resource class (Playback = 1, Capture = 2)
232
233 pCaps->ulResourceUnits = 1;
234
235 if ( pCaps->ulOperation == OPERATION_PLAY)
236 pCaps->ulResourceClass = 1;
237 else
238 pCaps->ulResourceClass = 2;
239 pCaps->fCanRecord = 1; // Yes Virgina we can record
240 pCaps->ulBlockAlign = 1; // Block alignment for this mode
241
242 //return success
243 pCaps->ulSupport = SUPPORT_SUCCESS;
244
245}
246/**@internal
247 * @param
248 * @return
249 * @notes
250 *
251 */
252void WAVEAUDIO::DevCaps(LPDAUDIO_CAPS lpCaps)
253{
254 lpCaps->dwFlags = DAUDIOCAPS_PRIMARYMONO |
255 DAUDIOCAPS_PRIMARYSTEREO |
256 DAUDIOCAPS_PRIMARY8BIT |
257 DAUDIOCAPS_PRIMARY16BIT |
258 DAUDIOCAPS_CONTINUOUSRATE |
259 DAUDIOCAPS_CERTIFIED |
260 DAUDIOCAPS_SECONDARYMONO |
261 DAUDIOCAPS_SECONDARYSTEREO |
262 DAUDIOCAPS_SECONDARY8BIT |
263 DAUDIOCAPS_SECONDARY16BIT;
264
265 lpCaps->dwMinSecondarySampleRate = SBLIVECAPS_MINSAMPLERATE;
266 lpCaps->dwMaxSecondarySampleRate = SBLIVECAPS_MAXSAMPLERATE;
267 lpCaps->dwPrimaryBuffers = 1;
268 lpCaps->dwMaxHwMixingAllBuffers = SBLIVECAPS_MAXSTREAMS;
269 lpCaps->dwMaxHwMixingStaticBuffers = SBLIVECAPS_MAXSTREAMS;
270 lpCaps->dwMaxHwMixingStreamingBuffers = SBLIVECAPS_MAXSTREAMS;
271 lpCaps->dwMaxHw3DAllBuffers = 0;
272 lpCaps->dwMaxHw3DStaticBuffers = 0;
273 lpCaps->dwMaxHw3DStreamingBuffers = 0;
274 lpCaps->dwFreeHw3DAllBuffers = 0;
275 lpCaps->dwFreeHw3DStaticBuffers = 0;
276 lpCaps->dwFreeHw3DStreamingBuffers = 0;
277 lpCaps->dwTotalHwMemBytes = 0;
278 lpCaps->dwFreeHwMemBytes = 0;
279 lpCaps->dwMaxContigFreeHwMemBytes = 0;
280 lpCaps->dwUnlockTransferRateHwBuffers = 0;
281 lpCaps->dwPlayCpuOverheadSwBuffers = 0;
282 lpCaps->dwReserved1 = 0;
283 lpCaps->dwReserved2 = 0;
284}
285
286/**@internal
287 * @param
288 * @return
289 * @notes
290 *
291 */
292#pragma off (unreferenced)
293virtual void WAVEAUDIO::ConfigDev(STREAM *stream, PWAVECONFIGINFO pConfigInfo)
294#pragma on (unreferenced)
295{
296 ULONG ulCount, ulConsumeRate, ulBytesPerIRQ;
297
298 // Set the clock select bits (_ucClockData)
299
300 // Set up _ucFormatData and write usSilence for the WAVESTREAM
301 switch (pConfigInfo->ulDataType) {
302 case DATATYPE_WAVEFORM:
303 case PCM:
304 if (pConfigInfo->ulBitsPerSample == 16) {
305 pConfigInfo->usSilence = 0x0000;
306 }
307 else {
308 pConfigInfo->usSilence = 0x8080;
309 }
310 break;
311
312 case DATATYPE_ALAW:
313 case DATATYPE_RIFF_ALAW:
314 case A_LAW:
315 pConfigInfo->usSilence = 0x5555;
316 break;
317
318 case DATATYPE_MULAW:
319 case DATATYPE_RIFF_MULAW:
320 case MU_LAW:
321 pConfigInfo->usSilence = 0x7F7F;
322 break;
323 } /* endswitch */
324
325 // Set the Stereo bit if necessary
326// if (pConfigInfo->ulNumChannels == 2)
327// _ucFormatData |= STEREO_BIT;
328
329 // calculate the count register value: _usCountData
330 // according to the CS4232 Spec the Upper and Lower Base registers are
331 // loaded with the number of samples - 1 to be transfered between interrupts
332 // (for all data formats except ADPCM)
333 // For All Devices :
334 // We want to generate 32 interrupts per second but if this requires that
335 // we copy more than 0x0800 bytes of data per irq. Then we recalculate
336 // If more that 0x0800 bytes is transfered per interrupt then there
337 // may be problems with apps that use DART and stream small buffers
338
339 ulCount = pConfigInfo->ulSampleRate;
340 ulCount >>= 5;
341 ulBytesPerIRQ = ulCount;
342 _usCountData = (USHORT)(ulCount -1);
343
344 // Calculate the BytesPerIRQ
345 // The BytesPerIRQ is the number of bytes consumed by this data format
346 // for every interrupt generated by the codec.
347 // This inforamtion is returned to the WAVESTREAM which uses it in
348 // buffer management decisions....
349
350 if (pConfigInfo->ulBitsPerSample == 16)
351 ulBytesPerIRQ <<= 1;
352 if (pConfigInfo->ulNumChannels == 2)
353 ulBytesPerIRQ <<= 1;
354 pConfigInfo->ulBytesPerIRQ = ulBytesPerIRQ;
355
356 // Check that we are at or below 0x800 bytes per irq
357 // if not reclaculate based on 0x800 bytes per irq
358
359 if (ulBytesPerIRQ > 0x00000800) {
360 ulCount = 0x00000800;
361 pConfigInfo->ulBytesPerIRQ = 0x00000800;
362 if (pConfigInfo->ulBitsPerSample == 16)
363 ulCount >>= 1;
364 if (pConfigInfo->ulNumChannels == 2)
365 ulCount >>= 1;
366 _usCountData = (USHORT)(ulCount -1);
367 }
368
369 // Calculate the PCMConsumeRate
370 // The consume rate is the number of bytes consumed by this data format
371 // per second. It calculated by taking the following equation:
372 // sampling rate * (BitsPerSample/8) * NumChannels
373 // This info is returned to the WAVESTREAM and used to calculate stream time
374
375 ulConsumeRate = pConfigInfo->ulSampleRate;
376 if (pConfigInfo->ulBitsPerSample == 16)
377 ulConsumeRate <<= 1;
378 if (pConfigInfo->ulNumChannels == 2)
379 ulConsumeRate <<= 1;
380 pConfigInfo->ulPCMConsumeRate = ulConsumeRate;
381
382}
383/**@internal Pause
384 * @param None
385 * @return int 1
386 * @notes
387 * stub function pause is implemented as a stop by the stream
388 */
389#pragma off (unreferenced)
390int WAVEAUDIO::Pause(STREAM *stream)
391#pragma on (unreferenced)
392{
393 return 1;
394}
395/**@internal Resume
396 * @param None
397 * @return int 1
398 * @notes
399 * stub function resume is implemented as a start by the stream
400 */
401#pragma off (unreferenced)
402int WAVEAUDIO::Resume(STREAM *stream)
403#pragma on (unreferenced)
404{
405 return 1;
406}
407
408#pragma code_seg ("_inittext");
409#pragma data_seg ("_initdata","endds");
410
411/**@internal
412 * @param
413 * @return
414 * @notes
415 *
416 */
417void WAVEAUDIO::_vSetup()
418{
419}
Note: See TracBrowser for help on using the repository browser.