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 |
|
---|
21 | snd_pcm_status_t status;
|
---|
22 |
|
---|
23 | int 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 |
|
---|
38 | FILE *f;
|
---|
39 |
|
---|
40 | int ThreadStop = 0;
|
---|
41 | uniaud_pcm *pcmread = NULL;
|
---|
42 | uniaud_pcm *pcmwrite = NULL;
|
---|
43 | static char *Buffer = NULL;
|
---|
44 | static int BufferPos = 0;
|
---|
45 | static int BufferReadPos = 0;
|
---|
46 | static int BufferSize = 0;
|
---|
47 | static int MaxBufferSize = 0;
|
---|
48 |
|
---|
49 | static HMTX read_sem = 0;
|
---|
50 |
|
---|
51 | static 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 |
|
---|
139 | int 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 |
|
---|
177 | int 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((¶ms), SNDRV_PCM_HW_PARAM_PERIODS))->min;
|
---|
244 | periods_max = ((snd_interval_t*)hw_param_interval((¶ms), 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, ¶ms);
|
---|
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(¶ms);
|
---|
274 |
|
---|
275 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,
|
---|
276 | SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
|
---|
277 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
|
---|
278 | samplesize*8, 0);
|
---|
279 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS,
|
---|
280 | samplesize*new_channels*8, 0);
|
---|
281 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_FORMAT,
|
---|
282 | new_format, 0);
|
---|
283 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS,
|
---|
284 | new_channels, 0);
|
---|
285 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_RATE,
|
---|
286 | new_sample_rate, 0);
|
---|
287 |
|
---|
288 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_PERIODS,
|
---|
289 | periods, 0);
|
---|
290 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
---|
291 | period_size*periods, 0);
|
---|
292 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
---|
293 | period_bytes*periods, 0);
|
---|
294 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
|
---|
295 | period_size, 0);
|
---|
296 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
|
---|
297 | period_bytes, 0);
|
---|
298 |
|
---|
299 | ret = _uniaud_pcm_set_hw_params(pcmwrite, ¶ms);
|
---|
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(¶ms, 0, sizeof(params));
|
---|
333 |
|
---|
334 | err = snd_pcm_hw_params_any(pcmread, ¶ms);
|
---|
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((¶ms), SNDRV_PCM_HW_PARAM_PERIODS))->min;
|
---|
341 | periods_max = ((snd_interval_t*)hw_param_interval((¶ms), SNDRV_PCM_HW_PARAM_PERIODS))->max;
|
---|
342 | periods = 2;//periods_min*pcmwrite->channels;
|
---|
343 | period_bytes = 240;//((snd_interval_t*)hw_param_interval((¶ms), 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((¶ms), 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(¶ms);
|
---|
356 |
|
---|
357 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,
|
---|
358 | SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
|
---|
359 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
|
---|
360 | samplesize*8, 0);
|
---|
361 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS,
|
---|
362 | samplesize*new_channels*8, 0);
|
---|
363 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_FORMAT,
|
---|
364 | new_format, 0);
|
---|
365 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS,
|
---|
366 | new_channels, 0);
|
---|
367 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_RATE,
|
---|
368 | new_sample_rate, 0);
|
---|
369 |
|
---|
370 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_PERIODS,
|
---|
371 | periods, 0);
|
---|
372 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
---|
373 | period_size*periods, 0);
|
---|
374 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
---|
375 | period_bytes*periods, 0);
|
---|
376 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
|
---|
377 | period_size, 0);
|
---|
378 | _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
|
---|
379 | period_bytes, 0);
|
---|
380 |
|
---|
381 | ret = _uniaud_pcm_set_hw_params(pcmread, ¶ms);
|
---|
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 | }
|
---|