source: contrib/API/tools/rwtest.c

Last change on this file was 578, checked in by David Azarewicz, 11 years ago

API updates

File size: 14.8 KB
Line 
1
2#define INCL_DOS
3#define INCL_KBD
4#define INCL_DOSERRORS
5#include <os2.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <io.h>
9#include <fcntl.h>
10#include <conio.h>
11#include <math.h>
12#include <string.h>
13#include <process.h>
14
15#include "uniaud.h"
16#include "unidef.h"
17#include "errno.h"
18
19#define DEBUG
20
21snd_pcm_status_t status;
22
23int read_key(void)
24{
25 static ULONG time = 0;
26 KBDKEYINFO Char;
27
28 KbdCharIn(&Char, IO_NOWAIT, 0);
29
30 if (time == Char.time)
31 return 0;
32
33 time = Char.time;
34
35 return Char.chChar;
36}
37
38FILE *f;
39
40int ThreadStop = 0;
41uniaud_pcm *pcmread = NULL;
42uniaud_pcm *pcmwrite = NULL;
43static char *Buffer = NULL;
44static int BufferPos = 0;
45static int BufferReadPos = 0;
46static int BufferSize = 0;
47static int MaxBufferSize = 0;
48
49static HMTX read_sem = 0;
50
51static void ReadAudio(void *arg)
52{
53 int err, ret, state;
54 char *buf = NULL;
55
56 printf("audio read thread started\n");fflush(stdout);
57
58 buf = malloc(pcmread->bufsize);
59 if (!buf)
60 {
61 printf("error allocating %i bytes\n", pcmread->bufsize);
62 return;
63 }
64 uniaud_pcm_prepare(pcmread);
65 uniaud_pcm_start(pcmread);
66
67
68 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 31, 0);
69
70 while(ThreadStop == 0)
71 {
72 err = uniaud_pcm_wait(pcmread, 100);
73 if (err < 0)
74 {
75 //printf("pcm wait %i\n", err);fflush(stdout);
76 if (err != -11) DosSleep(1);
77 if (ThreadStop) break;
78 //continue;
79 }
80// state = dyn_uniaud_pcm_state(pcm);
81
82
83 ret = uniaud_pcm_read(pcmread, buf, pcmread->bufsize);
84
85 if (ret > 0)
86 {
87 //printf("readed %i\n", ret);fflush(stdout);
88 if (DosRequestMutexSem(read_sem, 1000) != NO_ERROR)
89 {
90 DosSleep(1);
91 continue;
92 }
93 memcpy(Buffer+BufferPos, buf, ret);
94 BufferSize +=ret;
95 BufferPos +=ret;
96
97 if (((float)(BufferSize+ret) >= (float)(MaxBufferSize*0.8f)) &&
98 ((float)(BufferReadPos+ret) >= (float)(BufferSize*0.8f)))
99 {
100 memcpy(Buffer, Buffer+BufferReadPos, BufferSize-BufferReadPos);
101 BufferPos = BufferSize-BufferReadPos;
102 BufferSize = BufferSize-BufferReadPos;
103 BufferReadPos = 0;
104 }
105 if (BufferSize >= MaxBufferSize)
106 {
107 BufferSize = 0;
108 BufferPos = 0;
109 BufferReadPos = 0;
110 }
111 DosReleaseMutexSem(read_sem);
112 }
113
114// if (ret < 0)
115// printf("ret %i\n", ret);
116 if (ret == -EAGAIN)
117 {
118 DosSleep(1);
119 continue;
120 }
121
122 if (ret < 0)
123 {
124 state = uniaud_pcm_state(pcmread);
125// printf("state %i\n", state);
126 if ((state != SND_PCM_STATE_PREPARED) &&
127 (state != SND_PCM_STATE_RUNNING) &&
128 (state != SND_PCM_STATE_DRAINING) )
129 {
130 uniaud_pcm_prepare(pcmread);
131 }
132 }
133 DosSleep(1);
134 }
135 free(buf);
136 printf("audio in thread stopped\n");fflush(stdout);
137}
138
139int UniInRead(char* buf, int size)
140{
141 int sz = 0;
142 int readed = 0;
143
144 if (!buf || size <= 0)
145 return 0;
146
147// while (!BufferSize)
148// DosSleep(1);
149
150 if (DosRequestMutexSem(read_sem, 10000) != NO_ERROR)
151 return 0;
152
153 if (BufferSize > 0)
154 {
155 if (size <= BufferSize)
156 sz = size;
157 else
158 sz = BufferSize;
159 //printf("sz1 = %i\n", sz);
160
161 if (BufferReadPos >= BufferSize)
162 BufferReadPos = 0;
163 if ((BufferReadPos + sz) > BufferSize)
164 sz = BufferSize - BufferReadPos;
165 //printf("sz2 = %i\n", sz);
166 memcpy(buf, Buffer+BufferReadPos, sz);
167 BufferReadPos += sz;
168 readed+=sz;
169 }
170 else
171 DosSleep(1);
172 DosReleaseMutexSem(read_sem);
173// printf("return %i bytes at %i bs %i\n", readed, BufferReadPos, BufferSize);fflush(stdout);
174 return readed;
175}
176
177int main (int argc, char *argv[])
178{
179 int ver, err, ret;
180 int count;
181 int card_id = 0;
182 char *Buf;
183 int readed, written, fs;
184
185 snd_pcm_hw_params_t params = {0};
186 snd_pcm_sw_params_t swparams = {0};
187 int period_bytes, periods, periods_min, periods_max, samplesize;
188 int new_sample_rate, new_channels, new_format; // for resampling
189 snd_pcm_uframes_t period_size;
190
191 ver = uniaud_get_version();
192 if (ver < 111)
193 return -1;
194 // set capture to ON
195 uniaud_mixer_put_value_by_name(card_id,"Capture Switch",1, 0, 0);
196 uniaud_mixer_put_value_by_name(card_id,"Capture Switch",1, 1, 0);
197 uniaud_mixer_put_value_by_name(card_id,"Capture Volume",15, 0, 0);
198 uniaud_mixer_put_value_by_name(card_id,"Capture Volume",15, 1, 0);
199 uniaud_mixer_put_value_by_name(card_id,"Capture Source",2, 0, 0);
200 uniaud_mixer_put_value_by_name(card_id,"Capture Source",2, 1, 0);
201 uniaud_mixer_put_value_by_name(card_id,"Mic Capture Switch",1, 0, 0);
202 uniaud_mixer_put_value_by_name(card_id,"Line Capture Route",0, 0, 0);
203 uniaud_mixer_put_value_by_name(card_id,"Line Capture Route",0, 1, 0);
204 uniaud_mixer_put_value_by_name(card_id,"Line Capture Route",0, 2, 0);
205 uniaud_mixer_put_value_by_name(card_id,"Line Capture Route",0, 3, 0);
206
207
208 uniaud_mixer_put_value_by_name(card_id,"Master Playback Switch",1, 0, 0);
209 uniaud_mixer_put_value_by_name(card_id,"Master Playback Volume",30, 0, 0);
210 uniaud_mixer_put_value_by_name(card_id,"Master Playback Volume",30, 1, 0);
211 uniaud_mixer_put_value_by_name(card_id,"PCM Playback Switch",1, 0, 0);
212 uniaud_mixer_put_value_by_name(card_id,"PCM Playback Volume",31, 0, 0);
213 uniaud_mixer_put_value_by_name(card_id,"PCM Playback Volume",31, 1, 0);
214
215 printf("pcm write starting..\n");fflush(stdout);
216
217 err = uniaud_pcm_open(card_id, PCM_TYPE_WRITE, 0, 0, 8000, 2,
218 SNDRV_PCM_FORMAT_S16_LE, &pcmwrite);
219 printf("pcm write started.\n");fflush(stdout);
220
221 if (!pcmwrite || err != 0)
222 return -1;
223 printf("format: %i, ch: %i\n", pcmwrite->format, pcmwrite->channels);
224
225 printf("pcm read starting..\n");fflush(stdout);
226 err = uniaud_pcm_open(card_id, PCM_TYPE_READ, 0, 0, 48000, 2,
227 SNDRV_PCM_FORMAT_S16_LE, &pcmread);
228 printf("pcm read started. err = %i\n", err);fflush(stdout);
229
230 if (!pcmread || err != 0)
231 return -1;
232
233 MaxBufferSize = pcmwrite->bufsize * 1;
234 Buffer = malloc(MaxBufferSize);
235 Buf = malloc(MaxBufferSize);
236 if (Buffer && Buf)
237 {
238 printf("allocated %i bytes\n", MaxBufferSize);
239 DosCreateMutexSem(NULL, &read_sem, 0, FALSE);
240 _beginthread(ReadAudio, NULL, 0x10000, NULL);
241 }
242
243 periods_min = ((snd_interval_t*)hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS))->min;
244 periods_max = ((snd_interval_t*)hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS))->max;
245 periods = 2;//periods_min*pcmwrite->channels;
246 period_bytes = 480*4;
247 fs = uniaud_pcm_format_size(pcmwrite->format, pcmwrite->channels);
248 printf("format size: %i, format: %i, ch: %i\n", fs, pcmwrite->format, pcmwrite->channels);
249 period_size = period_bytes/fs;
250
251#if 1
252 /* setting parameters for write small chunks of data */
253 err = snd_pcm_hw_params_any(pcmwrite, &params);
254 if (err < 0) {
255 //printf("Broken configuration for playback: no configurations available: %i\n", err);
256 return err;
257 }
258
259
260#if 1
261 printf("write parameters:\n");
262 printf("buffer_size = %i\n",period_bytes*periods);
263 printf("period_size = %i\n",period_size);
264 printf("period_bytes = %i\n",period_bytes);
265 printf("periods = %i\n",periods);
266#endif
267
268 new_format = SNDRV_PCM_FORMAT_S16_LE;
269 new_channels = 2;
270 new_sample_rate = 8000;
271 samplesize = uniaud_pcm_format_size(new_format, 1);
272
273 _snd_pcm_hw_params_any(&params);
274
275 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
276 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
277 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
278 samplesize*8, 0);
279 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
280 samplesize*new_channels*8, 0);
281 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
282 new_format, 0);
283 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
284 new_channels, 0);
285 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
286 new_sample_rate, 0);
287
288 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIODS,
289 periods, 0);
290 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
291 period_size*periods, 0);
292 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
293 period_bytes*periods, 0);
294 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
295 period_size, 0);
296 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
297 period_bytes, 0);
298
299 ret = _uniaud_pcm_set_hw_params(pcmwrite, &params);
300
301 printf("write hw set err: %i\n", ret);
302
303 if (ret != 0)
304 return ret;
305
306 // printf("bufsize: %i\n",buffer_size);
307
308 pcmwrite->period_size = period_bytes;
309 pcmwrite->bufsize = period_bytes*periods;
310 pcmwrite->periods = periods;
311
312 swparams.avail_min = period_size;
313 swparams.period_step = 1;
314 if(periods <= 2)
315 swparams.silence_size = (period_size/2);
316 else
317 swparams.silence_size = period_size;
318
319 swparams.silence_threshold = swparams.silence_size;
320 swparams.sleep_min = 0;
321 swparams.start_threshold = 1;//period_size;
322 swparams.stop_threshold = period_size*periods;
323 swparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
324 swparams.xfer_align = period_size;
325 // swparams.boundary = buffer_size;
326 // while (swparams.boundary * 2 <= LONG_MAX - buffer_size)
327 // swparams.boundary *= 2;
328 ret = _uniaud_pcm_set_sw_params(pcmwrite, &swparams);
329#endif
330#if 0
331 /* setting parameters for read small chunks of data */
332 memset(&params, 0, sizeof(params));
333
334 err = snd_pcm_hw_params_any(pcmread, &params);
335 if (err < 0) {
336 //printf("Broken configuration for playback: no configurations available: %i\n", err);
337 return -1;
338 }
339
340 periods_min = ((snd_interval_t*)hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS))->min;
341 periods_max = ((snd_interval_t*)hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS))->max;
342 periods = 2;//periods_min*pcmwrite->channels;
343 period_bytes = 240;//((snd_interval_t*)hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_BYTES))->min;
344 period_size = period_bytes/uniaud_pcm_format_size(pcmread->format, pcmread->channels);
345 //period_size = ((snd_interval_t*)hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_BYTES))->min;
346 //period_bytes = period_size*uniaud_pcm_format_size(pcmread->format, pcmread->channels);
347#if 1
348 printf("read parameters:\n");
349 printf("buffer_size = %i\n",period_bytes*periods);
350 printf("period_size = %i\n",period_size);
351 printf("period_bytes = %i\n",period_bytes);
352 printf("periods = %i\n",periods);
353#endif
354
355 _snd_pcm_hw_params_any(&params);
356
357 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
358 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
359 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
360 samplesize*8, 0);
361 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
362 samplesize*new_channels*8, 0);
363 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
364 new_format, 0);
365 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
366 new_channels, 0);
367 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
368 new_sample_rate, 0);
369
370 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIODS,
371 periods, 0);
372 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
373 period_size*periods, 0);
374 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
375 period_bytes*periods, 0);
376 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
377 period_size, 0);
378 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
379 period_bytes, 0);
380
381 ret = _uniaud_pcm_set_hw_params(pcmread, &params);
382
383 printf("read hw set err: %i\n", ret);
384
385 if (ret != 0)
386 return -1;
387
388 pcmread->period_size = period_bytes;
389 pcmread->bufsize = period_bytes*periods;
390 pcmread->periods = periods;
391#endif
392
393 err = uniaud_pcm_prepare(pcmread);
394 err = uniaud_pcm_start(pcmread);
395
396 err = uniaud_pcm_prepare(pcmwrite);
397
398 count = pcmwrite->bufsize;
399
400 printf("count = %i\n", count);
401
402 while(read_key() != 27)
403 {
404 /* wait for data */
405 readed = UniInRead(Buf, count);
406// printf("readed %i\n",readed);
407
408 if( readed > 0 )
409 {
410#ifdef DEBUG
411 if( f == NULL ) f= fopen( "mic.u", "wb" );
412 if( f != NULL ) fwrite( Buf, 1, ret, f );
413#endif
414 written = 0;
415 while (written < readed)
416 {
417 ret = uniaud_pcm_write(pcmwrite, Buf+written, count - written);
418 if (ret == EAGAIN) continue;
419 err = uniaud_pcm_wait(pcmwrite, 1000);
420 if (err != 0)
421 {
422 //printf("err %i\n", err);
423 DosSleep(1);
424 }
425 if (ret < 0)
426 {
427 int state;
428
429 state = uniaud_pcm_state(pcmwrite);
430 printf("error %i writting. state %i\n", ret, state);
431 /* check for overrun */
432 if ( (state != SND_PCM_STATE_PREPARED) &&
433 (state != SND_PCM_STATE_RUNNING) &&
434 (state != SND_PCM_STATE_DRAINING) ) {
435 uniaud_pcm_prepare(pcmwrite);
436 }
437 }
438 if (ret > 0)
439 {
440 written+=ret;
441 //printf("written all=%i. now = %i from %i\n",written, ret, readed);
442 }
443 }
444 }
445 } /* while */
446 uniaud_pcm_close(pcmread);
447 uniaud_pcm_close(pcmwrite);
448 return 0;
449}
Note: See TracBrowser for help on using the repository browser.