source: contrib/API/lib/pcmmulti.c@ 541

Last change on this file since 541 was 541, checked in by David Azarewicz, 15 years ago

Initial import

File size: 38.2 KB
Line 
1/*
2 * This file is part of uniaud.dll.
3 *
4 * Copyright (c) 2010 Mensys BV
5 * Copyright (c) 2007 Vlad Stelmahovsky aka Vladest
6 *
7 * This library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License and the GNU General Public License along with this library.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21#define INCL_DOS
22#define INCL_DOSERRORS
23#include <os2.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <io.h>
27#include <fcntl.h>
28#include <conio.h>
29#include <math.h>
30#include <string.h>
31
32#include "uniaud.h"
33#include "unidef.h"
34#include "errno.h"
35
36
37chan_convert_table_t nforce_chan_convert_table =
38{
39 {0, 1, 2, 3, 4, 5, 0, 0}, /* source */
40 {0, 1, 2, 3, 4, 5, 0, 0} /* destination */
41};
42
43chan_convert_table_t cmedia_chan_convert_table =
44{
45 {0, 1, 2, 3, 4, 5, 0, 0}, /* source */
46 {0, 1, 4, 5, 2, 3, 0, 0} /* destination */
47};
48
49static struct card_type_id_table_s {
50 char *driver;
51 card_type_ids card_type_id;
52 chan_convert_table_t *chan_convert_table;
53} card_type_id_table[] =
54{
55 "EMU10K1", UNIAUD_TYPE_ID_EMU10K1, NULL,
56 "Audigy", UNIAUD_TYPE_ID_AUDIGY, NULL,
57 "Audigy2", UNIAUD_TYPE_ID_AUDIGY2, NULL,
58 "CMI8738-MC6", UNIAUD_TYPE_ID_CMI8738, &cmedia_chan_convert_table,
59 "CMI8738-MC4", UNIAUD_TYPE_ID_CMI8738, NULL,
60 "CMI8738", UNIAUD_TYPE_ID_CMI8738, &cmedia_chan_convert_table,
61 "CMI8338", UNIAUD_TYPE_ID_CMI8338, NULL,
62 "CMIPCI", UNIAUD_TYPE_ID_CMI, &cmedia_chan_convert_table,
63 "YMF724", UNIAUD_TYPE_ID_YMF724, NULL,
64 "YMF724F", UNIAUD_TYPE_ID_YMF724F, NULL,
65 "YMF740", UNIAUD_TYPE_ID_YMF740, NULL,
66 "YMF740C", UNIAUD_TYPE_ID_YMF740C, NULL,
67 "YMF744", UNIAUD_TYPE_ID_YMF744, NULL,
68 "YMF754", UNIAUD_TYPE_ID_YMF754, NULL,
69 "CA0108", UNIAUD_TYPE_ID_AUDIGYLS, NULL,
70 "FM801", UNIAUD_TYPE_ID_FM801, NULL,
71 "NFORCE", UNIAUD_TYPE_ID_NFORCE, /*&nforce_chan_convert_table*/NULL,
72 "ICH", UNIAUD_TYPE_ID_ICH, NULL,
73 "ICH4", UNIAUD_TYPE_ID_ICH4, NULL,
74 "ICH5", UNIAUD_TYPE_ID_ICH5, NULL,
75 "VIA8233A", UNIAUD_TYPE_ID_VIA8233A, NULL,
76 "VIA8237", UNIAUD_TYPE_ID_VIA8237, NULL,
77 "VIA8233", UNIAUD_TYPE_ID_VIA8233, NULL,
78 0, 0, 0
79};
80
81#include "fastmemcpy.h"
82/*
83 * Sad story about Creative:
84 * for routing table we have to set up
85 * table for each substream
86 * for example: we have 6ch, so have to create 3 stereo substreams
87 * each substream has own index (from 0 to 31)
88 * so we created 3 stereo substreams with indexes from 0 to 2
89 * now we have to say to each substream - to which output it have
90 * to be connected.
91 * each substream have routing with 12 (for audigy 16 and 24 for audigy2)
92 * values
93 * for sb live: first 4 means mono, second is right and third 4 is left
94 * channels
95 * we have to put for left and right channels numbers of fx-buses, to
96 * which they will be connected phisycally
97 * for sb live:
98 * fx phys channel
99 *
100 * 0x00 PCM Left - not sure about this
101 * 0x01 PCM Right
102 * 0x02 PCM Surround Left
103 * 0x03 PCM Surround Right
104 * 0x04 MIDI Left
105 * 0x05 MIDI Right
106 * 0x06 Center
107 * 0x07 LFE
108 */
109static int uniaud_mixer_sblive_set(int card_id, int channels)
110{
111 int i, index, ret=0;
112// int vol_def[12] = {255, 255, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0 };
113 int vol_4_ch[12] = {0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 };
114 int vol_6_ch[12] = {0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 };
115 int vol_def[12] = {255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 };
116// int vol_4_ch[12] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
117// int vol_6_ch[12] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
118 int routing_def[12] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
119 int routing_rear[12] = { 0, 0, 0, 0, 4, 4, 0, 0, 1, 1, 0, 0 };
120 int routing_front[12] = { 0, 0, 0, 0, 2, 2, 0, 0, 3, 3, 0, 0 };
121 int routing_lfe[12] = { 0, 0, 0, 0, 6, 6, 0, 0, 7, 7, 0, 0 };
122// int routing_front[12] = { 8, 9, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0 };
123// int routing_rear[12] = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
124// int routing_lfe[12] = { 6, 7, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0 };
125
126 for (index=0; index < 3; index++)
127 {
128 for (i=0; i < 12; i++)
129 {
130 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, index)) < 0)
131 return ret;
132 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",/*routing_def*/routing_front[i], i, index)) < 0)
133 return ret;
134 }
135 }
136 if (channels <= 2)
137 {
138 for (i=0; i < 12; i++)
139 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, 0)) < 0)
140 return ret;
141 for (i=0; i < 12; i++)
142 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_def[i], i, 0)) < 0)
143 return ret;
144 }
145
146 if (channels >= 4)
147 {
148 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 0, 0)) < 0)
149 return ret;
150 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 1, 0)) < 0)
151 return ret;
152 for (i=0; i < 12; i++)
153 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_4_ch[i], i, 1)) < 0)
154 return ret;
155#if 1
156 for (i=0; i < 12; i++)
157 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_rear[i], i, 1)) < 0)
158 return ret;
159#endif
160 }
161
162 if (channels == 6)
163 {
164 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Center Playback Volume",0, 0, 0)) < 0)
165 return ret;
166 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave LFE Playback Volume",0, 0, 0)) < 0)
167 return ret;
168 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone Center Playback Switch",1, 0, 1)) < 0)
169 return ret;
170 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone LFE Playback Switch",1, 0, 1)) < 0)
171 return ret;
172
173 for (i=0; i < 12; i++)
174 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_6_ch[i], i, 2)) < 0)
175 return ret;
176 for (i=0; i < 12; i++)
177 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_lfe[i], i, 2)) < 0)
178 return ret;
179 }
180
181// if ((ret = uniaud_mixer_put_value_by_name(card_id,"SB Live Analog/Digital Output Jack",0,0,0) < 0)
182// printf("err10\n");
183
184 return ret;
185}
186
187static int uniaud_mixer_audigy_set(int card_id, int channels)
188{
189 int i, index, ret=0;
190 int vol_def[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
191 int vol_4_ch[24] = {0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 };
192 int vol_6_ch[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
193 int routing_def[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
194 //int routing_front[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
195 //int routing_rear[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
196 int routing_lfe[24] = { 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0 };
197
198 for (index=0; index < 3; index++)
199 {
200 for (i=0; i < 24; i++)
201 {
202 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, index)) < 0)
203 return ret;
204 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_def[i], i, index)) < 0)
205 return ret;
206 }
207 }
208
209 if (channels >= 4)
210 {
211// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 0, 0)) < 0)
212// return ret;
213// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 1, 0)) < 0)
214// return ret;
215 for (i=0; i < 24; i++)
216 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_4_ch[i], i, 1)) < 0)
217 return ret;
218 }
219
220 if (channels == 6)
221 {
222// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Center Playback Volume",0, 0, 0)) < 0)
223// return ret;
224// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave LFE Playback Volume",0, 0, 0)) < 0)
225// return ret;
226// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone Center Playback Switch",1, 0, 1)) < 0)
227// return ret;
228// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone LFE Playback Switch",1, 0, 1)) < 0)
229// return ret;
230
231 for (i=0; i < 24; i++)
232 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_6_ch[i], i, 2)) < 0)
233 return ret;
234 for (i=0; i < 24; i++)
235 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_lfe[i], i, 2)) < 0)
236 return ret;
237 }
238
239// if ((ret = uniaud_mixer_put_value_by_name(card_id,"SB Live Analog/Digital Output Jack",0,0,0) < 0)
240// printf("err10\n");
241
242 return ret;
243}
244
245static int uniaud_mixer_audigy2_set(int card_id, int channels)
246{
247 int i, index, ret=0;
248 int vol_def[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
249 int vol_4_ch[24] = {0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 };
250 int vol_6_ch[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
251 int routing_def[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
252 //int routing_front[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
253 //int routing_rear[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
254 int routing_lfe[24] = { 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0 };
255
256 for (index=0; index < 3; index++)
257 {
258 for (i=0; i < 24; i++)
259 {
260 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, index)) < 0)
261 return ret;
262 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_def[i], i, index)) < 0)
263 return ret;
264 }
265 }
266
267 if (channels >= 4)
268 {
269// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 0, 0)) < 0)
270// return ret;
271// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 1, 0)) < 0)
272// return ret;
273 for (i=0; i < 24; i++)
274 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_4_ch[i], i, 1)) < 0)
275 return ret;
276 }
277
278 if (channels == 6)
279 {
280// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Center Playback Volume",0, 0, 0)) < 0)
281// return ret;
282// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave LFE Playback Volume",0, 0, 0)) < 0)
283// return ret;
284// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone Center Playback Switch",1, 0, 1)) < 0)
285// return ret;
286// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone LFE Playback Switch",1, 0, 1)) < 0)
287// return ret;
288
289 for (i=0; i < 24; i++)
290 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_6_ch[i], i, 2)) < 0)
291 return ret;
292 for (i=0; i < 24; i++)
293 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_lfe[i], i, 2)) < 0)
294 return ret;
295 }
296
297// if ((ret = uniaud_mixer_put_value_by_name(card_id,"SB Live Analog/Digital Output Jack",0,0,0) < 0)
298// printf("err10\n");
299
300 return ret;
301}
302
303card_type_ids uniaud_get_card_type_id(int card_id)
304{
305 int ret, i;
306 UniaudCardInfo CardInfoL = {0};
307
308 if ((ret = uniaud_get_card_info(card_id, &CardInfoL)) < 0)
309 return ret;
310
311 i = 0;
312 while(card_type_id_table[i].driver != 0)
313 {
314 if (strcmp(card_type_id_table[i].driver,CardInfoL.driver) == 0)
315 return card_type_id_table[i].card_type_id;
316 i++;
317 }
318 return UNIAUD_TYPE_ID_UNKNOWN;
319}
320
321chan_convert_table_t * uniaud_get_card_conv_table(card_type_ids cardt_id)
322{
323 int i;
324
325 i = 0;
326 while(card_type_id_table[i].driver != 0)
327 {
328 if (card_type_id_table[i].card_type_id == cardt_id)
329 return card_type_id_table[i].chan_convert_table;
330 i++;
331 }
332 return NULL;
333}
334
335int uniaud_is_pcm_spdif(int card_id, int pcm_id)
336{
337 int ret, caps;
338 POSS32_DEVCAPS pcaps = NULL;
339 POSS32_DEVCAPS pcaps1 = NULL;
340
341 caps = uniaud_get_pcm_instances(card_id);
342 if (caps <= 0) return -UNIAUD_INVALID_CARD;
343
344 if (pcm_id < 0 || pcm_id > (caps-1)) return -UNIAUD_INVALID_PARAMETER;
345
346 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
347 if (!pcaps) return -UNIAUD_MEMORY_ERROR;
348
349 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0) {
350 free(pcaps);
351 return ret;
352 }
353
354 pcaps1 = pcaps + pcm_id;
355
356 ret = 0;
357 if (!memicmp(pcaps1->szDeviceName, "IEC958", 6)) {
358 ret = 1;
359 }
360 if (pcaps) free(pcaps);
361
362 return ret;
363}
364
365int uniaud_fill_subpcms(int card_id, int *subpcms)
366{
367 int ret, i, caps;
368 card_type_ids cardt = UNIAUD_TYPE_ID_UNKNOWN;
369 POSS32_DEVCAPS pcaps = NULL;
370 POSS32_DEVCAPS pcaps1 = NULL;
371
372 caps = uniaud_get_pcm_instances(card_id);
373 if (caps <= 0)
374 return -UNIAUD_INVALID_CARD;
375
376 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
377 if (!pcaps)
378 return -UNIAUD_MEMORY_ERROR;
379
380 pcaps1 = pcaps;
381
382 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0)
383 return ret;
384
385 cardt = uniaud_get_card_type_id(card_id);
386
387// printf("cp1: %s\n", CardInfoL.driver);
388
389 switch(cardt)
390 {
391 case UNIAUD_TYPE_ID_YMF724:
392 case UNIAUD_TYPE_ID_YMF724F:
393 case UNIAUD_TYPE_ID_YMF740:
394 case UNIAUD_TYPE_ID_YMF740C:
395 case UNIAUD_TYPE_ID_YMF744:
396 case UNIAUD_TYPE_ID_YMF754:
397 case UNIAUD_TYPE_ID_AUDIGYLS:
398 *subpcms = 0;
399 *(subpcms+2) = 0;
400 for (i=0; i<caps;i++)
401 {
402 if (strstr(pcaps->szDeviceName,"Rear") != NULL)
403 {
404 // printf("found rear at %i\n",i);
405 *(subpcms+1) = i;
406 break;
407 }
408 pcaps++;
409 }
410 break;
411 }
412 free(pcaps1);
413 return 0;
414}
415
416int uniaud_get_max_channels(int card_id)
417{
418 int ret, chans, caps;
419 card_type_ids cardt = UNIAUD_TYPE_ID_UNKNOWN;
420 POSS32_DEVCAPS pcaps = NULL;
421
422
423 caps = uniaud_get_pcm_instances(card_id);
424 if (caps <= 0)
425 return -UNIAUD_INVALID_CARD;
426
427 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
428 if (!pcaps)
429 return -UNIAUD_MEMORY_ERROR;
430
431 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0)
432 return ret;
433
434 cardt = uniaud_get_card_type_id(card_id);
435
436// printf("cp1: %s\n", CardInfoL.driver);
437
438 switch(cardt)
439 {
440 case UNIAUD_TYPE_ID_EMU10K1:
441 case UNIAUD_TYPE_ID_AUDIGY:
442 chans = 6;
443 break;
444 case UNIAUD_TYPE_ID_AUDIGY2:
445 chans = 8;
446 break;
447 case UNIAUD_TYPE_ID_YMF724:
448 case UNIAUD_TYPE_ID_YMF724F:
449 case UNIAUD_TYPE_ID_YMF740:
450 case UNIAUD_TYPE_ID_YMF740C:
451 case UNIAUD_TYPE_ID_YMF744:
452 case UNIAUD_TYPE_ID_YMF754:
453 chans = 4;
454 break;
455 case UNIAUD_TYPE_ID_CMI8738:
456 case UNIAUD_TYPE_ID_CMI8338:
457 case UNIAUD_TYPE_ID_CMI:
458 case UNIAUD_TYPE_ID_FM801:
459 chans = uniaud_pcm_find_max_chan(pcaps, caps, 0);
460 break;
461 case UNIAUD_TYPE_ID_UNKNOWN:
462 default:
463 chans = uniaud_pcm_find_max_chan(pcaps, caps, 0);
464 break;
465 }
466 free(pcaps);
467 return chans;
468}
469
470int uniaud_pcm_open_subpcms(int card_id, int type, int *pcm_instance, int access_flag,
471 int sample_rate, int channels, int pcm_format,
472 uniaud_pcm **pcm)
473{
474 int err;
475
476 if (channels <= 2)
477 err = _uniaud_pcm_open(card_id, type, *pcm_instance, access_flag, sample_rate, channels,
478 pcm_format, pcm);
479 else
480 err = _uniaud_pcm_open(card_id, type, *pcm_instance, access_flag, sample_rate, 2,
481 pcm_format, pcm);
482
483 if (!(*pcm) || err != 0)
484 return err;
485
486 if (channels >= 4)
487 {
488 err = _uniaud_pcm_open(card_id, type, *(pcm_instance+1), access_flag, sample_rate, 2,
489 pcm_format, &(*pcm)->pcm_rear);
490 if (!(*pcm)->pcm_rear || err != 0)
491 return err;
492
493 (*pcm)->pcm_rear->multi_buf = malloc((*pcm)->pcm_rear->bufsize);
494 }
495
496 if (channels == 6)
497 {
498 err = _uniaud_pcm_open(card_id, type, *(pcm_instance+2), access_flag, sample_rate, 2,
499 pcm_format, &(*pcm)->pcm_center_lfe);
500 if (!(*pcm)->pcm_center_lfe || err != 0)
501 return err;
502 (*pcm)->pcm_center_lfe->multi_buf = malloc((*pcm)->pcm_center_lfe->bufsize);
503 }
504 return UNIAUD_NO_ERROR;
505}
506
507int uniaud_pcm_open_substreams(int card_id, int type, int pcm_instance, int access_flag,
508 int sample_rate, int channels, int pcm_format,
509 uniaud_pcm **pcm)
510{
511 int err;
512
513 if (channels <= 2)
514 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, channels,
515 pcm_format, pcm);
516 else
517 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, 2,
518 pcm_format, pcm);
519
520 if (!(*pcm) || err != 0)
521 return err;
522
523 if (channels >= 4)
524 {
525 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, 2,
526 pcm_format, &(*pcm)->pcm_rear);
527 if (!(*pcm)->pcm_rear || err != 0)
528 return err;
529
530 (*pcm)->pcm_rear->multi_buf = malloc((*pcm)->pcm_rear->bufsize);
531 }
532 if (channels == 6)
533 {
534 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, 2,
535 pcm_format, &(*pcm)->pcm_center_lfe);
536 if (!(*pcm)->pcm_center_lfe || err != 0)
537 return err;
538 (*pcm)->pcm_center_lfe->multi_buf = malloc((*pcm)->pcm_center_lfe->bufsize);
539 }
540 return UNIAUD_NO_ERROR;
541}
542
543int uniaud_pcm_open_single(int card_id, int type, int pcm_instance, int access_flag,
544 int sample_rate, int channels, int pcm_format,
545 uniaud_pcm **pcm)
546{
547 int err;
548#if 0
549 POSS32_DEVCAPS pcaps = NULL;
550 int ret, caps, chans, pcm_cap;
551 caps = uniaud_get_pcm_instances(card_id);
552 //printf("caps = %i\n", caps);
553 if (caps <= 0)
554 return -UNIAUD_INVALID_CARD;
555
556 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
557 if (!pcaps)
558 return -UNIAUD_MEMORY_ERROR;
559
560 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0)
561 return ret;
562
563 pcm_cap = uniaud_pcm_find_pcm_for_chan(pcaps, caps, type, channels);
564
565 free(pcaps);
566
567 if (pcm_cap < 0)
568 return -UNIAUD_INVALID_CARD;
569 //printf("found instance %i for %i channels\n", pcm_cap, channels);
570 err = _uniaud_pcm_open(card_id, type, /*pcm_cap*/1, access_flag, sample_rate, channels,
571 pcm_format, pcm);
572#else
573 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, channels,
574 pcm_format, pcm);
575#endif
576 //printf("cp1. err= %i\n", err);
577 if (!(*pcm) || err != 0)
578 return err;
579
580 return UNIAUD_NO_ERROR;
581}
582
583int uniaud_pcm_open(int card_id, int type, int pcm_instance, int access_flag,
584 int sample_rate, int channels, int pcm_format,
585 uniaud_pcm **pcm)
586{
587 card_type_ids cardt_id;
588 int err;
589
590 cardt_id = uniaud_get_card_type_id(card_id);
591 init_fast_memcpy(mm_support());
592 if (uniaud_is_pcm_spdif(card_id, pcm_instance))
593 {
594 err = uniaud_pcm_open_single(card_id, type, pcm_instance, access_flag, sample_rate, channels,
595 pcm_format, pcm);
596 }
597 else
598 {
599 switch(cardt_id)
600 {
601 // case UNIAUD_TYPE_ID_UNKNOWN:
602 // return -UNIAUD_INVALID_CARD;
603 case UNIAUD_TYPE_ID_EMU10K1:
604 err = uniaud_pcm_open_substreams(card_id, type, pcm_instance, access_flag, sample_rate, channels,
605 pcm_format, pcm);
606 if (!err && type == 0)
607 err = uniaud_mixer_sblive_set(card_id, channels);
608 break;
609 case UNIAUD_TYPE_ID_AUDIGY:
610 err = uniaud_pcm_open_substreams(card_id, type, pcm_instance, access_flag, sample_rate, channels,
611 pcm_format, pcm);
612 if (!err && type == 0)
613 err = uniaud_mixer_audigy_set(card_id, channels);
614 break;
615 case UNIAUD_TYPE_ID_AUDIGY2:
616 err = uniaud_pcm_open_substreams(card_id, type, pcm_instance, access_flag, sample_rate, channels,
617 pcm_format, pcm);
618 if (!err && type == 0)
619 err = uniaud_mixer_audigy2_set(card_id, channels);
620 break;
621 case UNIAUD_TYPE_ID_CMI8738:
622 // case UNIAUD_TYPE_ID_CMI8338: need sub pcm support
623 case UNIAUD_TYPE_ID_CMI:
624 {
625 int ch_mode = 1;
626 int instance = pcm_instance;
627 if (channels > 2)
628 {
629 instance = 1;
630 ch_mode = 0;
631 }
632 //printf("opening cmedia: inst: %i, ch: %i: sr: %i\n", instance, channels, sample_rate);
633 err = uniaud_pcm_open_single(card_id, type, instance, access_flag, sample_rate, channels,
634 pcm_format, pcm);
635 uniaud_mixer_put_value_by_name(card_id,"Four Channel Mode",ch_mode, 0, 0);
636 break;
637 }
638 case UNIAUD_TYPE_ID_FM801:
639 err = uniaud_pcm_open_single(card_id, type, pcm_instance, access_flag, sample_rate, channels,
640 pcm_format, pcm);
641 break;
642 case UNIAUD_TYPE_ID_YMF724:
643 case UNIAUD_TYPE_ID_YMF724F:
644 case UNIAUD_TYPE_ID_YMF740:
645 case UNIAUD_TYPE_ID_YMF740C:
646 case UNIAUD_TYPE_ID_YMF744:
647 case UNIAUD_TYPE_ID_YMF754:
648 case UNIAUD_TYPE_ID_AUDIGYLS:
649 {
650 int subpcms[3];
651 if ((err = uniaud_fill_subpcms(card_id, subpcms)) == 0)
652 {
653 err = uniaud_pcm_open_subpcms(card_id, type,
654 subpcms, access_flag,
655 sample_rate, channels,
656 pcm_format, pcm);
657 if (!err)
658 {
659 if (channels > 2)
660 {
661 if (uniaud_mixer_put_value_by_name(card_id,
662 "Shared Rear/Line-In Switch",
663 1, 0, 0) !=0);
664 // printf("error setting line in as rear\n");
665 if (uniaud_mixer_put_value_by_name(card_id,
666 "Surround Playback Switch",
667 1, 0, 0) !=0);
668 if (uniaud_mixer_put_value_by_name(card_id,
669 "Surround Playback Volume",
670 31, 0, 0) !=0);
671 if (uniaud_mixer_put_value_by_name(card_id,
672 "Surround Playback Switch",
673 1, 1, 0) !=0);
674 if (uniaud_mixer_put_value_by_name(card_id,
675 "Surround Playback Volume",
676 31, 1, 0) !=0);
677 }
678 }
679 }
680 }
681 break;
682 case UNIAUD_TYPE_ID_NFORCE:
683 case UNIAUD_TYPE_ID_ICH:
684 case UNIAUD_TYPE_ID_ICH4:
685 case UNIAUD_TYPE_ID_ICH5:
686 {
687 int ch_mode = 0; /* 2 ch */
688
689 switch(channels)
690 {
691 case 4: ch_mode = 1; break;
692 case 6: ch_mode = 2; break;
693 case 8: ch_mode = 3; break;
694 }
695
696 if (uniaud_mixer_put_value_by_name(card_id, "Channel Mode",
697 ch_mode, 0, 0) !=0);
698 err = uniaud_pcm_open_single(card_id, type, pcm_instance,
699 access_flag, sample_rate, channels,
700 pcm_format, pcm);
701 }
702 break;
703 case UNIAUD_TYPE_ID_VIA8233A:
704 case UNIAUD_TYPE_ID_VIA8237:
705 case UNIAUD_TYPE_ID_VIA8233:
706 {
707 int ch_mode = 0; /* 2 ch */
708 int instance = 0;
709
710 switch(channels)
711 {
712 case 4:
713 ch_mode = 1;
714 instance = 1;
715 if (uniaud_mixer_put_value_by_name(card_id, "Surround Down Mix",
716 0, 0, 0) !=0);
717 if (uniaud_mixer_put_value_by_name(card_id, "Swap Surround Slot",
718 0, 0, 0) !=0);
719 break;
720 case 6:
721 ch_mode = 2;
722 instance = 1;
723 if (uniaud_mixer_put_value_by_name(card_id, "Surround Down Mix",
724 0, 0, 0) !=0);
725 if (uniaud_mixer_put_value_by_name(card_id, "Center/LFE Down Mix",
726 0, 0, 0) !=0);
727 if (uniaud_mixer_put_value_by_name(card_id, "Mic As Center/LFE",
728 1, 0, 0) !=0);
729 if (uniaud_mixer_put_value_by_name(card_id, "Swap Surround Slot",
730 1, 0, 0) !=0);
731 break;
732 }
733
734 if (uniaud_mixer_put_value_by_name(card_id, "Channel Mode",
735 ch_mode, 0, 0) !=0);
736 if (cardt_id == UNIAUD_TYPE_ID_VIA8233A)
737 {
738 instance = 0;
739 }
740 //printf("opening pcm %i for card type %i, channels: %i\n", instance, cardt_id, channels);
741 err = uniaud_pcm_open_single(card_id, type, instance,
742 access_flag, sample_rate, channels,
743 pcm_format, pcm);
744
745 }
746 break;
747
748 default:
749 err = uniaud_pcm_open_single(card_id, type, pcm_instance, access_flag, sample_rate, channels,
750 pcm_format, pcm);
751 break;
752 } /* switch */
753 }
754 if (*pcm)
755 {
756 (*pcm)->card_type = cardt_id;
757 if (channels > 2)
758 (*pcm)->multi_channels = channels;
759 }
760 return err;
761}
762
763int uniaud_pcm_prepare(uniaud_pcm *pcm)
764{
765 int err;
766
767 err = _uniaud_pcm_prepare(pcm);
768 if (err < 0) return err;
769
770 if (pcm->pcm_rear)
771 {
772 err = _uniaud_pcm_prepare(pcm->pcm_rear);
773 if (err < 0) return err;
774 }
775 if (pcm->pcm_center_lfe)
776 {
777 err = _uniaud_pcm_prepare(pcm->pcm_center_lfe);
778 if (err < 0) return err;
779 }
780 return err;
781}
782
783int uniaud_pcm_start(uniaud_pcm *pcm)
784{
785 int err;
786
787 err = _uniaud_pcm_start(pcm);
788 if (err < 0) return err;
789
790 if (pcm->pcm_rear)
791 {
792 err = _uniaud_pcm_start(pcm->pcm_rear);
793 if (err < 0) return err;
794 }
795 if (pcm->pcm_center_lfe)
796 {
797 err = _uniaud_pcm_start(pcm->pcm_center_lfe);
798 if (err < 0) return err;
799 }
800 return err;
801}
802
803int uniaud_pcm_drop(uniaud_pcm *pcm)
804{
805 int err;
806
807 err = _uniaud_pcm_drop(pcm);
808 if (err < 0) return err;
809
810 if (pcm->pcm_rear)
811 {
812 err = _uniaud_pcm_drop(pcm->pcm_rear);
813 if (err < 0) return err;
814 }
815 if (pcm->pcm_center_lfe)
816 {
817 err = _uniaud_pcm_drop(pcm->pcm_center_lfe);
818 if (err < 0) return err;
819 }
820 return err;
821}
822
823int uniaud_pcm_pause(uniaud_pcm *pcm)
824{
825 int err;
826
827 err = _uniaud_pcm_pause(pcm);
828 if (err < 0) return err;
829
830 if (pcm->pcm_rear)
831 {
832 err = _uniaud_pcm_pause(pcm->pcm_rear);
833 if (err < 0) return err;
834 }
835 if (pcm->pcm_center_lfe)
836 {
837 err = _uniaud_pcm_pause(pcm->pcm_center_lfe);
838 if (err < 0) return err;
839 }
840 return err;
841}
842
843int uniaud_pcm_resume(uniaud_pcm *pcm)
844{
845 int err;
846
847 err = _uniaud_pcm_resume(pcm);
848 if (err < 0) return err;
849
850 if (pcm->pcm_rear)
851 {
852 err = _uniaud_pcm_resume(pcm->pcm_rear);
853 if (err < 0) return err;
854 }
855 if (pcm->pcm_center_lfe)
856 {
857 err = _uniaud_pcm_resume(pcm->pcm_center_lfe);
858 if (err < 0) return err;
859 }
860 return err;
861}
862
863
864int uniaud_pcm_close(uniaud_pcm *pcm)
865{
866 int err;
867
868 if (pcm && pcm->pcm_center_lfe)
869 {
870 err = _uniaud_pcm_close(pcm->pcm_center_lfe);
871 //if (err < 0) return err;
872 }
873 if (pcm && pcm->pcm_rear)
874 {
875 err = _uniaud_pcm_close(pcm->pcm_rear);
876 //if (err < 0) return err;
877 }
878
879 err = _uniaud_pcm_close(pcm);
880
881 return err;
882}
883
884int uniaud_pcm_wait(uniaud_pcm *pcm, int timeout)
885{
886 int err = 0;
887#if 0
888 if (pcm->pcm_center_lfe)
889 {
890 err = _uniaud_pcm_wait(pcm->pcm_center_lfe, timeout);
891 if (err < 0) return err;
892 } else
893 if (pcm->pcm_rear)
894 {
895 err = _uniaud_pcm_wait(pcm->pcm_rear, timeout);
896 if (err < 0) return err;
897 }
898 else
899#endif
900 //printf("tout = %i %x %x\n", timeout, pcm->pcm_center_lfe, pcm->pcm_rear);
901
902 //if (!pcm->pcm_center_lfe &&
903 // !pcm->pcm_rear)
904 err = _uniaud_pcm_wait(pcm, timeout);
905
906 return err;
907}
908
909static inline uint16_t bswap_16(uint16_t x){
910 return (x>>8) | (x<<8);
911}
912
913
914int16_t swapBuf[8*3] __attribute__((aligned(16))) = {0}; /*up to 24 bit samples to 8 channels */
915int last_ret = 0;
916
917int uniaud_pcm_write(uniaud_pcm *pcm, char *Buffer, int size)
918{
919 int err = 0;
920 int err1 = 0, err2 = 0, err3 = 0;
921 int ret = 0;
922 int ret1 = 0, ret2 = 0, ret3 = 0;
923 int i, j, state;
924 int written = 0;
925 //int written1 = 0;
926 int written_front = 0, written_rear = 0, written_lfe = 0;
927 chan_convert_table_t *ct = NULL;
928 //FILE *f;
929 int16_t *b = (int16_t *)Buffer;
930 //int16_t sample;
931
932 int samplesize = uniaud_pcm_format_size(pcm->format, 1);
933
934 //printf("ss=%i, ch: %i\n", samplesize, pcm->multi_channels);
935 if (!Buffer || size <= 0)
936 return -UNIAUD_MEMORY_ERROR;
937
938 ct = uniaud_get_card_conv_table(pcm->card_type);
939 if (last_ret == 0) last_ret = /*size*/pcm->period_size;
940 //printf("ss=%i, ch: %i, ct: %x, lr: %i\n", samplesize, pcm->multi_channels, ct, last_ret);
941 if (ct && pcm->multi_channels >= 4 && last_ret > 0)
942 {
943 //for (j=0; j < pcm->multi_channels; j++)
944 // printf("%i -> %i\n", ct->src[j], ct->dst[j]);
945 if (size < last_ret) last_ret = size;
946 //printf("lastret: %i\n", last_ret);
947 for(i=0; i < last_ret/samplesize; i+=pcm->multi_channels/**samplesize*/)
948 {
949 memset(&swapBuf[0], 0, sizeof(swapBuf));
950 for (j=0; j < pcm->multi_channels; j++)
951 swapBuf[j] = b[i+j];
952 for (j=0; j < pcm->multi_channels; j++)
953 b[i+ct->dst[j]] = swapBuf[ct->src[j]];
954
955 }
956 }
957
958 if ((!pcm->pcm_center_lfe && !pcm->pcm_rear) ||
959 pcm->multi_channels <= 2)
960 { // single PCM multichannel or 2 or less channels write
961 //again:
962 ret = _uniaud_pcm_write(pcm, Buffer, size);
963 //printf("ret = %i, size: <%i>\n", ret, size);
964 if (ret == -77)
965 {
966 //_uniaud_pcm_reinit(pcm);
967 //goto again;
968 }
969 if (ret>0)
970 last_ret = ret;
971 return ret;
972 }
973 if (!pcm->multi_buf)
974 return -UNIAUD_MEMORY_ERROR;
975
976// if ((size % (samplesize*pcm->multi_channels)) != 0)
977// printf("size is not aligned to number of channels\n");
978
979// printf("%i, %i, %i\n",samplesize, pcm->multi_channels, pcm->format);
980
981 j=0;
982 if (1)
983 {
984 for (i=0; i<size;i+=samplesize*pcm->multi_channels)
985 {
986#if 1
987 memcpy(pcm->multi_buf+j, Buffer+i, 4);
988 if (pcm->pcm_center_lfe)
989 {
990 memcpy(pcm->multi_buf+j, Buffer+i+4, 4);
991 }
992 if (pcm->pcm_rear)
993 {
994 memcpy(pcm->multi_buf+j, Buffer+i+8, 4);
995 }
996#else
997 unsigned int *bufPtrIn;
998 unsigned int *bufPtrOut;
999
1000 bufPtrIn = (unsigned int*)pcm->multi_buf;
1001 bufPtrOut = (unsigned int*)Buffer;
1002 bufPtrIn[j/4] = bufPtrOut[i/4];
1003#if 0
1004 (unsigned int)*(unsigned int*)(pcm->multi_buf+j) =
1005 (unsigned int)*(unsigned int*)(Buffer+i);
1006 if (pcm->pcm_center_lfe)
1007 {
1008 (unsigned int)*(unsigned int*)(pcm->pcm_center_lfe->multi_buf+j) =
1009 (unsigned int)*(unsigned int*)(Buffer+i+4);
1010 }
1011 if (pcm->pcm_rear)
1012 {
1013 (unsigned int)*(unsigned int*)(pcm->pcm_rear->multi_buf+j) =
1014 (unsigned int)*(unsigned int*)(Buffer+i+8);
1015 }
1016#endif
1017#endif
1018 j+=samplesize*2;
1019 }
1020 } /* !cf */
1021 {
1022#if 0
1023 FILE *f;
1024 f = fopen("uniaudm.dmp","ab");
1025 fwrite(pcm->pcm_center_lfe->multi_buf, j,1,f);
1026 fclose(f);
1027
1028#endif
1029 }
1030 while (written < size)
1031 {
1032 err1 = err2 = err3 = 0;
1033 ret1 = ret2 = ret3 = 0;
1034
1035 err3 = _uniaud_pcm_write(pcm, pcm->multi_buf+written_front, j-written_front);
1036
1037 if (pcm->pcm_rear)
1038 err1 = _uniaud_pcm_write(pcm->pcm_rear, pcm->pcm_rear->multi_buf+written_rear, j-written_rear);
1039
1040 if (pcm->pcm_center_lfe)
1041 err2 = _uniaud_pcm_write(pcm->pcm_center_lfe, pcm->pcm_center_lfe->multi_buf+written_lfe, j-written_lfe);
1042
1043
1044#if 0
1045 if (err1 > 0)
1046 ret1 = _uniaud_pcm_wait(pcm->pcm_rear, 1000);
1047 else if (err2 > 0)
1048 ret2 = _uniaud_pcm_wait(pcm->pcm_center_lfe, 1000);
1049 else
1050#endif
1051 // if (err3 > 0)
1052 ret3 = _uniaud_pcm_wait(pcm, 1000);
1053
1054 if (err1 > 0)
1055 {
1056 written+=err1;
1057 written_rear+=err1;
1058 }
1059 if (err2 > 0)
1060 {
1061 written+=err2;
1062 written_lfe+=err2;
1063 }
1064 if (err3 > 0)
1065 {
1066 written+=err3;
1067 written_front+=err3;
1068 }
1069
1070 if (err1 < 0 && err1 != -EAGAIN)
1071 {
1072 //if (err1 == -77)
1073 // _uniaud_pcm_reinit(pcm);
1074 state = uniaud_pcm_state(pcm->pcm_rear);
1075 if ( (state != SND_PCM_STATE_PREPARED) &&
1076 (state != SND_PCM_STATE_RUNNING) &&
1077 (state != SND_PCM_STATE_DRAINING) ) {
1078 if ((ret1 = _uniaud_pcm_prepare(pcm->pcm_rear))<0)
1079 break;
1080 }
1081// printf("err writing %i bytes to rear from %i, err: %i\n",written_rear,j,err1);
1082 }
1083
1084 if (err2 < 0 && err2 != -EAGAIN)
1085 {
1086 //if (err2 == -77)
1087 // _uniaud_pcm_reinit(pcm);
1088 state = uniaud_pcm_state(pcm->pcm_center_lfe);
1089 if ( (state != SND_PCM_STATE_PREPARED) &&
1090 (state != SND_PCM_STATE_RUNNING) &&
1091 (state != SND_PCM_STATE_DRAINING) ) {
1092 if ((ret2 = _uniaud_pcm_prepare(pcm->pcm_center_lfe))<0)
1093 break;
1094 }
1095// printf("err writing %i bytes to center/lfe from %i, err: %i\n",written_lfe,j,err2);
1096 }
1097
1098 if (err3 < 0 && err3 != -EAGAIN)
1099 {
1100 //if (err3 == -77)
1101 // _uniaud_pcm_reinit(pcm);
1102 state = uniaud_pcm_state(pcm);
1103 if ( (state != SND_PCM_STATE_PREPARED) &&
1104 (state != SND_PCM_STATE_RUNNING) &&
1105 (state != SND_PCM_STATE_DRAINING) ) {
1106 if ((ret3 = _uniaud_pcm_prepare(pcm))<0)
1107 break;
1108 }
1109// printf("err writing %i bytes to front from %i, err: %i\n",written_front,j,err3);
1110 }
1111 }
1112
1113// printf("wr: %i\n", j);
1114 if (written > 0)
1115 return written;
1116 return err;
1117}
1118
Note: See TracBrowser for help on using the repository browser.