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

Last change on this file since 175 was 142, checked in by ktk, 25 years ago

Import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: waudio.cpp 142 2000-04-23 14:55:46Z ktk $ */
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 */
252#pragma off (unreferenced)
253virtual void WAVEAUDIO::ConfigDev(STREAM *stream, PWAVECONFIGINFO pConfigInfo)
254#pragma on (unreferenced)
255{
256 ULONG ulCount, ulConsumeRate, ulBytesPerIRQ;
257
258 // Set the clock select bits (_ucClockData)
259
260 // Set up _ucFormatData and write usSilence for the WAVESTREAM
261 switch (pConfigInfo->ulDataType) {
262 case DATATYPE_WAVEFORM:
263 case PCM:
264 if (pConfigInfo->ulBitsPerSample == 16) {
265 pConfigInfo->usSilence = 0x0000;
266 }
267 else {
268 pConfigInfo->usSilence = 0x8080;
269 }
270 break;
271
272 case DATATYPE_ALAW:
273 case DATATYPE_RIFF_ALAW:
274 case A_LAW:
275 pConfigInfo->usSilence = 0x5555;
276 break;
277
278 case DATATYPE_MULAW:
279 case DATATYPE_RIFF_MULAW:
280 case MU_LAW:
281 pConfigInfo->usSilence = 0x7F7F;
282 break;
283 } /* endswitch */
284
285 // Set the Stereo bit if necessary
286// if (pConfigInfo->ulNumChannels == 2)
287// _ucFormatData |= STEREO_BIT;
288
289 // calculate the count register value: _usCountData
290 // according to the CS4232 Spec the Upper and Lower Base registers are
291 // loaded with the number of samples - 1 to be transfered between interrupts
292 // (for all data formats except ADPCM)
293 // For All Devices :
294 // We want to generate 32 interrupts per second but if this requires that
295 // we copy more than 0x0800 bytes of data per irq. Then we recalculate
296 // If more that 0x0800 bytes is transfered per interrupt then there
297 // may be problems with apps that use DART and stream small buffers
298
299 ulCount = pConfigInfo->ulSampleRate;
300 ulCount >>= 5;
301 ulBytesPerIRQ = ulCount;
302 _usCountData = (USHORT)(ulCount -1);
303
304 // Calculate the BytesPerIRQ
305 // The BytesPerIRQ is the number of bytes consumed by this data format
306 // for every interrupt generated by the codec.
307 // This inforamtion is returned to the WAVESTREAM which uses it in
308 // buffer management decisions....
309
310 if (pConfigInfo->ulBitsPerSample == 16)
311 ulBytesPerIRQ <<= 1;
312 if (pConfigInfo->ulNumChannels == 2)
313 ulBytesPerIRQ <<= 1;
314 pConfigInfo->ulBytesPerIRQ = ulBytesPerIRQ;
315
316 // Check that we are at or below 0x800 bytes per irq
317 // if not reclaculate based on 0x800 bytes per irq
318
319 if (ulBytesPerIRQ > 0x00000800) {
320 ulCount = 0x00000800;
321 pConfigInfo->ulBytesPerIRQ = 0x00000800;
322 if (pConfigInfo->ulBitsPerSample == 16)
323 ulCount >>= 1;
324 if (pConfigInfo->ulNumChannels == 2)
325 ulCount >>= 1;
326 _usCountData = (USHORT)(ulCount -1);
327 }
328
329 // Calculate the PCMConsumeRate
330 // The consume rate is the number of bytes consumed by this data format
331 // per second. It calculated by taking the following equation:
332 // sampling rate * (BitsPerSample/8) * NumChannels
333 // This info is returned to the WAVESTREAM and used to calculate stream time
334
335 ulConsumeRate = pConfigInfo->ulSampleRate;
336 if (pConfigInfo->ulBitsPerSample == 16)
337 ulConsumeRate <<= 1;
338 if (pConfigInfo->ulNumChannels == 2)
339 ulConsumeRate <<= 1;
340 pConfigInfo->ulPCMConsumeRate = ulConsumeRate;
341
342}
343/**@internal Pause
344 * @param None
345 * @return int 1
346 * @notes
347 * stub function pause is implemented as a stop by the stream
348 */
349#pragma off (unreferenced)
350int WAVEAUDIO::Pause(STREAM *stream)
351#pragma on (unreferenced)
352{
353 return 1;
354}
355/**@internal Resume
356 * @param None
357 * @return int 1
358 * @notes
359 * stub function resume is implemented as a start by the stream
360 */
361#pragma off (unreferenced)
362int WAVEAUDIO::Resume(STREAM *stream)
363#pragma on (unreferenced)
364{
365 return 1;
366}
367
368#pragma code_seg ("_inittext");
369#pragma data_seg ("_initdata","endds");
370
371/**@internal
372 * @param
373 * @return
374 * @notes
375 *
376 */
377void WAVEAUDIO::_vSetup()
378{
379}
Note: See TracBrowser for help on using the repository browser.